diff options
351 files changed, 15431 insertions, 6374 deletions
diff --git a/Documentation/arm/mem_alignment b/Documentation/arm/mem_alignment index d145ccca169a..c7c7a114c78c 100644 --- a/Documentation/arm/mem_alignment +++ b/Documentation/arm/mem_alignment | |||
@@ -24,7 +24,7 @@ real bad - it changes the behaviour of all unaligned instructions in user | |||
24 | space, and might cause programs to fail unexpectedly. | 24 | space, and might cause programs to fail unexpectedly. |
25 | 25 | ||
26 | To change the alignment trap behavior, simply echo a number into | 26 | To change the alignment trap behavior, simply echo a number into |
27 | /proc/sys/debug/alignment. The number is made up from various bits: | 27 | /proc/cpu/alignment. The number is made up from various bits: |
28 | 28 | ||
29 | bit behavior when set | 29 | bit behavior when set |
30 | --- ----------------- | 30 | --- ----------------- |
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e0f346d201ed..c9115c1b672c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt | |||
@@ -220,14 +220,17 @@ and is between 256 and 4096 characters. It is defined in the file | |||
220 | Bits in debug_level correspond to a level in | 220 | Bits in debug_level correspond to a level in |
221 | ACPI_DEBUG_PRINT statements, e.g., | 221 | ACPI_DEBUG_PRINT statements, e.g., |
222 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, ... | 222 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, ... |
223 | See Documentation/acpi/debug.txt for more information | 223 | The debug_level mask defaults to "info". See |
224 | about debug layers and levels. | 224 | Documentation/acpi/debug.txt for more information about |
225 | debug layers and levels. | ||
225 | 226 | ||
227 | Enable processor driver info messages: | ||
228 | acpi.debug_layer=0x20000000 | ||
229 | Enable PCI/PCI interrupt routing info messages: | ||
230 | acpi.debug_layer=0x400000 | ||
226 | Enable AML "Debug" output, i.e., stores to the Debug | 231 | Enable AML "Debug" output, i.e., stores to the Debug |
227 | object while interpreting AML: | 232 | object while interpreting AML: |
228 | acpi.debug_layer=0xffffffff acpi.debug_level=0x2 | 233 | acpi.debug_layer=0xffffffff acpi.debug_level=0x2 |
229 | Enable PCI/PCI interrupt routing info messages: | ||
230 | acpi.debug_layer=0x400000 acpi.debug_level=0x4 | ||
231 | Enable all messages related to ACPI hardware: | 234 | Enable all messages related to ACPI hardware: |
232 | acpi.debug_layer=0x2 acpi.debug_level=0xffffffff | 235 | acpi.debug_layer=0x2 acpi.debug_level=0xffffffff |
233 | 236 | ||
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3cd2ad958176..394d7d378dc7 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -1063,6 +1063,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1063 | 1063 | ||
1064 | STAC9227/9228/9229/927x | 1064 | STAC9227/9228/9229/927x |
1065 | ref Reference board | 1065 | ref Reference board |
1066 | ref-no-jd Reference board without HP/Mic jack detection | ||
1066 | 3stack D965 3stack | 1067 | 3stack D965 3stack |
1067 | 5stack D965 5stack + SPDIF | 1068 | 5stack D965 5stack + SPDIF |
1068 | dell-3stack Dell Dimension E520 | 1069 | dell-3stack Dell Dimension E520 |
@@ -1076,6 +1077,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
1076 | 1077 | ||
1077 | STAC92HD73* | 1078 | STAC92HD73* |
1078 | ref Reference board | 1079 | ref Reference board |
1080 | no-jd BIOS setup but without jack-detection | ||
1079 | dell-m6-amic Dell desktops/laptops with analog mics | 1081 | dell-m6-amic Dell desktops/laptops with analog mics |
1080 | dell-m6-dmic Dell desktops/laptops with digital mics | 1082 | dell-m6-dmic Dell desktops/laptops with digital mics |
1081 | dell-m6 Dell desktops/laptops with both type of mics | 1083 | dell-m6 Dell desktops/laptops with both type of mics |
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt index f370e7db86af..bab7711ce963 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 | |||
9 | the following struct:- | 9 | the following struct:- |
10 | 10 | ||
11 | /* SoC machine */ | 11 | /* SoC machine */ |
12 | struct snd_soc_machine { | 12 | struct snd_soc_card { |
13 | char *name; | 13 | char *name; |
14 | 14 | ||
15 | int (*probe)(struct platform_device *pdev); | 15 | int (*probe)(struct platform_device *pdev); |
@@ -67,10 +67,10 @@ static struct snd_soc_dai_link corgi_dai = { | |||
67 | .ops = &corgi_ops, | 67 | .ops = &corgi_ops, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | struct snd_soc_machine then sets up the machine with it's DAIs. e.g. | 70 | struct snd_soc_card then sets up the machine with it's DAIs. e.g. |
71 | 71 | ||
72 | /* corgi audio machine driver */ | 72 | /* corgi audio machine driver */ |
73 | static struct snd_soc_machine snd_soc_machine_corgi = { | 73 | static struct snd_soc_card snd_soc_corgi = { |
74 | .name = "Corgi", | 74 | .name = "Corgi", |
75 | .dai_link = &corgi_dai, | 75 | .dai_link = &corgi_dai, |
76 | .num_links = 1, | 76 | .num_links = 1, |
@@ -90,7 +90,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = { | |||
90 | 90 | ||
91 | /* corgi audio subsystem */ | 91 | /* corgi audio subsystem */ |
92 | static struct snd_soc_device corgi_snd_devdata = { | 92 | static struct snd_soc_device corgi_snd_devdata = { |
93 | .machine = &snd_soc_machine_corgi, | 93 | .machine = &snd_soc_corgi, |
94 | .platform = &pxa2xx_soc_platform, | 94 | .platform = &pxa2xx_soc_platform, |
95 | .codec_dev = &soc_codec_dev_wm8731, | 95 | .codec_dev = &soc_codec_dev_wm8731, |
96 | .codec_data = &corgi_wm8731_setup, | 96 | .codec_data = &corgi_wm8731_setup, |
diff --git a/Documentation/usb/gadget_serial.txt b/Documentation/usb/gadget_serial.txt index 9b22bd14c348..eac7df94d8e3 100644 --- a/Documentation/usb/gadget_serial.txt +++ b/Documentation/usb/gadget_serial.txt | |||
@@ -114,11 +114,11 @@ modules. | |||
114 | Then you must load the gadget serial driver. To load it as an | 114 | Then you must load the gadget serial driver. To load it as an |
115 | ACM device (recommended for interoperability), do this: | 115 | ACM device (recommended for interoperability), do this: |
116 | 116 | ||
117 | modprobe g_serial use_acm=1 | 117 | modprobe g_serial |
118 | 118 | ||
119 | To load it as a vendor specific bulk in/out device, do this: | 119 | To load it as a vendor specific bulk in/out device, do this: |
120 | 120 | ||
121 | modprobe g_serial | 121 | modprobe g_serial use_acm=0 |
122 | 122 | ||
123 | This will also automatically load the underlying gadget peripheral | 123 | This will also automatically load the underlying gadget peripheral |
124 | controller driver. This must be done each time you reboot the gadget | 124 | controller driver. This must be done each time you reboot the gadget |
diff --git a/Documentation/usb/proc_usb_info.txt b/Documentation/usb/proc_usb_info.txt index 077e9032d0cd..fafcd4723260 100644 --- a/Documentation/usb/proc_usb_info.txt +++ b/Documentation/usb/proc_usb_info.txt | |||
@@ -49,8 +49,10 @@ it and 002/048 sometime later. | |||
49 | 49 | ||
50 | These files can be read as binary data. The binary data consists | 50 | These files can be read as binary data. The binary data consists |
51 | of first the device descriptor, then the descriptors for each | 51 | of first the device descriptor, then the descriptors for each |
52 | configuration of the device. That information is also shown in | 52 | configuration of the device. Multi-byte fields in the device and |
53 | text form by the /proc/bus/usb/devices file, described later. | 53 | configuration descriptors, but not other descriptors, are converted |
54 | to host endianness by the kernel. This information is also shown | ||
55 | in text form by the /proc/bus/usb/devices file, described later. | ||
54 | 56 | ||
55 | These files may also be used to write user-level drivers for the USB | 57 | These files may also be used to write user-level drivers for the USB |
56 | devices. You would open the /proc/bus/usb/BBB/DDD file read/write, | 58 | devices. You would open the /proc/bus/usb/BBB/DDD file read/write, |
diff --git a/Documentation/usb/usbmon.txt b/Documentation/usb/usbmon.txt index 2917ce4ffdc4..270481906dc8 100644 --- a/Documentation/usb/usbmon.txt +++ b/Documentation/usb/usbmon.txt | |||
@@ -34,11 +34,12 @@ if usbmon is built into the kernel. | |||
34 | Verify that bus sockets are present. | 34 | Verify that bus sockets are present. |
35 | 35 | ||
36 | # ls /sys/kernel/debug/usbmon | 36 | # ls /sys/kernel/debug/usbmon |
37 | 0s 0t 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u | 37 | 0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u |
38 | # | 38 | # |
39 | 39 | ||
40 | Now you can choose to either use the sockets numbered '0' (to capture packets on | 40 | Now you can choose to either use the socket '0u' (to capture packets on all |
41 | all buses), and skip to step #3, or find the bus used by your device with step #2. | 41 | buses), and skip to step #3, or find the bus used by your device with step #2. |
42 | This allows to filter away annoying devices that talk continuously. | ||
42 | 43 | ||
43 | 2. Find which bus connects to the desired device | 44 | 2. Find which bus connects to the desired device |
44 | 45 | ||
@@ -99,8 +100,9 @@ on the event type, but there is a set of words, common for all types. | |||
99 | 100 | ||
100 | Here is the list of words, from left to right: | 101 | Here is the list of words, from left to right: |
101 | 102 | ||
102 | - URB Tag. This is used to identify URBs is normally a kernel mode address | 103 | - URB Tag. This is used to identify URBs, and is normally an in-kernel address |
103 | of the URB structure in hexadecimal. | 104 | of the URB structure in hexadecimal, but can be a sequence number or any |
105 | other unique string, within reason. | ||
104 | 106 | ||
105 | - Timestamp in microseconds, a decimal number. The timestamp's resolution | 107 | - Timestamp in microseconds, a decimal number. The timestamp's resolution |
106 | depends on available clock, and so it can be much worse than a microsecond | 108 | depends on available clock, and so it can be much worse than a microsecond |
diff --git a/MAINTAINERS b/MAINTAINERS index 24741de12a39..701025701514 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1527,10 +1527,10 @@ W: http://ebtables.sourceforge.net/ | |||
1527 | S: Maintained | 1527 | S: Maintained |
1528 | 1528 | ||
1529 | ECRYPT FILE SYSTEM | 1529 | ECRYPT FILE SYSTEM |
1530 | P: Mike Halcrow, Phillip Hellewell | 1530 | P: Tyler Hicks, Dustin Kirkland |
1531 | M: mhalcrow@us.ibm.com, phillip@hellewell.homeip.net | 1531 | M: tyhicks@linux.vnet.ibm.com, kirkland@canonical.com |
1532 | L: ecryptfs-devel@lists.sourceforge.net | 1532 | L: ecryptfs-devel@lists.launchpad.net |
1533 | W: http://ecryptfs.sourceforge.net/ | 1533 | W: https://launchpad.net/ecryptfs |
1534 | S: Supported | 1534 | S: Supported |
1535 | 1535 | ||
1536 | EDAC-CORE | 1536 | EDAC-CORE |
@@ -2191,9 +2191,9 @@ S: Supported | |||
2191 | 2191 | ||
2192 | INOTIFY | 2192 | INOTIFY |
2193 | P: John McCutchan | 2193 | P: John McCutchan |
2194 | M: ttb@tentacle.dhs.org | 2194 | M: john@johnmccutchan.com |
2195 | P: Robert Love | 2195 | P: Robert Love |
2196 | M: rml@novell.com | 2196 | M: rlove@rlove.org |
2197 | L: linux-kernel@vger.kernel.org | 2197 | L: linux-kernel@vger.kernel.org |
2198 | S: Maintained | 2198 | S: Maintained |
2199 | 2199 | ||
@@ -3977,7 +3977,7 @@ M: tiwai@suse.de | |||
3977 | L: alsa-devel@alsa-project.org (subscribers-only) | 3977 | L: alsa-devel@alsa-project.org (subscribers-only) |
3978 | S: Maintained | 3978 | S: Maintained |
3979 | 3979 | ||
3980 | SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT | 3980 | SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC) |
3981 | P: Liam Girdwood | 3981 | P: Liam Girdwood |
3982 | M: lrg@slimlogic.co.uk | 3982 | M: lrg@slimlogic.co.uk |
3983 | P: Mark Brown | 3983 | P: Mark Brown |
@@ -4529,7 +4529,7 @@ S: Maintained | |||
4529 | USB VIDEO CLASS | 4529 | USB VIDEO CLASS |
4530 | P: Laurent Pinchart | 4530 | P: Laurent Pinchart |
4531 | M: laurent.pinchart@skynet.be | 4531 | M: laurent.pinchart@skynet.be |
4532 | L: linux-uvc-devel@lists.berlios.de | 4532 | L: linux-uvc-devel@lists.berlios.de (subscribers-only) |
4533 | L: video4linux-list@redhat.com | 4533 | L: video4linux-list@redhat.com |
4534 | W: http://linux-uvc.berlios.de | 4534 | W: http://linux-uvc.berlios.de |
4535 | S: Maintained | 4535 | S: Maintained |
@@ -1,7 +1,7 @@ | |||
1 | VERSION = 2 | 1 | VERSION = 2 |
2 | PATCHLEVEL = 6 | 2 | PATCHLEVEL = 6 |
3 | SUBLEVEL = 28 | 3 | SUBLEVEL = 28 |
4 | EXTRAVERSION = -rc8 | 4 | EXTRAVERSION = |
5 | NAME = Erotic Pickled Herring | 5 | NAME = Erotic Pickled Herring |
6 | 6 | ||
7 | # *DOCUMENTATION* | 7 | # *DOCUMENTATION* |
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c index 47ccec95f3e8..ef12794c3c68 100644 --- a/arch/arm/common/sa1111.c +++ b/arch/arm/common/sa1111.c | |||
@@ -630,7 +630,7 @@ __sa1111_probe(struct device *me, struct resource *mem, int irq) | |||
630 | return -ENOMEM; | 630 | return -ENOMEM; |
631 | 631 | ||
632 | sachip->clk = clk_get(me, "SA1111_CLK"); | 632 | sachip->clk = clk_get(me, "SA1111_CLK"); |
633 | if (!sachip->clk) { | 633 | if (IS_ERR(sachip->clk)) { |
634 | ret = PTR_ERR(sachip->clk); | 634 | ret = PTR_ERR(sachip->clk); |
635 | goto err_free; | 635 | goto err_free; |
636 | } | 636 | } |
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c index c74f766ffc12..23af3c972c9a 100644 --- a/arch/arm/kernel/armksyms.c +++ b/arch/arm/kernel/armksyms.c | |||
@@ -115,6 +115,8 @@ EXPORT_SYMBOL(__strnlen_user); | |||
115 | EXPORT_SYMBOL(__strncpy_from_user); | 115 | EXPORT_SYMBOL(__strncpy_from_user); |
116 | 116 | ||
117 | #ifdef CONFIG_MMU | 117 | #ifdef CONFIG_MMU |
118 | EXPORT_SYMBOL(copy_page); | ||
119 | |||
118 | EXPORT_SYMBOL(__copy_from_user); | 120 | EXPORT_SYMBOL(__copy_from_user); |
119 | EXPORT_SYMBOL(__copy_to_user); | 121 | EXPORT_SYMBOL(__copy_to_user); |
120 | EXPORT_SYMBOL(__clear_user); | 122 | EXPORT_SYMBOL(__clear_user); |
@@ -181,8 +183,6 @@ EXPORT_SYMBOL(_find_first_bit_be); | |||
181 | EXPORT_SYMBOL(_find_next_bit_be); | 183 | EXPORT_SYMBOL(_find_next_bit_be); |
182 | #endif | 184 | #endif |
183 | 185 | ||
184 | EXPORT_SYMBOL(copy_page); | ||
185 | |||
186 | #ifdef CONFIG_FUNCTION_TRACER | 186 | #ifdef CONFIG_FUNCTION_TRACER |
187 | EXPORT_SYMBOL(mcount); | 187 | EXPORT_SYMBOL(mcount); |
188 | #endif | 188 | #endif |
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c index 57e6874d0b80..79abc4ddc0cf 100644 --- a/arch/arm/kernel/traps.c +++ b/arch/arm/kernel/traps.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/personality.h> | 18 | #include <linux/personality.h> |
19 | #include <linux/kallsyms.h> | 19 | #include <linux/kallsyms.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/hardirq.h> | ||
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
22 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
23 | 24 | ||
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h new file mode 100644 index 000000000000..6c4b1f7de20a --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/palmasoc.h | |||
@@ -0,0 +1,13 @@ | |||
1 | #ifndef _INCLUDE_PALMASOC_H_ | ||
2 | #define _INCLUDE_PALMASOC_H_ | ||
3 | struct palm27x_asoc_info { | ||
4 | int jack_gpio; | ||
5 | }; | ||
6 | |||
7 | #ifdef CONFIG_SND_PXA2XX_SOC_PALM27X | ||
8 | void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data); | ||
9 | #else | ||
10 | static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {} | ||
11 | #endif | ||
12 | |||
13 | #endif | ||
diff --git a/arch/arm/mach-pxa/include/mach/reset.h b/arch/arm/mach-pxa/include/mach/reset.h index 7b8842cfa5fc..31e6a7b6ad80 100644 --- a/arch/arm/mach-pxa/include/mach/reset.h +++ b/arch/arm/mach-pxa/include/mach/reset.h | |||
@@ -12,9 +12,8 @@ extern void clear_reset_status(unsigned int mask); | |||
12 | 12 | ||
13 | /** | 13 | /** |
14 | * init_gpio_reset() - register GPIO as reset generator | 14 | * init_gpio_reset() - register GPIO as reset generator |
15 | * | 15 | * @gpio: gpio nr |
16 | * @gpio - gpio nr | 16 | * @output: set gpio as out/low instead of input during normal work |
17 | * @output - set gpio as out/low instead of input during normal work | ||
18 | */ | 17 | */ |
19 | extern int init_gpio_reset(int gpio, int output); | 18 | extern int init_gpio_reset(int gpio, int output); |
20 | 19 | ||
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index 2df8d9facf57..22c9530e91e2 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/signal.h> | 12 | #include <linux/signal.h> |
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/hardirq.h> | ||
14 | #include <linux/init.h> | 15 | #include <linux/init.h> |
15 | #include <linux/kprobes.h> | 16 | #include <linux/kprobes.h> |
16 | #include <linux/uaccess.h> | 17 | #include <linux/uaccess.h> |
diff --git a/arch/avr32/boards/favr-32/flash.c b/arch/avr32/boards/favr-32/flash.c index 5f139b7cb5f7..604bbd5e41d9 100644 --- a/arch/avr32/boards/favr-32/flash.c +++ b/arch/avr32/boards/favr-32/flash.c | |||
@@ -13,7 +13,7 @@ | |||
13 | #include <linux/mtd/partitions.h> | 13 | #include <linux/mtd/partitions.h> |
14 | #include <linux/mtd/physmap.h> | 14 | #include <linux/mtd/physmap.h> |
15 | 15 | ||
16 | #include <asm/arch/smc.h> | 16 | #include <mach/smc.h> |
17 | 17 | ||
18 | static struct smc_timing flash_timing __initdata = { | 18 | static struct smc_timing flash_timing __initdata = { |
19 | .ncs_read_setup = 0, | 19 | .ncs_read_setup = 0, |
diff --git a/arch/avr32/boards/favr-32/setup.c b/arch/avr32/boards/favr-32/setup.c index 7538f3d2b9e0..1ee4faf0742d 100644 --- a/arch/avr32/boards/favr-32/setup.c +++ b/arch/avr32/boards/favr-32/setup.c | |||
@@ -25,10 +25,10 @@ | |||
25 | 25 | ||
26 | #include <asm/setup.h> | 26 | #include <asm/setup.h> |
27 | 27 | ||
28 | #include <asm/arch/at32ap700x.h> | 28 | #include <mach/at32ap700x.h> |
29 | #include <asm/arch/init.h> | 29 | #include <mach/init.h> |
30 | #include <asm/arch/board.h> | 30 | #include <mach/board.h> |
31 | #include <asm/arch/portmux.h> | 31 | #include <mach/portmux.h> |
32 | 32 | ||
33 | /* Oscillator frequencies. These are board-specific */ | 33 | /* Oscillator frequencies. These are board-specific */ |
34 | unsigned long at32_board_osc_rates[3] = { | 34 | unsigned long at32_board_osc_rates[3] = { |
diff --git a/arch/avr32/boot/images/Makefile b/arch/avr32/boot/images/Makefile index 219720a47bf9..1848bf0d7f62 100644 --- a/arch/avr32/boot/images/Makefile +++ b/arch/avr32/boot/images/Makefile | |||
@@ -10,7 +10,7 @@ MKIMAGE := $(srctree)/scripts/mkuboot.sh | |||
10 | 10 | ||
11 | extra-y := vmlinux.bin vmlinux.gz | 11 | extra-y := vmlinux.bin vmlinux.gz |
12 | 12 | ||
13 | OBJCOPYFLAGS_vmlinux.bin := -O binary | 13 | OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note.gnu.build-id |
14 | $(obj)/vmlinux.bin: vmlinux FORCE | 14 | $(obj)/vmlinux.bin: vmlinux FORCE |
15 | $(call if_changed,objcopy) | 15 | $(call if_changed,objcopy) |
16 | 16 | ||
diff --git a/arch/avr32/configs/atstk1006_defconfig b/arch/avr32/configs/atstk1006_defconfig index 8b6e54c9946a..6c45a3b77aa3 100644 --- a/arch/avr32/configs/atstk1006_defconfig +++ b/arch/avr32/configs/atstk1006_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.27-rc1 | 3 | # Linux kernel version: 2.6.28-rc8 |
4 | # Tue Aug 5 15:40:26 2008 | 4 | # Thu Dec 18 11:22:23 2008 |
5 | # | 5 | # |
6 | CONFIG_AVR32=y | 6 | CONFIG_AVR32=y |
7 | CONFIG_GENERIC_GPIO=y | 7 | CONFIG_GENERIC_GPIO=y |
@@ -67,6 +67,7 @@ CONFIG_SIGNALFD=y | |||
67 | CONFIG_TIMERFD=y | 67 | CONFIG_TIMERFD=y |
68 | CONFIG_EVENTFD=y | 68 | CONFIG_EVENTFD=y |
69 | CONFIG_SHMEM=y | 69 | CONFIG_SHMEM=y |
70 | CONFIG_AIO=y | ||
70 | CONFIG_VM_EVENT_COUNTERS=y | 71 | CONFIG_VM_EVENT_COUNTERS=y |
71 | CONFIG_SLUB_DEBUG=y | 72 | CONFIG_SLUB_DEBUG=y |
72 | # CONFIG_SLAB is not set | 73 | # CONFIG_SLAB is not set |
@@ -77,15 +78,8 @@ CONFIG_PROFILING=y | |||
77 | CONFIG_OPROFILE=m | 78 | CONFIG_OPROFILE=m |
78 | CONFIG_HAVE_OPROFILE=y | 79 | CONFIG_HAVE_OPROFILE=y |
79 | CONFIG_KPROBES=y | 80 | CONFIG_KPROBES=y |
80 | # CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set | ||
81 | # CONFIG_HAVE_IOREMAP_PROT is not set | ||
82 | CONFIG_HAVE_KPROBES=y | 81 | CONFIG_HAVE_KPROBES=y |
83 | # CONFIG_HAVE_KRETPROBES is not set | ||
84 | # CONFIG_HAVE_ARCH_TRACEHOOK is not set | ||
85 | # CONFIG_HAVE_DMA_ATTRS is not set | ||
86 | # CONFIG_USE_GENERIC_SMP_HELPERS is not set | ||
87 | CONFIG_HAVE_CLK=y | 82 | CONFIG_HAVE_CLK=y |
88 | CONFIG_PROC_PAGE_MONITOR=y | ||
89 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | 83 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set |
90 | CONFIG_SLABINFO=y | 84 | CONFIG_SLABINFO=y |
91 | CONFIG_RT_MUTEXES=y | 85 | CONFIG_RT_MUTEXES=y |
@@ -118,6 +112,7 @@ CONFIG_DEFAULT_CFQ=y | |||
118 | # CONFIG_DEFAULT_NOOP is not set | 112 | # CONFIG_DEFAULT_NOOP is not set |
119 | CONFIG_DEFAULT_IOSCHED="cfq" | 113 | CONFIG_DEFAULT_IOSCHED="cfq" |
120 | CONFIG_CLASSIC_RCU=y | 114 | CONFIG_CLASSIC_RCU=y |
115 | CONFIG_FREEZER=y | ||
121 | 116 | ||
122 | # | 117 | # |
123 | # System Type and features | 118 | # System Type and features |
@@ -134,6 +129,8 @@ CONFIG_CPU_AT32AP700X=y | |||
134 | CONFIG_CPU_AT32AP7000=y | 129 | CONFIG_CPU_AT32AP7000=y |
135 | CONFIG_BOARD_ATSTK1000=y | 130 | CONFIG_BOARD_ATSTK1000=y |
136 | # CONFIG_BOARD_ATNGW100 is not set | 131 | # CONFIG_BOARD_ATNGW100 is not set |
132 | # CONFIG_BOARD_FAVR_32 is not set | ||
133 | # CONFIG_BOARD_MIMC200 is not set | ||
137 | # CONFIG_BOARD_ATSTK1002 is not set | 134 | # CONFIG_BOARD_ATSTK1002 is not set |
138 | # CONFIG_BOARD_ATSTK1003 is not set | 135 | # CONFIG_BOARD_ATSTK1003 is not set |
139 | # CONFIG_BOARD_ATSTK1004 is not set | 136 | # CONFIG_BOARD_ATSTK1004 is not set |
@@ -171,14 +168,14 @@ CONFIG_FLATMEM_MANUAL=y | |||
171 | # CONFIG_SPARSEMEM_MANUAL is not set | 168 | # CONFIG_SPARSEMEM_MANUAL is not set |
172 | CONFIG_FLATMEM=y | 169 | CONFIG_FLATMEM=y |
173 | CONFIG_FLAT_NODE_MEM_MAP=y | 170 | CONFIG_FLAT_NODE_MEM_MAP=y |
174 | # CONFIG_SPARSEMEM_STATIC is not set | ||
175 | # CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set | ||
176 | CONFIG_PAGEFLAGS_EXTENDED=y | 171 | CONFIG_PAGEFLAGS_EXTENDED=y |
177 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 172 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
178 | # CONFIG_RESOURCES_64BIT is not set | 173 | # CONFIG_RESOURCES_64BIT is not set |
174 | # CONFIG_PHYS_ADDR_T_64BIT is not set | ||
179 | CONFIG_ZONE_DMA_FLAG=0 | 175 | CONFIG_ZONE_DMA_FLAG=0 |
180 | CONFIG_NR_QUICK=2 | 176 | CONFIG_NR_QUICK=2 |
181 | CONFIG_VIRT_TO_BUS=y | 177 | CONFIG_VIRT_TO_BUS=y |
178 | CONFIG_UNEVICTABLE_LRU=y | ||
182 | # CONFIG_OWNERSHIP_TRACE is not set | 179 | # CONFIG_OWNERSHIP_TRACE is not set |
183 | CONFIG_NMI_DEBUGGING=y | 180 | CONFIG_NMI_DEBUGGING=y |
184 | # CONFIG_HZ_100 is not set | 181 | # CONFIG_HZ_100 is not set |
@@ -186,7 +183,7 @@ CONFIG_HZ_250=y | |||
186 | # CONFIG_HZ_300 is not set | 183 | # CONFIG_HZ_300 is not set |
187 | # CONFIG_HZ_1000 is not set | 184 | # CONFIG_HZ_1000 is not set |
188 | CONFIG_HZ=250 | 185 | CONFIG_HZ=250 |
189 | # CONFIG_SCHED_HRTICK is not set | 186 | CONFIG_SCHED_HRTICK=y |
190 | CONFIG_CMDLINE="" | 187 | CONFIG_CMDLINE="" |
191 | 188 | ||
192 | # | 189 | # |
@@ -228,6 +225,8 @@ CONFIG_CPU_FREQ_AT32AP=y | |||
228 | # Executable file formats | 225 | # Executable file formats |
229 | # | 226 | # |
230 | CONFIG_BINFMT_ELF=y | 227 | CONFIG_BINFMT_ELF=y |
228 | CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y | ||
229 | # CONFIG_HAVE_AOUT is not set | ||
231 | # CONFIG_BINFMT_MISC is not set | 230 | # CONFIG_BINFMT_MISC is not set |
232 | CONFIG_NET=y | 231 | CONFIG_NET=y |
233 | 232 | ||
@@ -299,6 +298,7 @@ CONFIG_IPV6_TUNNEL=m | |||
299 | # CONFIG_ATM is not set | 298 | # CONFIG_ATM is not set |
300 | CONFIG_STP=m | 299 | CONFIG_STP=m |
301 | CONFIG_BRIDGE=m | 300 | CONFIG_BRIDGE=m |
301 | # CONFIG_NET_DSA is not set | ||
302 | # CONFIG_VLAN_8021Q is not set | 302 | # CONFIG_VLAN_8021Q is not set |
303 | # CONFIG_DECNET is not set | 303 | # CONFIG_DECNET is not set |
304 | CONFIG_LLC=m | 304 | CONFIG_LLC=m |
@@ -321,14 +321,8 @@ CONFIG_LLC=m | |||
321 | # CONFIG_IRDA is not set | 321 | # CONFIG_IRDA is not set |
322 | # CONFIG_BT is not set | 322 | # CONFIG_BT is not set |
323 | # CONFIG_AF_RXRPC is not set | 323 | # CONFIG_AF_RXRPC is not set |
324 | 324 | # CONFIG_PHONET is not set | |
325 | # | 325 | # CONFIG_WIRELESS is not set |
326 | # Wireless | ||
327 | # | ||
328 | # CONFIG_CFG80211 is not set | ||
329 | # CONFIG_WIRELESS_EXT is not set | ||
330 | # CONFIG_MAC80211 is not set | ||
331 | # CONFIG_IEEE80211 is not set | ||
332 | # CONFIG_RFKILL is not set | 326 | # CONFIG_RFKILL is not set |
333 | # CONFIG_NET_9P is not set | 327 | # CONFIG_NET_9P is not set |
334 | 328 | ||
@@ -359,6 +353,7 @@ CONFIG_MTD_CMDLINE_PARTS=y | |||
359 | # User Modules And Translation Layers | 353 | # User Modules And Translation Layers |
360 | # | 354 | # |
361 | CONFIG_MTD_CHAR=y | 355 | CONFIG_MTD_CHAR=y |
356 | CONFIG_HAVE_MTD_OTP=y | ||
362 | CONFIG_MTD_BLKDEVS=y | 357 | CONFIG_MTD_BLKDEVS=y |
363 | CONFIG_MTD_BLOCK=y | 358 | CONFIG_MTD_BLOCK=y |
364 | # CONFIG_FTL is not set | 359 | # CONFIG_FTL is not set |
@@ -407,6 +402,8 @@ CONFIG_MTD_PHYSMAP_BANKWIDTH=2 | |||
407 | # Self-contained MTD device drivers | 402 | # Self-contained MTD device drivers |
408 | # | 403 | # |
409 | CONFIG_MTD_DATAFLASH=m | 404 | CONFIG_MTD_DATAFLASH=m |
405 | # CONFIG_MTD_DATAFLASH_WRITE_VERIFY is not set | ||
406 | CONFIG_MTD_DATAFLASH_OTP=y | ||
410 | CONFIG_MTD_M25P80=m | 407 | CONFIG_MTD_M25P80=m |
411 | CONFIG_M25PXX_USE_FAST_READ=y | 408 | CONFIG_M25PXX_USE_FAST_READ=y |
412 | # CONFIG_MTD_SLRAM is not set | 409 | # CONFIG_MTD_SLRAM is not set |
@@ -464,9 +461,10 @@ CONFIG_ATMEL_TCLIB=y | |||
464 | CONFIG_ATMEL_TCB_CLKSRC=y | 461 | CONFIG_ATMEL_TCB_CLKSRC=y |
465 | CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 | 462 | CONFIG_ATMEL_TCB_CLKSRC_BLOCK=0 |
466 | # CONFIG_EEPROM_93CX6 is not set | 463 | # CONFIG_EEPROM_93CX6 is not set |
464 | # CONFIG_ICS932S401 is not set | ||
467 | CONFIG_ATMEL_SSC=m | 465 | CONFIG_ATMEL_SSC=m |
468 | # CONFIG_ENCLOSURE_SERVICES is not set | 466 | # CONFIG_ENCLOSURE_SERVICES is not set |
469 | # CONFIG_HAVE_IDE is not set | 467 | # CONFIG_C2PORT is not set |
470 | 468 | ||
471 | # | 469 | # |
472 | # SCSI device support | 470 | # SCSI device support |
@@ -548,6 +546,9 @@ CONFIG_MACB=y | |||
548 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | 546 | # CONFIG_IBM_NEW_EMAC_RGMII is not set |
549 | # CONFIG_IBM_NEW_EMAC_TAH is not set | 547 | # CONFIG_IBM_NEW_EMAC_TAH is not set |
550 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | 548 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set |
549 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
550 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
551 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
551 | # CONFIG_B44 is not set | 552 | # CONFIG_B44 is not set |
552 | # CONFIG_NETDEV_1000 is not set | 553 | # CONFIG_NETDEV_1000 is not set |
553 | # CONFIG_NETDEV_10000 is not set | 554 | # CONFIG_NETDEV_10000 is not set |
@@ -653,6 +654,7 @@ CONFIG_UNIX98_PTYS=y | |||
653 | CONFIG_I2C=m | 654 | CONFIG_I2C=m |
654 | CONFIG_I2C_BOARDINFO=y | 655 | CONFIG_I2C_BOARDINFO=y |
655 | CONFIG_I2C_CHARDEV=m | 656 | CONFIG_I2C_CHARDEV=m |
657 | CONFIG_I2C_HELPER_AUTO=y | ||
656 | CONFIG_I2C_ALGOBIT=m | 658 | CONFIG_I2C_ALGOBIT=m |
657 | 659 | ||
658 | # | 660 | # |
@@ -717,6 +719,10 @@ CONFIG_GPIOLIB=y | |||
717 | CONFIG_GPIO_SYSFS=y | 719 | CONFIG_GPIO_SYSFS=y |
718 | 720 | ||
719 | # | 721 | # |
722 | # Memory mapped GPIO expanders: | ||
723 | # | ||
724 | |||
725 | # | ||
720 | # I2C GPIO expanders: | 726 | # I2C GPIO expanders: |
721 | # | 727 | # |
722 | # CONFIG_GPIO_MAX732X is not set | 728 | # CONFIG_GPIO_MAX732X is not set |
@@ -745,11 +751,11 @@ CONFIG_WATCHDOG=y | |||
745 | # | 751 | # |
746 | # CONFIG_SOFT_WATCHDOG is not set | 752 | # CONFIG_SOFT_WATCHDOG is not set |
747 | CONFIG_AT32AP700X_WDT=y | 753 | CONFIG_AT32AP700X_WDT=y |
754 | CONFIG_SSB_POSSIBLE=y | ||
748 | 755 | ||
749 | # | 756 | # |
750 | # Sonics Silicon Backplane | 757 | # Sonics Silicon Backplane |
751 | # | 758 | # |
752 | CONFIG_SSB_POSSIBLE=y | ||
753 | # CONFIG_SSB is not set | 759 | # CONFIG_SSB is not set |
754 | 760 | ||
755 | # | 761 | # |
@@ -758,6 +764,10 @@ CONFIG_SSB_POSSIBLE=y | |||
758 | # CONFIG_MFD_CORE is not set | 764 | # CONFIG_MFD_CORE is not set |
759 | # CONFIG_MFD_SM501 is not set | 765 | # CONFIG_MFD_SM501 is not set |
760 | # CONFIG_HTC_PASIC3 is not set | 766 | # CONFIG_HTC_PASIC3 is not set |
767 | # CONFIG_MFD_TMIO is not set | ||
768 | # CONFIG_MFD_WM8400 is not set | ||
769 | # CONFIG_MFD_WM8350_I2C is not set | ||
770 | # CONFIG_REGULATOR is not set | ||
761 | 771 | ||
762 | # | 772 | # |
763 | # Multimedia devices | 773 | # Multimedia devices |
@@ -783,6 +793,7 @@ CONFIG_SSB_POSSIBLE=y | |||
783 | CONFIG_FB=y | 793 | CONFIG_FB=y |
784 | # CONFIG_FIRMWARE_EDID is not set | 794 | # CONFIG_FIRMWARE_EDID is not set |
785 | # CONFIG_FB_DDC is not set | 795 | # CONFIG_FB_DDC is not set |
796 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
786 | CONFIG_FB_CFB_FILLRECT=y | 797 | CONFIG_FB_CFB_FILLRECT=y |
787 | CONFIG_FB_CFB_COPYAREA=y | 798 | CONFIG_FB_CFB_COPYAREA=y |
788 | CONFIG_FB_CFB_IMAGEBLIT=y | 799 | CONFIG_FB_CFB_IMAGEBLIT=y |
@@ -804,10 +815,13 @@ CONFIG_FB_CFB_IMAGEBLIT=y | |||
804 | # CONFIG_FB_S1D13XXX is not set | 815 | # CONFIG_FB_S1D13XXX is not set |
805 | CONFIG_FB_ATMEL=y | 816 | CONFIG_FB_ATMEL=y |
806 | # CONFIG_FB_VIRTUAL is not set | 817 | # CONFIG_FB_VIRTUAL is not set |
818 | # CONFIG_FB_METRONOME is not set | ||
819 | # CONFIG_FB_MB862XX is not set | ||
807 | CONFIG_BACKLIGHT_LCD_SUPPORT=y | 820 | CONFIG_BACKLIGHT_LCD_SUPPORT=y |
808 | CONFIG_LCD_CLASS_DEVICE=y | 821 | CONFIG_LCD_CLASS_DEVICE=y |
809 | CONFIG_LCD_LTV350QV=y | 822 | CONFIG_LCD_LTV350QV=y |
810 | # CONFIG_LCD_ILI9320 is not set | 823 | # CONFIG_LCD_ILI9320 is not set |
824 | # CONFIG_LCD_TDO24M is not set | ||
811 | # CONFIG_LCD_VGG2432A4 is not set | 825 | # CONFIG_LCD_VGG2432A4 is not set |
812 | # CONFIG_LCD_PLATFORM is not set | 826 | # CONFIG_LCD_PLATFORM is not set |
813 | # CONFIG_BACKLIGHT_CLASS_DEVICE is not set | 827 | # CONFIG_BACKLIGHT_CLASS_DEVICE is not set |
@@ -818,6 +832,7 @@ CONFIG_LCD_LTV350QV=y | |||
818 | # CONFIG_DISPLAY_SUPPORT is not set | 832 | # CONFIG_DISPLAY_SUPPORT is not set |
819 | # CONFIG_LOGO is not set | 833 | # CONFIG_LOGO is not set |
820 | CONFIG_SOUND=m | 834 | CONFIG_SOUND=m |
835 | CONFIG_SOUND_OSS_CORE=y | ||
821 | CONFIG_SND=m | 836 | CONFIG_SND=m |
822 | CONFIG_SND_TIMER=m | 837 | CONFIG_SND_TIMER=m |
823 | CONFIG_SND_PCM=m | 838 | CONFIG_SND_PCM=m |
@@ -848,28 +863,32 @@ CONFIG_USB_SUPPORT=y | |||
848 | # CONFIG_USB_ARCH_HAS_EHCI is not set | 863 | # CONFIG_USB_ARCH_HAS_EHCI is not set |
849 | # CONFIG_USB_OTG_WHITELIST is not set | 864 | # CONFIG_USB_OTG_WHITELIST is not set |
850 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set | 865 | # CONFIG_USB_OTG_BLACKLIST_HUB is not set |
866 | # CONFIG_USB_MUSB_HDRC is not set | ||
867 | # CONFIG_USB_GADGET_MUSB_HDRC is not set | ||
851 | 868 | ||
852 | # | 869 | # |
853 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | 870 | # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed; |
854 | # | 871 | # |
855 | CONFIG_USB_GADGET=y | 872 | CONFIG_USB_GADGET=y |
856 | # CONFIG_USB_GADGET_DEBUG is not set | 873 | # CONFIG_USB_GADGET_DEBUG is not set |
857 | # CONFIG_USB_GADGET_DEBUG_FILES is not set | 874 | # CONFIG_USB_GADGET_DEBUG_FILES is not set |
858 | # CONFIG_USB_GADGET_DEBUG_FS is not set | 875 | # CONFIG_USB_GADGET_DEBUG_FS is not set |
876 | CONFIG_USB_GADGET_VBUS_DRAW=2 | ||
859 | CONFIG_USB_GADGET_SELECTED=y | 877 | CONFIG_USB_GADGET_SELECTED=y |
860 | # CONFIG_USB_GADGET_AMD5536UDC is not set | 878 | # CONFIG_USB_GADGET_AT91 is not set |
861 | CONFIG_USB_GADGET_ATMEL_USBA=y | 879 | CONFIG_USB_GADGET_ATMEL_USBA=y |
862 | CONFIG_USB_ATMEL_USBA=y | 880 | CONFIG_USB_ATMEL_USBA=y |
863 | # CONFIG_USB_GADGET_FSL_USB2 is not set | 881 | # CONFIG_USB_GADGET_FSL_USB2 is not set |
864 | # CONFIG_USB_GADGET_NET2280 is not set | ||
865 | # CONFIG_USB_GADGET_PXA25X is not set | ||
866 | # CONFIG_USB_GADGET_M66592 is not set | ||
867 | # CONFIG_USB_GADGET_PXA27X is not set | ||
868 | # CONFIG_USB_GADGET_GOKU is not set | ||
869 | # CONFIG_USB_GADGET_LH7A40X is not set | 882 | # CONFIG_USB_GADGET_LH7A40X is not set |
870 | # CONFIG_USB_GADGET_OMAP is not set | 883 | # CONFIG_USB_GADGET_OMAP is not set |
884 | # CONFIG_USB_GADGET_PXA25X is not set | ||
885 | # CONFIG_USB_GADGET_PXA27X is not set | ||
871 | # CONFIG_USB_GADGET_S3C2410 is not set | 886 | # CONFIG_USB_GADGET_S3C2410 is not set |
872 | # CONFIG_USB_GADGET_AT91 is not set | 887 | # CONFIG_USB_GADGET_M66592 is not set |
888 | # CONFIG_USB_GADGET_AMD5536UDC is not set | ||
889 | # CONFIG_USB_GADGET_FSL_QE is not set | ||
890 | # CONFIG_USB_GADGET_NET2280 is not set | ||
891 | # CONFIG_USB_GADGET_GOKU is not set | ||
873 | # CONFIG_USB_GADGET_DUMMY_HCD is not set | 892 | # CONFIG_USB_GADGET_DUMMY_HCD is not set |
874 | CONFIG_USB_GADGET_DUALSPEED=y | 893 | CONFIG_USB_GADGET_DUALSPEED=y |
875 | CONFIG_USB_ZERO=m | 894 | CONFIG_USB_ZERO=m |
@@ -887,7 +906,7 @@ CONFIG_MMC=y | |||
887 | # CONFIG_MMC_UNSAFE_RESUME is not set | 906 | # CONFIG_MMC_UNSAFE_RESUME is not set |
888 | 907 | ||
889 | # | 908 | # |
890 | # MMC/SD Card Drivers | 909 | # MMC/SD/SDIO Card Drivers |
891 | # | 910 | # |
892 | CONFIG_MMC_BLOCK=y | 911 | CONFIG_MMC_BLOCK=y |
893 | CONFIG_MMC_BLOCK_BOUNCE=y | 912 | CONFIG_MMC_BLOCK_BOUNCE=y |
@@ -895,10 +914,11 @@ CONFIG_MMC_BLOCK_BOUNCE=y | |||
895 | # CONFIG_MMC_TEST is not set | 914 | # CONFIG_MMC_TEST is not set |
896 | 915 | ||
897 | # | 916 | # |
898 | # MMC/SD Host Controller Drivers | 917 | # MMC/SD/SDIO Host Controller Drivers |
899 | # | 918 | # |
900 | # CONFIG_MMC_SDHCI is not set | 919 | # CONFIG_MMC_SDHCI is not set |
901 | CONFIG_MMC_ATMELMCI=y | 920 | CONFIG_MMC_ATMELMCI=y |
921 | # CONFIG_MMC_ATMELMCI_DMA is not set | ||
902 | CONFIG_MMC_SPI=m | 922 | CONFIG_MMC_SPI=m |
903 | # CONFIG_MEMSTICK is not set | 923 | # CONFIG_MEMSTICK is not set |
904 | CONFIG_NEW_LEDS=y | 924 | CONFIG_NEW_LEDS=y |
@@ -918,6 +938,7 @@ CONFIG_LEDS_GPIO=m | |||
918 | CONFIG_LEDS_TRIGGERS=y | 938 | CONFIG_LEDS_TRIGGERS=y |
919 | CONFIG_LEDS_TRIGGER_TIMER=m | 939 | CONFIG_LEDS_TRIGGER_TIMER=m |
920 | CONFIG_LEDS_TRIGGER_HEARTBEAT=m | 940 | CONFIG_LEDS_TRIGGER_HEARTBEAT=m |
941 | # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set | ||
921 | CONFIG_LEDS_TRIGGER_DEFAULT_ON=m | 942 | CONFIG_LEDS_TRIGGER_DEFAULT_ON=m |
922 | # CONFIG_ACCESSIBILITY is not set | 943 | # CONFIG_ACCESSIBILITY is not set |
923 | CONFIG_RTC_LIB=y | 944 | CONFIG_RTC_LIB=y |
@@ -950,25 +971,31 @@ CONFIG_RTC_INTF_DEV=y | |||
950 | # CONFIG_RTC_DRV_M41T80 is not set | 971 | # CONFIG_RTC_DRV_M41T80 is not set |
951 | # CONFIG_RTC_DRV_S35390A is not set | 972 | # CONFIG_RTC_DRV_S35390A is not set |
952 | # CONFIG_RTC_DRV_FM3130 is not set | 973 | # CONFIG_RTC_DRV_FM3130 is not set |
974 | # CONFIG_RTC_DRV_RX8581 is not set | ||
953 | 975 | ||
954 | # | 976 | # |
955 | # SPI RTC drivers | 977 | # SPI RTC drivers |
956 | # | 978 | # |
957 | # CONFIG_RTC_DRV_M41T94 is not set | 979 | # CONFIG_RTC_DRV_M41T94 is not set |
958 | # CONFIG_RTC_DRV_DS1305 is not set | 980 | # CONFIG_RTC_DRV_DS1305 is not set |
981 | # CONFIG_RTC_DRV_DS1390 is not set | ||
959 | # CONFIG_RTC_DRV_MAX6902 is not set | 982 | # CONFIG_RTC_DRV_MAX6902 is not set |
960 | # CONFIG_RTC_DRV_R9701 is not set | 983 | # CONFIG_RTC_DRV_R9701 is not set |
961 | # CONFIG_RTC_DRV_RS5C348 is not set | 984 | # CONFIG_RTC_DRV_RS5C348 is not set |
985 | # CONFIG_RTC_DRV_DS3234 is not set | ||
962 | 986 | ||
963 | # | 987 | # |
964 | # Platform RTC drivers | 988 | # Platform RTC drivers |
965 | # | 989 | # |
990 | # CONFIG_RTC_DRV_DS1286 is not set | ||
966 | # CONFIG_RTC_DRV_DS1511 is not set | 991 | # CONFIG_RTC_DRV_DS1511 is not set |
967 | # CONFIG_RTC_DRV_DS1553 is not set | 992 | # CONFIG_RTC_DRV_DS1553 is not set |
968 | # CONFIG_RTC_DRV_DS1742 is not set | 993 | # CONFIG_RTC_DRV_DS1742 is not set |
969 | # CONFIG_RTC_DRV_STK17TA8 is not set | 994 | # CONFIG_RTC_DRV_STK17TA8 is not set |
970 | # CONFIG_RTC_DRV_M48T86 is not set | 995 | # CONFIG_RTC_DRV_M48T86 is not set |
996 | # CONFIG_RTC_DRV_M48T35 is not set | ||
971 | # CONFIG_RTC_DRV_M48T59 is not set | 997 | # CONFIG_RTC_DRV_M48T59 is not set |
998 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
972 | # CONFIG_RTC_DRV_V3020 is not set | 999 | # CONFIG_RTC_DRV_V3020 is not set |
973 | 1000 | ||
974 | # | 1001 | # |
@@ -989,6 +1016,8 @@ CONFIG_DMA_ENGINE=y | |||
989 | # CONFIG_NET_DMA is not set | 1016 | # CONFIG_NET_DMA is not set |
990 | CONFIG_DMATEST=m | 1017 | CONFIG_DMATEST=m |
991 | # CONFIG_UIO is not set | 1018 | # CONFIG_UIO is not set |
1019 | # CONFIG_STAGING is not set | ||
1020 | CONFIG_STAGING_EXCLUDE_BUILD=y | ||
992 | 1021 | ||
993 | # | 1022 | # |
994 | # File systems | 1023 | # File systems |
@@ -998,12 +1027,17 @@ CONFIG_EXT2_FS=m | |||
998 | # CONFIG_EXT2_FS_XIP is not set | 1027 | # CONFIG_EXT2_FS_XIP is not set |
999 | CONFIG_EXT3_FS=m | 1028 | CONFIG_EXT3_FS=m |
1000 | # CONFIG_EXT3_FS_XATTR is not set | 1029 | # CONFIG_EXT3_FS_XATTR is not set |
1001 | # CONFIG_EXT4DEV_FS is not set | 1030 | CONFIG_EXT4_FS=m |
1031 | CONFIG_EXT4DEV_COMPAT=y | ||
1032 | # CONFIG_EXT4_FS_XATTR is not set | ||
1002 | CONFIG_JBD=m | 1033 | CONFIG_JBD=m |
1003 | # CONFIG_JBD_DEBUG is not set | 1034 | # CONFIG_JBD_DEBUG is not set |
1035 | CONFIG_JBD2=m | ||
1036 | # CONFIG_JBD2_DEBUG is not set | ||
1004 | # CONFIG_REISERFS_FS is not set | 1037 | # CONFIG_REISERFS_FS is not set |
1005 | # CONFIG_JFS_FS is not set | 1038 | # CONFIG_JFS_FS is not set |
1006 | # CONFIG_FS_POSIX_ACL is not set | 1039 | # CONFIG_FS_POSIX_ACL is not set |
1040 | CONFIG_FILE_LOCKING=y | ||
1007 | # CONFIG_XFS_FS is not set | 1041 | # CONFIG_XFS_FS is not set |
1008 | # CONFIG_OCFS2_FS is not set | 1042 | # CONFIG_OCFS2_FS is not set |
1009 | # CONFIG_DNOTIFY is not set | 1043 | # CONFIG_DNOTIFY is not set |
@@ -1036,6 +1070,7 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | |||
1036 | CONFIG_PROC_FS=y | 1070 | CONFIG_PROC_FS=y |
1037 | CONFIG_PROC_KCORE=y | 1071 | CONFIG_PROC_KCORE=y |
1038 | CONFIG_PROC_SYSCTL=y | 1072 | CONFIG_PROC_SYSCTL=y |
1073 | CONFIG_PROC_PAGE_MONITOR=y | ||
1039 | CONFIG_SYSFS=y | 1074 | CONFIG_SYSFS=y |
1040 | CONFIG_TMPFS=y | 1075 | CONFIG_TMPFS=y |
1041 | # CONFIG_TMPFS_POSIX_ACL is not set | 1076 | # CONFIG_TMPFS_POSIX_ACL is not set |
@@ -1054,7 +1089,8 @@ CONFIG_TMPFS=y | |||
1054 | # CONFIG_EFS_FS is not set | 1089 | # CONFIG_EFS_FS is not set |
1055 | CONFIG_JFFS2_FS=y | 1090 | CONFIG_JFFS2_FS=y |
1056 | CONFIG_JFFS2_FS_DEBUG=0 | 1091 | CONFIG_JFFS2_FS_DEBUG=0 |
1057 | # CONFIG_JFFS2_FS_WRITEBUFFER is not set | 1092 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
1093 | # CONFIG_JFFS2_FS_WBUF_VERIFY is not set | ||
1058 | # CONFIG_JFFS2_SUMMARY is not set | 1094 | # CONFIG_JFFS2_SUMMARY is not set |
1059 | # CONFIG_JFFS2_FS_XATTR is not set | 1095 | # CONFIG_JFFS2_FS_XATTR is not set |
1060 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 1096 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
@@ -1088,6 +1124,7 @@ CONFIG_LOCKD=y | |||
1088 | CONFIG_LOCKD_V4=y | 1124 | CONFIG_LOCKD_V4=y |
1089 | CONFIG_NFS_COMMON=y | 1125 | CONFIG_NFS_COMMON=y |
1090 | CONFIG_SUNRPC=y | 1126 | CONFIG_SUNRPC=y |
1127 | # CONFIG_SUNRPC_REGISTER_V4 is not set | ||
1091 | # CONFIG_RPCSEC_GSS_KRB5 is not set | 1128 | # CONFIG_RPCSEC_GSS_KRB5 is not set |
1092 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | 1129 | # CONFIG_RPCSEC_GSS_SPKM3 is not set |
1093 | # CONFIG_SMB_FS is not set | 1130 | # CONFIG_SMB_FS is not set |
@@ -1185,10 +1222,21 @@ CONFIG_DEBUG_BUGVERBOSE=y | |||
1185 | CONFIG_FRAME_POINTER=y | 1222 | CONFIG_FRAME_POINTER=y |
1186 | # CONFIG_BOOT_PRINTK_DELAY is not set | 1223 | # CONFIG_BOOT_PRINTK_DELAY is not set |
1187 | # CONFIG_RCU_TORTURE_TEST is not set | 1224 | # CONFIG_RCU_TORTURE_TEST is not set |
1225 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
1188 | # CONFIG_KPROBES_SANITY_TEST is not set | 1226 | # CONFIG_KPROBES_SANITY_TEST is not set |
1189 | # CONFIG_BACKTRACE_SELF_TEST is not set | 1227 | # CONFIG_BACKTRACE_SELF_TEST is not set |
1228 | # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set | ||
1190 | # CONFIG_LKDTM is not set | 1229 | # CONFIG_LKDTM is not set |
1191 | # CONFIG_FAULT_INJECTION is not set | 1230 | # CONFIG_FAULT_INJECTION is not set |
1231 | |||
1232 | # | ||
1233 | # Tracers | ||
1234 | # | ||
1235 | # CONFIG_IRQSOFF_TRACER is not set | ||
1236 | # CONFIG_SCHED_TRACER is not set | ||
1237 | # CONFIG_CONTEXT_SWITCH_TRACER is not set | ||
1238 | # CONFIG_BOOT_TRACER is not set | ||
1239 | # CONFIG_DYNAMIC_PRINTK_DEBUG is not set | ||
1192 | # CONFIG_SAMPLES is not set | 1240 | # CONFIG_SAMPLES is not set |
1193 | 1241 | ||
1194 | # | 1242 | # |
@@ -1196,17 +1244,26 @@ CONFIG_FRAME_POINTER=y | |||
1196 | # | 1244 | # |
1197 | # CONFIG_KEYS is not set | 1245 | # CONFIG_KEYS is not set |
1198 | # CONFIG_SECURITY is not set | 1246 | # CONFIG_SECURITY is not set |
1247 | # CONFIG_SECURITYFS is not set | ||
1199 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | 1248 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set |
1200 | CONFIG_CRYPTO=y | 1249 | CONFIG_CRYPTO=y |
1201 | 1250 | ||
1202 | # | 1251 | # |
1203 | # Crypto core or helper | 1252 | # Crypto core or helper |
1204 | # | 1253 | # |
1254 | CONFIG_CRYPTO_FIPS=y | ||
1205 | CONFIG_CRYPTO_ALGAPI=y | 1255 | CONFIG_CRYPTO_ALGAPI=y |
1256 | CONFIG_CRYPTO_ALGAPI2=y | ||
1206 | CONFIG_CRYPTO_AEAD=m | 1257 | CONFIG_CRYPTO_AEAD=m |
1258 | CONFIG_CRYPTO_AEAD2=y | ||
1207 | CONFIG_CRYPTO_BLKCIPHER=m | 1259 | CONFIG_CRYPTO_BLKCIPHER=m |
1260 | CONFIG_CRYPTO_BLKCIPHER2=y | ||
1208 | CONFIG_CRYPTO_HASH=m | 1261 | CONFIG_CRYPTO_HASH=m |
1262 | CONFIG_CRYPTO_HASH2=y | ||
1263 | CONFIG_CRYPTO_RNG=m | ||
1264 | CONFIG_CRYPTO_RNG2=y | ||
1209 | CONFIG_CRYPTO_MANAGER=m | 1265 | CONFIG_CRYPTO_MANAGER=m |
1266 | CONFIG_CRYPTO_MANAGER2=y | ||
1210 | # CONFIG_CRYPTO_GF128MUL is not set | 1267 | # CONFIG_CRYPTO_GF128MUL is not set |
1211 | # CONFIG_CRYPTO_NULL is not set | 1268 | # CONFIG_CRYPTO_NULL is not set |
1212 | # CONFIG_CRYPTO_CRYPTD is not set | 1269 | # CONFIG_CRYPTO_CRYPTD is not set |
@@ -1257,7 +1314,7 @@ CONFIG_CRYPTO_SHA1=m | |||
1257 | # | 1314 | # |
1258 | # Ciphers | 1315 | # Ciphers |
1259 | # | 1316 | # |
1260 | # CONFIG_CRYPTO_AES is not set | 1317 | CONFIG_CRYPTO_AES=m |
1261 | # CONFIG_CRYPTO_ANUBIS is not set | 1318 | # CONFIG_CRYPTO_ANUBIS is not set |
1262 | # CONFIG_CRYPTO_ARC4 is not set | 1319 | # CONFIG_CRYPTO_ARC4 is not set |
1263 | # CONFIG_CRYPTO_BLOWFISH is not set | 1320 | # CONFIG_CRYPTO_BLOWFISH is not set |
@@ -1278,14 +1335,17 @@ CONFIG_CRYPTO_DES=m | |||
1278 | # | 1335 | # |
1279 | CONFIG_CRYPTO_DEFLATE=y | 1336 | CONFIG_CRYPTO_DEFLATE=y |
1280 | CONFIG_CRYPTO_LZO=y | 1337 | CONFIG_CRYPTO_LZO=y |
1338 | |||
1339 | # | ||
1340 | # Random Number Generation | ||
1341 | # | ||
1342 | CONFIG_CRYPTO_ANSI_CPRNG=m | ||
1281 | # CONFIG_CRYPTO_HW is not set | 1343 | # CONFIG_CRYPTO_HW is not set |
1282 | 1344 | ||
1283 | # | 1345 | # |
1284 | # Library routines | 1346 | # Library routines |
1285 | # | 1347 | # |
1286 | CONFIG_BITREVERSE=y | 1348 | CONFIG_BITREVERSE=y |
1287 | # CONFIG_GENERIC_FIND_FIRST_BIT is not set | ||
1288 | # CONFIG_GENERIC_FIND_NEXT_BIT is not set | ||
1289 | CONFIG_CRC_CCITT=m | 1349 | CONFIG_CRC_CCITT=m |
1290 | CONFIG_CRC16=y | 1350 | CONFIG_CRC16=y |
1291 | CONFIG_CRC_T10DIF=m | 1351 | CONFIG_CRC_T10DIF=m |
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 0c6e02f80a31..066252eebf61 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -967,28 +967,28 @@ static inline void configure_usart0_pins(void) | |||
967 | { | 967 | { |
968 | u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ | 968 | u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ |
969 | 969 | ||
970 | select_peripheral(PIOA, pin_mask, PERIPH_B, 0); | 970 | select_peripheral(PIOA, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); |
971 | } | 971 | } |
972 | 972 | ||
973 | static inline void configure_usart1_pins(void) | 973 | static inline void configure_usart1_pins(void) |
974 | { | 974 | { |
975 | u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ | 975 | u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ |
976 | 976 | ||
977 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); | 977 | select_peripheral(PIOA, pin_mask, PERIPH_A, AT32_GPIOF_PULLUP); |
978 | } | 978 | } |
979 | 979 | ||
980 | static inline void configure_usart2_pins(void) | 980 | static inline void configure_usart2_pins(void) |
981 | { | 981 | { |
982 | u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ | 982 | u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ |
983 | 983 | ||
984 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); | 984 | select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); |
985 | } | 985 | } |
986 | 986 | ||
987 | static inline void configure_usart3_pins(void) | 987 | static inline void configure_usart3_pins(void) |
988 | { | 988 | { |
989 | u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ | 989 | u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ |
990 | 990 | ||
991 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); | 991 | select_peripheral(PIOB, pin_mask, PERIPH_B, AT32_GPIOF_PULLUP); |
992 | } | 992 | } |
993 | 993 | ||
994 | static struct platform_device *__initdata at32_usarts[4]; | 994 | static struct platform_device *__initdata at32_usarts[4]; |
diff --git a/arch/ia64/hp/sim/Kconfig b/arch/ia64/hp/sim/Kconfig index f92306bbedb8..8d513a8c5266 100644 --- a/arch/ia64/hp/sim/Kconfig +++ b/arch/ia64/hp/sim/Kconfig | |||
@@ -4,6 +4,7 @@ menu "HP Simulator drivers" | |||
4 | 4 | ||
5 | config HP_SIMETH | 5 | config HP_SIMETH |
6 | bool "Simulated Ethernet " | 6 | bool "Simulated Ethernet " |
7 | depends on NET | ||
7 | 8 | ||
8 | config HP_SIMSERIAL | 9 | config HP_SIMSERIAL |
9 | bool "Simulated serial driver support" | 10 | bool "Simulated serial driver support" |
diff --git a/arch/mips/Kconfig.debug b/arch/mips/Kconfig.debug index 765c8e287d2b..364ca8938807 100644 --- a/arch/mips/Kconfig.debug +++ b/arch/mips/Kconfig.debug | |||
@@ -48,7 +48,7 @@ config RUNTIME_DEBUG | |||
48 | help | 48 | help |
49 | If you say Y here, some debugging macros will do run-time checking. | 49 | If you say Y here, some debugging macros will do run-time checking. |
50 | If you say N here, those macros will mostly turn to no-ops. See | 50 | If you say N here, those macros will mostly turn to no-ops. See |
51 | include/asm-mips/debug.h for debuging macros. | 51 | arch/mips/include/asm/debug.h for debugging macros. |
52 | If unsure, say N. | 52 | If unsure, say N. |
53 | 53 | ||
54 | endmenu | 54 | endmenu |
diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index fe4699df9626..de4c7a0a96dd 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig | |||
@@ -1,71 +1,71 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.20 | 3 | # Linux kernel version: 2.6.28-rc7 |
4 | # Tue Feb 20 21:47:33 2007 | 4 | # Wed Dec 10 14:39:08 2008 |
5 | # | 5 | # |
6 | CONFIG_MIPS=y | 6 | CONFIG_MIPS=y |
7 | 7 | ||
8 | # | 8 | # |
9 | # Machine selection | 9 | # Machine selection |
10 | # | 10 | # |
11 | CONFIG_ZONE_DMA=y | 11 | # CONFIG_MACH_ALCHEMY is not set |
12 | # CONFIG_MIPS_MTX1 is not set | ||
13 | # CONFIG_MIPS_BOSPORUS is not set | ||
14 | # CONFIG_MIPS_PB1000 is not set | ||
15 | # CONFIG_MIPS_PB1100 is not set | ||
16 | # CONFIG_MIPS_PB1500 is not set | ||
17 | # CONFIG_MIPS_PB1550 is not set | ||
18 | # CONFIG_MIPS_PB1200 is not set | ||
19 | # CONFIG_MIPS_DB1000 is not set | ||
20 | # CONFIG_MIPS_DB1100 is not set | ||
21 | # CONFIG_MIPS_DB1500 is not set | ||
22 | # CONFIG_MIPS_DB1550 is not set | ||
23 | # CONFIG_MIPS_DB1200 is not set | ||
24 | # CONFIG_MIPS_MIRAGE is not set | ||
25 | # CONFIG_BASLER_EXCITE is not set | 12 | # CONFIG_BASLER_EXCITE is not set |
13 | # CONFIG_BCM47XX is not set | ||
26 | # CONFIG_MIPS_COBALT is not set | 14 | # CONFIG_MIPS_COBALT is not set |
27 | # CONFIG_MACH_DECSTATION is not set | 15 | # CONFIG_MACH_DECSTATION is not set |
28 | # CONFIG_MACH_JAZZ is not set | 16 | # CONFIG_MACH_JAZZ is not set |
17 | # CONFIG_LASAT is not set | ||
18 | # CONFIG_LEMOTE_FULONG is not set | ||
29 | # CONFIG_MIPS_MALTA is not set | 19 | # CONFIG_MIPS_MALTA is not set |
30 | # CONFIG_WR_PPMC is not set | ||
31 | # CONFIG_MIPS_SIM is not set | 20 | # CONFIG_MIPS_SIM is not set |
32 | # CONFIG_MOMENCO_JAGUAR_ATX is not set | 21 | # CONFIG_MACH_EMMA is not set |
33 | # CONFIG_MIPS_XXS1500 is not set | 22 | # CONFIG_MACH_VR41XX is not set |
23 | # CONFIG_NXP_STB220 is not set | ||
24 | # CONFIG_NXP_STB225 is not set | ||
34 | # CONFIG_PNX8550_JBS is not set | 25 | # CONFIG_PNX8550_JBS is not set |
35 | # CONFIG_PNX8550_STB810 is not set | 26 | # CONFIG_PNX8550_STB810 is not set |
36 | # CONFIG_MACH_VR41XX is not set | 27 | # CONFIG_PMC_MSP is not set |
37 | # CONFIG_PMC_YOSEMITE is not set | 28 | # CONFIG_PMC_YOSEMITE is not set |
38 | # CONFIG_MARKEINS is not set | ||
39 | # CONFIG_SGI_IP22 is not set | 29 | # CONFIG_SGI_IP22 is not set |
40 | # CONFIG_SGI_IP27 is not set | 30 | # CONFIG_SGI_IP27 is not set |
31 | # CONFIG_SGI_IP28 is not set | ||
41 | CONFIG_SGI_IP32=y | 32 | CONFIG_SGI_IP32=y |
42 | # CONFIG_SIBYTE_BIGSUR is not set | ||
43 | # CONFIG_SIBYTE_SWARM is not set | ||
44 | # CONFIG_SIBYTE_SENTOSA is not set | ||
45 | # CONFIG_SIBYTE_RHONE is not set | ||
46 | # CONFIG_SIBYTE_CARMEL is not set | ||
47 | # CONFIG_SIBYTE_LITTLESUR is not set | ||
48 | # CONFIG_SIBYTE_CRHINE is not set | 33 | # CONFIG_SIBYTE_CRHINE is not set |
34 | # CONFIG_SIBYTE_CARMEL is not set | ||
49 | # CONFIG_SIBYTE_CRHONE is not set | 35 | # CONFIG_SIBYTE_CRHONE is not set |
36 | # CONFIG_SIBYTE_RHONE is not set | ||
37 | # CONFIG_SIBYTE_SWARM is not set | ||
38 | # CONFIG_SIBYTE_LITTLESUR is not set | ||
39 | # CONFIG_SIBYTE_SENTOSA is not set | ||
40 | # CONFIG_SIBYTE_BIGSUR is not set | ||
50 | # CONFIG_SNI_RM is not set | 41 | # CONFIG_SNI_RM is not set |
51 | # CONFIG_TOSHIBA_JMR3927 is not set | 42 | # CONFIG_MACH_TX39XX is not set |
52 | # CONFIG_TOSHIBA_RBTX4927 is not set | 43 | # CONFIG_MACH_TX49XX is not set |
53 | # CONFIG_TOSHIBA_RBTX4938 is not set | 44 | # CONFIG_MIKROTIK_RB532 is not set |
45 | # CONFIG_WR_PPMC is not set | ||
54 | CONFIG_RWSEM_GENERIC_SPINLOCK=y | 46 | CONFIG_RWSEM_GENERIC_SPINLOCK=y |
55 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set | 47 | # CONFIG_ARCH_HAS_ILOG2_U32 is not set |
56 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set | 48 | # CONFIG_ARCH_HAS_ILOG2_U64 is not set |
49 | CONFIG_ARCH_SUPPORTS_OPROFILE=y | ||
57 | CONFIG_GENERIC_FIND_NEXT_BIT=y | 50 | CONFIG_GENERIC_FIND_NEXT_BIT=y |
58 | CONFIG_GENERIC_HWEIGHT=y | 51 | CONFIG_GENERIC_HWEIGHT=y |
59 | CONFIG_GENERIC_CALIBRATE_DELAY=y | 52 | CONFIG_GENERIC_CALIBRATE_DELAY=y |
53 | CONFIG_GENERIC_CLOCKEVENTS=y | ||
60 | CONFIG_GENERIC_TIME=y | 54 | CONFIG_GENERIC_TIME=y |
55 | CONFIG_GENERIC_CMOS_UPDATE=y | ||
61 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y | 56 | CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y |
62 | # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set | 57 | # CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set |
63 | CONFIG_ARC=y | 58 | CONFIG_ARC=y |
59 | CONFIG_CEVT_R4K=y | ||
60 | CONFIG_CSRC_R4K=y | ||
64 | CONFIG_DMA_NONCOHERENT=y | 61 | CONFIG_DMA_NONCOHERENT=y |
65 | CONFIG_DMA_NEED_PCI_MAP_STATE=y | 62 | CONFIG_DMA_NEED_PCI_MAP_STATE=y |
63 | # CONFIG_HOTPLUG_CPU is not set | ||
64 | # CONFIG_NO_IOPORT is not set | ||
66 | CONFIG_CPU_BIG_ENDIAN=y | 65 | CONFIG_CPU_BIG_ENDIAN=y |
67 | # CONFIG_CPU_LITTLE_ENDIAN is not set | 66 | # CONFIG_CPU_LITTLE_ENDIAN is not set |
68 | CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y | 67 | CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y |
68 | CONFIG_IRQ_CPU=y | ||
69 | CONFIG_ARC32=y | 69 | CONFIG_ARC32=y |
70 | CONFIG_BOOT_ELF32=y | 70 | CONFIG_BOOT_ELF32=y |
71 | CONFIG_MIPS_L1_CACHE_SHIFT=5 | 71 | CONFIG_MIPS_L1_CACHE_SHIFT=5 |
@@ -75,6 +75,7 @@ CONFIG_ARC_PROMLIB=y | |||
75 | # | 75 | # |
76 | # CPU selection | 76 | # CPU selection |
77 | # | 77 | # |
78 | # CONFIG_CPU_LOONGSON2 is not set | ||
78 | # CONFIG_CPU_MIPS32_R1 is not set | 79 | # CONFIG_CPU_MIPS32_R1 is not set |
79 | # CONFIG_CPU_MIPS32_R2 is not set | 80 | # CONFIG_CPU_MIPS32_R2 is not set |
80 | # CONFIG_CPU_MIPS64_R1 is not set | 81 | # CONFIG_CPU_MIPS64_R1 is not set |
@@ -87,6 +88,7 @@ CONFIG_ARC_PROMLIB=y | |||
87 | # CONFIG_CPU_TX49XX is not set | 88 | # CONFIG_CPU_TX49XX is not set |
88 | CONFIG_CPU_R5000=y | 89 | CONFIG_CPU_R5000=y |
89 | # CONFIG_CPU_R5432 is not set | 90 | # CONFIG_CPU_R5432 is not set |
91 | # CONFIG_CPU_R5500 is not set | ||
90 | # CONFIG_CPU_R6000 is not set | 92 | # CONFIG_CPU_R6000 is not set |
91 | # CONFIG_CPU_NEVADA is not set | 93 | # CONFIG_CPU_NEVADA is not set |
92 | # CONFIG_CPU_R8000 is not set | 94 | # CONFIG_CPU_R8000 is not set |
@@ -116,65 +118,73 @@ CONFIG_RM7000_CPU_SCACHE=y | |||
116 | CONFIG_MIPS_MT_DISABLED=y | 118 | CONFIG_MIPS_MT_DISABLED=y |
117 | # CONFIG_MIPS_MT_SMP is not set | 119 | # CONFIG_MIPS_MT_SMP is not set |
118 | # CONFIG_MIPS_MT_SMTC is not set | 120 | # CONFIG_MIPS_MT_SMTC is not set |
119 | # CONFIG_MIPS_VPE_LOADER is not set | ||
120 | CONFIG_CPU_HAS_LLSC=y | 121 | CONFIG_CPU_HAS_LLSC=y |
121 | CONFIG_CPU_HAS_SYNC=y | 122 | CONFIG_CPU_HAS_SYNC=y |
122 | CONFIG_GENERIC_HARDIRQS=y | 123 | CONFIG_GENERIC_HARDIRQS=y |
123 | CONFIG_GENERIC_IRQ_PROBE=y | 124 | CONFIG_GENERIC_IRQ_PROBE=y |
124 | CONFIG_ARCH_FLATMEM_ENABLE=y | 125 | CONFIG_ARCH_FLATMEM_ENABLE=y |
126 | CONFIG_ARCH_POPULATES_NODE_MAP=y | ||
125 | CONFIG_SELECT_MEMORY_MODEL=y | 127 | CONFIG_SELECT_MEMORY_MODEL=y |
126 | CONFIG_FLATMEM_MANUAL=y | 128 | CONFIG_FLATMEM_MANUAL=y |
127 | # CONFIG_DISCONTIGMEM_MANUAL is not set | 129 | # CONFIG_DISCONTIGMEM_MANUAL is not set |
128 | # CONFIG_SPARSEMEM_MANUAL is not set | 130 | # CONFIG_SPARSEMEM_MANUAL is not set |
129 | CONFIG_FLATMEM=y | 131 | CONFIG_FLATMEM=y |
130 | CONFIG_FLAT_NODE_MEM_MAP=y | 132 | CONFIG_FLAT_NODE_MEM_MAP=y |
131 | # CONFIG_SPARSEMEM_STATIC is not set | 133 | CONFIG_PAGEFLAGS_EXTENDED=y |
132 | CONFIG_SPLIT_PTLOCK_CPUS=4 | 134 | CONFIG_SPLIT_PTLOCK_CPUS=4 |
133 | CONFIG_RESOURCES_64BIT=y | 135 | CONFIG_RESOURCES_64BIT=y |
134 | CONFIG_ZONE_DMA_FLAG=1 | 136 | CONFIG_PHYS_ADDR_T_64BIT=y |
137 | CONFIG_ZONE_DMA_FLAG=0 | ||
138 | CONFIG_VIRT_TO_BUS=y | ||
139 | CONFIG_UNEVICTABLE_LRU=y | ||
140 | # CONFIG_NO_HZ is not set | ||
141 | # CONFIG_HIGH_RES_TIMERS is not set | ||
142 | CONFIG_GENERIC_CLOCKEVENTS_BUILD=y | ||
135 | # CONFIG_HZ_48 is not set | 143 | # CONFIG_HZ_48 is not set |
136 | # CONFIG_HZ_100 is not set | 144 | # CONFIG_HZ_100 is not set |
137 | # CONFIG_HZ_128 is not set | 145 | # CONFIG_HZ_128 is not set |
138 | # CONFIG_HZ_250 is not set | 146 | CONFIG_HZ_250=y |
139 | # CONFIG_HZ_256 is not set | 147 | # CONFIG_HZ_256 is not set |
140 | CONFIG_HZ_1000=y | 148 | # CONFIG_HZ_1000 is not set |
141 | # CONFIG_HZ_1024 is not set | 149 | # CONFIG_HZ_1024 is not set |
142 | CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | 150 | CONFIG_SYS_SUPPORTS_ARBIT_HZ=y |
143 | CONFIG_HZ=1000 | 151 | CONFIG_HZ=250 |
144 | # CONFIG_PREEMPT_NONE is not set | 152 | CONFIG_PREEMPT_NONE=y |
145 | CONFIG_PREEMPT_VOLUNTARY=y | 153 | # CONFIG_PREEMPT_VOLUNTARY is not set |
146 | # CONFIG_PREEMPT is not set | 154 | # CONFIG_PREEMPT is not set |
147 | # CONFIG_KEXEC is not set | 155 | # CONFIG_KEXEC is not set |
156 | # CONFIG_SECCOMP is not set | ||
148 | CONFIG_LOCKDEP_SUPPORT=y | 157 | CONFIG_LOCKDEP_SUPPORT=y |
149 | CONFIG_STACKTRACE_SUPPORT=y | 158 | CONFIG_STACKTRACE_SUPPORT=y |
150 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" | 159 | CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" |
151 | 160 | ||
152 | # | 161 | # |
153 | # Code maturity level options | 162 | # General setup |
154 | # | 163 | # |
155 | CONFIG_EXPERIMENTAL=y | 164 | CONFIG_EXPERIMENTAL=y |
156 | CONFIG_BROKEN_ON_SMP=y | 165 | CONFIG_BROKEN_ON_SMP=y |
157 | CONFIG_INIT_ENV_ARG_LIMIT=32 | 166 | CONFIG_INIT_ENV_ARG_LIMIT=32 |
158 | |||
159 | # | ||
160 | # General setup | ||
161 | # | ||
162 | CONFIG_LOCALVERSION="" | 167 | CONFIG_LOCALVERSION="" |
163 | CONFIG_LOCALVERSION_AUTO=y | 168 | CONFIG_LOCALVERSION_AUTO=y |
164 | CONFIG_SWAP=y | 169 | CONFIG_SWAP=y |
165 | CONFIG_SYSVIPC=y | 170 | CONFIG_SYSVIPC=y |
166 | # CONFIG_IPC_NS is not set | ||
167 | CONFIG_SYSVIPC_SYSCTL=y | 171 | CONFIG_SYSVIPC_SYSCTL=y |
168 | # CONFIG_POSIX_MQUEUE is not set | 172 | CONFIG_POSIX_MQUEUE=y |
169 | CONFIG_BSD_PROCESS_ACCT=y | 173 | CONFIG_BSD_PROCESS_ACCT=y |
170 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set | 174 | # CONFIG_BSD_PROCESS_ACCT_V3 is not set |
171 | # CONFIG_TASKSTATS is not set | 175 | # CONFIG_TASKSTATS is not set |
172 | # CONFIG_UTS_NS is not set | 176 | CONFIG_AUDIT=y |
173 | # CONFIG_AUDIT is not set | 177 | CONFIG_IKCONFIG=y |
174 | # CONFIG_IKCONFIG is not set | 178 | CONFIG_IKCONFIG_PROC=y |
179 | CONFIG_LOG_BUF_SHIFT=14 | ||
180 | # CONFIG_CGROUPS is not set | ||
181 | # CONFIG_GROUP_SCHED is not set | ||
175 | CONFIG_SYSFS_DEPRECATED=y | 182 | CONFIG_SYSFS_DEPRECATED=y |
183 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
176 | CONFIG_RELAY=y | 184 | CONFIG_RELAY=y |
177 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | 185 | # CONFIG_NAMESPACES is not set |
186 | # CONFIG_BLK_DEV_INITRD is not set | ||
187 | CONFIG_CC_OPTIMIZE_FOR_SIZE=y | ||
178 | CONFIG_SYSCTL=y | 188 | CONFIG_SYSCTL=y |
179 | CONFIG_EMBEDDED=y | 189 | CONFIG_EMBEDDED=y |
180 | CONFIG_SYSCTL_SYSCALL=y | 190 | CONFIG_SYSCTL_SYSCALL=y |
@@ -184,27 +194,43 @@ CONFIG_HOTPLUG=y | |||
184 | CONFIG_PRINTK=y | 194 | CONFIG_PRINTK=y |
185 | CONFIG_BUG=y | 195 | CONFIG_BUG=y |
186 | CONFIG_ELF_CORE=y | 196 | CONFIG_ELF_CORE=y |
197 | CONFIG_PCSPKR_PLATFORM=y | ||
198 | CONFIG_COMPAT_BRK=y | ||
187 | CONFIG_BASE_FULL=y | 199 | CONFIG_BASE_FULL=y |
188 | CONFIG_FUTEX=y | 200 | CONFIG_FUTEX=y |
201 | CONFIG_ANON_INODES=y | ||
189 | CONFIG_EPOLL=y | 202 | CONFIG_EPOLL=y |
203 | CONFIG_SIGNALFD=y | ||
204 | CONFIG_TIMERFD=y | ||
205 | CONFIG_EVENTFD=y | ||
190 | CONFIG_SHMEM=y | 206 | CONFIG_SHMEM=y |
191 | CONFIG_SLAB=y | 207 | CONFIG_AIO=y |
192 | CONFIG_VM_EVENT_COUNTERS=y | 208 | CONFIG_VM_EVENT_COUNTERS=y |
209 | CONFIG_PCI_QUIRKS=y | ||
210 | CONFIG_SLAB=y | ||
211 | # CONFIG_SLUB is not set | ||
212 | # CONFIG_SLOB is not set | ||
213 | CONFIG_PROFILING=y | ||
214 | # CONFIG_MARKERS is not set | ||
215 | CONFIG_OPROFILE=m | ||
216 | CONFIG_HAVE_OPROFILE=y | ||
217 | # CONFIG_HAVE_GENERIC_DMA_COHERENT is not set | ||
218 | CONFIG_SLABINFO=y | ||
193 | CONFIG_RT_MUTEXES=y | 219 | CONFIG_RT_MUTEXES=y |
194 | # CONFIG_TINY_SHMEM is not set | 220 | # CONFIG_TINY_SHMEM is not set |
195 | CONFIG_BASE_SMALL=0 | 221 | CONFIG_BASE_SMALL=0 |
196 | # CONFIG_SLOB is not set | 222 | CONFIG_MODULES=y |
197 | 223 | # CONFIG_MODULE_FORCE_LOAD is not set | |
198 | # | 224 | CONFIG_MODULE_UNLOAD=y |
199 | # Loadable module support | 225 | # CONFIG_MODULE_FORCE_UNLOAD is not set |
200 | # | 226 | # CONFIG_MODVERSIONS is not set |
201 | # CONFIG_MODULES is not set | 227 | # CONFIG_MODULE_SRCVERSION_ALL is not set |
202 | 228 | CONFIG_KMOD=y | |
203 | # | ||
204 | # Block layer | ||
205 | # | ||
206 | CONFIG_BLOCK=y | 229 | CONFIG_BLOCK=y |
207 | # CONFIG_BLK_DEV_IO_TRACE is not set | 230 | # CONFIG_BLK_DEV_IO_TRACE is not set |
231 | # CONFIG_BLK_DEV_BSG is not set | ||
232 | # CONFIG_BLK_DEV_INTEGRITY is not set | ||
233 | CONFIG_BLOCK_COMPAT=y | ||
208 | 234 | ||
209 | # | 235 | # |
210 | # IO Schedulers | 236 | # IO Schedulers |
@@ -213,59 +239,50 @@ CONFIG_IOSCHED_NOOP=y | |||
213 | CONFIG_IOSCHED_AS=y | 239 | CONFIG_IOSCHED_AS=y |
214 | CONFIG_IOSCHED_DEADLINE=y | 240 | CONFIG_IOSCHED_DEADLINE=y |
215 | CONFIG_IOSCHED_CFQ=y | 241 | CONFIG_IOSCHED_CFQ=y |
216 | CONFIG_DEFAULT_AS=y | 242 | # CONFIG_DEFAULT_AS is not set |
217 | # CONFIG_DEFAULT_DEADLINE is not set | 243 | # CONFIG_DEFAULT_DEADLINE is not set |
218 | # CONFIG_DEFAULT_CFQ is not set | 244 | CONFIG_DEFAULT_CFQ=y |
219 | # CONFIG_DEFAULT_NOOP is not set | 245 | # CONFIG_DEFAULT_NOOP is not set |
220 | CONFIG_DEFAULT_IOSCHED="anticipatory" | 246 | CONFIG_DEFAULT_IOSCHED="cfq" |
247 | CONFIG_CLASSIC_RCU=y | ||
248 | # CONFIG_FREEZER is not set | ||
221 | 249 | ||
222 | # | 250 | # |
223 | # Bus options (PCI, PCMCIA, EISA, ISA, TC) | 251 | # Bus options (PCI, PCMCIA, EISA, ISA, TC) |
224 | # | 252 | # |
225 | CONFIG_HW_HAS_PCI=y | 253 | CONFIG_HW_HAS_PCI=y |
226 | CONFIG_PCI=y | 254 | CONFIG_PCI=y |
255 | CONFIG_PCI_DOMAINS=y | ||
256 | # CONFIG_ARCH_SUPPORTS_MSI is not set | ||
257 | # CONFIG_PCI_LEGACY is not set | ||
227 | CONFIG_MMU=y | 258 | CONFIG_MMU=y |
228 | |||
229 | # | ||
230 | # PCCARD (PCMCIA/CardBus) support | ||
231 | # | ||
232 | # CONFIG_PCCARD is not set | 259 | # CONFIG_PCCARD is not set |
233 | |||
234 | # | ||
235 | # PCI Hotplug Support | ||
236 | # | ||
237 | # CONFIG_HOTPLUG_PCI is not set | 260 | # CONFIG_HOTPLUG_PCI is not set |
238 | 261 | ||
239 | # | 262 | # |
240 | # Executable file formats | 263 | # Executable file formats |
241 | # | 264 | # |
242 | CONFIG_BINFMT_ELF=y | 265 | CONFIG_BINFMT_ELF=y |
266 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | ||
267 | # CONFIG_HAVE_AOUT is not set | ||
243 | CONFIG_BINFMT_MISC=y | 268 | CONFIG_BINFMT_MISC=y |
244 | # CONFIG_BUILD_ELF64 is not set | ||
245 | CONFIG_MIPS32_COMPAT=y | 269 | CONFIG_MIPS32_COMPAT=y |
246 | CONFIG_COMPAT=y | 270 | CONFIG_COMPAT=y |
247 | CONFIG_SYSVIPC_COMPAT=y | 271 | CONFIG_SYSVIPC_COMPAT=y |
248 | CONFIG_MIPS32_O32=y | 272 | CONFIG_MIPS32_O32=y |
249 | # CONFIG_MIPS32_N32 is not set | 273 | CONFIG_MIPS32_N32=y |
250 | CONFIG_BINFMT_ELF32=y | 274 | CONFIG_BINFMT_ELF32=y |
251 | 275 | ||
252 | # | 276 | # |
253 | # Power management options | 277 | # Power management options |
254 | # | 278 | # |
255 | CONFIG_PM=y | 279 | CONFIG_ARCH_SUSPEND_POSSIBLE=y |
256 | # CONFIG_PM_LEGACY is not set | 280 | # CONFIG_PM is not set |
257 | # CONFIG_PM_DEBUG is not set | ||
258 | # CONFIG_PM_SYSFS_DEPRECATED is not set | ||
259 | |||
260 | # | ||
261 | # Networking | ||
262 | # | ||
263 | CONFIG_NET=y | 281 | CONFIG_NET=y |
264 | 282 | ||
265 | # | 283 | # |
266 | # Networking options | 284 | # Networking options |
267 | # | 285 | # |
268 | # CONFIG_NETDEBUG is not set | ||
269 | CONFIG_PACKET=y | 286 | CONFIG_PACKET=y |
270 | CONFIG_PACKET_MMAP=y | 287 | CONFIG_PACKET_MMAP=y |
271 | CONFIG_UNIX=y | 288 | CONFIG_UNIX=y |
@@ -273,56 +290,83 @@ CONFIG_XFRM=y | |||
273 | CONFIG_XFRM_USER=y | 290 | CONFIG_XFRM_USER=y |
274 | # CONFIG_XFRM_SUB_POLICY is not set | 291 | # CONFIG_XFRM_SUB_POLICY is not set |
275 | CONFIG_XFRM_MIGRATE=y | 292 | CONFIG_XFRM_MIGRATE=y |
293 | # CONFIG_XFRM_STATISTICS is not set | ||
294 | CONFIG_XFRM_IPCOMP=m | ||
276 | CONFIG_NET_KEY=y | 295 | CONFIG_NET_KEY=y |
277 | CONFIG_NET_KEY_MIGRATE=y | 296 | CONFIG_NET_KEY_MIGRATE=y |
278 | CONFIG_INET=y | 297 | CONFIG_INET=y |
279 | # CONFIG_IP_MULTICAST is not set | 298 | CONFIG_IP_MULTICAST=y |
280 | # CONFIG_IP_ADVANCED_ROUTER is not set | 299 | # CONFIG_IP_ADVANCED_ROUTER is not set |
281 | CONFIG_IP_FIB_HASH=y | 300 | CONFIG_IP_FIB_HASH=y |
282 | CONFIG_IP_PNP=y | 301 | CONFIG_IP_PNP=y |
283 | # CONFIG_IP_PNP_DHCP is not set | 302 | CONFIG_IP_PNP_DHCP=y |
284 | CONFIG_IP_PNP_BOOTP=y | 303 | CONFIG_IP_PNP_BOOTP=y |
285 | # CONFIG_IP_PNP_RARP is not set | 304 | # CONFIG_IP_PNP_RARP is not set |
286 | # CONFIG_NET_IPIP is not set | 305 | CONFIG_NET_IPIP=m |
287 | # CONFIG_NET_IPGRE is not set | 306 | CONFIG_NET_IPGRE=m |
307 | # CONFIG_NET_IPGRE_BROADCAST is not set | ||
308 | # CONFIG_IP_MROUTE is not set | ||
288 | # CONFIG_ARPD is not set | 309 | # CONFIG_ARPD is not set |
289 | # CONFIG_SYN_COOKIES is not set | 310 | # CONFIG_SYN_COOKIES is not set |
290 | # CONFIG_INET_AH is not set | 311 | CONFIG_INET_AH=m |
291 | # CONFIG_INET_ESP is not set | 312 | CONFIG_INET_ESP=m |
292 | # CONFIG_INET_IPCOMP is not set | 313 | CONFIG_INET_IPCOMP=m |
293 | # CONFIG_INET_XFRM_TUNNEL is not set | 314 | CONFIG_INET_XFRM_TUNNEL=m |
294 | # CONFIG_INET_TUNNEL is not set | 315 | CONFIG_INET_TUNNEL=m |
295 | CONFIG_INET_XFRM_MODE_TRANSPORT=y | 316 | CONFIG_INET_XFRM_MODE_TRANSPORT=y |
296 | CONFIG_INET_XFRM_MODE_TUNNEL=y | 317 | CONFIG_INET_XFRM_MODE_TUNNEL=y |
297 | CONFIG_INET_XFRM_MODE_BEET=y | 318 | CONFIG_INET_XFRM_MODE_BEET=y |
319 | # CONFIG_INET_LRO is not set | ||
298 | CONFIG_INET_DIAG=y | 320 | CONFIG_INET_DIAG=y |
299 | CONFIG_INET_TCP_DIAG=y | 321 | CONFIG_INET_TCP_DIAG=y |
300 | # CONFIG_TCP_CONG_ADVANCED is not set | 322 | CONFIG_TCP_CONG_ADVANCED=y |
323 | CONFIG_TCP_CONG_BIC=m | ||
301 | CONFIG_TCP_CONG_CUBIC=y | 324 | CONFIG_TCP_CONG_CUBIC=y |
325 | CONFIG_TCP_CONG_WESTWOOD=m | ||
326 | CONFIG_TCP_CONG_HTCP=m | ||
327 | # CONFIG_TCP_CONG_HSTCP is not set | ||
328 | # CONFIG_TCP_CONG_HYBLA is not set | ||
329 | # CONFIG_TCP_CONG_VEGAS is not set | ||
330 | # CONFIG_TCP_CONG_SCALABLE is not set | ||
331 | # CONFIG_TCP_CONG_LP is not set | ||
332 | # CONFIG_TCP_CONG_VENO is not set | ||
333 | # CONFIG_TCP_CONG_YEAH is not set | ||
334 | # CONFIG_TCP_CONG_ILLINOIS is not set | ||
335 | # CONFIG_DEFAULT_BIC is not set | ||
336 | CONFIG_DEFAULT_CUBIC=y | ||
337 | # CONFIG_DEFAULT_HTCP is not set | ||
338 | # CONFIG_DEFAULT_VEGAS is not set | ||
339 | # CONFIG_DEFAULT_WESTWOOD is not set | ||
340 | # CONFIG_DEFAULT_RENO is not set | ||
302 | CONFIG_DEFAULT_TCP_CONG="cubic" | 341 | CONFIG_DEFAULT_TCP_CONG="cubic" |
303 | CONFIG_TCP_MD5SIG=y | 342 | CONFIG_TCP_MD5SIG=y |
304 | # CONFIG_IPV6 is not set | 343 | CONFIG_IPV6=m |
305 | # CONFIG_INET6_XFRM_TUNNEL is not set | 344 | # CONFIG_IPV6_PRIVACY is not set |
306 | # CONFIG_INET6_TUNNEL is not set | 345 | # CONFIG_IPV6_ROUTER_PREF is not set |
346 | # CONFIG_IPV6_OPTIMISTIC_DAD is not set | ||
347 | CONFIG_INET6_AH=m | ||
348 | CONFIG_INET6_ESP=m | ||
349 | CONFIG_INET6_IPCOMP=m | ||
350 | # CONFIG_IPV6_MIP6 is not set | ||
351 | CONFIG_INET6_XFRM_TUNNEL=m | ||
352 | CONFIG_INET6_TUNNEL=m | ||
353 | CONFIG_INET6_XFRM_MODE_TRANSPORT=m | ||
354 | CONFIG_INET6_XFRM_MODE_TUNNEL=m | ||
355 | CONFIG_INET6_XFRM_MODE_BEET=m | ||
356 | # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set | ||
357 | CONFIG_IPV6_SIT=m | ||
358 | CONFIG_IPV6_NDISC_NODETYPE=y | ||
359 | CONFIG_IPV6_TUNNEL=m | ||
360 | # CONFIG_IPV6_MULTIPLE_TABLES is not set | ||
361 | # CONFIG_IPV6_MROUTE is not set | ||
307 | CONFIG_NETWORK_SECMARK=y | 362 | CONFIG_NETWORK_SECMARK=y |
308 | # CONFIG_NETFILTER is not set | 363 | # CONFIG_NETFILTER is not set |
309 | |||
310 | # | ||
311 | # DCCP Configuration (EXPERIMENTAL) | ||
312 | # | ||
313 | # CONFIG_IP_DCCP is not set | 364 | # CONFIG_IP_DCCP is not set |
314 | |||
315 | # | ||
316 | # SCTP Configuration (EXPERIMENTAL) | ||
317 | # | ||
318 | # CONFIG_IP_SCTP is not set | 365 | # CONFIG_IP_SCTP is not set |
319 | |||
320 | # | ||
321 | # TIPC Configuration (EXPERIMENTAL) | ||
322 | # | ||
323 | # CONFIG_TIPC is not set | 366 | # CONFIG_TIPC is not set |
324 | # CONFIG_ATM is not set | 367 | # CONFIG_ATM is not set |
325 | # CONFIG_BRIDGE is not set | 368 | # CONFIG_BRIDGE is not set |
369 | # CONFIG_NET_DSA is not set | ||
326 | # CONFIG_VLAN_8021Q is not set | 370 | # CONFIG_VLAN_8021Q is not set |
327 | # CONFIG_DECNET is not set | 371 | # CONFIG_DECNET is not set |
328 | # CONFIG_LLC2 is not set | 372 | # CONFIG_LLC2 is not set |
@@ -332,10 +376,6 @@ CONFIG_NETWORK_SECMARK=y | |||
332 | # CONFIG_LAPB is not set | 376 | # CONFIG_LAPB is not set |
333 | # CONFIG_ECONET is not set | 377 | # CONFIG_ECONET is not set |
334 | # CONFIG_WAN_ROUTER is not set | 378 | # CONFIG_WAN_ROUTER is not set |
335 | |||
336 | # | ||
337 | # QoS and/or fair queueing | ||
338 | # | ||
339 | # CONFIG_NET_SCHED is not set | 379 | # CONFIG_NET_SCHED is not set |
340 | 380 | ||
341 | # | 381 | # |
@@ -343,15 +383,14 @@ CONFIG_NETWORK_SECMARK=y | |||
343 | # | 383 | # |
344 | # CONFIG_NET_PKTGEN is not set | 384 | # CONFIG_NET_PKTGEN is not set |
345 | # CONFIG_HAMRADIO is not set | 385 | # CONFIG_HAMRADIO is not set |
386 | # CONFIG_CAN is not set | ||
346 | # CONFIG_IRDA is not set | 387 | # CONFIG_IRDA is not set |
347 | # CONFIG_BT is not set | 388 | # CONFIG_BT is not set |
348 | CONFIG_IEEE80211=y | 389 | # CONFIG_AF_RXRPC is not set |
349 | # CONFIG_IEEE80211_DEBUG is not set | 390 | # CONFIG_PHONET is not set |
350 | CONFIG_IEEE80211_CRYPT_WEP=y | 391 | # CONFIG_WIRELESS is not set |
351 | CONFIG_IEEE80211_CRYPT_CCMP=y | 392 | # CONFIG_RFKILL is not set |
352 | CONFIG_IEEE80211_SOFTMAC=y | 393 | # CONFIG_NET_9P is not set |
353 | # CONFIG_IEEE80211_SOFTMAC_DEBUG is not set | ||
354 | CONFIG_WIRELESS_EXT=y | ||
355 | 394 | ||
356 | # | 395 | # |
357 | # Device Drivers | 396 | # Device Drivers |
@@ -360,60 +399,40 @@ CONFIG_WIRELESS_EXT=y | |||
360 | # | 399 | # |
361 | # Generic Driver Options | 400 | # Generic Driver Options |
362 | # | 401 | # |
402 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
363 | CONFIG_STANDALONE=y | 403 | CONFIG_STANDALONE=y |
364 | CONFIG_PREVENT_FIRMWARE_BUILD=y | 404 | CONFIG_PREVENT_FIRMWARE_BUILD=y |
365 | CONFIG_FW_LOADER=y | 405 | CONFIG_FW_LOADER=y |
406 | CONFIG_FIRMWARE_IN_KERNEL=y | ||
407 | CONFIG_EXTRA_FIRMWARE="" | ||
366 | # CONFIG_SYS_HYPERVISOR is not set | 408 | # CONFIG_SYS_HYPERVISOR is not set |
367 | |||
368 | # | ||
369 | # Connector - unified userspace <-> kernelspace linker | ||
370 | # | ||
371 | CONFIG_CONNECTOR=y | 409 | CONFIG_CONNECTOR=y |
372 | CONFIG_PROC_EVENTS=y | 410 | CONFIG_PROC_EVENTS=y |
373 | |||
374 | # | ||
375 | # Memory Technology Devices (MTD) | ||
376 | # | ||
377 | # CONFIG_MTD is not set | 411 | # CONFIG_MTD is not set |
378 | |||
379 | # | ||
380 | # Parallel port support | ||
381 | # | ||
382 | # CONFIG_PARPORT is not set | 412 | # CONFIG_PARPORT is not set |
383 | 413 | CONFIG_BLK_DEV=y | |
384 | # | ||
385 | # Plug and Play support | ||
386 | # | ||
387 | # CONFIG_PNPACPI is not set | ||
388 | |||
389 | # | ||
390 | # Block devices | ||
391 | # | ||
392 | # CONFIG_BLK_CPQ_DA is not set | 414 | # CONFIG_BLK_CPQ_DA is not set |
393 | # CONFIG_BLK_CPQ_CISS_DA is not set | 415 | # CONFIG_BLK_CPQ_CISS_DA is not set |
394 | # CONFIG_BLK_DEV_DAC960 is not set | 416 | # CONFIG_BLK_DEV_DAC960 is not set |
395 | # CONFIG_BLK_DEV_UMEM is not set | 417 | # CONFIG_BLK_DEV_UMEM is not set |
396 | # CONFIG_BLK_DEV_COW_COMMON is not set | 418 | # CONFIG_BLK_DEV_COW_COMMON is not set |
397 | CONFIG_BLK_DEV_LOOP=y | 419 | CONFIG_BLK_DEV_LOOP=m |
398 | # CONFIG_BLK_DEV_CRYPTOLOOP is not set | 420 | CONFIG_BLK_DEV_CRYPTOLOOP=m |
399 | # CONFIG_BLK_DEV_NBD is not set | 421 | CONFIG_BLK_DEV_NBD=m |
400 | # CONFIG_BLK_DEV_SX8 is not set | 422 | # CONFIG_BLK_DEV_SX8 is not set |
401 | # CONFIG_BLK_DEV_RAM is not set | 423 | # CONFIG_BLK_DEV_RAM is not set |
402 | # CONFIG_BLK_DEV_INITRD is not set | 424 | # CONFIG_CDROM_PKTCDVD is not set |
403 | CONFIG_CDROM_PKTCDVD=y | 425 | # CONFIG_ATA_OVER_ETH is not set |
404 | CONFIG_CDROM_PKTCDVD_BUFFERS=8 | 426 | # CONFIG_BLK_DEV_HD is not set |
405 | # CONFIG_CDROM_PKTCDVD_WCACHE is not set | 427 | CONFIG_MISC_DEVICES=y |
406 | CONFIG_ATA_OVER_ETH=y | 428 | # CONFIG_PHANTOM is not set |
407 | 429 | # CONFIG_EEPROM_93CX6 is not set | |
408 | # | ||
409 | # Misc devices | ||
410 | # | ||
411 | CONFIG_SGI_IOC4=y | 430 | CONFIG_SGI_IOC4=y |
412 | # CONFIG_TIFM_CORE is not set | 431 | # CONFIG_TIFM_CORE is not set |
413 | 432 | # CONFIG_ENCLOSURE_SERVICES is not set | |
414 | # | 433 | # CONFIG_HP_ILO is not set |
415 | # ATA/ATAPI/MFM/RLL support | 434 | # CONFIG_C2PORT is not set |
416 | # | 435 | CONFIG_HAVE_IDE=y |
417 | # CONFIG_IDE is not set | 436 | # CONFIG_IDE is not set |
418 | 437 | ||
419 | # | 438 | # |
@@ -421,19 +440,20 @@ CONFIG_SGI_IOC4=y | |||
421 | # | 440 | # |
422 | CONFIG_RAID_ATTRS=y | 441 | CONFIG_RAID_ATTRS=y |
423 | CONFIG_SCSI=y | 442 | CONFIG_SCSI=y |
443 | CONFIG_SCSI_DMA=y | ||
424 | CONFIG_SCSI_TGT=y | 444 | CONFIG_SCSI_TGT=y |
425 | CONFIG_SCSI_NETLINK=y | 445 | # CONFIG_SCSI_NETLINK is not set |
426 | CONFIG_SCSI_PROC_FS=y | 446 | CONFIG_SCSI_PROC_FS=y |
427 | 447 | ||
428 | # | 448 | # |
429 | # SCSI support type (disk, tape, CD-ROM) | 449 | # SCSI support type (disk, tape, CD-ROM) |
430 | # | 450 | # |
431 | CONFIG_BLK_DEV_SD=y | 451 | CONFIG_BLK_DEV_SD=y |
432 | CONFIG_CHR_DEV_ST=y | 452 | # CONFIG_CHR_DEV_ST is not set |
433 | CONFIG_CHR_DEV_OSST=y | 453 | # CONFIG_CHR_DEV_OSST is not set |
434 | CONFIG_BLK_DEV_SR=y | 454 | CONFIG_BLK_DEV_SR=y |
435 | CONFIG_BLK_DEV_SR_VENDOR=y | 455 | CONFIG_BLK_DEV_SR_VENDOR=y |
436 | CONFIG_CHR_DEV_SG=y | 456 | CONFIG_CHR_DEV_SG=m |
437 | # CONFIG_CHR_DEV_SCH is not set | 457 | # CONFIG_CHR_DEV_SCH is not set |
438 | 458 | ||
439 | # | 459 | # |
@@ -443,35 +463,36 @@ CONFIG_SCSI_MULTI_LUN=y | |||
443 | CONFIG_SCSI_CONSTANTS=y | 463 | CONFIG_SCSI_CONSTANTS=y |
444 | CONFIG_SCSI_LOGGING=y | 464 | CONFIG_SCSI_LOGGING=y |
445 | CONFIG_SCSI_SCAN_ASYNC=y | 465 | CONFIG_SCSI_SCAN_ASYNC=y |
466 | CONFIG_SCSI_WAIT_SCAN=m | ||
446 | 467 | ||
447 | # | 468 | # |
448 | # SCSI Transports | 469 | # SCSI Transports |
449 | # | 470 | # |
450 | CONFIG_SCSI_SPI_ATTRS=y | 471 | CONFIG_SCSI_SPI_ATTRS=y |
451 | CONFIG_SCSI_FC_ATTRS=y | 472 | # CONFIG_SCSI_FC_ATTRS is not set |
452 | # CONFIG_SCSI_ISCSI_ATTRS is not set | 473 | # CONFIG_SCSI_ISCSI_ATTRS is not set |
453 | CONFIG_SCSI_SAS_ATTRS=y | 474 | CONFIG_SCSI_SAS_ATTRS=y |
454 | CONFIG_SCSI_SAS_LIBSAS=y | 475 | CONFIG_SCSI_SAS_LIBSAS=y |
476 | CONFIG_SCSI_SAS_HOST_SMP=y | ||
455 | # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set | 477 | # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set |
456 | 478 | # CONFIG_SCSI_SRP_ATTRS is not set | |
457 | # | 479 | CONFIG_SCSI_LOWLEVEL=y |
458 | # SCSI low-level drivers | ||
459 | # | ||
460 | # CONFIG_ISCSI_TCP is not set | 480 | # CONFIG_ISCSI_TCP is not set |
461 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set | 481 | # CONFIG_BLK_DEV_3W_XXXX_RAID is not set |
462 | # CONFIG_SCSI_3W_9XXX is not set | 482 | # CONFIG_SCSI_3W_9XXX is not set |
463 | # CONFIG_SCSI_ACARD is not set | 483 | # CONFIG_SCSI_ACARD is not set |
464 | # CONFIG_SCSI_AACRAID is not set | 484 | # CONFIG_SCSI_AACRAID is not set |
465 | CONFIG_SCSI_AIC7XXX=y | 485 | CONFIG_SCSI_AIC7XXX=y |
466 | CONFIG_AIC7XXX_CMDS_PER_DEVICE=8 | 486 | CONFIG_AIC7XXX_CMDS_PER_DEVICE=32 |
467 | CONFIG_AIC7XXX_RESET_DELAY_MS=15000 | 487 | CONFIG_AIC7XXX_RESET_DELAY_MS=15000 |
468 | CONFIG_AIC7XXX_DEBUG_ENABLE=y | 488 | CONFIG_AIC7XXX_DEBUG_ENABLE=y |
469 | CONFIG_AIC7XXX_DEBUG_MASK=0 | 489 | CONFIG_AIC7XXX_DEBUG_MASK=0 |
470 | CONFIG_AIC7XXX_REG_PRETTY_PRINT=y | 490 | CONFIG_AIC7XXX_REG_PRETTY_PRINT=y |
471 | # CONFIG_SCSI_AIC7XXX_OLD is not set | 491 | # CONFIG_SCSI_AIC7XXX_OLD is not set |
472 | # CONFIG_SCSI_AIC79XX is not set | 492 | # CONFIG_SCSI_AIC79XX is not set |
473 | CONFIG_SCSI_AIC94XX=y | 493 | # CONFIG_SCSI_AIC94XX is not set |
474 | # CONFIG_AIC94XX_DEBUG is not set | 494 | # CONFIG_SCSI_DPT_I2O is not set |
495 | # CONFIG_SCSI_ADVANSYS is not set | ||
475 | # CONFIG_SCSI_ARCMSR is not set | 496 | # CONFIG_SCSI_ARCMSR is not set |
476 | # CONFIG_MEGARAID_NEWGEN is not set | 497 | # CONFIG_MEGARAID_NEWGEN is not set |
477 | # CONFIG_MEGARAID_LEGACY is not set | 498 | # CONFIG_MEGARAID_LEGACY is not set |
@@ -482,6 +503,7 @@ CONFIG_SCSI_AIC94XX=y | |||
482 | # CONFIG_SCSI_IPS is not set | 503 | # CONFIG_SCSI_IPS is not set |
483 | # CONFIG_SCSI_INITIO is not set | 504 | # CONFIG_SCSI_INITIO is not set |
484 | # CONFIG_SCSI_INIA100 is not set | 505 | # CONFIG_SCSI_INIA100 is not set |
506 | # CONFIG_SCSI_MVSAS is not set | ||
485 | # CONFIG_SCSI_STEX is not set | 507 | # CONFIG_SCSI_STEX is not set |
486 | # CONFIG_SCSI_SYM53C8XX_2 is not set | 508 | # CONFIG_SCSI_SYM53C8XX_2 is not set |
487 | # CONFIG_SCSI_QLOGIC_1280 is not set | 509 | # CONFIG_SCSI_QLOGIC_1280 is not set |
@@ -492,147 +514,81 @@ CONFIG_SCSI_AIC94XX=y | |||
492 | # CONFIG_SCSI_DC390T is not set | 514 | # CONFIG_SCSI_DC390T is not set |
493 | # CONFIG_SCSI_DEBUG is not set | 515 | # CONFIG_SCSI_DEBUG is not set |
494 | # CONFIG_SCSI_SRP is not set | 516 | # CONFIG_SCSI_SRP is not set |
495 | 517 | # CONFIG_SCSI_DH is not set | |
496 | # | ||
497 | # Serial ATA (prod) and Parallel ATA (experimental) drivers | ||
498 | # | ||
499 | # CONFIG_ATA is not set | 518 | # CONFIG_ATA is not set |
500 | |||
501 | # | ||
502 | # Multi-device support (RAID and LVM) | ||
503 | # | ||
504 | # CONFIG_MD is not set | 519 | # CONFIG_MD is not set |
505 | |||
506 | # | ||
507 | # Fusion MPT device support | ||
508 | # | ||
509 | # CONFIG_FUSION is not set | 520 | # CONFIG_FUSION is not set |
510 | # CONFIG_FUSION_SPI is not set | ||
511 | # CONFIG_FUSION_FC is not set | ||
512 | # CONFIG_FUSION_SAS is not set | ||
513 | 521 | ||
514 | # | 522 | # |
515 | # IEEE 1394 (FireWire) support | 523 | # IEEE 1394 (FireWire) support |
516 | # | 524 | # |
517 | # CONFIG_IEEE1394 is not set | ||
518 | 525 | ||
519 | # | 526 | # |
520 | # I2O device support | 527 | # Enable only one of the two stacks, unless you know what you are doing |
521 | # | 528 | # |
529 | # CONFIG_FIREWIRE is not set | ||
530 | # CONFIG_IEEE1394 is not set | ||
522 | # CONFIG_I2O is not set | 531 | # CONFIG_I2O is not set |
523 | |||
524 | # | ||
525 | # Network device support | ||
526 | # | ||
527 | CONFIG_NETDEVICES=y | 532 | CONFIG_NETDEVICES=y |
528 | # CONFIG_DUMMY is not set | 533 | CONFIG_DUMMY=m |
529 | # CONFIG_BONDING is not set | 534 | CONFIG_BONDING=m |
535 | # CONFIG_MACVLAN is not set | ||
530 | # CONFIG_EQUALIZER is not set | 536 | # CONFIG_EQUALIZER is not set |
531 | # CONFIG_TUN is not set | 537 | # CONFIG_TUN is not set |
532 | 538 | # CONFIG_VETH is not set | |
533 | # | ||
534 | # ARCnet devices | ||
535 | # | ||
536 | # CONFIG_ARCNET is not set | 539 | # CONFIG_ARCNET is not set |
537 | 540 | # CONFIG_PHYLIB is not set | |
538 | # | ||
539 | # PHY device support | ||
540 | # | ||
541 | CONFIG_PHYLIB=y | ||
542 | |||
543 | # | ||
544 | # MII PHY device drivers | ||
545 | # | ||
546 | CONFIG_MARVELL_PHY=y | ||
547 | CONFIG_DAVICOM_PHY=y | ||
548 | CONFIG_QSEMI_PHY=y | ||
549 | CONFIG_LXT_PHY=y | ||
550 | CONFIG_CICADA_PHY=y | ||
551 | CONFIG_VITESSE_PHY=y | ||
552 | CONFIG_SMSC_PHY=y | ||
553 | # CONFIG_BROADCOM_PHY is not set | ||
554 | # CONFIG_FIXED_PHY is not set | ||
555 | |||
556 | # | ||
557 | # Ethernet (10 or 100Mbit) | ||
558 | # | ||
559 | CONFIG_NET_ETHERNET=y | 541 | CONFIG_NET_ETHERNET=y |
560 | # CONFIG_MII is not set | 542 | CONFIG_MII=y |
543 | # CONFIG_AX88796 is not set | ||
561 | CONFIG_SGI_O2MACE_ETH=y | 544 | CONFIG_SGI_O2MACE_ETH=y |
562 | # CONFIG_HAPPYMEAL is not set | 545 | # CONFIG_HAPPYMEAL is not set |
563 | # CONFIG_SUNGEM is not set | 546 | # CONFIG_SUNGEM is not set |
564 | # CONFIG_CASSINI is not set | 547 | # CONFIG_CASSINI is not set |
565 | # CONFIG_NET_VENDOR_3COM is not set | 548 | # CONFIG_NET_VENDOR_3COM is not set |
549 | # CONFIG_SMC91X is not set | ||
566 | # CONFIG_DM9000 is not set | 550 | # CONFIG_DM9000 is not set |
567 | 551 | CONFIG_NET_TULIP=y | |
568 | # | 552 | CONFIG_DE2104X=m |
569 | # Tulip family network device support | 553 | CONFIG_TULIP=m |
570 | # | 554 | # CONFIG_TULIP_MWI is not set |
571 | # CONFIG_NET_TULIP is not set | 555 | CONFIG_TULIP_MMIO=y |
556 | # CONFIG_TULIP_NAPI is not set | ||
557 | # CONFIG_DE4X5 is not set | ||
558 | # CONFIG_WINBOND_840 is not set | ||
559 | # CONFIG_DM9102 is not set | ||
560 | # CONFIG_ULI526X is not set | ||
572 | # CONFIG_HP100 is not set | 561 | # CONFIG_HP100 is not set |
562 | # CONFIG_IBM_NEW_EMAC_ZMII is not set | ||
563 | # CONFIG_IBM_NEW_EMAC_RGMII is not set | ||
564 | # CONFIG_IBM_NEW_EMAC_TAH is not set | ||
565 | # CONFIG_IBM_NEW_EMAC_EMAC4 is not set | ||
566 | # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set | ||
567 | # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set | ||
568 | # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set | ||
573 | # CONFIG_NET_PCI is not set | 569 | # CONFIG_NET_PCI is not set |
574 | 570 | # CONFIG_B44 is not set | |
575 | # | 571 | # CONFIG_ATL2 is not set |
576 | # Ethernet (1000 Mbit) | 572 | # CONFIG_NETDEV_1000 is not set |
577 | # | 573 | # CONFIG_NETDEV_10000 is not set |
578 | # CONFIG_ACENIC is not set | ||
579 | # CONFIG_DL2K is not set | ||
580 | # CONFIG_E1000 is not set | ||
581 | # CONFIG_NS83820 is not set | ||
582 | # CONFIG_HAMACHI is not set | ||
583 | # CONFIG_YELLOWFIN is not set | ||
584 | # CONFIG_R8169 is not set | ||
585 | # CONFIG_SIS190 is not set | ||
586 | # CONFIG_SKGE is not set | ||
587 | # CONFIG_SKY2 is not set | ||
588 | # CONFIG_SK98LIN is not set | ||
589 | # CONFIG_TIGON3 is not set | ||
590 | # CONFIG_BNX2 is not set | ||
591 | CONFIG_QLA3XXX=y | ||
592 | # CONFIG_ATL1 is not set | ||
593 | |||
594 | # | ||
595 | # Ethernet (10000 Mbit) | ||
596 | # | ||
597 | # CONFIG_CHELSIO_T1 is not set | ||
598 | CONFIG_CHELSIO_T3=y | ||
599 | # CONFIG_IXGB is not set | ||
600 | # CONFIG_S2IO is not set | ||
601 | # CONFIG_MYRI10GE is not set | ||
602 | CONFIG_NETXEN_NIC=y | ||
603 | |||
604 | # | ||
605 | # Token Ring devices | ||
606 | # | ||
607 | # CONFIG_TR is not set | 574 | # CONFIG_TR is not set |
608 | 575 | ||
609 | # | 576 | # |
610 | # Wireless LAN (non-hamradio) | 577 | # Wireless LAN |
611 | # | ||
612 | # CONFIG_NET_RADIO is not set | ||
613 | |||
614 | # | ||
615 | # Wan interfaces | ||
616 | # | 578 | # |
579 | # CONFIG_WLAN_PRE80211 is not set | ||
580 | # CONFIG_WLAN_80211 is not set | ||
581 | # CONFIG_IWLWIFI_LEDS is not set | ||
617 | # CONFIG_WAN is not set | 582 | # CONFIG_WAN is not set |
618 | # CONFIG_FDDI is not set | 583 | # CONFIG_FDDI is not set |
619 | # CONFIG_HIPPI is not set | 584 | # CONFIG_HIPPI is not set |
620 | # CONFIG_PPP is not set | 585 | # CONFIG_PPP is not set |
621 | # CONFIG_SLIP is not set | 586 | # CONFIG_SLIP is not set |
622 | # CONFIG_NET_FC is not set | 587 | # CONFIG_NET_FC is not set |
623 | # CONFIG_SHAPER is not set | ||
624 | # CONFIG_NETCONSOLE is not set | 588 | # CONFIG_NETCONSOLE is not set |
625 | # CONFIG_NETPOLL is not set | 589 | # CONFIG_NETPOLL is not set |
626 | # CONFIG_NET_POLL_CONTROLLER is not set | 590 | # CONFIG_NET_POLL_CONTROLLER is not set |
627 | |||
628 | # | ||
629 | # ISDN subsystem | ||
630 | # | ||
631 | # CONFIG_ISDN is not set | 591 | # CONFIG_ISDN is not set |
632 | |||
633 | # | ||
634 | # Telephony Support | ||
635 | # | ||
636 | # CONFIG_PHONE is not set | 592 | # CONFIG_PHONE is not set |
637 | 593 | ||
638 | # | 594 | # |
@@ -640,6 +596,7 @@ CONFIG_NETXEN_NIC=y | |||
640 | # | 596 | # |
641 | CONFIG_INPUT=y | 597 | CONFIG_INPUT=y |
642 | # CONFIG_INPUT_FF_MEMLESS is not set | 598 | # CONFIG_INPUT_FF_MEMLESS is not set |
599 | # CONFIG_INPUT_POLLDEV is not set | ||
643 | 600 | ||
644 | # | 601 | # |
645 | # Userland interfaces | 602 | # Userland interfaces |
@@ -649,16 +606,32 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y | |||
649 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 | 606 | CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 |
650 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 | 607 | CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 |
651 | # CONFIG_INPUT_JOYDEV is not set | 608 | # CONFIG_INPUT_JOYDEV is not set |
652 | # CONFIG_INPUT_TSDEV is not set | 609 | CONFIG_INPUT_EVDEV=m |
653 | # CONFIG_INPUT_EVDEV is not set | ||
654 | # CONFIG_INPUT_EVBUG is not set | 610 | # CONFIG_INPUT_EVBUG is not set |
655 | 611 | ||
656 | # | 612 | # |
657 | # Input Device Drivers | 613 | # Input Device Drivers |
658 | # | 614 | # |
659 | # CONFIG_INPUT_KEYBOARD is not set | 615 | CONFIG_INPUT_KEYBOARD=y |
660 | # CONFIG_INPUT_MOUSE is not set | 616 | CONFIG_KEYBOARD_ATKBD=y |
617 | # CONFIG_KEYBOARD_SUNKBD is not set | ||
618 | # CONFIG_KEYBOARD_LKKBD is not set | ||
619 | # CONFIG_KEYBOARD_XTKBD is not set | ||
620 | # CONFIG_KEYBOARD_NEWTON is not set | ||
621 | # CONFIG_KEYBOARD_STOWAWAY is not set | ||
622 | CONFIG_INPUT_MOUSE=y | ||
623 | CONFIG_MOUSE_PS2=y | ||
624 | CONFIG_MOUSE_PS2_ALPS=y | ||
625 | CONFIG_MOUSE_PS2_LOGIPS2PP=y | ||
626 | CONFIG_MOUSE_PS2_SYNAPTICS=y | ||
627 | CONFIG_MOUSE_PS2_LIFEBOOK=y | ||
628 | CONFIG_MOUSE_PS2_TRACKPOINT=y | ||
629 | # CONFIG_MOUSE_PS2_ELANTECH is not set | ||
630 | # CONFIG_MOUSE_PS2_TOUCHKIT is not set | ||
631 | # CONFIG_MOUSE_SERIAL is not set | ||
632 | # CONFIG_MOUSE_VSXXXAA is not set | ||
661 | # CONFIG_INPUT_JOYSTICK is not set | 633 | # CONFIG_INPUT_JOYSTICK is not set |
634 | # CONFIG_INPUT_TABLET is not set | ||
662 | # CONFIG_INPUT_TOUCHSCREEN is not set | 635 | # CONFIG_INPUT_TOUCHSCREEN is not set |
663 | # CONFIG_INPUT_MISC is not set | 636 | # CONFIG_INPUT_MISC is not set |
664 | 637 | ||
@@ -669,8 +642,8 @@ CONFIG_SERIO=y | |||
669 | # CONFIG_SERIO_I8042 is not set | 642 | # CONFIG_SERIO_I8042 is not set |
670 | CONFIG_SERIO_SERPORT=y | 643 | CONFIG_SERIO_SERPORT=y |
671 | # CONFIG_SERIO_PCIPS2 is not set | 644 | # CONFIG_SERIO_PCIPS2 is not set |
672 | # CONFIG_SERIO_MACEPS2 is not set | 645 | CONFIG_SERIO_MACEPS2=y |
673 | # CONFIG_SERIO_LIBPS2 is not set | 646 | CONFIG_SERIO_LIBPS2=y |
674 | CONFIG_SERIO_RAW=y | 647 | CONFIG_SERIO_RAW=y |
675 | # CONFIG_GAMEPORT is not set | 648 | # CONFIG_GAMEPORT is not set |
676 | 649 | ||
@@ -678,10 +651,13 @@ CONFIG_SERIO_RAW=y | |||
678 | # Character devices | 651 | # Character devices |
679 | # | 652 | # |
680 | CONFIG_VT=y | 653 | CONFIG_VT=y |
654 | # CONFIG_CONSOLE_TRANSLATIONS is not set | ||
681 | CONFIG_VT_CONSOLE=y | 655 | CONFIG_VT_CONSOLE=y |
682 | CONFIG_HW_CONSOLE=y | 656 | CONFIG_HW_CONSOLE=y |
683 | CONFIG_VT_HW_CONSOLE_BINDING=y | 657 | # CONFIG_VT_HW_CONSOLE_BINDING is not set |
658 | CONFIG_DEVKMEM=y | ||
684 | # CONFIG_SERIAL_NONSTANDARD is not set | 659 | # CONFIG_SERIAL_NONSTANDARD is not set |
660 | # CONFIG_NOZOMI is not set | ||
685 | 661 | ||
686 | # | 662 | # |
687 | # Serial drivers | 663 | # Serial drivers |
@@ -702,192 +678,304 @@ CONFIG_SERIAL_CORE_CONSOLE=y | |||
702 | CONFIG_UNIX98_PTYS=y | 678 | CONFIG_UNIX98_PTYS=y |
703 | CONFIG_LEGACY_PTYS=y | 679 | CONFIG_LEGACY_PTYS=y |
704 | CONFIG_LEGACY_PTY_COUNT=256 | 680 | CONFIG_LEGACY_PTY_COUNT=256 |
705 | |||
706 | # | ||
707 | # IPMI | ||
708 | # | ||
709 | # CONFIG_IPMI_HANDLER is not set | 681 | # CONFIG_IPMI_HANDLER is not set |
710 | 682 | CONFIG_HW_RANDOM=y | |
711 | # | ||
712 | # Watchdog Cards | ||
713 | # | ||
714 | # CONFIG_WATCHDOG is not set | ||
715 | # CONFIG_HW_RANDOM is not set | ||
716 | # CONFIG_RTC is not set | ||
717 | # CONFIG_GEN_RTC is not set | ||
718 | # CONFIG_DTLK is not set | ||
719 | # CONFIG_R3964 is not set | 683 | # CONFIG_R3964 is not set |
720 | # CONFIG_APPLICOM is not set | 684 | # CONFIG_APPLICOM is not set |
721 | # CONFIG_DRM is not set | ||
722 | # CONFIG_RAW_DRIVER is not set | 685 | # CONFIG_RAW_DRIVER is not set |
723 | |||
724 | # | ||
725 | # TPM devices | ||
726 | # | ||
727 | # CONFIG_TCG_TPM is not set | 686 | # CONFIG_TCG_TPM is not set |
687 | CONFIG_DEVPORT=y | ||
688 | # CONFIG_I2C is not set | ||
689 | # CONFIG_SPI is not set | ||
690 | # CONFIG_W1 is not set | ||
691 | # CONFIG_POWER_SUPPLY is not set | ||
692 | CONFIG_HWMON=y | ||
693 | # CONFIG_HWMON_VID is not set | ||
694 | # CONFIG_SENSORS_I5K_AMB is not set | ||
695 | # CONFIG_SENSORS_F71805F is not set | ||
696 | # CONFIG_SENSORS_F71882FG is not set | ||
697 | # CONFIG_SENSORS_IT87 is not set | ||
698 | # CONFIG_SENSORS_PC87360 is not set | ||
699 | # CONFIG_SENSORS_PC87427 is not set | ||
700 | # CONFIG_SENSORS_SIS5595 is not set | ||
701 | # CONFIG_SENSORS_SMSC47M1 is not set | ||
702 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
703 | # CONFIG_SENSORS_VIA686A is not set | ||
704 | # CONFIG_SENSORS_VT1211 is not set | ||
705 | # CONFIG_SENSORS_VT8231 is not set | ||
706 | # CONFIG_SENSORS_W83627HF is not set | ||
707 | # CONFIG_SENSORS_W83627EHF is not set | ||
708 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
709 | # CONFIG_THERMAL is not set | ||
710 | # CONFIG_THERMAL_HWMON is not set | ||
711 | CONFIG_WATCHDOG=y | ||
712 | # CONFIG_WATCHDOG_NOWAYOUT is not set | ||
728 | 713 | ||
729 | # | 714 | # |
730 | # I2C support | 715 | # Watchdog Device Drivers |
731 | # | 716 | # |
732 | # CONFIG_I2C is not set | 717 | # CONFIG_SOFT_WATCHDOG is not set |
718 | # CONFIG_ALIM7101_WDT is not set | ||
733 | 719 | ||
734 | # | 720 | # |
735 | # SPI support | 721 | # PCI-based Watchdog Cards |
736 | # | 722 | # |
737 | # CONFIG_SPI is not set | 723 | # CONFIG_PCIPCWATCHDOG is not set |
738 | # CONFIG_SPI_MASTER is not set | 724 | # CONFIG_WDTPCI is not set |
725 | CONFIG_SSB_POSSIBLE=y | ||
739 | 726 | ||
740 | # | 727 | # |
741 | # Dallas's 1-wire bus | 728 | # Sonics Silicon Backplane |
742 | # | 729 | # |
743 | # CONFIG_W1 is not set | 730 | # CONFIG_SSB is not set |
744 | 731 | ||
745 | # | 732 | # |
746 | # Hardware Monitoring support | 733 | # Multifunction device drivers |
747 | # | 734 | # |
748 | # CONFIG_HWMON is not set | 735 | # CONFIG_MFD_CORE is not set |
749 | # CONFIG_HWMON_VID is not set | 736 | # CONFIG_MFD_SM501 is not set |
737 | # CONFIG_HTC_PASIC3 is not set | ||
738 | # CONFIG_MFD_TMIO is not set | ||
739 | # CONFIG_REGULATOR is not set | ||
750 | 740 | ||
751 | # | 741 | # |
752 | # Multimedia devices | 742 | # Multimedia devices |
753 | # | 743 | # |
754 | # CONFIG_VIDEO_DEV is not set | ||
755 | 744 | ||
756 | # | 745 | # |
757 | # Digital Video Broadcasting Devices | 746 | # Multimedia core support |
758 | # | 747 | # |
759 | # CONFIG_DVB is not set | 748 | CONFIG_VIDEO_DEV=m |
749 | CONFIG_VIDEO_V4L2_COMMON=m | ||
750 | CONFIG_VIDEO_ALLOW_V4L1=y | ||
751 | CONFIG_VIDEO_V4L1_COMPAT=y | ||
752 | # CONFIG_DVB_CORE is not set | ||
753 | CONFIG_VIDEO_MEDIA=m | ||
760 | 754 | ||
761 | # | 755 | # |
762 | # Graphics support | 756 | # Multimedia drivers |
763 | # | 757 | # |
764 | # CONFIG_FIRMWARE_EDID is not set | 758 | # CONFIG_MEDIA_ATTACH is not set |
765 | # CONFIG_FB is not set | 759 | CONFIG_VIDEO_V4L2=m |
760 | CONFIG_VIDEO_V4L1=m | ||
761 | CONFIG_VIDEOBUF_GEN=m | ||
762 | CONFIG_VIDEOBUF_VMALLOC=m | ||
763 | CONFIG_VIDEO_CAPTURE_DRIVERS=y | ||
764 | # CONFIG_VIDEO_ADV_DEBUG is not set | ||
765 | # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set | ||
766 | CONFIG_VIDEO_HELPER_CHIPS_AUTO=y | ||
767 | CONFIG_VIDEO_VIVI=m | ||
768 | # CONFIG_VIDEO_CPIA is not set | ||
769 | # CONFIG_VIDEO_STRADIS is not set | ||
770 | # CONFIG_SOC_CAMERA is not set | ||
771 | CONFIG_RADIO_ADAPTERS=y | ||
772 | # CONFIG_RADIO_GEMTEK_PCI is not set | ||
773 | # CONFIG_RADIO_MAXIRADIO is not set | ||
774 | # CONFIG_RADIO_MAESTRO is not set | ||
775 | CONFIG_DAB=y | ||
766 | 776 | ||
767 | # | 777 | # |
768 | # Console display driver support | 778 | # Graphics support |
769 | # | 779 | # |
770 | # CONFIG_VGA_CONSOLE is not set | 780 | # CONFIG_DRM is not set |
771 | CONFIG_DUMMY_CONSOLE=y | 781 | # CONFIG_VGASTATE is not set |
782 | CONFIG_VIDEO_OUTPUT_CONTROL=y | ||
783 | CONFIG_FB=y | ||
784 | CONFIG_FIRMWARE_EDID=y | ||
785 | # CONFIG_FB_DDC is not set | ||
786 | # CONFIG_FB_BOOT_VESA_SUPPORT is not set | ||
787 | CONFIG_FB_CFB_FILLRECT=y | ||
788 | CONFIG_FB_CFB_COPYAREA=y | ||
789 | CONFIG_FB_CFB_IMAGEBLIT=y | ||
790 | # CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set | ||
791 | # CONFIG_FB_SYS_FILLRECT is not set | ||
792 | # CONFIG_FB_SYS_COPYAREA is not set | ||
793 | # CONFIG_FB_SYS_IMAGEBLIT is not set | ||
794 | # CONFIG_FB_FOREIGN_ENDIAN is not set | ||
795 | # CONFIG_FB_SYS_FOPS is not set | ||
796 | # CONFIG_FB_SVGALIB is not set | ||
797 | # CONFIG_FB_MACMODES is not set | ||
798 | # CONFIG_FB_BACKLIGHT is not set | ||
799 | # CONFIG_FB_MODE_HELPERS is not set | ||
800 | # CONFIG_FB_TILEBLITTING is not set | ||
801 | |||
802 | # | ||
803 | # Frame buffer hardware drivers | ||
804 | # | ||
805 | # CONFIG_FB_CIRRUS is not set | ||
806 | # CONFIG_FB_PM2 is not set | ||
807 | # CONFIG_FB_CYBER2000 is not set | ||
808 | # CONFIG_FB_ASILIANT is not set | ||
809 | # CONFIG_FB_IMSTT is not set | ||
810 | # CONFIG_FB_UVESA is not set | ||
811 | CONFIG_FB_GBE=y | ||
812 | CONFIG_FB_GBE_MEM=4 | ||
813 | # CONFIG_FB_S1D13XXX is not set | ||
814 | # CONFIG_FB_NVIDIA is not set | ||
815 | # CONFIG_FB_RIVA is not set | ||
816 | # CONFIG_FB_MATROX is not set | ||
817 | # CONFIG_FB_RADEON is not set | ||
818 | # CONFIG_FB_ATY128 is not set | ||
819 | # CONFIG_FB_ATY is not set | ||
820 | # CONFIG_FB_S3 is not set | ||
821 | # CONFIG_FB_SAVAGE is not set | ||
822 | # CONFIG_FB_SIS is not set | ||
823 | # CONFIG_FB_VIA is not set | ||
824 | # CONFIG_FB_NEOMAGIC is not set | ||
825 | # CONFIG_FB_KYRO is not set | ||
826 | # CONFIG_FB_3DFX is not set | ||
827 | # CONFIG_FB_VOODOO1 is not set | ||
828 | # CONFIG_FB_VT8623 is not set | ||
829 | # CONFIG_FB_TRIDENT is not set | ||
830 | # CONFIG_FB_ARK is not set | ||
831 | # CONFIG_FB_PM3 is not set | ||
832 | # CONFIG_FB_CARMINE is not set | ||
833 | # CONFIG_FB_VIRTUAL is not set | ||
834 | # CONFIG_FB_METRONOME is not set | ||
835 | # CONFIG_FB_MB862XX is not set | ||
772 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set | 836 | # CONFIG_BACKLIGHT_LCD_SUPPORT is not set |
773 | 837 | ||
774 | # | 838 | # |
775 | # Sound | 839 | # Display device support |
776 | # | 840 | # |
777 | # CONFIG_SOUND is not set | 841 | # CONFIG_DISPLAY_SUPPORT is not set |
778 | 842 | ||
779 | # | 843 | # |
780 | # HID Devices | 844 | # Console display driver support |
781 | # | 845 | # |
846 | # CONFIG_VGA_CONSOLE is not set | ||
847 | CONFIG_DUMMY_CONSOLE=y | ||
848 | CONFIG_FRAMEBUFFER_CONSOLE=y | ||
849 | # CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set | ||
850 | # CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set | ||
851 | CONFIG_FONTS=y | ||
852 | CONFIG_FONT_8x8=y | ||
853 | CONFIG_FONT_8x16=y | ||
854 | # CONFIG_FONT_6x11 is not set | ||
855 | # CONFIG_FONT_7x14 is not set | ||
856 | # CONFIG_FONT_PEARL_8x8 is not set | ||
857 | # CONFIG_FONT_ACORN_8x8 is not set | ||
858 | # CONFIG_FONT_MINI_4x6 is not set | ||
859 | # CONFIG_FONT_SUN8x16 is not set | ||
860 | # CONFIG_FONT_SUN12x22 is not set | ||
861 | # CONFIG_FONT_10x18 is not set | ||
862 | CONFIG_LOGO=y | ||
863 | # CONFIG_LOGO_LINUX_MONO is not set | ||
864 | # CONFIG_LOGO_LINUX_VGA16 is not set | ||
865 | # CONFIG_LOGO_LINUX_CLUT224 is not set | ||
866 | CONFIG_LOGO_SGI_CLUT224=y | ||
867 | # CONFIG_SOUND is not set | ||
868 | CONFIG_HID_SUPPORT=y | ||
782 | CONFIG_HID=y | 869 | CONFIG_HID=y |
783 | # CONFIG_HID_DEBUG is not set | 870 | # CONFIG_HID_DEBUG is not set |
871 | # CONFIG_HIDRAW is not set | ||
872 | # CONFIG_HID_PID is not set | ||
784 | 873 | ||
785 | # | 874 | # |
786 | # USB support | 875 | # Special HID drivers |
787 | # | ||
788 | CONFIG_USB_ARCH_HAS_HCD=y | ||
789 | CONFIG_USB_ARCH_HAS_OHCI=y | ||
790 | CONFIG_USB_ARCH_HAS_EHCI=y | ||
791 | # CONFIG_USB is not set | ||
792 | |||
793 | # | ||
794 | # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' | ||
795 | # | ||
796 | |||
797 | # | ||
798 | # USB Gadget Support | ||
799 | # | ||
800 | # CONFIG_USB_GADGET is not set | ||
801 | |||
802 | # | ||
803 | # MMC/SD Card support | ||
804 | # | 876 | # |
877 | CONFIG_HID_COMPAT=y | ||
878 | # CONFIG_USB_SUPPORT is not set | ||
879 | # CONFIG_UWB is not set | ||
805 | # CONFIG_MMC is not set | 880 | # CONFIG_MMC is not set |
806 | 881 | # CONFIG_MEMSTICK is not set | |
807 | # | ||
808 | # LED devices | ||
809 | # | ||
810 | # CONFIG_NEW_LEDS is not set | 882 | # CONFIG_NEW_LEDS is not set |
811 | 883 | # CONFIG_ACCESSIBILITY is not set | |
812 | # | ||
813 | # LED drivers | ||
814 | # | ||
815 | |||
816 | # | ||
817 | # LED Triggers | ||
818 | # | ||
819 | |||
820 | # | ||
821 | # InfiniBand support | ||
822 | # | ||
823 | # CONFIG_INFINIBAND is not set | 884 | # CONFIG_INFINIBAND is not set |
885 | CONFIG_RTC_LIB=y | ||
886 | CONFIG_RTC_CLASS=y | ||
887 | # CONFIG_RTC_HCTOSYS is not set | ||
888 | # CONFIG_RTC_DEBUG is not set | ||
824 | 889 | ||
825 | # | 890 | # |
826 | # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) | 891 | # RTC interfaces |
827 | # | 892 | # |
893 | # CONFIG_RTC_INTF_SYSFS is not set | ||
894 | # CONFIG_RTC_INTF_PROC is not set | ||
895 | CONFIG_RTC_INTF_DEV=y | ||
896 | # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set | ||
897 | # CONFIG_RTC_DRV_TEST is not set | ||
828 | 898 | ||
829 | # | 899 | # |
830 | # Real Time Clock | 900 | # SPI RTC drivers |
831 | # | 901 | # |
832 | # CONFIG_RTC_CLASS is not set | ||
833 | 902 | ||
834 | # | 903 | # |
835 | # DMA Engine support | 904 | # Platform RTC drivers |
836 | # | 905 | # |
837 | # CONFIG_DMA_ENGINE is not set | 906 | CONFIG_RTC_DRV_CMOS=y |
907 | # CONFIG_RTC_DRV_DS1286 is not set | ||
908 | # CONFIG_RTC_DRV_DS1511 is not set | ||
909 | # CONFIG_RTC_DRV_DS1553 is not set | ||
910 | # CONFIG_RTC_DRV_DS1742 is not set | ||
911 | # CONFIG_RTC_DRV_STK17TA8 is not set | ||
912 | # CONFIG_RTC_DRV_M48T86 is not set | ||
913 | # CONFIG_RTC_DRV_M48T35 is not set | ||
914 | # CONFIG_RTC_DRV_M48T59 is not set | ||
915 | # CONFIG_RTC_DRV_BQ4802 is not set | ||
916 | # CONFIG_RTC_DRV_V3020 is not set | ||
838 | 917 | ||
839 | # | 918 | # |
840 | # DMA Clients | 919 | # on-CPU RTC drivers |
841 | # | ||
842 | |||
843 | # | ||
844 | # DMA Devices | ||
845 | # | ||
846 | |||
847 | # | ||
848 | # Auxiliary Display support | ||
849 | # | ||
850 | |||
851 | # | ||
852 | # Virtualization | ||
853 | # | 920 | # |
921 | # CONFIG_DMADEVICES is not set | ||
922 | # CONFIG_UIO is not set | ||
923 | # CONFIG_STAGING is not set | ||
924 | CONFIG_STAGING_EXCLUDE_BUILD=y | ||
854 | 925 | ||
855 | # | 926 | # |
856 | # File systems | 927 | # File systems |
857 | # | 928 | # |
858 | CONFIG_EXT2_FS=y | 929 | CONFIG_EXT2_FS=y |
859 | # CONFIG_EXT2_FS_XATTR is not set | 930 | CONFIG_EXT2_FS_XATTR=y |
931 | CONFIG_EXT2_FS_POSIX_ACL=y | ||
932 | CONFIG_EXT2_FS_SECURITY=y | ||
860 | # CONFIG_EXT2_FS_XIP is not set | 933 | # CONFIG_EXT2_FS_XIP is not set |
861 | # CONFIG_EXT3_FS is not set | 934 | CONFIG_EXT3_FS=y |
862 | # CONFIG_EXT4DEV_FS is not set | 935 | CONFIG_EXT3_FS_XATTR=y |
936 | CONFIG_EXT3_FS_POSIX_ACL=y | ||
937 | CONFIG_EXT3_FS_SECURITY=y | ||
938 | # CONFIG_EXT4_FS is not set | ||
939 | CONFIG_JBD=y | ||
940 | CONFIG_FS_MBCACHE=y | ||
863 | # CONFIG_REISERFS_FS is not set | 941 | # CONFIG_REISERFS_FS is not set |
864 | # CONFIG_JFS_FS is not set | 942 | # CONFIG_JFS_FS is not set |
865 | CONFIG_FS_POSIX_ACL=y | 943 | CONFIG_FS_POSIX_ACL=y |
944 | CONFIG_FILE_LOCKING=y | ||
866 | # CONFIG_XFS_FS is not set | 945 | # CONFIG_XFS_FS is not set |
867 | # CONFIG_GFS2_FS is not set | 946 | # CONFIG_GFS2_FS is not set |
868 | # CONFIG_OCFS2_FS is not set | 947 | # CONFIG_OCFS2_FS is not set |
869 | # CONFIG_MINIX_FS is not set | 948 | CONFIG_DNOTIFY=y |
870 | # CONFIG_ROMFS_FS is not set | ||
871 | CONFIG_INOTIFY=y | 949 | CONFIG_INOTIFY=y |
872 | CONFIG_INOTIFY_USER=y | 950 | CONFIG_INOTIFY_USER=y |
873 | # CONFIG_QUOTA is not set | 951 | CONFIG_QUOTA=y |
874 | CONFIG_DNOTIFY=y | 952 | # CONFIG_QUOTA_NETLINK_INTERFACE is not set |
875 | # CONFIG_AUTOFS_FS is not set | 953 | CONFIG_PRINT_QUOTA_WARNING=y |
876 | # CONFIG_AUTOFS4_FS is not set | 954 | CONFIG_QFMT_V1=m |
877 | CONFIG_FUSE_FS=y | 955 | CONFIG_QFMT_V2=m |
956 | CONFIG_QUOTACTL=y | ||
957 | CONFIG_AUTOFS_FS=m | ||
958 | CONFIG_AUTOFS4_FS=m | ||
959 | CONFIG_FUSE_FS=m | ||
878 | CONFIG_GENERIC_ACL=y | 960 | CONFIG_GENERIC_ACL=y |
879 | 961 | ||
880 | # | 962 | # |
881 | # CD-ROM/DVD Filesystems | 963 | # CD-ROM/DVD Filesystems |
882 | # | 964 | # |
883 | # CONFIG_ISO9660_FS is not set | 965 | CONFIG_ISO9660_FS=m |
884 | # CONFIG_UDF_FS is not set | 966 | CONFIG_JOLIET=y |
967 | CONFIG_ZISOFS=y | ||
968 | CONFIG_UDF_FS=m | ||
969 | CONFIG_UDF_NLS=y | ||
885 | 970 | ||
886 | # | 971 | # |
887 | # DOS/FAT/NT Filesystems | 972 | # DOS/FAT/NT Filesystems |
888 | # | 973 | # |
889 | # CONFIG_MSDOS_FS is not set | 974 | CONFIG_FAT_FS=m |
890 | # CONFIG_VFAT_FS is not set | 975 | CONFIG_MSDOS_FS=m |
976 | CONFIG_VFAT_FS=m | ||
977 | CONFIG_FAT_DEFAULT_CODEPAGE=437 | ||
978 | CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | ||
891 | # CONFIG_NTFS_FS is not set | 979 | # CONFIG_NTFS_FS is not set |
892 | 980 | ||
893 | # | 981 | # |
@@ -896,11 +984,11 @@ CONFIG_GENERIC_ACL=y | |||
896 | CONFIG_PROC_FS=y | 984 | CONFIG_PROC_FS=y |
897 | CONFIG_PROC_KCORE=y | 985 | CONFIG_PROC_KCORE=y |
898 | CONFIG_PROC_SYSCTL=y | 986 | CONFIG_PROC_SYSCTL=y |
987 | CONFIG_PROC_PAGE_MONITOR=y | ||
899 | CONFIG_SYSFS=y | 988 | CONFIG_SYSFS=y |
900 | CONFIG_TMPFS=y | 989 | CONFIG_TMPFS=y |
901 | CONFIG_TMPFS_POSIX_ACL=y | 990 | CONFIG_TMPFS_POSIX_ACL=y |
902 | # CONFIG_HUGETLB_PAGE is not set | 991 | # CONFIG_HUGETLB_PAGE is not set |
903 | CONFIG_RAMFS=y | ||
904 | CONFIG_CONFIGFS_FS=y | 992 | CONFIG_CONFIGFS_FS=y |
905 | 993 | ||
906 | # | 994 | # |
@@ -916,33 +1004,42 @@ CONFIG_CONFIGFS_FS=y | |||
916 | # CONFIG_EFS_FS is not set | 1004 | # CONFIG_EFS_FS is not set |
917 | # CONFIG_CRAMFS is not set | 1005 | # CONFIG_CRAMFS is not set |
918 | # CONFIG_VXFS_FS is not set | 1006 | # CONFIG_VXFS_FS is not set |
1007 | # CONFIG_MINIX_FS is not set | ||
1008 | # CONFIG_OMFS_FS is not set | ||
919 | # CONFIG_HPFS_FS is not set | 1009 | # CONFIG_HPFS_FS is not set |
920 | # CONFIG_QNX4FS_FS is not set | 1010 | # CONFIG_QNX4FS_FS is not set |
1011 | # CONFIG_ROMFS_FS is not set | ||
921 | # CONFIG_SYSV_FS is not set | 1012 | # CONFIG_SYSV_FS is not set |
922 | # CONFIG_UFS_FS is not set | 1013 | # CONFIG_UFS_FS is not set |
923 | 1014 | CONFIG_NETWORK_FILESYSTEMS=y | |
924 | # | ||
925 | # Network File Systems | ||
926 | # | ||
927 | CONFIG_NFS_FS=y | 1015 | CONFIG_NFS_FS=y |
928 | CONFIG_NFS_V3=y | 1016 | CONFIG_NFS_V3=y |
929 | # CONFIG_NFS_V3_ACL is not set | 1017 | # CONFIG_NFS_V3_ACL is not set |
930 | # CONFIG_NFS_V4 is not set | 1018 | # CONFIG_NFS_V4 is not set |
931 | # CONFIG_NFS_DIRECTIO is not set | ||
932 | # CONFIG_NFSD is not set | ||
933 | CONFIG_ROOT_NFS=y | 1019 | CONFIG_ROOT_NFS=y |
1020 | CONFIG_NFSD=m | ||
1021 | CONFIG_NFSD_V3=y | ||
1022 | # CONFIG_NFSD_V3_ACL is not set | ||
1023 | # CONFIG_NFSD_V4 is not set | ||
934 | CONFIG_LOCKD=y | 1024 | CONFIG_LOCKD=y |
935 | CONFIG_LOCKD_V4=y | 1025 | CONFIG_LOCKD_V4=y |
1026 | CONFIG_EXPORTFS=m | ||
936 | CONFIG_NFS_COMMON=y | 1027 | CONFIG_NFS_COMMON=y |
937 | CONFIG_SUNRPC=y | 1028 | CONFIG_SUNRPC=y |
1029 | # CONFIG_SUNRPC_REGISTER_V4 is not set | ||
938 | # CONFIG_RPCSEC_GSS_KRB5 is not set | 1030 | # CONFIG_RPCSEC_GSS_KRB5 is not set |
939 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | 1031 | # CONFIG_RPCSEC_GSS_SPKM3 is not set |
940 | # CONFIG_SMB_FS is not set | 1032 | # CONFIG_SMB_FS is not set |
941 | # CONFIG_CIFS is not set | 1033 | CONFIG_CIFS=m |
1034 | # CONFIG_CIFS_STATS is not set | ||
1035 | # CONFIG_CIFS_WEAK_PW_HASH is not set | ||
1036 | # CONFIG_CIFS_UPCALL is not set | ||
1037 | # CONFIG_CIFS_XATTR is not set | ||
1038 | # CONFIG_CIFS_DEBUG2 is not set | ||
1039 | # CONFIG_CIFS_EXPERIMENTAL is not set | ||
942 | # CONFIG_NCP_FS is not set | 1040 | # CONFIG_NCP_FS is not set |
943 | # CONFIG_CODA_FS is not set | 1041 | # CONFIG_CODA_FS is not set |
944 | # CONFIG_AFS_FS is not set | 1042 | # CONFIG_AFS_FS is not set |
945 | # CONFIG_9P_FS is not set | ||
946 | 1043 | ||
947 | # | 1044 | # |
948 | # Partition Types | 1045 | # Partition Types |
@@ -953,45 +1050,83 @@ CONFIG_PARTITION_ADVANCED=y | |||
953 | # CONFIG_AMIGA_PARTITION is not set | 1050 | # CONFIG_AMIGA_PARTITION is not set |
954 | # CONFIG_ATARI_PARTITION is not set | 1051 | # CONFIG_ATARI_PARTITION is not set |
955 | # CONFIG_MAC_PARTITION is not set | 1052 | # CONFIG_MAC_PARTITION is not set |
956 | # CONFIG_MSDOS_PARTITION is not set | 1053 | CONFIG_MSDOS_PARTITION=y |
1054 | # CONFIG_BSD_DISKLABEL is not set | ||
1055 | # CONFIG_MINIX_SUBPARTITION is not set | ||
1056 | # CONFIG_SOLARIS_X86_PARTITION is not set | ||
1057 | # CONFIG_UNIXWARE_DISKLABEL is not set | ||
957 | # CONFIG_LDM_PARTITION is not set | 1058 | # CONFIG_LDM_PARTITION is not set |
958 | CONFIG_SGI_PARTITION=y | 1059 | CONFIG_SGI_PARTITION=y |
959 | # CONFIG_ULTRIX_PARTITION is not set | 1060 | # CONFIG_ULTRIX_PARTITION is not set |
960 | # CONFIG_SUN_PARTITION is not set | 1061 | # CONFIG_SUN_PARTITION is not set |
961 | # CONFIG_KARMA_PARTITION is not set | 1062 | # CONFIG_KARMA_PARTITION is not set |
962 | # CONFIG_EFI_PARTITION is not set | 1063 | # CONFIG_EFI_PARTITION is not set |
963 | 1064 | # CONFIG_SYSV68_PARTITION is not set | |
964 | # | 1065 | CONFIG_NLS=y |
965 | # Native Language Support | 1066 | CONFIG_NLS_DEFAULT="iso8859-1" |
966 | # | 1067 | CONFIG_NLS_CODEPAGE_437=m |
967 | # CONFIG_NLS is not set | 1068 | CONFIG_NLS_CODEPAGE_737=m |
968 | 1069 | CONFIG_NLS_CODEPAGE_775=m | |
969 | # | 1070 | CONFIG_NLS_CODEPAGE_850=m |
970 | # Distributed Lock Manager | 1071 | CONFIG_NLS_CODEPAGE_852=m |
971 | # | 1072 | CONFIG_NLS_CODEPAGE_855=m |
972 | CONFIG_DLM=y | 1073 | CONFIG_NLS_CODEPAGE_857=m |
973 | CONFIG_DLM_TCP=y | 1074 | CONFIG_NLS_CODEPAGE_860=m |
974 | # CONFIG_DLM_SCTP is not set | 1075 | CONFIG_NLS_CODEPAGE_861=m |
975 | # CONFIG_DLM_DEBUG is not set | 1076 | CONFIG_NLS_CODEPAGE_862=m |
976 | 1077 | CONFIG_NLS_CODEPAGE_863=m | |
977 | # | 1078 | CONFIG_NLS_CODEPAGE_864=m |
978 | # Profiling support | 1079 | CONFIG_NLS_CODEPAGE_865=m |
979 | # | 1080 | CONFIG_NLS_CODEPAGE_866=m |
980 | # CONFIG_PROFILING is not set | 1081 | CONFIG_NLS_CODEPAGE_869=m |
1082 | CONFIG_NLS_CODEPAGE_936=m | ||
1083 | CONFIG_NLS_CODEPAGE_950=m | ||
1084 | CONFIG_NLS_CODEPAGE_932=m | ||
1085 | CONFIG_NLS_CODEPAGE_949=m | ||
1086 | CONFIG_NLS_CODEPAGE_874=m | ||
1087 | CONFIG_NLS_ISO8859_8=m | ||
1088 | CONFIG_NLS_CODEPAGE_1250=m | ||
1089 | CONFIG_NLS_CODEPAGE_1251=m | ||
1090 | CONFIG_NLS_ASCII=m | ||
1091 | CONFIG_NLS_ISO8859_1=m | ||
1092 | CONFIG_NLS_ISO8859_2=m | ||
1093 | CONFIG_NLS_ISO8859_3=m | ||
1094 | CONFIG_NLS_ISO8859_4=m | ||
1095 | CONFIG_NLS_ISO8859_5=m | ||
1096 | CONFIG_NLS_ISO8859_6=m | ||
1097 | CONFIG_NLS_ISO8859_7=m | ||
1098 | CONFIG_NLS_ISO8859_9=m | ||
1099 | CONFIG_NLS_ISO8859_13=m | ||
1100 | CONFIG_NLS_ISO8859_14=m | ||
1101 | CONFIG_NLS_ISO8859_15=m | ||
1102 | CONFIG_NLS_KOI8_R=m | ||
1103 | CONFIG_NLS_KOI8_U=m | ||
1104 | CONFIG_NLS_UTF8=m | ||
1105 | # CONFIG_DLM is not set | ||
981 | 1106 | ||
982 | # | 1107 | # |
983 | # Kernel hacking | 1108 | # Kernel hacking |
984 | # | 1109 | # |
985 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y | 1110 | CONFIG_TRACE_IRQFLAGS_SUPPORT=y |
986 | # CONFIG_PRINTK_TIME is not set | 1111 | # CONFIG_PRINTK_TIME is not set |
1112 | CONFIG_ENABLE_WARN_DEPRECATED=y | ||
987 | CONFIG_ENABLE_MUST_CHECK=y | 1113 | CONFIG_ENABLE_MUST_CHECK=y |
988 | # CONFIG_MAGIC_SYSRQ is not set | 1114 | CONFIG_FRAME_WARN=2048 |
1115 | CONFIG_MAGIC_SYSRQ=y | ||
989 | # CONFIG_UNUSED_SYMBOLS is not set | 1116 | # CONFIG_UNUSED_SYMBOLS is not set |
990 | # CONFIG_DEBUG_FS is not set | 1117 | # CONFIG_DEBUG_FS is not set |
991 | # CONFIG_HEADERS_CHECK is not set | 1118 | # CONFIG_HEADERS_CHECK is not set |
992 | # CONFIG_DEBUG_KERNEL is not set | 1119 | # CONFIG_DEBUG_KERNEL is not set |
993 | CONFIG_LOG_BUF_SHIFT=14 | 1120 | # CONFIG_DEBUG_MEMORY_INIT is not set |
994 | CONFIG_CROSSCOMPILE=y | 1121 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set |
1122 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
1123 | |||
1124 | # | ||
1125 | # Tracers | ||
1126 | # | ||
1127 | # CONFIG_DYNAMIC_PRINTK_DEBUG is not set | ||
1128 | # CONFIG_SAMPLES is not set | ||
1129 | CONFIG_HAVE_ARCH_KGDB=y | ||
995 | CONFIG_CMDLINE="" | 1130 | CONFIG_CMDLINE="" |
996 | 1131 | ||
997 | # | 1132 | # |
@@ -1000,51 +1135,99 @@ CONFIG_CMDLINE="" | |||
1000 | CONFIG_KEYS=y | 1135 | CONFIG_KEYS=y |
1001 | CONFIG_KEYS_DEBUG_PROC_KEYS=y | 1136 | CONFIG_KEYS_DEBUG_PROC_KEYS=y |
1002 | # CONFIG_SECURITY is not set | 1137 | # CONFIG_SECURITY is not set |
1138 | # CONFIG_SECURITYFS is not set | ||
1139 | # CONFIG_SECURITY_FILE_CAPABILITIES is not set | ||
1140 | CONFIG_CRYPTO=y | ||
1003 | 1141 | ||
1004 | # | 1142 | # |
1005 | # Cryptographic options | 1143 | # Crypto core or helper |
1006 | # | 1144 | # |
1007 | CONFIG_CRYPTO=y | 1145 | # CONFIG_CRYPTO_FIPS is not set |
1008 | CONFIG_CRYPTO_ALGAPI=y | 1146 | CONFIG_CRYPTO_ALGAPI=y |
1147 | CONFIG_CRYPTO_AEAD=y | ||
1009 | CONFIG_CRYPTO_BLKCIPHER=y | 1148 | CONFIG_CRYPTO_BLKCIPHER=y |
1010 | CONFIG_CRYPTO_HASH=y | 1149 | CONFIG_CRYPTO_HASH=y |
1150 | CONFIG_CRYPTO_RNG=y | ||
1011 | CONFIG_CRYPTO_MANAGER=y | 1151 | CONFIG_CRYPTO_MANAGER=y |
1152 | CONFIG_CRYPTO_GF128MUL=y | ||
1153 | CONFIG_CRYPTO_NULL=y | ||
1154 | # CONFIG_CRYPTO_CRYPTD is not set | ||
1155 | CONFIG_CRYPTO_AUTHENC=m | ||
1156 | # CONFIG_CRYPTO_TEST is not set | ||
1157 | |||
1158 | # | ||
1159 | # Authenticated Encryption with Associated Data | ||
1160 | # | ||
1161 | # CONFIG_CRYPTO_CCM is not set | ||
1162 | # CONFIG_CRYPTO_GCM is not set | ||
1163 | # CONFIG_CRYPTO_SEQIV is not set | ||
1164 | |||
1165 | # | ||
1166 | # Block modes | ||
1167 | # | ||
1168 | CONFIG_CRYPTO_CBC=y | ||
1169 | # CONFIG_CRYPTO_CTR is not set | ||
1170 | # CONFIG_CRYPTO_CTS is not set | ||
1171 | CONFIG_CRYPTO_ECB=y | ||
1172 | CONFIG_CRYPTO_LRW=y | ||
1173 | CONFIG_CRYPTO_PCBC=y | ||
1174 | # CONFIG_CRYPTO_XTS is not set | ||
1175 | |||
1176 | # | ||
1177 | # Hash modes | ||
1178 | # | ||
1012 | CONFIG_CRYPTO_HMAC=y | 1179 | CONFIG_CRYPTO_HMAC=y |
1013 | CONFIG_CRYPTO_XCBC=y | 1180 | CONFIG_CRYPTO_XCBC=y |
1014 | CONFIG_CRYPTO_NULL=y | 1181 | |
1182 | # | ||
1183 | # Digest | ||
1184 | # | ||
1185 | CONFIG_CRYPTO_CRC32C=y | ||
1015 | CONFIG_CRYPTO_MD4=y | 1186 | CONFIG_CRYPTO_MD4=y |
1016 | CONFIG_CRYPTO_MD5=y | 1187 | CONFIG_CRYPTO_MD5=y |
1188 | CONFIG_CRYPTO_MICHAEL_MIC=y | ||
1189 | # CONFIG_CRYPTO_RMD128 is not set | ||
1190 | # CONFIG_CRYPTO_RMD160 is not set | ||
1191 | # CONFIG_CRYPTO_RMD256 is not set | ||
1192 | # CONFIG_CRYPTO_RMD320 is not set | ||
1017 | CONFIG_CRYPTO_SHA1=y | 1193 | CONFIG_CRYPTO_SHA1=y |
1018 | CONFIG_CRYPTO_SHA256=y | 1194 | CONFIG_CRYPTO_SHA256=y |
1019 | CONFIG_CRYPTO_SHA512=y | 1195 | CONFIG_CRYPTO_SHA512=y |
1020 | CONFIG_CRYPTO_WP512=y | ||
1021 | CONFIG_CRYPTO_TGR192=y | 1196 | CONFIG_CRYPTO_TGR192=y |
1022 | CONFIG_CRYPTO_GF128MUL=y | 1197 | CONFIG_CRYPTO_WP512=y |
1023 | CONFIG_CRYPTO_ECB=y | 1198 | |
1024 | CONFIG_CRYPTO_CBC=y | 1199 | # |
1025 | CONFIG_CRYPTO_PCBC=y | 1200 | # Ciphers |
1026 | CONFIG_CRYPTO_LRW=y | 1201 | # |
1027 | CONFIG_CRYPTO_DES=y | ||
1028 | CONFIG_CRYPTO_FCRYPT=y | ||
1029 | CONFIG_CRYPTO_BLOWFISH=y | ||
1030 | CONFIG_CRYPTO_TWOFISH=y | ||
1031 | CONFIG_CRYPTO_TWOFISH_COMMON=y | ||
1032 | CONFIG_CRYPTO_SERPENT=y | ||
1033 | CONFIG_CRYPTO_AES=y | 1202 | CONFIG_CRYPTO_AES=y |
1203 | CONFIG_CRYPTO_ANUBIS=y | ||
1204 | CONFIG_CRYPTO_ARC4=y | ||
1205 | CONFIG_CRYPTO_BLOWFISH=y | ||
1206 | CONFIG_CRYPTO_CAMELLIA=y | ||
1034 | CONFIG_CRYPTO_CAST5=y | 1207 | CONFIG_CRYPTO_CAST5=y |
1035 | CONFIG_CRYPTO_CAST6=y | 1208 | CONFIG_CRYPTO_CAST6=y |
1036 | CONFIG_CRYPTO_TEA=y | 1209 | CONFIG_CRYPTO_DES=y |
1037 | CONFIG_CRYPTO_ARC4=y | 1210 | CONFIG_CRYPTO_FCRYPT=y |
1038 | CONFIG_CRYPTO_KHAZAD=y | 1211 | CONFIG_CRYPTO_KHAZAD=y |
1039 | CONFIG_CRYPTO_ANUBIS=y | 1212 | # CONFIG_CRYPTO_SALSA20 is not set |
1213 | # CONFIG_CRYPTO_SEED is not set | ||
1214 | CONFIG_CRYPTO_SERPENT=y | ||
1215 | CONFIG_CRYPTO_TEA=y | ||
1216 | CONFIG_CRYPTO_TWOFISH=y | ||
1217 | CONFIG_CRYPTO_TWOFISH_COMMON=y | ||
1218 | |||
1219 | # | ||
1220 | # Compression | ||
1221 | # | ||
1040 | CONFIG_CRYPTO_DEFLATE=y | 1222 | CONFIG_CRYPTO_DEFLATE=y |
1041 | CONFIG_CRYPTO_MICHAEL_MIC=y | 1223 | # CONFIG_CRYPTO_LZO is not set |
1042 | CONFIG_CRYPTO_CRC32C=y | ||
1043 | CONFIG_CRYPTO_CAMELLIA=y | ||
1044 | 1224 | ||
1045 | # | 1225 | # |
1046 | # Hardware crypto devices | 1226 | # Random Number Generation |
1047 | # | 1227 | # |
1228 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
1229 | CONFIG_CRYPTO_HW=y | ||
1230 | # CONFIG_CRYPTO_DEV_HIFN_795X is not set | ||
1048 | 1231 | ||
1049 | # | 1232 | # |
1050 | # Library routines | 1233 | # Library routines |
@@ -1052,10 +1235,15 @@ CONFIG_CRYPTO_CAMELLIA=y | |||
1052 | CONFIG_BITREVERSE=y | 1235 | CONFIG_BITREVERSE=y |
1053 | # CONFIG_CRC_CCITT is not set | 1236 | # CONFIG_CRC_CCITT is not set |
1054 | CONFIG_CRC16=y | 1237 | CONFIG_CRC16=y |
1238 | CONFIG_CRC_T10DIF=y | ||
1239 | CONFIG_CRC_ITU_T=m | ||
1055 | CONFIG_CRC32=y | 1240 | CONFIG_CRC32=y |
1241 | # CONFIG_CRC7 is not set | ||
1056 | CONFIG_LIBCRC32C=y | 1242 | CONFIG_LIBCRC32C=y |
1243 | CONFIG_AUDIT_GENERIC=y | ||
1057 | CONFIG_ZLIB_INFLATE=y | 1244 | CONFIG_ZLIB_INFLATE=y |
1058 | CONFIG_ZLIB_DEFLATE=y | 1245 | CONFIG_ZLIB_DEFLATE=y |
1059 | CONFIG_PLIST=y | 1246 | CONFIG_PLIST=y |
1060 | CONFIG_HAS_IOMEM=y | 1247 | CONFIG_HAS_IOMEM=y |
1061 | CONFIG_HAS_IOPORT=y | 1248 | CONFIG_HAS_IOPORT=y |
1249 | CONFIG_HAS_DMA=y | ||
diff --git a/arch/mips/include/asm/asmmacro.h b/arch/mips/include/asm/asmmacro.h index 7a881755800f..6c8342ae74db 100644 --- a/arch/mips/include/asm/asmmacro.h +++ b/arch/mips/include/asm/asmmacro.h | |||
@@ -35,6 +35,16 @@ | |||
35 | mtc0 \reg, CP0_TCSTATUS | 35 | mtc0 \reg, CP0_TCSTATUS |
36 | _ehb | 36 | _ehb |
37 | .endm | 37 | .endm |
38 | #elif defined(CONFIG_CPU_MIPSR2) | ||
39 | .macro local_irq_enable reg=t0 | ||
40 | ei | ||
41 | irq_enable_hazard | ||
42 | .endm | ||
43 | |||
44 | .macro local_irq_disable reg=t0 | ||
45 | di | ||
46 | irq_disable_hazard | ||
47 | .endm | ||
38 | #else | 48 | #else |
39 | .macro local_irq_enable reg=t0 | 49 | .macro local_irq_enable reg=t0 |
40 | mfc0 \reg, CP0_STATUS | 50 | mfc0 \reg, CP0_STATUS |
diff --git a/arch/mips/include/asm/byteorder.h b/arch/mips/include/asm/byteorder.h index 2988d29a0867..33790b9e0cc0 100644 --- a/arch/mips/include/asm/byteorder.h +++ b/arch/mips/include/asm/byteorder.h | |||
@@ -50,9 +50,8 @@ static inline __attribute_const__ __u32 __arch_swab32(__u32 x) | |||
50 | static inline __attribute_const__ __u64 __arch_swab64(__u64 x) | 50 | static inline __attribute_const__ __u64 __arch_swab64(__u64 x) |
51 | { | 51 | { |
52 | __asm__( | 52 | __asm__( |
53 | " dsbh %0, %1 \n" | 53 | " dsbh %0, %1\n" |
54 | " dshd %0, %0 \n" | 54 | " dshd %0, %0" |
55 | " drotr %0, %0, 32 \n" | ||
56 | : "=r" (x) | 55 | : "=r" (x) |
57 | : "r" (x)); | 56 | : "r" (x)); |
58 | 57 | ||
diff --git a/arch/mips/include/asm/elf.h b/arch/mips/include/asm/elf.h index a8eac1697b3d..d58f128aa747 100644 --- a/arch/mips/include/asm/elf.h +++ b/arch/mips/include/asm/elf.h | |||
@@ -232,7 +232,7 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; | |||
232 | */ | 232 | */ |
233 | #ifdef __MIPSEB__ | 233 | #ifdef __MIPSEB__ |
234 | #define ELF_DATA ELFDATA2MSB | 234 | #define ELF_DATA ELFDATA2MSB |
235 | #elif __MIPSEL__ | 235 | #elif defined(__MIPSEL__) |
236 | #define ELF_DATA ELFDATA2LSB | 236 | #define ELF_DATA ELFDATA2LSB |
237 | #endif | 237 | #endif |
238 | #define ELF_ARCH EM_MIPS | 238 | #define ELF_ARCH EM_MIPS |
diff --git a/arch/mips/mm/dma-default.c b/arch/mips/mm/dma-default.c index 5b98d0e731c2..e6708b3ad343 100644 --- a/arch/mips/mm/dma-default.c +++ b/arch/mips/mm/dma-default.c | |||
@@ -111,6 +111,7 @@ EXPORT_SYMBOL(dma_alloc_coherent); | |||
111 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, | 111 | void dma_free_noncoherent(struct device *dev, size_t size, void *vaddr, |
112 | dma_addr_t dma_handle) | 112 | dma_addr_t dma_handle) |
113 | { | 113 | { |
114 | plat_unmap_dma_mem(dma_handle); | ||
114 | free_pages((unsigned long) vaddr, get_order(size)); | 115 | free_pages((unsigned long) vaddr, get_order(size)); |
115 | } | 116 | } |
116 | 117 | ||
@@ -121,6 +122,8 @@ void dma_free_coherent(struct device *dev, size_t size, void *vaddr, | |||
121 | { | 122 | { |
122 | unsigned long addr = (unsigned long) vaddr; | 123 | unsigned long addr = (unsigned long) vaddr; |
123 | 124 | ||
125 | plat_unmap_dma_mem(dma_handle); | ||
126 | |||
124 | if (!plat_device_is_coherent(dev)) | 127 | if (!plat_device_is_coherent(dev)) |
125 | addr = CAC_ADDR(addr); | 128 | addr = CAC_ADDR(addr); |
126 | 129 | ||
diff --git a/arch/parisc/include/asm/tlbflush.h b/arch/parisc/include/asm/tlbflush.h index b72ec66db699..1f6fd4fc05b9 100644 --- a/arch/parisc/include/asm/tlbflush.h +++ b/arch/parisc/include/asm/tlbflush.h | |||
@@ -44,9 +44,12 @@ static inline void flush_tlb_mm(struct mm_struct *mm) | |||
44 | { | 44 | { |
45 | BUG_ON(mm == &init_mm); /* Should never happen */ | 45 | BUG_ON(mm == &init_mm); /* Should never happen */ |
46 | 46 | ||
47 | #ifdef CONFIG_SMP | 47 | #if 1 || defined(CONFIG_SMP) |
48 | flush_tlb_all(); | 48 | flush_tlb_all(); |
49 | #else | 49 | #else |
50 | /* FIXME: currently broken, causing space id and protection ids | ||
51 | * to go out of sync, resulting in faults on userspace accesses. | ||
52 | */ | ||
50 | if (mm) { | 53 | if (mm) { |
51 | if (mm->context != 0) | 54 | if (mm->context != 0) |
52 | free_sid(mm->context); | 55 | free_sid(mm->context); |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 8fc6d72849ae..3d3daa674299 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -41,6 +41,7 @@ $(obj)/4xx.o: BOOTCFLAGS += -mcpu=405 | |||
41 | $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405 | 41 | $(obj)/ebony.o: BOOTCFLAGS += -mcpu=405 |
42 | $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405 | 42 | $(obj)/cuboot-taishan.o: BOOTCFLAGS += -mcpu=405 |
43 | $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405 | 43 | $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405 |
44 | $(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405 | ||
44 | $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405 | 45 | $(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405 |
45 | $(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405 | 46 | $(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405 |
46 | 47 | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index bdc8b0e860e5..5c33bc14bd9f 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -479,17 +479,20 @@ _GLOBAL(_tlbil_pid) | |||
479 | * (no broadcast) | 479 | * (no broadcast) |
480 | */ | 480 | */ |
481 | _GLOBAL(_tlbil_va) | 481 | _GLOBAL(_tlbil_va) |
482 | mfmsr r10 | ||
483 | wrteei 0 | ||
482 | slwi r4,r4,16 | 484 | slwi r4,r4,16 |
483 | mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ | 485 | mtspr SPRN_MAS6,r4 /* assume AS=0 for now */ |
484 | tlbsx 0,r3 | 486 | tlbsx 0,r3 |
485 | mfspr r4,SPRN_MAS1 /* check valid */ | 487 | mfspr r4,SPRN_MAS1 /* check valid */ |
486 | andis. r3,r4,MAS1_VALID@h | 488 | andis. r3,r4,MAS1_VALID@h |
487 | beqlr | 489 | beq 1f |
488 | rlwinm r4,r4,0,1,31 | 490 | rlwinm r4,r4,0,1,31 |
489 | mtspr SPRN_MAS1,r4 | 491 | mtspr SPRN_MAS1,r4 |
490 | tlbwe | 492 | tlbwe |
491 | msync | 493 | msync |
492 | isync | 494 | isync |
495 | 1: wrtee r10 | ||
493 | blr | 496 | blr |
494 | #endif /* CONFIG_FSL_BOOKE */ | 497 | #endif /* CONFIG_FSL_BOOKE */ |
495 | 498 | ||
diff --git a/arch/powerpc/lib/rheap.c b/arch/powerpc/lib/rheap.c index 29b2941cada0..45907c1dae66 100644 --- a/arch/powerpc/lib/rheap.c +++ b/arch/powerpc/lib/rheap.c | |||
@@ -556,6 +556,7 @@ unsigned long rh_alloc_fixed(rh_info_t * info, unsigned long start, int size, co | |||
556 | be = blk->start + blk->size; | 556 | be = blk->start + blk->size; |
557 | if (s >= bs && e <= be) | 557 | if (s >= bs && e <= be) |
558 | break; | 558 | break; |
559 | blk = NULL; | ||
559 | } | 560 | } |
560 | 561 | ||
561 | if (blk == NULL) | 562 | if (blk == NULL) |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index 7bbf4e4ed430..f0c3b88d50fa 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -507,6 +507,9 @@ unsigned long hugetlb_get_unmapped_area(struct file *file, unsigned long addr, | |||
507 | { | 507 | { |
508 | struct hstate *hstate = hstate_file(file); | 508 | struct hstate *hstate = hstate_file(file); |
509 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); | 509 | int mmu_psize = shift_to_mmu_psize(huge_page_shift(hstate)); |
510 | |||
511 | if (!mmu_huge_psizes[mmu_psize]) | ||
512 | return -EINVAL; | ||
510 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); | 513 | return slice_get_unmapped_area(addr, len, flags, mmu_psize, 1, 0); |
511 | } | 514 | } |
512 | 515 | ||
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index a8397bbad3d4..cf81049e1e51 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -901,10 +901,17 @@ static void mark_reserved_regions_for_nid(int nid) | |||
901 | if (end_pfn > node_ar.end_pfn) | 901 | if (end_pfn > node_ar.end_pfn) |
902 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) | 902 | reserve_size = (node_ar.end_pfn << PAGE_SHIFT) |
903 | - (start_pfn << PAGE_SHIFT); | 903 | - (start_pfn << PAGE_SHIFT); |
904 | dbg("reserve_bootmem %lx %lx nid=%d\n", physbase, | 904 | /* |
905 | reserve_size, node_ar.nid); | 905 | * Only worry about *this* node, others may not |
906 | reserve_bootmem_node(NODE_DATA(node_ar.nid), physbase, | 906 | * yet have valid NODE_DATA(). |
907 | reserve_size, BOOTMEM_DEFAULT); | 907 | */ |
908 | if (node_ar.nid == nid) { | ||
909 | dbg("reserve_bootmem %lx %lx nid=%d\n", | ||
910 | physbase, reserve_size, node_ar.nid); | ||
911 | reserve_bootmem_node(NODE_DATA(node_ar.nid), | ||
912 | physbase, reserve_size, | ||
913 | BOOTMEM_DEFAULT); | ||
914 | } | ||
908 | /* | 915 | /* |
909 | * if reserved region is contained in the active region | 916 | * if reserved region is contained in the active region |
910 | * then done. | 917 | * then done. |
@@ -929,7 +936,6 @@ static void mark_reserved_regions_for_nid(int nid) | |||
929 | void __init do_init_bootmem(void) | 936 | void __init do_init_bootmem(void) |
930 | { | 937 | { |
931 | int nid; | 938 | int nid; |
932 | unsigned int i; | ||
933 | 939 | ||
934 | min_low_pfn = 0; | 940 | min_low_pfn = 0; |
935 | max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; | 941 | max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT; |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 442cf36aa172..0ce45c2b42f8 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -413,6 +413,9 @@ static int axon_msi_probe(struct of_device *device, | |||
413 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | | 413 | MSIC_CTRL_IRQ_ENABLE | MSIC_CTRL_ENABLE | |
414 | MSIC_CTRL_FIFO_SIZE); | 414 | MSIC_CTRL_FIFO_SIZE); |
415 | 415 | ||
416 | msic->read_offset = dcr_read(msic->dcr_host, MSIC_WRITE_OFFSET_REG) | ||
417 | & MSIC_FIFO_SIZE_MASK; | ||
418 | |||
416 | device->dev.platform_data = msic; | 419 | device->dev.platform_data = msic; |
417 | 420 | ||
418 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; | 421 | ppc_md.setup_msi_irqs = axon_msi_setup_msi_irqs; |
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 80119b3398e7..5c9cbfc14c4d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -55,6 +55,8 @@ config GENERIC_HARDIRQS | |||
55 | 55 | ||
56 | config GENERIC_HARDIRQS_NO__DO_IRQ | 56 | config GENERIC_HARDIRQS_NO__DO_IRQ |
57 | def_bool y | 57 | def_bool y |
58 | depends on SUPERH32 && (!SH_DREAMCAST && !SH_SH4202_MICRODEV && \ | ||
59 | !SH_7751_SYSTEMH && !HD64461) | ||
58 | 60 | ||
59 | config GENERIC_IRQ_PROBE | 61 | config GENERIC_IRQ_PROBE |
60 | def_bool y | 62 | def_bool y |
diff --git a/arch/sparc/include/asm/ptrace_32.h b/arch/sparc/include/asm/ptrace_32.h index d409c4f21a5c..4cef450167dd 100644 --- a/arch/sparc/include/asm/ptrace_32.h +++ b/arch/sparc/include/asm/ptrace_32.h | |||
@@ -62,6 +62,8 @@ struct sparc_stackf { | |||
62 | 62 | ||
63 | #ifdef __KERNEL__ | 63 | #ifdef __KERNEL__ |
64 | 64 | ||
65 | #include <asm/system.h> | ||
66 | |||
65 | static inline bool pt_regs_is_syscall(struct pt_regs *regs) | 67 | static inline bool pt_regs_is_syscall(struct pt_regs *regs) |
66 | { | 68 | { |
67 | return (regs->psr & PSR_SYSCALL); | 69 | return (regs->psr & PSR_SYSCALL); |
@@ -72,6 +74,14 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) | |||
72 | return (regs->psr &= ~PSR_SYSCALL); | 74 | return (regs->psr &= ~PSR_SYSCALL); |
73 | } | 75 | } |
74 | 76 | ||
77 | #define arch_ptrace_stop_needed(exit_code, info) \ | ||
78 | ({ flush_user_windows(); \ | ||
79 | current_thread_info()->w_saved != 0; \ | ||
80 | }) | ||
81 | |||
82 | #define arch_ptrace_stop(exit_code, info) \ | ||
83 | synchronize_user_stack() | ||
84 | |||
75 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) | 85 | #define user_mode(regs) (!((regs)->psr & PSR_PS)) |
76 | #define instruction_pointer(regs) ((regs)->pc) | 86 | #define instruction_pointer(regs) ((regs)->pc) |
77 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) | 87 | #define user_stack_pointer(regs) ((regs)->u_regs[UREG_FP]) |
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h index 84e969f06afe..cd6fbfc20435 100644 --- a/arch/sparc/include/asm/ptrace_64.h +++ b/arch/sparc/include/asm/ptrace_64.h | |||
@@ -114,6 +114,7 @@ struct sparc_trapf { | |||
114 | #ifdef __KERNEL__ | 114 | #ifdef __KERNEL__ |
115 | 115 | ||
116 | #include <linux/threads.h> | 116 | #include <linux/threads.h> |
117 | #include <asm/system.h> | ||
117 | 118 | ||
118 | static inline int pt_regs_trap_type(struct pt_regs *regs) | 119 | static inline int pt_regs_trap_type(struct pt_regs *regs) |
119 | { | 120 | { |
@@ -130,6 +131,14 @@ static inline bool pt_regs_clear_syscall(struct pt_regs *regs) | |||
130 | return (regs->tstate &= ~TSTATE_SYSCALL); | 131 | return (regs->tstate &= ~TSTATE_SYSCALL); |
131 | } | 132 | } |
132 | 133 | ||
134 | #define arch_ptrace_stop_needed(exit_code, info) \ | ||
135 | ({ flush_user_windows(); \ | ||
136 | get_thread_wsaved() != 0; \ | ||
137 | }) | ||
138 | |||
139 | #define arch_ptrace_stop(exit_code, info) \ | ||
140 | synchronize_user_stack() | ||
141 | |||
133 | struct global_reg_snapshot { | 142 | struct global_reg_snapshot { |
134 | unsigned long tstate; | 143 | unsigned long tstate; |
135 | unsigned long tpc; | 144 | unsigned long tpc; |
diff --git a/arch/x86/Kconfig.cpu b/arch/x86/Kconfig.cpu index b815664fe370..8e99073b9e0f 100644 --- a/arch/x86/Kconfig.cpu +++ b/arch/x86/Kconfig.cpu | |||
@@ -520,6 +520,7 @@ config X86_PTRACE_BTS | |||
520 | bool "Branch Trace Store" | 520 | bool "Branch Trace Store" |
521 | default y | 521 | default y |
522 | depends on X86_DEBUGCTLMSR | 522 | depends on X86_DEBUGCTLMSR |
523 | depends on BROKEN | ||
523 | help | 524 | help |
524 | This adds a ptrace interface to the hardware's branch trace store. | 525 | This adds a ptrace interface to the hardware's branch trace store. |
525 | 526 | ||
diff --git a/arch/x86/include/asm/vmi.h b/arch/x86/include/asm/vmi.h index b7c0dea119fe..61e08c0a2907 100644 --- a/arch/x86/include/asm/vmi.h +++ b/arch/x86/include/asm/vmi.h | |||
@@ -223,9 +223,15 @@ struct pci_header { | |||
223 | } __attribute__((packed)); | 223 | } __attribute__((packed)); |
224 | 224 | ||
225 | /* Function prototypes for bootstrapping */ | 225 | /* Function prototypes for bootstrapping */ |
226 | #ifdef CONFIG_VMI | ||
226 | extern void vmi_init(void); | 227 | extern void vmi_init(void); |
228 | extern void vmi_activate(void); | ||
227 | extern void vmi_bringup(void); | 229 | extern void vmi_bringup(void); |
228 | extern void vmi_apply_boot_page_allocations(void); | 230 | #else |
231 | static inline void vmi_init(void) {} | ||
232 | static inline void vmi_activate(void) {} | ||
233 | static inline void vmi_bringup(void) {} | ||
234 | #endif | ||
229 | 235 | ||
230 | /* State needed to start an application processor in an SMP system. */ | 236 | /* State needed to start an application processor in an SMP system. */ |
231 | struct vmi_ap_state { | 237 | struct vmi_ap_state { |
diff --git a/arch/x86/kernel/amd_iommu.c b/arch/x86/kernel/amd_iommu.c index a7b6dec6fc3f..0a60d60ed036 100644 --- a/arch/x86/kernel/amd_iommu.c +++ b/arch/x86/kernel/amd_iommu.c | |||
@@ -235,8 +235,9 @@ static int iommu_completion_wait(struct amd_iommu *iommu) | |||
235 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; | 235 | status &= ~MMIO_STATUS_COM_WAIT_INT_MASK; |
236 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); | 236 | writel(status, iommu->mmio_base + MMIO_STATUS_OFFSET); |
237 | 237 | ||
238 | if (unlikely((i == EXIT_LOOP_COUNT) && printk_ratelimit())) | 238 | if (unlikely(i == EXIT_LOOP_COUNT)) |
239 | printk(KERN_WARNING "AMD IOMMU: Completion wait loop failed\n"); | 239 | panic("AMD IOMMU: Completion wait loop failed\n"); |
240 | |||
240 | out: | 241 | out: |
241 | spin_unlock_irqrestore(&iommu->lock, flags); | 242 | spin_unlock_irqrestore(&iommu->lock, flags); |
242 | 243 | ||
diff --git a/arch/x86/kernel/amd_iommu_init.c b/arch/x86/kernel/amd_iommu_init.c index 30ae2701b3df..c6cc22815d35 100644 --- a/arch/x86/kernel/amd_iommu_init.c +++ b/arch/x86/kernel/amd_iommu_init.c | |||
@@ -427,6 +427,10 @@ static u8 * __init alloc_command_buffer(struct amd_iommu *iommu) | |||
427 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, | 427 | memcpy_toio(iommu->mmio_base + MMIO_CMD_BUF_OFFSET, |
428 | &entry, sizeof(entry)); | 428 | &entry, sizeof(entry)); |
429 | 429 | ||
430 | /* set head and tail to zero manually */ | ||
431 | writel(0x00, iommu->mmio_base + MMIO_CMD_HEAD_OFFSET); | ||
432 | writel(0x00, iommu->mmio_base + MMIO_CMD_TAIL_OFFSET); | ||
433 | |||
430 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); | 434 | iommu_feature_enable(iommu, CONTROL_CMDBUF_EN); |
431 | 435 | ||
432 | return cmd_buf; | 436 | return cmd_buf; |
@@ -1074,7 +1078,8 @@ int __init amd_iommu_init(void) | |||
1074 | goto free; | 1078 | goto free; |
1075 | 1079 | ||
1076 | /* IOMMU rlookup table - find the IOMMU for a specific device */ | 1080 | /* IOMMU rlookup table - find the IOMMU for a specific device */ |
1077 | amd_iommu_rlookup_table = (void *)__get_free_pages(GFP_KERNEL, | 1081 | amd_iommu_rlookup_table = (void *)__get_free_pages( |
1082 | GFP_KERNEL | __GFP_ZERO, | ||
1078 | get_order(rlookup_table_size)); | 1083 | get_order(rlookup_table_size)); |
1079 | if (amd_iommu_rlookup_table == NULL) | 1084 | if (amd_iommu_rlookup_table == NULL) |
1080 | goto free; | 1085 | goto free; |
diff --git a/arch/x86/kernel/cpu/mcheck/mce_64.c b/arch/x86/kernel/cpu/mcheck/mce_64.c index 4b031a4ac856..1c838032fd37 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_64.c +++ b/arch/x86/kernel/cpu/mcheck/mce_64.c | |||
@@ -510,12 +510,9 @@ static void __cpuinit mce_cpu_features(struct cpuinfo_x86 *c) | |||
510 | */ | 510 | */ |
511 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) | 511 | void __cpuinit mcheck_init(struct cpuinfo_x86 *c) |
512 | { | 512 | { |
513 | static cpumask_t mce_cpus = CPU_MASK_NONE; | ||
514 | |||
515 | mce_cpu_quirks(c); | 513 | mce_cpu_quirks(c); |
516 | 514 | ||
517 | if (mce_dont_init || | 515 | if (mce_dont_init || |
518 | cpu_test_and_set(smp_processor_id(), mce_cpus) || | ||
519 | !mce_available(c)) | 516 | !mce_available(c)) |
520 | return; | 517 | return; |
521 | 518 | ||
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c index 82fb2809ce32..c4b5b24e0217 100644 --- a/arch/x86/kernel/microcode_core.c +++ b/arch/x86/kernel/microcode_core.c | |||
@@ -272,13 +272,18 @@ static struct attribute_group mc_attr_group = { | |||
272 | .name = "microcode", | 272 | .name = "microcode", |
273 | }; | 273 | }; |
274 | 274 | ||
275 | static void microcode_fini_cpu(int cpu) | 275 | static void __microcode_fini_cpu(int cpu) |
276 | { | 276 | { |
277 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; | 277 | struct ucode_cpu_info *uci = ucode_cpu_info + cpu; |
278 | 278 | ||
279 | mutex_lock(µcode_mutex); | ||
280 | microcode_ops->microcode_fini_cpu(cpu); | 279 | microcode_ops->microcode_fini_cpu(cpu); |
281 | uci->valid = 0; | 280 | uci->valid = 0; |
281 | } | ||
282 | |||
283 | static void microcode_fini_cpu(int cpu) | ||
284 | { | ||
285 | mutex_lock(µcode_mutex); | ||
286 | __microcode_fini_cpu(cpu); | ||
282 | mutex_unlock(µcode_mutex); | 287 | mutex_unlock(µcode_mutex); |
283 | } | 288 | } |
284 | 289 | ||
@@ -306,12 +311,16 @@ static int microcode_resume_cpu(int cpu) | |||
306 | * to this cpu (a bit of paranoia): | 311 | * to this cpu (a bit of paranoia): |
307 | */ | 312 | */ |
308 | if (microcode_ops->collect_cpu_info(cpu, &nsig)) { | 313 | if (microcode_ops->collect_cpu_info(cpu, &nsig)) { |
309 | microcode_fini_cpu(cpu); | 314 | __microcode_fini_cpu(cpu); |
315 | printk(KERN_ERR "failed to collect_cpu_info for resuming cpu #%d\n", | ||
316 | cpu); | ||
310 | return -1; | 317 | return -1; |
311 | } | 318 | } |
312 | 319 | ||
313 | if (memcmp(&nsig, &uci->cpu_sig, sizeof(nsig))) { | 320 | if ((nsig.sig != uci->cpu_sig.sig) || (nsig.pf != uci->cpu_sig.pf)) { |
314 | microcode_fini_cpu(cpu); | 321 | __microcode_fini_cpu(cpu); |
322 | printk(KERN_ERR "cached ucode doesn't match the resuming cpu #%d\n", | ||
323 | cpu); | ||
315 | /* Should we look for a new ucode here? */ | 324 | /* Should we look for a new ucode here? */ |
316 | return 1; | 325 | return 1; |
317 | } | 326 | } |
diff --git a/arch/x86/kernel/microcode_intel.c b/arch/x86/kernel/microcode_intel.c index 622dc4a21784..a8e62792d171 100644 --- a/arch/x86/kernel/microcode_intel.c +++ b/arch/x86/kernel/microcode_intel.c | |||
@@ -155,6 +155,7 @@ static DEFINE_SPINLOCK(microcode_update_lock); | |||
155 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | 155 | static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) |
156 | { | 156 | { |
157 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); | 157 | struct cpuinfo_x86 *c = &cpu_data(cpu_num); |
158 | unsigned long flags; | ||
158 | unsigned int val[2]; | 159 | unsigned int val[2]; |
159 | 160 | ||
160 | memset(csig, 0, sizeof(*csig)); | 161 | memset(csig, 0, sizeof(*csig)); |
@@ -174,11 +175,16 @@ static int collect_cpu_info(int cpu_num, struct cpu_signature *csig) | |||
174 | csig->pf = 1 << ((val[1] >> 18) & 7); | 175 | csig->pf = 1 << ((val[1] >> 18) & 7); |
175 | } | 176 | } |
176 | 177 | ||
178 | /* serialize access to the physical write to MSR 0x79 */ | ||
179 | spin_lock_irqsave(µcode_update_lock, flags); | ||
180 | |||
177 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); | 181 | wrmsr(MSR_IA32_UCODE_REV, 0, 0); |
178 | /* see notes above for revision 1.07. Apparent chip bug */ | 182 | /* see notes above for revision 1.07. Apparent chip bug */ |
179 | sync_core(); | 183 | sync_core(); |
180 | /* get the current revision from MSR 0x8B */ | 184 | /* get the current revision from MSR 0x8B */ |
181 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); | 185 | rdmsr(MSR_IA32_UCODE_REV, val[0], csig->rev); |
186 | spin_unlock_irqrestore(µcode_update_lock, flags); | ||
187 | |||
182 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", | 188 | pr_debug("microcode: collect_cpu_info : sig=0x%x, pf=0x%x, rev=0x%x\n", |
183 | csig->sig, csig->pf, csig->rev); | 189 | csig->sig, csig->pf, csig->rev); |
184 | 190 | ||
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c index ba7ad83e20a8..a35eaa379ff6 100644 --- a/arch/x86/kernel/pci-gart_64.c +++ b/arch/x86/kernel/pci-gart_64.c | |||
@@ -745,10 +745,8 @@ void __init gart_iommu_init(void) | |||
745 | unsigned long scratch; | 745 | unsigned long scratch; |
746 | long i; | 746 | long i; |
747 | 747 | ||
748 | if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) { | 748 | if (cache_k8_northbridges() < 0 || num_k8_northbridges == 0) |
749 | printk(KERN_INFO "PCI-GART: No AMD GART found.\n"); | ||
750 | return; | 749 | return; |
751 | } | ||
752 | 750 | ||
753 | #ifndef CONFIG_AGP_AMD64 | 751 | #ifndef CONFIG_AGP_AMD64 |
754 | no_agp = 1; | 752 | no_agp = 1; |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9d5674f7b6cc..bdec76e55594 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -794,6 +794,9 @@ void __init setup_arch(char **cmdline_p) | |||
794 | printk(KERN_INFO "Command line: %s\n", boot_command_line); | 794 | printk(KERN_INFO "Command line: %s\n", boot_command_line); |
795 | #endif | 795 | #endif |
796 | 796 | ||
797 | /* VMI may relocate the fixmap; do this before touching ioremap area */ | ||
798 | vmi_init(); | ||
799 | |||
797 | early_cpu_init(); | 800 | early_cpu_init(); |
798 | early_ioremap_init(); | 801 | early_ioremap_init(); |
799 | 802 | ||
@@ -880,13 +883,8 @@ void __init setup_arch(char **cmdline_p) | |||
880 | check_efer(); | 883 | check_efer(); |
881 | #endif | 884 | #endif |
882 | 885 | ||
883 | #if defined(CONFIG_VMI) && defined(CONFIG_X86_32) | 886 | /* Must be before kernel pagetables are setup */ |
884 | /* | 887 | vmi_activate(); |
885 | * Must be before kernel pagetables are setup | ||
886 | * or fixmap area is touched. | ||
887 | */ | ||
888 | vmi_init(); | ||
889 | #endif | ||
890 | 888 | ||
891 | /* after early param, so could get panic from serial */ | 889 | /* after early param, so could get panic from serial */ |
892 | reserve_early_setup_data(); | 890 | reserve_early_setup_data(); |
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7b1093397319..f71f96fc9e62 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c | |||
@@ -294,9 +294,7 @@ static void __cpuinit start_secondary(void *unused) | |||
294 | * fragile that we want to limit the things done here to the | 294 | * fragile that we want to limit the things done here to the |
295 | * most necessary things. | 295 | * most necessary things. |
296 | */ | 296 | */ |
297 | #ifdef CONFIG_VMI | ||
298 | vmi_bringup(); | 297 | vmi_bringup(); |
299 | #endif | ||
300 | cpu_init(); | 298 | cpu_init(); |
301 | preempt_disable(); | 299 | preempt_disable(); |
302 | smp_callin(); | 300 | smp_callin(); |
diff --git a/arch/x86/kernel/vmi_32.c b/arch/x86/kernel/vmi_32.c index 8b6c393ab9fd..22fd6577156a 100644 --- a/arch/x86/kernel/vmi_32.c +++ b/arch/x86/kernel/vmi_32.c | |||
@@ -960,8 +960,6 @@ static inline int __init activate_vmi(void) | |||
960 | 960 | ||
961 | void __init vmi_init(void) | 961 | void __init vmi_init(void) |
962 | { | 962 | { |
963 | unsigned long flags; | ||
964 | |||
965 | if (!vmi_rom) | 963 | if (!vmi_rom) |
966 | probe_vmi_rom(); | 964 | probe_vmi_rom(); |
967 | else | 965 | else |
@@ -973,13 +971,21 @@ void __init vmi_init(void) | |||
973 | 971 | ||
974 | reserve_top_address(-vmi_rom->virtual_top); | 972 | reserve_top_address(-vmi_rom->virtual_top); |
975 | 973 | ||
976 | local_irq_save(flags); | ||
977 | activate_vmi(); | ||
978 | |||
979 | #ifdef CONFIG_X86_IO_APIC | 974 | #ifdef CONFIG_X86_IO_APIC |
980 | /* This is virtual hardware; timer routing is wired correctly */ | 975 | /* This is virtual hardware; timer routing is wired correctly */ |
981 | no_timer_check = 1; | 976 | no_timer_check = 1; |
982 | #endif | 977 | #endif |
978 | } | ||
979 | |||
980 | void vmi_activate(void) | ||
981 | { | ||
982 | unsigned long flags; | ||
983 | |||
984 | if (!vmi_rom) | ||
985 | return; | ||
986 | |||
987 | local_irq_save(flags); | ||
988 | activate_vmi(); | ||
983 | local_irq_restore(flags & X86_EFLAGS_IF); | 989 | local_irq_restore(flags & X86_EFLAGS_IF); |
984 | } | 990 | } |
985 | 991 | ||
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c index c029d3eb9ef0..595b78672b36 100644 --- a/crypto/async_tx/async_xor.c +++ b/crypto/async_tx/async_xor.c | |||
@@ -53,10 +53,17 @@ do_async_xor(struct dma_chan *chan, struct page *dest, struct page **src_list, | |||
53 | int xor_src_cnt; | 53 | int xor_src_cnt; |
54 | dma_addr_t dma_dest; | 54 | dma_addr_t dma_dest; |
55 | 55 | ||
56 | dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_FROM_DEVICE); | 56 | /* map the dest bidrectional in case it is re-used as a source */ |
57 | for (i = 0; i < src_cnt; i++) | 57 | dma_dest = dma_map_page(dma->dev, dest, offset, len, DMA_BIDIRECTIONAL); |
58 | for (i = 0; i < src_cnt; i++) { | ||
59 | /* only map the dest once */ | ||
60 | if (unlikely(src_list[i] == dest)) { | ||
61 | dma_src[i] = dma_dest; | ||
62 | continue; | ||
63 | } | ||
58 | dma_src[i] = dma_map_page(dma->dev, src_list[i], offset, | 64 | dma_src[i] = dma_map_page(dma->dev, src_list[i], offset, |
59 | len, DMA_TO_DEVICE); | 65 | len, DMA_TO_DEVICE); |
66 | } | ||
60 | 67 | ||
61 | while (src_cnt) { | 68 | while (src_cnt) { |
62 | async_flags = flags; | 69 | async_flags = flags; |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 7edf6d913c13..765fd1c56cd6 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
@@ -688,14 +688,6 @@ void __init acpi_early_init(void) | |||
688 | if (acpi_disabled) | 688 | if (acpi_disabled) |
689 | return; | 689 | return; |
690 | 690 | ||
691 | /* | ||
692 | * ACPI CA initializes acpi_dbg_level to non-zero, which means | ||
693 | * we get debug output merely by turning on CONFIG_ACPI_DEBUG. | ||
694 | * Turn it off so we don't get output unless the user specifies | ||
695 | * acpi.debug_level. | ||
696 | */ | ||
697 | acpi_dbg_level = 0; | ||
698 | |||
699 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); | 691 | printk(KERN_INFO PREFIX "Core revision %08x\n", ACPI_CA_VERSION); |
700 | 692 | ||
701 | /* enable workarounds, unless strict ACPI spec. compliance */ | 693 | /* enable workarounds, unless strict ACPI spec. compliance */ |
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c index 25f531d892de..40e60fc2e596 100644 --- a/drivers/acpi/toshiba_acpi.c +++ b/drivers/acpi/toshiba_acpi.c | |||
@@ -824,32 +824,36 @@ static int __init toshiba_acpi_init(void) | |||
824 | toshiba_acpi_exit(); | 824 | toshiba_acpi_exit(); |
825 | return -ENOMEM; | 825 | return -ENOMEM; |
826 | } | 826 | } |
827 | } | ||
828 | 827 | ||
829 | /* Register input device for kill switch */ | 828 | /* Register input device for kill switch */ |
830 | toshiba_acpi.poll_dev = input_allocate_polled_device(); | 829 | toshiba_acpi.poll_dev = input_allocate_polled_device(); |
831 | if (!toshiba_acpi.poll_dev) { | 830 | if (!toshiba_acpi.poll_dev) { |
832 | printk(MY_ERR "unable to allocate kill-switch input device\n"); | 831 | printk(MY_ERR |
833 | toshiba_acpi_exit(); | 832 | "unable to allocate kill-switch input device\n"); |
834 | return -ENOMEM; | 833 | toshiba_acpi_exit(); |
835 | } | 834 | return -ENOMEM; |
836 | toshiba_acpi.poll_dev->private = &toshiba_acpi; | 835 | } |
837 | toshiba_acpi.poll_dev->poll = bt_poll_rfkill; | 836 | toshiba_acpi.poll_dev->private = &toshiba_acpi; |
838 | toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ | 837 | toshiba_acpi.poll_dev->poll = bt_poll_rfkill; |
839 | 838 | toshiba_acpi.poll_dev->poll_interval = 1000; /* msecs */ | |
840 | toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; | 839 | |
841 | toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; | 840 | toshiba_acpi.poll_dev->input->name = toshiba_acpi.rfk_name; |
842 | toshiba_acpi.poll_dev->input->id.vendor = 0x0930; /* Toshiba USB ID */ | 841 | toshiba_acpi.poll_dev->input->id.bustype = BUS_HOST; |
843 | set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); | 842 | /* Toshiba USB ID */ |
844 | set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); | 843 | toshiba_acpi.poll_dev->input->id.vendor = 0x0930; |
845 | input_report_switch(toshiba_acpi.poll_dev->input, SW_RFKILL_ALL, TRUE); | 844 | set_bit(EV_SW, toshiba_acpi.poll_dev->input->evbit); |
846 | input_sync(toshiba_acpi.poll_dev->input); | 845 | set_bit(SW_RFKILL_ALL, toshiba_acpi.poll_dev->input->swbit); |
847 | 846 | input_report_switch(toshiba_acpi.poll_dev->input, | |
848 | ret = input_register_polled_device(toshiba_acpi.poll_dev); | 847 | SW_RFKILL_ALL, TRUE); |
849 | if (ret) { | 848 | input_sync(toshiba_acpi.poll_dev->input); |
850 | printk(MY_ERR "unable to register kill-switch input device\n"); | 849 | |
851 | toshiba_acpi_exit(); | 850 | ret = input_register_polled_device(toshiba_acpi.poll_dev); |
852 | return ret; | 851 | if (ret) { |
852 | printk(MY_ERR | ||
853 | "unable to register kill-switch input device\n"); | ||
854 | toshiba_acpi_exit(); | ||
855 | return ret; | ||
856 | } | ||
853 | } | 857 | } |
854 | 858 | ||
855 | return 0; | 859 | return 0; |
diff --git a/drivers/acpi/utilities/utglobal.c b/drivers/acpi/utilities/utglobal.c index 670551b95e56..17ed5ac840f7 100644 --- a/drivers/acpi/utilities/utglobal.c +++ b/drivers/acpi/utilities/utglobal.c | |||
@@ -64,7 +64,7 @@ u32 acpi_dbg_level = ACPI_DEBUG_DEFAULT; | |||
64 | 64 | ||
65 | /* Debug switch - layer (component) mask */ | 65 | /* Debug switch - layer (component) mask */ |
66 | 66 | ||
67 | u32 acpi_dbg_layer = ACPI_COMPONENT_DEFAULT | ACPI_ALL_DRIVERS; | 67 | u32 acpi_dbg_layer = 0; |
68 | u32 acpi_gbl_nesting_level = 0; | 68 | u32 acpi_gbl_nesting_level = 0; |
69 | 69 | ||
70 | /* Debugger globals */ | 70 | /* Debugger globals */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5e2eb740df46..bc6695e3c848 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -4050,17 +4050,70 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { | |||
4050 | { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, | 4050 | { "ST3160023AS", "3.42", ATA_HORKAGE_NONCQ }, |
4051 | 4051 | ||
4052 | /* Seagate NCQ + FLUSH CACHE firmware bug */ | 4052 | /* Seagate NCQ + FLUSH CACHE firmware bug */ |
4053 | { "ST31500341AS", "9JU138", ATA_HORKAGE_NONCQ | | 4053 | { "ST31500341AS", "SD15", ATA_HORKAGE_NONCQ | |
4054 | ATA_HORKAGE_FIRMWARE_WARN }, | 4054 | ATA_HORKAGE_FIRMWARE_WARN }, |
4055 | { "ST31000333AS", "9FZ136", ATA_HORKAGE_NONCQ | | 4055 | { "ST31500341AS", "SD16", ATA_HORKAGE_NONCQ | |
4056 | ATA_HORKAGE_FIRMWARE_WARN }, | 4056 | ATA_HORKAGE_FIRMWARE_WARN }, |
4057 | { "ST3640623AS", "9FZ164", ATA_HORKAGE_NONCQ | | 4057 | { "ST31500341AS", "SD17", ATA_HORKAGE_NONCQ | |
4058 | ATA_HORKAGE_FIRMWARE_WARN }, | 4058 | ATA_HORKAGE_FIRMWARE_WARN }, |
4059 | { "ST3640323AS", "9FZ134", ATA_HORKAGE_NONCQ | | 4059 | { "ST31500341AS", "SD18", ATA_HORKAGE_NONCQ | |
4060 | ATA_HORKAGE_FIRMWARE_WARN }, | 4060 | ATA_HORKAGE_FIRMWARE_WARN }, |
4061 | { "ST3320813AS", "9FZ182", ATA_HORKAGE_NONCQ | | 4061 | { "ST31500341AS", "SD19", ATA_HORKAGE_NONCQ | |
4062 | ATA_HORKAGE_FIRMWARE_WARN }, | 4062 | ATA_HORKAGE_FIRMWARE_WARN }, |
4063 | { "ST3320613AS", "9FZ162", ATA_HORKAGE_NONCQ | | 4063 | |
4064 | { "ST31000333AS", "SD15", ATA_HORKAGE_NONCQ | | ||
4065 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4066 | { "ST31000333AS", "SD16", ATA_HORKAGE_NONCQ | | ||
4067 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4068 | { "ST31000333AS", "SD17", ATA_HORKAGE_NONCQ | | ||
4069 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4070 | { "ST31000333AS", "SD18", ATA_HORKAGE_NONCQ | | ||
4071 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4072 | { "ST31000333AS", "SD19", ATA_HORKAGE_NONCQ | | ||
4073 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4074 | |||
4075 | { "ST3640623AS", "SD15", ATA_HORKAGE_NONCQ | | ||
4076 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4077 | { "ST3640623AS", "SD16", ATA_HORKAGE_NONCQ | | ||
4078 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4079 | { "ST3640623AS", "SD17", ATA_HORKAGE_NONCQ | | ||
4080 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4081 | { "ST3640623AS", "SD18", ATA_HORKAGE_NONCQ | | ||
4082 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4083 | { "ST3640623AS", "SD19", ATA_HORKAGE_NONCQ | | ||
4084 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4085 | |||
4086 | { "ST3640323AS", "SD15", ATA_HORKAGE_NONCQ | | ||
4087 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4088 | { "ST3640323AS", "SD16", ATA_HORKAGE_NONCQ | | ||
4089 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4090 | { "ST3640323AS", "SD17", ATA_HORKAGE_NONCQ | | ||
4091 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4092 | { "ST3640323AS", "SD18", ATA_HORKAGE_NONCQ | | ||
4093 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4094 | { "ST3640323AS", "SD19", ATA_HORKAGE_NONCQ | | ||
4095 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4096 | |||
4097 | { "ST3320813AS", "SD15", ATA_HORKAGE_NONCQ | | ||
4098 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4099 | { "ST3320813AS", "SD16", ATA_HORKAGE_NONCQ | | ||
4100 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4101 | { "ST3320813AS", "SD17", ATA_HORKAGE_NONCQ | | ||
4102 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4103 | { "ST3320813AS", "SD18", ATA_HORKAGE_NONCQ | | ||
4104 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4105 | { "ST3320813AS", "SD19", ATA_HORKAGE_NONCQ | | ||
4106 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4107 | |||
4108 | { "ST3320613AS", "SD15", ATA_HORKAGE_NONCQ | | ||
4109 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4110 | { "ST3320613AS", "SD16", ATA_HORKAGE_NONCQ | | ||
4111 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4112 | { "ST3320613AS", "SD17", ATA_HORKAGE_NONCQ | | ||
4113 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4114 | { "ST3320613AS", "SD18", ATA_HORKAGE_NONCQ | | ||
4115 | ATA_HORKAGE_FIRMWARE_WARN }, | ||
4116 | { "ST3320613AS", "SD19", ATA_HORKAGE_NONCQ | | ||
4064 | ATA_HORKAGE_FIRMWARE_WARN }, | 4117 | ATA_HORKAGE_FIRMWARE_WARN }, |
4065 | 4118 | ||
4066 | /* Blacklist entries taken from Silicon Image 3124/3132 | 4119 | /* Blacklist entries taken from Silicon Image 3124/3132 |
diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index a098ba8eaab6..e0c4f05d7d57 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c | |||
@@ -183,7 +183,9 @@ static unsigned long hpt366_filter(struct ata_device *adev, unsigned long mask) | |||
183 | mask &= ~(0xF8 << ATA_SHIFT_UDMA); | 183 | mask &= ~(0xF8 << ATA_SHIFT_UDMA); |
184 | if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) | 184 | if (hpt_dma_blacklisted(adev, "UDMA4", bad_ata66_4)) |
185 | mask &= ~(0xF0 << ATA_SHIFT_UDMA); | 185 | mask &= ~(0xF0 << ATA_SHIFT_UDMA); |
186 | } | 186 | } else if (adev->class == ATA_DEV_ATAPI) |
187 | mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); | ||
188 | |||
187 | return ata_bmdma_mode_filter(adev, mask); | 189 | return ata_bmdma_mode_filter(adev, mask); |
188 | } | 190 | } |
189 | 191 | ||
@@ -211,11 +213,15 @@ static u32 hpt36x_find_mode(struct ata_port *ap, int speed) | |||
211 | 213 | ||
212 | static int hpt36x_cable_detect(struct ata_port *ap) | 214 | static int hpt36x_cable_detect(struct ata_port *ap) |
213 | { | 215 | { |
214 | u8 ata66; | ||
215 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); | 216 | struct pci_dev *pdev = to_pci_dev(ap->host->dev); |
217 | u8 ata66; | ||
216 | 218 | ||
219 | /* | ||
220 | * Each channel of pata_hpt366 occupies separate PCI function | ||
221 | * as the primary channel and bit1 indicates the cable type. | ||
222 | */ | ||
217 | pci_read_config_byte(pdev, 0x5A, &ata66); | 223 | pci_read_config_byte(pdev, 0x5A, &ata66); |
218 | if (ata66 & (1 << ap->port_no)) | 224 | if (ata66 & 2) |
219 | return ATA_CBL_PATA40; | 225 | return ATA_CBL_PATA40; |
220 | return ATA_CBL_PATA80; | 226 | return ATA_CBL_PATA80; |
221 | } | 227 | } |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 9364dc554257..9f7c543cc04b 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -1693,6 +1693,11 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
1693 | for (i = 0; i <= h->highest_lun; i++) { | 1693 | for (i = 0; i <= h->highest_lun; i++) { |
1694 | int j; | 1694 | int j; |
1695 | drv_found = 0; | 1695 | drv_found = 0; |
1696 | |||
1697 | /* skip holes in the array from already deleted drives */ | ||
1698 | if (h->drv[i].raid_level == -1) | ||
1699 | continue; | ||
1700 | |||
1696 | for (j = 0; j < num_luns; j++) { | 1701 | for (j = 0; j < num_luns; j++) { |
1697 | memcpy(&lunid, &ld_buff->LUN[j][0], 4); | 1702 | memcpy(&lunid, &ld_buff->LUN[j][0], 4); |
1698 | lunid = le32_to_cpu(lunid); | 1703 | lunid = le32_to_cpu(lunid); |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d16b02423d61..7d2e91cccb13 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
@@ -2081,10 +2081,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
2081 | if (!q) | 2081 | if (!q) |
2082 | return -ENXIO; | 2082 | return -ENXIO; |
2083 | 2083 | ||
2084 | rq = blk_get_request(q, READ, GFP_KERNEL); | ||
2085 | if (!rq) | ||
2086 | return -ENOMEM; | ||
2087 | |||
2088 | cdi->last_sense = 0; | 2084 | cdi->last_sense = 0; |
2089 | 2085 | ||
2090 | while (nframes) { | 2086 | while (nframes) { |
@@ -2096,9 +2092,17 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
2096 | 2092 | ||
2097 | len = nr * CD_FRAMESIZE_RAW; | 2093 | len = nr * CD_FRAMESIZE_RAW; |
2098 | 2094 | ||
2095 | rq = blk_get_request(q, READ, GFP_KERNEL); | ||
2096 | if (!rq) { | ||
2097 | ret = -ENOMEM; | ||
2098 | break; | ||
2099 | } | ||
2100 | |||
2099 | ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); | 2101 | ret = blk_rq_map_user(q, rq, NULL, ubuf, len, GFP_KERNEL); |
2100 | if (ret) | 2102 | if (ret) { |
2103 | blk_put_request(rq); | ||
2101 | break; | 2104 | break; |
2105 | } | ||
2102 | 2106 | ||
2103 | rq->cmd[0] = GPCMD_READ_CD; | 2107 | rq->cmd[0] = GPCMD_READ_CD; |
2104 | rq->cmd[1] = 1 << 2; | 2108 | rq->cmd[1] = 1 << 2; |
@@ -2124,6 +2128,7 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
2124 | 2128 | ||
2125 | if (blk_rq_unmap_user(bio)) | 2129 | if (blk_rq_unmap_user(bio)) |
2126 | ret = -EFAULT; | 2130 | ret = -EFAULT; |
2131 | blk_put_request(rq); | ||
2127 | 2132 | ||
2128 | if (ret) | 2133 | if (ret) |
2129 | break; | 2134 | break; |
@@ -2133,7 +2138,6 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
2133 | ubuf += len; | 2138 | ubuf += len; |
2134 | } | 2139 | } |
2135 | 2140 | ||
2136 | blk_put_request(rq); | ||
2137 | return ret; | 2141 | return ret; |
2138 | } | 2142 | } |
2139 | 2143 | ||
diff --git a/drivers/char/cp437.uni b/drivers/char/cp437.uni index 1f06889a96b9..bc6163484f62 100644 --- a/drivers/char/cp437.uni +++ b/drivers/char/cp437.uni | |||
@@ -27,7 +27,7 @@ | |||
27 | 0x0c U+2640 | 27 | 0x0c U+2640 |
28 | 0x0d U+266a | 28 | 0x0d U+266a |
29 | 0x0e U+266b | 29 | 0x0e U+266b |
30 | 0x0f U+263c | 30 | 0x0f U+263c U+00a4 |
31 | 0x10 U+25b6 U+25ba | 31 | 0x10 U+25b6 U+25ba |
32 | 0x11 U+25c0 U+25c4 | 32 | 0x11 U+25c0 U+25c4 |
33 | 0x12 U+2195 | 33 | 0x12 U+2195 |
@@ -55,7 +55,7 @@ | |||
55 | 0x24 U+0024 | 55 | 0x24 U+0024 |
56 | 0x25 U+0025 | 56 | 0x25 U+0025 |
57 | 0x26 U+0026 | 57 | 0x26 U+0026 |
58 | 0x27 U+0027 | 58 | 0x27 U+0027 U+00b4 |
59 | 0x28 U+0028 | 59 | 0x28 U+0028 |
60 | 0x29 U+0029 | 60 | 0x29 U+0029 |
61 | 0x2a U+002a | 61 | 0x2a U+002a |
@@ -84,7 +84,7 @@ | |||
84 | 0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3 | 84 | 0x41 U+0041 U+00c0 U+00c1 U+00c2 U+00c3 |
85 | 0x42 U+0042 | 85 | 0x42 U+0042 |
86 | 0x43 U+0043 U+00a9 | 86 | 0x43 U+0043 U+00a9 |
87 | 0x44 U+0044 | 87 | 0x44 U+0044 U+00d0 |
88 | 0x45 U+0045 U+00c8 U+00ca U+00cb | 88 | 0x45 U+0045 U+00c8 U+00ca U+00cb |
89 | 0x46 U+0046 | 89 | 0x46 U+0046 |
90 | 0x47 U+0047 | 90 | 0x47 U+0047 |
@@ -140,7 +140,7 @@ | |||
140 | 0x79 U+0079 U+00fd | 140 | 0x79 U+0079 U+00fd |
141 | 0x7a U+007a | 141 | 0x7a U+007a |
142 | 0x7b U+007b | 142 | 0x7b U+007b |
143 | 0x7c U+007c U+00a5 | 143 | 0x7c U+007c U+00a6 |
144 | 0x7d U+007d | 144 | 0x7d U+007d |
145 | 0x7e U+007e | 145 | 0x7e U+007e |
146 | # | 146 | # |
@@ -263,10 +263,10 @@ | |||
263 | 0xe8 U+03a6 U+00d8 | 263 | 0xe8 U+03a6 U+00d8 |
264 | 0xe9 U+0398 | 264 | 0xe9 U+0398 |
265 | 0xea U+03a9 U+2126 | 265 | 0xea U+03a9 U+2126 |
266 | 0xeb U+03b4 | 266 | 0xeb U+03b4 U+00f0 |
267 | 0xec U+221e | 267 | 0xec U+221e |
268 | 0xed U+03c6 U+00f8 | 268 | 0xed U+03c6 U+00f8 |
269 | 0xee U+03b5 | 269 | 0xee U+03b5 U+2208 |
270 | 0xef U+2229 | 270 | 0xef U+2229 |
271 | 0xf0 U+2261 | 271 | 0xf0 U+2261 |
272 | 0xf1 U+00b1 | 272 | 0xf1 U+00b1 |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index a5af6072e2b3..008176edbd64 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -2274,7 +2274,7 @@ rescan_last_byte: | |||
2274 | continue; /* nothing to display */ | 2274 | continue; /* nothing to display */ |
2275 | } | 2275 | } |
2276 | /* Glyph not found */ | 2276 | /* Glyph not found */ |
2277 | if ((!(vc->vc_utf && !vc->vc_disp_ctrl) || c < 128) && !(c & ~charmask)) { | 2277 | if ((!(vc->vc_utf && !vc->vc_disp_ctrl) && c < 128) && !(c & ~charmask)) { |
2278 | /* In legacy mode use the glyph we get by a 1:1 mapping. | 2278 | /* In legacy mode use the glyph we get by a 1:1 mapping. |
2279 | This would make absolutely no sense with Unicode in mind, | 2279 | This would make absolutely no sense with Unicode in mind, |
2280 | but do this for ASCII characters since a font may lack | 2280 | but do this for ASCII characters since a font may lack |
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.c b/drivers/char/xilinx_hwicap/buffer_icap.c index aa7f7962a9a0..05d897764f02 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.c +++ b/drivers/char/xilinx_hwicap/buffer_icap.c | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2008 Xilinx Inc. | 24 | * (c) Copyright 2003-2008 Xilinx Inc. |
28 | * All rights reserved. | 25 | * All rights reserved. |
29 | * | 26 | * |
diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index 8b0252bf06e2..d4f419ee87ab 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2008 Xilinx Inc. | 24 | * (c) Copyright 2003-2008 Xilinx Inc. |
28 | * All rights reserved. | 25 | * All rights reserved. |
29 | * | 26 | * |
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.c b/drivers/char/xilinx_hwicap/fifo_icap.c index 776b50528478..02225eb19cf6 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.c +++ b/drivers/char/xilinx_hwicap/fifo_icap.c | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2007-2008 Xilinx Inc. | 24 | * (c) Copyright 2007-2008 Xilinx Inc. |
28 | * All rights reserved. | 25 | * All rights reserved. |
29 | * | 26 | * |
diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index 62bda453c90b..4c9dd9a3b62a 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2007-2008 Xilinx Inc. | 24 | * (c) Copyright 2007-2008 Xilinx Inc. |
28 | * All rights reserved. | 25 | * All rights reserved. |
29 | * | 26 | * |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index d16131949097..f40ab699860f 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group | 24 | * (c) Copyright 2002 Xilinx Inc., Systems Engineering Group |
28 | * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group | 25 | * (c) Copyright 2004 Xilinx Inc., Systems Engineering Group |
29 | * (c) Copyright 2007-2008 Xilinx Inc. | 26 | * (c) Copyright 2007-2008 Xilinx Inc. |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 24d0d9b938fb..8cca11981c5f 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h | |||
@@ -21,9 +21,6 @@ | |||
21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | 21 | * INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
22 | * FOR A PARTICULAR PURPOSE. | 22 | * FOR A PARTICULAR PURPOSE. |
23 | * | 23 | * |
24 | * Xilinx products are not intended for use in life support appliances, | ||
25 | * devices, or systems. Use in such applications is expressly prohibited. | ||
26 | * | ||
27 | * (c) Copyright 2003-2007 Xilinx Inc. | 24 | * (c) Copyright 2003-2007 Xilinx Inc. |
28 | * All rights reserved. | 25 | * All rights reserved. |
29 | * | 26 | * |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 5317e08221ec..657996517374 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
@@ -388,7 +388,10 @@ int dma_async_device_register(struct dma_device *device) | |||
388 | 388 | ||
389 | init_completion(&device->done); | 389 | init_completion(&device->done); |
390 | kref_init(&device->refcount); | 390 | kref_init(&device->refcount); |
391 | |||
392 | mutex_lock(&dma_list_mutex); | ||
391 | device->dev_id = id++; | 393 | device->dev_id = id++; |
394 | mutex_unlock(&dma_list_mutex); | ||
392 | 395 | ||
393 | /* represent channels in sysfs. Probably want devs too */ | 396 | /* represent channels in sysfs. Probably want devs too */ |
394 | list_for_each_entry(chan, &device->channels, device_node) { | 397 | list_for_each_entry(chan, &device->channels, device_node) { |
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index ecd743f7cc61..6607fdd00b1c 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
@@ -1341,10 +1341,12 @@ static void ioat_dma_start_null_desc(struct ioat_dma_chan *ioat_chan) | |||
1341 | */ | 1341 | */ |
1342 | #define IOAT_TEST_SIZE 2000 | 1342 | #define IOAT_TEST_SIZE 2000 |
1343 | 1343 | ||
1344 | DECLARE_COMPLETION(test_completion); | ||
1344 | static void ioat_dma_test_callback(void *dma_async_param) | 1345 | static void ioat_dma_test_callback(void *dma_async_param) |
1345 | { | 1346 | { |
1346 | printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n", | 1347 | printk(KERN_ERR "ioatdma: ioat_dma_test_callback(%p)\n", |
1347 | dma_async_param); | 1348 | dma_async_param); |
1349 | complete(&test_completion); | ||
1348 | } | 1350 | } |
1349 | 1351 | ||
1350 | /** | 1352 | /** |
@@ -1410,7 +1412,8 @@ static int ioat_dma_self_test(struct ioatdma_device *device) | |||
1410 | goto free_resources; | 1412 | goto free_resources; |
1411 | } | 1413 | } |
1412 | device->common.device_issue_pending(dma_chan); | 1414 | device->common.device_issue_pending(dma_chan); |
1413 | msleep(1); | 1415 | |
1416 | wait_for_completion_timeout(&test_completion, msecs_to_jiffies(3000)); | ||
1414 | 1417 | ||
1415 | if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) | 1418 | if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) |
1416 | != DMA_SUCCESS) { | 1419 | != DMA_SUCCESS) { |
diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index c7a9306d951d..6be317262200 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c | |||
@@ -85,18 +85,28 @@ iop_adma_run_tx_complete_actions(struct iop_adma_desc_slot *desc, | |||
85 | enum dma_ctrl_flags flags = desc->async_tx.flags; | 85 | enum dma_ctrl_flags flags = desc->async_tx.flags; |
86 | u32 src_cnt; | 86 | u32 src_cnt; |
87 | dma_addr_t addr; | 87 | dma_addr_t addr; |
88 | dma_addr_t dest; | ||
88 | 89 | ||
90 | src_cnt = unmap->unmap_src_cnt; | ||
91 | dest = iop_desc_get_dest_addr(unmap, iop_chan); | ||
89 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | 92 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { |
90 | addr = iop_desc_get_dest_addr(unmap, iop_chan); | 93 | enum dma_data_direction dir; |
91 | dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); | 94 | |
95 | if (src_cnt > 1) /* is xor? */ | ||
96 | dir = DMA_BIDIRECTIONAL; | ||
97 | else | ||
98 | dir = DMA_FROM_DEVICE; | ||
99 | |||
100 | dma_unmap_page(dev, dest, len, dir); | ||
92 | } | 101 | } |
93 | 102 | ||
94 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | 103 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { |
95 | src_cnt = unmap->unmap_src_cnt; | ||
96 | while (src_cnt--) { | 104 | while (src_cnt--) { |
97 | addr = iop_desc_get_src_addr(unmap, | 105 | addr = iop_desc_get_src_addr(unmap, |
98 | iop_chan, | 106 | iop_chan, |
99 | src_cnt); | 107 | src_cnt); |
108 | if (addr == dest) | ||
109 | continue; | ||
100 | dma_unmap_page(dev, addr, len, | 110 | dma_unmap_page(dev, addr, len, |
101 | DMA_TO_DEVICE); | 111 | DMA_TO_DEVICE); |
102 | } | 112 | } |
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 0328da020a10..bcda17426411 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c | |||
@@ -311,17 +311,26 @@ mv_xor_run_tx_complete_actions(struct mv_xor_desc_slot *desc, | |||
311 | enum dma_ctrl_flags flags = desc->async_tx.flags; | 311 | enum dma_ctrl_flags flags = desc->async_tx.flags; |
312 | u32 src_cnt; | 312 | u32 src_cnt; |
313 | dma_addr_t addr; | 313 | dma_addr_t addr; |
314 | dma_addr_t dest; | ||
314 | 315 | ||
316 | src_cnt = unmap->unmap_src_cnt; | ||
317 | dest = mv_desc_get_dest_addr(unmap); | ||
315 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { | 318 | if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) { |
316 | addr = mv_desc_get_dest_addr(unmap); | 319 | enum dma_data_direction dir; |
317 | dma_unmap_page(dev, addr, len, DMA_FROM_DEVICE); | 320 | |
321 | if (src_cnt > 1) /* is xor ? */ | ||
322 | dir = DMA_BIDIRECTIONAL; | ||
323 | else | ||
324 | dir = DMA_FROM_DEVICE; | ||
325 | dma_unmap_page(dev, dest, len, dir); | ||
318 | } | 326 | } |
319 | 327 | ||
320 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { | 328 | if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) { |
321 | src_cnt = unmap->unmap_src_cnt; | ||
322 | while (src_cnt--) { | 329 | while (src_cnt--) { |
323 | addr = mv_desc_get_src_addr(unmap, | 330 | addr = mv_desc_get_src_addr(unmap, |
324 | src_cnt); | 331 | src_cnt); |
332 | if (addr == dest) | ||
333 | continue; | ||
325 | dma_unmap_page(dev, addr, len, | 334 | dma_unmap_page(dev, addr, len, |
326 | DMA_TO_DEVICE); | 335 | DMA_TO_DEVICE); |
327 | } | 336 | } |
diff --git a/drivers/edac/edac_device.c b/drivers/edac/edac_device.c index 5fcd3d89c75d..4041e9143283 100644 --- a/drivers/edac/edac_device.c +++ b/drivers/edac/edac_device.c | |||
@@ -394,6 +394,12 @@ static void edac_device_workq_function(struct work_struct *work_req) | |||
394 | 394 | ||
395 | mutex_lock(&device_ctls_mutex); | 395 | mutex_lock(&device_ctls_mutex); |
396 | 396 | ||
397 | /* If we are being removed, bail out immediately */ | ||
398 | if (edac_dev->op_state == OP_OFFLINE) { | ||
399 | mutex_unlock(&device_ctls_mutex); | ||
400 | return; | ||
401 | } | ||
402 | |||
397 | /* Only poll controllers that are running polled and have a check */ | 403 | /* Only poll controllers that are running polled and have a check */ |
398 | if ((edac_dev->op_state == OP_RUNNING_POLL) && | 404 | if ((edac_dev->op_state == OP_RUNNING_POLL) && |
399 | (edac_dev->edac_check != NULL)) { | 405 | (edac_dev->edac_check != NULL)) { |
@@ -585,14 +591,14 @@ struct edac_device_ctl_info *edac_device_del_device(struct device *dev) | |||
585 | /* mark this instance as OFFLINE */ | 591 | /* mark this instance as OFFLINE */ |
586 | edac_dev->op_state = OP_OFFLINE; | 592 | edac_dev->op_state = OP_OFFLINE; |
587 | 593 | ||
588 | /* clear workq processing on this instance */ | ||
589 | edac_device_workq_teardown(edac_dev); | ||
590 | |||
591 | /* deregister from global list */ | 594 | /* deregister from global list */ |
592 | del_edac_device_from_global_list(edac_dev); | 595 | del_edac_device_from_global_list(edac_dev); |
593 | 596 | ||
594 | mutex_unlock(&device_ctls_mutex); | 597 | mutex_unlock(&device_ctls_mutex); |
595 | 598 | ||
599 | /* clear workq processing on this instance */ | ||
600 | edac_device_workq_teardown(edac_dev); | ||
601 | |||
596 | /* Tear down the sysfs entries for this instance */ | 602 | /* Tear down the sysfs entries for this instance */ |
597 | edac_device_remove_sysfs(edac_dev); | 603 | edac_device_remove_sysfs(edac_dev); |
598 | 604 | ||
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 553dd4bc3075..afa8a12cd009 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -717,7 +717,7 @@ static int i915_getparam(struct drm_device *dev, void *data, | |||
717 | value = dev->pci_device; | 717 | value = dev->pci_device; |
718 | break; | 718 | break; |
719 | case I915_PARAM_HAS_GEM: | 719 | case I915_PARAM_HAS_GEM: |
720 | value = 1; | 720 | value = dev_priv->has_gem; |
721 | break; | 721 | break; |
722 | default: | 722 | default: |
723 | DRM_ERROR("Unknown parameter %d\n", param->param); | 723 | DRM_ERROR("Unknown parameter %d\n", param->param); |
@@ -830,6 +830,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) | |||
830 | 830 | ||
831 | dev_priv->regs = ioremap(base, size); | 831 | dev_priv->regs = ioremap(base, size); |
832 | 832 | ||
833 | #ifdef CONFIG_HIGHMEM64G | ||
834 | /* don't enable GEM on PAE - needs agp + set_memory_* interface fixes */ | ||
835 | dev_priv->has_gem = 0; | ||
836 | #else | ||
837 | /* enable GEM by default */ | ||
838 | dev_priv->has_gem = 1; | ||
839 | #endif | ||
840 | |||
833 | i915_gem_load(dev); | 841 | i915_gem_load(dev); |
834 | 842 | ||
835 | /* Init HWS */ | 843 | /* Init HWS */ |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index adc972cc6bfc..b3cc4731aa7c 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -106,6 +106,8 @@ struct intel_opregion { | |||
106 | typedef struct drm_i915_private { | 106 | typedef struct drm_i915_private { |
107 | struct drm_device *dev; | 107 | struct drm_device *dev; |
108 | 108 | ||
109 | int has_gem; | ||
110 | |||
109 | void __iomem *regs; | 111 | void __iomem *regs; |
110 | drm_local_map_t *sarea; | 112 | drm_local_map_t *sarea; |
111 | 113 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index ad672d854828..24fe8c10b4b2 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2309,7 +2309,14 @@ i915_gem_busy_ioctl(struct drm_device *dev, void *data, | |||
2309 | } | 2309 | } |
2310 | 2310 | ||
2311 | obj_priv = obj->driver_private; | 2311 | obj_priv = obj->driver_private; |
2312 | args->busy = obj_priv->active; | 2312 | /* Don't count being on the flushing list against the object being |
2313 | * done. Otherwise, a buffer left on the flushing list but not getting | ||
2314 | * flushed (because nobody's flushing that domain) won't ever return | ||
2315 | * unbusy and get reused by libdrm's bo cache. The other expected | ||
2316 | * consumer of this interface, OpenGL's occlusion queries, also specs | ||
2317 | * that the objects get unbusy "eventually" without any interference. | ||
2318 | */ | ||
2319 | args->busy = obj_priv->active && obj_priv->last_rendering_seqno != 0; | ||
2313 | 2320 | ||
2314 | drm_gem_object_unreference(obj); | 2321 | drm_gem_object_unreference(obj); |
2315 | mutex_unlock(&dev->struct_mutex); | 2322 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c index 99be11418ac2..8289e16419a8 100644 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ b/drivers/gpu/drm/radeon/radeon_irq.c | |||
@@ -44,7 +44,7 @@ void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) | |||
44 | else | 44 | else |
45 | dev_priv->irq_enable_reg &= ~mask; | 45 | dev_priv->irq_enable_reg &= ~mask; |
46 | 46 | ||
47 | if (!dev->irq_enabled) | 47 | if (dev->irq_enabled) |
48 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); | 48 | RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); |
49 | } | 49 | } |
50 | 50 | ||
@@ -57,7 +57,7 @@ static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state) | |||
57 | else | 57 | else |
58 | dev_priv->r500_disp_irq_reg &= ~mask; | 58 | dev_priv->r500_disp_irq_reg &= ~mask; |
59 | 59 | ||
60 | if (!dev->irq_enabled) | 60 | if (dev->irq_enabled) |
61 | RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); | 61 | RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); |
62 | } | 62 | } |
63 | 63 | ||
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c index 228f75723063..3fcf78e906db 100644 --- a/drivers/i2c/busses/i2c-cpm.c +++ b/drivers/i2c/busses/i2c-cpm.c | |||
@@ -365,6 +365,7 @@ static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) | |||
365 | pmsg = &msgs[tptr]; | 365 | pmsg = &msgs[tptr]; |
366 | if (pmsg->flags & I2C_M_RD) | 366 | if (pmsg->flags & I2C_M_RD) |
367 | ret = wait_event_interruptible_timeout(cpm->i2c_wait, | 367 | ret = wait_event_interruptible_timeout(cpm->i2c_wait, |
368 | (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) || | ||
368 | !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), | 369 | !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), |
369 | 1 * HZ); | 370 | 1 * HZ); |
370 | else | 371 | else |
diff --git a/drivers/i2c/busses/i2c-highlander.c b/drivers/i2c/busses/i2c-highlander.c index f4d22ae9d294..e5a8dae4a289 100644 --- a/drivers/i2c/busses/i2c-highlander.c +++ b/drivers/i2c/busses/i2c-highlander.c | |||
@@ -92,7 +92,7 @@ static void highlander_i2c_setup(struct highlander_i2c_dev *dev) | |||
92 | static void smbus_write_data(u8 *src, u16 *dst, int len) | 92 | static void smbus_write_data(u8 *src, u16 *dst, int len) |
93 | { | 93 | { |
94 | for (; len > 1; len -= 2) { | 94 | for (; len > 1; len -= 2) { |
95 | *dst++ = be16_to_cpup((u16 *)src); | 95 | *dst++ = be16_to_cpup((__be16 *)src); |
96 | src += 2; | 96 | src += 2; |
97 | } | 97 | } |
98 | 98 | ||
@@ -103,7 +103,7 @@ static void smbus_write_data(u8 *src, u16 *dst, int len) | |||
103 | static void smbus_read_data(u16 *src, u8 *dst, int len) | 103 | static void smbus_read_data(u16 *src, u8 *dst, int len) |
104 | { | 104 | { |
105 | for (; len > 1; len -= 2) { | 105 | for (; len > 1; len -= 2) { |
106 | *(u16 *)dst = cpu_to_be16p(src++); | 106 | *(__be16 *)dst = cpu_to_be16p(src++); |
107 | dst += 2; | 107 | dst += 2; |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/drivers/i2c/busses/i2c-pmcmsp.c b/drivers/i2c/busses/i2c-pmcmsp.c index dcf2045b5222..0bdb2d7f0570 100644 --- a/drivers/i2c/busses/i2c-pmcmsp.c +++ b/drivers/i2c/busses/i2c-pmcmsp.c | |||
@@ -486,7 +486,7 @@ static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd( | |||
486 | 486 | ||
487 | if (cmd->type == MSP_TWI_CMD_WRITE || | 487 | if (cmd->type == MSP_TWI_CMD_WRITE || |
488 | cmd->type == MSP_TWI_CMD_WRITE_READ) { | 488 | cmd->type == MSP_TWI_CMD_WRITE_READ) { |
489 | __be64 tmp = cpu_to_be64p((u64 *)cmd->write_data); | 489 | u64 tmp = be64_to_cpup((__be64 *)cmd->write_data); |
490 | tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8; | 490 | tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8; |
491 | dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp); | 491 | dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp); |
492 | pmcmsptwi_writel(tmp & 0x00000000ffffffffLL, | 492 | pmcmsptwi_writel(tmp & 0x00000000ffffffffLL, |
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 1fac4e233133..b7434d24904e 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c | |||
@@ -56,6 +56,7 @@ enum s3c24xx_i2c_state { | |||
56 | struct s3c24xx_i2c { | 56 | struct s3c24xx_i2c { |
57 | spinlock_t lock; | 57 | spinlock_t lock; |
58 | wait_queue_head_t wait; | 58 | wait_queue_head_t wait; |
59 | unsigned int suspended:1; | ||
59 | 60 | ||
60 | struct i2c_msg *msg; | 61 | struct i2c_msg *msg; |
61 | unsigned int msg_num; | 62 | unsigned int msg_num; |
@@ -507,7 +508,7 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, struct i2c_msg *msgs, int | |||
507 | unsigned long timeout; | 508 | unsigned long timeout; |
508 | int ret; | 509 | int ret; |
509 | 510 | ||
510 | if (!(readl(i2c->regs + S3C2410_IICCON) & S3C2410_IICCON_IRQEN)) | 511 | if (i2c->suspended) |
511 | return -EIO; | 512 | return -EIO; |
512 | 513 | ||
513 | ret = s3c24xx_i2c_set_master(i2c); | 514 | ret = s3c24xx_i2c_set_master(i2c); |
@@ -986,17 +987,26 @@ static int s3c24xx_i2c_remove(struct platform_device *pdev) | |||
986 | } | 987 | } |
987 | 988 | ||
988 | #ifdef CONFIG_PM | 989 | #ifdef CONFIG_PM |
990 | static int s3c24xx_i2c_suspend_late(struct platform_device *dev, | ||
991 | pm_message_t msg) | ||
992 | { | ||
993 | struct s3c24xx_i2c *i2c = platform_get_drvdata(dev); | ||
994 | i2c->suspended = 1; | ||
995 | return 0; | ||
996 | } | ||
997 | |||
989 | static int s3c24xx_i2c_resume(struct platform_device *dev) | 998 | static int s3c24xx_i2c_resume(struct platform_device *dev) |
990 | { | 999 | { |
991 | struct s3c24xx_i2c *i2c = platform_get_drvdata(dev); | 1000 | struct s3c24xx_i2c *i2c = platform_get_drvdata(dev); |
992 | 1001 | ||
993 | if (i2c != NULL) | 1002 | i2c->suspended = 0; |
994 | s3c24xx_i2c_init(i2c); | 1003 | s3c24xx_i2c_init(i2c); |
995 | 1004 | ||
996 | return 0; | 1005 | return 0; |
997 | } | 1006 | } |
998 | 1007 | ||
999 | #else | 1008 | #else |
1009 | #define s3c24xx_i2c_suspend_late NULL | ||
1000 | #define s3c24xx_i2c_resume NULL | 1010 | #define s3c24xx_i2c_resume NULL |
1001 | #endif | 1011 | #endif |
1002 | 1012 | ||
@@ -1005,6 +1015,7 @@ static int s3c24xx_i2c_resume(struct platform_device *dev) | |||
1005 | static struct platform_driver s3c2410_i2c_driver = { | 1015 | static struct platform_driver s3c2410_i2c_driver = { |
1006 | .probe = s3c24xx_i2c_probe, | 1016 | .probe = s3c24xx_i2c_probe, |
1007 | .remove = s3c24xx_i2c_remove, | 1017 | .remove = s3c24xx_i2c_remove, |
1018 | .suspend_late = s3c24xx_i2c_suspend_late, | ||
1008 | .resume = s3c24xx_i2c_resume, | 1019 | .resume = s3c24xx_i2c_resume, |
1009 | .driver = { | 1020 | .driver = { |
1010 | .owner = THIS_MODULE, | 1021 | .owner = THIS_MODULE, |
@@ -1015,6 +1026,7 @@ static struct platform_driver s3c2410_i2c_driver = { | |||
1015 | static struct platform_driver s3c2440_i2c_driver = { | 1026 | static struct platform_driver s3c2440_i2c_driver = { |
1016 | .probe = s3c24xx_i2c_probe, | 1027 | .probe = s3c24xx_i2c_probe, |
1017 | .remove = s3c24xx_i2c_remove, | 1028 | .remove = s3c24xx_i2c_remove, |
1029 | .suspend_late = s3c24xx_i2c_suspend_late, | ||
1018 | .resume = s3c24xx_i2c_resume, | 1030 | .resume = s3c24xx_i2c_resume, |
1019 | .driver = { | 1031 | .driver = { |
1020 | .owner = THIS_MODULE, | 1032 | .owner = THIS_MODULE, |
diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index 53f079cc00af..d8ede85fe17f 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c | |||
@@ -81,11 +81,12 @@ static u8 cs5530_udma_filter(ide_drive_t *drive) | |||
81 | { | 81 | { |
82 | ide_hwif_t *hwif = drive->hwif; | 82 | ide_hwif_t *hwif = drive->hwif; |
83 | ide_drive_t *mate = ide_get_pair_dev(drive); | 83 | ide_drive_t *mate = ide_get_pair_dev(drive); |
84 | u16 *mateid = mate->id; | 84 | u16 *mateid; |
85 | u8 mask = hwif->ultra_mask; | 85 | u8 mask = hwif->ultra_mask; |
86 | 86 | ||
87 | if (mate == NULL) | 87 | if (mate == NULL) |
88 | goto out; | 88 | goto out; |
89 | mateid = mate->id; | ||
89 | 90 | ||
90 | if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { | 91 | if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { |
91 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && | 92 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && |
diff --git a/drivers/ide/sc1200.c b/drivers/ide/sc1200.c index f1a8758e3a99..ec7f766ef5e4 100644 --- a/drivers/ide/sc1200.c +++ b/drivers/ide/sc1200.c | |||
@@ -104,11 +104,12 @@ static u8 sc1200_udma_filter(ide_drive_t *drive) | |||
104 | { | 104 | { |
105 | ide_hwif_t *hwif = drive->hwif; | 105 | ide_hwif_t *hwif = drive->hwif; |
106 | ide_drive_t *mate = ide_get_pair_dev(drive); | 106 | ide_drive_t *mate = ide_get_pair_dev(drive); |
107 | u16 *mateid = mate->id; | 107 | u16 *mateid; |
108 | u8 mask = hwif->ultra_mask; | 108 | u8 mask = hwif->ultra_mask; |
109 | 109 | ||
110 | if (mate == NULL) | 110 | if (mate == NULL) |
111 | goto out; | 111 | goto out; |
112 | mateid = mate->id; | ||
112 | 113 | ||
113 | if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { | 114 | if (ata_id_has_dma(mateid) && __ide_dma_bad_drive(mate) == 0) { |
114 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && | 115 | if ((mateid[ATA_ID_FIELD_VALID] & 4) && |
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index d333ae22459c..79ef5fd928ae 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c | |||
@@ -115,8 +115,14 @@ static int nodemgr_bus_read(struct csr1212_csr *csr, u64 addr, u16 length, | |||
115 | return error; | 115 | return error; |
116 | } | 116 | } |
117 | 117 | ||
118 | #define OUI_FREECOM_TECHNOLOGIES_GMBH 0x0001db | ||
119 | |||
118 | static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) | 120 | static int nodemgr_get_max_rom(quadlet_t *bus_info_data, void *__ci) |
119 | { | 121 | { |
122 | /* Freecom FireWire Hard Drive firmware bug */ | ||
123 | if (be32_to_cpu(bus_info_data[3]) >> 8 == OUI_FREECOM_TECHNOLOGIES_GMBH) | ||
124 | return 0; | ||
125 | |||
120 | return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3; | 126 | return (be32_to_cpu(bus_info_data[2]) >> 8) & 0x3; |
121 | } | 127 | } |
122 | 128 | ||
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index ac89a5deaca2..ab7c8e4a61f9 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
@@ -208,16 +208,19 @@ static void bitmap_checkfree(struct bitmap *bitmap, unsigned long page) | |||
208 | */ | 208 | */ |
209 | 209 | ||
210 | /* IO operations when bitmap is stored near all superblocks */ | 210 | /* IO operations when bitmap is stored near all superblocks */ |
211 | static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long index) | 211 | static struct page *read_sb_page(mddev_t *mddev, long offset, |
212 | struct page *page, | ||
213 | unsigned long index, int size) | ||
212 | { | 214 | { |
213 | /* choose a good rdev and read the page from there */ | 215 | /* choose a good rdev and read the page from there */ |
214 | 216 | ||
215 | mdk_rdev_t *rdev; | 217 | mdk_rdev_t *rdev; |
216 | struct list_head *tmp; | 218 | struct list_head *tmp; |
217 | struct page *page = alloc_page(GFP_KERNEL); | ||
218 | sector_t target; | 219 | sector_t target; |
219 | 220 | ||
220 | if (!page) | 221 | if (!page) |
222 | page = alloc_page(GFP_KERNEL); | ||
223 | if (!page) | ||
221 | return ERR_PTR(-ENOMEM); | 224 | return ERR_PTR(-ENOMEM); |
222 | 225 | ||
223 | rdev_for_each(rdev, tmp, mddev) { | 226 | rdev_for_each(rdev, tmp, mddev) { |
@@ -227,7 +230,9 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde | |||
227 | 230 | ||
228 | target = rdev->sb_start + offset + index * (PAGE_SIZE/512); | 231 | target = rdev->sb_start + offset + index * (PAGE_SIZE/512); |
229 | 232 | ||
230 | if (sync_page_io(rdev->bdev, target, PAGE_SIZE, page, READ)) { | 233 | if (sync_page_io(rdev->bdev, target, |
234 | roundup(size, bdev_hardsect_size(rdev->bdev)), | ||
235 | page, READ)) { | ||
231 | page->index = index; | 236 | page->index = index; |
232 | attach_page_buffers(page, NULL); /* so that free_buffer will | 237 | attach_page_buffers(page, NULL); /* so that free_buffer will |
233 | * quietly no-op */ | 238 | * quietly no-op */ |
@@ -544,7 +549,9 @@ static int bitmap_read_sb(struct bitmap *bitmap) | |||
544 | 549 | ||
545 | bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); | 550 | bitmap->sb_page = read_page(bitmap->file, 0, bitmap, bytes); |
546 | } else { | 551 | } else { |
547 | bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, 0); | 552 | bitmap->sb_page = read_sb_page(bitmap->mddev, bitmap->offset, |
553 | NULL, | ||
554 | 0, sizeof(bitmap_super_t)); | ||
548 | } | 555 | } |
549 | if (IS_ERR(bitmap->sb_page)) { | 556 | if (IS_ERR(bitmap->sb_page)) { |
550 | err = PTR_ERR(bitmap->sb_page); | 557 | err = PTR_ERR(bitmap->sb_page); |
@@ -957,11 +964,16 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) | |||
957 | */ | 964 | */ |
958 | page = bitmap->sb_page; | 965 | page = bitmap->sb_page; |
959 | offset = sizeof(bitmap_super_t); | 966 | offset = sizeof(bitmap_super_t); |
967 | read_sb_page(bitmap->mddev, bitmap->offset, | ||
968 | page, | ||
969 | index, count); | ||
960 | } else if (file) { | 970 | } else if (file) { |
961 | page = read_page(file, index, bitmap, count); | 971 | page = read_page(file, index, bitmap, count); |
962 | offset = 0; | 972 | offset = 0; |
963 | } else { | 973 | } else { |
964 | page = read_sb_page(bitmap->mddev, bitmap->offset, index); | 974 | page = read_sb_page(bitmap->mddev, bitmap->offset, |
975 | NULL, | ||
976 | index, count); | ||
965 | offset = 0; | 977 | offset = 0; |
966 | } | 978 | } |
967 | if (IS_ERR(page)) { /* read error */ | 979 | if (IS_ERR(page)) { /* read error */ |
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 73dc2ee9b014..b34301d56cd2 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig | |||
@@ -9,11 +9,11 @@ config DVB_B2C2_FLEXCOP | |||
9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE | 9 | select DVB_STV0297 if !DVB_FE_CUSTOMISE |
10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE | 10 | select DVB_BCM3510 if !DVB_FE_CUSTOMISE |
11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 11 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
12 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | ||
13 | select DVB_S5H1420 if !DVB_FE_CUSTOMISE | 12 | select DVB_S5H1420 if !DVB_FE_CUSTOMISE |
14 | select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE | 13 | select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE |
15 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 14 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
16 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | 15 | select DVB_CX24123 if !DVB_FE_CUSTOMISE |
16 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE | ||
17 | help | 17 | help |
18 | Support for the digital TV receiver chip made by B2C2 Inc. included in | 18 | Support for the digital TV receiver chip made by B2C2 Inc. included in |
19 | Technisats PCI cards and USB boxes. | 19 | Technisats PCI cards and USB boxes. |
diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index a127a4175c40..5cded3708541 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c | |||
@@ -628,12 +628,14 @@ int flexcop_frontend_init(struct flexcop_device *fc) | |||
628 | } | 628 | } |
629 | 629 | ||
630 | /* try the cable dvb (stv0297) */ | 630 | /* try the cable dvb (stv0297) */ |
631 | fc->fc_i2c_adap[0].no_base_addr = 1; | ||
631 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); | 632 | fc->fe = dvb_attach(stv0297_attach, &alps_tdee4_stv0297_config, i2c); |
632 | if (fc->fe != NULL) { | 633 | if (fc->fe != NULL) { |
633 | fc->dev_type = FC_CABLE; | 634 | fc->dev_type = FC_CABLE; |
634 | fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; | 635 | fc->fe->ops.tuner_ops.set_params = alps_tdee4_stv0297_tuner_set_params; |
635 | goto fe_found; | 636 | goto fe_found; |
636 | } | 637 | } |
638 | fc->fc_i2c_adap[0].no_base_addr = 0; | ||
637 | 639 | ||
638 | /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ | 640 | /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ |
639 | fc->fe = dvb_attach(mt312_attach, | 641 | fc->fe = dvb_attach(mt312_attach, |
diff --git a/drivers/media/dvb/b2c2/flexcop-i2c.c b/drivers/media/dvb/b2c2/flexcop-i2c.c index 43a112ec6d44..f13783f08f0f 100644 --- a/drivers/media/dvb/b2c2/flexcop-i2c.c +++ b/drivers/media/dvb/b2c2/flexcop-i2c.c | |||
@@ -47,9 +47,13 @@ static int flexcop_i2c_read4(struct flexcop_i2c_adapter *i2c, | |||
47 | int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ | 47 | int len = r100.tw_sm_c_100.total_bytes, /* remember total_bytes is buflen-1 */ |
48 | ret; | 48 | ret; |
49 | 49 | ||
50 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
51 | ret = flexcop_i2c_operation(i2c->fc, &r100); | 50 | ret = flexcop_i2c_operation(i2c->fc, &r100); |
52 | if (ret != 0) { | 51 | if (ret != 0) { |
52 | deb_i2c("Retrying operation\n"); | ||
53 | r100.tw_sm_c_100.no_base_addr_ack_error = i2c->no_base_addr; | ||
54 | ret = flexcop_i2c_operation(i2c->fc, &r100); | ||
55 | } | ||
56 | if (ret != 0) { | ||
53 | deb_i2c("read failed. %d\n", ret); | 57 | deb_i2c("read failed. %d\n", ret); |
54 | return ret; | 58 | return ret; |
55 | } | 59 | } |
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 7e9c090fc04e..27edb0ece587 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig | |||
@@ -8,7 +8,7 @@ config DVB_BT8XX | |||
8 | select DVB_OR51211 if !DVB_FE_CUSTOMISE | 8 | select DVB_OR51211 if !DVB_FE_CUSTOMISE |
9 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 9 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
10 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 10 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
11 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 11 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE |
12 | help | 12 | help |
13 | Support for PCI cards based on the Bt8xx PCI bridge. Examples are | 13 | Support for PCI cards based on the Bt8xx PCI bridge. Examples are |
14 | the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, | 14 | the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards, |
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 62b68c291d99..49f7b20c25d6 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig | |||
@@ -24,8 +24,8 @@ config DVB_USB_A800 | |||
24 | tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" | 24 | tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)" |
25 | depends on DVB_USB | 25 | depends on DVB_USB |
26 | select DVB_DIB3000MC | 26 | select DVB_DIB3000MC |
27 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | ||
28 | select DVB_PLL if !DVB_FE_CUSTOMISE | 27 | select DVB_PLL if !DVB_FE_CUSTOMISE |
28 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE | ||
29 | help | 29 | help |
30 | Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. | 30 | Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver. |
31 | 31 | ||
@@ -34,7 +34,7 @@ config DVB_USB_DIBUSB_MB | |||
34 | depends on DVB_USB | 34 | depends on DVB_USB |
35 | select DVB_PLL if !DVB_FE_CUSTOMISE | 35 | select DVB_PLL if !DVB_FE_CUSTOMISE |
36 | select DVB_DIB3000MB | 36 | select DVB_DIB3000MB |
37 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 37 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE |
38 | help | 38 | help |
39 | Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by | 39 | Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by |
40 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. | 40 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator. |
@@ -55,7 +55,7 @@ config DVB_USB_DIBUSB_MC | |||
55 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" | 55 | tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)" |
56 | depends on DVB_USB | 56 | depends on DVB_USB |
57 | select DVB_DIB3000MC | 57 | select DVB_DIB3000MC |
58 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 58 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE |
59 | help | 59 | help |
60 | Support for USB2.0 DVB-T receivers based on reference designs made by | 60 | Support for USB2.0 DVB-T receivers based on reference designs made by |
61 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. | 61 | DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator. |
@@ -73,11 +73,11 @@ config DVB_USB_DIB0700 | |||
73 | select DVB_DIB7000M | 73 | select DVB_DIB7000M |
74 | select DVB_DIB3000MC | 74 | select DVB_DIB3000MC |
75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 75 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
76 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | ||
77 | select MEDIA_TUNER_MT2266 if !DVB_FE_CUSTOMISE | ||
78 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | ||
79 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | ||
80 | select DVB_TUNER_DIB0070 | 76 | select DVB_TUNER_DIB0070 |
77 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE | ||
78 | select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMIZE | ||
79 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE | ||
80 | select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE | ||
81 | help | 81 | help |
82 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The | 82 | Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The |
83 | USB bridge is also present in devices having the DiB7700 DVB-T-USB | 83 | USB bridge is also present in devices having the DiB7700 DVB-T-USB |
@@ -95,7 +95,7 @@ config DVB_USB_UMT_010 | |||
95 | depends on DVB_USB | 95 | depends on DVB_USB |
96 | select DVB_PLL if !DVB_FE_CUSTOMISE | 96 | select DVB_PLL if !DVB_FE_CUSTOMISE |
97 | select DVB_DIB3000MC | 97 | select DVB_DIB3000MC |
98 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 98 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE |
99 | help | 99 | help |
100 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. | 100 | Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver. |
101 | 101 | ||
@@ -107,11 +107,11 @@ config DVB_USB_CXUSB | |||
107 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 107 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
108 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 108 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
109 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 109 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
110 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | ||
111 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMISE | ||
112 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | ||
113 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | 110 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE |
114 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE | 111 | select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE |
112 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE | ||
113 | select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE | ||
114 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE | ||
115 | help | 115 | help |
116 | Say Y here to support the Conexant USB2.0 hybrid reference design. | 116 | Say Y here to support the Conexant USB2.0 hybrid reference design. |
117 | Currently, only DVB and ATSC modes are supported, analog mode | 117 | Currently, only DVB and ATSC modes are supported, analog mode |
@@ -124,9 +124,9 @@ config DVB_USB_M920X | |||
124 | tristate "Uli m920x DVB-T USB2.0 support" | 124 | tristate "Uli m920x DVB-T USB2.0 support" |
125 | depends on DVB_USB | 125 | depends on DVB_USB |
126 | select DVB_MT352 if !DVB_FE_CUSTOMISE | 126 | select DVB_MT352 if !DVB_FE_CUSTOMISE |
127 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | ||
128 | select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE | ||
129 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | 127 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE |
128 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE | ||
129 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE | ||
130 | help | 130 | help |
131 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. | 131 | Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver. |
132 | Currently, only devices with a product id of | 132 | Currently, only devices with a product id of |
@@ -137,7 +137,7 @@ config DVB_USB_GL861 | |||
137 | tristate "Genesys Logic GL861 USB2.0 support" | 137 | tristate "Genesys Logic GL861 USB2.0 support" |
138 | depends on DVB_USB | 138 | depends on DVB_USB |
139 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 139 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
140 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 140 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE |
141 | help | 141 | help |
142 | Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 | 142 | Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0 |
143 | receiver with USB ID 0db0:5581. | 143 | receiver with USB ID 0db0:5581. |
@@ -146,7 +146,7 @@ config DVB_USB_AU6610 | |||
146 | tristate "Alcor Micro AU6610 USB2.0 support" | 146 | tristate "Alcor Micro AU6610 USB2.0 support" |
147 | depends on DVB_USB | 147 | depends on DVB_USB |
148 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 148 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
149 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 149 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE |
150 | help | 150 | help |
151 | Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. | 151 | Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver. |
152 | 152 | ||
@@ -198,8 +198,8 @@ config DVB_USB_NOVA_T_USB2 | |||
198 | tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" | 198 | tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support" |
199 | depends on DVB_USB | 199 | depends on DVB_USB |
200 | select DVB_DIB3000MC | 200 | select DVB_DIB3000MC |
201 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | ||
202 | select DVB_PLL if !DVB_FE_CUSTOMISE | 201 | select DVB_PLL if !DVB_FE_CUSTOMISE |
202 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE | ||
203 | help | 203 | help |
204 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. | 204 | Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver. |
205 | 205 | ||
@@ -235,8 +235,8 @@ config DVB_USB_OPERA1 | |||
235 | config DVB_USB_AF9005 | 235 | config DVB_USB_AF9005 |
236 | tristate "Afatech AF9005 DVB-T USB1.1 support" | 236 | tristate "Afatech AF9005 DVB-T USB1.1 support" |
237 | depends on DVB_USB && EXPERIMENTAL | 237 | depends on DVB_USB && EXPERIMENTAL |
238 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 238 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE |
239 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 239 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE |
240 | help | 240 | help |
241 | Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver | 241 | Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver |
242 | and the TerraTec Cinergy T USB XE (Rev.1) | 242 | and the TerraTec Cinergy T USB XE (Rev.1) |
@@ -284,7 +284,7 @@ config DVB_USB_DTV5100 | |||
284 | tristate "AME DTV-5100 USB2.0 DVB-T support" | 284 | tristate "AME DTV-5100 USB2.0 DVB-T support" |
285 | depends on DVB_USB | 285 | depends on DVB_USB |
286 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 286 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
287 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 287 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE |
288 | help | 288 | help |
289 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. | 289 | Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver. |
290 | 290 | ||
@@ -293,9 +293,9 @@ config DVB_USB_AF9015 | |||
293 | depends on DVB_USB && EXPERIMENTAL | 293 | depends on DVB_USB && EXPERIMENTAL |
294 | select DVB_AF9013 | 294 | select DVB_AF9013 |
295 | select DVB_PLL if !DVB_FE_CUSTOMISE | 295 | select DVB_PLL if !DVB_FE_CUSTOMISE |
296 | select MEDIA_TUNER_MT2060 if !DVB_FE_CUSTOMISE | 296 | select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMIZE |
297 | select MEDIA_TUNER_QT1010 if !DVB_FE_CUSTOMISE | 297 | select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMIZE |
298 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMISE | 298 | select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMIZE |
299 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | 299 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE |
300 | help | 300 | help |
301 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver | 301 | Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver |
diff --git a/drivers/media/dvb/dvb-usb/dib0700_devices.c b/drivers/media/dvb/dvb-usb/dib0700_devices.c index f28d3ae59e04..391732788911 100644 --- a/drivers/media/dvb/dvb-usb/dib0700_devices.c +++ b/drivers/media/dvb/dvb-usb/dib0700_devices.c | |||
@@ -446,13 +446,13 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap) | |||
446 | == NULL ? -ENODEV : 0; | 446 | == NULL ? -ENODEV : 0; |
447 | } | 447 | } |
448 | 448 | ||
449 | #define DEFAULT_RC_INTERVAL 150 | 449 | #define DEFAULT_RC_INTERVAL 50 |
450 | 450 | ||
451 | static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; | 451 | static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; |
452 | 452 | ||
453 | /* Number of keypresses to ignore before start repeating */ | 453 | /* Number of keypresses to ignore before start repeating */ |
454 | #define RC_REPEAT_DELAY 2 | 454 | #define RC_REPEAT_DELAY 6 |
455 | #define RC_REPEAT_DELAY_V1_20 5 | 455 | #define RC_REPEAT_DELAY_V1_20 10 |
456 | 456 | ||
457 | 457 | ||
458 | 458 | ||
diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 867027ceab3e..401a04effc06 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig | |||
@@ -106,7 +106,7 @@ config DVB_BUDGET_CI | |||
106 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE | 106 | select DVB_TDA1004X if !DVB_FE_CUSTOMISE |
107 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE | 107 | select DVB_LNBP21 if !DVB_FE_CUSTOMISE |
108 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE | 108 | select DVB_TDA10023 if !DVB_FE_CUSTOMISE |
109 | select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE | 109 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE |
110 | select VIDEO_IR | 110 | select VIDEO_IR |
111 | help | 111 | help |
112 | Support for simple SAA7146 based DVB cards | 112 | Support for simple SAA7146 based DVB cards |
diff --git a/drivers/media/video/compat_ioctl32.c b/drivers/media/video/compat_ioctl32.c index e6ca4012b5f0..0ea85a05e5c0 100644 --- a/drivers/media/video/compat_ioctl32.c +++ b/drivers/media/video/compat_ioctl32.c | |||
@@ -831,7 +831,7 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg) | |||
831 | { | 831 | { |
832 | int ret = -ENOIOCTLCMD; | 832 | int ret = -ENOIOCTLCMD; |
833 | 833 | ||
834 | if (!file->f_op->ioctl) | 834 | if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl) |
835 | return ret; | 835 | return ret; |
836 | 836 | ||
837 | switch (cmd) { | 837 | switch (cmd) { |
diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index ef48565de7f1..8940b5387dec 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig | |||
@@ -9,7 +9,7 @@ config VIDEO_CX18 | |||
9 | select VIDEO_CX2341X | 9 | select VIDEO_CX2341X |
10 | select VIDEO_CS5345 | 10 | select VIDEO_CS5345 |
11 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 11 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
12 | select MEDIA_TUNER_MXL5005S if !DVB_FE_CUSTOMISE | 12 | select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMIZE |
13 | ---help--- | 13 | ---help--- |
14 | This is a video4linux driver for Conexant cx23418 based | 14 | This is a video4linux driver for Conexant cx23418 based |
15 | PCI combo video recorder devices. | 15 | PCI combo video recorder devices. |
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 8c1b7fa47a41..00f1e2e8889e 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig | |||
@@ -11,16 +11,16 @@ config VIDEO_CX23885 | |||
11 | select VIDEO_CX25840 | 11 | select VIDEO_CX25840 |
12 | select VIDEO_CX2341X | 12 | select VIDEO_CX2341X |
13 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE | 13 | select DVB_DIB7000P if !DVB_FE_CUSTOMISE |
14 | select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE | ||
15 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE | 14 | select DVB_S5H1409 if !DVB_FE_CUSTOMISE |
16 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 15 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
17 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE | 16 | select DVB_LGDT330X if !DVB_FE_CUSTOMISE |
18 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE | 17 | select DVB_ZL10353 if !DVB_FE_CUSTOMISE |
18 | select DVB_TDA10048 if !DVB_FE_CUSTOMIZE | ||
19 | select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMIZE | ||
19 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE | 20 | select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE |
20 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 21 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE |
21 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 22 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE |
22 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE | 23 | select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE |
23 | select DVB_TDA10048 if !DVB_FE_CUSTOMIZE | ||
24 | ---help--- | 24 | ---help--- |
25 | This is a video4linux driver for Conexant 23885 based | 25 | This is a video4linux driver for Conexant 23885 based |
26 | TV cards. | 26 | TV cards. |
diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index 0b9e5fac6239..b0f837588e01 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig | |||
@@ -56,12 +56,12 @@ config VIDEO_CX88_DVB | |||
56 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | 56 | select DVB_NXT200X if !DVB_FE_CUSTOMISE |
57 | select DVB_CX24123 if !DVB_FE_CUSTOMISE | 57 | select DVB_CX24123 if !DVB_FE_CUSTOMISE |
58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 58 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
59 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | ||
60 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 59 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
61 | select DVB_CX24116 if !DVB_FE_CUSTOMISE | 60 | select DVB_CX24116 if !DVB_FE_CUSTOMISE |
62 | select DVB_STV0299 if !DVB_FE_CUSTOMISE | 61 | select DVB_STV0299 if !DVB_FE_CUSTOMISE |
63 | select DVB_STV0288 if !DVB_FE_CUSTOMISE | 62 | select DVB_STV0288 if !DVB_FE_CUSTOMISE |
64 | select DVB_STB6000 if !DVB_FE_CUSTOMISE | 63 | select DVB_STB6000 if !DVB_FE_CUSTOMISE |
64 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE | ||
65 | ---help--- | 65 | ---help--- |
66 | This adds support for DVB/ATSC cards based on the | 66 | This adds support for DVB/ATSC cards based on the |
67 | Conexant 2388x chip. | 67 | Conexant 2388x chip. |
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 610f535a257c..4ea1f1e04897 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c | |||
@@ -549,10 +549,11 @@ static int em28xx_config(struct em28xx *dev) | |||
549 | static void em28xx_config_i2c(struct em28xx *dev) | 549 | static void em28xx_config_i2c(struct em28xx *dev) |
550 | { | 550 | { |
551 | struct v4l2_routing route; | 551 | struct v4l2_routing route; |
552 | int zero = 0; | ||
552 | 553 | ||
553 | route.input = INPUT(dev->ctl_input)->vmux; | 554 | route.input = INPUT(dev->ctl_input)->vmux; |
554 | route.output = 0; | 555 | route.output = 0; |
555 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, NULL); | 556 | em28xx_i2c_call_clients(dev, VIDIOC_INT_RESET, &zero); |
556 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); | 557 | em28xx_i2c_call_clients(dev, VIDIOC_INT_S_VIDEO_ROUTING, &route); |
557 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); | 558 | em28xx_i2c_call_clients(dev, VIDIOC_STREAMON, NULL); |
558 | } | 559 | } |
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c index 748a87e82e44..02a6e9ef0337 100644 --- a/drivers/media/video/gspca/gspca.c +++ b/drivers/media/video/gspca/gspca.c | |||
@@ -1264,10 +1264,10 @@ static int vidioc_s_jpegcomp(struct file *file, void *priv, | |||
1264 | struct gspca_dev *gspca_dev = priv; | 1264 | struct gspca_dev *gspca_dev = priv; |
1265 | int ret; | 1265 | int ret; |
1266 | 1266 | ||
1267 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1268 | return -ERESTARTSYS; | ||
1269 | if (!gspca_dev->sd_desc->set_jcomp) | 1267 | if (!gspca_dev->sd_desc->set_jcomp) |
1270 | return -EINVAL; | 1268 | return -EINVAL; |
1269 | if (mutex_lock_interruptible(&gspca_dev->usb_lock)) | ||
1270 | return -ERESTARTSYS; | ||
1271 | ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); | 1271 | ret = gspca_dev->sd_desc->set_jcomp(gspca_dev, jpegcomp); |
1272 | mutex_unlock(&gspca_dev->usb_lock); | 1272 | mutex_unlock(&gspca_dev->usb_lock); |
1273 | return ret; | 1273 | return ret; |
diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 19eb274c9cd0..854c2a885358 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig | |||
@@ -42,7 +42,7 @@ config VIDEO_PVRUSB2_DVB | |||
42 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE | 42 | select DVB_S5H1411 if !DVB_FE_CUSTOMISE |
43 | select DVB_TDA10048 if !DVB_FE_CUSTOMIZE | 43 | select DVB_TDA10048 if !DVB_FE_CUSTOMIZE |
44 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE | 44 | select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE |
45 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 45 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE |
46 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE | 46 | select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE |
47 | ---help--- | 47 | ---help--- |
48 | 48 | ||
diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 7021bbf5897b..fc2164e28e76 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig | |||
@@ -34,9 +34,9 @@ config VIDEO_SAA7134_DVB | |||
34 | select DVB_NXT200X if !DVB_FE_CUSTOMISE | 34 | select DVB_NXT200X if !DVB_FE_CUSTOMISE |
35 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE | 35 | select DVB_TDA10086 if !DVB_FE_CUSTOMISE |
36 | select DVB_TDA826X if !DVB_FE_CUSTOMISE | 36 | select DVB_TDA826X if !DVB_FE_CUSTOMISE |
37 | select MEDIA_TUNER_TDA827X if !DVB_FE_CUSTOMISE | ||
38 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE | 37 | select DVB_ISL6421 if !DVB_FE_CUSTOMISE |
39 | select MEDIA_TUNER_SIMPLE if !DVB_FE_CUSTOMISE | 38 | select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMIZE |
39 | select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMIZE | ||
40 | ---help--- | 40 | ---help--- |
41 | This adds support for DVB cards based on the | 41 | This adds support for DVB cards based on the |
42 | Philips saa7134 chip. | 42 | Philips saa7134 chip. |
diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index d62fd4f6b52e..ee090413e598 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c | |||
@@ -2008,6 +2008,9 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) | |||
2008 | return FAILED; | 2008 | return FAILED; |
2009 | } | 2009 | } |
2010 | 2010 | ||
2011 | /* make sure we have no outstanding commands at this stage */ | ||
2012 | mptscsih_flush_running_cmds(hd); | ||
2013 | |||
2011 | ioc = hd->ioc; | 2014 | ioc = hd->ioc; |
2012 | printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n", | 2015 | printk(MYIOC_s_INFO_FMT "attempting host reset! (sc=%p)\n", |
2013 | ioc->name, SCpnt); | 2016 | ioc->name, SCpnt); |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a1a3d0e5d2b4..9e8222f9e90e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -543,9 +543,9 @@ bnx2_free_rx_mem(struct bnx2 *bp) | |||
543 | for (j = 0; j < bp->rx_max_pg_ring; j++) { | 543 | for (j = 0; j < bp->rx_max_pg_ring; j++) { |
544 | if (rxr->rx_pg_desc_ring[j]) | 544 | if (rxr->rx_pg_desc_ring[j]) |
545 | pci_free_consistent(bp->pdev, RXBD_RING_SIZE, | 545 | pci_free_consistent(bp->pdev, RXBD_RING_SIZE, |
546 | rxr->rx_pg_desc_ring[i], | 546 | rxr->rx_pg_desc_ring[j], |
547 | rxr->rx_pg_desc_mapping[i]); | 547 | rxr->rx_pg_desc_mapping[j]); |
548 | rxr->rx_pg_desc_ring[i] = NULL; | 548 | rxr->rx_pg_desc_ring[j] = NULL; |
549 | } | 549 | } |
550 | if (rxr->rx_pg_ring) | 550 | if (rxr->rx_pg_ring) |
551 | vfree(rxr->rx_pg_ring); | 551 | vfree(rxr->rx_pg_ring); |
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 523b9716a543..d115a6d30f29 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c | |||
@@ -1893,12 +1893,17 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) | |||
1893 | ctrl |= E1000_CTRL_PHY_RST; | 1893 | ctrl |= E1000_CTRL_PHY_RST; |
1894 | } | 1894 | } |
1895 | ret_val = e1000_acquire_swflag_ich8lan(hw); | 1895 | ret_val = e1000_acquire_swflag_ich8lan(hw); |
1896 | /* Whether or not the swflag was acquired, we need to reset the part */ | ||
1896 | hw_dbg(hw, "Issuing a global reset to ich8lan"); | 1897 | hw_dbg(hw, "Issuing a global reset to ich8lan"); |
1897 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); | 1898 | ew32(CTRL, (ctrl | E1000_CTRL_RST)); |
1898 | msleep(20); | 1899 | msleep(20); |
1899 | 1900 | ||
1900 | /* release the swflag because it is not reset by hardware reset */ | 1901 | if (!ret_val) { |
1901 | e1000_release_swflag_ich8lan(hw); | 1902 | /* release the swflag because it is not reset by |
1903 | * hardware reset | ||
1904 | */ | ||
1905 | e1000_release_swflag_ich8lan(hw); | ||
1906 | } | ||
1902 | 1907 | ||
1903 | ret_val = e1000e_get_auto_rd_done(hw); | 1908 | ret_val = e1000e_get_auto_rd_done(hw); |
1904 | if (ret_val) { | 1909 | if (ret_val) { |
diff --git a/drivers/net/enc28j60.c b/drivers/net/enc28j60.c index c414554ac321..36cb6e95b465 100644 --- a/drivers/net/enc28j60.c +++ b/drivers/net/enc28j60.c | |||
@@ -959,7 +959,7 @@ static void enc28j60_hw_rx(struct net_device *ndev) | |||
959 | ndev->stats.rx_packets++; | 959 | ndev->stats.rx_packets++; |
960 | ndev->stats.rx_bytes += len; | 960 | ndev->stats.rx_bytes += len; |
961 | ndev->last_rx = jiffies; | 961 | ndev->last_rx = jiffies; |
962 | netif_rx(skb); | 962 | netif_rx_ni(skb); |
963 | } | 963 | } |
964 | } | 964 | } |
965 | /* | 965 | /* |
diff --git a/drivers/net/jme.h b/drivers/net/jme.h index f863aee6648b..3f5d91543246 100644 --- a/drivers/net/jme.h +++ b/drivers/net/jme.h | |||
@@ -22,7 +22,7 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | #ifndef __JME_H_INCLUDED__ | 24 | #ifndef __JME_H_INCLUDED__ |
25 | #define __JME_H_INCLUDEE__ | 25 | #define __JME_H_INCLUDED__ |
26 | 26 | ||
27 | #define DRV_NAME "jme" | 27 | #define DRV_NAME "jme" |
28 | #define DRV_VERSION "1.0.3" | 28 | #define DRV_VERSION "1.0.3" |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 536bda1f428b..289fc267edf3 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
@@ -105,8 +105,6 @@ int mdiobus_register(struct mii_bus *bus) | |||
105 | return -EINVAL; | 105 | return -EINVAL; |
106 | } | 106 | } |
107 | 107 | ||
108 | bus->state = MDIOBUS_REGISTERED; | ||
109 | |||
110 | mutex_init(&bus->mdio_lock); | 108 | mutex_init(&bus->mdio_lock); |
111 | 109 | ||
112 | if (bus->reset) | 110 | if (bus->reset) |
@@ -123,6 +121,9 @@ int mdiobus_register(struct mii_bus *bus) | |||
123 | } | 121 | } |
124 | } | 122 | } |
125 | 123 | ||
124 | if (!err) | ||
125 | bus->state = MDIOBUS_REGISTERED; | ||
126 | |||
126 | pr_info("%s: probed\n", bus->name); | 127 | pr_info("%s: probed\n", bus->name); |
127 | 128 | ||
128 | return err; | 129 | return err; |
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 7e857e938adb..714a23035de1 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
@@ -116,6 +116,7 @@ struct ppp { | |||
116 | unsigned long last_xmit; /* jiffies when last pkt sent 9c */ | 116 | unsigned long last_xmit; /* jiffies when last pkt sent 9c */ |
117 | unsigned long last_recv; /* jiffies when last pkt rcvd a0 */ | 117 | unsigned long last_recv; /* jiffies when last pkt rcvd a0 */ |
118 | struct net_device *dev; /* network interface device a4 */ | 118 | struct net_device *dev; /* network interface device a4 */ |
119 | int closing; /* is device closing down? a8 */ | ||
119 | #ifdef CONFIG_PPP_MULTILINK | 120 | #ifdef CONFIG_PPP_MULTILINK |
120 | int nxchan; /* next channel to send something on */ | 121 | int nxchan; /* next channel to send something on */ |
121 | u32 nxseq; /* next sequence number to send */ | 122 | u32 nxseq; /* next sequence number to send */ |
@@ -995,7 +996,7 @@ ppp_xmit_process(struct ppp *ppp) | |||
995 | struct sk_buff *skb; | 996 | struct sk_buff *skb; |
996 | 997 | ||
997 | ppp_xmit_lock(ppp); | 998 | ppp_xmit_lock(ppp); |
998 | if (ppp->dev) { | 999 | if (!ppp->closing) { |
999 | ppp_push(ppp); | 1000 | ppp_push(ppp); |
1000 | while (!ppp->xmit_pending | 1001 | while (!ppp->xmit_pending |
1001 | && (skb = skb_dequeue(&ppp->file.xq))) | 1002 | && (skb = skb_dequeue(&ppp->file.xq))) |
@@ -1463,8 +1464,7 @@ static inline void | |||
1463 | ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) | 1464 | ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) |
1464 | { | 1465 | { |
1465 | ppp_recv_lock(ppp); | 1466 | ppp_recv_lock(ppp); |
1466 | /* ppp->dev == 0 means interface is closing down */ | 1467 | if (!ppp->closing) |
1467 | if (ppp->dev) | ||
1468 | ppp_receive_frame(ppp, skb, pch); | 1468 | ppp_receive_frame(ppp, skb, pch); |
1469 | else | 1469 | else |
1470 | kfree_skb(skb); | 1470 | kfree_skb(skb); |
@@ -2498,18 +2498,16 @@ init_ppp_file(struct ppp_file *pf, int kind) | |||
2498 | */ | 2498 | */ |
2499 | static void ppp_shutdown_interface(struct ppp *ppp) | 2499 | static void ppp_shutdown_interface(struct ppp *ppp) |
2500 | { | 2500 | { |
2501 | struct net_device *dev; | ||
2502 | |||
2503 | mutex_lock(&all_ppp_mutex); | 2501 | mutex_lock(&all_ppp_mutex); |
2504 | ppp_lock(ppp); | ||
2505 | dev = ppp->dev; | ||
2506 | ppp->dev = NULL; | ||
2507 | ppp_unlock(ppp); | ||
2508 | /* This will call dev_close() for us. */ | 2502 | /* This will call dev_close() for us. */ |
2509 | if (dev) { | 2503 | ppp_lock(ppp); |
2510 | unregister_netdev(dev); | 2504 | if (!ppp->closing) { |
2511 | free_netdev(dev); | 2505 | ppp->closing = 1; |
2512 | } | 2506 | ppp_unlock(ppp); |
2507 | unregister_netdev(ppp->dev); | ||
2508 | } else | ||
2509 | ppp_unlock(ppp); | ||
2510 | |||
2513 | cardmap_set(&all_ppp_units, ppp->file.index, NULL); | 2511 | cardmap_set(&all_ppp_units, ppp->file.index, NULL); |
2514 | ppp->file.dead = 1; | 2512 | ppp->file.dead = 1; |
2515 | ppp->owner = NULL; | 2513 | ppp->owner = NULL; |
@@ -2554,7 +2552,7 @@ static void ppp_destroy_interface(struct ppp *ppp) | |||
2554 | if (ppp->xmit_pending) | 2552 | if (ppp->xmit_pending) |
2555 | kfree_skb(ppp->xmit_pending); | 2553 | kfree_skb(ppp->xmit_pending); |
2556 | 2554 | ||
2557 | kfree(ppp); | 2555 | free_netdev(ppp->dev); |
2558 | } | 2556 | } |
2559 | 2557 | ||
2560 | /* | 2558 | /* |
@@ -2616,7 +2614,7 @@ ppp_connect_channel(struct channel *pch, int unit) | |||
2616 | if (pch->file.hdrlen > ppp->file.hdrlen) | 2614 | if (pch->file.hdrlen > ppp->file.hdrlen) |
2617 | ppp->file.hdrlen = pch->file.hdrlen; | 2615 | ppp->file.hdrlen = pch->file.hdrlen; |
2618 | hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ | 2616 | hdrlen = pch->file.hdrlen + 2; /* for protocol bytes */ |
2619 | if (ppp->dev && hdrlen > ppp->dev->hard_header_len) | 2617 | if (hdrlen > ppp->dev->hard_header_len) |
2620 | ppp->dev->hard_header_len = hdrlen; | 2618 | ppp->dev->hard_header_len = hdrlen; |
2621 | list_add_tail(&pch->clist, &ppp->channels); | 2619 | list_add_tail(&pch->clist, &ppp->channels); |
2622 | ++ppp->n_channels; | 2620 | ++ppp->n_channels; |
diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 1d2ef8f47780..5a40f2d78beb 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c | |||
@@ -1509,6 +1509,11 @@ static int __netdev_rx(struct net_device *dev, int *quota) | |||
1509 | desc->status = 0; | 1509 | desc->status = 0; |
1510 | np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE; | 1510 | np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE; |
1511 | } | 1511 | } |
1512 | |||
1513 | if (*quota == 0) { /* out of rx quota */ | ||
1514 | retcode = 1; | ||
1515 | goto out; | ||
1516 | } | ||
1512 | writew(np->rx_done, np->base + CompletionQConsumerIdx); | 1517 | writew(np->rx_done, np->base + CompletionQConsumerIdx); |
1513 | 1518 | ||
1514 | out: | 1519 | out: |
diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 1349e419673c..fed7eba65ead 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c | |||
@@ -1142,6 +1142,70 @@ static int gem_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1142 | return NETDEV_TX_OK; | 1142 | return NETDEV_TX_OK; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static void gem_pcs_reset(struct gem *gp) | ||
1146 | { | ||
1147 | int limit; | ||
1148 | u32 val; | ||
1149 | |||
1150 | /* Reset PCS unit. */ | ||
1151 | val = readl(gp->regs + PCS_MIICTRL); | ||
1152 | val |= PCS_MIICTRL_RST; | ||
1153 | writel(val, gp->regs + PCS_MIICTRL); | ||
1154 | |||
1155 | limit = 32; | ||
1156 | while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) { | ||
1157 | udelay(100); | ||
1158 | if (limit-- <= 0) | ||
1159 | break; | ||
1160 | } | ||
1161 | if (limit <= 0) | ||
1162 | printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", | ||
1163 | gp->dev->name); | ||
1164 | } | ||
1165 | |||
1166 | static void gem_pcs_reinit_adv(struct gem *gp) | ||
1167 | { | ||
1168 | u32 val; | ||
1169 | |||
1170 | /* Make sure PCS is disabled while changing advertisement | ||
1171 | * configuration. | ||
1172 | */ | ||
1173 | val = readl(gp->regs + PCS_CFG); | ||
1174 | val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO); | ||
1175 | writel(val, gp->regs + PCS_CFG); | ||
1176 | |||
1177 | /* Advertise all capabilities except assymetric | ||
1178 | * pause. | ||
1179 | */ | ||
1180 | val = readl(gp->regs + PCS_MIIADV); | ||
1181 | val |= (PCS_MIIADV_FD | PCS_MIIADV_HD | | ||
1182 | PCS_MIIADV_SP | PCS_MIIADV_AP); | ||
1183 | writel(val, gp->regs + PCS_MIIADV); | ||
1184 | |||
1185 | /* Enable and restart auto-negotiation, disable wrapback/loopback, | ||
1186 | * and re-enable PCS. | ||
1187 | */ | ||
1188 | val = readl(gp->regs + PCS_MIICTRL); | ||
1189 | val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE); | ||
1190 | val &= ~PCS_MIICTRL_WB; | ||
1191 | writel(val, gp->regs + PCS_MIICTRL); | ||
1192 | |||
1193 | val = readl(gp->regs + PCS_CFG); | ||
1194 | val |= PCS_CFG_ENABLE; | ||
1195 | writel(val, gp->regs + PCS_CFG); | ||
1196 | |||
1197 | /* Make sure serialink loopback is off. The meaning | ||
1198 | * of this bit is logically inverted based upon whether | ||
1199 | * you are in Serialink or SERDES mode. | ||
1200 | */ | ||
1201 | val = readl(gp->regs + PCS_SCTRL); | ||
1202 | if (gp->phy_type == phy_serialink) | ||
1203 | val &= ~PCS_SCTRL_LOOP; | ||
1204 | else | ||
1205 | val |= PCS_SCTRL_LOOP; | ||
1206 | writel(val, gp->regs + PCS_SCTRL); | ||
1207 | } | ||
1208 | |||
1145 | #define STOP_TRIES 32 | 1209 | #define STOP_TRIES 32 |
1146 | 1210 | ||
1147 | /* Must be invoked under gp->lock and gp->tx_lock. */ | 1211 | /* Must be invoked under gp->lock and gp->tx_lock. */ |
@@ -1168,6 +1232,9 @@ static void gem_reset(struct gem *gp) | |||
1168 | 1232 | ||
1169 | if (limit <= 0) | 1233 | if (limit <= 0) |
1170 | printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); | 1234 | printk(KERN_ERR "%s: SW reset is ghetto.\n", gp->dev->name); |
1235 | |||
1236 | if (gp->phy_type == phy_serialink || gp->phy_type == phy_serdes) | ||
1237 | gem_pcs_reinit_adv(gp); | ||
1171 | } | 1238 | } |
1172 | 1239 | ||
1173 | /* Must be invoked under gp->lock and gp->tx_lock. */ | 1240 | /* Must be invoked under gp->lock and gp->tx_lock. */ |
@@ -1324,7 +1391,7 @@ static int gem_set_link_modes(struct gem *gp) | |||
1324 | gp->phy_type == phy_serdes) { | 1391 | gp->phy_type == phy_serdes) { |
1325 | u32 pcs_lpa = readl(gp->regs + PCS_MIILP); | 1392 | u32 pcs_lpa = readl(gp->regs + PCS_MIILP); |
1326 | 1393 | ||
1327 | if (pcs_lpa & PCS_MIIADV_FD) | 1394 | if ((pcs_lpa & PCS_MIIADV_FD) || gp->phy_type == phy_serdes) |
1328 | full_duplex = 1; | 1395 | full_duplex = 1; |
1329 | speed = SPEED_1000; | 1396 | speed = SPEED_1000; |
1330 | } | 1397 | } |
@@ -1488,6 +1555,9 @@ static void gem_link_timer(unsigned long data) | |||
1488 | val = readl(gp->regs + PCS_MIISTAT); | 1555 | val = readl(gp->regs + PCS_MIISTAT); |
1489 | 1556 | ||
1490 | if ((val & PCS_MIISTAT_LS) != 0) { | 1557 | if ((val & PCS_MIISTAT_LS) != 0) { |
1558 | if (gp->lstate == link_up) | ||
1559 | goto restart; | ||
1560 | |||
1491 | gp->lstate = link_up; | 1561 | gp->lstate = link_up; |
1492 | netif_carrier_on(gp->dev); | 1562 | netif_carrier_on(gp->dev); |
1493 | (void)gem_set_link_modes(gp); | 1563 | (void)gem_set_link_modes(gp); |
@@ -1708,61 +1778,8 @@ static void gem_init_phy(struct gem *gp) | |||
1708 | if (gp->phy_mii.def && gp->phy_mii.def->ops->init) | 1778 | if (gp->phy_mii.def && gp->phy_mii.def->ops->init) |
1709 | gp->phy_mii.def->ops->init(&gp->phy_mii); | 1779 | gp->phy_mii.def->ops->init(&gp->phy_mii); |
1710 | } else { | 1780 | } else { |
1711 | u32 val; | 1781 | gem_pcs_reset(gp); |
1712 | int limit; | 1782 | gem_pcs_reinit_adv(gp); |
1713 | |||
1714 | /* Reset PCS unit. */ | ||
1715 | val = readl(gp->regs + PCS_MIICTRL); | ||
1716 | val |= PCS_MIICTRL_RST; | ||
1717 | writel(val, gp->regs + PCS_MIICTRL); | ||
1718 | |||
1719 | limit = 32; | ||
1720 | while (readl(gp->regs + PCS_MIICTRL) & PCS_MIICTRL_RST) { | ||
1721 | udelay(100); | ||
1722 | if (limit-- <= 0) | ||
1723 | break; | ||
1724 | } | ||
1725 | if (limit <= 0) | ||
1726 | printk(KERN_WARNING "%s: PCS reset bit would not clear.\n", | ||
1727 | gp->dev->name); | ||
1728 | |||
1729 | /* Make sure PCS is disabled while changing advertisement | ||
1730 | * configuration. | ||
1731 | */ | ||
1732 | val = readl(gp->regs + PCS_CFG); | ||
1733 | val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO); | ||
1734 | writel(val, gp->regs + PCS_CFG); | ||
1735 | |||
1736 | /* Advertise all capabilities except assymetric | ||
1737 | * pause. | ||
1738 | */ | ||
1739 | val = readl(gp->regs + PCS_MIIADV); | ||
1740 | val |= (PCS_MIIADV_FD | PCS_MIIADV_HD | | ||
1741 | PCS_MIIADV_SP | PCS_MIIADV_AP); | ||
1742 | writel(val, gp->regs + PCS_MIIADV); | ||
1743 | |||
1744 | /* Enable and restart auto-negotiation, disable wrapback/loopback, | ||
1745 | * and re-enable PCS. | ||
1746 | */ | ||
1747 | val = readl(gp->regs + PCS_MIICTRL); | ||
1748 | val |= (PCS_MIICTRL_RAN | PCS_MIICTRL_ANE); | ||
1749 | val &= ~PCS_MIICTRL_WB; | ||
1750 | writel(val, gp->regs + PCS_MIICTRL); | ||
1751 | |||
1752 | val = readl(gp->regs + PCS_CFG); | ||
1753 | val |= PCS_CFG_ENABLE; | ||
1754 | writel(val, gp->regs + PCS_CFG); | ||
1755 | |||
1756 | /* Make sure serialink loopback is off. The meaning | ||
1757 | * of this bit is logically inverted based upon whether | ||
1758 | * you are in Serialink or SERDES mode. | ||
1759 | */ | ||
1760 | val = readl(gp->regs + PCS_SCTRL); | ||
1761 | if (gp->phy_type == phy_serialink) | ||
1762 | val &= ~PCS_SCTRL_LOOP; | ||
1763 | else | ||
1764 | val |= PCS_SCTRL_LOOP; | ||
1765 | writel(val, gp->regs + PCS_SCTRL); | ||
1766 | } | 1783 | } |
1767 | 1784 | ||
1768 | /* Default aneg parameters */ | 1785 | /* Default aneg parameters */ |
@@ -2680,6 +2697,21 @@ static int gem_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
2680 | cmd->speed = 0; | 2697 | cmd->speed = 0; |
2681 | cmd->duplex = cmd->port = cmd->phy_address = | 2698 | cmd->duplex = cmd->port = cmd->phy_address = |
2682 | cmd->transceiver = cmd->autoneg = 0; | 2699 | cmd->transceiver = cmd->autoneg = 0; |
2700 | |||
2701 | /* serdes means usually a Fibre connector, with most fixed */ | ||
2702 | if (gp->phy_type == phy_serdes) { | ||
2703 | cmd->port = PORT_FIBRE; | ||
2704 | cmd->supported = (SUPPORTED_1000baseT_Half | | ||
2705 | SUPPORTED_1000baseT_Full | | ||
2706 | SUPPORTED_FIBRE | SUPPORTED_Autoneg | | ||
2707 | SUPPORTED_Pause | SUPPORTED_Asym_Pause); | ||
2708 | cmd->advertising = cmd->supported; | ||
2709 | cmd->transceiver = XCVR_INTERNAL; | ||
2710 | if (gp->lstate == link_up) | ||
2711 | cmd->speed = SPEED_1000; | ||
2712 | cmd->duplex = DUPLEX_FULL; | ||
2713 | cmd->autoneg = 1; | ||
2714 | } | ||
2683 | } | 2715 | } |
2684 | cmd->maxtxpkt = cmd->maxrxpkt = 0; | 2716 | cmd->maxtxpkt = cmd->maxrxpkt = 0; |
2685 | 2717 | ||
diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index c41d68761364..e60498232b94 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c | |||
@@ -1098,6 +1098,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) | |||
1098 | dma_addr_t tail_list_phys; | 1098 | dma_addr_t tail_list_phys; |
1099 | u8 *tail_buffer; | 1099 | u8 *tail_buffer; |
1100 | unsigned long flags; | 1100 | unsigned long flags; |
1101 | unsigned int txlen; | ||
1101 | 1102 | ||
1102 | if ( ! priv->phyOnline ) { | 1103 | if ( ! priv->phyOnline ) { |
1103 | TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n", | 1104 | TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT: %s PHY is not ready\n", |
@@ -1108,6 +1109,7 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) | |||
1108 | 1109 | ||
1109 | if (skb_padto(skb, TLAN_MIN_FRAME_SIZE)) | 1110 | if (skb_padto(skb, TLAN_MIN_FRAME_SIZE)) |
1110 | return 0; | 1111 | return 0; |
1112 | txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE); | ||
1111 | 1113 | ||
1112 | tail_list = priv->txList + priv->txTail; | 1114 | tail_list = priv->txList + priv->txTail; |
1113 | tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail; | 1115 | tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail; |
@@ -1125,16 +1127,16 @@ static int TLan_StartTx( struct sk_buff *skb, struct net_device *dev ) | |||
1125 | 1127 | ||
1126 | if ( bbuf ) { | 1128 | if ( bbuf ) { |
1127 | tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE ); | 1129 | tail_buffer = priv->txBuffer + ( priv->txTail * TLAN_MAX_FRAME_SIZE ); |
1128 | skb_copy_from_linear_data(skb, tail_buffer, skb->len); | 1130 | skb_copy_from_linear_data(skb, tail_buffer, txlen); |
1129 | } else { | 1131 | } else { |
1130 | tail_list->buffer[0].address = pci_map_single(priv->pciDev, | 1132 | tail_list->buffer[0].address = pci_map_single(priv->pciDev, |
1131 | skb->data, skb->len, | 1133 | skb->data, txlen, |
1132 | PCI_DMA_TODEVICE); | 1134 | PCI_DMA_TODEVICE); |
1133 | TLan_StoreSKB(tail_list, skb); | 1135 | TLan_StoreSKB(tail_list, skb); |
1134 | } | 1136 | } |
1135 | 1137 | ||
1136 | tail_list->frameSize = (u16) skb->len; | 1138 | tail_list->frameSize = (u16) txlen; |
1137 | tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) skb->len; | 1139 | tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen; |
1138 | tail_list->buffer[1].count = 0; | 1140 | tail_list->buffer[1].count = 0; |
1139 | tail_list->buffer[1].address = 0; | 1141 | tail_list->buffer[1].address = 0; |
1140 | 1142 | ||
@@ -1431,7 +1433,9 @@ static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int ) | |||
1431 | if ( ! bbuf ) { | 1433 | if ( ! bbuf ) { |
1432 | struct sk_buff *skb = TLan_GetSKB(head_list); | 1434 | struct sk_buff *skb = TLan_GetSKB(head_list); |
1433 | pci_unmap_single(priv->pciDev, head_list->buffer[0].address, | 1435 | pci_unmap_single(priv->pciDev, head_list->buffer[0].address, |
1434 | skb->len, PCI_DMA_TODEVICE); | 1436 | max(skb->len, |
1437 | (unsigned int)TLAN_MIN_FRAME_SIZE), | ||
1438 | PCI_DMA_TODEVICE); | ||
1435 | dev_kfree_skb_any(skb); | 1439 | dev_kfree_skb_any(skb); |
1436 | head_list->buffer[8].address = 0; | 1440 | head_list->buffer[8].address = 0; |
1437 | head_list->buffer[9].address = 0; | 1441 | head_list->buffer[9].address = 0; |
@@ -2055,9 +2059,12 @@ static void TLan_FreeLists( struct net_device *dev ) | |||
2055 | list = priv->txList + i; | 2059 | list = priv->txList + i; |
2056 | skb = TLan_GetSKB(list); | 2060 | skb = TLan_GetSKB(list); |
2057 | if ( skb ) { | 2061 | if ( skb ) { |
2058 | pci_unmap_single(priv->pciDev, | 2062 | pci_unmap_single( |
2059 | list->buffer[0].address, skb->len, | 2063 | priv->pciDev, |
2060 | PCI_DMA_TODEVICE); | 2064 | list->buffer[0].address, |
2065 | max(skb->len, | ||
2066 | (unsigned int)TLAN_MIN_FRAME_SIZE), | ||
2067 | PCI_DMA_TODEVICE); | ||
2061 | dev_kfree_skb_any( skb ); | 2068 | dev_kfree_skb_any( skb ); |
2062 | list->buffer[8].address = 0; | 2069 | list->buffer[8].address = 0; |
2063 | list->buffer[9].address = 0; | 2070 | list->buffer[9].address = 0; |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index f9e244da30ae..9bcb6cbd5aa9 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
@@ -113,7 +113,7 @@ struct acpiphp_slot { | |||
113 | 113 | ||
114 | u8 device; /* pci device# */ | 114 | u8 device; /* pci device# */ |
115 | 115 | ||
116 | u32 sun; /* ACPI _SUN (slot unique number) */ | 116 | unsigned long long sun; /* ACPI _SUN (slot unique number) */ |
117 | u32 flags; /* see below */ | 117 | u32 flags; /* see below */ |
118 | }; | 118 | }; |
119 | 119 | ||
diff --git a/drivers/pci/hotplug/acpiphp_core.c b/drivers/pci/hotplug/acpiphp_core.c index 95b536a23d25..43c10bd261b4 100644 --- a/drivers/pci/hotplug/acpiphp_core.c +++ b/drivers/pci/hotplug/acpiphp_core.c | |||
@@ -337,7 +337,7 @@ int acpiphp_register_hotplug_slot(struct acpiphp_slot *acpiphp_slot) | |||
337 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; | 337 | slot->hotplug_slot->info->cur_bus_speed = PCI_SPEED_UNKNOWN; |
338 | 338 | ||
339 | acpiphp_slot->slot = slot; | 339 | acpiphp_slot->slot = slot; |
340 | snprintf(name, SLOT_NAME_SIZE, "%u", slot->acpi_slot->sun); | 340 | snprintf(name, SLOT_NAME_SIZE, "%llu", slot->acpi_slot->sun); |
341 | 341 | ||
342 | retval = pci_hp_register(slot->hotplug_slot, | 342 | retval = pci_hp_register(slot->hotplug_slot, |
343 | acpiphp_slot->bridge->pci_bus, | 343 | acpiphp_slot->bridge->pci_bus, |
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 955aae4071f7..3affc6472e65 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
@@ -255,13 +255,13 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
255 | 255 | ||
256 | bridge->nr_slots++; | 256 | bridge->nr_slots++; |
257 | 257 | ||
258 | dbg("found ACPI PCI Hotplug slot %d at PCI %04x:%02x:%02x\n", | 258 | dbg("found ACPI PCI Hotplug slot %llu at PCI %04x:%02x:%02x\n", |
259 | slot->sun, pci_domain_nr(bridge->pci_bus), | 259 | slot->sun, pci_domain_nr(bridge->pci_bus), |
260 | bridge->pci_bus->number, slot->device); | 260 | bridge->pci_bus->number, slot->device); |
261 | retval = acpiphp_register_hotplug_slot(slot); | 261 | retval = acpiphp_register_hotplug_slot(slot); |
262 | if (retval) { | 262 | if (retval) { |
263 | if (retval == -EBUSY) | 263 | if (retval == -EBUSY) |
264 | warn("Slot %d already registered by another " | 264 | warn("Slot %llu already registered by another " |
265 | "hotplug driver\n", slot->sun); | 265 | "hotplug driver\n", slot->sun); |
266 | else | 266 | else |
267 | warn("acpiphp_register_hotplug_slot failed " | 267 | warn("acpiphp_register_hotplug_slot failed " |
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index c892daae74d6..633e743442ac 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
@@ -1402,10 +1402,6 @@ static int __init ibmphp_init(void) | |||
1402 | goto error; | 1402 | goto error; |
1403 | } | 1403 | } |
1404 | 1404 | ||
1405 | /* lock ourselves into memory with a module | ||
1406 | * count of -1 so that no one can unload us. */ | ||
1407 | module_put(THIS_MODULE); | ||
1408 | |||
1409 | exit: | 1405 | exit: |
1410 | return rc; | 1406 | return rc; |
1411 | 1407 | ||
@@ -1423,4 +1419,3 @@ static void __exit ibmphp_exit(void) | |||
1423 | } | 1419 | } |
1424 | 1420 | ||
1425 | module_init(ibmphp_init); | 1421 | module_init(ibmphp_init); |
1426 | module_exit(ibmphp_exit); | ||
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 4b23bc39b11e..39cf248d24e3 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -432,18 +432,19 @@ static int pciehp_probe(struct pcie_device *dev, const struct pcie_port_service_ | |||
432 | goto err_out_release_ctlr; | 432 | goto err_out_release_ctlr; |
433 | } | 433 | } |
434 | 434 | ||
435 | /* Check if slot is occupied */ | ||
435 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); | 436 | t_slot = pciehp_find_slot(ctrl, ctrl->slot_device_offset); |
436 | 437 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); | |
437 | t_slot->hpc_ops->get_adapter_status(t_slot, &value); /* Check if slot is occupied */ | 438 | if (value) { |
438 | if (value && pciehp_force) { | 439 | if (pciehp_force) |
439 | rc = pciehp_enable_slot(t_slot); | 440 | pciehp_enable_slot(t_slot); |
440 | if (rc) /* -ENODEV: shouldn't happen, but deal with it */ | 441 | } else { |
441 | value = 0; | 442 | /* Power off slot if not occupied */ |
442 | } | 443 | if (POWER_CTRL(ctrl)) { |
443 | if ((POWER_CTRL(ctrl)) && !value) { | 444 | rc = t_slot->hpc_ops->power_off_slot(t_slot); |
444 | rc = t_slot->hpc_ops->power_off_slot(t_slot); /* Power off slot if not occupied*/ | 445 | if (rc) |
445 | if (rc) | 446 | goto err_out_free_ctrl_slot; |
446 | goto err_out_free_ctrl_slot; | 447 | } |
447 | } | 448 | } |
448 | 449 | ||
449 | return 0; | 450 | return 0; |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index dfc63d01f20a..aac7006949f1 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -252,7 +252,7 @@ static void report_resume(struct pci_dev *dev, void *data) | |||
252 | 252 | ||
253 | if (!dev->driver || | 253 | if (!dev->driver || |
254 | !dev->driver->err_handler || | 254 | !dev->driver->err_handler || |
255 | !dev->driver->err_handler->slot_reset) | 255 | !dev->driver->err_handler->resume) |
256 | return; | 256 | return; |
257 | 257 | ||
258 | err_handler = dev->driver->err_handler; | 258 | err_handler = dev->driver->err_handler; |
diff --git a/drivers/pcmcia/bfin_cf_pcmcia.c b/drivers/pcmcia/bfin_cf_pcmcia.c index bb7338863fb9..b59d4115d20f 100644 --- a/drivers/pcmcia/bfin_cf_pcmcia.c +++ b/drivers/pcmcia/bfin_cf_pcmcia.c | |||
@@ -334,6 +334,6 @@ static void __exit bfin_cf_exit(void) | |||
334 | module_init(bfin_cf_init); | 334 | module_init(bfin_cf_init); |
335 | module_exit(bfin_cf_exit); | 335 | module_exit(bfin_cf_exit); |
336 | 336 | ||
337 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>") | 337 | MODULE_AUTHOR("Michael Hennerich <hennerich@blackfin.uclinux.org>"); |
338 | MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver"); | 338 | MODULE_DESCRIPTION("BFIN CF/PCMCIA Driver"); |
339 | MODULE_LICENSE("GPL"); | 339 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index 2cd77ab8fc66..054e05294af8 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -328,6 +328,13 @@ isl1208_i2c_set_time(struct i2c_client *client, struct rtc_time const *tm) | |||
328 | int sr; | 328 | int sr; |
329 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; | 329 | u8 regs[ISL1208_RTC_SECTION_LEN] = { 0, }; |
330 | 330 | ||
331 | /* The clock has an 8 bit wide bcd-coded register (they never learn) | ||
332 | * for the year. tm_year is an offset from 1900 and we are interested | ||
333 | * in the 2000-2099 range, so any value less than 100 is invalid. | ||
334 | */ | ||
335 | if (tm->tm_year < 100) | ||
336 | return -EINVAL; | ||
337 | |||
331 | regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec); | 338 | regs[ISL1208_REG_SC] = bin2bcd(tm->tm_sec); |
332 | regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min); | 339 | regs[ISL1208_REG_MN] = bin2bcd(tm->tm_min); |
333 | regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL; | 340 | regs[ISL1208_REG_HR] = bin2bcd(tm->tm_hour) | ISL1208_REG_HR_MIL; |
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 162cd927d94b..94acbeed4e7c 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c | |||
@@ -175,8 +175,8 @@ static struct aac_driver_ident aac_drivers[] = { | |||
175 | { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Boxster/PERC3DiB) */ | 175 | { aac_rx_init, "percraid", "DELL ", "PERCRAID ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* PERC 3/Di (Boxster/PERC3DiB) */ |
176 | { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* catapult */ | 176 | { aac_rx_init, "aacraid", "ADAPTEC ", "catapult ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* catapult */ |
177 | { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* tomcat */ | 177 | { aac_rx_init, "aacraid", "ADAPTEC ", "tomcat ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* tomcat */ |
178 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2120S (Crusader) */ | 178 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2120S ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2120S (Crusader) */ |
179 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan) */ | 179 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG }, /* Adaptec 2200S (Vulcan) */ |
180 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan-2m) */ | 180 | { aac_rx_init, "aacraid", "ADAPTEC ", "Adaptec 2200S ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Adaptec 2200S (Vulcan-2m) */ |
181 | { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S220 (Legend Crusader) */ | 181 | { aac_rx_init, "aacraid", "Legend ", "Legend S220 ", 1, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S220 (Legend Crusader) */ |
182 | { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S230 (Legend Vulcan) */ | 182 | { aac_rx_init, "aacraid", "Legend ", "Legend S230 ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend S230 (Legend Vulcan) */ |
diff --git a/drivers/scsi/device_handler/scsi_dh_hp_sw.c b/drivers/scsi/device_handler/scsi_dh_hp_sw.c index 9aec4ca64e56..f7da7530875e 100644 --- a/drivers/scsi/device_handler/scsi_dh_hp_sw.c +++ b/drivers/scsi/device_handler/scsi_dh_hp_sw.c | |||
@@ -107,6 +107,7 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
107 | struct request *req; | 107 | struct request *req; |
108 | int ret; | 108 | int ret; |
109 | 109 | ||
110 | retry: | ||
110 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); | 111 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); |
111 | if (!req) | 112 | if (!req) |
112 | return SCSI_DH_RES_TEMP_UNAVAIL; | 113 | return SCSI_DH_RES_TEMP_UNAVAIL; |
@@ -121,7 +122,6 @@ static int hp_sw_tur(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
121 | memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); | 122 | memset(req->sense, 0, SCSI_SENSE_BUFFERSIZE); |
122 | req->sense_len = 0; | 123 | req->sense_len = 0; |
123 | 124 | ||
124 | retry: | ||
125 | ret = blk_execute_rq(req->q, NULL, req, 1); | 125 | ret = blk_execute_rq(req->q, NULL, req, 1); |
126 | if (ret == -EIO) { | 126 | if (ret == -EIO) { |
127 | if (req->sense_len > 0) { | 127 | if (req->sense_len > 0) { |
@@ -136,8 +136,10 @@ retry: | |||
136 | h->path_state = HP_SW_PATH_ACTIVE; | 136 | h->path_state = HP_SW_PATH_ACTIVE; |
137 | ret = SCSI_DH_OK; | 137 | ret = SCSI_DH_OK; |
138 | } | 138 | } |
139 | if (ret == SCSI_DH_IMM_RETRY) | 139 | if (ret == SCSI_DH_IMM_RETRY) { |
140 | blk_put_request(req); | ||
140 | goto retry; | 141 | goto retry; |
142 | } | ||
141 | if (ret == SCSI_DH_DEV_OFFLINED) { | 143 | if (ret == SCSI_DH_DEV_OFFLINED) { |
142 | h->path_state = HP_SW_PATH_PASSIVE; | 144 | h->path_state = HP_SW_PATH_PASSIVE; |
143 | ret = SCSI_DH_OK; | 145 | ret = SCSI_DH_OK; |
@@ -200,6 +202,7 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
200 | struct request *req; | 202 | struct request *req; |
201 | int ret, retry; | 203 | int ret, retry; |
202 | 204 | ||
205 | retry: | ||
203 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); | 206 | req = blk_get_request(sdev->request_queue, WRITE, GFP_NOIO); |
204 | if (!req) | 207 | if (!req) |
205 | return SCSI_DH_RES_TEMP_UNAVAIL; | 208 | return SCSI_DH_RES_TEMP_UNAVAIL; |
@@ -216,7 +219,6 @@ static int hp_sw_start_stop(struct scsi_device *sdev, struct hp_sw_dh_data *h) | |||
216 | req->sense_len = 0; | 219 | req->sense_len = 0; |
217 | retry = h->retries; | 220 | retry = h->retries; |
218 | 221 | ||
219 | retry: | ||
220 | ret = blk_execute_rq(req->q, NULL, req, 1); | 222 | ret = blk_execute_rq(req->q, NULL, req, 1); |
221 | if (ret == -EIO) { | 223 | if (ret == -EIO) { |
222 | if (req->sense_len > 0) { | 224 | if (req->sense_len > 0) { |
@@ -231,8 +233,10 @@ retry: | |||
231 | ret = SCSI_DH_OK; | 233 | ret = SCSI_DH_OK; |
232 | 234 | ||
233 | if (ret == SCSI_DH_RETRY) { | 235 | if (ret == SCSI_DH_RETRY) { |
234 | if (--retry) | 236 | if (--retry) { |
237 | blk_put_request(req); | ||
235 | goto retry; | 238 | goto retry; |
239 | } | ||
236 | ret = SCSI_DH_IO; | 240 | ret = SCSI_DH_IO; |
237 | } | 241 | } |
238 | 242 | ||
diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 2a5b29d12172..e2dd6a45924a 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c | |||
@@ -864,21 +864,23 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) | |||
864 | 864 | ||
865 | INIT_WORK(&vport->crq_work, handle_crq); | 865 | INIT_WORK(&vport->crq_work, handle_crq); |
866 | 866 | ||
867 | err = crq_queue_create(&vport->crq_queue, target); | 867 | err = scsi_add_host(shost, target->dev); |
868 | if (err) | 868 | if (err) |
869 | goto free_srp_target; | 869 | goto free_srp_target; |
870 | 870 | ||
871 | err = scsi_add_host(shost, target->dev); | 871 | err = scsi_tgt_alloc_queue(shost); |
872 | if (err) | 872 | if (err) |
873 | goto destroy_queue; | 873 | goto remove_host; |
874 | 874 | ||
875 | err = scsi_tgt_alloc_queue(shost); | 875 | err = crq_queue_create(&vport->crq_queue, target); |
876 | if (err) | 876 | if (err) |
877 | goto destroy_queue; | 877 | goto free_queue; |
878 | 878 | ||
879 | return 0; | 879 | return 0; |
880 | destroy_queue: | 880 | free_queue: |
881 | crq_queue_destroy(target); | 881 | scsi_tgt_free_queue(shost); |
882 | remove_host: | ||
883 | scsi_remove_host(shost); | ||
882 | free_srp_target: | 884 | free_srp_target: |
883 | srp_target_free(target); | 885 | srp_target_free(target); |
884 | put_host: | 886 | put_host: |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 801c7cf54d2e..3fdee7370ccc 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
@@ -489,12 +489,6 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
489 | if (!__kfifo_get(session->cmdpool.queue, | 489 | if (!__kfifo_get(session->cmdpool.queue, |
490 | (void*)&task, sizeof(void*))) | 490 | (void*)&task, sizeof(void*))) |
491 | return NULL; | 491 | return NULL; |
492 | |||
493 | if ((hdr->opcode == (ISCSI_OP_NOOP_OUT | ISCSI_OP_IMMEDIATE)) && | ||
494 | hdr->ttt == RESERVED_ITT) { | ||
495 | conn->ping_task = task; | ||
496 | conn->last_ping = jiffies; | ||
497 | } | ||
498 | } | 492 | } |
499 | /* | 493 | /* |
500 | * released in complete pdu for task we expect a response for, and | 494 | * released in complete pdu for task we expect a response for, and |
@@ -703,6 +697,11 @@ static void iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) | |||
703 | task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); | 697 | task = __iscsi_conn_send_pdu(conn, (struct iscsi_hdr *)&hdr, NULL, 0); |
704 | if (!task) | 698 | if (!task) |
705 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); | 699 | iscsi_conn_printk(KERN_ERR, conn, "Could not send nopout\n"); |
700 | else if (!rhdr) { | ||
701 | /* only track our nops */ | ||
702 | conn->ping_task = task; | ||
703 | conn->last_ping = jiffies; | ||
704 | } | ||
706 | } | 705 | } |
707 | 706 | ||
708 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | 707 | static int iscsi_handle_reject(struct iscsi_conn *conn, struct iscsi_hdr *hdr, |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index fa45a1a66867..148d3af92aef 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -648,8 +648,8 @@ static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd) | |||
648 | struct request *req = cmd->request; | 648 | struct request *req = cmd->request; |
649 | unsigned long flags; | 649 | unsigned long flags; |
650 | 650 | ||
651 | scsi_unprep_request(req); | ||
652 | spin_lock_irqsave(q->queue_lock, flags); | 651 | spin_lock_irqsave(q->queue_lock, flags); |
652 | scsi_unprep_request(req); | ||
653 | blk_requeue_request(q, req); | 653 | blk_requeue_request(q, req); |
654 | spin_unlock_irqrestore(q->queue_lock, flags); | 654 | spin_unlock_irqrestore(q->queue_lock, flags); |
655 | 655 | ||
diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index d1812d32f47d..63f0de29aa14 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c | |||
@@ -827,7 +827,7 @@ static int __init maple_bus_init(void) | |||
827 | 827 | ||
828 | maple_queue_cache = | 828 | maple_queue_cache = |
829 | kmem_cache_create("maple_queue_cache", 0x400, 0, | 829 | kmem_cache_create("maple_queue_cache", 0x400, 0, |
830 | SLAB_POISON|SLAB_HWCACHE_ALIGN, NULL); | 830 | SLAB_HWCACHE_ALIGN, NULL); |
831 | 831 | ||
832 | if (!maple_queue_cache) | 832 | if (!maple_queue_cache) |
833 | goto cleanup_bothirqs; | 833 | goto cleanup_bothirqs; |
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index c95b286a1239..5d457c96bd7e 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -22,6 +22,8 @@ menuconfig STAGING | |||
22 | If in doubt, say N here. | 22 | If in doubt, say N here. |
23 | 23 | ||
24 | 24 | ||
25 | if STAGING | ||
26 | |||
25 | config STAGING_EXCLUDE_BUILD | 27 | config STAGING_EXCLUDE_BUILD |
26 | bool "Exclude Staging drivers from being built" if STAGING | 28 | bool "Exclude Staging drivers from being built" if STAGING |
27 | default y | 29 | default y |
@@ -62,3 +64,4 @@ source "drivers/staging/at76_usb/Kconfig" | |||
62 | source "drivers/staging/poch/Kconfig" | 64 | source "drivers/staging/poch/Kconfig" |
63 | 65 | ||
64 | endif # !STAGING_EXCLUDE_BUILD | 66 | endif # !STAGING_EXCLUDE_BUILD |
67 | endif # STAGING | ||
diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 8e74657f106c..43a863c5cc43 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c | |||
@@ -51,6 +51,7 @@ static struct usb_device_id usbtmc_devices[] = { | |||
51 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, | 51 | { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, |
52 | { 0, } /* terminating entry */ | 52 | { 0, } /* terminating entry */ |
53 | }; | 53 | }; |
54 | MODULE_DEVICE_TABLE(usb, usbtmc_devices); | ||
54 | 55 | ||
55 | /* | 56 | /* |
56 | * This structure is the capabilities for the device | 57 | * This structure is the capabilities for the device |
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 3d7793d93031..8c081308b0e2 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c | |||
@@ -279,7 +279,9 @@ static int usb_unbind_interface(struct device *dev) | |||
279 | * altsetting means creating new endpoint device entries). | 279 | * altsetting means creating new endpoint device entries). |
280 | * When either of these happens, defer the Set-Interface. | 280 | * When either of these happens, defer the Set-Interface. |
281 | */ | 281 | */ |
282 | if (!error && intf->dev.power.status == DPM_ON) | 282 | if (intf->cur_altsetting->desc.bAlternateSetting == 0) |
283 | ; /* Already in altsetting 0 so skip Set-Interface */ | ||
284 | else if (!error && intf->dev.power.status == DPM_ON) | ||
283 | usb_set_interface(udev, intf->altsetting[0]. | 285 | usb_set_interface(udev, intf->altsetting[0]. |
284 | desc.bInterfaceNumber, 0); | 286 | desc.bInterfaceNumber, 0); |
285 | else | 287 | else |
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 428b5993575a..3a8bb53fc473 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c | |||
@@ -651,6 +651,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
651 | fs_in_desc.bEndpointAddress; | 651 | fs_in_desc.bEndpointAddress; |
652 | hs_out_desc.bEndpointAddress = | 652 | hs_out_desc.bEndpointAddress = |
653 | fs_out_desc.bEndpointAddress; | 653 | fs_out_desc.bEndpointAddress; |
654 | hs_notify_desc.bEndpointAddress = | ||
655 | fs_notify_desc.bEndpointAddress; | ||
654 | 656 | ||
655 | /* copy descriptors, and track endpoint copies */ | 657 | /* copy descriptors, and track endpoint copies */ |
656 | f->hs_descriptors = usb_copy_descriptors(eth_hs_function); | 658 | f->hs_descriptors = usb_copy_descriptors(eth_hs_function); |
@@ -662,6 +664,8 @@ rndis_bind(struct usb_configuration *c, struct usb_function *f) | |||
662 | f->hs_descriptors, &hs_in_desc); | 664 | f->hs_descriptors, &hs_in_desc); |
663 | rndis->hs.out = usb_find_endpoint(eth_hs_function, | 665 | rndis->hs.out = usb_find_endpoint(eth_hs_function, |
664 | f->hs_descriptors, &hs_out_desc); | 666 | f->hs_descriptors, &hs_out_desc); |
667 | rndis->hs.notify = usb_find_endpoint(eth_hs_function, | ||
668 | f->hs_descriptors, &hs_notify_desc); | ||
665 | } | 669 | } |
666 | 670 | ||
667 | rndis->port.open = rndis_open; | 671 | rndis->port.open = rndis_open; |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index aad1359a3eb1..fb6f2933b01b 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -143,6 +143,7 @@ static struct ftdi_sio_quirk ftdi_HE_TIRA1_quirk = { | |||
143 | static struct usb_device_id id_table_combined [] = { | 143 | static struct usb_device_id id_table_combined [] = { |
144 | { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, | 144 | { USB_DEVICE(FTDI_VID, FTDI_AMC232_PID) }, |
145 | { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, | 145 | { USB_DEVICE(FTDI_VID, FTDI_CANUSB_PID) }, |
146 | { USB_DEVICE(FTDI_VID, FTDI_CANDAPTER_PID) }, | ||
146 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, | 147 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_0_PID) }, |
147 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, | 148 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_1_PID) }, |
148 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, | 149 | { USB_DEVICE(FTDI_VID, FTDI_SCS_DEVICE_2_PID) }, |
@@ -166,6 +167,7 @@ static struct usb_device_id id_table_combined [] = { | |||
166 | { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, | 167 | { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, |
167 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, | 168 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, |
168 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, | 169 | { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, |
170 | { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, | ||
169 | { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, | 171 | { USB_DEVICE(FTDI_VID, FTDI_XF_632_PID) }, |
170 | { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, | 172 | { USB_DEVICE(FTDI_VID, FTDI_XF_634_PID) }, |
171 | { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, | 173 | { USB_DEVICE(FTDI_VID, FTDI_XF_547_PID) }, |
diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index 07a3992abad2..373ee09975bb 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h | |||
@@ -40,6 +40,9 @@ | |||
40 | /* AlphaMicro Components AMC-232USB01 device */ | 40 | /* AlphaMicro Components AMC-232USB01 device */ |
41 | #define FTDI_AMC232_PID 0xFF00 /* Product Id */ | 41 | #define FTDI_AMC232_PID 0xFF00 /* Product Id */ |
42 | 42 | ||
43 | /* www.candapter.com Ewert Energy Systems CANdapter device */ | ||
44 | #define FTDI_CANDAPTER_PID 0x9F80 /* Product Id */ | ||
45 | |||
43 | /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ | 46 | /* SCS HF Radio Modems PID's (http://www.scs-ptc.com) */ |
44 | /* the VID is the standard ftdi vid (FTDI_VID) */ | 47 | /* the VID is the standard ftdi vid (FTDI_VID) */ |
45 | #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ | 48 | #define FTDI_SCS_DEVICE_0_PID 0xD010 /* SCS PTC-IIusb */ |
@@ -75,6 +78,9 @@ | |||
75 | /* OpenDCC (www.opendcc.de) product id */ | 78 | /* OpenDCC (www.opendcc.de) product id */ |
76 | #define FTDI_OPENDCC_PID 0xBFD8 | 79 | #define FTDI_OPENDCC_PID 0xBFD8 |
77 | 80 | ||
81 | /* Sprog II (Andrew Crosland's SprogII DCC interface) */ | ||
82 | #define FTDI_SPROG_II 0xF0C8 | ||
83 | |||
78 | /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ | 84 | /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ |
79 | /* they use the ftdi chipset for the USB interface and the vendor id is the same */ | 85 | /* they use the ftdi chipset for the USB interface and the vendor id is the same */ |
80 | #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ | 86 | #define FTDI_XF_632_PID 0xFC08 /* 632: 16x2 Character Display */ |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 491c8857b644..1aed584be5eb 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -91,6 +91,8 @@ static struct usb_device_id id_table [] = { | |||
91 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, | 91 | { USB_DEVICE(WS002IN_VENDOR_ID, WS002IN_PRODUCT_ID) }, |
92 | { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, | 92 | { USB_DEVICE(COREGA_VENDOR_ID, COREGA_PRODUCT_ID) }, |
93 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, | 93 | { USB_DEVICE(YCCABLE_VENDOR_ID, YCCABLE_PRODUCT_ID) }, |
94 | { USB_DEVICE(SUPERIAL_VENDOR_ID, SUPERIAL_PRODUCT_ID) }, | ||
95 | { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, | ||
94 | { } /* Terminating entry */ | 96 | { } /* Terminating entry */ |
95 | }; | 97 | }; |
96 | 98 | ||
diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index a3bd039c78e9..54974f446a8c 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h | |||
@@ -110,3 +110,11 @@ | |||
110 | /* Y.C. Cable U.S.A., Inc - USB to RS-232 */ | 110 | /* Y.C. Cable U.S.A., Inc - USB to RS-232 */ |
111 | #define YCCABLE_VENDOR_ID 0x05ad | 111 | #define YCCABLE_VENDOR_ID 0x05ad |
112 | #define YCCABLE_PRODUCT_ID 0x0fba | 112 | #define YCCABLE_PRODUCT_ID 0x0fba |
113 | |||
114 | /* "Superial" USB - Serial */ | ||
115 | #define SUPERIAL_VENDOR_ID 0x5372 | ||
116 | #define SUPERIAL_PRODUCT_ID 0x2303 | ||
117 | |||
118 | /* Hewlett-Packard LD220-HP POS Pole Display */ | ||
119 | #define HP_VENDOR_ID 0x03f0 | ||
120 | #define HP_LD220_PRODUCT_ID 0x3524 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 31c42d1cae13..01d0c70d60e9 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -16,56 +16,6 @@ | |||
16 | * For questions or problems with this driver, contact Texas Instruments | 16 | * For questions or problems with this driver, contact Texas Instruments |
17 | * technical support, or Al Borchers <alborchers@steinerpoint.com>, or | 17 | * technical support, or Al Borchers <alborchers@steinerpoint.com>, or |
18 | * Peter Berger <pberger@brimson.com>. | 18 | * Peter Berger <pberger@brimson.com>. |
19 | * | ||
20 | * This driver needs this hotplug script in /etc/hotplug/usb/ti_usb_3410_5052 | ||
21 | * or in /etc/hotplug.d/usb/ti_usb_3410_5052.hotplug to set the device | ||
22 | * configuration. | ||
23 | * | ||
24 | * #!/bin/bash | ||
25 | * | ||
26 | * BOOT_CONFIG=1 | ||
27 | * ACTIVE_CONFIG=2 | ||
28 | * | ||
29 | * if [[ "$ACTION" != "add" ]] | ||
30 | * then | ||
31 | * exit | ||
32 | * fi | ||
33 | * | ||
34 | * CONFIG_PATH=/sys${DEVPATH%/?*}/bConfigurationValue | ||
35 | * | ||
36 | * if [[ 0`cat $CONFIG_PATH` -ne $BOOT_CONFIG ]] | ||
37 | * then | ||
38 | * exit | ||
39 | * fi | ||
40 | * | ||
41 | * PRODUCT=${PRODUCT%/?*} # delete version | ||
42 | * VENDOR_ID=`printf "%d" 0x${PRODUCT%/?*}` | ||
43 | * PRODUCT_ID=`printf "%d" 0x${PRODUCT#*?/}` | ||
44 | * | ||
45 | * PARAM_PATH=/sys/module/ti_usb_3410_5052/parameters | ||
46 | * | ||
47 | * function scan() { | ||
48 | * s=$1 | ||
49 | * shift | ||
50 | * for i | ||
51 | * do | ||
52 | * if [[ $s -eq $i ]] | ||
53 | * then | ||
54 | * return 0 | ||
55 | * fi | ||
56 | * done | ||
57 | * return 1 | ||
58 | * } | ||
59 | * | ||
60 | * IFS=$IFS, | ||
61 | * | ||
62 | * if (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_3410` && | ||
63 | * scan $PRODUCT_ID 13328 `cat $PARAM_PATH/product_3410`) || | ||
64 | * (scan $VENDOR_ID 1105 `cat $PARAM_PATH/vendor_5052` && | ||
65 | * scan $PRODUCT_ID 20562 20818 20570 20575 `cat $PARAM_PATH/product_5052`) | ||
66 | * then | ||
67 | * echo $ACTIVE_CONFIG > $CONFIG_PATH | ||
68 | * fi | ||
69 | */ | 19 | */ |
70 | 20 | ||
71 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
@@ -457,9 +407,10 @@ static int ti_startup(struct usb_serial *serial) | |||
457 | goto free_tdev; | 407 | goto free_tdev; |
458 | } | 408 | } |
459 | 409 | ||
460 | /* the second configuration must be set (in sysfs by hotplug script) */ | 410 | /* the second configuration must be set */ |
461 | if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) { | 411 | if (dev->actconfig->desc.bConfigurationValue == TI_BOOT_CONFIG) { |
462 | status = -ENODEV; | 412 | status = usb_driver_set_configuration(dev, TI_ACTIVE_CONFIG); |
413 | status = status ? status : -ENODEV; | ||
463 | goto free_tdev; | 414 | goto free_tdev; |
464 | } | 415 | } |
465 | 416 | ||
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index e61f2bfc64ad..bfcc1fe82518 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -167,8 +167,22 @@ UNUSUAL_DEV( 0x0421, 0x005d, 0x0001, 0x0600, | |||
167 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 167 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
168 | US_FL_FIX_CAPACITY ), | 168 | US_FL_FIX_CAPACITY ), |
169 | 169 | ||
170 | /* Reported by Ozan Sener <themgzzy@gmail.com> */ | ||
171 | UNUSUAL_DEV( 0x0421, 0x0060, 0x0551, 0x0551, | ||
172 | "Nokia", | ||
173 | "3500c", | ||
174 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
175 | US_FL_FIX_CAPACITY ), | ||
176 | |||
177 | /* Reported by CSECSY Laszlo <boobaa@frugalware.org> */ | ||
178 | UNUSUAL_DEV( 0x0421, 0x0063, 0x0001, 0x0601, | ||
179 | "Nokia", | ||
180 | "Nokia 3109c", | ||
181 | US_SC_DEVICE, US_PR_DEVICE, NULL, | ||
182 | US_FL_FIX_CAPACITY ), | ||
183 | |||
170 | /* Patch for Nokia 5310 capacity */ | 184 | /* Patch for Nokia 5310 capacity */ |
171 | UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0591, | 185 | UNUSUAL_DEV( 0x0421, 0x006a, 0x0000, 0x0701, |
172 | "Nokia", | 186 | "Nokia", |
173 | "5310", | 187 | "5310", |
174 | US_SC_DEVICE, US_PR_DEVICE, NULL, | 188 | US_SC_DEVICE, US_PR_DEVICE, NULL, |
diff --git a/drivers/video/aty/radeon_accel.c b/drivers/video/aty/radeon_accel.c index 8da5e5ab8547..a469a3d6edcb 100644 --- a/drivers/video/aty/radeon_accel.c +++ b/drivers/video/aty/radeon_accel.c | |||
@@ -5,61 +5,61 @@ | |||
5 | * --dte | 5 | * --dte |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define FLUSH_CACHE_WORKAROUND 1 | 8 | static void radeon_fixup_offset(struct radeonfb_info *rinfo) |
9 | |||
10 | void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries) | ||
11 | { | 9 | { |
12 | int i; | 10 | u32 local_base; |
11 | |||
12 | /* *** Ugly workaround *** */ | ||
13 | /* | ||
14 | * On some platforms, the video memory is mapped at 0 in radeon chip space | ||
15 | * (like PPCs) by the firmware. X will always move it up so that it's seen | ||
16 | * by the chip to be at the same address as the PCI BAR. | ||
17 | * That means that when switching back from X, there is a mismatch between | ||
18 | * the offsets programmed into the engine. This means that potentially, | ||
19 | * accel operations done before radeonfb has a chance to re-init the engine | ||
20 | * will have incorrect offsets, and potentially trash system memory ! | ||
21 | * | ||
22 | * The correct fix is for fbcon to never call any accel op before the engine | ||
23 | * has properly been re-initialized (by a call to set_var), but this is a | ||
24 | * complex fix. This workaround in the meantime, called before every accel | ||
25 | * operation, makes sure the offsets are in sync. | ||
26 | */ | ||
13 | 27 | ||
14 | for (i=0; i<2000000; i++) { | 28 | radeon_fifo_wait (1); |
15 | rinfo->fifo_free = INREG(RBBM_STATUS) & 0x7f; | 29 | local_base = INREG(MC_FB_LOCATION) << 16; |
16 | if (rinfo->fifo_free >= entries) | 30 | if (local_base == rinfo->fb_local_base) |
17 | return; | 31 | return; |
18 | udelay(10); | ||
19 | } | ||
20 | printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); | ||
21 | /* XXX Todo: attempt to reset the engine */ | ||
22 | } | ||
23 | 32 | ||
24 | static inline void radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) | 33 | rinfo->fb_local_base = local_base; |
25 | { | ||
26 | if (entries <= rinfo->fifo_free) | ||
27 | rinfo->fifo_free -= entries; | ||
28 | else | ||
29 | radeon_fifo_update_and_wait(rinfo, entries); | ||
30 | } | ||
31 | 34 | ||
32 | static inline void radeonfb_set_creg(struct radeonfb_info *rinfo, u32 reg, | 35 | radeon_fifo_wait (3); |
33 | u32 *cache, u32 new_val) | 36 | OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | |
34 | { | 37 | (rinfo->fb_local_base >> 10)); |
35 | if (new_val == *cache) | 38 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
36 | return; | 39 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
37 | *cache = new_val; | ||
38 | radeon_fifo_wait(rinfo, 1); | ||
39 | OUTREG(reg, new_val); | ||
40 | } | 40 | } |
41 | 41 | ||
42 | static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, | 42 | static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, |
43 | const struct fb_fillrect *region) | 43 | const struct fb_fillrect *region) |
44 | { | 44 | { |
45 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, | 45 | radeon_fifo_wait(4); |
46 | rinfo->dp_gui_mc_base | GMC_BRUSH_SOLID_COLOR | ROP3_P); | 46 | |
47 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, | 47 | OUTREG(DP_GUI_MASTER_CNTL, |
48 | DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); | 48 | rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ |
49 | radeonfb_set_creg(rinfo, DP_BRUSH_FRGD_CLR, &rinfo->dp_brush_fg_cache, | 49 | | GMC_BRUSH_SOLID_COLOR |
50 | region->color); | 50 | | ROP3_P); |
51 | 51 | if (radeon_get_dstbpp(rinfo->depth) != DST_8BPP) | |
52 | /* Ensure the dst cache is flushed and the engine idle before | 52 | OUTREG(DP_BRUSH_FRGD_CLR, rinfo->pseudo_palette[region->color]); |
53 | * issuing the operation. | 53 | else |
54 | * | 54 | OUTREG(DP_BRUSH_FRGD_CLR, region->color); |
55 | * This works around engine lockups on some cards | 55 | OUTREG(DP_WRITE_MSK, 0xffffffff); |
56 | */ | 56 | OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); |
57 | #if FLUSH_CACHE_WORKAROUND | 57 | |
58 | radeon_fifo_wait(rinfo, 2); | 58 | radeon_fifo_wait(2); |
59 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | 59 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); |
60 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | 60 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); |
61 | #endif | 61 | |
62 | radeon_fifo_wait(rinfo, 2); | 62 | radeon_fifo_wait(2); |
63 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); | 63 | OUTREG(DST_Y_X, (region->dy << 16) | region->dx); |
64 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); | 64 | OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); |
65 | } | 65 | } |
@@ -70,14 +70,15 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) | |||
70 | struct fb_fillrect modded; | 70 | struct fb_fillrect modded; |
71 | int vxres, vyres; | 71 | int vxres, vyres; |
72 | 72 | ||
73 | WARN_ON(rinfo->gfx_mode); | 73 | if (info->state != FBINFO_STATE_RUNNING) |
74 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
75 | return; | 74 | return; |
76 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 75 | if (info->flags & FBINFO_HWACCEL_DISABLED) { |
77 | cfb_fillrect(info, region); | 76 | cfb_fillrect(info, region); |
78 | return; | 77 | return; |
79 | } | 78 | } |
80 | 79 | ||
80 | radeon_fixup_offset(rinfo); | ||
81 | |||
81 | vxres = info->var.xres_virtual; | 82 | vxres = info->var.xres_virtual; |
82 | vyres = info->var.yres_virtual; | 83 | vyres = info->var.yres_virtual; |
83 | 84 | ||
@@ -90,10 +91,6 @@ void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) | |||
90 | if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; | 91 | if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; |
91 | if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; | 92 | if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; |
92 | 93 | ||
93 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
94 | info->fix.visual == FB_VISUAL_DIRECTCOLOR ) | ||
95 | modded.color = ((u32 *) (info->pseudo_palette))[region->color]; | ||
96 | |||
97 | radeonfb_prim_fillrect(rinfo, &modded); | 94 | radeonfb_prim_fillrect(rinfo, &modded); |
98 | } | 95 | } |
99 | 96 | ||
@@ -112,22 +109,22 @@ static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, | |||
112 | if ( xdir < 0 ) { sx += w-1; dx += w-1; } | 109 | if ( xdir < 0 ) { sx += w-1; dx += w-1; } |
113 | if ( ydir < 0 ) { sy += h-1; dy += h-1; } | 110 | if ( ydir < 0 ) { sy += h-1; dy += h-1; } |
114 | 111 | ||
115 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, | 112 | radeon_fifo_wait(3); |
116 | rinfo->dp_gui_mc_base | | 113 | OUTREG(DP_GUI_MASTER_CNTL, |
117 | GMC_BRUSH_NONE | | 114 | rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ |
118 | GMC_SRC_DATATYPE_COLOR | | 115 | | GMC_BRUSH_NONE |
119 | ROP3_S | | 116 | | GMC_SRC_DSTCOLOR |
120 | DP_SRC_SOURCE_MEMORY); | 117 | | ROP3_S |
121 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, | 118 | | DP_SRC_SOURCE_MEMORY ); |
122 | (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) | | 119 | OUTREG(DP_WRITE_MSK, 0xffffffff); |
123 | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); | 120 | OUTREG(DP_CNTL, (xdir>=0 ? DST_X_LEFT_TO_RIGHT : 0) |
124 | 121 | | (ydir>=0 ? DST_Y_TOP_TO_BOTTOM : 0)); | |
125 | #if FLUSH_CACHE_WORKAROUND | 122 | |
126 | radeon_fifo_wait(rinfo, 2); | 123 | radeon_fifo_wait(2); |
127 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | 124 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); |
128 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | 125 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); |
129 | #endif | 126 | |
130 | radeon_fifo_wait(rinfo, 3); | 127 | radeon_fifo_wait(3); |
131 | OUTREG(SRC_Y_X, (sy << 16) | sx); | 128 | OUTREG(SRC_Y_X, (sy << 16) | sx); |
132 | OUTREG(DST_Y_X, (dy << 16) | dx); | 129 | OUTREG(DST_Y_X, (dy << 16) | dx); |
133 | OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); | 130 | OUTREG(DST_HEIGHT_WIDTH, (h << 16) | w); |
@@ -146,14 +143,15 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | |||
146 | modded.width = area->width; | 143 | modded.width = area->width; |
147 | modded.height = area->height; | 144 | modded.height = area->height; |
148 | 145 | ||
149 | WARN_ON(rinfo->gfx_mode); | 146 | if (info->state != FBINFO_STATE_RUNNING) |
150 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
151 | return; | 147 | return; |
152 | if (info->flags & FBINFO_HWACCEL_DISABLED) { | 148 | if (info->flags & FBINFO_HWACCEL_DISABLED) { |
153 | cfb_copyarea(info, area); | 149 | cfb_copyarea(info, area); |
154 | return; | 150 | return; |
155 | } | 151 | } |
156 | 152 | ||
153 | radeon_fixup_offset(rinfo); | ||
154 | |||
157 | vxres = info->var.xres_virtual; | 155 | vxres = info->var.xres_virtual; |
158 | vyres = info->var.yres_virtual; | 156 | vyres = info->var.yres_virtual; |
159 | 157 | ||
@@ -170,116 +168,13 @@ void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) | |||
170 | radeonfb_prim_copyarea(rinfo, &modded); | 168 | radeonfb_prim_copyarea(rinfo, &modded); |
171 | } | 169 | } |
172 | 170 | ||
173 | static void radeonfb_prim_imageblit(struct radeonfb_info *rinfo, | ||
174 | const struct fb_image *image, | ||
175 | u32 fg, u32 bg) | ||
176 | { | ||
177 | unsigned int dwords; | ||
178 | u32 *bits; | ||
179 | |||
180 | radeonfb_set_creg(rinfo, DP_GUI_MASTER_CNTL, &rinfo->dp_gui_mc_cache, | ||
181 | rinfo->dp_gui_mc_base | | ||
182 | GMC_BRUSH_NONE | GMC_DST_CLIP_LEAVE | | ||
183 | GMC_SRC_DATATYPE_MONO_FG_BG | | ||
184 | ROP3_S | | ||
185 | GMC_BYTE_ORDER_MSB_TO_LSB | | ||
186 | DP_SRC_SOURCE_HOST_DATA); | ||
187 | radeonfb_set_creg(rinfo, DP_CNTL, &rinfo->dp_cntl_cache, | ||
188 | DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM); | ||
189 | radeonfb_set_creg(rinfo, DP_SRC_FRGD_CLR, &rinfo->dp_src_fg_cache, fg); | ||
190 | radeonfb_set_creg(rinfo, DP_SRC_BKGD_CLR, &rinfo->dp_src_bg_cache, bg); | ||
191 | |||
192 | /* Ensure the dst cache is flushed and the engine idle before | ||
193 | * issuing the operation. | ||
194 | * | ||
195 | * This works around engine lockups on some cards | ||
196 | */ | ||
197 | #if FLUSH_CACHE_WORKAROUND | ||
198 | radeon_fifo_wait(rinfo, 2); | ||
199 | OUTREG(DSTCACHE_CTLSTAT, RB2D_DC_FLUSH_ALL); | ||
200 | OUTREG(WAIT_UNTIL, (WAIT_2D_IDLECLEAN | WAIT_DMA_GUI_IDLE)); | ||
201 | #endif | ||
202 | |||
203 | /* X here pads width to a multiple of 32 and uses the clipper to | ||
204 | * adjust the result. Is that really necessary ? Things seem to | ||
205 | * work ok for me without that and the doco doesn't seem to imply] | ||
206 | * there is such a restriction. | ||
207 | */ | ||
208 | radeon_fifo_wait(rinfo, 4); | ||
209 | OUTREG(SC_TOP_LEFT, (image->dy << 16) | image->dx); | ||
210 | OUTREG(SC_BOTTOM_RIGHT, ((image->dy + image->height) << 16) | | ||
211 | (image->dx + image->width)); | ||
212 | OUTREG(DST_Y_X, (image->dy << 16) | image->dx); | ||
213 | |||
214 | OUTREG(DST_HEIGHT_WIDTH, (image->height << 16) | ((image->width + 31) & ~31)); | ||
215 | |||
216 | dwords = (image->width + 31) >> 5; | ||
217 | dwords *= image->height; | ||
218 | bits = (u32*)(image->data); | ||
219 | |||
220 | while(dwords >= 8) { | ||
221 | radeon_fifo_wait(rinfo, 8); | ||
222 | #if BITS_PER_LONG == 64 | ||
223 | __raw_writeq(*((u64 *)(bits)), rinfo->mmio_base + HOST_DATA0); | ||
224 | __raw_writeq(*((u64 *)(bits+2)), rinfo->mmio_base + HOST_DATA2); | ||
225 | __raw_writeq(*((u64 *)(bits+4)), rinfo->mmio_base + HOST_DATA4); | ||
226 | __raw_writeq(*((u64 *)(bits+6)), rinfo->mmio_base + HOST_DATA6); | ||
227 | bits += 8; | ||
228 | #else | ||
229 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); | ||
230 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA1); | ||
231 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA2); | ||
232 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA3); | ||
233 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA4); | ||
234 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA5); | ||
235 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA6); | ||
236 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA7); | ||
237 | #endif | ||
238 | dwords -= 8; | ||
239 | } | ||
240 | while(dwords--) { | ||
241 | radeon_fifo_wait(rinfo, 1); | ||
242 | __raw_writel(*(bits++), rinfo->mmio_base + HOST_DATA0); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) | 171 | void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) |
247 | { | 172 | { |
248 | struct radeonfb_info *rinfo = info->par; | 173 | struct radeonfb_info *rinfo = info->par; |
249 | u32 fg, bg; | ||
250 | 174 | ||
251 | WARN_ON(rinfo->gfx_mode); | 175 | if (info->state != FBINFO_STATE_RUNNING) |
252 | if (info->state != FBINFO_STATE_RUNNING || rinfo->gfx_mode) | ||
253 | return; | ||
254 | |||
255 | if (!image->width || !image->height) | ||
256 | return; | 176 | return; |
257 | 177 | radeon_engine_idle(); | |
258 | /* We only do 1 bpp color expansion for now */ | ||
259 | if (!accel_cexp || | ||
260 | (info->flags & FBINFO_HWACCEL_DISABLED) || image->depth != 1) | ||
261 | goto fallback; | ||
262 | |||
263 | /* Fallback if running out of the screen. We may do clipping | ||
264 | * in the future */ | ||
265 | if ((image->dx + image->width) > info->var.xres_virtual || | ||
266 | (image->dy + image->height) > info->var.yres_virtual) | ||
267 | goto fallback; | ||
268 | |||
269 | if (info->fix.visual == FB_VISUAL_TRUECOLOR || | ||
270 | info->fix.visual == FB_VISUAL_DIRECTCOLOR) { | ||
271 | fg = ((u32*)(info->pseudo_palette))[image->fg_color]; | ||
272 | bg = ((u32*)(info->pseudo_palette))[image->bg_color]; | ||
273 | } else { | ||
274 | fg = image->fg_color; | ||
275 | bg = image->bg_color; | ||
276 | } | ||
277 | |||
278 | radeonfb_prim_imageblit(rinfo, image, fg, bg); | ||
279 | return; | ||
280 | |||
281 | fallback: | ||
282 | radeon_engine_idle(rinfo); | ||
283 | 178 | ||
284 | cfb_imageblit(info, image); | 179 | cfb_imageblit(info, image); |
285 | } | 180 | } |
@@ -290,8 +185,7 @@ int radeonfb_sync(struct fb_info *info) | |||
290 | 185 | ||
291 | if (info->state != FBINFO_STATE_RUNNING) | 186 | if (info->state != FBINFO_STATE_RUNNING) |
292 | return 0; | 187 | return 0; |
293 | 188 | radeon_engine_idle(); | |
294 | radeon_engine_idle(rinfo); | ||
295 | 189 | ||
296 | return 0; | 190 | return 0; |
297 | } | 191 | } |
@@ -367,10 +261,9 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) | |||
367 | /* disable 3D engine */ | 261 | /* disable 3D engine */ |
368 | OUTREG(RB3D_CNTL, 0); | 262 | OUTREG(RB3D_CNTL, 0); |
369 | 263 | ||
370 | rinfo->fifo_free = 0; | ||
371 | radeonfb_engine_reset(rinfo); | 264 | radeonfb_engine_reset(rinfo); |
372 | 265 | ||
373 | radeon_fifo_wait(rinfo, 1); | 266 | radeon_fifo_wait (1); |
374 | if (IS_R300_VARIANT(rinfo)) { | 267 | if (IS_R300_VARIANT(rinfo)) { |
375 | OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) | | 268 | OUTREG(RB2D_DSTCACHE_MODE, INREG(RB2D_DSTCACHE_MODE) | |
376 | RB2D_DC_AUTOFLUSH_ENABLE | | 269 | RB2D_DC_AUTOFLUSH_ENABLE | |
@@ -384,7 +277,7 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) | |||
384 | OUTREG(RB2D_DSTCACHE_MODE, 0); | 277 | OUTREG(RB2D_DSTCACHE_MODE, 0); |
385 | } | 278 | } |
386 | 279 | ||
387 | radeon_fifo_wait(rinfo, 3); | 280 | radeon_fifo_wait (3); |
388 | /* We re-read MC_FB_LOCATION from card as it can have been | 281 | /* We re-read MC_FB_LOCATION from card as it can have been |
389 | * modified by XFree drivers (ouch !) | 282 | * modified by XFree drivers (ouch !) |
390 | */ | 283 | */ |
@@ -395,57 +288,41 @@ void radeonfb_engine_init (struct radeonfb_info *rinfo) | |||
395 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 288 | OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
396 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); | 289 | OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); |
397 | 290 | ||
398 | radeon_fifo_wait(rinfo, 1); | 291 | radeon_fifo_wait (1); |
399 | #ifdef __BIG_ENDIAN | 292 | #if defined(__BIG_ENDIAN) |
400 | OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); | 293 | OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); |
401 | #else | 294 | #else |
402 | OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); | 295 | OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); |
403 | #endif | 296 | #endif |
404 | radeon_fifo_wait(rinfo, 2); | 297 | radeon_fifo_wait (2); |
405 | OUTREG(DEFAULT_SC_TOP_LEFT, 0); | 298 | OUTREG(DEFAULT_SC_TOP_LEFT, 0); |
406 | OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | | 299 | OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | |
407 | DEFAULT_SC_BOTTOM_MAX)); | 300 | DEFAULT_SC_BOTTOM_MAX)); |
408 | 301 | ||
409 | /* set default DP_GUI_MASTER_CNTL */ | ||
410 | temp = radeon_get_dstbpp(rinfo->depth); | 302 | temp = radeon_get_dstbpp(rinfo->depth); |
411 | rinfo->dp_gui_mc_base = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); | 303 | rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); |
412 | 304 | ||
413 | rinfo->dp_gui_mc_cache = rinfo->dp_gui_mc_base | | 305 | radeon_fifo_wait (1); |
414 | GMC_BRUSH_SOLID_COLOR | | 306 | OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | |
415 | GMC_SRC_DATATYPE_COLOR; | 307 | GMC_BRUSH_SOLID_COLOR | |
416 | radeon_fifo_wait(rinfo, 1); | 308 | GMC_SRC_DATATYPE_COLOR)); |
417 | OUTREG(DP_GUI_MASTER_CNTL, rinfo->dp_gui_mc_cache); | ||
418 | 309 | ||
310 | radeon_fifo_wait (7); | ||
419 | 311 | ||
420 | /* clear line drawing regs */ | 312 | /* clear line drawing regs */ |
421 | radeon_fifo_wait(rinfo, 2); | ||
422 | OUTREG(DST_LINE_START, 0); | 313 | OUTREG(DST_LINE_START, 0); |
423 | OUTREG(DST_LINE_END, 0); | 314 | OUTREG(DST_LINE_END, 0); |
424 | 315 | ||
425 | /* set brush and source color regs */ | 316 | /* set brush color regs */ |
426 | rinfo->dp_brush_fg_cache = 0xffffffff; | 317 | OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); |
427 | rinfo->dp_brush_bg_cache = 0x00000000; | 318 | OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); |
428 | rinfo->dp_src_fg_cache = 0xffffffff; | 319 | |
429 | rinfo->dp_src_bg_cache = 0x00000000; | 320 | /* set source color regs */ |
430 | radeon_fifo_wait(rinfo, 4); | 321 | OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); |
431 | OUTREG(DP_BRUSH_FRGD_CLR, rinfo->dp_brush_fg_cache); | 322 | OUTREG(DP_SRC_BKGD_CLR, 0x00000000); |
432 | OUTREG(DP_BRUSH_BKGD_CLR, rinfo->dp_brush_bg_cache); | ||
433 | OUTREG(DP_SRC_FRGD_CLR, rinfo->dp_src_fg_cache); | ||
434 | OUTREG(DP_SRC_BKGD_CLR, rinfo->dp_src_bg_cache); | ||
435 | |||
436 | /* Default direction */ | ||
437 | rinfo->dp_cntl_cache = DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM; | ||
438 | radeon_fifo_wait(rinfo, 1); | ||
439 | OUTREG(DP_CNTL, rinfo->dp_cntl_cache); | ||
440 | 323 | ||
441 | /* default write mask */ | 324 | /* default write mask */ |
442 | radeon_fifo_wait(rinfo, 1); | ||
443 | OUTREG(DP_WRITE_MSK, 0xffffffff); | 325 | OUTREG(DP_WRITE_MSK, 0xffffffff); |
444 | 326 | ||
445 | /* Default to no swapping of host data */ | 327 | radeon_engine_idle (); |
446 | radeon_fifo_wait(rinfo, 1); | ||
447 | OUTREG(RBBM_GUICNTL, RBBM_GUICNTL_HOST_DATA_SWAP_NONE); | ||
448 | |||
449 | /* Make sure it's settled */ | ||
450 | radeon_engine_idle(rinfo); | ||
451 | } | 328 | } |
diff --git a/drivers/video/aty/radeon_backlight.c b/drivers/video/aty/radeon_backlight.c index f343ba83f0ae..1a056adb61c8 100644 --- a/drivers/video/aty/radeon_backlight.c +++ b/drivers/video/aty/radeon_backlight.c | |||
@@ -66,7 +66,7 @@ static int radeon_bl_update_status(struct backlight_device *bd) | |||
66 | level = bd->props.brightness; | 66 | level = bd->props.brightness; |
67 | 67 | ||
68 | del_timer_sync(&rinfo->lvds_timer); | 68 | del_timer_sync(&rinfo->lvds_timer); |
69 | radeon_engine_idle(rinfo); | 69 | radeon_engine_idle(); |
70 | 70 | ||
71 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); | 71 | lvds_gen_cntl = INREG(LVDS_GEN_CNTL); |
72 | if (level > 0) { | 72 | if (level > 0) { |
diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index d5b27f9d374d..d0f1a7fc2c9d 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c | |||
@@ -282,8 +282,6 @@ static int backlight = 1; | |||
282 | static int backlight = 0; | 282 | static int backlight = 0; |
283 | #endif | 283 | #endif |
284 | 284 | ||
285 | int accel_cexp = 0; | ||
286 | |||
287 | /* | 285 | /* |
288 | * prototypes | 286 | * prototypes |
289 | */ | 287 | */ |
@@ -854,6 +852,7 @@ static int radeonfb_pan_display (struct fb_var_screeninfo *var, | |||
854 | if (rinfo->asleep) | 852 | if (rinfo->asleep) |
855 | return 0; | 853 | return 0; |
856 | 854 | ||
855 | radeon_fifo_wait(2); | ||
857 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) | 856 | OUTREG(CRTC_OFFSET, ((var->yoffset * var->xres_virtual + var->xoffset) |
858 | * var->bits_per_pixel / 8) & ~7); | 857 | * var->bits_per_pixel / 8) & ~7); |
859 | return 0; | 858 | return 0; |
@@ -883,6 +882,7 @@ static int radeonfb_ioctl (struct fb_info *info, unsigned int cmd, | |||
883 | if (rc) | 882 | if (rc) |
884 | return rc; | 883 | return rc; |
885 | 884 | ||
885 | radeon_fifo_wait(2); | ||
886 | if (value & 0x01) { | 886 | if (value & 0x01) { |
887 | tmp = INREG(LVDS_GEN_CNTL); | 887 | tmp = INREG(LVDS_GEN_CNTL); |
888 | 888 | ||
@@ -940,7 +940,7 @@ int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch) | |||
940 | if (rinfo->lock_blank) | 940 | if (rinfo->lock_blank) |
941 | return 0; | 941 | return 0; |
942 | 942 | ||
943 | radeon_engine_idle(rinfo); | 943 | radeon_engine_idle(); |
944 | 944 | ||
945 | val = INREG(CRTC_EXT_CNTL); | 945 | val = INREG(CRTC_EXT_CNTL); |
946 | val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | | 946 | val &= ~(CRTC_DISPLAY_DIS | CRTC_HSYNC_DIS | |
@@ -1048,7 +1048,7 @@ static int radeonfb_blank (int blank, struct fb_info *info) | |||
1048 | 1048 | ||
1049 | if (rinfo->asleep) | 1049 | if (rinfo->asleep) |
1050 | return 0; | 1050 | return 0; |
1051 | 1051 | ||
1052 | return radeon_screen_blank(rinfo, blank, 0); | 1052 | return radeon_screen_blank(rinfo, blank, 0); |
1053 | } | 1053 | } |
1054 | 1054 | ||
@@ -1074,6 +1074,8 @@ static int radeon_setcolreg (unsigned regno, unsigned red, unsigned green, | |||
1074 | pindex = regno; | 1074 | pindex = regno; |
1075 | 1075 | ||
1076 | if (!rinfo->asleep) { | 1076 | if (!rinfo->asleep) { |
1077 | radeon_fifo_wait(9); | ||
1078 | |||
1077 | if (rinfo->bpp == 16) { | 1079 | if (rinfo->bpp == 16) { |
1078 | pindex = regno * 8; | 1080 | pindex = regno * 8; |
1079 | 1081 | ||
@@ -1242,6 +1244,8 @@ static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_reg | |||
1242 | { | 1244 | { |
1243 | int i; | 1245 | int i; |
1244 | 1246 | ||
1247 | radeon_fifo_wait(20); | ||
1248 | |||
1245 | /* Workaround from XFree */ | 1249 | /* Workaround from XFree */ |
1246 | if (rinfo->is_mobility) { | 1250 | if (rinfo->is_mobility) { |
1247 | /* A temporal workaround for the occational blanking on certain laptop | 1251 | /* A temporal workaround for the occational blanking on certain laptop |
@@ -1337,7 +1341,7 @@ static void radeon_lvds_timer_func(unsigned long data) | |||
1337 | { | 1341 | { |
1338 | struct radeonfb_info *rinfo = (struct radeonfb_info *)data; | 1342 | struct radeonfb_info *rinfo = (struct radeonfb_info *)data; |
1339 | 1343 | ||
1340 | radeon_engine_idle(rinfo); | 1344 | radeon_engine_idle(); |
1341 | 1345 | ||
1342 | OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); | 1346 | OUTREG(LVDS_GEN_CNTL, rinfo->pending_lvds_gen_cntl); |
1343 | } | 1347 | } |
@@ -1355,11 +1359,10 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1355 | if (nomodeset) | 1359 | if (nomodeset) |
1356 | return; | 1360 | return; |
1357 | 1361 | ||
1358 | radeon_engine_idle(rinfo); | ||
1359 | |||
1360 | if (!regs_only) | 1362 | if (!regs_only) |
1361 | radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); | 1363 | radeon_screen_blank(rinfo, FB_BLANK_NORMAL, 0); |
1362 | 1364 | ||
1365 | radeon_fifo_wait(31); | ||
1363 | for (i=0; i<10; i++) | 1366 | for (i=0; i<10; i++) |
1364 | OUTREG(common_regs[i].reg, common_regs[i].val); | 1367 | OUTREG(common_regs[i].reg, common_regs[i].val); |
1365 | 1368 | ||
@@ -1387,6 +1390,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1387 | radeon_write_pll_regs(rinfo, mode); | 1390 | radeon_write_pll_regs(rinfo, mode); |
1388 | 1391 | ||
1389 | if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { | 1392 | if ((primary_mon == MT_DFP) || (primary_mon == MT_LCD)) { |
1393 | radeon_fifo_wait(10); | ||
1390 | OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); | 1394 | OUTREG(FP_CRTC_H_TOTAL_DISP, mode->fp_crtc_h_total_disp); |
1391 | OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); | 1395 | OUTREG(FP_CRTC_V_TOTAL_DISP, mode->fp_crtc_v_total_disp); |
1392 | OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); | 1396 | OUTREG(FP_H_SYNC_STRT_WID, mode->fp_h_sync_strt_wid); |
@@ -1401,6 +1405,7 @@ void radeon_write_mode (struct radeonfb_info *rinfo, struct radeon_regs *mode, | |||
1401 | if (!regs_only) | 1405 | if (!regs_only) |
1402 | radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); | 1406 | radeon_screen_blank(rinfo, FB_BLANK_UNBLANK, 0); |
1403 | 1407 | ||
1408 | radeon_fifo_wait(2); | ||
1404 | OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); | 1409 | OUTPLL(VCLK_ECP_CNTL, mode->vclk_ecp_cntl); |
1405 | 1410 | ||
1406 | return; | 1411 | return; |
@@ -1551,7 +1556,7 @@ static int radeonfb_set_par(struct fb_info *info) | |||
1551 | /* We always want engine to be idle on a mode switch, even | 1556 | /* We always want engine to be idle on a mode switch, even |
1552 | * if we won't actually change the mode | 1557 | * if we won't actually change the mode |
1553 | */ | 1558 | */ |
1554 | radeon_engine_idle(rinfo); | 1559 | radeon_engine_idle(); |
1555 | 1560 | ||
1556 | hSyncStart = mode->xres + mode->right_margin; | 1561 | hSyncStart = mode->xres + mode->right_margin; |
1557 | hSyncEnd = hSyncStart + mode->hsync_len; | 1562 | hSyncEnd = hSyncStart + mode->hsync_len; |
@@ -1846,6 +1851,7 @@ static int radeonfb_set_par(struct fb_info *info) | |||
1846 | return 0; | 1851 | return 0; |
1847 | } | 1852 | } |
1848 | 1853 | ||
1854 | |||
1849 | static struct fb_ops radeonfb_ops = { | 1855 | static struct fb_ops radeonfb_ops = { |
1850 | .owner = THIS_MODULE, | 1856 | .owner = THIS_MODULE, |
1851 | .fb_check_var = radeonfb_check_var, | 1857 | .fb_check_var = radeonfb_check_var, |
@@ -1869,7 +1875,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |||
1869 | info->par = rinfo; | 1875 | info->par = rinfo; |
1870 | info->pseudo_palette = rinfo->pseudo_palette; | 1876 | info->pseudo_palette = rinfo->pseudo_palette; |
1871 | info->flags = FBINFO_DEFAULT | 1877 | info->flags = FBINFO_DEFAULT |
1872 | | FBINFO_HWACCEL_IMAGEBLIT | ||
1873 | | FBINFO_HWACCEL_COPYAREA | 1878 | | FBINFO_HWACCEL_COPYAREA |
1874 | | FBINFO_HWACCEL_FILLRECT | 1879 | | FBINFO_HWACCEL_FILLRECT |
1875 | | FBINFO_HWACCEL_XPAN | 1880 | | FBINFO_HWACCEL_XPAN |
@@ -1877,7 +1882,6 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |||
1877 | info->fbops = &radeonfb_ops; | 1882 | info->fbops = &radeonfb_ops; |
1878 | info->screen_base = rinfo->fb_base; | 1883 | info->screen_base = rinfo->fb_base; |
1879 | info->screen_size = rinfo->mapped_vram; | 1884 | info->screen_size = rinfo->mapped_vram; |
1880 | |||
1881 | /* Fill fix common fields */ | 1885 | /* Fill fix common fields */ |
1882 | strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); | 1886 | strlcpy(info->fix.id, rinfo->name, sizeof(info->fix.id)); |
1883 | info->fix.smem_start = rinfo->fb_base_phys; | 1887 | info->fix.smem_start = rinfo->fb_base_phys; |
@@ -1892,25 +1896,8 @@ static int __devinit radeon_set_fbinfo (struct radeonfb_info *rinfo) | |||
1892 | info->fix.mmio_len = RADEON_REGSIZE; | 1896 | info->fix.mmio_len = RADEON_REGSIZE; |
1893 | info->fix.accel = FB_ACCEL_ATI_RADEON; | 1897 | info->fix.accel = FB_ACCEL_ATI_RADEON; |
1894 | 1898 | ||
1895 | /* Allocate colormap */ | ||
1896 | fb_alloc_cmap(&info->cmap, 256, 0); | 1899 | fb_alloc_cmap(&info->cmap, 256, 0); |
1897 | 1900 | ||
1898 | /* Setup pixmap used for acceleration */ | ||
1899 | #define PIXMAP_SIZE (2048 * 4) | ||
1900 | |||
1901 | info->pixmap.addr = kmalloc(PIXMAP_SIZE, GFP_KERNEL); | ||
1902 | if (!info->pixmap.addr) { | ||
1903 | printk(KERN_ERR "radeonfb: Failed to allocate pixmap !\n"); | ||
1904 | noaccel = 1; | ||
1905 | goto bail; | ||
1906 | } | ||
1907 | info->pixmap.size = PIXMAP_SIZE; | ||
1908 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
1909 | info->pixmap.scan_align = 4; | ||
1910 | info->pixmap.buf_align = 4; | ||
1911 | info->pixmap.access_align = 32; | ||
1912 | |||
1913 | bail: | ||
1914 | if (noaccel) | 1901 | if (noaccel) |
1915 | info->flags |= FBINFO_HWACCEL_DISABLED; | 1902 | info->flags |= FBINFO_HWACCEL_DISABLED; |
1916 | 1903 | ||
@@ -2019,6 +2006,7 @@ static void radeon_identify_vram(struct radeonfb_info *rinfo) | |||
2019 | u32 tom = INREG(NB_TOM); | 2006 | u32 tom = INREG(NB_TOM); |
2020 | tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); | 2007 | tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024); |
2021 | 2008 | ||
2009 | radeon_fifo_wait(6); | ||
2022 | OUTREG(MC_FB_LOCATION, tom); | 2010 | OUTREG(MC_FB_LOCATION, tom); |
2023 | OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); | 2011 | OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); |
2024 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); | 2012 | OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16); |
@@ -2522,8 +2510,6 @@ static int __init radeonfb_setup (char *options) | |||
2522 | } else if (!strncmp(this_opt, "ignore_devlist", 14)) { | 2510 | } else if (!strncmp(this_opt, "ignore_devlist", 14)) { |
2523 | ignore_devlist = 1; | 2511 | ignore_devlist = 1; |
2524 | #endif | 2512 | #endif |
2525 | } else if (!strncmp(this_opt, "accel_cexp", 12)) { | ||
2526 | accel_cexp = 1; | ||
2527 | } else | 2513 | } else |
2528 | mode_option = this_opt; | 2514 | mode_option = this_opt; |
2529 | } | 2515 | } |
@@ -2571,8 +2557,6 @@ module_param(monitor_layout, charp, 0); | |||
2571 | MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); | 2557 | MODULE_PARM_DESC(monitor_layout, "Specify monitor mapping (like XFree86)"); |
2572 | module_param(force_measure_pll, bool, 0); | 2558 | module_param(force_measure_pll, bool, 0); |
2573 | MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); | 2559 | MODULE_PARM_DESC(force_measure_pll, "Force measurement of PLL (debug)"); |
2574 | module_param(accel_cexp, bool, 0); | ||
2575 | MODULE_PARM_DESC(accel_cexp, "Use acceleration engine for color expansion"); | ||
2576 | #ifdef CONFIG_MTRR | 2560 | #ifdef CONFIG_MTRR |
2577 | module_param(nomtrr, bool, 0); | 2561 | module_param(nomtrr, bool, 0); |
2578 | MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); | 2562 | MODULE_PARM_DESC(nomtrr, "bool: disable use of MTRR registers"); |
diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 3df5015f1d13..675abdafc2d8 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c | |||
@@ -2653,9 +2653,9 @@ int radeonfb_pci_suspend(struct pci_dev *pdev, pm_message_t mesg) | |||
2653 | 2653 | ||
2654 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { | 2654 | if (!(info->flags & FBINFO_HWACCEL_DISABLED)) { |
2655 | /* Make sure engine is reset */ | 2655 | /* Make sure engine is reset */ |
2656 | radeon_engine_idle(rinfo); | 2656 | radeon_engine_idle(); |
2657 | radeonfb_engine_reset(rinfo); | 2657 | radeonfb_engine_reset(rinfo); |
2658 | radeon_engine_idle(rinfo); | 2658 | radeon_engine_idle(); |
2659 | } | 2659 | } |
2660 | 2660 | ||
2661 | /* Blank display and LCD */ | 2661 | /* Blank display and LCD */ |
@@ -2767,7 +2767,7 @@ int radeonfb_pci_resume(struct pci_dev *pdev) | |||
2767 | 2767 | ||
2768 | rinfo->asleep = 0; | 2768 | rinfo->asleep = 0; |
2769 | } else | 2769 | } else |
2770 | radeon_engine_idle(rinfo); | 2770 | radeon_engine_idle(); |
2771 | 2771 | ||
2772 | /* Restore display & engine */ | 2772 | /* Restore display & engine */ |
2773 | radeon_write_mode (rinfo, &rinfo->state, 1); | 2773 | radeon_write_mode (rinfo, &rinfo->state, 1); |
diff --git a/drivers/video/aty/radeonfb.h b/drivers/video/aty/radeonfb.h index 974ca6d86540..3ea1b00fdd22 100644 --- a/drivers/video/aty/radeonfb.h +++ b/drivers/video/aty/radeonfb.h | |||
@@ -336,15 +336,7 @@ struct radeonfb_info { | |||
336 | int mon2_type; | 336 | int mon2_type; |
337 | u8 *mon2_EDID; | 337 | u8 *mon2_EDID; |
338 | 338 | ||
339 | /* accel bits */ | 339 | u32 dp_gui_master_cntl; |
340 | u32 dp_gui_mc_base; | ||
341 | u32 dp_gui_mc_cache; | ||
342 | u32 dp_cntl_cache; | ||
343 | u32 dp_brush_fg_cache; | ||
344 | u32 dp_brush_bg_cache; | ||
345 | u32 dp_src_fg_cache; | ||
346 | u32 dp_src_bg_cache; | ||
347 | u32 fifo_free; | ||
348 | 340 | ||
349 | struct pll_info pll; | 341 | struct pll_info pll; |
350 | 342 | ||
@@ -356,7 +348,6 @@ struct radeonfb_info { | |||
356 | int lock_blank; | 348 | int lock_blank; |
357 | int dynclk; | 349 | int dynclk; |
358 | int no_schedule; | 350 | int no_schedule; |
359 | int gfx_mode; | ||
360 | enum radeon_pm_mode pm_mode; | 351 | enum radeon_pm_mode pm_mode; |
361 | reinit_function_ptr reinit_func; | 352 | reinit_function_ptr reinit_func; |
362 | 353 | ||
@@ -401,14 +392,8 @@ static inline void _radeon_msleep(struct radeonfb_info *rinfo, unsigned long ms) | |||
401 | #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) | 392 | #define OUTREG8(addr,val) writeb(val, (rinfo->mmio_base)+addr) |
402 | #define INREG16(addr) readw((rinfo->mmio_base)+addr) | 393 | #define INREG16(addr) readw((rinfo->mmio_base)+addr) |
403 | #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) | 394 | #define OUTREG16(addr,val) writew(val, (rinfo->mmio_base)+addr) |
404 | |||
405 | #ifdef CONFIG_PPC | ||
406 | #define INREG(addr) ({ eieio(); ld_le32(rinfo->mmio_base+(addr)); }) | ||
407 | #define OUTREG(addr,val) do { eieio(); st_le32(rinfo->mmio_base+(addr),(val)); } while(0) | ||
408 | #else | ||
409 | #define INREG(addr) readl((rinfo->mmio_base)+addr) | 395 | #define INREG(addr) readl((rinfo->mmio_base)+addr) |
410 | #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) | 396 | #define OUTREG(addr,val) writel(val, (rinfo->mmio_base)+addr) |
411 | #endif | ||
412 | 397 | ||
413 | static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, | 398 | static inline void _OUTREGP(struct radeonfb_info *rinfo, u32 addr, |
414 | u32 val, u32 mask) | 399 | u32 val, u32 mask) |
@@ -550,7 +535,17 @@ static inline u32 radeon_get_dstbpp(u16 depth) | |||
550 | * 2D Engine helper routines | 535 | * 2D Engine helper routines |
551 | */ | 536 | */ |
552 | 537 | ||
553 | extern void radeon_fifo_update_and_wait(struct radeonfb_info *rinfo, int entries); | 538 | static inline void _radeon_fifo_wait(struct radeonfb_info *rinfo, int entries) |
539 | { | ||
540 | int i; | ||
541 | |||
542 | for (i=0; i<2000000; i++) { | ||
543 | if ((INREG(RBBM_STATUS) & 0x7f) >= entries) | ||
544 | return; | ||
545 | udelay(1); | ||
546 | } | ||
547 | printk(KERN_ERR "radeonfb: FIFO Timeout !\n"); | ||
548 | } | ||
554 | 549 | ||
555 | static inline void radeon_engine_flush (struct radeonfb_info *rinfo) | 550 | static inline void radeon_engine_flush (struct radeonfb_info *rinfo) |
556 | { | 551 | { |
@@ -563,7 +558,7 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo) | |||
563 | /* Ensure FIFO is empty, ie, make sure the flush commands | 558 | /* Ensure FIFO is empty, ie, make sure the flush commands |
564 | * has reached the cache | 559 | * has reached the cache |
565 | */ | 560 | */ |
566 | radeon_fifo_update_and_wait(rinfo, 64); | 561 | _radeon_fifo_wait (rinfo, 64); |
567 | 562 | ||
568 | /* Wait for the flush to complete */ | 563 | /* Wait for the flush to complete */ |
569 | for (i=0; i < 2000000; i++) { | 564 | for (i=0; i < 2000000; i++) { |
@@ -575,12 +570,12 @@ static inline void radeon_engine_flush (struct radeonfb_info *rinfo) | |||
575 | } | 570 | } |
576 | 571 | ||
577 | 572 | ||
578 | static inline void radeon_engine_idle(struct radeonfb_info *rinfo) | 573 | static inline void _radeon_engine_idle(struct radeonfb_info *rinfo) |
579 | { | 574 | { |
580 | int i; | 575 | int i; |
581 | 576 | ||
582 | /* ensure FIFO is empty before waiting for idle */ | 577 | /* ensure FIFO is empty before waiting for idle */ |
583 | radeon_fifo_update_and_wait (rinfo, 64); | 578 | _radeon_fifo_wait (rinfo, 64); |
584 | 579 | ||
585 | for (i=0; i<2000000; i++) { | 580 | for (i=0; i<2000000; i++) { |
586 | if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { | 581 | if (((INREG(RBBM_STATUS) & GUI_ACTIVE)) == 0) { |
@@ -593,6 +588,8 @@ static inline void radeon_engine_idle(struct radeonfb_info *rinfo) | |||
593 | } | 588 | } |
594 | 589 | ||
595 | 590 | ||
591 | #define radeon_engine_idle() _radeon_engine_idle(rinfo) | ||
592 | #define radeon_fifo_wait(entries) _radeon_fifo_wait(rinfo,entries) | ||
596 | #define radeon_msleep(ms) _radeon_msleep(rinfo,ms) | 593 | #define radeon_msleep(ms) _radeon_msleep(rinfo,ms) |
597 | 594 | ||
598 | 595 | ||
@@ -622,7 +619,6 @@ extern void radeonfb_imageblit(struct fb_info *p, const struct fb_image *image); | |||
622 | extern int radeonfb_sync(struct fb_info *info); | 619 | extern int radeonfb_sync(struct fb_info *info); |
623 | extern void radeonfb_engine_init (struct radeonfb_info *rinfo); | 620 | extern void radeonfb_engine_init (struct radeonfb_info *rinfo); |
624 | extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); | 621 | extern void radeonfb_engine_reset(struct radeonfb_info *rinfo); |
625 | extern void radeon_fixup_mem_offset(struct radeonfb_info *rinfo); | ||
626 | 622 | ||
627 | /* Other functions */ | 623 | /* Other functions */ |
628 | extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); | 624 | extern int radeon_screen_blank(struct radeonfb_info *rinfo, int blank, int mode_switch); |
@@ -638,6 +634,4 @@ static inline void radeonfb_bl_init(struct radeonfb_info *rinfo) {} | |||
638 | static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} | 634 | static inline void radeonfb_bl_exit(struct radeonfb_info *rinfo) {} |
639 | #endif | 635 | #endif |
640 | 636 | ||
641 | extern int accel_cexp; | ||
642 | |||
643 | #endif /* __RADEONFB_H__ */ | 637 | #endif /* __RADEONFB_H__ */ |
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index 0d15b0eaf79a..5139c25ca962 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c | |||
@@ -356,7 +356,9 @@ int w1_reset_select_slave(struct w1_slave *sl) | |||
356 | w1_write_8(sl->master, W1_SKIP_ROM); | 356 | w1_write_8(sl->master, W1_SKIP_ROM); |
357 | else { | 357 | else { |
358 | u8 match[9] = {W1_MATCH_ROM, }; | 358 | u8 match[9] = {W1_MATCH_ROM, }; |
359 | memcpy(&match[1], (u8 *)&sl->reg_num, 8); | 359 | u64 rn = le64_to_cpu(*((u64*)&sl->reg_num)); |
360 | |||
361 | memcpy(&match[1], &rn, 8); | ||
360 | w1_write_block(sl->master, match, 9); | 362 | w1_write_block(sl->master, match, 9); |
361 | } | 363 | } |
362 | return 0; | 364 | return 0; |
diff --git a/fs/9p/fid.c b/fs/9p/fid.c index 3031e3233dd6..2a983d49d19c 100644 --- a/fs/9p/fid.c +++ b/fs/9p/fid.c | |||
@@ -45,7 +45,7 @@ int v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) | |||
45 | struct v9fs_dentry *dent; | 45 | struct v9fs_dentry *dent; |
46 | 46 | ||
47 | P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n", | 47 | P9_DPRINTK(P9_DEBUG_VFS, "fid %d dentry %s\n", |
48 | fid->fid, dentry->d_iname); | 48 | fid->fid, dentry->d_name.name); |
49 | 49 | ||
50 | dent = dentry->d_fsdata; | 50 | dent = dentry->d_fsdata; |
51 | if (!dent) { | 51 | if (!dent) { |
@@ -79,7 +79,7 @@ static struct p9_fid *v9fs_fid_find(struct dentry *dentry, u32 uid, int any) | |||
79 | struct p9_fid *fid, *ret; | 79 | struct p9_fid *fid, *ret; |
80 | 80 | ||
81 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", | 81 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", |
82 | dentry->d_iname, dentry, uid, any); | 82 | dentry->d_name.name, dentry, uid, any); |
83 | dent = (struct v9fs_dentry *) dentry->d_fsdata; | 83 | dent = (struct v9fs_dentry *) dentry->d_fsdata; |
84 | ret = NULL; | 84 | ret = NULL; |
85 | if (dent) { | 85 | if (dent) { |
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 24eb01087b6d..332b5ff02fec 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c | |||
@@ -160,7 +160,7 @@ static int v9fs_parse_options(struct v9fs_session_info *v9ses) | |||
160 | v9ses->flags |= V9FS_ACCESS_ANY; | 160 | v9ses->flags |= V9FS_ACCESS_ANY; |
161 | else { | 161 | else { |
162 | v9ses->flags |= V9FS_ACCESS_SINGLE; | 162 | v9ses->flags |= V9FS_ACCESS_SINGLE; |
163 | v9ses->uid = simple_strtol(s, &e, 10); | 163 | v9ses->uid = simple_strtoul(s, &e, 10); |
164 | if (*e != '\0') | 164 | if (*e != '\0') |
165 | v9ses->uid = ~0; | 165 | v9ses->uid = ~0; |
166 | } | 166 | } |
diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index f9534f18df0a..06dcc7c4f234 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c | |||
@@ -52,7 +52,8 @@ | |||
52 | 52 | ||
53 | static int v9fs_dentry_delete(struct dentry *dentry) | 53 | static int v9fs_dentry_delete(struct dentry *dentry) |
54 | { | 54 | { |
55 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 55 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, |
56 | dentry); | ||
56 | 57 | ||
57 | return 1; | 58 | return 1; |
58 | } | 59 | } |
@@ -69,7 +70,8 @@ static int v9fs_dentry_delete(struct dentry *dentry) | |||
69 | static int v9fs_cached_dentry_delete(struct dentry *dentry) | 70 | static int v9fs_cached_dentry_delete(struct dentry *dentry) |
70 | { | 71 | { |
71 | struct inode *inode = dentry->d_inode; | 72 | struct inode *inode = dentry->d_inode; |
72 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 73 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, |
74 | dentry); | ||
73 | 75 | ||
74 | if(!inode) | 76 | if(!inode) |
75 | return 1; | 77 | return 1; |
@@ -88,7 +90,8 @@ void v9fs_dentry_release(struct dentry *dentry) | |||
88 | struct v9fs_dentry *dent; | 90 | struct v9fs_dentry *dent; |
89 | struct p9_fid *temp, *current_fid; | 91 | struct p9_fid *temp, *current_fid; |
90 | 92 | ||
91 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 93 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, |
94 | dentry); | ||
92 | dent = dentry->d_fsdata; | 95 | dent = dentry->d_fsdata; |
93 | if (dent) { | 96 | if (dent) { |
94 | list_for_each_entry_safe(current_fid, temp, &dent->fidlist, | 97 | list_for_each_entry_safe(current_fid, temp, &dent->fidlist, |
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 8314d3f43b71..2dfcf5487efe 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c | |||
@@ -963,7 +963,8 @@ static int v9fs_vfs_readlink(struct dentry *dentry, char __user * buffer, | |||
963 | if (buflen > PATH_MAX) | 963 | if (buflen > PATH_MAX) |
964 | buflen = PATH_MAX; | 964 | buflen = PATH_MAX; |
965 | 965 | ||
966 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_iname, dentry); | 966 | P9_DPRINTK(P9_DEBUG_VFS, " dentry: %s (%p)\n", dentry->d_name.name, |
967 | dentry); | ||
967 | 968 | ||
968 | retval = v9fs_readlink(dentry, link, buflen); | 969 | retval = v9fs_readlink(dentry, link, buflen); |
969 | 970 | ||
@@ -1022,7 +1023,8 @@ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) | |||
1022 | { | 1023 | { |
1023 | char *s = nd_get_link(nd); | 1024 | char *s = nd_get_link(nd); |
1024 | 1025 | ||
1025 | P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, s); | 1026 | P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, |
1027 | IS_ERR(s) ? "<error>" : s); | ||
1026 | if (!IS_ERR(s)) | 1028 | if (!IS_ERR(s)) |
1027 | __putname(s); | 1029 | __putname(s); |
1028 | } | 1030 | } |
diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index 2af8626ced43..6d51696dc762 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c | |||
@@ -3983,7 +3983,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, | |||
3983 | 3983 | ||
3984 | node->flags = le16_to_cpu(pSMBr->DFSFlags); | 3984 | node->flags = le16_to_cpu(pSMBr->DFSFlags); |
3985 | if (is_unicode) { | 3985 | if (is_unicode) { |
3986 | __le16 *tmp = kmalloc(strlen(searchName)*2, GFP_KERNEL); | 3986 | __le16 *tmp = kmalloc(strlen(searchName)*2 + 2, |
3987 | GFP_KERNEL); | ||
3987 | cifsConvertToUCS((__le16 *) tmp, searchName, | 3988 | cifsConvertToUCS((__le16 *) tmp, searchName, |
3988 | PATH_MAX, nls_codepage, remap); | 3989 | PATH_MAX, nls_codepage, remap); |
3989 | node->path_consumed = hostlen_fromUCS(tmp, | 3990 | node->path_consumed = hostlen_fromUCS(tmp, |
diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index 5f180cf7abbd..5e0c0d0aef7d 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h | |||
@@ -86,7 +86,8 @@ | |||
86 | #define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask) \ | 86 | #define OCFS2_CLEAR_INCOMPAT_FEATURE(sb,mask) \ |
87 | OCFS2_SB(sb)->s_feature_incompat &= ~(mask) | 87 | OCFS2_SB(sb)->s_feature_incompat &= ~(mask) |
88 | 88 | ||
89 | #define OCFS2_FEATURE_COMPAT_SUPP OCFS2_FEATURE_COMPAT_BACKUP_SB | 89 | #define OCFS2_FEATURE_COMPAT_SUPP (OCFS2_FEATURE_COMPAT_BACKUP_SB \ |
90 | | OCFS2_FEATURE_COMPAT_JBD2_SB) | ||
90 | #define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \ | 91 | #define OCFS2_FEATURE_INCOMPAT_SUPP (OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT \ |
91 | | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \ | 92 | | OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC \ |
92 | | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \ | 93 | | OCFS2_FEATURE_INCOMPAT_INLINE_DATA \ |
@@ -153,6 +154,11 @@ | |||
153 | #define OCFS2_FEATURE_COMPAT_BACKUP_SB 0x0001 | 154 | #define OCFS2_FEATURE_COMPAT_BACKUP_SB 0x0001 |
154 | 155 | ||
155 | /* | 156 | /* |
157 | * The filesystem will correctly handle journal feature bits. | ||
158 | */ | ||
159 | #define OCFS2_FEATURE_COMPAT_JBD2_SB 0x0002 | ||
160 | |||
161 | /* | ||
156 | * Unwritten extents support. | 162 | * Unwritten extents support. |
157 | */ | 163 | */ |
158 | #define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001 | 164 | #define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN 0x0001 |
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c index 054e2efb0b7e..74d7367ade13 100644 --- a/fs/ocfs2/xattr.c +++ b/fs/ocfs2/xattr.c | |||
@@ -2645,9 +2645,9 @@ static int ocfs2_xattr_update_xattr_search(struct inode *inode, | |||
2645 | return ret; | 2645 | return ret; |
2646 | } | 2646 | } |
2647 | 2647 | ||
2648 | i = xs->here - old_xh->xh_entries; | ||
2649 | xs->here = &xs->header->xh_entries[i]; | ||
2650 | } | 2648 | } |
2649 | i = xs->here - old_xh->xh_entries; | ||
2650 | xs->here = &xs->header->xh_entries[i]; | ||
2651 | } | 2651 | } |
2652 | 2652 | ||
2653 | return ret; | 2653 | return ret; |
diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index 09d33c7740f0..db8852d8bcf7 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h | |||
@@ -172,7 +172,7 @@ | |||
172 | 172 | ||
173 | /* Defaults for debug_level, debug and normal */ | 173 | /* Defaults for debug_level, debug and normal */ |
174 | 174 | ||
175 | #define ACPI_DEBUG_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) | 175 | #define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO) |
176 | #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) | 176 | #define ACPI_NORMAL_DEFAULT (ACPI_LV_INIT | ACPI_LV_DEBUG_OBJECT) |
177 | #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) | 177 | #define ACPI_DEBUG_ALL (ACPI_LV_AML_DISASSEMBLE | ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_ALL) |
178 | 178 | ||
diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 029c8c06c151..0515e754449d 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h | |||
@@ -141,6 +141,10 @@ static inline void *acpi_os_acquire_object(acpi_cache_t * cache) | |||
141 | /* | 141 | /* |
142 | * We need to show where it is safe to preempt execution of ACPICA | 142 | * We need to show where it is safe to preempt execution of ACPICA |
143 | */ | 143 | */ |
144 | #define ACPI_PREEMPTION_POINT() cond_resched() | 144 | #define ACPI_PREEMPTION_POINT() \ |
145 | do { \ | ||
146 | if (!irqs_disabled()) \ | ||
147 | cond_resched(); \ | ||
148 | } while (0) | ||
145 | 149 | ||
146 | #endif /* __ACLINUX_H__ */ | 150 | #endif /* __ACLINUX_H__ */ |
diff --git a/include/linux/mfd/wm8350/audio.h b/include/linux/mfd/wm8350/audio.h index 217bb22ebb8e..af95a1d2f3a1 100644 --- a/include/linux/mfd/wm8350/audio.h +++ b/include/linux/mfd/wm8350/audio.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * audio.h -- Audio Driver for Wolfson WM8350 PMIC | 2 | * audio.h -- Audio Driver for Wolfson WM8350 PMIC |
3 | * | 3 | * |
4 | * Copyright 2007 Wolfson Microelectronics PLC | 4 | * Copyright 2007, 2008 Wolfson Microelectronics PLC |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -70,9 +70,9 @@ | |||
70 | #define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */ | 70 | #define WM8350_CODEC_ISEL_0_5 3 /* x0.5 */ |
71 | 71 | ||
72 | #define WM8350_VMID_OFF 0 | 72 | #define WM8350_VMID_OFF 0 |
73 | #define WM8350_VMID_500K 1 | 73 | #define WM8350_VMID_300K 1 |
74 | #define WM8350_VMID_100K 2 | 74 | #define WM8350_VMID_50K 2 |
75 | #define WM8350_VMID_10K 3 | 75 | #define WM8350_VMID_5K 3 |
76 | 76 | ||
77 | /* | 77 | /* |
78 | * R40 (0x28) - Clock Control 1 | 78 | * R40 (0x28) - Clock Control 1 |
@@ -591,8 +591,38 @@ | |||
591 | #define WM8350_IRQ_CODEC_MICSCD 41 | 591 | #define WM8350_IRQ_CODEC_MICSCD 41 |
592 | #define WM8350_IRQ_CODEC_MICD 42 | 592 | #define WM8350_IRQ_CODEC_MICD 42 |
593 | 593 | ||
594 | /* | ||
595 | * WM8350 Platform data. | ||
596 | * | ||
597 | * This must be initialised per platform for best audio performance. | ||
598 | * Please see WM8350 datasheet for information. | ||
599 | */ | ||
600 | struct wm8350_audio_platform_data { | ||
601 | int vmid_discharge_msecs; /* VMID --> OFF discharge time */ | ||
602 | int drain_msecs; /* OFF drain time */ | ||
603 | int cap_discharge_msecs; /* Cap ON (from OFF) discharge time */ | ||
604 | int vmid_charge_msecs; /* vmid power up time */ | ||
605 | u32 vmid_s_curve:2; /* vmid enable s curve speed */ | ||
606 | u32 dis_out4:2; /* out4 discharge speed */ | ||
607 | u32 dis_out3:2; /* out3 discharge speed */ | ||
608 | u32 dis_out2:2; /* out2 discharge speed */ | ||
609 | u32 dis_out1:2; /* out1 discharge speed */ | ||
610 | u32 vroi_out4:1; /* out4 tie off */ | ||
611 | u32 vroi_out3:1; /* out3 tie off */ | ||
612 | u32 vroi_out2:1; /* out2 tie off */ | ||
613 | u32 vroi_out1:1; /* out1 tie off */ | ||
614 | u32 vroi_enable:1; /* enable tie off */ | ||
615 | u32 codec_current_on:2; /* current level ON */ | ||
616 | u32 codec_current_standby:2; /* current level STANDBY */ | ||
617 | u32 codec_current_charge:2; /* codec current @ vmid charge */ | ||
618 | }; | ||
619 | |||
620 | struct snd_soc_codec; | ||
621 | |||
594 | struct wm8350_codec { | 622 | struct wm8350_codec { |
595 | struct platform_device *pdev; | 623 | struct platform_device *pdev; |
624 | struct snd_soc_codec *codec; | ||
625 | struct wm8350_audio_platform_data *platform_data; | ||
596 | }; | 626 | }; |
597 | 627 | ||
598 | #endif | 628 | #endif |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 9d77b1d7dca8..e26f54952892 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -319,6 +319,7 @@ enum | |||
319 | { | 319 | { |
320 | NAPI_STATE_SCHED, /* Poll is scheduled */ | 320 | NAPI_STATE_SCHED, /* Poll is scheduled */ |
321 | NAPI_STATE_DISABLE, /* Disable pending */ | 321 | NAPI_STATE_DISABLE, /* Disable pending */ |
322 | NAPI_STATE_NPSVC, /* Netpoll - don't dequeue from poll_list */ | ||
322 | }; | 323 | }; |
323 | 324 | ||
324 | extern void __napi_schedule(struct napi_struct *n); | 325 | extern void __napi_schedule(struct napi_struct *n); |
@@ -1497,6 +1498,12 @@ static inline void netif_rx_complete(struct net_device *dev, | |||
1497 | { | 1498 | { |
1498 | unsigned long flags; | 1499 | unsigned long flags; |
1499 | 1500 | ||
1501 | /* | ||
1502 | * don't let napi dequeue from the cpu poll list | ||
1503 | * just in case its running on a different cpu | ||
1504 | */ | ||
1505 | if (unlikely(test_bit(NAPI_STATE_NPSVC, &napi->state))) | ||
1506 | return; | ||
1500 | local_irq_save(flags); | 1507 | local_irq_save(flags); |
1501 | __netif_rx_complete(dev, napi); | 1508 | __netif_rx_complete(dev, napi); |
1502 | local_irq_restore(flags); | 1509 | local_irq_restore(flags); |
diff --git a/include/linux/netfilter/nfnetlink_conntrack.h b/include/linux/netfilter/nfnetlink_conntrack.h index c19595c89304..29fe9ea1d346 100644 --- a/include/linux/netfilter/nfnetlink_conntrack.h +++ b/include/linux/netfilter/nfnetlink_conntrack.h | |||
@@ -141,6 +141,7 @@ enum ctattr_protonat { | |||
141 | #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) | 141 | #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1) |
142 | 142 | ||
143 | enum ctattr_natseq { | 143 | enum ctattr_natseq { |
144 | CTA_NAT_SEQ_UNSPEC, | ||
144 | CTA_NAT_SEQ_CORRECTION_POS, | 145 | CTA_NAT_SEQ_CORRECTION_POS, |
145 | CTA_NAT_SEQ_OFFSET_BEFORE, | 146 | CTA_NAT_SEQ_OFFSET_BEFORE, |
146 | CTA_NAT_SEQ_OFFSET_AFTER, | 147 | CTA_NAT_SEQ_OFFSET_AFTER, |
diff --git a/include/linux/smp.h b/include/linux/smp.h index 3f9a60043a97..6e7ba16ff454 100644 --- a/include/linux/smp.h +++ b/include/linux/smp.h | |||
@@ -146,6 +146,8 @@ static inline void smp_send_reschedule(int cpu) { } | |||
146 | }) | 146 | }) |
147 | #define smp_call_function_mask(mask, func, info, wait) \ | 147 | #define smp_call_function_mask(mask, func, info, wait) \ |
148 | (up_smp_call_function(func, info)) | 148 | (up_smp_call_function(func, info)) |
149 | #define smp_call_function_many(mask, func, info, wait) \ | ||
150 | (up_smp_call_function(func, info)) | ||
149 | static inline void init_call_single_data(void) | 151 | static inline void init_call_single_data(void) |
150 | { | 152 | { |
151 | } | 153 | } |
diff --git a/include/linux/usb/ch9.h b/include/linux/usb/ch9.h index 73a2f4eb1f7a..9b42baed3900 100644 --- a/include/linux/usb/ch9.h +++ b/include/linux/usb/ch9.h | |||
@@ -158,8 +158,12 @@ struct usb_ctrlrequest { | |||
158 | * (rarely) accepted by SET_DESCRIPTOR. | 158 | * (rarely) accepted by SET_DESCRIPTOR. |
159 | * | 159 | * |
160 | * Note that all multi-byte values here are encoded in little endian | 160 | * Note that all multi-byte values here are encoded in little endian |
161 | * byte order "on the wire". But when exposed through Linux-USB APIs, | 161 | * byte order "on the wire". Within the kernel and when exposed |
162 | * they've been converted to cpu byte order. | 162 | * through the Linux-USB APIs, they are not converted to cpu byte |
163 | * order; it is the responsibility of the client code to do this. | ||
164 | * The single exception is when device and configuration descriptors (but | ||
165 | * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD); | ||
166 | * in this case the fields are converted to host endianness by the kernel. | ||
163 | */ | 167 | */ |
164 | 168 | ||
165 | /* | 169 | /* |
diff --git a/include/net/irda/irda_device.h b/include/net/irda/irda_device.h index 3025ae17ddbe..94c852d47d0f 100644 --- a/include/net/irda/irda_device.h +++ b/include/net/irda/irda_device.h | |||
@@ -135,9 +135,11 @@ struct dongle_reg { | |||
135 | 135 | ||
136 | /* | 136 | /* |
137 | * Per-packet information we need to hide inside sk_buff | 137 | * Per-packet information we need to hide inside sk_buff |
138 | * (must not exceed 48 bytes, check with struct sk_buff) | 138 | * (must not exceed 48 bytes, check with struct sk_buff) |
139 | * The default_qdisc_pad field is a temporary hack. | ||
139 | */ | 140 | */ |
140 | struct irda_skb_cb { | 141 | struct irda_skb_cb { |
142 | unsigned int default_qdisc_pad; | ||
141 | magic_t magic; /* Be sure that we can trust the information */ | 143 | magic_t magic; /* Be sure that we can trust the information */ |
142 | __u32 next_speed; /* The Speed to be set *after* this frame */ | 144 | __u32 next_speed; /* The Speed to be set *after* this frame */ |
143 | __u16 mtt; /* Minimum turn around time */ | 145 | __u16 mtt; /* Minimum turn around time */ |
diff --git a/include/sound/core.h b/include/sound/core.h index 1508c4ec1ba9..f632484bc743 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, ...) | |||
353 | * snd_printk - printk wrapper | 353 | * snd_printk - printk wrapper |
354 | * @fmt: format string | 354 | * @fmt: format string |
355 | * | 355 | * |
356 | * Works like print() but prints the file and the line of the caller | 356 | * Works like printk() but prints the file and the line of the caller |
357 | * when configured with CONFIG_SND_VERBOSE_PRINTK. | 357 | * when configured with CONFIG_SND_VERBOSE_PRINTK. |
358 | */ | 358 | */ |
359 | #define snd_printk(fmt, args...) \ | 359 | #define snd_printk(fmt, args...) \ |
@@ -380,18 +380,40 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...) | |||
380 | printk(fmt ,##args) | 380 | printk(fmt ,##args) |
381 | #endif | 381 | #endif |
382 | 382 | ||
383 | /** | ||
384 | * snd_BUG - give a BUG warning message and stack trace | ||
385 | * | ||
386 | * Calls WARN() if CONFIG_SND_DEBUG is set. | ||
387 | * Ignored when CONFIG_SND_DEBUG is not set. | ||
388 | */ | ||
383 | #define snd_BUG() WARN(1, "BUG?\n") | 389 | #define snd_BUG() WARN(1, "BUG?\n") |
390 | |||
391 | /** | ||
392 | * snd_BUG_ON - debugging check macro | ||
393 | * @cond: condition to evaluate | ||
394 | * | ||
395 | * When CONFIG_SND_DEBUG is set, this macro evaluates the given condition, | ||
396 | * and call WARN() and returns the value if it's non-zero. | ||
397 | * | ||
398 | * When CONFIG_SND_DEBUG is not set, this just returns zero, and the given | ||
399 | * condition is ignored. | ||
400 | * | ||
401 | * NOTE: the argument won't be evaluated at all when CONFIG_SND_DEBUG=n. | ||
402 | * Thus, don't put any statement that influences on the code behavior, | ||
403 | * such as pre/post increment, to the argument of this macro. | ||
404 | * If you want to evaluate and give a warning, use standard WARN_ON(). | ||
405 | */ | ||
384 | #define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond)) | 406 | #define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond)) |
385 | 407 | ||
386 | #else /* !CONFIG_SND_DEBUG */ | 408 | #else /* !CONFIG_SND_DEBUG */ |
387 | 409 | ||
388 | #define snd_printd(fmt, args...) do { } while (0) | 410 | #define snd_printd(fmt, args...) do { } while (0) |
389 | #define snd_BUG() do { } while (0) | 411 | #define snd_BUG() do { } while (0) |
390 | static inline int __snd_bug_on(void) | 412 | static inline int __snd_bug_on(int cond) |
391 | { | 413 | { |
392 | return 0; | 414 | return 0; |
393 | } | 415 | } |
394 | #define snd_BUG_ON(cond) __snd_bug_on() /* always false */ | 416 | #define snd_BUG_ON(cond) __snd_bug_on(0 && (cond)) /* always false */ |
395 | 417 | ||
396 | #endif /* CONFIG_SND_DEBUG */ | 418 | #endif /* CONFIG_SND_DEBUG */ |
397 | 419 | ||
diff --git a/include/sound/l3.h b/include/sound/l3.h new file mode 100644 index 000000000000..423a08f0f1b0 --- /dev/null +++ b/include/sound/l3.h | |||
@@ -0,0 +1,18 @@ | |||
1 | #ifndef _L3_H_ | ||
2 | #define _L3_H_ 1 | ||
3 | |||
4 | struct l3_pins { | ||
5 | void (*setdat)(int); | ||
6 | void (*setclk)(int); | ||
7 | void (*setmode)(int); | ||
8 | int data_hold; | ||
9 | int data_setup; | ||
10 | int clock_high; | ||
11 | int mode_hold; | ||
12 | int mode; | ||
13 | int mode_setup; | ||
14 | }; | ||
15 | |||
16 | int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len); | ||
17 | |||
18 | #endif | ||
diff --git a/include/sound/s3c24xx_uda134x.h b/include/sound/s3c24xx_uda134x.h new file mode 100644 index 000000000000..33df4cb909d3 --- /dev/null +++ b/include/sound/s3c24xx_uda134x.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _S3C24XX_UDA134X_H_ | ||
2 | #define _S3C24XX_UDA134X_H_ 1 | ||
3 | |||
4 | #include <sound/uda134x.h> | ||
5 | |||
6 | struct s3c24xx_uda134x_platform_data { | ||
7 | int l3_clk; | ||
8 | int l3_mode; | ||
9 | int l3_data; | ||
10 | void (*power) (int); | ||
11 | int model; | ||
12 | }; | ||
13 | |||
14 | #endif | ||
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h new file mode 100644 index 000000000000..24247f763608 --- /dev/null +++ b/include/sound/soc-dai.h | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * linux/sound/soc-dai.h -- ALSA SoC Layer | ||
3 | * | ||
4 | * Copyright: 2005-2008 Wolfson Microelectronics. PLC. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * Digital Audio Interface (DAI) API. | ||
11 | */ | ||
12 | |||
13 | #ifndef __LINUX_SND_SOC_DAI_H | ||
14 | #define __LINUX_SND_SOC_DAI_H | ||
15 | |||
16 | |||
17 | #include <linux/list.h> | ||
18 | |||
19 | struct snd_pcm_substream; | ||
20 | |||
21 | /* | ||
22 | * DAI hardware audio formats. | ||
23 | * | ||
24 | * Describes the physical PCM data formating and clocking. Add new formats | ||
25 | * to the end. | ||
26 | */ | ||
27 | #define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ | ||
28 | #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */ | ||
29 | #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ | ||
30 | #define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */ | ||
31 | #define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */ | ||
32 | #define SND_SOC_DAIFMT_AC97 5 /* AC97 */ | ||
33 | |||
34 | /* left and right justified also known as MSB and LSB respectively */ | ||
35 | #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J | ||
36 | #define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J | ||
37 | |||
38 | /* | ||
39 | * DAI Clock gating. | ||
40 | * | ||
41 | * DAI bit clocks can be be gated (disabled) when not the DAI is not | ||
42 | * sending or receiving PCM data in a frame. This can be used to save power. | ||
43 | */ | ||
44 | #define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ | ||
45 | #define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */ | ||
46 | |||
47 | /* | ||
48 | * DAI Left/Right Clocks. | ||
49 | * | ||
50 | * Specifies whether the DAI can support different samples for similtanious | ||
51 | * playback and capture. This usually requires a seperate physical frame | ||
52 | * clock for playback and capture. | ||
53 | */ | ||
54 | #define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */ | ||
55 | #define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */ | ||
56 | |||
57 | /* | ||
58 | * TDM | ||
59 | * | ||
60 | * Time Division Multiplexing. Allows PCM data to be multplexed with other | ||
61 | * data on the DAI. | ||
62 | */ | ||
63 | #define SND_SOC_DAIFMT_TDM (1 << 6) | ||
64 | |||
65 | /* | ||
66 | * DAI hardware signal inversions. | ||
67 | * | ||
68 | * Specifies whether the DAI can also support inverted clocks for the specified | ||
69 | * format. | ||
70 | */ | ||
71 | #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ | ||
72 | #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ | ||
73 | #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ | ||
74 | #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ | ||
75 | |||
76 | /* | ||
77 | * DAI hardware clock masters. | ||
78 | * | ||
79 | * This is wrt the codec, the inverse is true for the interface | ||
80 | * i.e. if the codec is clk and frm master then the interface is | ||
81 | * clk and frame slave. | ||
82 | */ | ||
83 | #define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */ | ||
84 | #define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */ | ||
85 | #define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ | ||
86 | #define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */ | ||
87 | |||
88 | #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f | ||
89 | #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 | ||
90 | #define SND_SOC_DAIFMT_INV_MASK 0x0f00 | ||
91 | #define SND_SOC_DAIFMT_MASTER_MASK 0xf000 | ||
92 | |||
93 | /* | ||
94 | * Master Clock Directions | ||
95 | */ | ||
96 | #define SND_SOC_CLOCK_IN 0 | ||
97 | #define SND_SOC_CLOCK_OUT 1 | ||
98 | |||
99 | struct snd_soc_dai_ops; | ||
100 | struct snd_soc_dai; | ||
101 | struct snd_ac97_bus_ops; | ||
102 | |||
103 | /* Digital Audio Interface registration */ | ||
104 | int snd_soc_register_dai(struct snd_soc_dai *dai); | ||
105 | void snd_soc_unregister_dai(struct snd_soc_dai *dai); | ||
106 | int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count); | ||
107 | void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count); | ||
108 | |||
109 | /* Digital Audio Interface clocking API.*/ | ||
110 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
111 | unsigned int freq, int dir); | ||
112 | |||
113 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | ||
114 | int div_id, int div); | ||
115 | |||
116 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, | ||
117 | int pll_id, unsigned int freq_in, unsigned int freq_out); | ||
118 | |||
119 | /* Digital Audio interface formatting */ | ||
120 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); | ||
121 | |||
122 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
123 | unsigned int mask, int slots); | ||
124 | |||
125 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); | ||
126 | |||
127 | /* Digital Audio Interface mute */ | ||
128 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); | ||
129 | |||
130 | /* | ||
131 | * Digital Audio Interface. | ||
132 | * | ||
133 | * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97 | ||
134 | * operations an capabilities. Codec and platfom drivers will register a this | ||
135 | * structure for every DAI they have. | ||
136 | * | ||
137 | * This structure covers the clocking, formating and ALSA operations for each | ||
138 | * interface a | ||
139 | */ | ||
140 | struct snd_soc_dai_ops { | ||
141 | /* | ||
142 | * DAI clocking configuration, all optional. | ||
143 | * Called by soc_card drivers, normally in their hw_params. | ||
144 | */ | ||
145 | int (*set_sysclk)(struct snd_soc_dai *dai, | ||
146 | int clk_id, unsigned int freq, int dir); | ||
147 | int (*set_pll)(struct snd_soc_dai *dai, | ||
148 | int pll_id, unsigned int freq_in, unsigned int freq_out); | ||
149 | int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div); | ||
150 | |||
151 | /* | ||
152 | * DAI format configuration | ||
153 | * Called by soc_card drivers, normally in their hw_params. | ||
154 | */ | ||
155 | int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); | ||
156 | int (*set_tdm_slot)(struct snd_soc_dai *dai, | ||
157 | unsigned int mask, int slots); | ||
158 | int (*set_tristate)(struct snd_soc_dai *dai, int tristate); | ||
159 | |||
160 | /* | ||
161 | * DAI digital mute - optional. | ||
162 | * Called by soc-core to minimise any pops. | ||
163 | */ | ||
164 | int (*digital_mute)(struct snd_soc_dai *dai, int mute); | ||
165 | |||
166 | /* | ||
167 | * ALSA PCM audio operations - all optional. | ||
168 | * Called by soc-core during audio PCM operations. | ||
169 | */ | ||
170 | int (*startup)(struct snd_pcm_substream *, | ||
171 | struct snd_soc_dai *); | ||
172 | void (*shutdown)(struct snd_pcm_substream *, | ||
173 | struct snd_soc_dai *); | ||
174 | int (*hw_params)(struct snd_pcm_substream *, | ||
175 | struct snd_pcm_hw_params *, struct snd_soc_dai *); | ||
176 | int (*hw_free)(struct snd_pcm_substream *, | ||
177 | struct snd_soc_dai *); | ||
178 | int (*prepare)(struct snd_pcm_substream *, | ||
179 | struct snd_soc_dai *); | ||
180 | int (*trigger)(struct snd_pcm_substream *, int, | ||
181 | struct snd_soc_dai *); | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * Digital Audio Interface runtime data. | ||
186 | * | ||
187 | * Holds runtime data for a DAI. | ||
188 | */ | ||
189 | struct snd_soc_dai { | ||
190 | /* DAI description */ | ||
191 | char *name; | ||
192 | unsigned int id; | ||
193 | int ac97_control; | ||
194 | |||
195 | struct device *dev; | ||
196 | |||
197 | /* DAI callbacks */ | ||
198 | int (*probe)(struct platform_device *pdev, | ||
199 | struct snd_soc_dai *dai); | ||
200 | void (*remove)(struct platform_device *pdev, | ||
201 | struct snd_soc_dai *dai); | ||
202 | int (*suspend)(struct snd_soc_dai *dai); | ||
203 | int (*resume)(struct snd_soc_dai *dai); | ||
204 | |||
205 | /* ops */ | ||
206 | struct snd_soc_dai_ops ops; | ||
207 | |||
208 | /* DAI capabilities */ | ||
209 | struct snd_soc_pcm_stream capture; | ||
210 | struct snd_soc_pcm_stream playback; | ||
211 | |||
212 | /* DAI runtime info */ | ||
213 | struct snd_pcm_runtime *runtime; | ||
214 | struct snd_soc_codec *codec; | ||
215 | unsigned int active; | ||
216 | unsigned char pop_wait:1; | ||
217 | void *dma_data; | ||
218 | |||
219 | /* DAI private data */ | ||
220 | void *private_data; | ||
221 | |||
222 | /* parent codec/platform */ | ||
223 | union { | ||
224 | struct snd_soc_codec *codec; | ||
225 | struct snd_soc_platform *platform; | ||
226 | }; | ||
227 | |||
228 | struct list_head list; | ||
229 | }; | ||
230 | |||
231 | #endif | ||
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index ca699a3017f3..7ee2f70ca42e 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -221,8 +221,6 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | |||
221 | int num); | 221 | int num); |
222 | 222 | ||
223 | /* dapm path setup */ | 223 | /* dapm path setup */ |
224 | int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec, | ||
225 | const char *sink_name, const char *control_name, const char *src_name); | ||
226 | int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); | 224 | int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec); |
227 | void snd_soc_dapm_free(struct snd_soc_device *socdev); | 225 | void snd_soc_dapm_free(struct snd_soc_device *socdev); |
228 | int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, | 226 | int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 5e0189876afd..f86e455d3828 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -21,8 +21,6 @@ | |||
21 | #include <sound/control.h> | 21 | #include <sound/control.h> |
22 | #include <sound/ac97_codec.h> | 22 | #include <sound/ac97_codec.h> |
23 | 23 | ||
24 | #define SND_SOC_VERSION "0.13.2" | ||
25 | |||
26 | /* | 24 | /* |
27 | * Convenience kcontrol builders | 25 | * Convenience kcontrol builders |
28 | */ | 26 | */ |
@@ -145,105 +143,31 @@ enum snd_soc_bias_level { | |||
145 | SND_SOC_BIAS_OFF, | 143 | SND_SOC_BIAS_OFF, |
146 | }; | 144 | }; |
147 | 145 | ||
148 | /* | ||
149 | * Digital Audio Interface (DAI) types | ||
150 | */ | ||
151 | #define SND_SOC_DAI_AC97 0x1 | ||
152 | #define SND_SOC_DAI_I2S 0x2 | ||
153 | #define SND_SOC_DAI_PCM 0x4 | ||
154 | #define SND_SOC_DAI_AC97_BUS 0x8 /* for custom i.e. non ac97_codec.c */ | ||
155 | |||
156 | /* | ||
157 | * DAI hardware audio formats | ||
158 | */ | ||
159 | #define SND_SOC_DAIFMT_I2S 0 /* I2S mode */ | ||
160 | #define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */ | ||
161 | #define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */ | ||
162 | #define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */ | ||
163 | #define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */ | ||
164 | #define SND_SOC_DAIFMT_AC97 5 /* AC97 */ | ||
165 | |||
166 | #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J | ||
167 | #define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J | ||
168 | |||
169 | /* | ||
170 | * DAI Gating | ||
171 | */ | ||
172 | #define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */ | ||
173 | #define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */ | ||
174 | |||
175 | /* | ||
176 | * DAI Sync | ||
177 | * Synchronous LR (Left Right) clocks and Frame signals. | ||
178 | */ | ||
179 | #define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */ | ||
180 | #define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */ | ||
181 | |||
182 | /* | ||
183 | * TDM | ||
184 | */ | ||
185 | #define SND_SOC_DAIFMT_TDM (1 << 6) | ||
186 | |||
187 | /* | ||
188 | * DAI hardware signal inversions | ||
189 | */ | ||
190 | #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */ | ||
191 | #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ | ||
192 | #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ | ||
193 | #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ | ||
194 | |||
195 | /* | ||
196 | * DAI hardware clock masters | ||
197 | * This is wrt the codec, the inverse is true for the interface | ||
198 | * i.e. if the codec is clk and frm master then the interface is | ||
199 | * clk and frame slave. | ||
200 | */ | ||
201 | #define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */ | ||
202 | #define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */ | ||
203 | #define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */ | ||
204 | #define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */ | ||
205 | |||
206 | #define SND_SOC_DAIFMT_FORMAT_MASK 0x000f | ||
207 | #define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 | ||
208 | #define SND_SOC_DAIFMT_INV_MASK 0x0f00 | ||
209 | #define SND_SOC_DAIFMT_MASTER_MASK 0xf000 | ||
210 | |||
211 | |||
212 | /* | ||
213 | * Master Clock Directions | ||
214 | */ | ||
215 | #define SND_SOC_CLOCK_IN 0 | ||
216 | #define SND_SOC_CLOCK_OUT 1 | ||
217 | |||
218 | /* | ||
219 | * AC97 codec ID's bitmask | ||
220 | */ | ||
221 | #define SND_SOC_DAI_AC97_ID0 (1 << 0) | ||
222 | #define SND_SOC_DAI_AC97_ID1 (1 << 1) | ||
223 | #define SND_SOC_DAI_AC97_ID2 (1 << 2) | ||
224 | #define SND_SOC_DAI_AC97_ID3 (1 << 3) | ||
225 | |||
226 | struct snd_soc_device; | 146 | struct snd_soc_device; |
227 | struct snd_soc_pcm_stream; | 147 | struct snd_soc_pcm_stream; |
228 | struct snd_soc_ops; | 148 | struct snd_soc_ops; |
229 | struct snd_soc_dai_mode; | 149 | struct snd_soc_dai_mode; |
230 | struct snd_soc_pcm_runtime; | 150 | struct snd_soc_pcm_runtime; |
231 | struct snd_soc_dai; | 151 | struct snd_soc_dai; |
152 | struct snd_soc_platform; | ||
232 | struct snd_soc_codec; | 153 | struct snd_soc_codec; |
233 | struct snd_soc_machine_config; | ||
234 | struct soc_enum; | 154 | struct soc_enum; |
235 | struct snd_soc_ac97_ops; | 155 | struct snd_soc_ac97_ops; |
236 | struct snd_soc_clock_info; | ||
237 | 156 | ||
238 | typedef int (*hw_write_t)(void *,const char* ,int); | 157 | typedef int (*hw_write_t)(void *,const char* ,int); |
239 | typedef int (*hw_read_t)(void *,char* ,int); | 158 | typedef int (*hw_read_t)(void *,char* ,int); |
240 | 159 | ||
241 | extern struct snd_ac97_bus_ops soc_ac97_ops; | 160 | extern struct snd_ac97_bus_ops soc_ac97_ops; |
242 | 161 | ||
162 | int snd_soc_register_platform(struct snd_soc_platform *platform); | ||
163 | void snd_soc_unregister_platform(struct snd_soc_platform *platform); | ||
164 | int snd_soc_register_codec(struct snd_soc_codec *codec); | ||
165 | void snd_soc_unregister_codec(struct snd_soc_codec *codec); | ||
166 | |||
243 | /* pcm <-> DAI connect */ | 167 | /* pcm <-> DAI connect */ |
244 | void snd_soc_free_pcms(struct snd_soc_device *socdev); | 168 | void snd_soc_free_pcms(struct snd_soc_device *socdev); |
245 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); | 169 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid); |
246 | int snd_soc_register_card(struct snd_soc_device *socdev); | 170 | int snd_soc_init_card(struct snd_soc_device *socdev); |
247 | 171 | ||
248 | /* set runtime hw params */ | 172 | /* set runtime hw params */ |
249 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, | 173 | int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, |
@@ -263,27 +187,6 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
263 | struct snd_ac97_bus_ops *ops, int num); | 187 | struct snd_ac97_bus_ops *ops, int num); |
264 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); | 188 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); |
265 | 189 | ||
266 | /* Digital Audio Interface clocking API.*/ | ||
267 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | ||
268 | unsigned int freq, int dir); | ||
269 | |||
270 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | ||
271 | int div_id, int div); | ||
272 | |||
273 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, | ||
274 | int pll_id, unsigned int freq_in, unsigned int freq_out); | ||
275 | |||
276 | /* Digital Audio interface formatting */ | ||
277 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); | ||
278 | |||
279 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | ||
280 | unsigned int mask, int slots); | ||
281 | |||
282 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate); | ||
283 | |||
284 | /* Digital Audio Interface mute */ | ||
285 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute); | ||
286 | |||
287 | /* | 190 | /* |
288 | *Controls | 191 | *Controls |
289 | */ | 192 | */ |
@@ -341,66 +244,14 @@ struct snd_soc_ops { | |||
341 | int (*trigger)(struct snd_pcm_substream *, int); | 244 | int (*trigger)(struct snd_pcm_substream *, int); |
342 | }; | 245 | }; |
343 | 246 | ||
344 | /* ASoC DAI ops */ | ||
345 | struct snd_soc_dai_ops { | ||
346 | /* DAI clocking configuration */ | ||
347 | int (*set_sysclk)(struct snd_soc_dai *dai, | ||
348 | int clk_id, unsigned int freq, int dir); | ||
349 | int (*set_pll)(struct snd_soc_dai *dai, | ||
350 | int pll_id, unsigned int freq_in, unsigned int freq_out); | ||
351 | int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div); | ||
352 | |||
353 | /* DAI format configuration */ | ||
354 | int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt); | ||
355 | int (*set_tdm_slot)(struct snd_soc_dai *dai, | ||
356 | unsigned int mask, int slots); | ||
357 | int (*set_tristate)(struct snd_soc_dai *dai, int tristate); | ||
358 | |||
359 | /* digital mute */ | ||
360 | int (*digital_mute)(struct snd_soc_dai *dai, int mute); | ||
361 | }; | ||
362 | |||
363 | /* SoC DAI (Digital Audio Interface) */ | ||
364 | struct snd_soc_dai { | ||
365 | /* DAI description */ | ||
366 | char *name; | ||
367 | unsigned int id; | ||
368 | unsigned char type; | ||
369 | |||
370 | /* DAI callbacks */ | ||
371 | int (*probe)(struct platform_device *pdev, | ||
372 | struct snd_soc_dai *dai); | ||
373 | void (*remove)(struct platform_device *pdev, | ||
374 | struct snd_soc_dai *dai); | ||
375 | int (*suspend)(struct platform_device *pdev, | ||
376 | struct snd_soc_dai *dai); | ||
377 | int (*resume)(struct platform_device *pdev, | ||
378 | struct snd_soc_dai *dai); | ||
379 | |||
380 | /* ops */ | ||
381 | struct snd_soc_ops ops; | ||
382 | struct snd_soc_dai_ops dai_ops; | ||
383 | |||
384 | /* DAI capabilities */ | ||
385 | struct snd_soc_pcm_stream capture; | ||
386 | struct snd_soc_pcm_stream playback; | ||
387 | |||
388 | /* DAI runtime info */ | ||
389 | struct snd_pcm_runtime *runtime; | ||
390 | struct snd_soc_codec *codec; | ||
391 | unsigned int active; | ||
392 | unsigned char pop_wait:1; | ||
393 | void *dma_data; | ||
394 | |||
395 | /* DAI private data */ | ||
396 | void *private_data; | ||
397 | }; | ||
398 | |||
399 | /* SoC Audio Codec */ | 247 | /* SoC Audio Codec */ |
400 | struct snd_soc_codec { | 248 | struct snd_soc_codec { |
401 | char *name; | 249 | char *name; |
402 | struct module *owner; | 250 | struct module *owner; |
403 | struct mutex mutex; | 251 | struct mutex mutex; |
252 | struct device *dev; | ||
253 | |||
254 | struct list_head list; | ||
404 | 255 | ||
405 | /* callbacks */ | 256 | /* callbacks */ |
406 | int (*set_bias_level)(struct snd_soc_codec *, | 257 | int (*set_bias_level)(struct snd_soc_codec *, |
@@ -426,6 +277,7 @@ struct snd_soc_codec { | |||
426 | short reg_cache_step; | 277 | short reg_cache_step; |
427 | 278 | ||
428 | /* dapm */ | 279 | /* dapm */ |
280 | u32 pop_time; | ||
429 | struct list_head dapm_widgets; | 281 | struct list_head dapm_widgets; |
430 | struct list_head dapm_paths; | 282 | struct list_head dapm_paths; |
431 | enum snd_soc_bias_level bias_level; | 283 | enum snd_soc_bias_level bias_level; |
@@ -435,6 +287,11 @@ struct snd_soc_codec { | |||
435 | /* codec DAI's */ | 287 | /* codec DAI's */ |
436 | struct snd_soc_dai *dai; | 288 | struct snd_soc_dai *dai; |
437 | unsigned int num_dai; | 289 | unsigned int num_dai; |
290 | |||
291 | #ifdef CONFIG_DEBUG_FS | ||
292 | struct dentry *debugfs_reg; | ||
293 | struct dentry *debugfs_pop_time; | ||
294 | #endif | ||
438 | }; | 295 | }; |
439 | 296 | ||
440 | /* codec device */ | 297 | /* codec device */ |
@@ -448,13 +305,12 @@ struct snd_soc_codec_device { | |||
448 | /* SoC platform interface */ | 305 | /* SoC platform interface */ |
449 | struct snd_soc_platform { | 306 | struct snd_soc_platform { |
450 | char *name; | 307 | char *name; |
308 | struct list_head list; | ||
451 | 309 | ||
452 | int (*probe)(struct platform_device *pdev); | 310 | int (*probe)(struct platform_device *pdev); |
453 | int (*remove)(struct platform_device *pdev); | 311 | int (*remove)(struct platform_device *pdev); |
454 | int (*suspend)(struct platform_device *pdev, | 312 | int (*suspend)(struct snd_soc_dai *dai); |
455 | struct snd_soc_dai *dai); | 313 | int (*resume)(struct snd_soc_dai *dai); |
456 | int (*resume)(struct platform_device *pdev, | ||
457 | struct snd_soc_dai *dai); | ||
458 | 314 | ||
459 | /* pcm creation and destruction */ | 315 | /* pcm creation and destruction */ |
460 | int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, | 316 | int (*pcm_new)(struct snd_card *, struct snd_soc_dai *, |
@@ -484,9 +340,14 @@ struct snd_soc_dai_link { | |||
484 | struct snd_pcm *pcm; | 340 | struct snd_pcm *pcm; |
485 | }; | 341 | }; |
486 | 342 | ||
487 | /* SoC machine */ | 343 | /* SoC card */ |
488 | struct snd_soc_machine { | 344 | struct snd_soc_card { |
489 | char *name; | 345 | char *name; |
346 | struct device *dev; | ||
347 | |||
348 | struct list_head list; | ||
349 | |||
350 | int instantiated; | ||
490 | 351 | ||
491 | int (*probe)(struct platform_device *pdev); | 352 | int (*probe)(struct platform_device *pdev); |
492 | int (*remove)(struct platform_device *pdev); | 353 | int (*remove)(struct platform_device *pdev); |
@@ -499,23 +360,26 @@ struct snd_soc_machine { | |||
499 | int (*resume_post)(struct platform_device *pdev); | 360 | int (*resume_post)(struct platform_device *pdev); |
500 | 361 | ||
501 | /* callbacks */ | 362 | /* callbacks */ |
502 | int (*set_bias_level)(struct snd_soc_machine *, | 363 | int (*set_bias_level)(struct snd_soc_card *, |
503 | enum snd_soc_bias_level level); | 364 | enum snd_soc_bias_level level); |
504 | 365 | ||
505 | /* CPU <--> Codec DAI links */ | 366 | /* CPU <--> Codec DAI links */ |
506 | struct snd_soc_dai_link *dai_link; | 367 | struct snd_soc_dai_link *dai_link; |
507 | int num_links; | 368 | int num_links; |
369 | |||
370 | struct snd_soc_device *socdev; | ||
371 | |||
372 | struct snd_soc_platform *platform; | ||
373 | struct delayed_work delayed_work; | ||
374 | struct work_struct deferred_resume_work; | ||
508 | }; | 375 | }; |
509 | 376 | ||
510 | /* SoC Device - the audio subsystem */ | 377 | /* SoC Device - the audio subsystem */ |
511 | struct snd_soc_device { | 378 | struct snd_soc_device { |
512 | struct device *dev; | 379 | struct device *dev; |
513 | struct snd_soc_machine *machine; | 380 | struct snd_soc_card *card; |
514 | struct snd_soc_platform *platform; | ||
515 | struct snd_soc_codec *codec; | 381 | struct snd_soc_codec *codec; |
516 | struct snd_soc_codec_device *codec_dev; | 382 | struct snd_soc_codec_device *codec_dev; |
517 | struct delayed_work delayed_work; | ||
518 | struct work_struct deferred_resume_work; | ||
519 | void *codec_data; | 383 | void *codec_data; |
520 | }; | 384 | }; |
521 | 385 | ||
@@ -542,4 +406,6 @@ struct soc_enum { | |||
542 | void *dapm; | 406 | void *dapm; |
543 | }; | 407 | }; |
544 | 408 | ||
409 | #include <sound/soc-dai.h> | ||
410 | |||
545 | #endif | 411 | #endif |
diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h new file mode 100644 index 000000000000..475ef8bb7dcd --- /dev/null +++ b/include/sound/uda134x.h | |||
@@ -0,0 +1,26 @@ | |||
1 | /* | ||
2 | * uda134x.h -- UDA134x ALSA SoC Codec driver | ||
3 | * | ||
4 | * Copyright 2007 Dension Audio Systems Ltd. | ||
5 | * Author: Zoltan Devai | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef _UDA134X_H | ||
13 | #define _UDA134X_H | ||
14 | |||
15 | #include <sound/l3.h> | ||
16 | |||
17 | struct uda134x_platform_data { | ||
18 | struct l3_pins l3; | ||
19 | void (*power) (int); | ||
20 | int model; | ||
21 | #define UDA134X_UDA1340 1 | ||
22 | #define UDA134X_UDA1341 2 | ||
23 | #define UDA134X_UDA1344 3 | ||
24 | }; | ||
25 | |||
26 | #endif /* _UDA134X_H */ | ||
diff --git a/include/sound/version.h b/include/sound/version.h index 4aafeda88634..2b48237e23bf 100644 --- a/include/sound/version.h +++ b/include/sound/version.h | |||
@@ -1,3 +1,3 @@ | |||
1 | /* include/version.h */ | 1 | /* include/version.h */ |
2 | #define CONFIG_SND_VERSION "1.0.18rc3" | 2 | #define CONFIG_SND_VERSION "1.0.18a" |
3 | #define CONFIG_SND_DATE "" | 3 | #define CONFIG_SND_DATE "" |
diff --git a/include/video/radeon.h b/include/video/radeon.h index d5dcaf154ba4..1cd09cc5b169 100644 --- a/include/video/radeon.h +++ b/include/video/radeon.h | |||
@@ -525,9 +525,6 @@ | |||
525 | #define CRTC_DISPLAY_DIS (1 << 10) | 525 | #define CRTC_DISPLAY_DIS (1 << 10) |
526 | #define CRTC_CRT_ON (1 << 15) | 526 | #define CRTC_CRT_ON (1 << 15) |
527 | 527 | ||
528 | /* DSTCACHE_MODE bits constants */ | ||
529 | #define RB2D_DC_AUTOFLUSH_ENABLE (1 << 8) | ||
530 | #define RB2D_DC_DC_DISABLE_IGNORE_PE (1 << 17) | ||
531 | 528 | ||
532 | /* DSTCACHE_CTLSTAT bit constants */ | 529 | /* DSTCACHE_CTLSTAT bit constants */ |
533 | #define RB2D_DC_FLUSH_2D (1 << 0) | 530 | #define RB2D_DC_FLUSH_2D (1 << 0) |
@@ -869,10 +866,15 @@ | |||
869 | #define GMC_DST_16BPP_YVYU422 0x00000c00 | 866 | #define GMC_DST_16BPP_YVYU422 0x00000c00 |
870 | #define GMC_DST_32BPP_AYUV444 0x00000e00 | 867 | #define GMC_DST_32BPP_AYUV444 0x00000e00 |
871 | #define GMC_DST_16BPP_ARGB4444 0x00000f00 | 868 | #define GMC_DST_16BPP_ARGB4444 0x00000f00 |
869 | #define GMC_SRC_MONO 0x00000000 | ||
870 | #define GMC_SRC_MONO_LBKGD 0x00001000 | ||
871 | #define GMC_SRC_DSTCOLOR 0x00003000 | ||
872 | #define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 | 872 | #define GMC_BYTE_ORDER_MSB_TO_LSB 0x00000000 |
873 | #define GMC_BYTE_ORDER_LSB_TO_MSB 0x00004000 | 873 | #define GMC_BYTE_ORDER_LSB_TO_MSB 0x00004000 |
874 | #define GMC_DP_CONVERSION_TEMP_9300 0x00008000 | 874 | #define GMC_DP_CONVERSION_TEMP_9300 0x00008000 |
875 | #define GMC_DP_CONVERSION_TEMP_6500 0x00000000 | 875 | #define GMC_DP_CONVERSION_TEMP_6500 0x00000000 |
876 | #define GMC_DP_SRC_RECT 0x02000000 | ||
877 | #define GMC_DP_SRC_HOST 0x03000000 | ||
876 | #define GMC_DP_SRC_HOST_BYTEALIGN 0x04000000 | 878 | #define GMC_DP_SRC_HOST_BYTEALIGN 0x04000000 |
877 | #define GMC_3D_FCN_EN_CLR 0x00000000 | 879 | #define GMC_3D_FCN_EN_CLR 0x00000000 |
878 | #define GMC_3D_FCN_EN_SET 0x08000000 | 880 | #define GMC_3D_FCN_EN_SET 0x08000000 |
@@ -883,9 +885,6 @@ | |||
883 | #define GMC_WRITE_MASK_LEAVE 0x00000000 | 885 | #define GMC_WRITE_MASK_LEAVE 0x00000000 |
884 | #define GMC_WRITE_MASK_SET 0x40000000 | 886 | #define GMC_WRITE_MASK_SET 0x40000000 |
885 | #define GMC_CLR_CMP_CNTL_DIS (1 << 28) | 887 | #define GMC_CLR_CMP_CNTL_DIS (1 << 28) |
886 | #define GMC_SRC_DATATYPE_MASK (3 << 12) | ||
887 | #define GMC_SRC_DATATYPE_MONO_FG_BG (0 << 12) | ||
888 | #define GMC_SRC_DATATYPE_MONO_FG_LA (1 << 12) | ||
889 | #define GMC_SRC_DATATYPE_COLOR (3 << 12) | 888 | #define GMC_SRC_DATATYPE_COLOR (3 << 12) |
890 | #define ROP3_S 0x00cc0000 | 889 | #define ROP3_S 0x00cc0000 |
891 | #define ROP3_SRCCOPY 0x00cc0000 | 890 | #define ROP3_SRCCOPY 0x00cc0000 |
@@ -894,7 +893,6 @@ | |||
894 | #define DP_SRC_SOURCE_MASK (7 << 24) | 893 | #define DP_SRC_SOURCE_MASK (7 << 24) |
895 | #define GMC_BRUSH_NONE (15 << 4) | 894 | #define GMC_BRUSH_NONE (15 << 4) |
896 | #define DP_SRC_SOURCE_MEMORY (2 << 24) | 895 | #define DP_SRC_SOURCE_MEMORY (2 << 24) |
897 | #define DP_SRC_SOURCE_HOST_DATA (3 << 24) | ||
898 | #define GMC_BRUSH_SOLIDCOLOR 0x000000d0 | 896 | #define GMC_BRUSH_SOLIDCOLOR 0x000000d0 |
899 | 897 | ||
900 | /* DP_MIX bit constants */ | 898 | /* DP_MIX bit constants */ |
@@ -980,12 +978,6 @@ | |||
980 | #define DISP_PWR_MAN_TV_ENABLE_RST (1 << 25) | 978 | #define DISP_PWR_MAN_TV_ENABLE_RST (1 << 25) |
981 | #define DISP_PWR_MAN_AUTO_PWRUP_EN (1 << 26) | 979 | #define DISP_PWR_MAN_AUTO_PWRUP_EN (1 << 26) |
982 | 980 | ||
983 | /* RBBM_GUICNTL constants */ | ||
984 | #define RBBM_GUICNTL_HOST_DATA_SWAP_NONE (0 << 0) | ||
985 | #define RBBM_GUICNTL_HOST_DATA_SWAP_16BIT (1 << 0) | ||
986 | #define RBBM_GUICNTL_HOST_DATA_SWAP_32BIT (2 << 0) | ||
987 | #define RBBM_GUICNTL_HOST_DATA_SWAP_HDW (3 << 0) | ||
988 | |||
989 | /* masks */ | 981 | /* masks */ |
990 | 982 | ||
991 | #define CONFIG_MEMSIZE_MASK 0x1f000000 | 983 | #define CONFIG_MEMSIZE_MASK 0x1f000000 |
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index fe00b3b983a8..2606d0fb4e54 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -702,7 +702,7 @@ static int rebind_subsystems(struct cgroupfs_root *root, | |||
702 | * any child cgroups exist. This is theoretically supportable | 702 | * any child cgroups exist. This is theoretically supportable |
703 | * but involves complex error handling, so it's being left until | 703 | * but involves complex error handling, so it's being left until |
704 | * later */ | 704 | * later */ |
705 | if (!list_empty(&cgrp->children)) | 705 | if (root->number_of_cgroups > 1) |
706 | return -EBUSY; | 706 | return -EBUSY; |
707 | 707 | ||
708 | /* Process each subsystem */ | 708 | /* Process each subsystem */ |
@@ -1024,7 +1024,7 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1024 | if (ret == -EBUSY) { | 1024 | if (ret == -EBUSY) { |
1025 | mutex_unlock(&cgroup_mutex); | 1025 | mutex_unlock(&cgroup_mutex); |
1026 | mutex_unlock(&inode->i_mutex); | 1026 | mutex_unlock(&inode->i_mutex); |
1027 | goto drop_new_super; | 1027 | goto free_cg_links; |
1028 | } | 1028 | } |
1029 | 1029 | ||
1030 | /* EBUSY should be the only error here */ | 1030 | /* EBUSY should be the only error here */ |
@@ -1073,10 +1073,11 @@ static int cgroup_get_sb(struct file_system_type *fs_type, | |||
1073 | 1073 | ||
1074 | return simple_set_mnt(mnt, sb); | 1074 | return simple_set_mnt(mnt, sb); |
1075 | 1075 | ||
1076 | free_cg_links: | ||
1077 | free_cg_links(&tmp_cg_links); | ||
1076 | drop_new_super: | 1078 | drop_new_super: |
1077 | up_write(&sb->s_umount); | 1079 | up_write(&sb->s_umount); |
1078 | deactivate_super(sb); | 1080 | deactivate_super(sb); |
1079 | free_cg_links(&tmp_cg_links); | ||
1080 | return ret; | 1081 | return ret; |
1081 | } | 1082 | } |
1082 | 1083 | ||
@@ -2934,9 +2935,6 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, | |||
2934 | again: | 2935 | again: |
2935 | root = subsys->root; | 2936 | root = subsys->root; |
2936 | if (root == &rootnode) { | 2937 | if (root == &rootnode) { |
2937 | printk(KERN_INFO | ||
2938 | "Not cloning cgroup for unused subsystem %s\n", | ||
2939 | subsys->name); | ||
2940 | mutex_unlock(&cgroup_mutex); | 2938 | mutex_unlock(&cgroup_mutex); |
2941 | return 0; | 2939 | return 0; |
2942 | } | 2940 | } |
diff --git a/kernel/posix-timers.c b/kernel/posix-timers.c index 5e79c662294b..a140e44eebba 100644 --- a/kernel/posix-timers.c +++ b/kernel/posix-timers.c | |||
@@ -197,6 +197,11 @@ static int common_timer_create(struct k_itimer *new_timer) | |||
197 | return 0; | 197 | return 0; |
198 | } | 198 | } |
199 | 199 | ||
200 | static int no_timer_create(struct k_itimer *new_timer) | ||
201 | { | ||
202 | return -EOPNOTSUPP; | ||
203 | } | ||
204 | |||
200 | /* | 205 | /* |
201 | * Return nonzero if we know a priori this clockid_t value is bogus. | 206 | * Return nonzero if we know a priori this clockid_t value is bogus. |
202 | */ | 207 | */ |
@@ -248,6 +253,7 @@ static __init int init_posix_timers(void) | |||
248 | .clock_getres = hrtimer_get_res, | 253 | .clock_getres = hrtimer_get_res, |
249 | .clock_get = posix_get_monotonic_raw, | 254 | .clock_get = posix_get_monotonic_raw, |
250 | .clock_set = do_posix_clock_nosettime, | 255 | .clock_set = do_posix_clock_nosettime, |
256 | .timer_create = no_timer_create, | ||
251 | }; | 257 | }; |
252 | 258 | ||
253 | register_posix_clock(CLOCK_REALTIME, &clock_realtime); | 259 | register_posix_clock(CLOCK_REALTIME, &clock_realtime); |
diff --git a/kernel/sched_clock.c b/kernel/sched_clock.c index 81787248b60f..e8ab096ddfe3 100644 --- a/kernel/sched_clock.c +++ b/kernel/sched_clock.c | |||
@@ -118,13 +118,13 @@ static u64 __update_sched_clock(struct sched_clock_data *scd, u64 now) | |||
118 | 118 | ||
119 | /* | 119 | /* |
120 | * scd->clock = clamp(scd->tick_gtod + delta, | 120 | * scd->clock = clamp(scd->tick_gtod + delta, |
121 | * max(scd->tick_gtod, scd->clock), | 121 | * max(scd->tick_gtod, scd->clock), |
122 | * max(scd->clock, scd->tick_gtod + TICK_NSEC)); | 122 | * scd->tick_gtod + TICK_NSEC); |
123 | */ | 123 | */ |
124 | 124 | ||
125 | clock = scd->tick_gtod + delta; | 125 | clock = scd->tick_gtod + delta; |
126 | min_clock = wrap_max(scd->tick_gtod, scd->clock); | 126 | min_clock = wrap_max(scd->tick_gtod, scd->clock); |
127 | max_clock = wrap_max(scd->clock, scd->tick_gtod + TICK_NSEC); | 127 | max_clock = scd->tick_gtod + TICK_NSEC; |
128 | 128 | ||
129 | clock = wrap_max(clock, min_clock); | 129 | clock = wrap_max(clock, min_clock); |
130 | clock = wrap_min(clock, max_clock); | 130 | clock = wrap_min(clock, max_clock); |
diff --git a/lib/dynamic_printk.c b/lib/dynamic_printk.c index d83660fd6fdd..8e30295e8566 100644 --- a/lib/dynamic_printk.c +++ b/lib/dynamic_printk.c | |||
@@ -135,7 +135,7 @@ int unregister_dynamic_debug_module(char *mod_name) | |||
135 | nr_entries--; | 135 | nr_entries--; |
136 | out: | 136 | out: |
137 | up(&debug_list_mutex); | 137 | up(&debug_list_mutex); |
138 | return 0; | 138 | return ret; |
139 | } | 139 | } |
140 | EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module); | 140 | EXPORT_SYMBOL_GPL(unregister_dynamic_debug_module); |
141 | 141 | ||
@@ -289,7 +289,7 @@ static ssize_t pr_debug_write(struct file *file, const char __user *buf, | |||
289 | dynamic_enabled = DYNAMIC_ENABLED_SOME; | 289 | dynamic_enabled = DYNAMIC_ENABLED_SOME; |
290 | err = 0; | 290 | err = 0; |
291 | printk(KERN_DEBUG | 291 | printk(KERN_DEBUG |
292 | "debugging enabled for module %s", | 292 | "debugging enabled for module %s\n", |
293 | elem->name); | 293 | elem->name); |
294 | } else if (!value && (elem->enable == 1)) { | 294 | } else if (!value && (elem->enable == 1)) { |
295 | elem->enable = 0; | 295 | elem->enable = 0; |
@@ -309,7 +309,7 @@ static ssize_t pr_debug_write(struct file *file, const char __user *buf, | |||
309 | err = 0; | 309 | err = 0; |
310 | printk(KERN_DEBUG | 310 | printk(KERN_DEBUG |
311 | "debugging disabled for module " | 311 | "debugging disabled for module " |
312 | "%s", elem->name); | 312 | "%s\n", elem->name); |
313 | } | 313 | } |
314 | } | 314 | } |
315 | } | 315 | } |
diff --git a/mm/migrate.c b/mm/migrate.c index d8f07667fc80..037b0967c1e3 100644 --- a/mm/migrate.c +++ b/mm/migrate.c | |||
@@ -998,7 +998,7 @@ static void do_pages_stat_array(struct mm_struct *mm, unsigned long nr_pages, | |||
998 | unsigned long addr = (unsigned long)(*pages); | 998 | unsigned long addr = (unsigned long)(*pages); |
999 | struct vm_area_struct *vma; | 999 | struct vm_area_struct *vma; |
1000 | struct page *page; | 1000 | struct page *page; |
1001 | int err; | 1001 | int err = -EFAULT; |
1002 | 1002 | ||
1003 | vma = find_vma(mm, addr); | 1003 | vma = find_vma(mm, addr); |
1004 | if (!vma) | 1004 | if (!vma) |
@@ -535,7 +535,7 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, | |||
535 | struct kmem_cache *c; | 535 | struct kmem_cache *c; |
536 | 536 | ||
537 | c = slob_alloc(sizeof(struct kmem_cache), | 537 | c = slob_alloc(sizeof(struct kmem_cache), |
538 | flags, ARCH_KMALLOC_MINALIGN, -1); | 538 | GFP_KERNEL, ARCH_KMALLOC_MINALIGN, -1); |
539 | 539 | ||
540 | if (c) { | 540 | if (c) { |
541 | c->name = name; | 541 | c->name = name; |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ba537fae0a4c..ce68e046d963 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -1786,8 +1786,6 @@ static inline void rfcomm_accept_connection(struct rfcomm_session *s) | |||
1786 | if (err < 0) | 1786 | if (err < 0) |
1787 | return; | 1787 | return; |
1788 | 1788 | ||
1789 | __module_get(nsock->ops->owner); | ||
1790 | |||
1791 | /* Set our callbacks */ | 1789 | /* Set our callbacks */ |
1792 | nsock->sk->sk_data_ready = rfcomm_l2data_ready; | 1790 | nsock->sk->sk_data_ready = rfcomm_l2data_ready; |
1793 | nsock->sk->sk_state_change = rfcomm_l2state_change; | 1791 | nsock->sk->sk_state_change = rfcomm_l2state_change; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 6c7af390be0a..dadac6281f20 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -133,9 +133,11 @@ static int poll_one_napi(struct netpoll_info *npinfo, | |||
133 | 133 | ||
134 | npinfo->rx_flags |= NETPOLL_RX_DROP; | 134 | npinfo->rx_flags |= NETPOLL_RX_DROP; |
135 | atomic_inc(&trapped); | 135 | atomic_inc(&trapped); |
136 | set_bit(NAPI_STATE_NPSVC, &napi->state); | ||
136 | 137 | ||
137 | work = napi->poll(napi, budget); | 138 | work = napi->poll(napi, budget); |
138 | 139 | ||
140 | clear_bit(NAPI_STATE_NPSVC, &napi->state); | ||
139 | atomic_dec(&trapped); | 141 | atomic_dec(&trapped); |
140 | npinfo->rx_flags &= ~NETPOLL_RX_DROP; | 142 | npinfo->rx_flags &= ~NETPOLL_RX_DROP; |
141 | 143 | ||
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index bea54a685109..8d489e746b21 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
@@ -61,7 +61,7 @@ static struct | |||
61 | static struct xt_table nat_table = { | 61 | static struct xt_table nat_table = { |
62 | .name = "nat", | 62 | .name = "nat", |
63 | .valid_hooks = NAT_VALID_HOOKS, | 63 | .valid_hooks = NAT_VALID_HOOKS, |
64 | .lock = __RW_LOCK_UNLOCKED(__nat_table.lock), | 64 | .lock = __RW_LOCK_UNLOCKED(nat_table.lock), |
65 | .me = THIS_MODULE, | 65 | .me = THIS_MODULE, |
66 | .af = AF_INET, | 66 | .af = AF_INET, |
67 | }; | 67 | }; |
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index 7cd22262de3a..a453aac91bd3 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
@@ -40,18 +40,14 @@ | |||
40 | 40 | ||
41 | #include "tcp_vegas.h" | 41 | #include "tcp_vegas.h" |
42 | 42 | ||
43 | /* Default values of the Vegas variables, in fixed-point representation | 43 | static int alpha = 2; |
44 | * with V_PARAM_SHIFT bits to the right of the binary point. | 44 | static int beta = 4; |
45 | */ | 45 | static int gamma = 1; |
46 | #define V_PARAM_SHIFT 1 | ||
47 | static int alpha = 2<<V_PARAM_SHIFT; | ||
48 | static int beta = 4<<V_PARAM_SHIFT; | ||
49 | static int gamma = 1<<V_PARAM_SHIFT; | ||
50 | 46 | ||
51 | module_param(alpha, int, 0644); | 47 | module_param(alpha, int, 0644); |
52 | MODULE_PARM_DESC(alpha, "lower bound of packets in network (scale by 2)"); | 48 | MODULE_PARM_DESC(alpha, "lower bound of packets in network"); |
53 | module_param(beta, int, 0644); | 49 | module_param(beta, int, 0644); |
54 | MODULE_PARM_DESC(beta, "upper bound of packets in network (scale by 2)"); | 50 | MODULE_PARM_DESC(beta, "upper bound of packets in network"); |
55 | module_param(gamma, int, 0644); | 51 | module_param(gamma, int, 0644); |
56 | MODULE_PARM_DESC(gamma, "limit on increase (scale by 2)"); | 52 | MODULE_PARM_DESC(gamma, "limit on increase (scale by 2)"); |
57 | 53 | ||
@@ -172,49 +168,13 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | |||
172 | return; | 168 | return; |
173 | } | 169 | } |
174 | 170 | ||
175 | /* The key players are v_beg_snd_una and v_beg_snd_nxt. | ||
176 | * | ||
177 | * These are so named because they represent the approximate values | ||
178 | * of snd_una and snd_nxt at the beginning of the current RTT. More | ||
179 | * precisely, they represent the amount of data sent during the RTT. | ||
180 | * At the end of the RTT, when we receive an ACK for v_beg_snd_nxt, | ||
181 | * we will calculate that (v_beg_snd_nxt - v_beg_snd_una) outstanding | ||
182 | * bytes of data have been ACKed during the course of the RTT, giving | ||
183 | * an "actual" rate of: | ||
184 | * | ||
185 | * (v_beg_snd_nxt - v_beg_snd_una) / (rtt duration) | ||
186 | * | ||
187 | * Unfortunately, v_beg_snd_una is not exactly equal to snd_una, | ||
188 | * because delayed ACKs can cover more than one segment, so they | ||
189 | * don't line up nicely with the boundaries of RTTs. | ||
190 | * | ||
191 | * Another unfortunate fact of life is that delayed ACKs delay the | ||
192 | * advance of the left edge of our send window, so that the number | ||
193 | * of bytes we send in an RTT is often less than our cwnd will allow. | ||
194 | * So we keep track of our cwnd separately, in v_beg_snd_cwnd. | ||
195 | */ | ||
196 | |||
197 | if (after(ack, vegas->beg_snd_nxt)) { | 171 | if (after(ack, vegas->beg_snd_nxt)) { |
198 | /* Do the Vegas once-per-RTT cwnd adjustment. */ | 172 | /* Do the Vegas once-per-RTT cwnd adjustment. */ |
199 | u32 old_wnd, old_snd_cwnd; | ||
200 | |||
201 | |||
202 | /* Here old_wnd is essentially the window of data that was | ||
203 | * sent during the previous RTT, and has all | ||
204 | * been acknowledged in the course of the RTT that ended | ||
205 | * with the ACK we just received. Likewise, old_snd_cwnd | ||
206 | * is the cwnd during the previous RTT. | ||
207 | */ | ||
208 | old_wnd = (vegas->beg_snd_nxt - vegas->beg_snd_una) / | ||
209 | tp->mss_cache; | ||
210 | old_snd_cwnd = vegas->beg_snd_cwnd; | ||
211 | 173 | ||
212 | /* Save the extent of the current window so we can use this | 174 | /* Save the extent of the current window so we can use this |
213 | * at the end of the next RTT. | 175 | * at the end of the next RTT. |
214 | */ | 176 | */ |
215 | vegas->beg_snd_una = vegas->beg_snd_nxt; | ||
216 | vegas->beg_snd_nxt = tp->snd_nxt; | 177 | vegas->beg_snd_nxt = tp->snd_nxt; |
217 | vegas->beg_snd_cwnd = tp->snd_cwnd; | ||
218 | 178 | ||
219 | /* We do the Vegas calculations only if we got enough RTT | 179 | /* We do the Vegas calculations only if we got enough RTT |
220 | * samples that we can be reasonably sure that we got | 180 | * samples that we can be reasonably sure that we got |
@@ -252,22 +212,14 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | |||
252 | * | 212 | * |
253 | * This is: | 213 | * This is: |
254 | * (actual rate in segments) * baseRTT | 214 | * (actual rate in segments) * baseRTT |
255 | * We keep it as a fixed point number with | ||
256 | * V_PARAM_SHIFT bits to the right of the binary point. | ||
257 | */ | 215 | */ |
258 | target_cwnd = ((u64)old_wnd * vegas->baseRTT); | 216 | target_cwnd = tp->snd_cwnd * vegas->baseRTT / rtt; |
259 | target_cwnd <<= V_PARAM_SHIFT; | ||
260 | do_div(target_cwnd, rtt); | ||
261 | 217 | ||
262 | /* Calculate the difference between the window we had, | 218 | /* Calculate the difference between the window we had, |
263 | * and the window we would like to have. This quantity | 219 | * and the window we would like to have. This quantity |
264 | * is the "Diff" from the Arizona Vegas papers. | 220 | * is the "Diff" from the Arizona Vegas papers. |
265 | * | ||
266 | * Again, this is a fixed point number with | ||
267 | * V_PARAM_SHIFT bits to the right of the binary | ||
268 | * point. | ||
269 | */ | 221 | */ |
270 | diff = (old_wnd << V_PARAM_SHIFT) - target_cwnd; | 222 | diff = tp->snd_cwnd * (rtt-vegas->baseRTT) / vegas->baseRTT; |
271 | 223 | ||
272 | if (diff > gamma && tp->snd_ssthresh > 2 ) { | 224 | if (diff > gamma && tp->snd_ssthresh > 2 ) { |
273 | /* Going too fast. Time to slow down | 225 | /* Going too fast. Time to slow down |
@@ -282,16 +234,13 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | |||
282 | * truncation robs us of full link | 234 | * truncation robs us of full link |
283 | * utilization. | 235 | * utilization. |
284 | */ | 236 | */ |
285 | tp->snd_cwnd = min(tp->snd_cwnd, | 237 | tp->snd_cwnd = min(tp->snd_cwnd, (u32)target_cwnd+1); |
286 | ((u32)target_cwnd >> | ||
287 | V_PARAM_SHIFT)+1); | ||
288 | 238 | ||
289 | } else if (tp->snd_cwnd <= tp->snd_ssthresh) { | 239 | } else if (tp->snd_cwnd <= tp->snd_ssthresh) { |
290 | /* Slow start. */ | 240 | /* Slow start. */ |
291 | tcp_slow_start(tp); | 241 | tcp_slow_start(tp); |
292 | } else { | 242 | } else { |
293 | /* Congestion avoidance. */ | 243 | /* Congestion avoidance. */ |
294 | u32 next_snd_cwnd; | ||
295 | 244 | ||
296 | /* Figure out where we would like cwnd | 245 | /* Figure out where we would like cwnd |
297 | * to be. | 246 | * to be. |
@@ -300,26 +249,17 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 in_flight) | |||
300 | /* The old window was too fast, so | 249 | /* The old window was too fast, so |
301 | * we slow down. | 250 | * we slow down. |
302 | */ | 251 | */ |
303 | next_snd_cwnd = old_snd_cwnd - 1; | 252 | tp->snd_cwnd--; |
304 | } else if (diff < alpha) { | 253 | } else if (diff < alpha) { |
305 | /* We don't have enough extra packets | 254 | /* We don't have enough extra packets |
306 | * in the network, so speed up. | 255 | * in the network, so speed up. |
307 | */ | 256 | */ |
308 | next_snd_cwnd = old_snd_cwnd + 1; | 257 | tp->snd_cwnd++; |
309 | } else { | 258 | } else { |
310 | /* Sending just as fast as we | 259 | /* Sending just as fast as we |
311 | * should be. | 260 | * should be. |
312 | */ | 261 | */ |
313 | next_snd_cwnd = old_snd_cwnd; | ||
314 | } | 262 | } |
315 | |||
316 | /* Adjust cwnd upward or downward, toward the | ||
317 | * desired value. | ||
318 | */ | ||
319 | if (next_snd_cwnd > tp->snd_cwnd) | ||
320 | tp->snd_cwnd++; | ||
321 | else if (next_snd_cwnd < tp->snd_cwnd) | ||
322 | tp->snd_cwnd--; | ||
323 | } | 263 | } |
324 | 264 | ||
325 | if (tp->snd_cwnd < 2) | 265 | if (tp->snd_cwnd < 2) |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 172438320eec..d0f54d18e19b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -912,8 +912,13 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
912 | is invalid, but ndisc specs say nothing | 912 | is invalid, but ndisc specs say nothing |
913 | about it. It could be misconfiguration, or | 913 | about it. It could be misconfiguration, or |
914 | an smart proxy agent tries to help us :-) | 914 | an smart proxy agent tries to help us :-) |
915 | |||
916 | We should not print the error if NA has been | ||
917 | received from loopback - it is just our own | ||
918 | unsolicited advertisement. | ||
915 | */ | 919 | */ |
916 | ND_PRINTK1(KERN_WARNING | 920 | if (skb->pkt_type != PACKET_LOOPBACK) |
921 | ND_PRINTK1(KERN_WARNING | ||
917 | "ICMPv6 NA: someone advertises our address on %s!\n", | 922 | "ICMPv6 NA: someone advertises our address on %s!\n", |
918 | ifp->idev->dev->name); | 923 | ifp->idev->dev->name); |
919 | in6_ifa_put(ifp); | 924 | in6_ifa_put(ifp); |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index 90c8506a0aac..8c0308032178 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -562,7 +562,6 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, | |||
562 | const struct in_addr *mask, | 562 | const struct in_addr *mask, |
563 | struct netlbl_audit *audit_info) | 563 | struct netlbl_audit *audit_info) |
564 | { | 564 | { |
565 | int ret_val = 0; | ||
566 | struct netlbl_af4list *list_entry; | 565 | struct netlbl_af4list *list_entry; |
567 | struct netlbl_unlhsh_addr4 *entry; | 566 | struct netlbl_unlhsh_addr4 *entry; |
568 | struct audit_buffer *audit_buf; | 567 | struct audit_buffer *audit_buf; |
@@ -577,7 +576,7 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, | |||
577 | if (list_entry != NULL) | 576 | if (list_entry != NULL) |
578 | entry = netlbl_unlhsh_addr4_entry(list_entry); | 577 | entry = netlbl_unlhsh_addr4_entry(list_entry); |
579 | else | 578 | else |
580 | ret_val = -ENOENT; | 579 | entry = NULL; |
581 | 580 | ||
582 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, | 581 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, |
583 | audit_info); | 582 | audit_info); |
@@ -588,19 +587,21 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, | |||
588 | addr->s_addr, mask->s_addr); | 587 | addr->s_addr, mask->s_addr); |
589 | if (dev != NULL) | 588 | if (dev != NULL) |
590 | dev_put(dev); | 589 | dev_put(dev); |
591 | if (entry && security_secid_to_secctx(entry->secid, | 590 | if (entry != NULL && |
592 | &secctx, | 591 | security_secid_to_secctx(entry->secid, |
593 | &secctx_len) == 0) { | 592 | &secctx, &secctx_len) == 0) { |
594 | audit_log_format(audit_buf, " sec_obj=%s", secctx); | 593 | audit_log_format(audit_buf, " sec_obj=%s", secctx); |
595 | security_release_secctx(secctx, secctx_len); | 594 | security_release_secctx(secctx, secctx_len); |
596 | } | 595 | } |
597 | audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); | 596 | audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); |
598 | audit_log_end(audit_buf); | 597 | audit_log_end(audit_buf); |
599 | } | 598 | } |
600 | 599 | ||
601 | if (ret_val == 0) | 600 | if (entry == NULL) |
602 | call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4); | 601 | return -ENOENT; |
603 | return ret_val; | 602 | |
603 | call_rcu(&entry->rcu, netlbl_unlhsh_free_addr4); | ||
604 | return 0; | ||
604 | } | 605 | } |
605 | 606 | ||
606 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 607 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
@@ -624,7 +625,6 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, | |||
624 | const struct in6_addr *mask, | 625 | const struct in6_addr *mask, |
625 | struct netlbl_audit *audit_info) | 626 | struct netlbl_audit *audit_info) |
626 | { | 627 | { |
627 | int ret_val = 0; | ||
628 | struct netlbl_af6list *list_entry; | 628 | struct netlbl_af6list *list_entry; |
629 | struct netlbl_unlhsh_addr6 *entry; | 629 | struct netlbl_unlhsh_addr6 *entry; |
630 | struct audit_buffer *audit_buf; | 630 | struct audit_buffer *audit_buf; |
@@ -638,7 +638,7 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, | |||
638 | if (list_entry != NULL) | 638 | if (list_entry != NULL) |
639 | entry = netlbl_unlhsh_addr6_entry(list_entry); | 639 | entry = netlbl_unlhsh_addr6_entry(list_entry); |
640 | else | 640 | else |
641 | ret_val = -ENOENT; | 641 | entry = NULL; |
642 | 642 | ||
643 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, | 643 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_UNLBL_STCDEL, |
644 | audit_info); | 644 | audit_info); |
@@ -649,19 +649,21 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, | |||
649 | addr, mask); | 649 | addr, mask); |
650 | if (dev != NULL) | 650 | if (dev != NULL) |
651 | dev_put(dev); | 651 | dev_put(dev); |
652 | if (entry && security_secid_to_secctx(entry->secid, | 652 | if (entry != NULL && |
653 | &secctx, | 653 | security_secid_to_secctx(entry->secid, |
654 | &secctx_len) == 0) { | 654 | &secctx, &secctx_len) == 0) { |
655 | audit_log_format(audit_buf, " sec_obj=%s", secctx); | 655 | audit_log_format(audit_buf, " sec_obj=%s", secctx); |
656 | security_release_secctx(secctx, secctx_len); | 656 | security_release_secctx(secctx, secctx_len); |
657 | } | 657 | } |
658 | audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); | 658 | audit_log_format(audit_buf, " res=%u", entry != NULL ? 1 : 0); |
659 | audit_log_end(audit_buf); | 659 | audit_log_end(audit_buf); |
660 | } | 660 | } |
661 | 661 | ||
662 | if (ret_val == 0) | 662 | if (entry == NULL) |
663 | call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6); | 663 | return -ENOENT; |
664 | return ret_val; | 664 | |
665 | call_rcu(&entry->rcu, netlbl_unlhsh_free_addr6); | ||
666 | return 0; | ||
665 | } | 667 | } |
666 | #endif /* IPv6 */ | 668 | #endif /* IPv6 */ |
667 | 669 | ||
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index 9978afbd9f2a..803eeef0aa85 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c | |||
@@ -155,12 +155,13 @@ static void gprs_data_ready(struct sock *sk, int len) | |||
155 | static void gprs_write_space(struct sock *sk) | 155 | static void gprs_write_space(struct sock *sk) |
156 | { | 156 | { |
157 | struct gprs_dev *dev = sk->sk_user_data; | 157 | struct gprs_dev *dev = sk->sk_user_data; |
158 | struct net_device *net = dev->net; | ||
158 | unsigned credits = pep_writeable(sk); | 159 | unsigned credits = pep_writeable(sk); |
159 | 160 | ||
160 | spin_lock_bh(&dev->tx_lock); | 161 | spin_lock_bh(&dev->tx_lock); |
161 | dev->tx_max = credits; | 162 | dev->tx_max = credits; |
162 | if (credits > skb_queue_len(&dev->tx_queue)) | 163 | if (credits > skb_queue_len(&dev->tx_queue) && netif_running(net)) |
163 | netif_wake_queue(dev->net); | 164 | netif_wake_queue(net); |
164 | spin_unlock_bh(&dev->tx_lock); | 165 | spin_unlock_bh(&dev->tx_lock); |
165 | } | 166 | } |
166 | 167 | ||
@@ -168,6 +169,23 @@ static void gprs_write_space(struct sock *sk) | |||
168 | * Network device callbacks | 169 | * Network device callbacks |
169 | */ | 170 | */ |
170 | 171 | ||
172 | static int gprs_open(struct net_device *dev) | ||
173 | { | ||
174 | struct gprs_dev *gp = netdev_priv(dev); | ||
175 | |||
176 | gprs_write_space(gp->sk); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | static int gprs_close(struct net_device *dev) | ||
181 | { | ||
182 | struct gprs_dev *gp = netdev_priv(dev); | ||
183 | |||
184 | netif_stop_queue(dev); | ||
185 | flush_work(&gp->tx_work); | ||
186 | return 0; | ||
187 | } | ||
188 | |||
171 | static int gprs_xmit(struct sk_buff *skb, struct net_device *net) | 189 | static int gprs_xmit(struct sk_buff *skb, struct net_device *net) |
172 | { | 190 | { |
173 | struct gprs_dev *dev = netdev_priv(net); | 191 | struct gprs_dev *dev = netdev_priv(net); |
@@ -254,6 +272,8 @@ static void gprs_setup(struct net_device *net) | |||
254 | net->tx_queue_len = 10; | 272 | net->tx_queue_len = 10; |
255 | 273 | ||
256 | net->destructor = free_netdev; | 274 | net->destructor = free_netdev; |
275 | net->open = gprs_open; | ||
276 | net->stop = gprs_close; | ||
257 | net->hard_start_xmit = gprs_xmit; /* mandatory */ | 277 | net->hard_start_xmit = gprs_xmit; /* mandatory */ |
258 | net->change_mtu = gprs_set_mtu; | 278 | net->change_mtu = gprs_set_mtu; |
259 | net->get_stats = gprs_get_stats; | 279 | net->get_stats = gprs_get_stats; |
@@ -318,7 +338,6 @@ int gprs_attach(struct sock *sk) | |||
318 | dev->sk = sk; | 338 | dev->sk = sk; |
319 | 339 | ||
320 | printk(KERN_DEBUG"%s: attached\n", net->name); | 340 | printk(KERN_DEBUG"%s: attached\n", net->name); |
321 | gprs_write_space(sk); /* kick off TX */ | ||
322 | return net->ifindex; | 341 | return net->ifindex; |
323 | 342 | ||
324 | out_rel: | 343 | out_rel: |
@@ -341,7 +360,5 @@ void gprs_detach(struct sock *sk) | |||
341 | 360 | ||
342 | printk(KERN_DEBUG"%s: detached\n", net->name); | 361 | printk(KERN_DEBUG"%s: detached\n", net->name); |
343 | unregister_netdev(net); | 362 | unregister_netdev(net); |
344 | flush_scheduled_work(); | ||
345 | sock_put(sk); | 363 | sock_put(sk); |
346 | skb_queue_purge(&dev->tx_queue); | ||
347 | } | 364 | } |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index a11959908d9a..98402f0efa47 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -46,9 +46,6 @@ | |||
46 | layering other disciplines. It does not need to do bandwidth | 46 | layering other disciplines. It does not need to do bandwidth |
47 | control either since that can be handled by using token | 47 | control either since that can be handled by using token |
48 | bucket or other rate control. | 48 | bucket or other rate control. |
49 | |||
50 | The simulator is limited by the Linux timer resolution | ||
51 | and will create packet bursts on the HZ boundary (1ms). | ||
52 | */ | 49 | */ |
53 | 50 | ||
54 | struct netem_sched_data { | 51 | struct netem_sched_data { |
diff --git a/net/socket.c b/net/socket.c index 92764d836891..76ba80aeac1a 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2307,6 +2307,7 @@ int kernel_accept(struct socket *sock, struct socket **newsock, int flags) | |||
2307 | } | 2307 | } |
2308 | 2308 | ||
2309 | (*newsock)->ops = sock->ops; | 2309 | (*newsock)->ops = sock->ops; |
2310 | __module_get((*newsock)->ops->owner); | ||
2310 | 2311 | ||
2311 | done: | 2312 | done: |
2312 | return err; | 2313 | return err; |
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c index 7fa37e15f196..a351dd0a09c7 100644 --- a/sound/ac97_bus.c +++ b/sound/ac97_bus.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <sound/ac97_codec.h> | ||
18 | 19 | ||
19 | /* | 20 | /* |
20 | * Let drivers decide whether they want to support given codec from their | 21 | * 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 31cbe68fd42f..c3ee77fc4b2d 100644 --- a/sound/aoa/codecs/Makefile +++ b/sound/aoa/codecs/Makefile | |||
@@ -1,3 +1,7 @@ | |||
1 | snd-aoa-codec-onyx-objs := onyx.o | ||
2 | snd-aoa-codec-tas-objs := tas.o | ||
3 | snd-aoa-codec-toonie-objs := toonie.o | ||
4 | |||
1 | obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o | 5 | obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o |
2 | obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o | 6 | obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o |
3 | obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o | 7 | obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o |
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/onyx.c index 6a3837d480e5..15500b9d2da0 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.c +++ b/sound/aoa/codecs/onyx.c | |||
@@ -37,7 +37,7 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | |||
37 | MODULE_LICENSE("GPL"); | 37 | MODULE_LICENSE("GPL"); |
38 | MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); | 38 | MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa"); |
39 | 39 | ||
40 | #include "snd-aoa-codec-onyx.h" | 40 | #include "onyx.h" |
41 | #include "../aoa.h" | 41 | #include "../aoa.h" |
42 | #include "../soundbus/soundbus.h" | 42 | #include "../soundbus/soundbus.h" |
43 | 43 | ||
@@ -292,7 +292,7 @@ static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol, | |||
292 | static struct snd_kcontrol_new capture_source_control = { | 292 | static struct snd_kcontrol_new capture_source_control = { |
293 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 293 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
294 | /* If we name this 'Input Source', it properly shows up in | 294 | /* If we name this 'Input Source', it properly shows up in |
295 | * alsamixer as a selection, * but it's shown under the | 295 | * alsamixer as a selection, * but it's shown under the |
296 | * 'Playback' category. | 296 | * 'Playback' category. |
297 | * If I name it 'Capture Source', it shows up in strange | 297 | * If I name it 'Capture Source', it shows up in strange |
298 | * ways (two bools of which one can be selected at a | 298 | * 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, | |||
477 | 477 | ||
478 | ucontrol->value.iec958.status[3] = 0x3f; | 478 | ucontrol->value.iec958.status[3] = 0x3f; |
479 | ucontrol->value.iec958.status[4] = 0x0f; | 479 | ucontrol->value.iec958.status[4] = 0x0f; |
480 | 480 | ||
481 | return 0; | 481 | return 0; |
482 | } | 482 | } |
483 | 483 | ||
@@ -682,7 +682,7 @@ static int onyx_usable(struct codec_info_item *cii, | |||
682 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); | 682 | onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v); |
683 | spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); | 683 | spdif_enabled = !!(v & ONYX_SPDIF_ENABLE); |
684 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); | 684 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); |
685 | analog_enabled = | 685 | analog_enabled = |
686 | (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) | 686 | (v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT)) |
687 | != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); | 687 | != (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT); |
688 | mutex_unlock(&onyx->mutex); | 688 | mutex_unlock(&onyx->mutex); |
@@ -882,7 +882,7 @@ static int onyx_init_codec(struct aoa_codec *codec) | |||
882 | msleep(1); | 882 | msleep(1); |
883 | onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); | 883 | onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0); |
884 | msleep(1); | 884 | msleep(1); |
885 | 885 | ||
886 | if (onyx_register_init(onyx)) { | 886 | if (onyx_register_init(onyx)) { |
887 | printk(KERN_ERR PFX "failed to initialise onyx registers\n"); | 887 | printk(KERN_ERR PFX "failed to initialise onyx registers\n"); |
888 | return -ENODEV; | 888 | return -ENODEV; |
@@ -1069,7 +1069,7 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter) | |||
1069 | 1069 | ||
1070 | /* if that didn't work, try desperate mode for older | 1070 | /* if that didn't work, try desperate mode for older |
1071 | * machines that have stuff missing from the device tree */ | 1071 | * machines that have stuff missing from the device tree */ |
1072 | 1072 | ||
1073 | if (!of_device_is_compatible(busnode, "k2-i2c")) | 1073 | if (!of_device_is_compatible(busnode, "k2-i2c")) |
1074 | return -ENODEV; | 1074 | return -ENODEV; |
1075 | 1075 | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.h b/sound/aoa/codecs/onyx.h index ffd20254ff76..ffd20254ff76 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.h +++ b/sound/aoa/codecs/onyx.h | |||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h b/sound/aoa/codecs/tas-basstreble.h index 69b61136fd54..69b61136fd54 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h +++ b/sound/aoa/codecs/tas-basstreble.h | |||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h b/sound/aoa/codecs/tas-gain-table.h index 4cfa6757715e..4cfa6757715e 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h +++ b/sound/aoa/codecs/tas-gain-table.h | |||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.c b/sound/aoa/codecs/tas.c index 6c515b2b8bbd..008e0f85097d 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.c +++ b/sound/aoa/codecs/tas.c | |||
@@ -71,9 +71,9 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | |||
71 | MODULE_LICENSE("GPL"); | 71 | MODULE_LICENSE("GPL"); |
72 | MODULE_DESCRIPTION("tas codec driver for snd-aoa"); | 72 | MODULE_DESCRIPTION("tas codec driver for snd-aoa"); |
73 | 73 | ||
74 | #include "snd-aoa-codec-tas.h" | 74 | #include "tas.h" |
75 | #include "snd-aoa-codec-tas-gain-table.h" | 75 | #include "tas-gain-table.h" |
76 | #include "snd-aoa-codec-tas-basstreble.h" | 76 | #include "tas-basstreble.h" |
77 | #include "../aoa.h" | 77 | #include "../aoa.h" |
78 | #include "../soundbus/soundbus.h" | 78 | #include "../soundbus/soundbus.h" |
79 | 79 | ||
@@ -880,7 +880,7 @@ static void tas_exit_codec(struct aoa_codec *codec) | |||
880 | return; | 880 | return; |
881 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); | 881 | tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas); |
882 | } | 882 | } |
883 | 883 | ||
884 | 884 | ||
885 | static struct i2c_driver tas_driver; | 885 | static struct i2c_driver tas_driver; |
886 | 886 | ||
diff --git a/sound/aoa/codecs/snd-aoa-codec-tas.h b/sound/aoa/codecs/tas.h index ae177e3466e6..ae177e3466e6 100644 --- a/sound/aoa/codecs/snd-aoa-codec-tas.h +++ b/sound/aoa/codecs/tas.h | |||
diff --git a/sound/aoa/codecs/snd-aoa-codec-toonie.c b/sound/aoa/codecs/toonie.c index 3c7d1d8a9a6f..f13827e17562 100644 --- a/sound/aoa/codecs/snd-aoa-codec-toonie.c +++ b/sound/aoa/codecs/toonie.c | |||
@@ -131,7 +131,7 @@ static int __init toonie_init(void) | |||
131 | toonie->codec.owner = THIS_MODULE; | 131 | toonie->codec.owner = THIS_MODULE; |
132 | toonie->codec.init = toonie_init_codec; | 132 | toonie->codec.init = toonie_init_codec; |
133 | toonie->codec.exit = toonie_exit_codec; | 133 | toonie->codec.exit = toonie_exit_codec; |
134 | 134 | ||
135 | if (aoa_codec_register(&toonie->codec)) { | 135 | if (aoa_codec_register(&toonie->codec)) { |
136 | kfree(toonie); | 136 | kfree(toonie); |
137 | return -EINVAL; | 137 | return -EINVAL; |
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile index 62dc7287f663..a1596e88c718 100644 --- a/sound/aoa/core/Makefile +++ b/sound/aoa/core/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_SND_AOA) += snd-aoa.o | 1 | obj-$(CONFIG_SND_AOA) += snd-aoa.o |
2 | snd-aoa-objs := snd-aoa-core.o \ | 2 | snd-aoa-objs := core.o \ |
3 | snd-aoa-alsa.o \ | 3 | alsa.o \ |
4 | snd-aoa-gpio-pmf.o \ | 4 | gpio-pmf.o \ |
5 | snd-aoa-gpio-feature.o | 5 | gpio-feature.o |
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/alsa.c index 17fe689ed287..617850463582 100644 --- a/sound/aoa/core/snd-aoa-alsa.c +++ b/sound/aoa/core/alsa.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | */ | 7 | */ |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include "snd-aoa-alsa.h" | 9 | #include "alsa.h" |
10 | 10 | ||
11 | static int index = -1; | 11 | static int index = -1; |
12 | module_param(index, int, 0444); | 12 | module_param(index, int, 0444); |
@@ -64,7 +64,7 @@ int aoa_snd_device_new(snd_device_type_t type, | |||
64 | { | 64 | { |
65 | struct snd_card *card = aoa_get_card(); | 65 | struct snd_card *card = aoa_get_card(); |
66 | int err; | 66 | int err; |
67 | 67 | ||
68 | if (!card) return -ENOMEM; | 68 | if (!card) return -ENOMEM; |
69 | 69 | ||
70 | err = snd_device_new(card, type, device_data, ops); | 70 | err = snd_device_new(card, type, device_data, ops); |
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/alsa.h index 9669e4489cab..9669e4489cab 100644 --- a/sound/aoa/core/snd-aoa-alsa.h +++ b/sound/aoa/core/alsa.h | |||
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/core.c index 19fdae400687..10bec6c61382 100644 --- a/sound/aoa/core/snd-aoa-core.c +++ b/sound/aoa/core/core.c | |||
@@ -10,7 +10,7 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/list.h> | 11 | #include <linux/list.h> |
12 | #include "../aoa.h" | 12 | #include "../aoa.h" |
13 | #include "snd-aoa-alsa.h" | 13 | #include "alsa.h" |
14 | 14 | ||
15 | MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); | 15 | MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver"); |
16 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); | 16 | MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); |
diff --git a/sound/aoa/core/snd-aoa-gpio-feature.c b/sound/aoa/core/gpio-feature.c index 805dcbff2257..c93ad5dec66b 100644 --- a/sound/aoa/core/snd-aoa-gpio-feature.c +++ b/sound/aoa/core/gpio-feature.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * GPL v2, can be found in COPYING. | 6 | * GPL v2, can be found in COPYING. |
7 | * | 7 | * |
8 | * This file contains the GPIO control routines for | 8 | * This file contains the GPIO control routines for |
9 | * direct (through feature calls) access to the GPIO | 9 | * direct (through feature calls) access to the GPIO |
10 | * registers. | 10 | * registers. |
11 | */ | 11 | */ |
diff --git a/sound/aoa/core/snd-aoa-gpio-pmf.c b/sound/aoa/core/gpio-pmf.c index 5ca2220eac7d..5ca2220eac7d 100644 --- a/sound/aoa/core/snd-aoa-gpio-pmf.c +++ b/sound/aoa/core/gpio-pmf.c | |||
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile index 55fc5e7e52cf..da37c10eca51 100644 --- a/sound/aoa/fabrics/Makefile +++ b/sound/aoa/fabrics/Makefile | |||
@@ -1 +1,3 @@ | |||
1 | snd-aoa-fabric-layout-objs += layout.o | ||
2 | |||
1 | obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o | 3 | obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o |
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/layout.c index dea7abb082cd..ad60f5d10e82 100644 --- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ b/sound/aoa/fabrics/layout.c | |||
@@ -66,7 +66,7 @@ struct layout { | |||
66 | unsigned int layout_id; | 66 | unsigned int layout_id; |
67 | struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; | 67 | struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; |
68 | int flags; | 68 | int flags; |
69 | 69 | ||
70 | /* if busname is not assigned, we use 'Master' below, | 70 | /* if busname is not assigned, we use 'Master' below, |
71 | * so that our layout table doesn't need to be filled | 71 | * so that our layout table doesn't need to be filled |
72 | * too much. | 72 | * too much. |
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile index e57a5cf65655..1b949b2a4028 100644 --- a/sound/aoa/soundbus/i2sbus/Makefile +++ b/sound/aoa/soundbus/i2sbus/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o | 1 | obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o |
2 | snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o | 2 | snd-aoa-i2sbus-objs := core.o pcm.o control.o |
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-control.c b/sound/aoa/soundbus/i2sbus/control.c index 87beb4ad4d63..87beb4ad4d63 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-control.c +++ b/sound/aoa/soundbus/i2sbus/control.c | |||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/core.c index b4590df07466..be468edf3ecb 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c +++ b/sound/aoa/soundbus/i2sbus/core.c | |||
@@ -64,7 +64,7 @@ static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev, | |||
64 | struct dbdma_command_mem *r) | 64 | struct dbdma_command_mem *r) |
65 | { | 65 | { |
66 | if (!r->space) return; | 66 | if (!r->space) return; |
67 | 67 | ||
68 | dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, | 68 | dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev, |
69 | r->size, r->space, r->bus_addr); | 69 | r->size, r->space, r->bus_addr); |
70 | } | 70 | } |
@@ -247,7 +247,7 @@ static int i2sbus_add_dev(struct macio_dev *macio, | |||
247 | * but request_resource doesn't know about parents and | 247 | * but request_resource doesn't know about parents and |
248 | * contained resources... | 248 | * contained resources... |
249 | */ | 249 | */ |
250 | dev->allocated_resource[i] = | 250 | dev->allocated_resource[i] = |
251 | request_mem_region(dev->resources[i].start, | 251 | request_mem_region(dev->resources[i].start, |
252 | dev->resources[i].end - | 252 | dev->resources[i].end - |
253 | dev->resources[i].start + 1, | 253 | dev->resources[i].start + 1, |
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h index ff29654782c9..befefd99e271 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus.h +++ b/sound/aoa/soundbus/i2sbus/i2sbus.h | |||
@@ -18,7 +18,7 @@ | |||
18 | #include <asm/pmac_feature.h> | 18 | #include <asm/pmac_feature.h> |
19 | #include <asm/dbdma.h> | 19 | #include <asm/dbdma.h> |
20 | 20 | ||
21 | #include "i2sbus-interface.h" | 21 | #include "interface.h" |
22 | #include "../soundbus.h" | 22 | #include "../soundbus.h" |
23 | 23 | ||
24 | struct i2sbus_control { | 24 | struct i2sbus_control { |
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h b/sound/aoa/soundbus/i2sbus/interface.h index c6b5f5452d20..c6b5f5452d20 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-interface.h +++ b/sound/aoa/soundbus/i2sbus/interface.h | |||
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c index 59bacd365733..59bacd365733 100644 --- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c +++ b/sound/aoa/soundbus/i2sbus/pcm.c | |||
diff --git a/sound/core/device.c b/sound/core/device.c index c58d8227254c..a67dfac08c03 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) | |||
98 | kfree(dev); | 98 | kfree(dev); |
99 | return 0; | 99 | return 0; |
100 | } | 100 | } |
101 | snd_printd("device free %p (from %p), not found\n", device_data, | 101 | snd_printd("device free %p (from %pF), not found\n", device_data, |
102 | __builtin_return_address(0)); | 102 | __builtin_return_address(0)); |
103 | return -ENXIO; | 103 | return -ENXIO; |
104 | } | 104 | } |
@@ -135,7 +135,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data) | |||
135 | } | 135 | } |
136 | return 0; | 136 | return 0; |
137 | } | 137 | } |
138 | snd_printd("device disconnect %p (from %p), not found\n", device_data, | 138 | snd_printd("device disconnect %p (from %pF), not found\n", device_data, |
139 | __builtin_return_address(0)); | 139 | __builtin_return_address(0)); |
140 | return -ENXIO; | 140 | return -ENXIO; |
141 | } | 141 | } |
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig index 255fd18b9aec..0bcf14640fde 100644 --- a/sound/drivers/Kconfig +++ b/sound/drivers/Kconfig | |||
@@ -163,7 +163,7 @@ config SND_ML403_AC97CR | |||
163 | 163 | ||
164 | config SND_AC97_POWER_SAVE | 164 | config SND_AC97_POWER_SAVE |
165 | bool "AC97 Power-Saving Mode" | 165 | bool "AC97 Power-Saving Mode" |
166 | depends on SND_AC97_CODEC && EXPERIMENTAL | 166 | depends on SND_AC97_CODEC |
167 | default n | 167 | default n |
168 | help | 168 | help |
169 | Say Y here to enable the aggressive power-saving support of | 169 | 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 1899cf0685bc..2a02f704f366 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) | |||
96 | return -EINVAL; | 96 | return -EINVAL; |
97 | 97 | ||
98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | 98 | hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); |
99 | pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ; | 99 | pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED; |
100 | pcsp_chip.timer.function = pcsp_do_timer; | 100 | pcsp_chip.timer.function = pcsp_do_timer; |
101 | 101 | ||
102 | card = snd_card_new(index, id, THIS_MODULE, 0); | 102 | card = snd_card_new(index, id, THIS_MODULE, 0); |
@@ -188,10 +188,8 @@ static int __devexit pcsp_remove(struct platform_device *dev) | |||
188 | 188 | ||
189 | static void pcsp_stop_beep(struct snd_pcsp *chip) | 189 | static void pcsp_stop_beep(struct snd_pcsp *chip) |
190 | { | 190 | { |
191 | spin_lock_irq(&chip->substream_lock); | 191 | pcsp_sync_stop(chip); |
192 | if (!chip->playback_substream) | 192 | pcspkr_stop_sound(); |
193 | pcspkr_stop_sound(); | ||
194 | spin_unlock_irq(&chip->substream_lock); | ||
195 | } | 193 | } |
196 | 194 | ||
197 | #ifdef CONFIG_PM | 195 | #ifdef CONFIG_PM |
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h index 1d661f795e8c..cdef2664218f 100644 --- a/sound/drivers/pcsp/pcsp.h +++ b/sound/drivers/pcsp/pcsp.h | |||
@@ -62,6 +62,8 @@ struct snd_pcsp { | |||
62 | unsigned short port, irq, dma; | 62 | unsigned short port, irq, dma; |
63 | spinlock_t substream_lock; | 63 | spinlock_t substream_lock; |
64 | struct snd_pcm_substream *playback_substream; | 64 | struct snd_pcm_substream *playback_substream; |
65 | unsigned int fmt_size; | ||
66 | unsigned int is_signed; | ||
65 | size_t playback_ptr; | 67 | size_t playback_ptr; |
66 | size_t period_ptr; | 68 | size_t period_ptr; |
67 | atomic_t timer_active; | 69 | atomic_t timer_active; |
@@ -77,6 +79,7 @@ struct snd_pcsp { | |||
77 | extern struct snd_pcsp pcsp_chip; | 79 | extern struct snd_pcsp pcsp_chip; |
78 | 80 | ||
79 | extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); | 81 | extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle); |
82 | extern void pcsp_sync_stop(struct snd_pcsp *chip); | ||
80 | 83 | ||
81 | extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); | 84 | extern int snd_pcsp_new_pcm(struct snd_pcsp *chip); |
82 | extern int snd_pcsp_new_mixer(struct snd_pcsp *chip); | 85 | 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 1f42e4063118..84cc2658c05b 100644 --- a/sound/drivers/pcsp/pcsp_lib.c +++ b/sound/drivers/pcsp/pcsp_lib.c | |||
@@ -8,6 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/moduleparam.h> | 10 | #include <linux/moduleparam.h> |
11 | #include <linux/interrupt.h> | ||
11 | #include <sound/pcm.h> | 12 | #include <sound/pcm.h> |
12 | #include <asm/io.h> | 13 | #include <asm/io.h> |
13 | #include "pcsp.h" | 14 | #include "pcsp.h" |
@@ -19,61 +20,57 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround " | |||
19 | 20 | ||
20 | #define DMIX_WANTS_S16 1 | 21 | #define DMIX_WANTS_S16 1 |
21 | 22 | ||
22 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | 23 | /* |
24 | * Call snd_pcm_period_elapsed in a tasklet | ||
25 | * This avoids spinlock messes and long-running irq contexts | ||
26 | */ | ||
27 | static void pcsp_call_pcm_elapsed(unsigned long priv) | ||
28 | { | ||
29 | if (atomic_read(&pcsp_chip.timer_active)) { | ||
30 | struct snd_pcm_substream *substream; | ||
31 | substream = pcsp_chip.playback_substream; | ||
32 | if (substream) | ||
33 | snd_pcm_period_elapsed(substream); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0); | ||
38 | |||
39 | /* write the port and returns the next expire time in ns; | ||
40 | * called at the trigger-start and in hrtimer callback | ||
41 | */ | ||
42 | static unsigned long pcsp_timer_update(struct hrtimer *handle) | ||
23 | { | 43 | { |
24 | unsigned char timer_cnt, val; | 44 | unsigned char timer_cnt, val; |
25 | int fmt_size, periods_elapsed; | ||
26 | u64 ns; | 45 | u64 ns; |
27 | size_t period_bytes, buffer_bytes; | ||
28 | struct snd_pcm_substream *substream; | 46 | struct snd_pcm_substream *substream; |
29 | struct snd_pcm_runtime *runtime; | 47 | struct snd_pcm_runtime *runtime; |
30 | struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); | 48 | struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); |
49 | unsigned long flags; | ||
31 | 50 | ||
32 | if (chip->thalf) { | 51 | if (chip->thalf) { |
33 | outb(chip->val61, 0x61); | 52 | outb(chip->val61, 0x61); |
34 | chip->thalf = 0; | 53 | chip->thalf = 0; |
35 | if (!atomic_read(&chip->timer_active)) | 54 | if (!atomic_read(&chip->timer_active)) |
36 | return HRTIMER_NORESTART; | 55 | return 0; |
37 | hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer), | 56 | return chip->ns_rem; |
38 | ktime_set(0, chip->ns_rem)); | ||
39 | return HRTIMER_RESTART; | ||
40 | } | 57 | } |
41 | 58 | ||
42 | spin_lock_irq(&chip->substream_lock); | ||
43 | /* Takashi Iwai says regarding this extra lock: | ||
44 | |||
45 | If the irq handler handles some data on the DMA buffer, it should | ||
46 | do snd_pcm_stream_lock(). | ||
47 | That protects basically against all races among PCM callbacks, yes. | ||
48 | However, there are two remaining issues: | ||
49 | 1. The substream pointer you try to lock isn't protected _before_ | ||
50 | this lock yet. | ||
51 | 2. snd_pcm_period_elapsed() itself acquires the lock. | ||
52 | The requirement of another lock is because of 1. When you get | ||
53 | chip->playback_substream, it's not protected. | ||
54 | Keeping this lock while snd_pcm_period_elapsed() assures the substream | ||
55 | is still protected (at least, not released). And the other status is | ||
56 | handled properly inside snd_pcm_stream_lock() in | ||
57 | snd_pcm_period_elapsed(). | ||
58 | |||
59 | */ | ||
60 | if (!chip->playback_substream) | ||
61 | goto exit_nr_unlock1; | ||
62 | substream = chip->playback_substream; | ||
63 | snd_pcm_stream_lock(substream); | ||
64 | if (!atomic_read(&chip->timer_active)) | 59 | if (!atomic_read(&chip->timer_active)) |
65 | goto exit_nr_unlock2; | 60 | return 0; |
61 | substream = chip->playback_substream; | ||
62 | if (!substream) | ||
63 | return 0; | ||
66 | 64 | ||
67 | runtime = substream->runtime; | 65 | runtime = substream->runtime; |
68 | fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3; | ||
69 | /* assume it is mono! */ | 66 | /* assume it is mono! */ |
70 | val = runtime->dma_area[chip->playback_ptr + fmt_size - 1]; | 67 | val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1]; |
71 | if (snd_pcm_format_signed(runtime->format)) | 68 | if (chip->is_signed) |
72 | val ^= 0x80; | 69 | val ^= 0x80; |
73 | timer_cnt = val * CUR_DIV() / 256; | 70 | timer_cnt = val * CUR_DIV() / 256; |
74 | 71 | ||
75 | if (timer_cnt && chip->enable) { | 72 | if (timer_cnt && chip->enable) { |
76 | spin_lock(&i8253_lock); | 73 | spin_lock_irqsave(&i8253_lock, flags); |
77 | if (!nforce_wa) { | 74 | if (!nforce_wa) { |
78 | outb_p(chip->val61, 0x61); | 75 | outb_p(chip->val61, 0x61); |
79 | outb_p(timer_cnt, 0x42); | 76 | outb_p(timer_cnt, 0x42); |
@@ -82,12 +79,39 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | |||
82 | outb(chip->val61 ^ 2, 0x61); | 79 | outb(chip->val61 ^ 2, 0x61); |
83 | chip->thalf = 1; | 80 | chip->thalf = 1; |
84 | } | 81 | } |
85 | spin_unlock(&i8253_lock); | 82 | spin_unlock_irqrestore(&i8253_lock, flags); |
86 | } | 83 | } |
87 | 84 | ||
85 | chip->ns_rem = PCSP_PERIOD_NS(); | ||
86 | ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); | ||
87 | chip->ns_rem -= ns; | ||
88 | return ns; | ||
89 | } | ||
90 | |||
91 | enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | ||
92 | { | ||
93 | struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer); | ||
94 | struct snd_pcm_substream *substream; | ||
95 | int periods_elapsed, pointer_update; | ||
96 | size_t period_bytes, buffer_bytes; | ||
97 | unsigned long ns; | ||
98 | unsigned long flags; | ||
99 | |||
100 | pointer_update = !chip->thalf; | ||
101 | ns = pcsp_timer_update(handle); | ||
102 | if (!ns) | ||
103 | return HRTIMER_NORESTART; | ||
104 | |||
105 | /* update the playback position */ | ||
106 | substream = chip->playback_substream; | ||
107 | if (!substream) | ||
108 | return HRTIMER_NORESTART; | ||
109 | |||
88 | period_bytes = snd_pcm_lib_period_bytes(substream); | 110 | period_bytes = snd_pcm_lib_period_bytes(substream); |
89 | buffer_bytes = snd_pcm_lib_buffer_bytes(substream); | 111 | buffer_bytes = snd_pcm_lib_buffer_bytes(substream); |
90 | chip->playback_ptr += PCSP_INDEX_INC() * fmt_size; | 112 | |
113 | spin_lock_irqsave(&chip->substream_lock, flags); | ||
114 | chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size; | ||
91 | periods_elapsed = chip->playback_ptr - chip->period_ptr; | 115 | periods_elapsed = chip->playback_ptr - chip->period_ptr; |
92 | if (periods_elapsed < 0) { | 116 | if (periods_elapsed < 0) { |
93 | #if PCSP_DEBUG | 117 | #if PCSP_DEBUG |
@@ -102,41 +126,30 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle) | |||
102 | * or ALSA will BUG on us. */ | 126 | * or ALSA will BUG on us. */ |
103 | chip->playback_ptr %= buffer_bytes; | 127 | chip->playback_ptr %= buffer_bytes; |
104 | 128 | ||
105 | snd_pcm_stream_unlock(substream); | ||
106 | |||
107 | if (periods_elapsed) { | 129 | if (periods_elapsed) { |
108 | snd_pcm_period_elapsed(substream); | ||
109 | chip->period_ptr += periods_elapsed * period_bytes; | 130 | chip->period_ptr += periods_elapsed * period_bytes; |
110 | chip->period_ptr %= buffer_bytes; | 131 | chip->period_ptr %= buffer_bytes; |
111 | } | 132 | } |
133 | spin_unlock_irqrestore(&chip->substream_lock, flags); | ||
112 | 134 | ||
113 | spin_unlock_irq(&chip->substream_lock); | 135 | if (periods_elapsed) |
136 | tasklet_schedule(&pcsp_pcm_tasklet); | ||
114 | 137 | ||
115 | if (!atomic_read(&chip->timer_active)) | 138 | hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns)); |
116 | return HRTIMER_NORESTART; | ||
117 | 139 | ||
118 | chip->ns_rem = PCSP_PERIOD_NS(); | ||
119 | ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem); | ||
120 | chip->ns_rem -= ns; | ||
121 | hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer), | ||
122 | ktime_set(0, ns)); | ||
123 | return HRTIMER_RESTART; | 140 | return HRTIMER_RESTART; |
124 | |||
125 | exit_nr_unlock2: | ||
126 | snd_pcm_stream_unlock(substream); | ||
127 | exit_nr_unlock1: | ||
128 | spin_unlock_irq(&chip->substream_lock); | ||
129 | return HRTIMER_NORESTART; | ||
130 | } | 141 | } |
131 | 142 | ||
132 | static void pcsp_start_playing(struct snd_pcsp *chip) | 143 | static int pcsp_start_playing(struct snd_pcsp *chip) |
133 | { | 144 | { |
145 | unsigned long ns; | ||
146 | |||
134 | #if PCSP_DEBUG | 147 | #if PCSP_DEBUG |
135 | printk(KERN_INFO "PCSP: start_playing called\n"); | 148 | printk(KERN_INFO "PCSP: start_playing called\n"); |
136 | #endif | 149 | #endif |
137 | if (atomic_read(&chip->timer_active)) { | 150 | if (atomic_read(&chip->timer_active)) { |
138 | printk(KERN_ERR "PCSP: Timer already active\n"); | 151 | printk(KERN_ERR "PCSP: Timer already active\n"); |
139 | return; | 152 | return -EIO; |
140 | } | 153 | } |
141 | 154 | ||
142 | spin_lock(&i8253_lock); | 155 | spin_lock(&i8253_lock); |
@@ -146,7 +159,12 @@ static void pcsp_start_playing(struct snd_pcsp *chip) | |||
146 | atomic_set(&chip->timer_active, 1); | 159 | atomic_set(&chip->timer_active, 1); |
147 | chip->thalf = 0; | 160 | chip->thalf = 0; |
148 | 161 | ||
149 | hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL); | 162 | ns = pcsp_timer_update(&pcsp_chip.timer); |
163 | if (!ns) | ||
164 | return -EIO; | ||
165 | |||
166 | hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL); | ||
167 | return 0; | ||
150 | } | 168 | } |
151 | 169 | ||
152 | static void pcsp_stop_playing(struct snd_pcsp *chip) | 170 | static void pcsp_stop_playing(struct snd_pcsp *chip) |
@@ -165,26 +183,35 @@ static void pcsp_stop_playing(struct snd_pcsp *chip) | |||
165 | spin_unlock(&i8253_lock); | 183 | spin_unlock(&i8253_lock); |
166 | } | 184 | } |
167 | 185 | ||
186 | /* | ||
187 | * Force to stop and sync the stream | ||
188 | */ | ||
189 | void pcsp_sync_stop(struct snd_pcsp *chip) | ||
190 | { | ||
191 | local_irq_disable(); | ||
192 | pcsp_stop_playing(chip); | ||
193 | local_irq_enable(); | ||
194 | hrtimer_cancel(&chip->timer); | ||
195 | tasklet_kill(&pcsp_pcm_tasklet); | ||
196 | } | ||
197 | |||
168 | static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) | 198 | static int snd_pcsp_playback_close(struct snd_pcm_substream *substream) |
169 | { | 199 | { |
170 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); | 200 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); |
171 | #if PCSP_DEBUG | 201 | #if PCSP_DEBUG |
172 | printk(KERN_INFO "PCSP: close called\n"); | 202 | printk(KERN_INFO "PCSP: close called\n"); |
173 | #endif | 203 | #endif |
174 | if (atomic_read(&chip->timer_active)) { | 204 | pcsp_sync_stop(chip); |
175 | printk(KERN_ERR "PCSP: timer still active\n"); | ||
176 | pcsp_stop_playing(chip); | ||
177 | } | ||
178 | spin_lock_irq(&chip->substream_lock); | ||
179 | chip->playback_substream = NULL; | 205 | chip->playback_substream = NULL; |
180 | spin_unlock_irq(&chip->substream_lock); | ||
181 | return 0; | 206 | return 0; |
182 | } | 207 | } |
183 | 208 | ||
184 | static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, | 209 | static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, |
185 | struct snd_pcm_hw_params *hw_params) | 210 | struct snd_pcm_hw_params *hw_params) |
186 | { | 211 | { |
212 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); | ||
187 | int err; | 213 | int err; |
214 | pcsp_sync_stop(chip); | ||
188 | err = snd_pcm_lib_malloc_pages(substream, | 215 | err = snd_pcm_lib_malloc_pages(substream, |
189 | params_buffer_bytes(hw_params)); | 216 | params_buffer_bytes(hw_params)); |
190 | if (err < 0) | 217 | if (err < 0) |
@@ -194,9 +221,11 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream, | |||
194 | 221 | ||
195 | static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) | 222 | static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream) |
196 | { | 223 | { |
224 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); | ||
197 | #if PCSP_DEBUG | 225 | #if PCSP_DEBUG |
198 | printk(KERN_INFO "PCSP: hw_free called\n"); | 226 | printk(KERN_INFO "PCSP: hw_free called\n"); |
199 | #endif | 227 | #endif |
228 | pcsp_sync_stop(chip); | ||
200 | return snd_pcm_lib_free_pages(substream); | 229 | return snd_pcm_lib_free_pages(substream); |
201 | } | 230 | } |
202 | 231 | ||
@@ -212,8 +241,12 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream) | |||
212 | snd_pcm_lib_period_bytes(substream), | 241 | snd_pcm_lib_period_bytes(substream), |
213 | substream->runtime->periods); | 242 | substream->runtime->periods); |
214 | #endif | 243 | #endif |
244 | pcsp_sync_stop(chip); | ||
215 | chip->playback_ptr = 0; | 245 | chip->playback_ptr = 0; |
216 | chip->period_ptr = 0; | 246 | chip->period_ptr = 0; |
247 | chip->fmt_size = | ||
248 | snd_pcm_format_physical_width(substream->runtime->format) >> 3; | ||
249 | chip->is_signed = snd_pcm_format_signed(substream->runtime->format); | ||
217 | return 0; | 250 | return 0; |
218 | } | 251 | } |
219 | 252 | ||
@@ -226,8 +259,7 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd) | |||
226 | switch (cmd) { | 259 | switch (cmd) { |
227 | case SNDRV_PCM_TRIGGER_START: | 260 | case SNDRV_PCM_TRIGGER_START: |
228 | case SNDRV_PCM_TRIGGER_RESUME: | 261 | case SNDRV_PCM_TRIGGER_RESUME: |
229 | pcsp_start_playing(chip); | 262 | return pcsp_start_playing(chip); |
230 | break; | ||
231 | case SNDRV_PCM_TRIGGER_STOP: | 263 | case SNDRV_PCM_TRIGGER_STOP: |
232 | case SNDRV_PCM_TRIGGER_SUSPEND: | 264 | case SNDRV_PCM_TRIGGER_SUSPEND: |
233 | pcsp_stop_playing(chip); | 265 | pcsp_stop_playing(chip); |
@@ -242,7 +274,11 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream | |||
242 | *substream) | 274 | *substream) |
243 | { | 275 | { |
244 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); | 276 | struct snd_pcsp *chip = snd_pcm_substream_chip(substream); |
245 | return bytes_to_frames(substream->runtime, chip->playback_ptr); | 277 | unsigned int pos; |
278 | spin_lock(&chip->substream_lock); | ||
279 | pos = chip->playback_ptr; | ||
280 | spin_unlock(&chip->substream_lock); | ||
281 | return bytes_to_frames(substream->runtime, pos); | ||
246 | } | 282 | } |
247 | 283 | ||
248 | static struct snd_pcm_hardware snd_pcsp_playback = { | 284 | static struct snd_pcm_hardware snd_pcsp_playback = { |
@@ -279,9 +315,7 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream) | |||
279 | return -EBUSY; | 315 | return -EBUSY; |
280 | } | 316 | } |
281 | runtime->hw = snd_pcsp_playback; | 317 | runtime->hw = snd_pcsp_playback; |
282 | spin_lock_irq(&chip->substream_lock); | ||
283 | chip->playback_substream = substream; | 318 | chip->playback_substream = substream; |
284 | spin_unlock_irq(&chip->substream_lock); | ||
285 | return 0; | 319 | return 0; |
286 | } | 320 | } |
287 | 321 | ||
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c index 667eccc676a4..ea06877be4b1 100644 --- a/sound/isa/sb/sb8.c +++ b/sound/isa/sb/sb8.c | |||
@@ -140,8 +140,10 @@ static int __devinit snd_sb8_probe(struct device *pdev, unsigned int dev) | |||
140 | break; | 140 | break; |
141 | } | 141 | } |
142 | } | 142 | } |
143 | if (i >= ARRAY_SIZE(possible_ports)) | 143 | if (i >= ARRAY_SIZE(possible_ports)) { |
144 | err = -EINVAL; | ||
144 | goto _err; | 145 | goto _err; |
146 | } | ||
145 | } | 147 | } |
146 | acard->chip = chip; | 148 | acard->chip = chip; |
147 | 149 | ||
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c index bd510eceff1f..e2b843b4f9d0 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[] = { | |||
175 | { 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL}, | 175 | { 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL}, |
176 | { 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL}, | 176 | { 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL}, |
177 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, | 177 | { 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL}, |
178 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL}, | 178 | { 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL}, |
179 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, | 179 | { 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF}, |
180 | { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, | 180 | { 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL }, |
181 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, | 181 | { 0x594d4802, 0xffffffff, "YMF752", NULL, NULL }, |
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c index 6e831aff1bd0..2c7cd97d2234 100644 --- a/sound/pci/ac97/ac97_patch.c +++ b/sound/pci/ac97/ac97_patch.c | |||
@@ -2832,6 +2832,8 @@ static int patch_alc655(struct snd_ac97 * ac97) | |||
2832 | val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ | 2832 | val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ |
2833 | else | 2833 | else |
2834 | val |= (1 << 1); /* Pin 47 is spdif input pin */ | 2834 | val |= (1 << 1); /* Pin 47 is spdif input pin */ |
2835 | /* this seems missing on some hardwares */ | ||
2836 | ac97->ext_id |= AC97_EI_SPDIF; | ||
2835 | } | 2837 | } |
2836 | val &= ~(1 << 12); /* vref enable */ | 2838 | val &= ~(1 << 12); /* vref enable */ |
2837 | snd_ac97_write_cache(ac97, 0x7a, val); | 2839 | snd_ac97_write_cache(ac97, 0x7a, val); |
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 74175fc80c7f..14b8d9a91aae 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h | |||
@@ -664,10 +664,14 @@ struct snd_ca0106_pcm { | |||
664 | struct snd_ca0106_details { | 664 | struct snd_ca0106_details { |
665 | u32 serial; | 665 | u32 serial; |
666 | char * name; | 666 | char * name; |
667 | int ac97; | 667 | int ac97; /* ac97 = 0 -> Select MIC, Line in, TAD in, AUX in. |
668 | int gpio_type; | 668 | ac97 = 1 -> Default to AC97 in. */ |
669 | int i2c_adc; | 669 | int gpio_type; /* gpio_type = 1 -> shared mic-in/line-in |
670 | int spi_dac; | 670 | gpio_type = 2 -> shared side-out/line-in. */ |
671 | int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume | ||
672 | controls, phone, mic, line-in and aux. */ | ||
673 | int spi_dac; /* spi_dac=1 adds the mute switch for each analog | ||
674 | output, front, rear, etc. */ | ||
671 | }; | 675 | }; |
672 | 676 | ||
673 | // definition of the chip-specific record | 677 | // definition of the chip-specific record |
@@ -686,11 +690,12 @@ struct snd_ca0106 { | |||
686 | spinlock_t emu_lock; | 690 | spinlock_t emu_lock; |
687 | 691 | ||
688 | struct snd_ac97 *ac97; | 692 | struct snd_ac97 *ac97; |
689 | struct snd_pcm *pcm; | 693 | struct snd_pcm *pcm[4]; |
690 | 694 | ||
691 | struct snd_ca0106_channel playback_channels[4]; | 695 | struct snd_ca0106_channel playback_channels[4]; |
692 | struct snd_ca0106_channel capture_channels[4]; | 696 | struct snd_ca0106_channel capture_channels[4]; |
693 | u32 spdif_bits[4]; /* s/pdif out setup */ | 697 | u32 spdif_bits[4]; /* s/pdif out default setup */ |
698 | u32 spdif_str_bits[4]; /* s/pdif out per-stream setup */ | ||
694 | int spdif_enable; | 699 | int spdif_enable; |
695 | int capture_source; | 700 | int capture_source; |
696 | int i2c_capture_source; | 701 | int i2c_capture_source; |
@@ -703,6 +708,11 @@ struct snd_ca0106 { | |||
703 | struct snd_ca_midi midi2; | 708 | struct snd_ca_midi midi2; |
704 | 709 | ||
705 | u16 spi_dac_reg[16]; | 710 | u16 spi_dac_reg[16]; |
711 | |||
712 | #ifdef CONFIG_PM | ||
713 | #define NUM_SAVED_VOLUMES 9 | ||
714 | unsigned int saved_vol[NUM_SAVED_VOLUMES]; | ||
715 | #endif | ||
706 | }; | 716 | }; |
707 | 717 | ||
708 | int snd_ca0106_mixer(struct snd_ca0106 *emu); | 718 | int snd_ca0106_mixer(struct snd_ca0106 *emu); |
@@ -721,3 +731,11 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value); | |||
721 | 731 | ||
722 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, | 732 | int snd_ca0106_spi_write(struct snd_ca0106 * emu, |
723 | unsigned int data); | 733 | unsigned int data); |
734 | |||
735 | #ifdef CONFIG_PM | ||
736 | void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip); | ||
737 | void snd_ca0106_mixer_resume(struct snd_ca0106 *chip); | ||
738 | #else | ||
739 | #define snd_ca0106_mixer_suspend(chip) do { } while (0) | ||
740 | #define snd_ca0106_mixer_resume(chip) do { } while (0) | ||
741 | #endif | ||
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 88fbf285d2b7..0e62205d4081 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -254,7 +254,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { | |||
254 | .name = "MSI K8N Diamond MB", | 254 | .name = "MSI K8N Diamond MB", |
255 | .gpio_type = 2, | 255 | .gpio_type = 2, |
256 | .i2c_adc = 1, | 256 | .i2c_adc = 1, |
257 | .spi_dac = 2 } , | 257 | .spi_dac = 1 } , |
258 | /* Shuttle XPC SD31P which has an onboard Creative Labs | 258 | /* Shuttle XPC SD31P which has an onboard Creative Labs |
259 | * Sound Blaster Live! 24-bit EAX | 259 | * Sound Blaster Live! 24-bit EAX |
260 | * high-definition 7.1 audio processor". | 260 | * high-definition 7.1 audio processor". |
@@ -305,9 +305,15 @@ static struct snd_pcm_hardware snd_ca0106_capture_hw = { | |||
305 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 305 | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
306 | SNDRV_PCM_INFO_MMAP_VALID), | 306 | SNDRV_PCM_INFO_MMAP_VALID), |
307 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, | 307 | .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE, |
308 | #if 0 /* FIXME: looks like 44.1kHz capture causes noisy output on 48kHz */ | ||
308 | .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 309 | .rates = (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
309 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), | 310 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), |
310 | .rate_min = 44100, | 311 | .rate_min = 44100, |
312 | #else | ||
313 | .rates = (SNDRV_PCM_RATE_48000 | | ||
314 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000), | ||
315 | .rate_min = 48000, | ||
316 | #endif /* FIXME */ | ||
311 | .rate_max = 192000, | 317 | .rate_max = 192000, |
312 | .channels_min = 2, | 318 | .channels_min = 2, |
313 | .channels_max = 2, | 319 | .channels_max = 2, |
@@ -479,6 +485,15 @@ static const int spi_dacd_bit[] = { | |||
479 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, | 485 | [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, |
480 | }; | 486 | }; |
481 | 487 | ||
488 | static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) | ||
489 | { | ||
490 | if (chip->spdif_str_bits[idx] != chip->spdif_bits[idx]) { | ||
491 | chip->spdif_str_bits[idx] = chip->spdif_bits[idx]; | ||
492 | snd_ca0106_ptr_write(chip, SPCS0 + idx, 0, | ||
493 | chip->spdif_str_bits[idx]); | ||
494 | } | ||
495 | } | ||
496 | |||
482 | /* open_playback callback */ | 497 | /* open_playback callback */ |
483 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, | 498 | static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, |
484 | int channel_id) | 499 | int channel_id) |
@@ -524,6 +539,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr | |||
524 | if (err < 0) | 539 | if (err < 0) |
525 | return err; | 540 | return err; |
526 | } | 541 | } |
542 | |||
543 | restore_spdif_bits(chip, channel_id); | ||
544 | |||
527 | return 0; | 545 | return 0; |
528 | } | 546 | } |
529 | 547 | ||
@@ -535,6 +553,8 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) | |||
535 | struct snd_ca0106_pcm *epcm = runtime->private_data; | 553 | struct snd_ca0106_pcm *epcm = runtime->private_data; |
536 | chip->playback_channels[epcm->channel_id].use = 0; | 554 | chip->playback_channels[epcm->channel_id].use = 0; |
537 | 555 | ||
556 | restore_spdif_bits(chip, epcm->channel_id); | ||
557 | |||
538 | if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { | 558 | if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { |
539 | const int reg = spi_dacd_reg[epcm->channel_id]; | 559 | const int reg = spi_dacd_reg[epcm->channel_id]; |
540 | 560 | ||
@@ -847,15 +867,18 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
847 | struct snd_pcm_substream *s; | 867 | struct snd_pcm_substream *s; |
848 | u32 basic = 0; | 868 | u32 basic = 0; |
849 | u32 extended = 0; | 869 | u32 extended = 0; |
850 | int running=0; | 870 | u32 bits; |
871 | int running = 0; | ||
851 | 872 | ||
852 | switch (cmd) { | 873 | switch (cmd) { |
853 | case SNDRV_PCM_TRIGGER_START: | 874 | case SNDRV_PCM_TRIGGER_START: |
854 | running=1; | 875 | case SNDRV_PCM_TRIGGER_RESUME: |
876 | running = 1; | ||
855 | break; | 877 | break; |
856 | case SNDRV_PCM_TRIGGER_STOP: | 878 | case SNDRV_PCM_TRIGGER_STOP: |
879 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
857 | default: | 880 | default: |
858 | running=0; | 881 | running = 0; |
859 | break; | 882 | break; |
860 | } | 883 | } |
861 | snd_pcm_group_for_each_entry(s, substream) { | 884 | snd_pcm_group_for_each_entry(s, substream) { |
@@ -865,22 +888,32 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream, | |||
865 | runtime = s->runtime; | 888 | runtime = s->runtime; |
866 | epcm = runtime->private_data; | 889 | epcm = runtime->private_data; |
867 | channel = epcm->channel_id; | 890 | channel = epcm->channel_id; |
868 | //snd_printk("channel=%d\n",channel); | 891 | /* snd_printk("channel=%d\n",channel); */ |
869 | epcm->running = running; | 892 | epcm->running = running; |
870 | basic |= (0x1<<channel); | 893 | basic |= (0x1 << channel); |
871 | extended |= (0x10<<channel); | 894 | extended |= (0x10 << channel); |
872 | snd_pcm_trigger_done(s, substream); | 895 | snd_pcm_trigger_done(s, substream); |
873 | } | 896 | } |
874 | //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); | 897 | /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */ |
875 | 898 | ||
876 | switch (cmd) { | 899 | switch (cmd) { |
877 | case SNDRV_PCM_TRIGGER_START: | 900 | case SNDRV_PCM_TRIGGER_START: |
878 | snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended)); | 901 | case SNDRV_PCM_TRIGGER_RESUME: |
879 | snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic)); | 902 | bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0); |
903 | bits |= extended; | ||
904 | snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits); | ||
905 | bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0); | ||
906 | bits |= basic; | ||
907 | snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits); | ||
880 | break; | 908 | break; |
881 | case SNDRV_PCM_TRIGGER_STOP: | 909 | case SNDRV_PCM_TRIGGER_STOP: |
882 | snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic)); | 910 | case SNDRV_PCM_TRIGGER_SUSPEND: |
883 | snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended)); | 911 | bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0); |
912 | bits &= ~basic; | ||
913 | snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits); | ||
914 | bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0); | ||
915 | bits &= ~extended; | ||
916 | snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits); | ||
884 | break; | 917 | break; |
885 | default: | 918 | default: |
886 | result = -EINVAL; | 919 | result = -EINVAL; |
@@ -1103,21 +1136,13 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip) | |||
1103 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); | 1136 | return snd_ac97_mixer(pbus, &ac97, &chip->ac97); |
1104 | } | 1137 | } |
1105 | 1138 | ||
1139 | static void ca0106_stop_chip(struct snd_ca0106 *chip); | ||
1140 | |||
1106 | static int snd_ca0106_free(struct snd_ca0106 *chip) | 1141 | static int snd_ca0106_free(struct snd_ca0106 *chip) |
1107 | { | 1142 | { |
1108 | if (chip->res_port != NULL) { /* avoid access to already used hardware */ | 1143 | if (chip->res_port != NULL) { |
1109 | // disable interrupts | 1144 | /* avoid access to already used hardware */ |
1110 | snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0); | 1145 | ca0106_stop_chip(chip); |
1111 | outl(0, chip->port + INTE); | ||
1112 | snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0); | ||
1113 | udelay(1000); | ||
1114 | // disable audio | ||
1115 | //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); | ||
1116 | outl(0, chip->port + HCFG); | ||
1117 | /* FIXME: We need to stop and DMA transfers here. | ||
1118 | * But as I am not sure how yet, we cannot from the dma pages. | ||
1119 | * So we can fix: snd-malloc: Memory leak? pages not freed = 8 | ||
1120 | */ | ||
1121 | } | 1146 | } |
1122 | if (chip->irq >= 0) | 1147 | if (chip->irq >= 0) |
1123 | free_irq(chip->irq, chip); | 1148 | free_irq(chip->irq, chip); |
@@ -1203,15 +1228,14 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id) | |||
1203 | return IRQ_HANDLED; | 1228 | return IRQ_HANDLED; |
1204 | } | 1229 | } |
1205 | 1230 | ||
1206 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm) | 1231 | static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device) |
1207 | { | 1232 | { |
1208 | struct snd_pcm *pcm; | 1233 | struct snd_pcm *pcm; |
1209 | struct snd_pcm_substream *substream; | 1234 | struct snd_pcm_substream *substream; |
1210 | int err; | 1235 | int err; |
1211 | 1236 | ||
1212 | if (rpcm) | 1237 | err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm); |
1213 | *rpcm = NULL; | 1238 | if (err < 0) |
1214 | if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0) | ||
1215 | return err; | 1239 | return err; |
1216 | 1240 | ||
1217 | pcm->private_data = emu; | 1241 | pcm->private_data = emu; |
@@ -1238,7 +1262,6 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s | |||
1238 | pcm->info_flags = 0; | 1262 | pcm->info_flags = 0; |
1239 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; | 1263 | pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX; |
1240 | strcpy(pcm->name, "CA0106"); | 1264 | strcpy(pcm->name, "CA0106"); |
1241 | emu->pcm = pcm; | ||
1242 | 1265 | ||
1243 | for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; | 1266 | for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; |
1244 | substream; | 1267 | substream; |
@@ -1260,8 +1283,7 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct s | |||
1260 | return err; | 1283 | return err; |
1261 | } | 1284 | } |
1262 | 1285 | ||
1263 | if (rpcm) | 1286 | emu->pcm[device] = pcm; |
1264 | *rpcm = pcm; | ||
1265 | 1287 | ||
1266 | return 0; | 1288 | return 0; |
1267 | } | 1289 | } |
@@ -1301,89 +1323,10 @@ static unsigned int i2c_adc_init[][2] = { | |||
1301 | { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ | 1323 | { 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */ |
1302 | }; | 1324 | }; |
1303 | 1325 | ||
1304 | static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | 1326 | static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) |
1305 | struct pci_dev *pci, | ||
1306 | struct snd_ca0106 **rchip) | ||
1307 | { | 1327 | { |
1308 | struct snd_ca0106 *chip; | ||
1309 | struct snd_ca0106_details *c; | ||
1310 | int err; | ||
1311 | int ch; | 1328 | int ch; |
1312 | static struct snd_device_ops ops = { | 1329 | unsigned int def_bits; |
1313 | .dev_free = snd_ca0106_dev_free, | ||
1314 | }; | ||
1315 | |||
1316 | *rchip = NULL; | ||
1317 | |||
1318 | if ((err = pci_enable_device(pci)) < 0) | ||
1319 | return err; | ||
1320 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || | ||
1321 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { | ||
1322 | printk(KERN_ERR "error to set 32bit mask DMA\n"); | ||
1323 | pci_disable_device(pci); | ||
1324 | return -ENXIO; | ||
1325 | } | ||
1326 | |||
1327 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
1328 | if (chip == NULL) { | ||
1329 | pci_disable_device(pci); | ||
1330 | return -ENOMEM; | ||
1331 | } | ||
1332 | |||
1333 | chip->card = card; | ||
1334 | chip->pci = pci; | ||
1335 | chip->irq = -1; | ||
1336 | |||
1337 | spin_lock_init(&chip->emu_lock); | ||
1338 | |||
1339 | chip->port = pci_resource_start(pci, 0); | ||
1340 | if ((chip->res_port = request_region(chip->port, 0x20, | ||
1341 | "snd_ca0106")) == NULL) { | ||
1342 | snd_ca0106_free(chip); | ||
1343 | printk(KERN_ERR "cannot allocate the port\n"); | ||
1344 | return -EBUSY; | ||
1345 | } | ||
1346 | |||
1347 | if (request_irq(pci->irq, snd_ca0106_interrupt, | ||
1348 | IRQF_SHARED, "snd_ca0106", chip)) { | ||
1349 | snd_ca0106_free(chip); | ||
1350 | printk(KERN_ERR "cannot grab irq\n"); | ||
1351 | return -EBUSY; | ||
1352 | } | ||
1353 | chip->irq = pci->irq; | ||
1354 | |||
1355 | /* This stores the periods table. */ | ||
1356 | if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) { | ||
1357 | snd_ca0106_free(chip); | ||
1358 | return -ENOMEM; | ||
1359 | } | ||
1360 | |||
1361 | pci_set_master(pci); | ||
1362 | /* read serial */ | ||
1363 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); | ||
1364 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); | ||
1365 | #if 1 | ||
1366 | printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model, | ||
1367 | pci->revision, chip->serial); | ||
1368 | #endif | ||
1369 | strcpy(card->driver, "CA0106"); | ||
1370 | strcpy(card->shortname, "CA0106"); | ||
1371 | |||
1372 | for (c = ca0106_chip_details; c->serial; c++) { | ||
1373 | if (subsystem[dev]) { | ||
1374 | if (c->serial == subsystem[dev]) | ||
1375 | break; | ||
1376 | } else if (c->serial == chip->serial) | ||
1377 | break; | ||
1378 | } | ||
1379 | chip->details = c; | ||
1380 | if (subsystem[dev]) { | ||
1381 | printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n", | ||
1382 | c->name, chip->serial, subsystem[dev]); | ||
1383 | } | ||
1384 | |||
1385 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
1386 | c->name, chip->port, chip->irq); | ||
1387 | 1330 | ||
1388 | outl(0, chip->port + INTE); | 1331 | outl(0, chip->port + INTE); |
1389 | 1332 | ||
@@ -1401,31 +1344,22 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1401 | * AN = 0 (Audio data) | 1344 | * AN = 0 (Audio data) |
1402 | * P = 0 (Consumer) | 1345 | * P = 0 (Consumer) |
1403 | */ | 1346 | */ |
1404 | snd_ca0106_ptr_write(chip, SPCS0, 0, | 1347 | def_bits = |
1405 | chip->spdif_bits[0] = | 1348 | SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | |
1406 | SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | | 1349 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | |
1407 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | | 1350 | SPCS_GENERATIONSTATUS | 0x00001200 | |
1408 | SPCS_GENERATIONSTATUS | 0x00001200 | | 1351 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT; |
1409 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); | 1352 | if (!resume) { |
1353 | chip->spdif_str_bits[0] = chip->spdif_bits[0] = def_bits; | ||
1354 | chip->spdif_str_bits[1] = chip->spdif_bits[1] = def_bits; | ||
1355 | chip->spdif_str_bits[2] = chip->spdif_bits[2] = def_bits; | ||
1356 | chip->spdif_str_bits[3] = chip->spdif_bits[3] = def_bits; | ||
1357 | } | ||
1410 | /* Only SPCS1 has been tested */ | 1358 | /* Only SPCS1 has been tested */ |
1411 | snd_ca0106_ptr_write(chip, SPCS1, 0, | 1359 | snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_str_bits[1]); |
1412 | chip->spdif_bits[1] = | 1360 | snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_str_bits[0]); |
1413 | SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | | 1361 | snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_str_bits[2]); |
1414 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | | 1362 | snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_str_bits[3]); |
1415 | SPCS_GENERATIONSTATUS | 0x00001200 | | ||
1416 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); | ||
1417 | snd_ca0106_ptr_write(chip, SPCS2, 0, | ||
1418 | chip->spdif_bits[2] = | ||
1419 | SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | | ||
1420 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | | ||
1421 | SPCS_GENERATIONSTATUS | 0x00001200 | | ||
1422 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); | ||
1423 | snd_ca0106_ptr_write(chip, SPCS3, 0, | ||
1424 | chip->spdif_bits[3] = | ||
1425 | SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 | | ||
1426 | SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC | | ||
1427 | SPCS_GENERATIONSTATUS | 0x00001200 | | ||
1428 | 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT); | ||
1429 | 1363 | ||
1430 | snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); | 1364 | snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000); |
1431 | snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); | 1365 | snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000); |
@@ -1433,92 +1367,124 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1433 | /* Write 0x8000 to AC97_REC_GAIN to mute it. */ | 1367 | /* Write 0x8000 to AC97_REC_GAIN to mute it. */ |
1434 | outb(AC97_REC_GAIN, chip->port + AC97ADDRESS); | 1368 | outb(AC97_REC_GAIN, chip->port + AC97ADDRESS); |
1435 | outw(0x8000, chip->port + AC97DATA); | 1369 | outw(0x8000, chip->port + AC97DATA); |
1436 | #if 0 | 1370 | #if 0 /* FIXME: what are these? */ |
1437 | snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006); | 1371 | snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006); |
1438 | snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006); | 1372 | snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006); |
1439 | snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006); | 1373 | snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006); |
1440 | snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006); | 1374 | snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006); |
1441 | #endif | 1375 | #endif |
1442 | 1376 | ||
1443 | //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */ | 1377 | /* OSS drivers set this. */ |
1378 | /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */ | ||
1379 | |||
1444 | /* Analog or Digital output */ | 1380 | /* Analog or Digital output */ |
1445 | snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); | 1381 | snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); |
1446 | snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */ | 1382 | /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. |
1383 | * Use 0x000f0000 for surround71 | ||
1384 | */ | ||
1385 | snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); | ||
1386 | |||
1447 | chip->spdif_enable = 0; /* Set digital SPDIF output off */ | 1387 | chip->spdif_enable = 0; /* Set digital SPDIF output off */ |
1448 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ | 1388 | /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */ |
1449 | //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */ | 1389 | /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */ |
1390 | |||
1391 | /* goes to 0x40c80000 when doing SPDIF IN/OUT */ | ||
1392 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); | ||
1393 | /* (Mute) CAPTURE feedback into PLAYBACK volume. | ||
1394 | * Only lower 16 bits matter. | ||
1395 | */ | ||
1396 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); | ||
1397 | /* SPDIF IN Volume */ | ||
1398 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); | ||
1399 | /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */ | ||
1400 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); | ||
1450 | 1401 | ||
1451 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */ | ||
1452 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */ | ||
1453 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */ | ||
1454 | snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */ | ||
1455 | snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410); | 1402 | snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410); |
1456 | snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676); | 1403 | snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676); |
1457 | snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410); | 1404 | snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410); |
1458 | snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676); | 1405 | snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676); |
1459 | for(ch = 0; ch < 4; ch++) { | 1406 | |
1460 | snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */ | 1407 | for (ch = 0; ch < 4; ch++) { |
1408 | /* Only high 16 bits matter */ | ||
1409 | snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); | ||
1461 | snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030); | 1410 | snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030); |
1462 | //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */ | 1411 | #if 0 /* Mute */ |
1463 | //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */ | 1412 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); |
1464 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */ | 1413 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); |
1465 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */ | 1414 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); |
1415 | snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); | ||
1416 | #endif | ||
1466 | } | 1417 | } |
1467 | if (chip->details->i2c_adc == 1) { | 1418 | if (chip->details->i2c_adc == 1) { |
1468 | /* Select MIC, Line in, TAD in, AUX in */ | 1419 | /* Select MIC, Line in, TAD in, AUX in */ |
1469 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); | 1420 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); |
1470 | /* Default to CAPTURE_SOURCE to i2s in */ | 1421 | /* Default to CAPTURE_SOURCE to i2s in */ |
1471 | chip->capture_source = 3; | 1422 | if (!resume) |
1423 | chip->capture_source = 3; | ||
1472 | } else if (chip->details->ac97 == 1) { | 1424 | } else if (chip->details->ac97 == 1) { |
1473 | /* Default to AC97 in */ | 1425 | /* Default to AC97 in */ |
1474 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4); | 1426 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4); |
1475 | /* Default to CAPTURE_SOURCE to AC97 in */ | 1427 | /* Default to CAPTURE_SOURCE to AC97 in */ |
1476 | chip->capture_source = 4; | 1428 | if (!resume) |
1429 | chip->capture_source = 4; | ||
1477 | } else { | 1430 | } else { |
1478 | /* Select MIC, Line in, TAD in, AUX in */ | 1431 | /* Select MIC, Line in, TAD in, AUX in */ |
1479 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); | 1432 | snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); |
1480 | /* Default to Set CAPTURE_SOURCE to i2s in */ | 1433 | /* Default to Set CAPTURE_SOURCE to i2s in */ |
1481 | chip->capture_source = 3; | 1434 | if (!resume) |
1435 | chip->capture_source = 3; | ||
1482 | } | 1436 | } |
1483 | 1437 | ||
1484 | if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */ | 1438 | if (chip->details->gpio_type == 2) { |
1485 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ | 1439 | /* The SB0438 use GPIO differently. */ |
1440 | /* FIXME: Still need to find out what the other GPIO bits do. | ||
1441 | * E.g. For digital spdif out. | ||
1442 | */ | ||
1486 | outl(0x0, chip->port+GPIO); | 1443 | outl(0x0, chip->port+GPIO); |
1487 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | 1444 | /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ |
1488 | outl(0x005f5301, chip->port+GPIO); /* Analog */ | 1445 | outl(0x005f5301, chip->port+GPIO); /* Analog */ |
1489 | } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */ | 1446 | } else if (chip->details->gpio_type == 1) { |
1490 | /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ | 1447 | /* The SB0410 and SB0413 use GPIO differently. */ |
1448 | /* FIXME: Still need to find out what the other GPIO bits do. | ||
1449 | * E.g. For digital spdif out. | ||
1450 | */ | ||
1491 | outl(0x0, chip->port+GPIO); | 1451 | outl(0x0, chip->port+GPIO); |
1492 | //outl(0x00f0e000, chip->port+GPIO); /* Analog */ | 1452 | /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */ |
1493 | outl(0x005f5301, chip->port+GPIO); /* Analog */ | 1453 | outl(0x005f5301, chip->port+GPIO); /* Analog */ |
1494 | } else { | 1454 | } else { |
1495 | outl(0x0, chip->port+GPIO); | 1455 | outl(0x0, chip->port+GPIO); |
1496 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ | 1456 | outl(0x005f03a3, chip->port+GPIO); /* Analog */ |
1497 | //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */ | 1457 | /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */ |
1498 | } | 1458 | } |
1499 | snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */ | 1459 | snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */ |
1500 | 1460 | ||
1501 | //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); | 1461 | /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */ |
1502 | //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */ | 1462 | /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */ |
1503 | //outl(0x00000009, chip->port+HCFG); | 1463 | /* outl(0x00001409, chip->port+HCFG); */ |
1504 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */ | 1464 | /* outl(0x00000009, chip->port+HCFG); */ |
1465 | /* AC97 2.0, Enable outputs. */ | ||
1466 | outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); | ||
1505 | 1467 | ||
1506 | if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */ | 1468 | if (chip->details->i2c_adc == 1) { |
1469 | /* The SB0410 and SB0413 use I2C to control ADC. */ | ||
1507 | int size, n; | 1470 | int size, n; |
1508 | 1471 | ||
1509 | size = ARRAY_SIZE(i2c_adc_init); | 1472 | size = ARRAY_SIZE(i2c_adc_init); |
1510 | //snd_printk("I2C:array size=0x%x\n", size); | 1473 | /* snd_printk("I2C:array size=0x%x\n", size); */ |
1511 | for (n=0; n < size; n++) { | 1474 | for (n = 0; n < size; n++) |
1512 | snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]); | 1475 | snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], |
1513 | } | 1476 | i2c_adc_init[n][1]); |
1514 | for (n=0; n < 4; n++) { | 1477 | for (n = 0; n < 4; n++) { |
1515 | chip->i2c_capture_volume[n][0]= 0xcf; | 1478 | chip->i2c_capture_volume[n][0] = 0xcf; |
1516 | chip->i2c_capture_volume[n][1]= 0xcf; | 1479 | chip->i2c_capture_volume[n][1] = 0xcf; |
1517 | } | 1480 | } |
1518 | chip->i2c_capture_source=2; /* Line in */ | 1481 | chip->i2c_capture_source = 2; /* Line in */ |
1519 | //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */ | 1482 | /* Enable Line-in capture. MIC in currently untested. */ |
1483 | /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ | ||
1520 | } | 1484 | } |
1521 | if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */ | 1485 | |
1486 | if (chip->details->spi_dac == 1) { | ||
1487 | /* The SB0570 use SPI to control DAC. */ | ||
1522 | int size, n; | 1488 | int size, n; |
1523 | 1489 | ||
1524 | size = ARRAY_SIZE(spi_dac_init); | 1490 | size = ARRAY_SIZE(spi_dac_init); |
@@ -1530,9 +1496,112 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | |||
1530 | chip->spi_dac_reg[reg] = spi_dac_init[n]; | 1496 | chip->spi_dac_reg[reg] = spi_dac_init[n]; |
1531 | } | 1497 | } |
1532 | } | 1498 | } |
1499 | } | ||
1533 | 1500 | ||
1534 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, | 1501 | static void ca0106_stop_chip(struct snd_ca0106 *chip) |
1535 | chip, &ops)) < 0) { | 1502 | { |
1503 | /* disable interrupts */ | ||
1504 | snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0); | ||
1505 | outl(0, chip->port + INTE); | ||
1506 | snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0); | ||
1507 | udelay(1000); | ||
1508 | /* disable audio */ | ||
1509 | /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */ | ||
1510 | outl(0, chip->port + HCFG); | ||
1511 | /* FIXME: We need to stop and DMA transfers here. | ||
1512 | * But as I am not sure how yet, we cannot from the dma pages. | ||
1513 | * So we can fix: snd-malloc: Memory leak? pages not freed = 8 | ||
1514 | */ | ||
1515 | } | ||
1516 | |||
1517 | static int __devinit snd_ca0106_create(int dev, struct snd_card *card, | ||
1518 | struct pci_dev *pci, | ||
1519 | struct snd_ca0106 **rchip) | ||
1520 | { | ||
1521 | struct snd_ca0106 *chip; | ||
1522 | struct snd_ca0106_details *c; | ||
1523 | int err; | ||
1524 | static struct snd_device_ops ops = { | ||
1525 | .dev_free = snd_ca0106_dev_free, | ||
1526 | }; | ||
1527 | |||
1528 | *rchip = NULL; | ||
1529 | |||
1530 | err = pci_enable_device(pci); | ||
1531 | if (err < 0) | ||
1532 | return err; | ||
1533 | if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 || | ||
1534 | pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) { | ||
1535 | printk(KERN_ERR "error to set 32bit mask DMA\n"); | ||
1536 | pci_disable_device(pci); | ||
1537 | return -ENXIO; | ||
1538 | } | ||
1539 | |||
1540 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
1541 | if (chip == NULL) { | ||
1542 | pci_disable_device(pci); | ||
1543 | return -ENOMEM; | ||
1544 | } | ||
1545 | |||
1546 | chip->card = card; | ||
1547 | chip->pci = pci; | ||
1548 | chip->irq = -1; | ||
1549 | |||
1550 | spin_lock_init(&chip->emu_lock); | ||
1551 | |||
1552 | chip->port = pci_resource_start(pci, 0); | ||
1553 | chip->res_port = request_region(chip->port, 0x20, "snd_ca0106"); | ||
1554 | if (!chip->res_port) { | ||
1555 | snd_ca0106_free(chip); | ||
1556 | printk(KERN_ERR "cannot allocate the port\n"); | ||
1557 | return -EBUSY; | ||
1558 | } | ||
1559 | |||
1560 | if (request_irq(pci->irq, snd_ca0106_interrupt, | ||
1561 | IRQF_SHARED, "snd_ca0106", chip)) { | ||
1562 | snd_ca0106_free(chip); | ||
1563 | printk(KERN_ERR "cannot grab irq\n"); | ||
1564 | return -EBUSY; | ||
1565 | } | ||
1566 | chip->irq = pci->irq; | ||
1567 | |||
1568 | /* This stores the periods table. */ | ||
1569 | if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), | ||
1570 | 1024, &chip->buffer) < 0) { | ||
1571 | snd_ca0106_free(chip); | ||
1572 | return -ENOMEM; | ||
1573 | } | ||
1574 | |||
1575 | pci_set_master(pci); | ||
1576 | /* read serial */ | ||
1577 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial); | ||
1578 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model); | ||
1579 | printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", | ||
1580 | chip->model, pci->revision, chip->serial); | ||
1581 | strcpy(card->driver, "CA0106"); | ||
1582 | strcpy(card->shortname, "CA0106"); | ||
1583 | |||
1584 | for (c = ca0106_chip_details; c->serial; c++) { | ||
1585 | if (subsystem[dev]) { | ||
1586 | if (c->serial == subsystem[dev]) | ||
1587 | break; | ||
1588 | } else if (c->serial == chip->serial) | ||
1589 | break; | ||
1590 | } | ||
1591 | chip->details = c; | ||
1592 | if (subsystem[dev]) { | ||
1593 | printk(KERN_INFO "snd-ca0106: Sound card name=%s, " | ||
1594 | "subsystem=0x%x. Forced to subsystem=0x%x\n", | ||
1595 | c->name, chip->serial, subsystem[dev]); | ||
1596 | } | ||
1597 | |||
1598 | sprintf(card->longname, "%s at 0x%lx irq %i", | ||
1599 | c->name, chip->port, chip->irq); | ||
1600 | |||
1601 | ca0106_init_chip(chip, 0); | ||
1602 | |||
1603 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
1604 | if (err < 0) { | ||
1536 | snd_ca0106_free(chip); | 1605 | snd_ca0106_free(chip); |
1537 | return err; | 1606 | return err; |
1538 | } | 1607 | } |
@@ -1629,7 +1698,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1629 | static int dev; | 1698 | static int dev; |
1630 | struct snd_card *card; | 1699 | struct snd_card *card; |
1631 | struct snd_ca0106 *chip; | 1700 | struct snd_ca0106 *chip; |
1632 | int err; | 1701 | int i, err; |
1633 | 1702 | ||
1634 | if (dev >= SNDRV_CARDS) | 1703 | if (dev >= SNDRV_CARDS) |
1635 | return -ENODEV; | 1704 | return -ENODEV; |
@@ -1642,44 +1711,31 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1642 | if (card == NULL) | 1711 | if (card == NULL) |
1643 | return -ENOMEM; | 1712 | return -ENOMEM; |
1644 | 1713 | ||
1645 | if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) { | 1714 | err = snd_ca0106_create(dev, card, pci, &chip); |
1646 | snd_card_free(card); | 1715 | if (err < 0) |
1647 | return err; | 1716 | goto error; |
1648 | } | 1717 | card->private_data = chip; |
1649 | 1718 | ||
1650 | if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) { | 1719 | for (i = 0; i < 4; i++) { |
1651 | snd_card_free(card); | 1720 | err = snd_ca0106_pcm(chip, i); |
1652 | return err; | 1721 | if (err < 0) |
1653 | } | 1722 | goto error; |
1654 | if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) { | ||
1655 | snd_card_free(card); | ||
1656 | return err; | ||
1657 | } | ||
1658 | if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) { | ||
1659 | snd_card_free(card); | ||
1660 | return err; | ||
1661 | } | ||
1662 | if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) { | ||
1663 | snd_card_free(card); | ||
1664 | return err; | ||
1665 | } | ||
1666 | if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */ | ||
1667 | if ((err = snd_ca0106_ac97(chip)) < 0) { | ||
1668 | snd_card_free(card); | ||
1669 | return err; | ||
1670 | } | ||
1671 | } | 1723 | } |
1672 | if ((err = snd_ca0106_mixer(chip)) < 0) { | 1724 | |
1673 | snd_card_free(card); | 1725 | if (chip->details->ac97 == 1) { |
1674 | return err; | 1726 | /* The SB0410 and SB0413 do not have an AC97 chip. */ |
1727 | err = snd_ca0106_ac97(chip); | ||
1728 | if (err < 0) | ||
1729 | goto error; | ||
1675 | } | 1730 | } |
1731 | err = snd_ca0106_mixer(chip); | ||
1732 | if (err < 0) | ||
1733 | goto error; | ||
1676 | 1734 | ||
1677 | snd_printdd("ca0106: probe for MIDI channel A ..."); | 1735 | snd_printdd("ca0106: probe for MIDI channel A ..."); |
1678 | if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) { | 1736 | err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A); |
1679 | snd_card_free(card); | 1737 | if (err < 0) |
1680 | snd_printdd(" failed, err=0x%x\n",err); | 1738 | goto error; |
1681 | return err; | ||
1682 | } | ||
1683 | snd_printdd(" done.\n"); | 1739 | snd_printdd(" done.\n"); |
1684 | 1740 | ||
1685 | #ifdef CONFIG_PROC_FS | 1741 | #ifdef CONFIG_PROC_FS |
@@ -1688,14 +1744,17 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci, | |||
1688 | 1744 | ||
1689 | snd_card_set_dev(card, &pci->dev); | 1745 | snd_card_set_dev(card, &pci->dev); |
1690 | 1746 | ||
1691 | if ((err = snd_card_register(card)) < 0) { | 1747 | err = snd_card_register(card); |
1692 | snd_card_free(card); | 1748 | if (err < 0) |
1693 | return err; | 1749 | goto error; |
1694 | } | ||
1695 | 1750 | ||
1696 | pci_set_drvdata(pci, card); | 1751 | pci_set_drvdata(pci, card); |
1697 | dev++; | 1752 | dev++; |
1698 | return 0; | 1753 | return 0; |
1754 | |||
1755 | error: | ||
1756 | snd_card_free(card); | ||
1757 | return err; | ||
1699 | } | 1758 | } |
1700 | 1759 | ||
1701 | static void __devexit snd_ca0106_remove(struct pci_dev *pci) | 1760 | static void __devexit snd_ca0106_remove(struct pci_dev *pci) |
@@ -1704,6 +1763,59 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci) | |||
1704 | pci_set_drvdata(pci, NULL); | 1763 | pci_set_drvdata(pci, NULL); |
1705 | } | 1764 | } |
1706 | 1765 | ||
1766 | #ifdef CONFIG_PM | ||
1767 | static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state) | ||
1768 | { | ||
1769 | struct snd_card *card = pci_get_drvdata(pci); | ||
1770 | struct snd_ca0106 *chip = card->private_data; | ||
1771 | int i; | ||
1772 | |||
1773 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | ||
1774 | for (i = 0; i < 4; i++) | ||
1775 | snd_pcm_suspend_all(chip->pcm[i]); | ||
1776 | if (chip->details->ac97) | ||
1777 | snd_ac97_suspend(chip->ac97); | ||
1778 | snd_ca0106_mixer_suspend(chip); | ||
1779 | |||
1780 | ca0106_stop_chip(chip); | ||
1781 | |||
1782 | pci_disable_device(pci); | ||
1783 | pci_save_state(pci); | ||
1784 | pci_set_power_state(pci, pci_choose_state(pci, state)); | ||
1785 | return 0; | ||
1786 | } | ||
1787 | |||
1788 | static int snd_ca0106_resume(struct pci_dev *pci) | ||
1789 | { | ||
1790 | struct snd_card *card = pci_get_drvdata(pci); | ||
1791 | struct snd_ca0106 *chip = card->private_data; | ||
1792 | int i; | ||
1793 | |||
1794 | pci_set_power_state(pci, PCI_D0); | ||
1795 | pci_restore_state(pci); | ||
1796 | |||
1797 | if (pci_enable_device(pci) < 0) { | ||
1798 | snd_card_disconnect(card); | ||
1799 | return -EIO; | ||
1800 | } | ||
1801 | |||
1802 | pci_set_master(pci); | ||
1803 | |||
1804 | ca0106_init_chip(chip, 1); | ||
1805 | |||
1806 | if (chip->details->ac97) | ||
1807 | snd_ac97_resume(chip->ac97); | ||
1808 | snd_ca0106_mixer_resume(chip); | ||
1809 | if (chip->details->spi_dac) { | ||
1810 | for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++) | ||
1811 | snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]); | ||
1812 | } | ||
1813 | |||
1814 | snd_power_change_state(card, SNDRV_CTL_POWER_D0); | ||
1815 | return 0; | ||
1816 | } | ||
1817 | #endif | ||
1818 | |||
1707 | // PCI IDs | 1819 | // PCI IDs |
1708 | static struct pci_device_id snd_ca0106_ids[] = { | 1820 | static struct pci_device_id snd_ca0106_ids[] = { |
1709 | { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */ | 1821 | { 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */ |
@@ -1717,6 +1829,10 @@ static struct pci_driver driver = { | |||
1717 | .id_table = snd_ca0106_ids, | 1829 | .id_table = snd_ca0106_ids, |
1718 | .probe = snd_ca0106_probe, | 1830 | .probe = snd_ca0106_probe, |
1719 | .remove = __devexit_p(snd_ca0106_remove), | 1831 | .remove = __devexit_p(snd_ca0106_remove), |
1832 | #ifdef CONFIG_PM | ||
1833 | .suspend = snd_ca0106_suspend, | ||
1834 | .resume = snd_ca0106_resume, | ||
1835 | #endif | ||
1720 | }; | 1836 | }; |
1721 | 1837 | ||
1722 | // initialization of the module | 1838 | // initialization of the module |
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 3025ed1b6e1e..ad2888705d2a 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c | |||
@@ -75,6 +75,84 @@ | |||
75 | 75 | ||
76 | #include "ca0106.h" | 76 | #include "ca0106.h" |
77 | 77 | ||
78 | static void ca0106_spdif_enable(struct snd_ca0106 *emu) | ||
79 | { | ||
80 | unsigned int val; | ||
81 | |||
82 | if (emu->spdif_enable) { | ||
83 | /* Digital */ | ||
84 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | ||
85 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); | ||
86 | val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000; | ||
87 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); | ||
88 | val = inl(emu->port + GPIO) & ~0x101; | ||
89 | outl(val, emu->port + GPIO); | ||
90 | |||
91 | } else { | ||
92 | /* Analog */ | ||
93 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | ||
94 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); | ||
95 | val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000; | ||
96 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val); | ||
97 | val = inl(emu->port + GPIO) | 0x101; | ||
98 | outl(val, emu->port + GPIO); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | static void ca0106_set_capture_source(struct snd_ca0106 *emu) | ||
103 | { | ||
104 | unsigned int val = emu->capture_source; | ||
105 | unsigned int source, mask; | ||
106 | source = (val << 28) | (val << 24) | (val << 20) | (val << 16); | ||
107 | mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; | ||
108 | snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); | ||
109 | } | ||
110 | |||
111 | static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu, | ||
112 | unsigned int val, int force) | ||
113 | { | ||
114 | unsigned int ngain, ogain; | ||
115 | u32 source; | ||
116 | |||
117 | snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | ||
118 | ngain = emu->i2c_capture_volume[val][0]; /* Left */ | ||
119 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ | ||
120 | if (force || ngain != ogain) | ||
121 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff); | ||
122 | ngain = emu->i2c_capture_volume[val][1]; /* Right */ | ||
123 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */ | ||
124 | if (force || ngain != ogain) | ||
125 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff); | ||
126 | source = 1 << val; | ||
127 | snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ | ||
128 | emu->i2c_capture_source = val; | ||
129 | } | ||
130 | |||
131 | static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu) | ||
132 | { | ||
133 | u32 tmp; | ||
134 | |||
135 | if (emu->capture_mic_line_in) { | ||
136 | /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ | ||
137 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
138 | tmp = tmp | 0x400; | ||
139 | outl(tmp, emu->port+GPIO); | ||
140 | /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */ | ||
141 | } else { | ||
142 | /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */ | ||
143 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
144 | outl(tmp, emu->port+GPIO); | ||
145 | /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */ | ||
146 | } | ||
147 | } | ||
148 | |||
149 | static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx) | ||
150 | { | ||
151 | snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_str_bits[idx]); | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | */ | ||
78 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); | 156 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); |
79 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); | 157 | static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); |
80 | 158 | ||
@@ -95,30 +173,12 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol, | |||
95 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 173 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
96 | unsigned int val; | 174 | unsigned int val; |
97 | int change = 0; | 175 | int change = 0; |
98 | u32 mask; | ||
99 | 176 | ||
100 | val = !!ucontrol->value.integer.value[0]; | 177 | val = !!ucontrol->value.integer.value[0]; |
101 | change = (emu->spdif_enable != val); | 178 | change = (emu->spdif_enable != val); |
102 | if (change) { | 179 | if (change) { |
103 | emu->spdif_enable = val; | 180 | emu->spdif_enable = val; |
104 | if (val) { | 181 | ca0106_spdif_enable(emu); |
105 | /* Digital */ | ||
106 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | ||
107 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000); | ||
108 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, | ||
109 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000); | ||
110 | mask = inl(emu->port + GPIO) & ~0x101; | ||
111 | outl(mask, emu->port + GPIO); | ||
112 | |||
113 | } else { | ||
114 | /* Analog */ | ||
115 | snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf); | ||
116 | snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000); | ||
117 | snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, | ||
118 | snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000); | ||
119 | mask = inl(emu->port + GPIO) | 0x101; | ||
120 | outl(mask, emu->port + GPIO); | ||
121 | } | ||
122 | } | 182 | } |
123 | return change; | 183 | return change; |
124 | } | 184 | } |
@@ -154,8 +214,6 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, | |||
154 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 214 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
155 | unsigned int val; | 215 | unsigned int val; |
156 | int change = 0; | 216 | int change = 0; |
157 | u32 mask; | ||
158 | u32 source; | ||
159 | 217 | ||
160 | val = ucontrol->value.enumerated.item[0] ; | 218 | val = ucontrol->value.enumerated.item[0] ; |
161 | if (val >= 6) | 219 | if (val >= 6) |
@@ -163,9 +221,7 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol, | |||
163 | change = (emu->capture_source != val); | 221 | change = (emu->capture_source != val); |
164 | if (change) { | 222 | if (change) { |
165 | emu->capture_source = val; | 223 | emu->capture_source = val; |
166 | source = (val << 28) | (val << 24) | (val << 20) | (val << 16); | 224 | ca0106_set_capture_source(emu); |
167 | mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff; | ||
168 | snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask); | ||
169 | } | 225 | } |
170 | return change; | 226 | return change; |
171 | } | 227 | } |
@@ -200,9 +256,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, | |||
200 | { | 256 | { |
201 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 257 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
202 | unsigned int source_id; | 258 | unsigned int source_id; |
203 | unsigned int ngain, ogain; | ||
204 | int change = 0; | 259 | int change = 0; |
205 | u32 source; | ||
206 | /* If the capture source has changed, | 260 | /* If the capture source has changed, |
207 | * update the capture volume from the cached value | 261 | * update the capture volume from the cached value |
208 | * for the particular source. | 262 | * for the particular source. |
@@ -212,18 +266,7 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol, | |||
212 | return -EINVAL; | 266 | return -EINVAL; |
213 | change = (emu->i2c_capture_source != source_id); | 267 | change = (emu->i2c_capture_source != source_id); |
214 | if (change) { | 268 | if (change) { |
215 | snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | 269 | ca0106_set_i2c_capture_source(emu, source_id, 0); |
216 | ngain = emu->i2c_capture_volume[source_id][0]; /* Left */ | ||
217 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */ | ||
218 | if (ngain != ogain) | ||
219 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff)); | ||
220 | ngain = emu->i2c_capture_volume[source_id][1]; /* Left */ | ||
221 | ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */ | ||
222 | if (ngain != ogain) | ||
223 | snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff)); | ||
224 | source = 1 << source_id; | ||
225 | snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */ | ||
226 | emu->i2c_capture_source = source_id; | ||
227 | } | 270 | } |
228 | return change; | 271 | return change; |
229 | } | 272 | } |
@@ -271,7 +314,6 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, | |||
271 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 314 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
272 | unsigned int val; | 315 | unsigned int val; |
273 | int change = 0; | 316 | int change = 0; |
274 | u32 tmp; | ||
275 | 317 | ||
276 | val = ucontrol->value.enumerated.item[0] ; | 318 | val = ucontrol->value.enumerated.item[0] ; |
277 | if (val > 1) | 319 | if (val > 1) |
@@ -279,18 +321,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol, | |||
279 | change = (emu->capture_mic_line_in != val); | 321 | change = (emu->capture_mic_line_in != val); |
280 | if (change) { | 322 | if (change) { |
281 | emu->capture_mic_line_in = val; | 323 | emu->capture_mic_line_in = val; |
282 | if (val) { | 324 | ca0106_set_capture_mic_line_in(emu); |
283 | //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | ||
284 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
285 | tmp = tmp | 0x400; | ||
286 | outl(tmp, emu->port+GPIO); | ||
287 | //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); | ||
288 | } else { | ||
289 | //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */ | ||
290 | tmp = inl(emu->port+GPIO) & ~0x400; | ||
291 | outl(tmp, emu->port+GPIO); | ||
292 | //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); | ||
293 | } | ||
294 | } | 325 | } |
295 | return change; | 326 | return change; |
296 | } | 327 | } |
@@ -322,16 +353,33 @@ static int snd_ca0106_spdif_info(struct snd_kcontrol *kcontrol, | |||
322 | return 0; | 353 | return 0; |
323 | } | 354 | } |
324 | 355 | ||
325 | static int snd_ca0106_spdif_get(struct snd_kcontrol *kcontrol, | 356 | static void decode_spdif_bits(unsigned char *status, unsigned int bits) |
357 | { | ||
358 | status[0] = (bits >> 0) & 0xff; | ||
359 | status[1] = (bits >> 8) & 0xff; | ||
360 | status[2] = (bits >> 16) & 0xff; | ||
361 | status[3] = (bits >> 24) & 0xff; | ||
362 | } | ||
363 | |||
364 | static int snd_ca0106_spdif_get_default(struct snd_kcontrol *kcontrol, | ||
326 | struct snd_ctl_elem_value *ucontrol) | 365 | struct snd_ctl_elem_value *ucontrol) |
327 | { | 366 | { |
328 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 367 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
329 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 368 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
330 | 369 | ||
331 | ucontrol->value.iec958.status[0] = (emu->spdif_bits[idx] >> 0) & 0xff; | 370 | decode_spdif_bits(ucontrol->value.iec958.status, |
332 | ucontrol->value.iec958.status[1] = (emu->spdif_bits[idx] >> 8) & 0xff; | 371 | emu->spdif_bits[idx]); |
333 | ucontrol->value.iec958.status[2] = (emu->spdif_bits[idx] >> 16) & 0xff; | 372 | return 0; |
334 | ucontrol->value.iec958.status[3] = (emu->spdif_bits[idx] >> 24) & 0xff; | 373 | } |
374 | |||
375 | static int snd_ca0106_spdif_get_stream(struct snd_kcontrol *kcontrol, | ||
376 | struct snd_ctl_elem_value *ucontrol) | ||
377 | { | ||
378 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
379 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
380 | |||
381 | decode_spdif_bits(ucontrol->value.iec958.status, | ||
382 | emu->spdif_str_bits[idx]); | ||
335 | return 0; | 383 | return 0; |
336 | } | 384 | } |
337 | 385 | ||
@@ -345,24 +393,48 @@ static int snd_ca0106_spdif_get_mask(struct snd_kcontrol *kcontrol, | |||
345 | return 0; | 393 | return 0; |
346 | } | 394 | } |
347 | 395 | ||
348 | static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol, | 396 | static unsigned int encode_spdif_bits(unsigned char *status) |
397 | { | ||
398 | return ((unsigned int)status[0] << 0) | | ||
399 | ((unsigned int)status[1] << 8) | | ||
400 | ((unsigned int)status[2] << 16) | | ||
401 | ((unsigned int)status[3] << 24); | ||
402 | } | ||
403 | |||
404 | static int snd_ca0106_spdif_put_default(struct snd_kcontrol *kcontrol, | ||
349 | struct snd_ctl_elem_value *ucontrol) | 405 | struct snd_ctl_elem_value *ucontrol) |
350 | { | 406 | { |
351 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | 407 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); |
352 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | 408 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); |
353 | int change; | ||
354 | unsigned int val; | 409 | unsigned int val; |
355 | 410 | ||
356 | val = (ucontrol->value.iec958.status[0] << 0) | | 411 | val = encode_spdif_bits(ucontrol->value.iec958.status); |
357 | (ucontrol->value.iec958.status[1] << 8) | | 412 | if (val != emu->spdif_bits[idx]) { |
358 | (ucontrol->value.iec958.status[2] << 16) | | ||
359 | (ucontrol->value.iec958.status[3] << 24); | ||
360 | change = val != emu->spdif_bits[idx]; | ||
361 | if (change) { | ||
362 | snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val); | ||
363 | emu->spdif_bits[idx] = val; | 413 | emu->spdif_bits[idx] = val; |
414 | /* FIXME: this isn't safe, but needed to keep the compatibility | ||
415 | * with older alsa-lib config | ||
416 | */ | ||
417 | emu->spdif_str_bits[idx] = val; | ||
418 | ca0106_set_spdif_bits(emu, idx); | ||
419 | return 1; | ||
364 | } | 420 | } |
365 | return change; | 421 | return 0; |
422 | } | ||
423 | |||
424 | static int snd_ca0106_spdif_put_stream(struct snd_kcontrol *kcontrol, | ||
425 | struct snd_ctl_elem_value *ucontrol) | ||
426 | { | ||
427 | struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol); | ||
428 | unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
429 | unsigned int val; | ||
430 | |||
431 | val = encode_spdif_bits(ucontrol->value.iec958.status); | ||
432 | if (val != emu->spdif_str_bits[idx]) { | ||
433 | emu->spdif_str_bits[idx] = val; | ||
434 | ca0106_set_spdif_bits(emu, idx); | ||
435 | return 1; | ||
436 | } | ||
437 | return 0; | ||
366 | } | 438 | } |
367 | 439 | ||
368 | static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, | 440 | static int snd_ca0106_volume_info(struct snd_kcontrol *kcontrol, |
@@ -573,8 +645,16 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { | |||
573 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), | 645 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), |
574 | .count = 4, | 646 | .count = 4, |
575 | .info = snd_ca0106_spdif_info, | 647 | .info = snd_ca0106_spdif_info, |
576 | .get = snd_ca0106_spdif_get, | 648 | .get = snd_ca0106_spdif_get_default, |
577 | .put = snd_ca0106_spdif_put | 649 | .put = snd_ca0106_spdif_put_default |
650 | }, | ||
651 | { | ||
652 | .iface = SNDRV_CTL_ELEM_IFACE_PCM, | ||
653 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM), | ||
654 | .count = 4, | ||
655 | .info = snd_ca0106_spdif_info, | ||
656 | .get = snd_ca0106_spdif_get_stream, | ||
657 | .put = snd_ca0106_spdif_put_stream | ||
578 | }, | 658 | }, |
579 | }; | 659 | }; |
580 | 660 | ||
@@ -773,3 +853,50 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) | |||
773 | return 0; | 853 | return 0; |
774 | } | 854 | } |
775 | 855 | ||
856 | #ifdef CONFIG_PM | ||
857 | struct ca0106_vol_tbl { | ||
858 | unsigned int channel_id; | ||
859 | unsigned int reg; | ||
860 | }; | ||
861 | |||
862 | static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = { | ||
863 | { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 }, | ||
864 | { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 }, | ||
865 | { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 }, | ||
866 | { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 }, | ||
867 | { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 }, | ||
868 | { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 }, | ||
869 | { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 }, | ||
870 | { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 }, | ||
871 | { 1, CAPTURE_CONTROL }, | ||
872 | }; | ||
873 | |||
874 | void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip) | ||
875 | { | ||
876 | int i; | ||
877 | |||
878 | /* save volumes */ | ||
879 | for (i = 0; i < NUM_SAVED_VOLUMES; i++) | ||
880 | chip->saved_vol[i] = | ||
881 | snd_ca0106_ptr_read(chip, saved_volumes[i].reg, | ||
882 | saved_volumes[i].channel_id); | ||
883 | } | ||
884 | |||
885 | void snd_ca0106_mixer_resume(struct snd_ca0106 *chip) | ||
886 | { | ||
887 | int i; | ||
888 | |||
889 | for (i = 0; i < NUM_SAVED_VOLUMES; i++) | ||
890 | snd_ca0106_ptr_write(chip, saved_volumes[i].reg, | ||
891 | saved_volumes[i].channel_id, | ||
892 | chip->saved_vol[i]); | ||
893 | |||
894 | ca0106_spdif_enable(chip); | ||
895 | ca0106_set_capture_source(chip); | ||
896 | ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1); | ||
897 | for (i = 0; i < 4; i++) | ||
898 | ca0106_set_spdif_bits(chip, i); | ||
899 | if (chip->details->i2c_adc) | ||
900 | ca0106_set_capture_mic_line_in(chip); | ||
901 | } | ||
902 | #endif /* CONFIG_PM */ | ||
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index fb6dc3980257..8ab07aa63652 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -3640,7 +3640,10 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3640 | { | 3640 | { |
3641 | struct snd_card *card = pci_get_drvdata(pci); | 3641 | struct snd_card *card = pci_get_drvdata(pci); |
3642 | struct snd_cs46xx *chip = card->private_data; | 3642 | struct snd_cs46xx *chip = card->private_data; |
3643 | int i, amp_saved; | 3643 | int amp_saved; |
3644 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | ||
3645 | int i; | ||
3646 | #endif | ||
3644 | 3647 | ||
3645 | pci_set_power_state(pci, PCI_D0); | 3648 | pci_set_power_state(pci, PCI_D0); |
3646 | pci_restore_state(pci); | 3649 | pci_restore_state(pci); |
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index de5ee8f097f6..7958006a1d66 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -69,7 +69,7 @@ MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); | |||
69 | * EMU10K1 init / done | 69 | * EMU10K1 init / done |
70 | *************************************************************************/ | 70 | *************************************************************************/ |
71 | 71 | ||
72 | void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch) | 72 | void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch) |
73 | { | 73 | { |
74 | snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); | 74 | snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0); |
75 | snd_emu10k1_ptr_write(emu, IP, ch, 0); | 75 | snd_emu10k1_ptr_write(emu, IP, ch, 0); |
@@ -151,9 +151,9 @@ static unsigned int i2c_adc_init[][2] = { | |||
151 | { 0x12, 0x32 }, /* ALC Control 3 */ | 151 | { 0x12, 0x32 }, /* ALC Control 3 */ |
152 | { 0x13, 0x00 }, /* Noise gate control */ | 152 | { 0x13, 0x00 }, /* Noise gate control */ |
153 | { 0x14, 0xa6 }, /* Limiter control */ | 153 | { 0x14, 0xa6 }, /* Limiter control */ |
154 | { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */ | 154 | { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */ |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | 157 | static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) |
158 | { | 158 | { |
159 | unsigned int silent_page; | 159 | unsigned int silent_page; |
@@ -161,8 +161,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
161 | u32 tmp; | 161 | u32 tmp; |
162 | 162 | ||
163 | /* disable audio and lock cache */ | 163 | /* disable audio and lock cache */ |
164 | outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, | 164 | outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | |
165 | emu->port + HCFG); | 165 | HCFG_MUTEBUTTONENABLE, emu->port + HCFG); |
166 | 166 | ||
167 | /* reset recording buffers */ | 167 | /* reset recording buffers */ |
168 | snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE); | 168 | 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) | |||
179 | snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); | 179 | snd_emu10k1_ptr_write(emu, SOLEL, 0, 0); |
180 | snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); | 180 | snd_emu10k1_ptr_write(emu, SOLEH, 0, 0); |
181 | 181 | ||
182 | if (emu->audigy){ | 182 | if (emu->audigy) { |
183 | /* set SPDIF bypass mode */ | 183 | /* set SPDIF bypass mode */ |
184 | snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT); | 184 | snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT); |
185 | /* enable rear left + rear right AC97 slots */ | 185 | /* 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) | |||
197 | 197 | ||
198 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | 198 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
199 | /* Hacks for Alice3 to work independent of haP16V driver */ | 199 | /* Hacks for Alice3 to work independent of haP16V driver */ |
200 | //Setup SRCMulti_I2S SamplingRate | 200 | /* Setup SRCMulti_I2S SamplingRate */ |
201 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); | 201 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); |
202 | tmp &= 0xfffff1ff; | 202 | tmp &= 0xfffff1ff; |
203 | tmp |= (0x2<<9); | 203 | tmp |= (0x2<<9); |
204 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); | 204 | snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp); |
205 | 205 | ||
206 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ | 206 | /* Setup SRCSel (Enable Spdif,I2S SRCMulti) */ |
207 | snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); | 207 | snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14); |
208 | /* Setup SRCMulti Input Audio Enable */ | 208 | /* Setup SRCMulti Input Audio Enable */ |
@@ -217,7 +217,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
217 | if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ | 217 | if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ |
218 | /* Hacks for Alice3 to work independent of haP16V driver */ | 218 | /* Hacks for Alice3 to work independent of haP16V driver */ |
219 | snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); | 219 | snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); |
220 | //Setup SRCMulti_I2S SamplingRate | 220 | /* Setup SRCMulti_I2S SamplingRate */ |
221 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); | 221 | tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); |
222 | tmp &= 0xfffff1ff; | 222 | tmp &= 0xfffff1ff; |
223 | tmp |= (0x2<<9); | 223 | tmp |= (0x2<<9); |
@@ -270,13 +270,13 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) | |||
270 | size = ARRAY_SIZE(i2c_adc_init); | 270 | size = ARRAY_SIZE(i2c_adc_init); |
271 | for (n = 0; n < size; n++) | 271 | for (n = 0; n < size; n++) |
272 | snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); | 272 | snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]); |
273 | for (n=0; n < 4; n++) { | 273 | for (n = 0; n < 4; n++) { |
274 | emu->i2c_capture_volume[n][0]= 0xcf; | 274 | emu->i2c_capture_volume[n][0] = 0xcf; |
275 | emu->i2c_capture_volume[n][1]= 0xcf; | 275 | emu->i2c_capture_volume[n][1] = 0xcf; |
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
279 | 279 | ||
280 | snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); | 280 | snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); |
281 | snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ | 281 | snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ |
282 | snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */ | 282 | 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) | |||
313 | (emu->model == 0x21 && emu->revision < 6)) | 313 | (emu->model == 0x21 && emu->revision < 6)) |
314 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG); | 314 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG); |
315 | else | 315 | else |
316 | // With on-chip joystick | 316 | /* With on-chip joystick */ |
317 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); | 317 | outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); |
318 | 318 | ||
319 | if (enable_ir) { /* enable IR for SB Live */ | 319 | 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) | |||
335 | outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG); | 335 | outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG); |
336 | udelay(100); | 336 | udelay(100); |
337 | outl(reg, emu->port + HCFG); | 337 | outl(reg, emu->port + HCFG); |
338 | } | 338 | } |
339 | } | 339 | } |
340 | 340 | ||
341 | if (emu->card_capabilities->emu_model) { | 341 | if (emu->card_capabilities->emu_model) { |
342 | ; /* Disable all access to A_IOCFG for the emu1010 */ | 342 | ; /* Disable all access to A_IOCFG for the emu1010 */ |
343 | } else if (emu->card_capabilities->i2c_adc) { | 343 | } else if (emu->card_capabilities->i2c_adc) { |
@@ -364,7 +364,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) | |||
364 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ | 364 | ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */ |
365 | } else if (emu->audigy) { | 365 | } else if (emu->audigy) { |
366 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); | 366 | outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); |
367 | 367 | ||
368 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ | 368 | if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ |
369 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. | 369 | /* Unmute Analog now. Set GPO6 to 1 for Apollo. |
370 | * This has to be done after init ALice3 I2SOut beyond 48KHz. | 370 | * 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) | |||
378 | outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); | 378 | outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG); |
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
382 | #if 0 | 382 | #if 0 |
383 | { | 383 | { |
384 | unsigned int tmp; | 384 | unsigned int tmp; |
385 | /* FIXME: the following routine disables LiveDrive-II !! */ | 385 | /* FIXME: the following routine disables LiveDrive-II !! */ |
386 | // TOSLink detection | 386 | /* TOSLink detection */ |
387 | emu->tos_link = 0; | 387 | emu->tos_link = 0; |
388 | tmp = inl(emu->port + HCFG); | 388 | tmp = inl(emu->port + HCFG); |
389 | if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { | 389 | if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) { |
@@ -400,7 +400,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu) | |||
400 | snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); | 400 | snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE); |
401 | } | 401 | } |
402 | 402 | ||
403 | int snd_emu10k1_done(struct snd_emu10k1 * emu) | 403 | int snd_emu10k1_done(struct snd_emu10k1 *emu) |
404 | { | 404 | { |
405 | int ch; | 405 | int ch; |
406 | 406 | ||
@@ -495,7 +495,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) | |||
495 | 495 | ||
496 | #define EC_LAST_PROMFILE_ADDR 0x2f | 496 | #define EC_LAST_PROMFILE_ADDR 0x2f |
497 | 497 | ||
498 | #define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The | 498 | #define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The |
499 | * can be up to 30 characters in length | 499 | * can be up to 30 characters in length |
500 | * and is stored as a NULL-terminated | 500 | * and is stored as a NULL-terminated |
501 | * ASCII string. Any unused bytes must be | 501 | * ASCII string. Any unused bytes must be |
@@ -503,8 +503,8 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) | |||
503 | #define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */ | 503 | #define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */ |
504 | 504 | ||
505 | 505 | ||
506 | /* Most of this stuff is pretty self-evident. According to the hardware | 506 | /* Most of this stuff is pretty self-evident. According to the hardware |
507 | * dudes, we need to leave the ADCCAL bit low in order to avoid a DC | 507 | * dudes, we need to leave the ADCCAL bit low in order to avoid a DC |
508 | * offset problem. Weird. | 508 | * offset problem. Weird. |
509 | */ | 509 | */ |
510 | #define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \ | 510 | #define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \ |
@@ -523,7 +523,7 @@ int snd_emu10k1_done(struct snd_emu10k1 * emu) | |||
523 | * register. | 523 | * register. |
524 | */ | 524 | */ |
525 | 525 | ||
526 | static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value) | 526 | static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value) |
527 | { | 527 | { |
528 | unsigned short count; | 528 | unsigned short count; |
529 | unsigned int data; | 529 | unsigned int data; |
@@ -561,7 +561,7 @@ static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value | |||
561 | * channel. | 561 | * channel. |
562 | */ | 562 | */ |
563 | 563 | ||
564 | static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, | 564 | static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu, |
565 | unsigned short gain) | 565 | unsigned short gain) |
566 | { | 566 | { |
567 | unsigned int bit; | 567 | unsigned int bit; |
@@ -574,7 +574,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, | |||
574 | 574 | ||
575 | for (bit = (1 << 15); bit; bit >>= 1) { | 575 | for (bit = (1 << 15); bit; bit >>= 1) { |
576 | unsigned int value; | 576 | unsigned int value; |
577 | 577 | ||
578 | value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA); | 578 | value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA); |
579 | 579 | ||
580 | if (gain & bit) | 580 | if (gain & bit) |
@@ -589,7 +589,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu, | |||
589 | snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); | 589 | snd_emu10k1_ecard_write(emu, emu->ecard_ctrl); |
590 | } | 590 | } |
591 | 591 | ||
592 | static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu) | 592 | static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu) |
593 | { | 593 | { |
594 | unsigned int hc_value; | 594 | unsigned int hc_value; |
595 | 595 | ||
@@ -598,7 +598,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu) | |||
598 | EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) | | 598 | EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) | |
599 | EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL); | 599 | EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL); |
600 | 600 | ||
601 | /* Step 0: Set the codec type in the hardware control register | 601 | /* Step 0: Set the codec type in the hardware control register |
602 | * and enable audio output */ | 602 | * and enable audio output */ |
603 | hc_value = inl(emu->port + HCFG); | 603 | hc_value = inl(emu->port + HCFG); |
604 | outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG); | 604 | 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) | |||
629 | return 0; | 629 | return 0; |
630 | } | 630 | } |
631 | 631 | ||
632 | static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) | 632 | static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu) |
633 | { | 633 | { |
634 | unsigned long special_port; | 634 | unsigned long special_port; |
635 | unsigned int value; | 635 | unsigned int value; |
@@ -656,7 +656,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu) | |||
656 | return 0; | 656 | return 0; |
657 | } | 657 | } |
658 | 658 | ||
659 | static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename) | 659 | static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename) |
660 | { | 660 | { |
661 | int err; | 661 | int err; |
662 | int n, i; | 662 | int n, i; |
@@ -666,11 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
666 | unsigned long flags; | 666 | unsigned long flags; |
667 | const struct firmware *fw_entry; | 667 | const struct firmware *fw_entry; |
668 | 668 | ||
669 | if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) { | 669 | err = request_firmware(&fw_entry, filename, &emu->pci->dev); |
670 | snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err); | 670 | if (err != 0) { |
671 | snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err); | ||
671 | return err; | 672 | return err; |
672 | } | 673 | } |
673 | snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); | 674 | snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size); |
674 | 675 | ||
675 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ | 676 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ |
676 | /* GPIO7 -> FPGA PGMN | 677 | /* GPIO7 -> FPGA PGMN |
@@ -685,13 +686,13 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
685 | outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ | 686 | outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */ |
686 | write_post = inl(emu->port + A_IOCFG); | 687 | write_post = inl(emu->port + A_IOCFG); |
687 | udelay(100); /* Allow FPGA memory to clean */ | 688 | udelay(100); /* Allow FPGA memory to clean */ |
688 | for(n = 0; n < fw_entry->size; n++) { | 689 | for (n = 0; n < fw_entry->size; n++) { |
689 | value=fw_entry->data[n]; | 690 | value = fw_entry->data[n]; |
690 | for(i = 0; i < 8; i++) { | 691 | for (i = 0; i < 8; i++) { |
691 | reg = 0x80; | 692 | reg = 0x80; |
692 | if (value & 0x1) | 693 | if (value & 0x1) |
693 | reg = reg | 0x20; | 694 | reg = reg | 0x20; |
694 | value = value >> 1; | 695 | value = value >> 1; |
695 | outl(reg, emu->port + A_IOCFG); | 696 | outl(reg, emu->port + A_IOCFG); |
696 | write_post = inl(emu->port + A_IOCFG); | 697 | write_post = inl(emu->port + A_IOCFG); |
697 | outl(reg | 0x40, emu->port + A_IOCFG); | 698 | outl(reg | 0x40, emu->port + A_IOCFG); |
@@ -703,14 +704,14 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
703 | write_post = inl(emu->port + A_IOCFG); | 704 | write_post = inl(emu->port + A_IOCFG); |
704 | spin_unlock_irqrestore(&emu->emu_lock, flags); | 705 | spin_unlock_irqrestore(&emu->emu_lock, flags); |
705 | 706 | ||
706 | release_firmware(fw_entry); | 707 | release_firmware(fw_entry); |
707 | return 0; | 708 | return 0; |
708 | } | 709 | } |
709 | 710 | ||
710 | static int emu1010_firmware_thread(void *data) | 711 | static int emu1010_firmware_thread(void *data) |
711 | { | 712 | { |
712 | struct snd_emu10k1 * emu = data; | 713 | struct snd_emu10k1 *emu = data; |
713 | int tmp,tmp2; | 714 | int tmp, tmp2; |
714 | int reg; | 715 | int reg; |
715 | int err; | 716 | int err; |
716 | 717 | ||
@@ -719,50 +720,50 @@ static int emu1010_firmware_thread(void *data) | |||
719 | msleep_interruptible(1000); | 720 | msleep_interruptible(1000); |
720 | if (kthread_should_stop()) | 721 | if (kthread_should_stop()) |
721 | break; | 722 | break; |
722 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */ | 723 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */ |
723 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); /* OPTIONS: Which cards are attached to the EMU */ | 724 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); /* OPTIONS: Which cards are attached to the EMU */ |
724 | if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { | 725 | if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) { |
725 | /* Audio Dock attached */ | 726 | /* Audio Dock attached */ |
726 | /* Return to Audio Dock programming mode */ | 727 | /* Return to Audio Dock programming mode */ |
727 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | 728 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); |
728 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | 729 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK); |
729 | if (emu->card_capabilities->emu_model == | 730 | if (emu->card_capabilities->emu_model == |
730 | EMU_MODEL_EMU1010) { | 731 | EMU_MODEL_EMU1010) { |
731 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | 732 | err = snd_emu1010_load_firmware(emu, DOCK_FILENAME); |
733 | if (err != 0) | ||
732 | continue; | 734 | continue; |
733 | } | ||
734 | } else if (emu->card_capabilities->emu_model == | 735 | } else if (emu->card_capabilities->emu_model == |
735 | EMU_MODEL_EMU1010B) { | 736 | EMU_MODEL_EMU1010B) { |
736 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | 737 | err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); |
738 | if (err != 0) | ||
737 | continue; | 739 | continue; |
738 | } | ||
739 | } else if (emu->card_capabilities->emu_model == | 740 | } else if (emu->card_capabilities->emu_model == |
740 | EMU_MODEL_EMU1616) { | 741 | EMU_MODEL_EMU1616) { |
741 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | 742 | err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME); |
743 | if (err != 0) | ||
742 | continue; | 744 | continue; |
743 | } | ||
744 | } | 745 | } |
745 | 746 | ||
746 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | 747 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0); |
747 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | 748 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ®); |
748 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | 749 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg); |
749 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | 750 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ |
750 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 751 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); |
751 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | 752 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg); |
752 | if ((reg & 0x1f) != 0x15) { | 753 | if ((reg & 0x1f) != 0x15) { |
753 | /* FPGA failed to be programmed */ | 754 | /* FPGA failed to be programmed */ |
754 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | 755 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg); |
755 | continue; | 756 | continue; |
756 | } | 757 | } |
757 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); | 758 | snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n"); |
758 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp ); | 759 | snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp); |
759 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 ); | 760 | snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2); |
760 | snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2); | 761 | snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2); |
761 | /* Sync clocking between 1010 and Dock */ | 762 | /* Sync clocking between 1010 and Dock */ |
762 | /* Allow DLL to settle */ | 763 | /* Allow DLL to settle */ |
763 | msleep(10); | 764 | msleep(10); |
764 | /* Unmute all. Default is muted after a firmware load */ | 765 | /* Unmute all. Default is muted after a firmware load */ |
765 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE ); | 766 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE); |
766 | } | 767 | } |
767 | } | 768 | } |
768 | snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); | 769 | snd_printk(KERN_INFO "emu1010: firmware thread stopping\n"); |
@@ -800,10 +801,10 @@ static int emu1010_firmware_thread(void *data) | |||
800 | * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops | 801 | * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops |
801 | * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops | 802 | * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops |
802 | */ | 803 | */ |
803 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | 804 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu) |
804 | { | 805 | { |
805 | unsigned int i; | 806 | unsigned int i; |
806 | int tmp,tmp2; | 807 | int tmp, tmp2; |
807 | int reg; | 808 | int reg; |
808 | int err; | 809 | int err; |
809 | const char *filename = NULL; | 810 | const char *filename = NULL; |
@@ -818,7 +819,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
818 | * Lock Tank Memory Cache, | 819 | * Lock Tank Memory Cache, |
819 | * Mute all codecs. | 820 | * Mute all codecs. |
820 | */ | 821 | */ |
821 | outl(0x0005a004, emu->port + HCFG); | 822 | outl(0x0005a004, emu->port + HCFG); |
822 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, | 823 | /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave, |
823 | * Mute all codecs. | 824 | * Mute all codecs. |
824 | */ | 825 | */ |
@@ -829,25 +830,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
829 | outl(0x0005a000, emu->port + HCFG); | 830 | outl(0x0005a000, emu->port + HCFG); |
830 | 831 | ||
831 | /* Disable 48Volt power to Audio Dock */ | 832 | /* Disable 48Volt power to Audio Dock */ |
832 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); | 833 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); |
833 | 834 | ||
834 | /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ | 835 | /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ |
835 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 836 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); |
836 | snd_printdd("reg1=0x%x\n",reg); | 837 | snd_printdd("reg1 = 0x%x\n", reg); |
837 | if ((reg & 0x3f) == 0x15) { | 838 | if ((reg & 0x3f) == 0x15) { |
838 | /* FPGA netlist already present so clear it */ | 839 | /* FPGA netlist already present so clear it */ |
839 | /* Return to programming mode */ | 840 | /* Return to programming mode */ |
840 | 841 | ||
841 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02 ); | 842 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02); |
842 | } | 843 | } |
843 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 844 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); |
844 | snd_printdd("reg2=0x%x\n",reg); | 845 | snd_printdd("reg2 = 0x%x\n", reg); |
845 | if ((reg & 0x3f) == 0x15) { | 846 | if ((reg & 0x3f) == 0x15) { |
846 | /* FPGA failed to return to programming mode */ | 847 | /* FPGA failed to return to programming mode */ |
847 | snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); | 848 | snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); |
848 | return -ENODEV; | 849 | return -ENODEV; |
849 | } | 850 | } |
850 | snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); | 851 | snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg); |
851 | switch (emu->card_capabilities->emu_model) { | 852 | switch (emu->card_capabilities->emu_model) { |
852 | case EMU_MODEL_EMU1010: | 853 | case EMU_MODEL_EMU1010: |
853 | filename = HANA_FILENAME; | 854 | filename = HANA_FILENAME; |
@@ -876,25 +877,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
876 | } | 877 | } |
877 | 878 | ||
878 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | 879 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ |
879 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 880 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ®); |
880 | if ((reg & 0x3f) != 0x15) { | 881 | if ((reg & 0x3f) != 0x15) { |
881 | /* FPGA failed to be programmed */ | 882 | /* FPGA failed to be programmed */ |
882 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg); | 883 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg); |
883 | return -ENODEV; | 884 | return -ENODEV; |
884 | } | 885 | } |
885 | 886 | ||
886 | snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); | 887 | snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n"); |
887 | snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp ); | 888 | snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp); |
888 | snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 ); | 889 | snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2); |
889 | snd_printk("Hana ver:%d.%d\n",tmp ,tmp2); | 890 | snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2); |
890 | /* Enable 48Volt power to Audio Dock */ | 891 | /* Enable 48Volt power to Audio Dock */ |
891 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON ); | 892 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON); |
892 | 893 | ||
893 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); | 894 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); |
894 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); | 895 | snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); |
895 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); | 896 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); |
896 | snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg); | 897 | snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg); |
897 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp ); | 898 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp); |
898 | /* Optical -> ADAT I/O */ | 899 | /* Optical -> ADAT I/O */ |
899 | /* 0 : SPDIF | 900 | /* 0 : SPDIF |
900 | * 1 : ADAT | 901 | * 1 : ADAT |
@@ -904,41 +905,42 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
904 | tmp = 0; | 905 | tmp = 0; |
905 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | | 906 | tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) | |
906 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); | 907 | (emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0); |
907 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp ); | 908 | snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp); |
908 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp ); | 909 | snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp); |
909 | /* Set no attenuation on Audio Dock pads. */ | 910 | /* Set no attenuation on Audio Dock pads. */ |
910 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 ); | 911 | snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00); |
911 | emu->emu1010.adc_pads = 0x00; | 912 | emu->emu1010.adc_pads = 0x00; |
912 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp ); | 913 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); |
913 | /* Unmute Audio dock DACs, Headphone source DAC-4. */ | 914 | /* Unmute Audio dock DACs, Headphone source DAC-4. */ |
914 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 ); | 915 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); |
915 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 ); | 916 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); |
916 | snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp ); | 917 | snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp); |
917 | /* DAC PADs. */ | 918 | /* DAC PADs. */ |
918 | snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f ); | 919 | snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f); |
919 | emu->emu1010.dac_pads = 0x0f; | 920 | emu->emu1010.dac_pads = 0x0f; |
920 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp ); | 921 | snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp); |
921 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 ); | 922 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30); |
922 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); | 923 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); |
923 | /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ | 924 | /* SPDIF Format. Set Consumer mode, 24bit, copy enable */ |
924 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); | 925 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); |
925 | /* MIDI routing */ | 926 | /* MIDI routing */ |
926 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); | 927 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); |
927 | /* Unknown. */ | 928 | /* Unknown. */ |
928 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); | 929 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); |
929 | /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */ | 930 | /* IRQ Enable: Alll on */ |
931 | /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */ | ||
930 | /* IRQ Enable: All off */ | 932 | /* IRQ Enable: All off */ |
931 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 ); | 933 | snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00); |
932 | 934 | ||
933 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ® ); | 935 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, ®); |
934 | snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg); | 936 | snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg); |
935 | /* Default WCLK set to 48kHz. */ | 937 | /* Default WCLK set to 48kHz. */ |
936 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 ); | 938 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00); |
937 | /* Word Clock source, Internal 48kHz x1 */ | 939 | /* Word Clock source, Internal 48kHz x1 */ |
938 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K ); | 940 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); |
939 | //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X ); | 941 | /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ |
940 | /* Audio Dock LEDs. */ | 942 | /* Audio Dock LEDs. */ |
941 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 ); | 943 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); |
942 | 944 | ||
943 | #if 0 | 945 | #if 0 |
944 | /* For 96kHz */ | 946 | /* For 96kHz */ |
@@ -992,7 +994,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
992 | * Defaults only, users will set their own values anyways, let's | 994 | * Defaults only, users will set their own values anyways, let's |
993 | * just copy/paste. | 995 | * just copy/paste. |
994 | */ | 996 | */ |
995 | 997 | ||
996 | snd_emu1010_fpga_link_dst_src_write(emu, | 998 | snd_emu1010_fpga_link_dst_src_write(emu, |
997 | EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); | 999 | EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); |
998 | snd_emu1010_fpga_link_dst_src_write(emu, | 1000 | snd_emu1010_fpga_link_dst_src_write(emu, |
@@ -1037,19 +1039,19 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1037 | snd_emu1010_fpga_link_dst_src_write(emu, | 1039 | snd_emu1010_fpga_link_dst_src_write(emu, |
1038 | EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2); | 1040 | EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2); |
1039 | #endif | 1041 | #endif |
1040 | for (i = 0;i < 0x20; i++ ) { | 1042 | for (i = 0; i < 0x20; i++) { |
1041 | /* AudioDock Elink <- Silence */ | 1043 | /* AudioDock Elink <- Silence */ |
1042 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE); | 1044 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE); |
1043 | } | 1045 | } |
1044 | for (i = 0;i < 4; i++) { | 1046 | for (i = 0; i < 4; i++) { |
1045 | /* Hana SPDIF Out <- Silence */ | 1047 | /* Hana SPDIF Out <- Silence */ |
1046 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE); | 1048 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE); |
1047 | } | 1049 | } |
1048 | for (i = 0;i < 7; i++) { | 1050 | for (i = 0; i < 7; i++) { |
1049 | /* Hamoa DAC <- Silence */ | 1051 | /* Hamoa DAC <- Silence */ |
1050 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE); | 1052 | snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE); |
1051 | } | 1053 | } |
1052 | for (i = 0;i < 7; i++) { | 1054 | for (i = 0; i < 7; i++) { |
1053 | /* Hana ADAT Out <- Silence */ | 1055 | /* Hana ADAT Out <- Silence */ |
1054 | snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE); | 1056 | snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE); |
1055 | } | 1057 | } |
@@ -1065,30 +1067,30 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1065 | EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1); | 1067 | EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1); |
1066 | snd_emu1010_fpga_link_dst_src_write(emu, | 1068 | snd_emu1010_fpga_link_dst_src_write(emu, |
1067 | EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); | 1069 | EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1); |
1068 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all | 1070 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */ |
1071 | |||
1072 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); | ||
1069 | 1073 | ||
1070 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp ); | ||
1071 | |||
1072 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, | 1074 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, |
1073 | * Lock Sound Memory Cache, Lock Tank Memory Cache, | 1075 | * Lock Sound Memory Cache, Lock Tank Memory Cache, |
1074 | * Mute all codecs. | 1076 | * Mute all codecs. |
1075 | */ | 1077 | */ |
1076 | outl(0x0000a000, emu->port + HCFG); | 1078 | outl(0x0000a000, emu->port + HCFG); |
1077 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, | 1079 | /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave, |
1078 | * Lock Sound Memory Cache, Lock Tank Memory Cache, | 1080 | * Lock Sound Memory Cache, Lock Tank Memory Cache, |
1079 | * Un-Mute all codecs. | 1081 | * Un-Mute all codecs. |
1080 | */ | 1082 | */ |
1081 | outl(0x0000a001, emu->port + HCFG); | 1083 | outl(0x0000a001, emu->port + HCFG); |
1082 | 1084 | ||
1083 | /* Initial boot complete. Now patches */ | 1085 | /* Initial boot complete. Now patches */ |
1084 | 1086 | ||
1085 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp ); | 1087 | snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp); |
1086 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */ | 1088 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ |
1087 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */ | 1089 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ |
1088 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */ | 1090 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */ |
1089 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */ | 1091 | snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */ |
1090 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp ); | 1092 | snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp); |
1091 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ | 1093 | snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */ |
1092 | 1094 | ||
1093 | /* Start Micro/Audio Dock firmware loader thread */ | 1095 | /* Start Micro/Audio Dock firmware loader thread */ |
1094 | if (!emu->emu1010.firmware_thread) { | 1096 | if (!emu->emu1010.firmware_thread) { |
@@ -1218,20 +1220,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
1218 | emu->emu1010.output_source[23] = 28; | 1220 | emu->emu1010.output_source[23] = 28; |
1219 | } | 1221 | } |
1220 | /* TEMP: Select SPDIF in/out */ | 1222 | /* TEMP: Select SPDIF in/out */ |
1221 | //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */ | 1223 | /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */ |
1222 | 1224 | ||
1223 | /* TEMP: Select 48kHz SPDIF out */ | 1225 | /* TEMP: Select 48kHz SPDIF out */ |
1224 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ | 1226 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */ |
1225 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ | 1227 | snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */ |
1226 | /* Word Clock source, Internal 48kHz x1 */ | 1228 | /* Word Clock source, Internal 48kHz x1 */ |
1227 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K ); | 1229 | snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K); |
1228 | //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X ); | 1230 | /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */ |
1229 | emu->emu1010.internal_clock = 1; /* 48000 */ | 1231 | emu->emu1010.internal_clock = 1; /* 48000 */ |
1230 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */ | 1232 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */ |
1231 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ | 1233 | snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */ |
1232 | //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */ | 1234 | /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */ |
1233 | //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */ | 1235 | /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */ |
1234 | //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */ | 1236 | /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */ |
1235 | 1237 | ||
1236 | return 0; | 1238 | return 0; |
1237 | } | 1239 | } |
@@ -1247,13 +1249,13 @@ static void free_pm_buffer(struct snd_emu10k1 *emu); | |||
1247 | static int snd_emu10k1_free(struct snd_emu10k1 *emu) | 1249 | static int snd_emu10k1_free(struct snd_emu10k1 *emu) |
1248 | { | 1250 | { |
1249 | if (emu->port) { /* avoid access to already used hardware */ | 1251 | if (emu->port) { /* avoid access to already used hardware */ |
1250 | snd_emu10k1_fx8010_tram_setup(emu, 0); | 1252 | snd_emu10k1_fx8010_tram_setup(emu, 0); |
1251 | snd_emu10k1_done(emu); | 1253 | snd_emu10k1_done(emu); |
1252 | snd_emu10k1_free_efx(emu); | 1254 | snd_emu10k1_free_efx(emu); |
1253 | } | 1255 | } |
1254 | if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { | 1256 | if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) { |
1255 | /* Disable 48Volt power to Audio Dock */ | 1257 | /* Disable 48Volt power to Audio Dock */ |
1256 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 ); | 1258 | snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0); |
1257 | } | 1259 | } |
1258 | if (emu->emu1010.firmware_thread) | 1260 | if (emu->emu1010.firmware_thread) |
1259 | kthread_stop(emu->emu1010.firmware_thread); | 1261 | kthread_stop(emu->emu1010.firmware_thread); |
@@ -1278,7 +1280,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu) | |||
1278 | #endif | 1280 | #endif |
1279 | if (emu->port) | 1281 | if (emu->port) |
1280 | pci_release_regions(emu->pci); | 1282 | pci_release_regions(emu->pci); |
1281 | if (emu->card_capabilities->ca0151_chip) /* P16V */ | 1283 | if (emu->card_capabilities->ca0151_chip) /* P16V */ |
1282 | snd_p16v_free(emu); | 1284 | snd_p16v_free(emu); |
1283 | pci_disable_device(emu->pci); | 1285 | pci_disable_device(emu->pci); |
1284 | kfree(emu); | 1286 | kfree(emu); |
@@ -1292,21 +1294,6 @@ static int snd_emu10k1_dev_free(struct snd_device *device) | |||
1292 | } | 1294 | } |
1293 | 1295 | ||
1294 | static struct snd_emu_chip_details emu_chip_details[] = { | 1296 | static struct snd_emu_chip_details emu_chip_details[] = { |
1295 | /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/ | ||
1296 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
1297 | /* DSP: CA0108-IAT | ||
1298 | * DAC: CS4382-KQ | ||
1299 | * ADC: Philips 1361T | ||
1300 | * AC97: STAC9750 | ||
1301 | * CA0151: None | ||
1302 | */ | ||
1303 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | ||
1304 | .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]", | ||
1305 | .id = "Audigy2", | ||
1306 | .emu10k2_chip = 1, | ||
1307 | .ca0108_chip = 1, | ||
1308 | .spk71 = 1, | ||
1309 | .ac97_chip = 1} , | ||
1310 | /* Audigy4 (Not PRO) SB0610 */ | 1297 | /* Audigy4 (Not PRO) SB0610 */ |
1311 | /* Tested by James@superbug.co.uk 4th April 2006 */ | 1298 | /* Tested by James@superbug.co.uk 4th April 2006 */ |
1312 | /* A_IOCFG bits | 1299 | /* A_IOCFG bits |
@@ -1346,20 +1333,37 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1346 | * CA0151: None | 1333 | * CA0151: None |
1347 | */ | 1334 | */ |
1348 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, | 1335 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102, |
1349 | .driver = "Audigy2", .name = "Audigy 4 [SB0610]", | 1336 | .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]", |
1350 | .id = "Audigy2", | 1337 | .id = "Audigy2", |
1351 | .emu10k2_chip = 1, | 1338 | .emu10k2_chip = 1, |
1352 | .ca0108_chip = 1, | 1339 | .ca0108_chip = 1, |
1353 | .spk71 = 1, | 1340 | .spk71 = 1, |
1354 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | 1341 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ |
1355 | .ac97_chip = 1} , | 1342 | .ac97_chip = 1} , |
1343 | /* Audigy 2 Value AC3 out does not work yet. | ||
1344 | * Need to find out how to turn off interpolators. | ||
1345 | */ | ||
1346 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | ||
1347 | /* DSP: CA0108-IAT | ||
1348 | * DAC: CS4382-KQ | ||
1349 | * ADC: Philips 1361T | ||
1350 | * AC97: STAC9750 | ||
1351 | * CA0151: None | ||
1352 | */ | ||
1353 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102, | ||
1354 | .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]", | ||
1355 | .id = "Audigy2", | ||
1356 | .emu10k2_chip = 1, | ||
1357 | .ca0108_chip = 1, | ||
1358 | .spk71 = 1, | ||
1359 | .ac97_chip = 1} , | ||
1356 | /* Audigy 2 ZS Notebook Cardbus card.*/ | 1360 | /* Audigy 2 ZS Notebook Cardbus card.*/ |
1357 | /* Tested by James@superbug.co.uk 6th November 2006 */ | 1361 | /* Tested by James@superbug.co.uk 6th November 2006 */ |
1358 | /* Audio output 7.1/Headphones working. | 1362 | /* Audio output 7.1/Headphones working. |
1359 | * Digital output working. (AC3 not checked, only PCM) | 1363 | * Digital output working. (AC3 not checked, only PCM) |
1360 | * Audio Mic/Line inputs working. | 1364 | * Audio Mic/Line inputs working. |
1361 | * Digital input not tested. | 1365 | * Digital input not tested. |
1362 | */ | 1366 | */ |
1363 | /* DSP: Tina2 | 1367 | /* DSP: Tina2 |
1364 | * DAC: Wolfson WM8768/WM8568 | 1368 | * DAC: Wolfson WM8768/WM8568 |
1365 | * ADC: Wolfson WM8775 | 1369 | * ADC: Wolfson WM8775 |
@@ -1386,7 +1390,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1386 | * | 1390 | * |
1387 | */ | 1391 | */ |
1388 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, | 1392 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, |
1389 | .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", | 1393 | .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]", |
1390 | .id = "Audigy2", | 1394 | .id = "Audigy2", |
1391 | .emu10k2_chip = 1, | 1395 | .emu10k2_chip = 1, |
1392 | .ca0108_chip = 1, | 1396 | .ca0108_chip = 1, |
@@ -1396,7 +1400,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1396 | .spk71 = 1} , | 1400 | .spk71 = 1} , |
1397 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ | 1401 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ |
1398 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, | 1402 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102, |
1399 | .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", | 1403 | .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]", |
1400 | .id = "EMU1010", | 1404 | .id = "EMU1010", |
1401 | .emu10k2_chip = 1, | 1405 | .emu10k2_chip = 1, |
1402 | .ca0108_chip = 1, | 1406 | .ca0108_chip = 1, |
@@ -1404,47 +1408,49 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1404 | .spk71 = 1 , | 1408 | .spk71 = 1 , |
1405 | .emu_model = EMU_MODEL_EMU1616}, | 1409 | .emu_model = EMU_MODEL_EMU1616}, |
1406 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ | 1410 | /* Tested by James@superbug.co.uk 4th Nov 2007. */ |
1411 | /* This is MAEM8960, 0202 is MAEM 8980 */ | ||
1407 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, | 1412 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, |
1408 | .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]", | 1413 | .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]", |
1409 | .id = "EMU1010", | 1414 | .id = "EMU1010", |
1410 | .emu10k2_chip = 1, | 1415 | .emu10k2_chip = 1, |
1411 | .ca0108_chip = 1, | 1416 | .ca0108_chip = 1, |
1412 | .spk71 = 1, | 1417 | .spk71 = 1, |
1413 | .emu_model = EMU_MODEL_EMU1010B}, | 1418 | .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */ |
1414 | /* Tested by James@superbug.co.uk 8th July 2005. */ | 1419 | /* Tested by James@superbug.co.uk 8th July 2005. */ |
1420 | /* This is MAEM8810, 0202 is MAEM8820 */ | ||
1415 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, | 1421 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, |
1416 | .driver = "Audigy2", .name = "E-mu 1010 [4001]", | 1422 | .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]", |
1417 | .id = "EMU1010", | 1423 | .id = "EMU1010", |
1418 | .emu10k2_chip = 1, | 1424 | .emu10k2_chip = 1, |
1419 | .ca0102_chip = 1, | 1425 | .ca0102_chip = 1, |
1420 | .spk71 = 1, | 1426 | .spk71 = 1, |
1421 | .emu_model = EMU_MODEL_EMU1010}, /* Emu 1010 */ | 1427 | .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */ |
1422 | /* EMU0404b */ | 1428 | /* EMU0404b */ |
1423 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, | 1429 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102, |
1424 | .driver = "Audigy2", .name = "E-mu 0404b [4002]", | 1430 | .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]", |
1425 | .id = "EMU0404", | 1431 | .id = "EMU0404", |
1426 | .emu10k2_chip = 1, | 1432 | .emu10k2_chip = 1, |
1427 | .ca0108_chip = 1, | 1433 | .ca0108_chip = 1, |
1428 | .spk71 = 1, | 1434 | .spk71 = 1, |
1429 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ | 1435 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */ |
1430 | /* Tested by James@superbug.co.uk 20-3-2007. */ | 1436 | /* Tested by James@superbug.co.uk 20-3-2007. */ |
1431 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, | 1437 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102, |
1432 | .driver = "Audigy2", .name = "E-mu 0404 [4002]", | 1438 | .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]", |
1433 | .id = "EMU0404", | 1439 | .id = "EMU0404", |
1434 | .emu10k2_chip = 1, | 1440 | .emu10k2_chip = 1, |
1435 | .ca0102_chip = 1, | 1441 | .ca0102_chip = 1, |
1436 | .spk71 = 1, | 1442 | .spk71 = 1, |
1437 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ | 1443 | .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */ |
1438 | /* Audigy4 (Not PRO) SB0610 */ | 1444 | /* Note that all E-mu cards require kernel 2.6 or newer. */ |
1439 | {.vendor = 0x1102, .device = 0x0008, | 1445 | {.vendor = 0x1102, .device = 0x0008, |
1440 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", | 1446 | .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]", |
1441 | .id = "Audigy2", | 1447 | .id = "Audigy2", |
1442 | .emu10k2_chip = 1, | 1448 | .emu10k2_chip = 1, |
1443 | .ca0108_chip = 1, | 1449 | .ca0108_chip = 1, |
1444 | .ac97_chip = 1} , | 1450 | .ac97_chip = 1} , |
1445 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 1451 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
1446 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, | 1452 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, |
1447 | .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", | 1453 | .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]", |
1448 | .id = "Audigy2", | 1454 | .id = "Audigy2", |
1449 | .emu10k2_chip = 1, | 1455 | .emu10k2_chip = 1, |
1450 | .ca0102_chip = 1, | 1456 | .ca0102_chip = 1, |
@@ -1457,7 +1463,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1457 | * Just like 0x20021102 | 1463 | * Just like 0x20021102 |
1458 | */ | 1464 | */ |
1459 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102, | 1465 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102, |
1460 | .driver = "Audigy2", .name = "Audigy 2 [SB0350b]", | 1466 | .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]", |
1461 | .id = "Audigy2", | 1467 | .id = "Audigy2", |
1462 | .emu10k2_chip = 1, | 1468 | .emu10k2_chip = 1, |
1463 | .ca0102_chip = 1, | 1469 | .ca0102_chip = 1, |
@@ -1467,7 +1473,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1467 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | 1473 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ |
1468 | .ac97_chip = 1} , | 1474 | .ac97_chip = 1} , |
1469 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, | 1475 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102, |
1470 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]", | 1476 | .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]", |
1471 | .id = "Audigy2", | 1477 | .id = "Audigy2", |
1472 | .emu10k2_chip = 1, | 1478 | .emu10k2_chip = 1, |
1473 | .ca0102_chip = 1, | 1479 | .ca0102_chip = 1, |
@@ -1477,7 +1483,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1477 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ | 1483 | .invert_shared_spdif = 1, /* digital/analog switch swapped */ |
1478 | .ac97_chip = 1} , | 1484 | .ac97_chip = 1} , |
1479 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, | 1485 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102, |
1480 | .driver = "Audigy2", .name = "Audigy 2 ZS [2001]", | 1486 | .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]", |
1481 | .id = "Audigy2", | 1487 | .id = "Audigy2", |
1482 | .emu10k2_chip = 1, | 1488 | .emu10k2_chip = 1, |
1483 | .ca0102_chip = 1, | 1489 | .ca0102_chip = 1, |
@@ -1495,7 +1501,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1495 | * CA0151: Yes | 1501 | * CA0151: Yes |
1496 | */ | 1502 | */ |
1497 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, | 1503 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102, |
1498 | .driver = "Audigy2", .name = "Audigy 2 [SB0240]", | 1504 | .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]", |
1499 | .id = "Audigy2", | 1505 | .id = "Audigy2", |
1500 | .emu10k2_chip = 1, | 1506 | .emu10k2_chip = 1, |
1501 | .ca0102_chip = 1, | 1507 | .ca0102_chip = 1, |
@@ -1505,7 +1511,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1505 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ | 1511 | .adc_1361t = 1, /* 24 bit capture instead of 16bit */ |
1506 | .ac97_chip = 1} , | 1512 | .ac97_chip = 1} , |
1507 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, | 1513 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102, |
1508 | .driver = "Audigy2", .name = "Audigy 2 EX [1005]", | 1514 | .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]", |
1509 | .id = "Audigy2", | 1515 | .id = "Audigy2", |
1510 | .emu10k2_chip = 1, | 1516 | .emu10k2_chip = 1, |
1511 | .ca0102_chip = 1, | 1517 | .ca0102_chip = 1, |
@@ -1515,7 +1521,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1515 | /* Dell OEM/Creative Labs Audigy 2 ZS */ | 1521 | /* Dell OEM/Creative Labs Audigy 2 ZS */ |
1516 | /* See ALSA bug#1365 */ | 1522 | /* See ALSA bug#1365 */ |
1517 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, | 1523 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102, |
1518 | .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]", | 1524 | .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]", |
1519 | .id = "Audigy2", | 1525 | .id = "Audigy2", |
1520 | .emu10k2_chip = 1, | 1526 | .emu10k2_chip = 1, |
1521 | .ca0102_chip = 1, | 1527 | .ca0102_chip = 1, |
@@ -1524,7 +1530,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1524 | .spdif_bug = 1, | 1530 | .spdif_bug = 1, |
1525 | .ac97_chip = 1} , | 1531 | .ac97_chip = 1} , |
1526 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, | 1532 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102, |
1527 | .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]", | 1533 | .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]", |
1528 | .id = "Audigy2", | 1534 | .id = "Audigy2", |
1529 | .emu10k2_chip = 1, | 1535 | .emu10k2_chip = 1, |
1530 | .ca0102_chip = 1, | 1536 | .ca0102_chip = 1, |
@@ -1535,7 +1541,7 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1535 | .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ | 1541 | .adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */ |
1536 | .ac97_chip = 1} , | 1542 | .ac97_chip = 1} , |
1537 | {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, | 1543 | {.vendor = 0x1102, .device = 0x0004, .revision = 0x04, |
1538 | .driver = "Audigy2", .name = "Audigy 2 [Unknown]", | 1544 | .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]", |
1539 | .id = "Audigy2", | 1545 | .id = "Audigy2", |
1540 | .emu10k2_chip = 1, | 1546 | .emu10k2_chip = 1, |
1541 | .ca0102_chip = 1, | 1547 | .ca0102_chip = 1, |
@@ -1543,78 +1549,79 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1543 | .spdif_bug = 1, | 1549 | .spdif_bug = 1, |
1544 | .ac97_chip = 1} , | 1550 | .ac97_chip = 1} , |
1545 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, | 1551 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102, |
1546 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | 1552 | .driver = "Audigy", .name = "SB Audigy 1 [SB0092]", |
1547 | .id = "Audigy", | 1553 | .id = "Audigy", |
1548 | .emu10k2_chip = 1, | 1554 | .emu10k2_chip = 1, |
1549 | .ca0102_chip = 1, | 1555 | .ca0102_chip = 1, |
1550 | .ac97_chip = 1} , | 1556 | .ac97_chip = 1} , |
1551 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, | 1557 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102, |
1552 | .driver = "Audigy", .name = "Audigy 1 ES [SB0160]", | 1558 | .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]", |
1553 | .id = "Audigy", | 1559 | .id = "Audigy", |
1554 | .emu10k2_chip = 1, | 1560 | .emu10k2_chip = 1, |
1555 | .ca0102_chip = 1, | 1561 | .ca0102_chip = 1, |
1556 | .spdif_bug = 1, | 1562 | .spdif_bug = 1, |
1557 | .ac97_chip = 1} , | 1563 | .ac97_chip = 1} , |
1558 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, | 1564 | {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102, |
1559 | .driver = "Audigy", .name = "Audigy 1 [SB0090]", | 1565 | .driver = "Audigy", .name = "SB Audigy 1 [SB0090]", |
1560 | .id = "Audigy", | 1566 | .id = "Audigy", |
1561 | .emu10k2_chip = 1, | 1567 | .emu10k2_chip = 1, |
1562 | .ca0102_chip = 1, | 1568 | .ca0102_chip = 1, |
1563 | .ac97_chip = 1} , | 1569 | .ac97_chip = 1} , |
1564 | {.vendor = 0x1102, .device = 0x0004, | 1570 | {.vendor = 0x1102, .device = 0x0004, |
1565 | .driver = "Audigy", .name = "Audigy 1 [Unknown]", | 1571 | .driver = "Audigy", .name = "Audigy 1 [Unknown]", |
1566 | .id = "Audigy", | 1572 | .id = "Audigy", |
1567 | .emu10k2_chip = 1, | 1573 | .emu10k2_chip = 1, |
1568 | .ca0102_chip = 1, | 1574 | .ca0102_chip = 1, |
1569 | .ac97_chip = 1} , | 1575 | .ac97_chip = 1} , |
1570 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102, | 1576 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, |
1571 | .driver = "EMU10K1", .name = "SBLive! [SB0105]", | 1577 | .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", |
1578 | .id = "Live", | ||
1579 | .emu10k1_chip = 1, | ||
1580 | .ac97_chip = 1, | ||
1581 | .sblive51 = 1} , | ||
1582 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102, | ||
1583 | .driver = "EMU10K1", .name = "SB Live! [SB0105]", | ||
1572 | .id = "Live", | 1584 | .id = "Live", |
1573 | .emu10k1_chip = 1, | 1585 | .emu10k1_chip = 1, |
1574 | .ac97_chip = 1, | 1586 | .ac97_chip = 1, |
1575 | .sblive51 = 1} , | 1587 | .sblive51 = 1} , |
1576 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102, | 1588 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102, |
1577 | .driver = "EMU10K1", .name = "SBLive! Value [SB0103]", | 1589 | .driver = "EMU10K1", .name = "SB Live! Value [SB0103]", |
1578 | .id = "Live", | 1590 | .id = "Live", |
1579 | .emu10k1_chip = 1, | 1591 | .emu10k1_chip = 1, |
1580 | .ac97_chip = 1, | 1592 | .ac97_chip = 1, |
1581 | .sblive51 = 1} , | 1593 | .sblive51 = 1} , |
1582 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, | 1594 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102, |
1583 | .driver = "EMU10K1", .name = "SBLive! Value [SB0101]", | 1595 | .driver = "EMU10K1", .name = "SB Live! Value [SB0101]", |
1584 | .id = "Live", | 1596 | .id = "Live", |
1585 | .emu10k1_chip = 1, | 1597 | .emu10k1_chip = 1, |
1586 | .ac97_chip = 1, | 1598 | .ac97_chip = 1, |
1587 | .sblive51 = 1} , | 1599 | .sblive51 = 1} , |
1588 | /* Tested by ALSA bug#1680 26th December 2005 */ | 1600 | /* Tested by ALSA bug#1680 26th December 2005 */ |
1589 | /* note: It really has SB0220 written on the card. */ | 1601 | /* note: It really has SB0220 written on the card, */ |
1602 | /* but it's SB0228 according to kx.inf */ | ||
1590 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102, | 1603 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102, |
1591 | .driver = "EMU10K1", .name = "SB Live 5.1 Dell OEM [SB0220]", | 1604 | .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]", |
1592 | .id = "Live", | 1605 | .id = "Live", |
1593 | .emu10k1_chip = 1, | 1606 | .emu10k1_chip = 1, |
1594 | .ac97_chip = 1, | 1607 | .ac97_chip = 1, |
1595 | .sblive51 = 1} , | 1608 | .sblive51 = 1} , |
1596 | /* Tested by Thomas Zehetbauer 27th Aug 2005 */ | 1609 | /* Tested by Thomas Zehetbauer 27th Aug 2005 */ |
1597 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102, | 1610 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102, |
1598 | .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]", | 1611 | .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]", |
1599 | .id = "Live", | ||
1600 | .emu10k1_chip = 1, | ||
1601 | .ac97_chip = 1, | ||
1602 | .sblive51 = 1} , | ||
1603 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102, | ||
1604 | .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]", | ||
1605 | .id = "Live", | 1612 | .id = "Live", |
1606 | .emu10k1_chip = 1, | 1613 | .emu10k1_chip = 1, |
1607 | .ac97_chip = 1, | 1614 | .ac97_chip = 1, |
1608 | .sblive51 = 1} , | 1615 | .sblive51 = 1} , |
1609 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, | 1616 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102, |
1610 | .driver = "EMU10K1", .name = "SB Live 5.1", | 1617 | .driver = "EMU10K1", .name = "SB Live! 5.1", |
1611 | .id = "Live", | 1618 | .id = "Live", |
1612 | .emu10k1_chip = 1, | 1619 | .emu10k1_chip = 1, |
1613 | .ac97_chip = 1, | 1620 | .ac97_chip = 1, |
1614 | .sblive51 = 1} , | 1621 | .sblive51 = 1} , |
1615 | /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ | 1622 | /* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */ |
1616 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, | 1623 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102, |
1617 | .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]", | 1624 | .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]", |
1618 | .id = "Live", | 1625 | .id = "Live", |
1619 | .emu10k1_chip = 1, | 1626 | .emu10k1_chip = 1, |
1620 | .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum | 1627 | .ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum |
@@ -1622,78 +1629,78 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1622 | */ | 1629 | */ |
1623 | .sblive51 = 1} , | 1630 | .sblive51 = 1} , |
1624 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, | 1631 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102, |
1625 | .driver = "EMU10K1", .name = "SBLive! Value [CT4850]", | 1632 | .driver = "EMU10K1", .name = "SB Live! Value [CT4850]", |
1626 | .id = "Live", | 1633 | .id = "Live", |
1627 | .emu10k1_chip = 1, | 1634 | .emu10k1_chip = 1, |
1628 | .ac97_chip = 1, | 1635 | .ac97_chip = 1, |
1629 | .sblive51 = 1} , | 1636 | .sblive51 = 1} , |
1630 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, | 1637 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102, |
1631 | .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]", | 1638 | .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]", |
1632 | .id = "Live", | 1639 | .id = "Live", |
1633 | .emu10k1_chip = 1, | 1640 | .emu10k1_chip = 1, |
1634 | .ac97_chip = 1} , | 1641 | .ac97_chip = 1} , |
1635 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, | 1642 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102, |
1636 | .driver = "EMU10K1", .name = "SBLive! Value [CT4871]", | 1643 | .driver = "EMU10K1", .name = "SB Live! Value [CT4871]", |
1637 | .id = "Live", | 1644 | .id = "Live", |
1638 | .emu10k1_chip = 1, | 1645 | .emu10k1_chip = 1, |
1639 | .ac97_chip = 1, | 1646 | .ac97_chip = 1, |
1640 | .sblive51 = 1} , | 1647 | .sblive51 = 1} , |
1641 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, | 1648 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102, |
1642 | .driver = "EMU10K1", .name = "SBLive! Value [CT4831]", | 1649 | .driver = "EMU10K1", .name = "SB Live! Value [CT4831]", |
1643 | .id = "Live", | 1650 | .id = "Live", |
1644 | .emu10k1_chip = 1, | 1651 | .emu10k1_chip = 1, |
1645 | .ac97_chip = 1, | 1652 | .ac97_chip = 1, |
1646 | .sblive51 = 1} , | 1653 | .sblive51 = 1} , |
1647 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, | 1654 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102, |
1648 | .driver = "EMU10K1", .name = "SBLive! Value [CT4870]", | 1655 | .driver = "EMU10K1", .name = "SB Live! Value [CT4870]", |
1649 | .id = "Live", | 1656 | .id = "Live", |
1650 | .emu10k1_chip = 1, | 1657 | .emu10k1_chip = 1, |
1651 | .ac97_chip = 1, | 1658 | .ac97_chip = 1, |
1652 | .sblive51 = 1} , | 1659 | .sblive51 = 1} , |
1653 | /* Tested by James@superbug.co.uk 3rd July 2005 */ | 1660 | /* Tested by James@superbug.co.uk 3rd July 2005 */ |
1654 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, | 1661 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102, |
1655 | .driver = "EMU10K1", .name = "SBLive! Value [CT4832]", | 1662 | .driver = "EMU10K1", .name = "SB Live! Value [CT4832]", |
1656 | .id = "Live", | 1663 | .id = "Live", |
1657 | .emu10k1_chip = 1, | 1664 | .emu10k1_chip = 1, |
1658 | .ac97_chip = 1, | 1665 | .ac97_chip = 1, |
1659 | .sblive51 = 1} , | 1666 | .sblive51 = 1} , |
1660 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, | 1667 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102, |
1661 | .driver = "EMU10K1", .name = "SBLive! Value [CT4830]", | 1668 | .driver = "EMU10K1", .name = "SB Live! Value [CT4830]", |
1662 | .id = "Live", | 1669 | .id = "Live", |
1663 | .emu10k1_chip = 1, | 1670 | .emu10k1_chip = 1, |
1664 | .ac97_chip = 1, | 1671 | .ac97_chip = 1, |
1665 | .sblive51 = 1} , | 1672 | .sblive51 = 1} , |
1666 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, | 1673 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102, |
1667 | .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", | 1674 | .driver = "EMU10K1", .name = "SB PCI512 [CT4790]", |
1668 | .id = "Live", | 1675 | .id = "Live", |
1669 | .emu10k1_chip = 1, | 1676 | .emu10k1_chip = 1, |
1670 | .ac97_chip = 1, | 1677 | .ac97_chip = 1, |
1671 | .sblive51 = 1} , | 1678 | .sblive51 = 1} , |
1672 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, | 1679 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102, |
1673 | .driver = "EMU10K1", .name = "SBLive! Value [CT4780]", | 1680 | .driver = "EMU10K1", .name = "SB Live! Value [CT4780]", |
1674 | .id = "Live", | 1681 | .id = "Live", |
1675 | .emu10k1_chip = 1, | 1682 | .emu10k1_chip = 1, |
1676 | .ac97_chip = 1, | 1683 | .ac97_chip = 1, |
1677 | .sblive51 = 1} , | 1684 | .sblive51 = 1} , |
1678 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, | 1685 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102, |
1679 | .driver = "EMU10K1", .name = "E-mu APS [4001]", | 1686 | .driver = "EMU10K1", .name = "E-mu APS [PC545]", |
1680 | .id = "APS", | 1687 | .id = "APS", |
1681 | .emu10k1_chip = 1, | 1688 | .emu10k1_chip = 1, |
1682 | .ecard = 1} , | 1689 | .ecard = 1} , |
1683 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, | 1690 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102, |
1684 | .driver = "EMU10K1", .name = "SBLive! [CT4620]", | 1691 | .driver = "EMU10K1", .name = "SB Live! [CT4620]", |
1685 | .id = "Live", | 1692 | .id = "Live", |
1686 | .emu10k1_chip = 1, | 1693 | .emu10k1_chip = 1, |
1687 | .ac97_chip = 1, | 1694 | .ac97_chip = 1, |
1688 | .sblive51 = 1} , | 1695 | .sblive51 = 1} , |
1689 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, | 1696 | {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102, |
1690 | .driver = "EMU10K1", .name = "SBLive! Value [CT4670]", | 1697 | .driver = "EMU10K1", .name = "SB Live! Value [CT4670]", |
1691 | .id = "Live", | 1698 | .id = "Live", |
1692 | .emu10k1_chip = 1, | 1699 | .emu10k1_chip = 1, |
1693 | .ac97_chip = 1, | 1700 | .ac97_chip = 1, |
1694 | .sblive51 = 1} , | 1701 | .sblive51 = 1} , |
1695 | {.vendor = 0x1102, .device = 0x0002, | 1702 | {.vendor = 0x1102, .device = 0x0002, |
1696 | .driver = "EMU10K1", .name = "SB Live [Unknown]", | 1703 | .driver = "EMU10K1", .name = "SB Live! [Unknown]", |
1697 | .id = "Live", | 1704 | .id = "Live", |
1698 | .emu10k1_chip = 1, | 1705 | .emu10k1_chip = 1, |
1699 | .ac97_chip = 1, | 1706 | .ac97_chip = 1, |
@@ -1702,13 +1709,13 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1702 | }; | 1709 | }; |
1703 | 1710 | ||
1704 | int __devinit snd_emu10k1_create(struct snd_card *card, | 1711 | int __devinit snd_emu10k1_create(struct snd_card *card, |
1705 | struct pci_dev * pci, | 1712 | struct pci_dev *pci, |
1706 | unsigned short extin_mask, | 1713 | unsigned short extin_mask, |
1707 | unsigned short extout_mask, | 1714 | unsigned short extout_mask, |
1708 | long max_cache_bytes, | 1715 | long max_cache_bytes, |
1709 | int enable_ir, | 1716 | int enable_ir, |
1710 | uint subsystem, | 1717 | uint subsystem, |
1711 | struct snd_emu10k1 ** remu) | 1718 | struct snd_emu10k1 **remu) |
1712 | { | 1719 | { |
1713 | struct snd_emu10k1 *emu; | 1720 | struct snd_emu10k1 *emu; |
1714 | int idx, err; | 1721 | int idx, err; |
@@ -1718,11 +1725,12 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1718 | static struct snd_device_ops ops = { | 1725 | static struct snd_device_ops ops = { |
1719 | .dev_free = snd_emu10k1_dev_free, | 1726 | .dev_free = snd_emu10k1_dev_free, |
1720 | }; | 1727 | }; |
1721 | 1728 | ||
1722 | *remu = NULL; | 1729 | *remu = NULL; |
1723 | 1730 | ||
1724 | /* enable PCI device */ | 1731 | /* enable PCI device */ |
1725 | if ((err = pci_enable_device(pci)) < 0) | 1732 | err = pci_enable_device(pci); |
1733 | if (err < 0) | ||
1726 | return err; | 1734 | return err; |
1727 | 1735 | ||
1728 | emu = kzalloc(sizeof(*emu), GFP_KERNEL); | 1736 | emu = kzalloc(sizeof(*emu), GFP_KERNEL); |
@@ -1749,16 +1757,17 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1749 | emu->revision = pci->revision; | 1757 | emu->revision = pci->revision; |
1750 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); | 1758 | pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial); |
1751 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); | 1759 | pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model); |
1752 | 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); | 1760 | 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); |
1753 | 1761 | ||
1754 | for (c = emu_chip_details; c->vendor; c++) { | 1762 | for (c = emu_chip_details; c->vendor; c++) { |
1755 | if (c->vendor == pci->vendor && c->device == pci->device) { | 1763 | if (c->vendor == pci->vendor && c->device == pci->device) { |
1756 | if (subsystem) { | 1764 | if (subsystem) { |
1757 | if (c->subsystem && (c->subsystem == subsystem) ) { | 1765 | if (c->subsystem && (c->subsystem == subsystem)) |
1758 | break; | 1766 | break; |
1759 | } else continue; | 1767 | else |
1768 | continue; | ||
1760 | } else { | 1769 | } else { |
1761 | if (c->subsystem && (c->subsystem != emu->serial) ) | 1770 | if (c->subsystem && (c->subsystem != emu->serial)) |
1762 | continue; | 1771 | continue; |
1763 | if (c->revision && c->revision != emu->revision) | 1772 | if (c->revision && c->revision != emu->revision) |
1764 | continue; | 1773 | continue; |
@@ -1774,14 +1783,18 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1774 | } | 1783 | } |
1775 | emu->card_capabilities = c; | 1784 | emu->card_capabilities = c; |
1776 | if (c->subsystem && !subsystem) | 1785 | if (c->subsystem && !subsystem) |
1777 | snd_printdd("Sound card name=%s\n", c->name); | 1786 | snd_printdd("Sound card name = %s\n", c->name); |
1778 | else if (subsystem) | 1787 | else if (subsystem) |
1779 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n", | 1788 | snd_printdd("Sound card name = %s, " |
1780 | c->name, pci->vendor, pci->device, emu->serial, c->subsystem); | 1789 | "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. " |
1781 | else | 1790 | "Forced to subsytem = 0x%x\n", c->name, |
1782 | snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n", | 1791 | pci->vendor, pci->device, emu->serial, c->subsystem); |
1783 | c->name, pci->vendor, pci->device, emu->serial); | 1792 | else |
1784 | 1793 | snd_printdd("Sound card name = %s, " | |
1794 | "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n", | ||
1795 | c->name, pci->vendor, pci->device, | ||
1796 | emu->serial); | ||
1797 | |||
1785 | if (!*card->id && c->id) { | 1798 | if (!*card->id && c->id) { |
1786 | int i, n = 0; | 1799 | int i, n = 0; |
1787 | strlcpy(card->id, c->id, sizeof(card->id)); | 1800 | strlcpy(card->id, c->id, sizeof(card->id)); |
@@ -1815,7 +1828,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1815 | else | 1828 | else |
1816 | emu->gpr_base = FXGPREGBASE; | 1829 | emu->gpr_base = FXGPREGBASE; |
1817 | 1830 | ||
1818 | if ((err = pci_request_regions(pci, "EMU10K1")) < 0) { | 1831 | err = pci_request_regions(pci, "EMU10K1"); |
1832 | if (err < 0) { | ||
1819 | kfree(emu); | 1833 | kfree(emu); |
1820 | pci_disable_device(pci); | 1834 | pci_disable_device(pci); |
1821 | return err; | 1835 | return err; |
@@ -1862,21 +1876,25 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1862 | emu->enable_ir = enable_ir; | 1876 | emu->enable_ir = enable_ir; |
1863 | 1877 | ||
1864 | if (emu->card_capabilities->ca_cardbus_chip) { | 1878 | if (emu->card_capabilities->ca_cardbus_chip) { |
1865 | if ((err = snd_emu10k1_cardbus_init(emu)) < 0) | 1879 | err = snd_emu10k1_cardbus_init(emu); |
1880 | if (err < 0) | ||
1866 | goto error; | 1881 | goto error; |
1867 | } | 1882 | } |
1868 | if (emu->card_capabilities->ecard) { | 1883 | if (emu->card_capabilities->ecard) { |
1869 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) | 1884 | err = snd_emu10k1_ecard_init(emu); |
1885 | if (err < 0) | ||
1870 | goto error; | 1886 | goto error; |
1871 | } else if (emu->card_capabilities->emu_model) { | 1887 | } else if (emu->card_capabilities->emu_model) { |
1872 | if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { | 1888 | err = snd_emu10k1_emu1010_init(emu); |
1873 | snd_emu10k1_free(emu); | 1889 | if (err < 0) { |
1874 | return err; | 1890 | snd_emu10k1_free(emu); |
1875 | } | 1891 | return err; |
1892 | } | ||
1876 | } else { | 1893 | } else { |
1877 | /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version | 1894 | /* 5.1: Enable the additional AC97 Slots. If the emu10k1 version |
1878 | does not support this, it shouldn't do any harm */ | 1895 | does not support this, it shouldn't do any harm */ |
1879 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); | 1896 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, |
1897 | AC97SLOT_CNTR|AC97SLOT_LFE); | ||
1880 | } | 1898 | } |
1881 | 1899 | ||
1882 | /* initialize TRAM setup */ | 1900 | /* initialize TRAM setup */ |
@@ -1916,7 +1934,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1916 | snd_emu10k1_synth_alloc(emu, 4096); | 1934 | snd_emu10k1_synth_alloc(emu, 4096); |
1917 | if (emu->reserved_page) | 1935 | if (emu->reserved_page) |
1918 | emu->reserved_page->map_locked = 1; | 1936 | emu->reserved_page->map_locked = 1; |
1919 | 1937 | ||
1920 | /* Clear silent pages and set up pointers */ | 1938 | /* Clear silent pages and set up pointers */ |
1921 | memset(emu->silent_page.area, 0, PAGE_SIZE); | 1939 | memset(emu->silent_page.area, 0, PAGE_SIZE); |
1922 | silent_page = emu->silent_page.addr << 1; | 1940 | silent_page = emu->silent_page.addr << 1; |
@@ -1929,19 +1947,23 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1929 | emu->voices[idx].number = idx; | 1947 | emu->voices[idx].number = idx; |
1930 | } | 1948 | } |
1931 | 1949 | ||
1932 | if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0) | 1950 | err = snd_emu10k1_init(emu, enable_ir, 0); |
1951 | if (err < 0) | ||
1933 | goto error; | 1952 | goto error; |
1934 | #ifdef CONFIG_PM | 1953 | #ifdef CONFIG_PM |
1935 | if ((err = alloc_pm_buffer(emu)) < 0) | 1954 | err = alloc_pm_buffer(emu); |
1955 | if (err < 0) | ||
1936 | goto error; | 1956 | goto error; |
1937 | #endif | 1957 | #endif |
1938 | 1958 | ||
1939 | /* Initialize the effect engine */ | 1959 | /* Initialize the effect engine */ |
1940 | if ((err = snd_emu10k1_init_efx(emu)) < 0) | 1960 | err = snd_emu10k1_init_efx(emu); |
1961 | if (err < 0) | ||
1941 | goto error; | 1962 | goto error; |
1942 | snd_emu10k1_audio_enable(emu); | 1963 | snd_emu10k1_audio_enable(emu); |
1943 | 1964 | ||
1944 | if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0) | 1965 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops); |
1966 | if (err < 0) | ||
1945 | goto error; | 1967 | goto error; |
1946 | 1968 | ||
1947 | #ifdef CONFIG_PROC_FS | 1969 | #ifdef CONFIG_PROC_FS |
@@ -1981,7 +2003,7 @@ static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu) | |||
1981 | if (emu->audigy) | 2003 | if (emu->audigy) |
1982 | size += ARRAY_SIZE(saved_regs_audigy); | 2004 | size += ARRAY_SIZE(saved_regs_audigy); |
1983 | emu->saved_ptr = vmalloc(4 * NUM_G * size); | 2005 | emu->saved_ptr = vmalloc(4 * NUM_G * size); |
1984 | if (! emu->saved_ptr) | 2006 | if (!emu->saved_ptr) |
1985 | return -ENOMEM; | 2007 | return -ENOMEM; |
1986 | if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) | 2008 | if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0) |
1987 | return -ENOMEM; | 2009 | return -ENOMEM; |
@@ -2026,7 +2048,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) | |||
2026 | if (emu->card_capabilities->ecard) | 2048 | if (emu->card_capabilities->ecard) |
2027 | snd_emu10k1_ecard_init(emu); | 2049 | snd_emu10k1_ecard_init(emu); |
2028 | else if (emu->card_capabilities->emu_model) | 2050 | else if (emu->card_capabilities->emu_model) |
2029 | snd_emu10k1_emu1010_init(emu); | 2051 | snd_emu10k1_emu1010_init(emu); |
2030 | else | 2052 | else |
2031 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); | 2053 | snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); |
2032 | snd_emu10k1_init(emu, emu->enable_ir, 1); | 2054 | snd_emu10k1_init(emu, emu->enable_ir, 1); |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index f34bbfb705f5..b0fb6c917c38 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -1639,6 +1639,45 @@ static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata = | |||
1639 | .put = snd_emu10k1_shared_spdif_put | 1639 | .put = snd_emu10k1_shared_spdif_put |
1640 | }; | 1640 | }; |
1641 | 1641 | ||
1642 | /* workaround for too low volume on Audigy due to 16bit/24bit conversion */ | ||
1643 | |||
1644 | #define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info | ||
1645 | |||
1646 | static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol, | ||
1647 | struct snd_ctl_elem_value *ucontrol) | ||
1648 | { | ||
1649 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); | ||
1650 | unsigned int val; | ||
1651 | |||
1652 | /* FIXME: better to use a cached version */ | ||
1653 | val = snd_ac97_read(emu->ac97, AC97_REC_GAIN); | ||
1654 | ucontrol->value.integer.value[0] = !!val; | ||
1655 | return 0; | ||
1656 | } | ||
1657 | |||
1658 | static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol, | ||
1659 | struct snd_ctl_elem_value *ucontrol) | ||
1660 | { | ||
1661 | struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol); | ||
1662 | unsigned int val; | ||
1663 | |||
1664 | if (ucontrol->value.integer.value[0]) | ||
1665 | val = 0x0f0f; | ||
1666 | else | ||
1667 | val = 0; | ||
1668 | return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val); | ||
1669 | } | ||
1670 | |||
1671 | static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata = | ||
1672 | { | ||
1673 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1674 | .name = "Analog Capture Boost", | ||
1675 | .info = snd_audigy_capture_boost_info, | ||
1676 | .get = snd_audigy_capture_boost_get, | ||
1677 | .put = snd_audigy_capture_boost_put | ||
1678 | }; | ||
1679 | |||
1680 | |||
1642 | /* | 1681 | /* |
1643 | */ | 1682 | */ |
1644 | static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97) | 1683 | static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97) |
@@ -2087,5 +2126,12 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu, | |||
2087 | } | 2126 | } |
2088 | } | 2127 | } |
2089 | 2128 | ||
2129 | if (emu->card_capabilities->ac97_chip && emu->audigy) { | ||
2130 | err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost, | ||
2131 | emu)); | ||
2132 | if (err < 0) | ||
2133 | return err; | ||
2134 | } | ||
2135 | |||
2090 | return 0; | 2136 | return 0; |
2091 | } | 2137 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 5dd3e89f620a..b77f330d2650 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -69,6 +69,7 @@ enum { | |||
69 | }; | 69 | }; |
70 | 70 | ||
71 | enum { | 71 | enum { |
72 | STAC_92HD73XX_NO_JD, /* no jack-detection */ | ||
72 | STAC_92HD73XX_REF, | 73 | STAC_92HD73XX_REF, |
73 | STAC_DELL_M6_AMIC, | 74 | STAC_DELL_M6_AMIC, |
74 | STAC_DELL_M6_DMIC, | 75 | STAC_DELL_M6_DMIC, |
@@ -127,6 +128,7 @@ enum { | |||
127 | }; | 128 | }; |
128 | 129 | ||
129 | enum { | 130 | enum { |
131 | STAC_D965_REF_NO_JD, /* no jack-detection */ | ||
130 | STAC_D965_REF, | 132 | STAC_D965_REF, |
131 | STAC_D965_3ST, | 133 | STAC_D965_3ST, |
132 | STAC_D965_5ST, | 134 | STAC_D965_5ST, |
@@ -857,6 +859,7 @@ static struct hda_verb stac92hd83xxx_core_init[] = { | |||
857 | 859 | ||
858 | /* power state controls amps */ | 860 | /* power state controls amps */ |
859 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, | 861 | { 0x01, AC_VERB_SET_EAPD, 1 << 2}, |
862 | {} | ||
860 | }; | 863 | }; |
861 | 864 | ||
862 | static struct hda_verb stac92hd71bxx_core_init[] = { | 865 | static struct hda_verb stac92hd71bxx_core_init[] = { |
@@ -868,6 +871,7 @@ static struct hda_verb stac92hd71bxx_core_init[] = { | |||
868 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 871 | { 0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
869 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 872 | { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
870 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 873 | { 0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
874 | {} | ||
871 | }; | 875 | }; |
872 | 876 | ||
873 | #define HD_DISABLE_PORTF 2 | 877 | #define HD_DISABLE_PORTF 2 |
@@ -1611,6 +1615,7 @@ static unsigned int *stac92hd73xx_brd_tbl[STAC_92HD73XX_MODELS] = { | |||
1611 | }; | 1615 | }; |
1612 | 1616 | ||
1613 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { | 1617 | static const char *stac92hd73xx_models[STAC_92HD73XX_MODELS] = { |
1618 | [STAC_92HD73XX_NO_JD] = "no-jd", | ||
1614 | [STAC_92HD73XX_REF] = "ref", | 1619 | [STAC_92HD73XX_REF] = "ref", |
1615 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", | 1620 | [STAC_DELL_M6_AMIC] = "dell-m6-amic", |
1616 | [STAC_DELL_M6_DMIC] = "dell-m6-dmic", | 1621 | [STAC_DELL_M6_DMIC] = "dell-m6-dmic", |
@@ -1640,6 +1645,8 @@ static struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = { | |||
1640 | "unknown Dell", STAC_DELL_M6_DMIC), | 1645 | "unknown Dell", STAC_DELL_M6_DMIC), |
1641 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f, | 1646 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x029f, |
1642 | "Dell Studio 1537", STAC_DELL_M6_DMIC), | 1647 | "Dell Studio 1537", STAC_DELL_M6_DMIC), |
1648 | SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02a0, | ||
1649 | "Dell Studio 17", STAC_DELL_M6_DMIC), | ||
1643 | {} /* terminator */ | 1650 | {} /* terminator */ |
1644 | }; | 1651 | }; |
1645 | 1652 | ||
@@ -1662,6 +1669,7 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { | |||
1662 | /* SigmaTel reference board */ | 1669 | /* SigmaTel reference board */ |
1663 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 1670 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
1664 | "DFI LanParty", STAC_92HD71BXX_REF), | 1671 | "DFI LanParty", STAC_92HD71BXX_REF), |
1672 | {} /* terminator */ | ||
1665 | }; | 1673 | }; |
1666 | 1674 | ||
1667 | static unsigned int ref92hd71bxx_pin_configs[11] = { | 1675 | static unsigned int ref92hd71bxx_pin_configs[11] = { |
@@ -2027,6 +2035,7 @@ static unsigned int dell_3st_pin_configs[14] = { | |||
2027 | }; | 2035 | }; |
2028 | 2036 | ||
2029 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | 2037 | static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { |
2038 | [STAC_D965_REF_NO_JD] = ref927x_pin_configs, | ||
2030 | [STAC_D965_REF] = ref927x_pin_configs, | 2039 | [STAC_D965_REF] = ref927x_pin_configs, |
2031 | [STAC_D965_3ST] = d965_3st_pin_configs, | 2040 | [STAC_D965_3ST] = d965_3st_pin_configs, |
2032 | [STAC_D965_5ST] = d965_5st_pin_configs, | 2041 | [STAC_D965_5ST] = d965_5st_pin_configs, |
@@ -2035,6 +2044,7 @@ static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { | |||
2035 | }; | 2044 | }; |
2036 | 2045 | ||
2037 | static const char *stac927x_models[STAC_927X_MODELS] = { | 2046 | static const char *stac927x_models[STAC_927X_MODELS] = { |
2047 | [STAC_D965_REF_NO_JD] = "ref-no-jd", | ||
2038 | [STAC_D965_REF] = "ref", | 2048 | [STAC_D965_REF] = "ref", |
2039 | [STAC_D965_3ST] = "3stack", | 2049 | [STAC_D965_3ST] = "3stack", |
2040 | [STAC_D965_5ST] = "5stack", | 2050 | [STAC_D965_5ST] = "5stack", |
@@ -2896,7 +2906,7 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
2896 | } | 2906 | } |
2897 | 2907 | ||
2898 | if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && | 2908 | if ((spec->multiout.num_dacs - cfg->line_outs) > 0 && |
2899 | cfg->hp_outs && !spec->multiout.hp_nid) | 2909 | cfg->hp_outs == 1 && !spec->multiout.hp_nid) |
2900 | spec->multiout.hp_nid = nid; | 2910 | spec->multiout.hp_nid = nid; |
2901 | 2911 | ||
2902 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | 2912 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
@@ -4254,14 +4264,17 @@ again: | |||
4254 | 4264 | ||
4255 | switch (spec->multiout.num_dacs) { | 4265 | switch (spec->multiout.num_dacs) { |
4256 | case 0x3: /* 6 Channel */ | 4266 | case 0x3: /* 6 Channel */ |
4267 | spec->multiout.hp_nid = 0x17; | ||
4257 | spec->mixer = stac92hd73xx_6ch_mixer; | 4268 | spec->mixer = stac92hd73xx_6ch_mixer; |
4258 | spec->init = stac92hd73xx_6ch_core_init; | 4269 | spec->init = stac92hd73xx_6ch_core_init; |
4259 | break; | 4270 | break; |
4260 | case 0x4: /* 8 Channel */ | 4271 | case 0x4: /* 8 Channel */ |
4272 | spec->multiout.hp_nid = 0x18; | ||
4261 | spec->mixer = stac92hd73xx_8ch_mixer; | 4273 | spec->mixer = stac92hd73xx_8ch_mixer; |
4262 | spec->init = stac92hd73xx_8ch_core_init; | 4274 | spec->init = stac92hd73xx_8ch_core_init; |
4263 | break; | 4275 | break; |
4264 | case 0x5: /* 10 Channel */ | 4276 | case 0x5: /* 10 Channel */ |
4277 | spec->multiout.hp_nid = 0x19; | ||
4265 | spec->mixer = stac92hd73xx_10ch_mixer; | 4278 | spec->mixer = stac92hd73xx_10ch_mixer; |
4266 | spec->init = stac92hd73xx_10ch_core_init; | 4279 | spec->init = stac92hd73xx_10ch_core_init; |
4267 | }; | 4280 | }; |
@@ -4297,6 +4310,7 @@ again: | |||
4297 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; | 4310 | spec->amp_nids = &stac92hd73xx_amp_nids[DELL_M6_AMP]; |
4298 | spec->eapd_switch = 0; | 4311 | spec->eapd_switch = 0; |
4299 | spec->num_amps = 1; | 4312 | spec->num_amps = 1; |
4313 | spec->multiout.hp_nid = 0; /* dual HPs */ | ||
4300 | 4314 | ||
4301 | if (!spec->init) | 4315 | if (!spec->init) |
4302 | spec->init = dell_m6_core_init; | 4316 | spec->init = dell_m6_core_init; |
@@ -4351,6 +4365,9 @@ again: | |||
4351 | return err; | 4365 | return err; |
4352 | } | 4366 | } |
4353 | 4367 | ||
4368 | if (spec->board_config == STAC_92HD73XX_NO_JD) | ||
4369 | spec->hp_detect = 0; | ||
4370 | |||
4354 | codec->patch_ops = stac92xx_patch_ops; | 4371 | codec->patch_ops = stac92xx_patch_ops; |
4355 | 4372 | ||
4356 | return 0; | 4373 | return 0; |
@@ -4899,6 +4916,10 @@ static int patch_stac927x(struct hda_codec *codec) | |||
4899 | */ | 4916 | */ |
4900 | codec->bus->needs_damn_long_delay = 1; | 4917 | codec->bus->needs_damn_long_delay = 1; |
4901 | 4918 | ||
4919 | /* no jack detecion for ref-no-jd model */ | ||
4920 | if (spec->board_config == STAC_D965_REF_NO_JD) | ||
4921 | spec->hp_detect = 0; | ||
4922 | |||
4902 | return 0; | 4923 | return 0; |
4903 | } | 4924 | } |
4904 | 4925 | ||
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 1b3f11702713..0dfa0540ce2c 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c | |||
@@ -382,23 +382,25 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id) | |||
382 | unsigned char status_mask = | 382 | unsigned char status_mask = |
383 | VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM; | 383 | VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM; |
384 | int handled = 0; | 384 | int handled = 0; |
385 | #ifdef CONFIG_SND_DEBUG | ||
386 | int timeout = 0; | 385 | int timeout = 0; |
387 | #endif | ||
388 | 386 | ||
389 | while (1) { | 387 | while (1) { |
390 | status = inb(ICEREG1724(ice, IRQSTAT)); | 388 | status = inb(ICEREG1724(ice, IRQSTAT)); |
391 | status &= status_mask; | 389 | status &= status_mask; |
392 | if (status == 0) | 390 | if (status == 0) |
393 | break; | 391 | break; |
394 | #ifdef CONFIG_SND_DEBUG | ||
395 | if (++timeout > 10) { | 392 | if (++timeout > 10) { |
396 | printk(KERN_ERR | 393 | status = inb(ICEREG1724(ice, IRQSTAT)); |
397 | "ice1724: Too long irq loop, status = 0x%x\n", | 394 | printk(KERN_ERR "ice1724: Too long irq loop, " |
398 | status); | 395 | "status = 0x%x\n", status); |
396 | if (status & VT1724_IRQ_MPU_TX) { | ||
397 | printk(KERN_ERR "ice1724: Disabling MPU_TX\n"); | ||
398 | outb(inb(ICEREG1724(ice, IRQMASK)) | | ||
399 | VT1724_IRQ_MPU_TX, | ||
400 | ICEREG1724(ice, IRQMASK)); | ||
401 | } | ||
399 | break; | 402 | break; |
400 | } | 403 | } |
401 | #endif | ||
402 | handled = 1; | 404 | handled = 1; |
403 | if (status & VT1724_IRQ_MPU_TX) { | 405 | if (status & VT1724_IRQ_MPU_TX) { |
404 | spin_lock(&ice->reg_lock); | 406 | spin_lock(&ice->reg_lock); |
@@ -2351,7 +2353,6 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2351 | { | 2353 | { |
2352 | struct snd_ice1712 *ice; | 2354 | struct snd_ice1712 *ice; |
2353 | int err; | 2355 | int err; |
2354 | unsigned char mask; | ||
2355 | static struct snd_device_ops ops = { | 2356 | static struct snd_device_ops ops = { |
2356 | .dev_free = snd_vt1724_dev_free, | 2357 | .dev_free = snd_vt1724_dev_free, |
2357 | }; | 2358 | }; |
@@ -2412,9 +2413,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card, | |||
2412 | return -EIO; | 2413 | return -EIO; |
2413 | } | 2414 | } |
2414 | 2415 | ||
2415 | /* unmask used interrupts */ | 2416 | /* MPU_RX and TX irq masks are cleared later dynamically */ |
2416 | mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX; | 2417 | outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK)); |
2417 | outb(mask, ICEREG1724(ice, IRQMASK)); | 2418 | |
2418 | /* don't handle FIFO overrun/underruns (just yet), | 2419 | /* don't handle FIFO overrun/underruns (just yet), |
2419 | * since they cause machine lockups | 2420 | * since they cause machine lockups |
2420 | */ | 2421 | */ |
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c index ae7601f353a7..f23a73577c22 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 * | |||
1010 | .dev_free = snd_mixart_chip_dev_free, | 1010 | .dev_free = snd_mixart_chip_dev_free, |
1011 | }; | 1011 | }; |
1012 | 1012 | ||
1013 | mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1013 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1014 | if (! chip) { | 1014 | if (! chip) { |
1015 | snd_printk(KERN_ERR "cannot allocate chip\n"); | 1015 | snd_printk(KERN_ERR "cannot allocate chip\n"); |
1016 | return -ENOMEM; | 1016 | return -ENOMEM; |
@@ -1025,6 +1025,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card * | |||
1025 | return err; | 1025 | return err; |
1026 | } | 1026 | } |
1027 | 1027 | ||
1028 | mgr->chip[idx] = chip; | ||
1028 | snd_card_set_dev(card, &mgr->pci->dev); | 1029 | snd_card_set_dev(card, &mgr->pci->dev); |
1029 | 1030 | ||
1030 | return 0; | 1031 | return 0; |
@@ -1377,6 +1378,7 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci, | |||
1377 | sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); | 1378 | sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); |
1378 | 1379 | ||
1379 | if ((err = snd_mixart_create(mgr, card, i)) < 0) { | 1380 | if ((err = snd_mixart_create(mgr, card, i)) < 0) { |
1381 | snd_card_free(card); | ||
1380 | snd_mixart_free(mgr); | 1382 | snd_mixart_free(mgr); |
1381 | return err; | 1383 | return err; |
1382 | } | 1384 | } |
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c index 8309d4487722..471ee27e6c8a 100644 --- a/sound/pci/pcxhr/pcxhr.c +++ b/sound/pci/pcxhr/pcxhr.c | |||
@@ -1024,7 +1024,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, | |||
1024 | .dev_free = pcxhr_chip_dev_free, | 1024 | .dev_free = pcxhr_chip_dev_free, |
1025 | }; | 1025 | }; |
1026 | 1026 | ||
1027 | mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL); | 1027 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); |
1028 | if (! chip) { | 1028 | if (! chip) { |
1029 | snd_printk(KERN_ERR "cannot allocate chip\n"); | 1029 | snd_printk(KERN_ERR "cannot allocate chip\n"); |
1030 | return -ENOMEM; | 1030 | return -ENOMEM; |
@@ -1050,6 +1050,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, | |||
1050 | return err; | 1050 | return err; |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | mgr->chip[idx] = chip; | ||
1053 | snd_card_set_dev(card, &mgr->pci->dev); | 1054 | snd_card_set_dev(card, &mgr->pci->dev); |
1054 | 1055 | ||
1055 | return 0; | 1056 | return 0; |
@@ -1310,6 +1311,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id | |||
1310 | sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); | 1311 | sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i); |
1311 | 1312 | ||
1312 | if ((err = pcxhr_create(mgr, card, i)) < 0) { | 1313 | if ((err = pcxhr_create(mgr, card, i)) < 0) { |
1314 | snd_card_free(card); | ||
1313 | pcxhr_free(mgr); | 1315 | pcxhr_free(mgr); |
1314 | return err; | 1316 | return err; |
1315 | } | 1317 | } |
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c index 1d0eeb1f506c..3caacfb9d8e0 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."); | |||
172 | 172 | ||
173 | #define MAX_WRITE_RETRY 10 /* cmd interface limits */ | 173 | #define MAX_WRITE_RETRY 10 /* cmd interface limits */ |
174 | #define MAX_ERROR_COUNT 10 | 174 | #define MAX_ERROR_COUNT 10 |
175 | #define CMDIF_TIMEOUT 500000 | 175 | #define CMDIF_TIMEOUT 50000 |
176 | #define RESET_TRIES 5 | 176 | #define RESET_TRIES 5 |
177 | 177 | ||
178 | #define READ_PORT_ULONG(p) inl((unsigned long)&(p)) | 178 | #define READ_PORT_ULONG(p) inl((unsigned long)&(p)) |
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index a38c0c790d2b..af76ee862d27 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) | |||
1033 | } | 1033 | } |
1034 | if (of_device_is_compatible(sound, "tumbler")) { | 1034 | if (of_device_is_compatible(sound, "tumbler")) { |
1035 | chip->model = PMAC_TUMBLER; | 1035 | chip->model = PMAC_TUMBLER; |
1036 | chip->can_capture = 0; /* no capture */ | 1036 | chip->can_capture = machine_is_compatible("PowerMac4,2"); |
1037 | chip->can_duplex = 0; | 1037 | chip->can_duplex = 0; |
1038 | // chip->can_byte_swap = 0; /* FIXME: check this */ | 1038 | // chip->can_byte_swap = 0; /* FIXME: check this */ |
1039 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); | 1039 | chip->num_freqs = ARRAY_SIZE(tumbler_freqs); |
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c index f746e15b8481..3eb223385416 100644 --- a/sound/ppc/tumbler.c +++ b/sound/ppc/tumbler.c | |||
@@ -875,7 +875,8 @@ static struct snd_kcontrol_new snapper_mixers[] __initdata = { | |||
875 | .put = tumbler_put_master_switch | 875 | .put = tumbler_put_master_switch |
876 | }, | 876 | }, |
877 | DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM), | 877 | DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM), |
878 | DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2), | 878 | /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */ |
879 | DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2), | ||
879 | DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC), | 880 | DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC), |
880 | DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), | 881 | DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), |
881 | DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), | 882 | DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), |
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 4dfda6674bec..ef025c66cc66 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -22,17 +22,16 @@ if SND_SOC | |||
22 | config SND_SOC_AC97_BUS | 22 | config SND_SOC_AC97_BUS |
23 | bool | 23 | bool |
24 | 24 | ||
25 | # All the supported Soc's | 25 | # All the supported SoCs |
26 | source "sound/soc/at32/Kconfig" | 26 | source "sound/soc/atmel/Kconfig" |
27 | source "sound/soc/at91/Kconfig" | ||
28 | source "sound/soc/au1x/Kconfig" | 27 | source "sound/soc/au1x/Kconfig" |
28 | source "sound/soc/blackfin/Kconfig" | ||
29 | source "sound/soc/davinci/Kconfig" | ||
30 | source "sound/soc/fsl/Kconfig" | ||
31 | source "sound/soc/omap/Kconfig" | ||
29 | source "sound/soc/pxa/Kconfig" | 32 | source "sound/soc/pxa/Kconfig" |
30 | source "sound/soc/s3c24xx/Kconfig" | 33 | source "sound/soc/s3c24xx/Kconfig" |
31 | source "sound/soc/sh/Kconfig" | 34 | source "sound/soc/sh/Kconfig" |
32 | source "sound/soc/fsl/Kconfig" | ||
33 | source "sound/soc/davinci/Kconfig" | ||
34 | source "sound/soc/omap/Kconfig" | ||
35 | source "sound/soc/blackfin/Kconfig" | ||
36 | 35 | ||
37 | # Supported codecs | 36 | # Supported codecs |
38 | source "sound/soc/codecs/Kconfig" | 37 | source "sound/soc/codecs/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index d849349f2c66..86a9b1f5b0f3 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,13 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o |
2 | 2 | ||
3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 3 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
4 | obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/ | 4 | obj-$(CONFIG_SND_SOC) += codecs/ |
5 | obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/ | 5 | obj-$(CONFIG_SND_SOC) += atmel/ |
6 | obj-$(CONFIG_SND_SOC) += au1x/ | ||
7 | obj-$(CONFIG_SND_SOC) += blackfin/ | ||
8 | obj-$(CONFIG_SND_SOC) += davinci/ | ||
9 | obj-$(CONFIG_SND_SOC) += fsl/ | ||
10 | obj-$(CONFIG_SND_SOC) += omap/ | ||
11 | obj-$(CONFIG_SND_SOC) += pxa/ | ||
12 | obj-$(CONFIG_SND_SOC) += s3c24xx/ | ||
13 | obj-$(CONFIG_SND_SOC) += sh/ | ||
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig deleted file mode 100644 index b0765e86c085..000000000000 --- a/sound/soc/at32/Kconfig +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | config SND_AT32_SOC | ||
2 | tristate "SoC Audio for the Atmel AT32 System-on-a-Chip" | ||
3 | depends on AVR32 && SND_SOC | ||
4 | help | ||
5 | Say Y or M if you want to add support for codecs attached to | ||
6 | the AT32 SSC interface. You will also need to | ||
7 | to select the audio interfaces to support below. | ||
8 | |||
9 | |||
10 | config SND_AT32_SOC_SSC | ||
11 | tristate | ||
12 | |||
13 | |||
14 | |||
15 | config SND_AT32_SOC_PLAYPAQ | ||
16 | tristate "SoC Audio support for PlayPaq with WM8510" | ||
17 | depends on SND_AT32_SOC && BOARD_PLAYPAQ | ||
18 | select SND_AT32_SOC_SSC | ||
19 | select SND_SOC_WM8510 | ||
20 | help | ||
21 | Say Y or M here if you want to add support for SoC audio | ||
22 | on the LRS PlayPaq. | ||
23 | |||
24 | |||
25 | |||
26 | config SND_AT32_SOC_PLAYPAQ_SLAVE | ||
27 | bool "Run CODEC on PlayPaq in slave mode" | ||
28 | depends on SND_AT32_SOC_PLAYPAQ | ||
29 | default n | ||
30 | help | ||
31 | Say Y if you want to run with the AT32 SSC generating the BCLK | ||
32 | and FRAME signals on the PlayPaq. Unless you want to play | ||
33 | with the AT32 as the SSC master, you probably want to say N here, | ||
34 | as this will give you better sound quality. | ||
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile deleted file mode 100644 index c03e55ececeb..000000000000 --- a/sound/soc/at32/Makefile +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | # AT32 Platform Support | ||
2 | snd-soc-at32-objs := at32-pcm.o | ||
3 | snd-soc-at32-ssc-objs := at32-ssc.o | ||
4 | |||
5 | obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o | ||
6 | obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o | ||
7 | |||
8 | # AT32 Machine Support | ||
9 | snd-soc-playpaq-objs := playpaq_wm8510.o | ||
10 | |||
11 | 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 deleted file mode 100644 index c83584f989a9..000000000000 --- a/sound/soc/at32/at32-pcm.c +++ /dev/null | |||
@@ -1,492 +0,0 @@ | |||
1 | /* sound/soc/at32/at32-pcm.c | ||
2 | * ASoC PCM interface for Atmel AT32 SoC | ||
3 | * | ||
4 | * Copyright (C) 2008 Long Range Systems | ||
5 | * Geoffrey Wossum <gwossum@acm.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Note that this is basically a port of the sound/soc/at91-pcm.c to | ||
12 | * the AVR32 kernel. Thanks to Frank Mandarino for that code. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/slab.h> | ||
19 | #include <linux/dma-mapping.h> | ||
20 | #include <linux/atmel_pdc.h> | ||
21 | |||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #include "at32-pcm.h" | ||
28 | |||
29 | |||
30 | |||
31 | /*--------------------------------------------------------------------------*\ | ||
32 | * Hardware definition | ||
33 | \*--------------------------------------------------------------------------*/ | ||
34 | /* TODO: These values were taken from the AT91 platform driver, check | ||
35 | * them against real values for AT32 | ||
36 | */ | ||
37 | static const struct snd_pcm_hardware at32_pcm_hardware = { | ||
38 | .info = (SNDRV_PCM_INFO_MMAP | | ||
39 | SNDRV_PCM_INFO_MMAP_VALID | | ||
40 | SNDRV_PCM_INFO_INTERLEAVED | | ||
41 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
42 | SNDRV_PCM_INFO_PAUSE), | ||
43 | |||
44 | .formats = SNDRV_PCM_FMTBIT_S16, | ||
45 | .period_bytes_min = 32, | ||
46 | .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */ | ||
47 | .periods_min = 2, | ||
48 | .periods_max = 1024, | ||
49 | .buffer_bytes_max = 32 * 1024, | ||
50 | }; | ||
51 | |||
52 | |||
53 | |||
54 | /*--------------------------------------------------------------------------*\ | ||
55 | * Data types | ||
56 | \*--------------------------------------------------------------------------*/ | ||
57 | struct at32_runtime_data { | ||
58 | struct at32_pcm_dma_params *params; | ||
59 | dma_addr_t dma_buffer; /* physical address of DMA buffer */ | ||
60 | dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ | ||
61 | size_t period_size; | ||
62 | |||
63 | dma_addr_t period_ptr; /* physical address of next period */ | ||
64 | int periods; /* period index of period_ptr */ | ||
65 | |||
66 | /* Save PDC registers (for power management) */ | ||
67 | u32 pdc_xpr_save; | ||
68 | u32 pdc_xcr_save; | ||
69 | u32 pdc_xnpr_save; | ||
70 | u32 pdc_xncr_save; | ||
71 | }; | ||
72 | |||
73 | |||
74 | |||
75 | /*--------------------------------------------------------------------------*\ | ||
76 | * Helper functions | ||
77 | \*--------------------------------------------------------------------------*/ | ||
78 | static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | ||
79 | { | ||
80 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
81 | struct snd_dma_buffer *dmabuf = &substream->dma_buffer; | ||
82 | size_t size = at32_pcm_hardware.buffer_bytes_max; | ||
83 | |||
84 | dmabuf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
85 | dmabuf->dev.dev = pcm->card->dev; | ||
86 | dmabuf->private_data = NULL; | ||
87 | dmabuf->area = dma_alloc_coherent(pcm->card->dev, size, | ||
88 | &dmabuf->addr, GFP_KERNEL); | ||
89 | pr_debug("at32_pcm: preallocate_dma_buffer: " | ||
90 | "area=%p, addr=%p, size=%ld\n", | ||
91 | (void *)dmabuf->area, (void *)dmabuf->addr, size); | ||
92 | |||
93 | if (!dmabuf->area) | ||
94 | return -ENOMEM; | ||
95 | |||
96 | dmabuf->bytes = size; | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | |||
101 | |||
102 | /*--------------------------------------------------------------------------*\ | ||
103 | * ISR | ||
104 | \*--------------------------------------------------------------------------*/ | ||
105 | static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream) | ||
106 | { | ||
107 | struct snd_pcm_runtime *rtd = substream->runtime; | ||
108 | struct at32_runtime_data *prtd = rtd->private_data; | ||
109 | struct at32_pcm_dma_params *params = prtd->params; | ||
110 | static int count; | ||
111 | |||
112 | count++; | ||
113 | if (ssc_sr & params->mask->ssc_endbuf) { | ||
114 | pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n", | ||
115 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? | ||
116 | "underrun" : "overrun", params->name, ssc_sr, count); | ||
117 | |||
118 | /* re-start the PDC */ | ||
119 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
120 | params->mask->pdc_disable); | ||
121 | prtd->period_ptr += prtd->period_size; | ||
122 | if (prtd->period_ptr >= prtd->dma_buffer_end) | ||
123 | prtd->period_ptr = prtd->dma_buffer; | ||
124 | |||
125 | |||
126 | ssc_writex(params->ssc->regs, params->pdc->xpr, | ||
127 | prtd->period_ptr); | ||
128 | ssc_writex(params->ssc->regs, params->pdc->xcr, | ||
129 | prtd->period_size / params->pdc_xfer_size); | ||
130 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
131 | params->mask->pdc_enable); | ||
132 | } | ||
133 | |||
134 | |||
135 | if (ssc_sr & params->mask->ssc_endx) { | ||
136 | /* Load the PDC next pointer and counter registers */ | ||
137 | prtd->period_ptr += prtd->period_size; | ||
138 | if (prtd->period_ptr >= prtd->dma_buffer_end) | ||
139 | prtd->period_ptr = prtd->dma_buffer; | ||
140 | ssc_writex(params->ssc->regs, params->pdc->xnpr, | ||
141 | prtd->period_ptr); | ||
142 | ssc_writex(params->ssc->regs, params->pdc->xncr, | ||
143 | prtd->period_size / params->pdc_xfer_size); | ||
144 | } | ||
145 | |||
146 | |||
147 | snd_pcm_period_elapsed(substream); | ||
148 | } | ||
149 | |||
150 | |||
151 | |||
152 | /*--------------------------------------------------------------------------*\ | ||
153 | * PCM operations | ||
154 | \*--------------------------------------------------------------------------*/ | ||
155 | static int at32_pcm_hw_params(struct snd_pcm_substream *substream, | ||
156 | struct snd_pcm_hw_params *params) | ||
157 | { | ||
158 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
159 | struct at32_runtime_data *prtd = runtime->private_data; | ||
160 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
161 | |||
162 | /* this may get called several times by oss emulation | ||
163 | * with different params | ||
164 | */ | ||
165 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
166 | runtime->dma_bytes = params_buffer_bytes(params); | ||
167 | |||
168 | prtd->params = rtd->dai->cpu_dai->dma_data; | ||
169 | prtd->params->dma_intr_handler = at32_pcm_dma_irq; | ||
170 | |||
171 | prtd->dma_buffer = runtime->dma_addr; | ||
172 | prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; | ||
173 | prtd->period_size = params_period_bytes(params); | ||
174 | |||
175 | pr_debug("hw_params: DMA for %s initialized " | ||
176 | "(dma_bytes=%ld, period_size=%ld)\n", | ||
177 | prtd->params->name, runtime->dma_bytes, prtd->period_size); | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | |||
183 | |||
184 | static int at32_pcm_hw_free(struct snd_pcm_substream *substream) | ||
185 | { | ||
186 | struct at32_runtime_data *prtd = substream->runtime->private_data; | ||
187 | struct at32_pcm_dma_params *params = prtd->params; | ||
188 | |||
189 | if (params != NULL) { | ||
190 | ssc_writex(params->ssc->regs, SSC_PDC_PTCR, | ||
191 | params->mask->pdc_disable); | ||
192 | prtd->params->dma_intr_handler = NULL; | ||
193 | } | ||
194 | |||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | |||
199 | |||
200 | static int at32_pcm_prepare(struct snd_pcm_substream *substream) | ||
201 | { | ||
202 | struct at32_runtime_data *prtd = substream->runtime->private_data; | ||
203 | struct at32_pcm_dma_params *params = prtd->params; | ||
204 | |||
205 | ssc_writex(params->ssc->regs, SSC_IDR, | ||
206 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
207 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
208 | params->mask->pdc_disable); | ||
209 | |||
210 | return 0; | ||
211 | } | ||
212 | |||
213 | |||
214 | static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | ||
215 | { | ||
216 | struct snd_pcm_runtime *rtd = substream->runtime; | ||
217 | struct at32_runtime_data *prtd = rtd->private_data; | ||
218 | struct at32_pcm_dma_params *params = prtd->params; | ||
219 | int ret = 0; | ||
220 | |||
221 | pr_debug("at32_pcm_trigger: buffer_size = %ld, " | ||
222 | "dma_area = %p, dma_bytes = %ld\n", | ||
223 | rtd->buffer_size, rtd->dma_area, rtd->dma_bytes); | ||
224 | |||
225 | switch (cmd) { | ||
226 | case SNDRV_PCM_TRIGGER_START: | ||
227 | prtd->period_ptr = prtd->dma_buffer; | ||
228 | |||
229 | ssc_writex(params->ssc->regs, params->pdc->xpr, | ||
230 | prtd->period_ptr); | ||
231 | ssc_writex(params->ssc->regs, params->pdc->xcr, | ||
232 | prtd->period_size / params->pdc_xfer_size); | ||
233 | |||
234 | prtd->period_ptr += prtd->period_size; | ||
235 | ssc_writex(params->ssc->regs, params->pdc->xnpr, | ||
236 | prtd->period_ptr); | ||
237 | ssc_writex(params->ssc->regs, params->pdc->xncr, | ||
238 | prtd->period_size / params->pdc_xfer_size); | ||
239 | |||
240 | pr_debug("trigger: period_ptr=%lx, xpr=%x, " | ||
241 | "xcr=%d, xnpr=%x, xncr=%d\n", | ||
242 | (unsigned long)prtd->period_ptr, | ||
243 | ssc_readx(params->ssc->regs, params->pdc->xpr), | ||
244 | ssc_readx(params->ssc->regs, params->pdc->xcr), | ||
245 | ssc_readx(params->ssc->regs, params->pdc->xnpr), | ||
246 | ssc_readx(params->ssc->regs, params->pdc->xncr)); | ||
247 | |||
248 | ssc_writex(params->ssc->regs, SSC_IER, | ||
249 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
250 | ssc_writex(params->ssc->regs, SSC_PDC_PTCR, | ||
251 | params->mask->pdc_enable); | ||
252 | |||
253 | pr_debug("sr=%x, imr=%x\n", | ||
254 | ssc_readx(params->ssc->regs, SSC_SR), | ||
255 | ssc_readx(params->ssc->regs, SSC_IER)); | ||
256 | break; /* SNDRV_PCM_TRIGGER_START */ | ||
257 | |||
258 | |||
259 | |||
260 | case SNDRV_PCM_TRIGGER_STOP: | ||
261 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
262 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
263 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
264 | params->mask->pdc_disable); | ||
265 | break; | ||
266 | |||
267 | |||
268 | case SNDRV_PCM_TRIGGER_RESUME: | ||
269 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
270 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
271 | params->mask->pdc_enable); | ||
272 | break; | ||
273 | |||
274 | default: | ||
275 | ret = -EINVAL; | ||
276 | } | ||
277 | |||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | |||
282 | |||
283 | static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream) | ||
284 | { | ||
285 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
286 | struct at32_runtime_data *prtd = runtime->private_data; | ||
287 | struct at32_pcm_dma_params *params = prtd->params; | ||
288 | dma_addr_t ptr; | ||
289 | snd_pcm_uframes_t x; | ||
290 | |||
291 | ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr); | ||
292 | x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); | ||
293 | |||
294 | if (x == runtime->buffer_size) | ||
295 | x = 0; | ||
296 | |||
297 | return x; | ||
298 | } | ||
299 | |||
300 | |||
301 | |||
302 | static int at32_pcm_open(struct snd_pcm_substream *substream) | ||
303 | { | ||
304 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
305 | struct at32_runtime_data *prtd; | ||
306 | int ret = 0; | ||
307 | |||
308 | snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware); | ||
309 | |||
310 | /* ensure that buffer size is a multiple of period size */ | ||
311 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
312 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
313 | if (ret < 0) | ||
314 | goto out; | ||
315 | |||
316 | prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); | ||
317 | if (prtd == NULL) { | ||
318 | ret = -ENOMEM; | ||
319 | goto out; | ||
320 | } | ||
321 | runtime->private_data = prtd; | ||
322 | |||
323 | |||
324 | out: | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | static int at32_pcm_close(struct snd_pcm_substream *substream) | ||
331 | { | ||
332 | struct at32_runtime_data *prtd = substream->runtime->private_data; | ||
333 | |||
334 | kfree(prtd); | ||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | |||
339 | static int at32_pcm_mmap(struct snd_pcm_substream *substream, | ||
340 | struct vm_area_struct *vma) | ||
341 | { | ||
342 | return remap_pfn_range(vma, vma->vm_start, | ||
343 | substream->dma_buffer.addr >> PAGE_SHIFT, | ||
344 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
345 | } | ||
346 | |||
347 | |||
348 | |||
349 | static struct snd_pcm_ops at32_pcm_ops = { | ||
350 | .open = at32_pcm_open, | ||
351 | .close = at32_pcm_close, | ||
352 | .ioctl = snd_pcm_lib_ioctl, | ||
353 | .hw_params = at32_pcm_hw_params, | ||
354 | .hw_free = at32_pcm_hw_free, | ||
355 | .prepare = at32_pcm_prepare, | ||
356 | .trigger = at32_pcm_trigger, | ||
357 | .pointer = at32_pcm_pointer, | ||
358 | .mmap = at32_pcm_mmap, | ||
359 | }; | ||
360 | |||
361 | |||
362 | |||
363 | /*--------------------------------------------------------------------------*\ | ||
364 | * ASoC platform driver | ||
365 | \*--------------------------------------------------------------------------*/ | ||
366 | static u64 at32_pcm_dmamask = 0xffffffff; | ||
367 | |||
368 | static int at32_pcm_new(struct snd_card *card, | ||
369 | struct snd_soc_dai *dai, | ||
370 | struct snd_pcm *pcm) | ||
371 | { | ||
372 | int ret = 0; | ||
373 | |||
374 | if (!card->dev->dma_mask) | ||
375 | card->dev->dma_mask = &at32_pcm_dmamask; | ||
376 | if (!card->dev->coherent_dma_mask) | ||
377 | card->dev->coherent_dma_mask = 0xffffffff; | ||
378 | |||
379 | if (dai->playback.channels_min) { | ||
380 | ret = at32_pcm_preallocate_dma_buffer( | ||
381 | pcm, SNDRV_PCM_STREAM_PLAYBACK); | ||
382 | if (ret) | ||
383 | goto out; | ||
384 | } | ||
385 | |||
386 | if (dai->capture.channels_min) { | ||
387 | pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n"); | ||
388 | ret = at32_pcm_preallocate_dma_buffer( | ||
389 | pcm, SNDRV_PCM_STREAM_CAPTURE); | ||
390 | if (ret) | ||
391 | goto out; | ||
392 | } | ||
393 | |||
394 | |||
395 | out: | ||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | |||
400 | |||
401 | static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
402 | { | ||
403 | struct snd_pcm_substream *substream; | ||
404 | struct snd_dma_buffer *buf; | ||
405 | int stream; | ||
406 | |||
407 | for (stream = 0; stream < 2; stream++) { | ||
408 | substream = pcm->streams[stream].substream; | ||
409 | if (substream == NULL) | ||
410 | continue; | ||
411 | |||
412 | buf = &substream->dma_buffer; | ||
413 | if (!buf->area) | ||
414 | continue; | ||
415 | dma_free_coherent(pcm->card->dev, buf->bytes, | ||
416 | buf->area, buf->addr); | ||
417 | buf->area = NULL; | ||
418 | } | ||
419 | } | ||
420 | |||
421 | |||
422 | |||
423 | #ifdef CONFIG_PM | ||
424 | static int at32_pcm_suspend(struct platform_device *pdev, | ||
425 | struct snd_soc_dai *dai) | ||
426 | { | ||
427 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
428 | struct at32_runtime_data *prtd; | ||
429 | struct at32_pcm_dma_params *params; | ||
430 | |||
431 | if (runtime == NULL) | ||
432 | return 0; | ||
433 | prtd = runtime->private_data; | ||
434 | params = prtd->params; | ||
435 | |||
436 | /* Disable the PDC and save the PDC registers */ | ||
437 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
438 | params->mask->pdc_disable); | ||
439 | |||
440 | prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); | ||
441 | prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); | ||
442 | prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr); | ||
443 | prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr); | ||
444 | |||
445 | return 0; | ||
446 | } | ||
447 | |||
448 | |||
449 | |||
450 | static int at32_pcm_resume(struct platform_device *pdev, | ||
451 | struct snd_soc_dai *dai) | ||
452 | { | ||
453 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
454 | struct at32_runtime_data *prtd; | ||
455 | struct at32_pcm_dma_params *params; | ||
456 | |||
457 | if (runtime == NULL) | ||
458 | return 0; | ||
459 | prtd = runtime->private_data; | ||
460 | params = prtd->params; | ||
461 | |||
462 | /* Restore the PDC registers and enable the PDC */ | ||
463 | ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save); | ||
464 | ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save); | ||
465 | ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); | ||
466 | ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); | ||
467 | |||
468 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable); | ||
469 | return 0; | ||
470 | } | ||
471 | #else /* CONFIG_PM */ | ||
472 | # define at32_pcm_suspend NULL | ||
473 | # define at32_pcm_resume NULL | ||
474 | #endif /* CONFIG_PM */ | ||
475 | |||
476 | |||
477 | |||
478 | struct snd_soc_platform at32_soc_platform = { | ||
479 | .name = "at32-audio", | ||
480 | .pcm_ops = &at32_pcm_ops, | ||
481 | .pcm_new = at32_pcm_new, | ||
482 | .pcm_free = at32_pcm_free_dma_buffers, | ||
483 | .suspend = at32_pcm_suspend, | ||
484 | .resume = at32_pcm_resume, | ||
485 | }; | ||
486 | EXPORT_SYMBOL_GPL(at32_soc_platform); | ||
487 | |||
488 | |||
489 | |||
490 | MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>"); | ||
491 | MODULE_DESCRIPTION("Atmel AT32 PCM module"); | ||
492 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h deleted file mode 100644 index 2a52430417da..000000000000 --- a/sound/soc/at32/at32-pcm.h +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | /* sound/soc/at32/at32-pcm.h | ||
2 | * ASoC PCM interface for Atmel AT32 SoC | ||
3 | * | ||
4 | * Copyright (C) 2008 Long Range Systems | ||
5 | * Geoffrey Wossum <gwossum@acm.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __SOUND_SOC_AT32_AT32_PCM_H | ||
13 | #define __SOUND_SOC_AT32_AT32_PCM_H __FILE__ | ||
14 | |||
15 | #include <linux/atmel-ssc.h> | ||
16 | |||
17 | |||
18 | /* | ||
19 | * Registers and status bits that are required by the PCM driver | ||
20 | * TODO: Is ptcr really used? | ||
21 | */ | ||
22 | struct at32_pdc_regs { | ||
23 | u32 xpr; /* PDC RX/TX pointer */ | ||
24 | u32 xcr; /* PDC RX/TX counter */ | ||
25 | u32 xnpr; /* PDC next RX/TX pointer */ | ||
26 | u32 xncr; /* PDC next RX/TX counter */ | ||
27 | u32 ptcr; /* PDC transfer control */ | ||
28 | }; | ||
29 | |||
30 | |||
31 | |||
32 | /* | ||
33 | * SSC mask info | ||
34 | */ | ||
35 | struct at32_ssc_mask { | ||
36 | u32 ssc_enable; /* SSC RX/TX enable */ | ||
37 | u32 ssc_disable; /* SSC RX/TX disable */ | ||
38 | u32 ssc_endx; /* SSC ENDTX or ENDRX */ | ||
39 | u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */ | ||
40 | u32 pdc_enable; /* PDC RX/TX enable */ | ||
41 | u32 pdc_disable; /* PDC RX/TX disable */ | ||
42 | }; | ||
43 | |||
44 | |||
45 | |||
46 | /* | ||
47 | * This structure, shared between the PCM driver and the interface, | ||
48 | * contains all information required by the PCM driver to perform the | ||
49 | * PDC DMA operation. All fields except dma_intr_handler() are initialized | ||
50 | * by the interface. The dms_intr_handler() pointer is set by the PCM | ||
51 | * driver and called by the interface SSC interrupt handler if it is | ||
52 | * non-NULL. | ||
53 | */ | ||
54 | struct at32_pcm_dma_params { | ||
55 | char *name; /* stream identifier */ | ||
56 | int pdc_xfer_size; /* PDC counter increment in bytes */ | ||
57 | struct ssc_device *ssc; /* SSC device for stream */ | ||
58 | struct at32_pdc_regs *pdc; /* PDC register info */ | ||
59 | struct at32_ssc_mask *mask; /* SSC mask info */ | ||
60 | struct snd_pcm_substream *substream; | ||
61 | void (*dma_intr_handler) (u32, struct snd_pcm_substream *); | ||
62 | }; | ||
63 | |||
64 | |||
65 | |||
66 | /* | ||
67 | * The AT32 ASoC platform driver | ||
68 | */ | ||
69 | extern struct snd_soc_platform at32_soc_platform; | ||
70 | |||
71 | |||
72 | |||
73 | /* | ||
74 | * SSC register access (since ssc_writel() / ssc_readl() require literal name) | ||
75 | */ | ||
76 | #define ssc_readx(base, reg) (__raw_readl((base) + (reg))) | ||
77 | #define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) | ||
78 | |||
79 | #endif /* __SOUND_SOC_AT32_AT32_PCM_H */ | ||
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c deleted file mode 100644 index 4ef6492c902e..000000000000 --- a/sound/soc/at32/at32-ssc.c +++ /dev/null | |||
@@ -1,849 +0,0 @@ | |||
1 | /* sound/soc/at32/at32-ssc.c | ||
2 | * ASoC platform driver for AT32 using SSC as DAI | ||
3 | * | ||
4 | * Copyright (C) 2008 Long Range Systems | ||
5 | * Geoffrey Wossum <gwossum@acm.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * Note that this is basically a port of the sound/soc/at91-ssc.c to | ||
12 | * the AVR32 kernel. Thanks to Frank Mandarino for that code. | ||
13 | */ | ||
14 | |||
15 | /* #define DEBUG */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/atmel_pdc.h> | ||
25 | #include <linux/atmel-ssc.h> | ||
26 | |||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/pcm_params.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/soc.h> | ||
32 | |||
33 | #include "at32-pcm.h" | ||
34 | #include "at32-ssc.h" | ||
35 | |||
36 | |||
37 | |||
38 | /*-------------------------------------------------------------------------*\ | ||
39 | * Constants | ||
40 | \*-------------------------------------------------------------------------*/ | ||
41 | #define NUM_SSC_DEVICES 3 | ||
42 | |||
43 | /* | ||
44 | * SSC direction masks | ||
45 | */ | ||
46 | #define SSC_DIR_MASK_UNUSED 0 | ||
47 | #define SSC_DIR_MASK_PLAYBACK 1 | ||
48 | #define SSC_DIR_MASK_CAPTURE 2 | ||
49 | |||
50 | /* | ||
51 | * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These | ||
52 | * are expected to be used with SSC_BF | ||
53 | */ | ||
54 | /* START bit field values */ | ||
55 | #define SSC_START_CONTINUOUS 0 | ||
56 | #define SSC_START_TX_RX 1 | ||
57 | #define SSC_START_LOW_RF 2 | ||
58 | #define SSC_START_HIGH_RF 3 | ||
59 | #define SSC_START_FALLING_RF 4 | ||
60 | #define SSC_START_RISING_RF 5 | ||
61 | #define SSC_START_LEVEL_RF 6 | ||
62 | #define SSC_START_EDGE_RF 7 | ||
63 | #define SSS_START_COMPARE_0 8 | ||
64 | |||
65 | /* CKI bit field values */ | ||
66 | #define SSC_CKI_FALLING 0 | ||
67 | #define SSC_CKI_RISING 1 | ||
68 | |||
69 | /* CKO bit field values */ | ||
70 | #define SSC_CKO_NONE 0 | ||
71 | #define SSC_CKO_CONTINUOUS 1 | ||
72 | #define SSC_CKO_TRANSFER 2 | ||
73 | |||
74 | /* CKS bit field values */ | ||
75 | #define SSC_CKS_DIV 0 | ||
76 | #define SSC_CKS_CLOCK 1 | ||
77 | #define SSC_CKS_PIN 2 | ||
78 | |||
79 | /* FSEDGE bit field values */ | ||
80 | #define SSC_FSEDGE_POSITIVE 0 | ||
81 | #define SSC_FSEDGE_NEGATIVE 1 | ||
82 | |||
83 | /* FSOS bit field values */ | ||
84 | #define SSC_FSOS_NONE 0 | ||
85 | #define SSC_FSOS_NEGATIVE 1 | ||
86 | #define SSC_FSOS_POSITIVE 2 | ||
87 | #define SSC_FSOS_LOW 3 | ||
88 | #define SSC_FSOS_HIGH 4 | ||
89 | #define SSC_FSOS_TOGGLE 5 | ||
90 | |||
91 | #define START_DELAY 1 | ||
92 | |||
93 | |||
94 | |||
95 | /*-------------------------------------------------------------------------*\ | ||
96 | * Module data | ||
97 | \*-------------------------------------------------------------------------*/ | ||
98 | /* | ||
99 | * SSC PDC registered required by the PCM DMA engine | ||
100 | */ | ||
101 | static struct at32_pdc_regs pdc_tx_reg = { | ||
102 | .xpr = SSC_PDC_TPR, | ||
103 | .xcr = SSC_PDC_TCR, | ||
104 | .xnpr = SSC_PDC_TNPR, | ||
105 | .xncr = SSC_PDC_TNCR, | ||
106 | }; | ||
107 | |||
108 | |||
109 | |||
110 | static struct at32_pdc_regs pdc_rx_reg = { | ||
111 | .xpr = SSC_PDC_RPR, | ||
112 | .xcr = SSC_PDC_RCR, | ||
113 | .xnpr = SSC_PDC_RNPR, | ||
114 | .xncr = SSC_PDC_RNCR, | ||
115 | }; | ||
116 | |||
117 | |||
118 | |||
119 | /* | ||
120 | * SSC and PDC status bits for transmit and receive | ||
121 | */ | ||
122 | static struct at32_ssc_mask ssc_tx_mask = { | ||
123 | .ssc_enable = SSC_BIT(CR_TXEN), | ||
124 | .ssc_disable = SSC_BIT(CR_TXDIS), | ||
125 | .ssc_endx = SSC_BIT(SR_ENDTX), | ||
126 | .ssc_endbuf = SSC_BIT(SR_TXBUFE), | ||
127 | .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN), | ||
128 | .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS), | ||
129 | }; | ||
130 | |||
131 | |||
132 | |||
133 | static struct at32_ssc_mask ssc_rx_mask = { | ||
134 | .ssc_enable = SSC_BIT(CR_RXEN), | ||
135 | .ssc_disable = SSC_BIT(CR_RXDIS), | ||
136 | .ssc_endx = SSC_BIT(SR_ENDRX), | ||
137 | .ssc_endbuf = SSC_BIT(SR_RXBUFF), | ||
138 | .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN), | ||
139 | .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS), | ||
140 | }; | ||
141 | |||
142 | |||
143 | |||
144 | /* | ||
145 | * DMA parameters for each SSC | ||
146 | */ | ||
147 | static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { | ||
148 | { | ||
149 | { | ||
150 | .name = "SSC0 PCM out", | ||
151 | .pdc = &pdc_tx_reg, | ||
152 | .mask = &ssc_tx_mask, | ||
153 | }, | ||
154 | { | ||
155 | .name = "SSC0 PCM in", | ||
156 | .pdc = &pdc_rx_reg, | ||
157 | .mask = &ssc_rx_mask, | ||
158 | }, | ||
159 | }, | ||
160 | { | ||
161 | { | ||
162 | .name = "SSC1 PCM out", | ||
163 | .pdc = &pdc_tx_reg, | ||
164 | .mask = &ssc_tx_mask, | ||
165 | }, | ||
166 | { | ||
167 | .name = "SSC1 PCM in", | ||
168 | .pdc = &pdc_rx_reg, | ||
169 | .mask = &ssc_rx_mask, | ||
170 | }, | ||
171 | }, | ||
172 | { | ||
173 | { | ||
174 | .name = "SSC2 PCM out", | ||
175 | .pdc = &pdc_tx_reg, | ||
176 | .mask = &ssc_tx_mask, | ||
177 | }, | ||
178 | { | ||
179 | .name = "SSC2 PCM in", | ||
180 | .pdc = &pdc_rx_reg, | ||
181 | .mask = &ssc_rx_mask, | ||
182 | }, | ||
183 | }, | ||
184 | }; | ||
185 | |||
186 | |||
187 | |||
188 | static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = { | ||
189 | { | ||
190 | .name = "ssc0", | ||
191 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock), | ||
192 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
193 | .initialized = 0, | ||
194 | }, | ||
195 | { | ||
196 | .name = "ssc1", | ||
197 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), | ||
198 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
199 | .initialized = 0, | ||
200 | }, | ||
201 | { | ||
202 | .name = "ssc2", | ||
203 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock), | ||
204 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
205 | .initialized = 0, | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | |||
210 | |||
211 | |||
212 | /*-------------------------------------------------------------------------*\ | ||
213 | * ISR | ||
214 | \*-------------------------------------------------------------------------*/ | ||
215 | /* | ||
216 | * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt | ||
217 | * handler in the PCM driver. | ||
218 | */ | ||
219 | static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id) | ||
220 | { | ||
221 | struct at32_ssc_info *ssc_p = dev_id; | ||
222 | struct at32_pcm_dma_params *dma_params; | ||
223 | u32 ssc_sr; | ||
224 | u32 ssc_substream_mask; | ||
225 | int i; | ||
226 | |||
227 | ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) & | ||
228 | ssc_readl(ssc_p->ssc->regs, IMR)); | ||
229 | |||
230 | /* | ||
231 | * Loop through substreams attached to this SSC. If a DMA-related | ||
232 | * interrupt occured on that substream, call the DMA interrupt | ||
233 | * handler function, if one has been registered in the dma_param | ||
234 | * structure by the PCM driver. | ||
235 | */ | ||
236 | for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) { | ||
237 | dma_params = ssc_p->dma_params[i]; | ||
238 | |||
239 | if ((dma_params != NULL) && | ||
240 | (dma_params->dma_intr_handler != NULL)) { | ||
241 | ssc_substream_mask = (dma_params->mask->ssc_endx | | ||
242 | dma_params->mask->ssc_endbuf); | ||
243 | if (ssc_sr & ssc_substream_mask) { | ||
244 | dma_params->dma_intr_handler(ssc_sr, | ||
245 | dma_params-> | ||
246 | substream); | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | |||
252 | return IRQ_HANDLED; | ||
253 | } | ||
254 | |||
255 | /*-------------------------------------------------------------------------*\ | ||
256 | * DAI functions | ||
257 | \*-------------------------------------------------------------------------*/ | ||
258 | /* | ||
259 | * Startup. Only that one substream allowed in each direction. | ||
260 | */ | ||
261 | static int at32_ssc_startup(struct snd_pcm_substream *substream) | ||
262 | { | ||
263 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
264 | struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
265 | int dir_mask; | ||
266 | |||
267 | dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | ||
268 | SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE); | ||
269 | |||
270 | spin_lock_irq(&ssc_p->lock); | ||
271 | if (ssc_p->dir_mask & dir_mask) { | ||
272 | spin_unlock_irq(&ssc_p->lock); | ||
273 | return -EBUSY; | ||
274 | } | ||
275 | ssc_p->dir_mask |= dir_mask; | ||
276 | spin_unlock_irq(&ssc_p->lock); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | |||
282 | |||
283 | /* | ||
284 | * Shutdown. Clear DMA parameters and shutdown the SSC if there | ||
285 | * are no other substreams open. | ||
286 | */ | ||
287 | static void at32_ssc_shutdown(struct snd_pcm_substream *substream) | ||
288 | { | ||
289 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
290 | struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
291 | struct at32_pcm_dma_params *dma_params; | ||
292 | int dir_mask; | ||
293 | |||
294 | dma_params = ssc_p->dma_params[substream->stream]; | ||
295 | |||
296 | if (dma_params != NULL) { | ||
297 | ssc_writel(dma_params->ssc->regs, CR, | ||
298 | dma_params->mask->ssc_disable); | ||
299 | pr_debug("%s disabled SSC_SR=0x%08x\n", | ||
300 | (substream->stream ? "receiver" : "transmit"), | ||
301 | ssc_readl(ssc_p->ssc->regs, SR)); | ||
302 | |||
303 | dma_params->ssc = NULL; | ||
304 | dma_params->substream = NULL; | ||
305 | ssc_p->dma_params[substream->stream] = NULL; | ||
306 | } | ||
307 | |||
308 | |||
309 | dir_mask = 1 << substream->stream; | ||
310 | spin_lock_irq(&ssc_p->lock); | ||
311 | ssc_p->dir_mask &= ~dir_mask; | ||
312 | if (!ssc_p->dir_mask) { | ||
313 | /* Shutdown the SSC clock */ | ||
314 | pr_debug("at32-ssc: Stopping user %d clock\n", | ||
315 | ssc_p->ssc->user); | ||
316 | clk_disable(ssc_p->ssc->clk); | ||
317 | |||
318 | if (ssc_p->initialized) { | ||
319 | free_irq(ssc_p->ssc->irq, ssc_p); | ||
320 | ssc_p->initialized = 0; | ||
321 | } | ||
322 | |||
323 | /* Reset the SSC */ | ||
324 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | ||
325 | |||
326 | /* clear the SSC dividers */ | ||
327 | ssc_p->cmr_div = 0; | ||
328 | ssc_p->tcmr_period = 0; | ||
329 | ssc_p->rcmr_period = 0; | ||
330 | } | ||
331 | spin_unlock_irq(&ssc_p->lock); | ||
332 | } | ||
333 | |||
334 | |||
335 | |||
336 | /* | ||
337 | * Set the SSC system clock rate | ||
338 | */ | ||
339 | static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
340 | int clk_id, unsigned int freq, int dir) | ||
341 | { | ||
342 | /* TODO: What the heck do I do here? */ | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | |||
347 | |||
348 | /* | ||
349 | * Record DAI format for use by hw_params() | ||
350 | */ | ||
351 | static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
352 | unsigned int fmt) | ||
353 | { | ||
354 | struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
355 | |||
356 | ssc_p->daifmt = fmt; | ||
357 | return 0; | ||
358 | } | ||
359 | |||
360 | |||
361 | |||
362 | /* | ||
363 | * Record SSC clock dividers for use in hw_params() | ||
364 | */ | ||
365 | static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | ||
366 | int div_id, int div) | ||
367 | { | ||
368 | struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
369 | |||
370 | switch (div_id) { | ||
371 | case AT32_SSC_CMR_DIV: | ||
372 | /* | ||
373 | * The same master clock divider is used for both | ||
374 | * transmit and receive, so if a value has already | ||
375 | * been set, it must match this value | ||
376 | */ | ||
377 | if (ssc_p->cmr_div == 0) | ||
378 | ssc_p->cmr_div = div; | ||
379 | else if (div != ssc_p->cmr_div) | ||
380 | return -EBUSY; | ||
381 | break; | ||
382 | |||
383 | case AT32_SSC_TCMR_PERIOD: | ||
384 | ssc_p->tcmr_period = div; | ||
385 | break; | ||
386 | |||
387 | case AT32_SSC_RCMR_PERIOD: | ||
388 | ssc_p->rcmr_period = div; | ||
389 | break; | ||
390 | |||
391 | default: | ||
392 | return -EINVAL; | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | |||
399 | |||
400 | /* | ||
401 | * Configure the SSC | ||
402 | */ | ||
403 | static int at32_ssc_hw_params(struct snd_pcm_substream *substream, | ||
404 | struct snd_pcm_hw_params *params) | ||
405 | { | ||
406 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
407 | int id = rtd->dai->cpu_dai->id; | ||
408 | struct at32_ssc_info *ssc_p = &ssc_info[id]; | ||
409 | struct at32_pcm_dma_params *dma_params; | ||
410 | int channels, bits; | ||
411 | u32 tfmr, rfmr, tcmr, rcmr; | ||
412 | int start_event; | ||
413 | int ret; | ||
414 | |||
415 | |||
416 | /* | ||
417 | * Currently, there is only one set of dma_params for each direction. | ||
418 | * If more are added, this code will have to be changed to select | ||
419 | * the proper set | ||
420 | */ | ||
421 | dma_params = &ssc_dma_params[id][substream->stream]; | ||
422 | dma_params->ssc = ssc_p->ssc; | ||
423 | dma_params->substream = substream; | ||
424 | |||
425 | ssc_p->dma_params[substream->stream] = dma_params; | ||
426 | |||
427 | |||
428 | /* | ||
429 | * The cpu_dai->dma_data field is only used to communicate the | ||
430 | * appropriate DMA parameters to the PCM driver's hw_params() | ||
431 | * function. It should not be used for other purposes as it | ||
432 | * is common to all substreams. | ||
433 | */ | ||
434 | rtd->dai->cpu_dai->dma_data = dma_params; | ||
435 | |||
436 | channels = params_channels(params); | ||
437 | |||
438 | |||
439 | /* | ||
440 | * Determine sample size in bits and the PDC increment | ||
441 | */ | ||
442 | switch (params_format(params)) { | ||
443 | case SNDRV_PCM_FORMAT_S8: | ||
444 | bits = 8; | ||
445 | dma_params->pdc_xfer_size = 1; | ||
446 | break; | ||
447 | |||
448 | case SNDRV_PCM_FORMAT_S16: | ||
449 | bits = 16; | ||
450 | dma_params->pdc_xfer_size = 2; | ||
451 | break; | ||
452 | |||
453 | case SNDRV_PCM_FORMAT_S24: | ||
454 | bits = 24; | ||
455 | dma_params->pdc_xfer_size = 4; | ||
456 | break; | ||
457 | |||
458 | case SNDRV_PCM_FORMAT_S32: | ||
459 | bits = 32; | ||
460 | dma_params->pdc_xfer_size = 4; | ||
461 | break; | ||
462 | |||
463 | default: | ||
464 | pr_warning("at32-ssc: Unsupported PCM format %d", | ||
465 | params_format(params)); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n", | ||
469 | bits, dma_params->pdc_xfer_size, channels); | ||
470 | |||
471 | |||
472 | /* | ||
473 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
474 | * to the size of the Frame Mode Register FSLEN field. | ||
475 | */ | ||
476 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) | ||
477 | if (bits > 16) { | ||
478 | pr_warning("at32-ssc: " | ||
479 | "sample size %d is too large for I2S\n", | ||
480 | bits); | ||
481 | return -EINVAL; | ||
482 | } | ||
483 | |||
484 | |||
485 | /* | ||
486 | * Compute the SSC register settings | ||
487 | */ | ||
488 | switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK | | ||
489 | SND_SOC_DAIFMT_MASTER_MASK)) { | ||
490 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: | ||
491 | /* | ||
492 | * I2S format, SSC provides BCLK and LRS clocks. | ||
493 | * | ||
494 | * The SSC transmit and receive clocks are generated from the | ||
495 | * MCK divider, and the BCLK signal is output on the SSC TK line | ||
496 | */ | ||
497 | pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n"); | ||
498 | rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | | ||
499 | SSC_BF(RCMR_STTDLY, START_DELAY) | | ||
500 | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | | ||
501 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | | ||
502 | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | | ||
503 | SSC_BF(RCMR_CKS, SSC_CKS_DIV)); | ||
504 | |||
505 | rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
506 | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | | ||
507 | SSC_BF(RFMR_FSLEN, bits - 1) | | ||
508 | SSC_BF(RFMR_DATNB, channels - 1) | | ||
509 | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); | ||
510 | |||
511 | tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | | ||
512 | SSC_BF(TCMR_STTDLY, START_DELAY) | | ||
513 | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | | ||
514 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | | ||
515 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | | ||
516 | SSC_BF(TCMR_CKS, SSC_CKS_DIV)); | ||
517 | |||
518 | tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
519 | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | | ||
520 | SSC_BF(TFMR_FSLEN, bits - 1) | | ||
521 | SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) | | ||
522 | SSC_BF(TFMR_DATLEN, bits - 1)); | ||
523 | break; | ||
524 | |||
525 | |||
526 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | ||
527 | /* | ||
528 | * I2S format, CODEC supplies BCLK and LRC clock. | ||
529 | * | ||
530 | * The SSC transmit clock is obtained from the BCLK signal | ||
531 | * on the TK line, and the SSC receive clock is generated from | ||
532 | * the transmit clock. | ||
533 | * | ||
534 | * For single channel data, one sample is transferred on the | ||
535 | * falling edge of the LRC clock. For two channel data, one | ||
536 | * sample is transferred on both edges of the LRC clock. | ||
537 | */ | ||
538 | pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n"); | ||
539 | start_event = ((channels == 1) ? | ||
540 | SSC_START_FALLING_RF : SSC_START_EDGE_RF); | ||
541 | |||
542 | rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) | | ||
543 | SSC_BF(RCMR_START, start_event) | | ||
544 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | | ||
545 | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | | ||
546 | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK)); | ||
547 | |||
548 | rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
549 | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | | ||
550 | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); | ||
551 | |||
552 | tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) | | ||
553 | SSC_BF(TCMR_START, start_event) | | ||
554 | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | | ||
555 | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | | ||
556 | SSC_BF(TCMR_CKS, SSC_CKS_PIN)); | ||
557 | |||
558 | tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
559 | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | | ||
560 | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1)); | ||
561 | break; | ||
562 | |||
563 | |||
564 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | ||
565 | /* | ||
566 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | ||
567 | * | ||
568 | * The SSC transmit and receive clocks are generated from the | ||
569 | * MCK divider, and the BCLK signal is output on the SSC TK line | ||
570 | */ | ||
571 | pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n"); | ||
572 | rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | | ||
573 | SSC_BF(RCMR_STTDLY, 1) | | ||
574 | SSC_BF(RCMR_START, SSC_START_RISING_RF) | | ||
575 | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | | ||
576 | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | | ||
577 | SSC_BF(RCMR_CKS, SSC_CKS_DIV)); | ||
578 | |||
579 | rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
580 | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | | ||
581 | SSC_BF(RFMR_DATNB, channels - 1) | | ||
582 | SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1)); | ||
583 | |||
584 | tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | | ||
585 | SSC_BF(TCMR_STTDLY, 1) | | ||
586 | SSC_BF(TCMR_START, SSC_START_RISING_RF) | | ||
587 | SSC_BF(TCMR_CKI, SSC_CKI_RISING) | | ||
588 | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | | ||
589 | SSC_BF(TCMR_CKS, SSC_CKS_DIV)); | ||
590 | |||
591 | tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | | ||
592 | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | | ||
593 | SSC_BF(TFMR_DATNB, channels - 1) | | ||
594 | SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1)); | ||
595 | break; | ||
596 | |||
597 | |||
598 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: | ||
599 | default: | ||
600 | pr_warning("at32-ssc: unsupported DAI format 0x%x\n", | ||
601 | ssc_p->daifmt); | ||
602 | return -EINVAL; | ||
603 | break; | ||
604 | } | ||
605 | pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", | ||
606 | rcmr, rfmr, tcmr, tfmr); | ||
607 | |||
608 | |||
609 | if (!ssc_p->initialized) { | ||
610 | /* enable peripheral clock */ | ||
611 | pr_debug("at32-ssc: Starting clock\n"); | ||
612 | clk_enable(ssc_p->ssc->clk); | ||
613 | |||
614 | /* Reset the SSC and its PDC registers */ | ||
615 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | ||
616 | |||
617 | ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); | ||
618 | ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); | ||
619 | ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); | ||
620 | ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); | ||
621 | |||
622 | ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); | ||
623 | ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); | ||
624 | ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); | ||
625 | ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); | ||
626 | |||
627 | ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0, | ||
628 | ssc_p->name, ssc_p); | ||
629 | if (ret < 0) { | ||
630 | pr_warning("at32-ssc: request irq failed (%d)\n", ret); | ||
631 | pr_debug("at32-ssc: Stopping clock\n"); | ||
632 | clk_disable(ssc_p->ssc->clk); | ||
633 | return ret; | ||
634 | } | ||
635 | |||
636 | ssc_p->initialized = 1; | ||
637 | } | ||
638 | |||
639 | /* Set SSC clock mode register */ | ||
640 | ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); | ||
641 | |||
642 | /* set receive clock mode and format */ | ||
643 | ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); | ||
644 | ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); | ||
645 | |||
646 | /* set transmit clock mode and format */ | ||
647 | ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); | ||
648 | ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); | ||
649 | |||
650 | pr_debug("at32-ssc: SSC initialized\n"); | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | |||
655 | |||
656 | static int at32_ssc_prepare(struct snd_pcm_substream *substream) | ||
657 | { | ||
658 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
659 | struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
660 | struct at32_pcm_dma_params *dma_params; | ||
661 | |||
662 | dma_params = ssc_p->dma_params[substream->stream]; | ||
663 | |||
664 | ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable); | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | |||
670 | |||
671 | #ifdef CONFIG_PM | ||
672 | static int at32_ssc_suspend(struct platform_device *pdev, | ||
673 | struct snd_soc_dai *cpu_dai) | ||
674 | { | ||
675 | struct at32_ssc_info *ssc_p; | ||
676 | |||
677 | if (!cpu_dai->active) | ||
678 | return 0; | ||
679 | |||
680 | ssc_p = &ssc_info[cpu_dai->id]; | ||
681 | |||
682 | /* Save the status register before disabling transmit and receive */ | ||
683 | ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR); | ||
684 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS)); | ||
685 | |||
686 | /* Save the current interrupt mask, then disable unmasked interrupts */ | ||
687 | ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR); | ||
688 | ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr); | ||
689 | |||
690 | ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR); | ||
691 | ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR); | ||
692 | ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR); | ||
693 | ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR); | ||
694 | ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR); | ||
695 | |||
696 | return 0; | ||
697 | } | ||
698 | |||
699 | |||
700 | |||
701 | static int at32_ssc_resume(struct platform_device *pdev, | ||
702 | struct snd_soc_dai *cpu_dai) | ||
703 | { | ||
704 | struct at32_ssc_info *ssc_p; | ||
705 | u32 cr; | ||
706 | |||
707 | if (!cpu_dai->active) | ||
708 | return 0; | ||
709 | |||
710 | ssc_p = &ssc_info[cpu_dai->id]; | ||
711 | |||
712 | /* restore SSC register settings */ | ||
713 | ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr); | ||
714 | ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr); | ||
715 | ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr); | ||
716 | ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr); | ||
717 | ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr); | ||
718 | |||
719 | /* re-enable interrupts */ | ||
720 | ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr); | ||
721 | |||
722 | /* Re-enable recieve and transmit as appropriate */ | ||
723 | cr = 0; | ||
724 | cr |= | ||
725 | (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0; | ||
726 | cr |= | ||
727 | (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0; | ||
728 | ssc_writel(ssc_p->ssc->regs, CR, cr); | ||
729 | |||
730 | return 0; | ||
731 | } | ||
732 | #else /* CONFIG_PM */ | ||
733 | # define at32_ssc_suspend NULL | ||
734 | # define at32_ssc_resume NULL | ||
735 | #endif /* CONFIG_PM */ | ||
736 | |||
737 | |||
738 | #define AT32_SSC_RATES \ | ||
739 | (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \ | ||
740 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
741 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
742 | |||
743 | |||
744 | #define AT32_SSC_FORMATS \ | ||
745 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \ | ||
746 | SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32) | ||
747 | |||
748 | |||
749 | struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = { | ||
750 | { | ||
751 | .name = "at32-ssc0", | ||
752 | .id = 0, | ||
753 | .type = SND_SOC_DAI_PCM, | ||
754 | .suspend = at32_ssc_suspend, | ||
755 | .resume = at32_ssc_resume, | ||
756 | .playback = { | ||
757 | .channels_min = 1, | ||
758 | .channels_max = 2, | ||
759 | .rates = AT32_SSC_RATES, | ||
760 | .formats = AT32_SSC_FORMATS, | ||
761 | }, | ||
762 | .capture = { | ||
763 | .channels_min = 1, | ||
764 | .channels_max = 2, | ||
765 | .rates = AT32_SSC_RATES, | ||
766 | .formats = AT32_SSC_FORMATS, | ||
767 | }, | ||
768 | .ops = { | ||
769 | .startup = at32_ssc_startup, | ||
770 | .shutdown = at32_ssc_shutdown, | ||
771 | .prepare = at32_ssc_prepare, | ||
772 | .hw_params = at32_ssc_hw_params, | ||
773 | }, | ||
774 | .dai_ops = { | ||
775 | .set_sysclk = at32_ssc_set_dai_sysclk, | ||
776 | .set_fmt = at32_ssc_set_dai_fmt, | ||
777 | .set_clkdiv = at32_ssc_set_dai_clkdiv, | ||
778 | }, | ||
779 | .private_data = &ssc_info[0], | ||
780 | }, | ||
781 | { | ||
782 | .name = "at32-ssc1", | ||
783 | .id = 1, | ||
784 | .type = SND_SOC_DAI_PCM, | ||
785 | .suspend = at32_ssc_suspend, | ||
786 | .resume = at32_ssc_resume, | ||
787 | .playback = { | ||
788 | .channels_min = 1, | ||
789 | .channels_max = 2, | ||
790 | .rates = AT32_SSC_RATES, | ||
791 | .formats = AT32_SSC_FORMATS, | ||
792 | }, | ||
793 | .capture = { | ||
794 | .channels_min = 1, | ||
795 | .channels_max = 2, | ||
796 | .rates = AT32_SSC_RATES, | ||
797 | .formats = AT32_SSC_FORMATS, | ||
798 | }, | ||
799 | .ops = { | ||
800 | .startup = at32_ssc_startup, | ||
801 | .shutdown = at32_ssc_shutdown, | ||
802 | .prepare = at32_ssc_prepare, | ||
803 | .hw_params = at32_ssc_hw_params, | ||
804 | }, | ||
805 | .dai_ops = { | ||
806 | .set_sysclk = at32_ssc_set_dai_sysclk, | ||
807 | .set_fmt = at32_ssc_set_dai_fmt, | ||
808 | .set_clkdiv = at32_ssc_set_dai_clkdiv, | ||
809 | }, | ||
810 | .private_data = &ssc_info[1], | ||
811 | }, | ||
812 | { | ||
813 | .name = "at32-ssc2", | ||
814 | .id = 2, | ||
815 | .type = SND_SOC_DAI_PCM, | ||
816 | .suspend = at32_ssc_suspend, | ||
817 | .resume = at32_ssc_resume, | ||
818 | .playback = { | ||
819 | .channels_min = 1, | ||
820 | .channels_max = 2, | ||
821 | .rates = AT32_SSC_RATES, | ||
822 | .formats = AT32_SSC_FORMATS, | ||
823 | }, | ||
824 | .capture = { | ||
825 | .channels_min = 1, | ||
826 | .channels_max = 2, | ||
827 | .rates = AT32_SSC_RATES, | ||
828 | .formats = AT32_SSC_FORMATS, | ||
829 | }, | ||
830 | .ops = { | ||
831 | .startup = at32_ssc_startup, | ||
832 | .shutdown = at32_ssc_shutdown, | ||
833 | .prepare = at32_ssc_prepare, | ||
834 | .hw_params = at32_ssc_hw_params, | ||
835 | }, | ||
836 | .dai_ops = { | ||
837 | .set_sysclk = at32_ssc_set_dai_sysclk, | ||
838 | .set_fmt = at32_ssc_set_dai_fmt, | ||
839 | .set_clkdiv = at32_ssc_set_dai_clkdiv, | ||
840 | }, | ||
841 | .private_data = &ssc_info[2], | ||
842 | }, | ||
843 | }; | ||
844 | EXPORT_SYMBOL_GPL(at32_ssc_dai); | ||
845 | |||
846 | |||
847 | MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>"); | ||
848 | MODULE_DESCRIPTION("AT32 SSC ASoC Interface"); | ||
849 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h deleted file mode 100644 index 3c052dbbe460..000000000000 --- a/sound/soc/at32/at32-ssc.h +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* sound/soc/at32/at32-ssc.h | ||
2 | * ASoC SSC interface for Atmel AT32 SoC | ||
3 | * | ||
4 | * Copyright (C) 2008 Long Range Systems | ||
5 | * Geoffrey Wossum <gwossum@acm.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __SOUND_SOC_AT32_AT32_SSC_H | ||
13 | #define __SOUND_SOC_AT32_AT32_SSC_H __FILE__ | ||
14 | |||
15 | #include <linux/types.h> | ||
16 | #include <linux/atmel-ssc.h> | ||
17 | |||
18 | #include "at32-pcm.h" | ||
19 | |||
20 | |||
21 | |||
22 | struct at32_ssc_state { | ||
23 | u32 ssc_cmr; | ||
24 | u32 ssc_rcmr; | ||
25 | u32 ssc_rfmr; | ||
26 | u32 ssc_tcmr; | ||
27 | u32 ssc_tfmr; | ||
28 | u32 ssc_sr; | ||
29 | u32 ssc_imr; | ||
30 | }; | ||
31 | |||
32 | |||
33 | |||
34 | struct at32_ssc_info { | ||
35 | char *name; | ||
36 | struct ssc_device *ssc; | ||
37 | spinlock_t lock; /* lock for dir_mask */ | ||
38 | unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */ | ||
39 | unsigned short initialized; /* true if SSC has been initialized */ | ||
40 | unsigned short daifmt; | ||
41 | unsigned short cmr_div; | ||
42 | unsigned short tcmr_period; | ||
43 | unsigned short rcmr_period; | ||
44 | struct at32_pcm_dma_params *dma_params[2]; | ||
45 | struct at32_ssc_state ssc_state; | ||
46 | }; | ||
47 | |||
48 | |||
49 | /* SSC divider ids */ | ||
50 | #define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */ | ||
51 | #define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ | ||
52 | #define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ | ||
53 | |||
54 | |||
55 | extern struct snd_soc_dai at32_ssc_dai[]; | ||
56 | |||
57 | |||
58 | |||
59 | #endif /* __SOUND_SOC_AT32_AT32_SSC_H */ | ||
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig deleted file mode 100644 index 85a883299c2e..000000000000 --- a/sound/soc/at91/Kconfig +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | config SND_AT91_SOC | ||
2 | tristate "SoC Audio for the Atmel AT91 System-on-Chip" | ||
3 | depends on ARCH_AT91 | ||
4 | help | ||
5 | Say Y or M if you want to add support for codecs attached to | ||
6 | the AT91 SSC interface. You will also need | ||
7 | to select the audio interfaces to support below. | ||
8 | |||
9 | config SND_AT91_SOC_SSC | ||
10 | tristate | ||
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile deleted file mode 100644 index b817f11df286..000000000000 --- a/sound/soc/at91/Makefile +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | # AT91 Platform Support | ||
2 | snd-soc-at91-objs := at91-pcm.o | ||
3 | snd-soc-at91-ssc-objs := at91-ssc.o | ||
4 | |||
5 | obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o | ||
6 | 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 deleted file mode 100644 index 7ab48bd25e4c..000000000000 --- a/sound/soc/at91/at91-pcm.c +++ /dev/null | |||
@@ -1,434 +0,0 @@ | |||
1 | /* | ||
2 | * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC | ||
3 | * | ||
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | ||
5 | * Endrelia Technologies Inc. | ||
6 | * Created: Mar 3, 2006 | ||
7 | * | ||
8 | * Based on pxa2xx-pcm.c by: | ||
9 | * | ||
10 | * Author: Nicolas Pitre | ||
11 | * Created: Nov 30, 2004 | ||
12 | * Copyright: (C) 2004 MontaVista Software, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/dma-mapping.h> | ||
24 | #include <linux/atmel_pdc.h> | ||
25 | |||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/pcm_params.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | #include <mach/hardware.h> | ||
32 | #include <mach/at91_ssc.h> | ||
33 | |||
34 | #include "at91-pcm.h" | ||
35 | |||
36 | #if 0 | ||
37 | #define DBG(x...) printk(KERN_INFO "at91-pcm: " x) | ||
38 | #else | ||
39 | #define DBG(x...) | ||
40 | #endif | ||
41 | |||
42 | static const struct snd_pcm_hardware at91_pcm_hardware = { | ||
43 | .info = SNDRV_PCM_INFO_MMAP | | ||
44 | SNDRV_PCM_INFO_MMAP_VALID | | ||
45 | SNDRV_PCM_INFO_INTERLEAVED | | ||
46 | SNDRV_PCM_INFO_PAUSE, | ||
47 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
48 | .period_bytes_min = 32, | ||
49 | .period_bytes_max = 8192, | ||
50 | .periods_min = 2, | ||
51 | .periods_max = 1024, | ||
52 | .buffer_bytes_max = 32 * 1024, | ||
53 | }; | ||
54 | |||
55 | struct at91_runtime_data { | ||
56 | struct at91_pcm_dma_params *params; | ||
57 | dma_addr_t dma_buffer; /* physical address of dma buffer */ | ||
58 | dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ | ||
59 | size_t period_size; | ||
60 | dma_addr_t period_ptr; /* physical address of next period */ | ||
61 | u32 pdc_xpr_save; /* PDC register save */ | ||
62 | u32 pdc_xcr_save; | ||
63 | u32 pdc_xnpr_save; | ||
64 | u32 pdc_xncr_save; | ||
65 | }; | ||
66 | |||
67 | static void at91_pcm_dma_irq(u32 ssc_sr, | ||
68 | struct snd_pcm_substream *substream) | ||
69 | { | ||
70 | struct at91_runtime_data *prtd = substream->runtime->private_data; | ||
71 | struct at91_pcm_dma_params *params = prtd->params; | ||
72 | static int count = 0; | ||
73 | |||
74 | count++; | ||
75 | |||
76 | if (ssc_sr & params->mask->ssc_endbuf) { | ||
77 | |||
78 | printk(KERN_WARNING | ||
79 | "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n", | ||
80 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
81 | ? "underrun" : "overrun", | ||
82 | params->name, ssc_sr, count); | ||
83 | |||
84 | /* re-start the PDC */ | ||
85 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable); | ||
86 | |||
87 | prtd->period_ptr += prtd->period_size; | ||
88 | if (prtd->period_ptr >= prtd->dma_buffer_end) { | ||
89 | prtd->period_ptr = prtd->dma_buffer; | ||
90 | } | ||
91 | |||
92 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr); | ||
93 | at91_ssc_write(params->ssc_base + params->pdc->xcr, | ||
94 | prtd->period_size / params->pdc_xfer_size); | ||
95 | |||
96 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable); | ||
97 | } | ||
98 | |||
99 | if (ssc_sr & params->mask->ssc_endx) { | ||
100 | |||
101 | /* Load the PDC next pointer and counter registers */ | ||
102 | prtd->period_ptr += prtd->period_size; | ||
103 | if (prtd->period_ptr >= prtd->dma_buffer_end) { | ||
104 | prtd->period_ptr = prtd->dma_buffer; | ||
105 | } | ||
106 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, | ||
107 | prtd->period_ptr); | ||
108 | at91_ssc_write(params->ssc_base + params->pdc->xncr, | ||
109 | prtd->period_size / params->pdc_xfer_size); | ||
110 | } | ||
111 | |||
112 | snd_pcm_period_elapsed(substream); | ||
113 | } | ||
114 | |||
115 | static int at91_pcm_hw_params(struct snd_pcm_substream *substream, | ||
116 | struct snd_pcm_hw_params *params) | ||
117 | { | ||
118 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
119 | struct at91_runtime_data *prtd = runtime->private_data; | ||
120 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
121 | |||
122 | /* this may get called several times by oss emulation | ||
123 | * with different params */ | ||
124 | |||
125 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
126 | runtime->dma_bytes = params_buffer_bytes(params); | ||
127 | |||
128 | prtd->params = rtd->dai->cpu_dai->dma_data; | ||
129 | prtd->params->dma_intr_handler = at91_pcm_dma_irq; | ||
130 | |||
131 | prtd->dma_buffer = runtime->dma_addr; | ||
132 | prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; | ||
133 | prtd->period_size = params_period_bytes(params); | ||
134 | |||
135 | DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n", | ||
136 | prtd->params->name, runtime->dma_bytes, prtd->period_size); | ||
137 | return 0; | ||
138 | } | ||
139 | |||
140 | static int at91_pcm_hw_free(struct snd_pcm_substream *substream) | ||
141 | { | ||
142 | struct at91_runtime_data *prtd = substream->runtime->private_data; | ||
143 | struct at91_pcm_dma_params *params = prtd->params; | ||
144 | |||
145 | if (params != NULL) { | ||
146 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable); | ||
147 | prtd->params->dma_intr_handler = NULL; | ||
148 | } | ||
149 | |||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | static int at91_pcm_prepare(struct snd_pcm_substream *substream) | ||
154 | { | ||
155 | struct at91_runtime_data *prtd = substream->runtime->private_data; | ||
156 | struct at91_pcm_dma_params *params = prtd->params; | ||
157 | |||
158 | at91_ssc_write(params->ssc_base + AT91_SSC_IDR, | ||
159 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
160 | |||
161 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int at91_pcm_trigger(struct snd_pcm_substream *substream, | ||
166 | int cmd) | ||
167 | { | ||
168 | struct at91_runtime_data *prtd = substream->runtime->private_data; | ||
169 | struct at91_pcm_dma_params *params = prtd->params; | ||
170 | int ret = 0; | ||
171 | |||
172 | switch (cmd) { | ||
173 | case SNDRV_PCM_TRIGGER_START: | ||
174 | prtd->period_ptr = prtd->dma_buffer; | ||
175 | |||
176 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr); | ||
177 | at91_ssc_write(params->ssc_base + params->pdc->xcr, | ||
178 | prtd->period_size / params->pdc_xfer_size); | ||
179 | |||
180 | prtd->period_ptr += prtd->period_size; | ||
181 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr); | ||
182 | at91_ssc_write(params->ssc_base + params->pdc->xncr, | ||
183 | prtd->period_size / params->pdc_xfer_size); | ||
184 | |||
185 | DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n", | ||
186 | (unsigned long) prtd->period_ptr, | ||
187 | at91_ssc_read(params->ssc_base + params->pdc->xpr), | ||
188 | at91_ssc_read(params->ssc_base + params->pdc->xcr), | ||
189 | at91_ssc_read(params->ssc_base + params->pdc->xnpr), | ||
190 | at91_ssc_read(params->ssc_base + params->pdc->xncr)); | ||
191 | |||
192 | at91_ssc_write(params->ssc_base + AT91_SSC_IER, | ||
193 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
194 | |||
195 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, | ||
196 | params->mask->pdc_enable); | ||
197 | |||
198 | DBG("sr=%lx imr=%lx\n", | ||
199 | at91_ssc_read(params->ssc_base + AT91_SSC_SR), | ||
200 | at91_ssc_read(params->ssc_base + AT91_SSC_IMR)); | ||
201 | break; | ||
202 | |||
203 | case SNDRV_PCM_TRIGGER_STOP: | ||
204 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
205 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
206 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable); | ||
207 | break; | ||
208 | |||
209 | case SNDRV_PCM_TRIGGER_RESUME: | ||
210 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
211 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable); | ||
212 | break; | ||
213 | |||
214 | default: | ||
215 | ret = -EINVAL; | ||
216 | } | ||
217 | |||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static snd_pcm_uframes_t at91_pcm_pointer( | ||
222 | struct snd_pcm_substream *substream) | ||
223 | { | ||
224 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
225 | struct at91_runtime_data *prtd = runtime->private_data; | ||
226 | struct at91_pcm_dma_params *params = prtd->params; | ||
227 | dma_addr_t ptr; | ||
228 | snd_pcm_uframes_t x; | ||
229 | |||
230 | ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr); | ||
231 | x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); | ||
232 | |||
233 | if (x == runtime->buffer_size) | ||
234 | x = 0; | ||
235 | return x; | ||
236 | } | ||
237 | |||
238 | static int at91_pcm_open(struct snd_pcm_substream *substream) | ||
239 | { | ||
240 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
241 | struct at91_runtime_data *prtd; | ||
242 | int ret = 0; | ||
243 | |||
244 | snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware); | ||
245 | |||
246 | /* ensure that buffer size is a multiple of period size */ | ||
247 | ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); | ||
248 | if (ret < 0) | ||
249 | goto out; | ||
250 | |||
251 | prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL); | ||
252 | if (prtd == NULL) { | ||
253 | ret = -ENOMEM; | ||
254 | goto out; | ||
255 | } | ||
256 | runtime->private_data = prtd; | ||
257 | |||
258 | out: | ||
259 | return ret; | ||
260 | } | ||
261 | |||
262 | static int at91_pcm_close(struct snd_pcm_substream *substream) | ||
263 | { | ||
264 | struct at91_runtime_data *prtd = substream->runtime->private_data; | ||
265 | |||
266 | kfree(prtd); | ||
267 | return 0; | ||
268 | } | ||
269 | |||
270 | static int at91_pcm_mmap(struct snd_pcm_substream *substream, | ||
271 | struct vm_area_struct *vma) | ||
272 | { | ||
273 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
274 | |||
275 | return dma_mmap_writecombine(substream->pcm->card->dev, vma, | ||
276 | runtime->dma_area, | ||
277 | runtime->dma_addr, | ||
278 | runtime->dma_bytes); | ||
279 | } | ||
280 | |||
281 | struct snd_pcm_ops at91_pcm_ops = { | ||
282 | .open = at91_pcm_open, | ||
283 | .close = at91_pcm_close, | ||
284 | .ioctl = snd_pcm_lib_ioctl, | ||
285 | .hw_params = at91_pcm_hw_params, | ||
286 | .hw_free = at91_pcm_hw_free, | ||
287 | .prepare = at91_pcm_prepare, | ||
288 | .trigger = at91_pcm_trigger, | ||
289 | .pointer = at91_pcm_pointer, | ||
290 | .mmap = at91_pcm_mmap, | ||
291 | }; | ||
292 | |||
293 | static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, | ||
294 | int stream) | ||
295 | { | ||
296 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
297 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
298 | size_t size = at91_pcm_hardware.buffer_bytes_max; | ||
299 | |||
300 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
301 | buf->dev.dev = pcm->card->dev; | ||
302 | buf->private_data = NULL; | ||
303 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | ||
304 | &buf->addr, GFP_KERNEL); | ||
305 | |||
306 | DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | ||
307 | (void *) buf->area, | ||
308 | (void *) buf->addr, | ||
309 | size); | ||
310 | |||
311 | if (!buf->area) | ||
312 | return -ENOMEM; | ||
313 | |||
314 | buf->bytes = size; | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static u64 at91_pcm_dmamask = 0xffffffff; | ||
319 | |||
320 | static int at91_pcm_new(struct snd_card *card, | ||
321 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
322 | { | ||
323 | int ret = 0; | ||
324 | |||
325 | if (!card->dev->dma_mask) | ||
326 | card->dev->dma_mask = &at91_pcm_dmamask; | ||
327 | if (!card->dev->coherent_dma_mask) | ||
328 | card->dev->coherent_dma_mask = 0xffffffff; | ||
329 | |||
330 | if (dai->playback.channels_min) { | ||
331 | ret = at91_pcm_preallocate_dma_buffer(pcm, | ||
332 | SNDRV_PCM_STREAM_PLAYBACK); | ||
333 | if (ret) | ||
334 | goto out; | ||
335 | } | ||
336 | |||
337 | if (dai->capture.channels_min) { | ||
338 | ret = at91_pcm_preallocate_dma_buffer(pcm, | ||
339 | SNDRV_PCM_STREAM_CAPTURE); | ||
340 | if (ret) | ||
341 | goto out; | ||
342 | } | ||
343 | out: | ||
344 | return ret; | ||
345 | } | ||
346 | |||
347 | static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
348 | { | ||
349 | struct snd_pcm_substream *substream; | ||
350 | struct snd_dma_buffer *buf; | ||
351 | int stream; | ||
352 | |||
353 | for (stream = 0; stream < 2; stream++) { | ||
354 | substream = pcm->streams[stream].substream; | ||
355 | if (!substream) | ||
356 | continue; | ||
357 | |||
358 | buf = &substream->dma_buffer; | ||
359 | if (!buf->area) | ||
360 | continue; | ||
361 | |||
362 | dma_free_writecombine(pcm->card->dev, buf->bytes, | ||
363 | buf->area, buf->addr); | ||
364 | buf->area = NULL; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | #ifdef CONFIG_PM | ||
369 | static int at91_pcm_suspend(struct platform_device *pdev, | ||
370 | struct snd_soc_dai *dai) | ||
371 | { | ||
372 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
373 | struct at91_runtime_data *prtd; | ||
374 | struct at91_pcm_dma_params *params; | ||
375 | |||
376 | if (!runtime) | ||
377 | return 0; | ||
378 | |||
379 | prtd = runtime->private_data; | ||
380 | params = prtd->params; | ||
381 | |||
382 | /* disable the PDC and save the PDC registers */ | ||
383 | |||
384 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable); | ||
385 | |||
386 | prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr); | ||
387 | prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr); | ||
388 | prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr); | ||
389 | prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr); | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | static int at91_pcm_resume(struct platform_device *pdev, | ||
395 | struct snd_soc_dai *dai) | ||
396 | { | ||
397 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
398 | struct at91_runtime_data *prtd; | ||
399 | struct at91_pcm_dma_params *params; | ||
400 | |||
401 | if (!runtime) | ||
402 | return 0; | ||
403 | |||
404 | prtd = runtime->private_data; | ||
405 | params = prtd->params; | ||
406 | |||
407 | /* restore the PDC registers and enable the PDC */ | ||
408 | at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save); | ||
409 | at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save); | ||
410 | at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save); | ||
411 | at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save); | ||
412 | |||
413 | at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable); | ||
414 | return 0; | ||
415 | } | ||
416 | #else | ||
417 | #define at91_pcm_suspend NULL | ||
418 | #define at91_pcm_resume NULL | ||
419 | #endif | ||
420 | |||
421 | struct snd_soc_platform at91_soc_platform = { | ||
422 | .name = "at91-audio", | ||
423 | .pcm_ops = &at91_pcm_ops, | ||
424 | .pcm_new = at91_pcm_new, | ||
425 | .pcm_free = at91_pcm_free_dma_buffers, | ||
426 | .suspend = at91_pcm_suspend, | ||
427 | .resume = at91_pcm_resume, | ||
428 | }; | ||
429 | |||
430 | EXPORT_SYMBOL_GPL(at91_soc_platform); | ||
431 | |||
432 | MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>"); | ||
433 | MODULE_DESCRIPTION("Atmel AT91 PCM module"); | ||
434 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h deleted file mode 100644 index e5aada2cb102..000000000000 --- a/sound/soc/at91/at91-pcm.h +++ /dev/null | |||
@@ -1,72 +0,0 @@ | |||
1 | /* | ||
2 | * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC | ||
3 | * | ||
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | ||
5 | * Endrelia Technologies Inc. | ||
6 | * Created: Mar 3, 2006 | ||
7 | * | ||
8 | * Based on pxa2xx-pcm.h by: | ||
9 | * | ||
10 | * Author: Nicolas Pitre | ||
11 | * Created: Nov 30, 2004 | ||
12 | * Copyright: MontaVista Software, Inc. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify | ||
15 | * it under the terms of the GNU General Public License version 2 as | ||
16 | * published by the Free Software Foundation. | ||
17 | */ | ||
18 | |||
19 | #ifndef _AT91_PCM_H | ||
20 | #define _AT91_PCM_H | ||
21 | |||
22 | #include <mach/hardware.h> | ||
23 | |||
24 | struct at91_ssc_periph { | ||
25 | void __iomem *base; | ||
26 | u32 pid; | ||
27 | }; | ||
28 | |||
29 | /* | ||
30 | * Registers and status bits that are required by the PCM driver. | ||
31 | */ | ||
32 | struct at91_pdc_regs { | ||
33 | unsigned int xpr; /* PDC recv/trans pointer */ | ||
34 | unsigned int xcr; /* PDC recv/trans counter */ | ||
35 | unsigned int xnpr; /* PDC next recv/trans pointer */ | ||
36 | unsigned int xncr; /* PDC next recv/trans counter */ | ||
37 | unsigned int ptcr; /* PDC transfer control */ | ||
38 | }; | ||
39 | |||
40 | struct at91_ssc_mask { | ||
41 | u32 ssc_enable; /* SSC recv/trans enable */ | ||
42 | u32 ssc_disable; /* SSC recv/trans disable */ | ||
43 | u32 ssc_endx; /* SSC ENDTX or ENDRX */ | ||
44 | u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */ | ||
45 | u32 pdc_enable; /* PDC recv/trans enable */ | ||
46 | u32 pdc_disable; /* PDC recv/trans disable */ | ||
47 | }; | ||
48 | |||
49 | /* | ||
50 | * This structure, shared between the PCM driver and the interface, | ||
51 | * contains all information required by the PCM driver to perform the | ||
52 | * PDC DMA operation. All fields except dma_intr_handler() are initialized | ||
53 | * by the interface. The dms_intr_handler() pointer is set by the PCM | ||
54 | * driver and called by the interface SSC interrupt handler if it is | ||
55 | * non-NULL. | ||
56 | */ | ||
57 | struct at91_pcm_dma_params { | ||
58 | char *name; /* stream identifier */ | ||
59 | int pdc_xfer_size; /* PDC counter increment in bytes */ | ||
60 | void __iomem *ssc_base; /* SSC base address */ | ||
61 | struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */ | ||
62 | struct at91_ssc_mask *mask;/* SSC & PDC status bits */ | ||
63 | struct snd_pcm_substream *substream; | ||
64 | void (*dma_intr_handler)(u32, struct snd_pcm_substream *); | ||
65 | }; | ||
66 | |||
67 | extern struct snd_soc_platform at91_soc_platform; | ||
68 | |||
69 | #define at91_ssc_read(a) ((unsigned long) __raw_readl(a)) | ||
70 | #define at91_ssc_write(a,v) __raw_writel((v),(a)) | ||
71 | |||
72 | #endif /* _AT91_PCM_H */ | ||
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c deleted file mode 100644 index 1b61cc461261..000000000000 --- a/sound/soc/at91/at91-ssc.c +++ /dev/null | |||
@@ -1,791 +0,0 @@ | |||
1 | /* | ||
2 | * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver | ||
3 | * | ||
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | ||
5 | * Endrelia Technologies Inc. | ||
6 | * | ||
7 | * Based on pxa2xx Platform drivers by | ||
8 | * Liam Girdwood <lrg@slimlogic.co.uk> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/init.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/clk.h> | ||
23 | #include <linux/atmel_pdc.h> | ||
24 | |||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | #include <mach/hardware.h> | ||
32 | #include <mach/at91_pmc.h> | ||
33 | #include <mach/at91_ssc.h> | ||
34 | |||
35 | #include "at91-pcm.h" | ||
36 | #include "at91-ssc.h" | ||
37 | |||
38 | #if 0 | ||
39 | #define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x) | ||
40 | #else | ||
41 | #define DBG(x...) | ||
42 | #endif | ||
43 | |||
44 | #if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20) | ||
45 | #define NUM_SSC_DEVICES 1 | ||
46 | #else | ||
47 | #define NUM_SSC_DEVICES 3 | ||
48 | #endif | ||
49 | |||
50 | |||
51 | /* | ||
52 | * SSC PDC registers required by the PCM DMA engine. | ||
53 | */ | ||
54 | static struct at91_pdc_regs pdc_tx_reg = { | ||
55 | .xpr = ATMEL_PDC_TPR, | ||
56 | .xcr = ATMEL_PDC_TCR, | ||
57 | .xnpr = ATMEL_PDC_TNPR, | ||
58 | .xncr = ATMEL_PDC_TNCR, | ||
59 | }; | ||
60 | |||
61 | static struct at91_pdc_regs pdc_rx_reg = { | ||
62 | .xpr = ATMEL_PDC_RPR, | ||
63 | .xcr = ATMEL_PDC_RCR, | ||
64 | .xnpr = ATMEL_PDC_RNPR, | ||
65 | .xncr = ATMEL_PDC_RNCR, | ||
66 | }; | ||
67 | |||
68 | /* | ||
69 | * SSC & PDC status bits for transmit and receive. | ||
70 | */ | ||
71 | static struct at91_ssc_mask ssc_tx_mask = { | ||
72 | .ssc_enable = AT91_SSC_TXEN, | ||
73 | .ssc_disable = AT91_SSC_TXDIS, | ||
74 | .ssc_endx = AT91_SSC_ENDTX, | ||
75 | .ssc_endbuf = AT91_SSC_TXBUFE, | ||
76 | .pdc_enable = ATMEL_PDC_TXTEN, | ||
77 | .pdc_disable = ATMEL_PDC_TXTDIS, | ||
78 | }; | ||
79 | |||
80 | static struct at91_ssc_mask ssc_rx_mask = { | ||
81 | .ssc_enable = AT91_SSC_RXEN, | ||
82 | .ssc_disable = AT91_SSC_RXDIS, | ||
83 | .ssc_endx = AT91_SSC_ENDRX, | ||
84 | .ssc_endbuf = AT91_SSC_RXBUFF, | ||
85 | .pdc_enable = ATMEL_PDC_RXTEN, | ||
86 | .pdc_disable = ATMEL_PDC_RXTDIS, | ||
87 | }; | ||
88 | |||
89 | |||
90 | /* | ||
91 | * DMA parameters. | ||
92 | */ | ||
93 | static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { | ||
94 | {{ | ||
95 | .name = "SSC0 PCM out", | ||
96 | .pdc = &pdc_tx_reg, | ||
97 | .mask = &ssc_tx_mask, | ||
98 | }, | ||
99 | { | ||
100 | .name = "SSC0 PCM in", | ||
101 | .pdc = &pdc_rx_reg, | ||
102 | .mask = &ssc_rx_mask, | ||
103 | }}, | ||
104 | #if NUM_SSC_DEVICES == 3 | ||
105 | {{ | ||
106 | .name = "SSC1 PCM out", | ||
107 | .pdc = &pdc_tx_reg, | ||
108 | .mask = &ssc_tx_mask, | ||
109 | }, | ||
110 | { | ||
111 | .name = "SSC1 PCM in", | ||
112 | .pdc = &pdc_rx_reg, | ||
113 | .mask = &ssc_rx_mask, | ||
114 | }}, | ||
115 | {{ | ||
116 | .name = "SSC2 PCM out", | ||
117 | .pdc = &pdc_tx_reg, | ||
118 | .mask = &ssc_tx_mask, | ||
119 | }, | ||
120 | { | ||
121 | .name = "SSC2 PCM in", | ||
122 | .pdc = &pdc_rx_reg, | ||
123 | .mask = &ssc_rx_mask, | ||
124 | }}, | ||
125 | #endif | ||
126 | }; | ||
127 | |||
128 | struct at91_ssc_state { | ||
129 | u32 ssc_cmr; | ||
130 | u32 ssc_rcmr; | ||
131 | u32 ssc_rfmr; | ||
132 | u32 ssc_tcmr; | ||
133 | u32 ssc_tfmr; | ||
134 | u32 ssc_sr; | ||
135 | u32 ssc_imr; | ||
136 | }; | ||
137 | |||
138 | static struct at91_ssc_info { | ||
139 | char *name; | ||
140 | struct at91_ssc_periph ssc; | ||
141 | spinlock_t lock; /* lock for dir_mask */ | ||
142 | unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */ | ||
143 | unsigned short initialized; /* 1=SSC has been initialized */ | ||
144 | unsigned short daifmt; | ||
145 | unsigned short cmr_div; | ||
146 | unsigned short tcmr_period; | ||
147 | unsigned short rcmr_period; | ||
148 | struct at91_pcm_dma_params *dma_params[2]; | ||
149 | struct at91_ssc_state ssc_state; | ||
150 | |||
151 | } ssc_info[NUM_SSC_DEVICES] = { | ||
152 | { | ||
153 | .name = "ssc0", | ||
154 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock), | ||
155 | .dir_mask = 0, | ||
156 | .initialized = 0, | ||
157 | }, | ||
158 | #if NUM_SSC_DEVICES == 3 | ||
159 | { | ||
160 | .name = "ssc1", | ||
161 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), | ||
162 | .dir_mask = 0, | ||
163 | .initialized = 0, | ||
164 | }, | ||
165 | { | ||
166 | .name = "ssc2", | ||
167 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock), | ||
168 | .dir_mask = 0, | ||
169 | .initialized = 0, | ||
170 | }, | ||
171 | #endif | ||
172 | }; | ||
173 | |||
174 | static unsigned int at91_ssc_sysclk; | ||
175 | |||
176 | /* | ||
177 | * SSC interrupt handler. Passes PDC interrupts to the DMA | ||
178 | * interrupt handler in the PCM driver. | ||
179 | */ | ||
180 | static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id) | ||
181 | { | ||
182 | struct at91_ssc_info *ssc_p = dev_id; | ||
183 | struct at91_pcm_dma_params *dma_params; | ||
184 | u32 ssc_sr; | ||
185 | int i; | ||
186 | |||
187 | ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR) | ||
188 | & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR); | ||
189 | |||
190 | /* | ||
191 | * Loop through the substreams attached to this SSC. If | ||
192 | * a DMA-related interrupt occurred on that substream, call | ||
193 | * the DMA interrupt handler function, if one has been | ||
194 | * registered in the dma_params structure by the PCM driver. | ||
195 | */ | ||
196 | for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) { | ||
197 | dma_params = ssc_p->dma_params[i]; | ||
198 | |||
199 | if (dma_params != NULL && dma_params->dma_intr_handler != NULL && | ||
200 | (ssc_sr & | ||
201 | (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf))) | ||
202 | |||
203 | dma_params->dma_intr_handler(ssc_sr, dma_params->substream); | ||
204 | } | ||
205 | |||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Startup. Only that one substream allowed in each direction. | ||
211 | */ | ||
212 | static int at91_ssc_startup(struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
215 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
216 | int dir_mask; | ||
217 | |||
218 | DBG("ssc_startup: SSC_SR=0x%08lx\n", | ||
219 | at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); | ||
220 | dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2; | ||
221 | |||
222 | spin_lock_irq(&ssc_p->lock); | ||
223 | if (ssc_p->dir_mask & dir_mask) { | ||
224 | spin_unlock_irq(&ssc_p->lock); | ||
225 | return -EBUSY; | ||
226 | } | ||
227 | ssc_p->dir_mask |= dir_mask; | ||
228 | spin_unlock_irq(&ssc_p->lock); | ||
229 | |||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | /* | ||
234 | * Shutdown. Clear DMA parameters and shutdown the SSC if there | ||
235 | * are no other substreams open. | ||
236 | */ | ||
237 | static void at91_ssc_shutdown(struct snd_pcm_substream *substream) | ||
238 | { | ||
239 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
240 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
241 | struct at91_pcm_dma_params *dma_params; | ||
242 | int dir, dir_mask; | ||
243 | |||
244 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | ||
245 | dma_params = ssc_p->dma_params[dir]; | ||
246 | |||
247 | if (dma_params != NULL) { | ||
248 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, | ||
249 | dma_params->mask->ssc_disable); | ||
250 | DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"), | ||
251 | at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)); | ||
252 | |||
253 | dma_params->ssc_base = NULL; | ||
254 | dma_params->substream = NULL; | ||
255 | ssc_p->dma_params[dir] = NULL; | ||
256 | } | ||
257 | |||
258 | dir_mask = 1 << dir; | ||
259 | |||
260 | spin_lock_irq(&ssc_p->lock); | ||
261 | ssc_p->dir_mask &= ~dir_mask; | ||
262 | if (!ssc_p->dir_mask) { | ||
263 | /* Shutdown the SSC clock. */ | ||
264 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); | ||
265 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid); | ||
266 | |||
267 | if (ssc_p->initialized) { | ||
268 | free_irq(ssc_p->ssc.pid, ssc_p); | ||
269 | ssc_p->initialized = 0; | ||
270 | } | ||
271 | |||
272 | /* Reset the SSC */ | ||
273 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); | ||
274 | |||
275 | /* Clear the SSC dividers */ | ||
276 | ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; | ||
277 | } | ||
278 | spin_unlock_irq(&ssc_p->lock); | ||
279 | } | ||
280 | |||
281 | /* | ||
282 | * Record the SSC system clock rate. | ||
283 | */ | ||
284 | static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
285 | int clk_id, unsigned int freq, int dir) | ||
286 | { | ||
287 | /* | ||
288 | * The only clock supplied to the SSC is the AT91 master clock, | ||
289 | * which is only used if the SSC is generating BCLK and/or | ||
290 | * LRC clocks. | ||
291 | */ | ||
292 | switch (clk_id) { | ||
293 | case AT91_SYSCLK_MCK: | ||
294 | at91_ssc_sysclk = freq; | ||
295 | break; | ||
296 | default: | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | /* | ||
304 | * Record the DAI format for use in hw_params(). | ||
305 | */ | ||
306 | static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
307 | unsigned int fmt) | ||
308 | { | ||
309 | struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
310 | |||
311 | ssc_p->daifmt = fmt; | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Record SSC clock dividers for use in hw_params(). | ||
317 | */ | ||
318 | static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | ||
319 | int div_id, int div) | ||
320 | { | ||
321 | struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
322 | |||
323 | switch (div_id) { | ||
324 | case AT91SSC_CMR_DIV: | ||
325 | /* | ||
326 | * The same master clock divider is used for both | ||
327 | * transmit and receive, so if a value has already | ||
328 | * been set, it must match this value. | ||
329 | */ | ||
330 | if (ssc_p->cmr_div == 0) | ||
331 | ssc_p->cmr_div = div; | ||
332 | else | ||
333 | if (div != ssc_p->cmr_div) | ||
334 | return -EBUSY; | ||
335 | break; | ||
336 | |||
337 | case AT91SSC_TCMR_PERIOD: | ||
338 | ssc_p->tcmr_period = div; | ||
339 | break; | ||
340 | |||
341 | case AT91SSC_RCMR_PERIOD: | ||
342 | ssc_p->rcmr_period = div; | ||
343 | break; | ||
344 | |||
345 | default: | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | return 0; | ||
350 | } | ||
351 | |||
352 | /* | ||
353 | * Configure the SSC. | ||
354 | */ | ||
355 | static int at91_ssc_hw_params(struct snd_pcm_substream *substream, | ||
356 | struct snd_pcm_hw_params *params) | ||
357 | { | ||
358 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
359 | int id = rtd->dai->cpu_dai->id; | ||
360 | struct at91_ssc_info *ssc_p = &ssc_info[id]; | ||
361 | struct at91_pcm_dma_params *dma_params; | ||
362 | int dir, channels, bits; | ||
363 | u32 tfmr, rfmr, tcmr, rcmr; | ||
364 | int start_event; | ||
365 | int ret; | ||
366 | |||
367 | /* | ||
368 | * Currently, there is only one set of dma params for | ||
369 | * each direction. If more are added, this code will | ||
370 | * have to be changed to select the proper set. | ||
371 | */ | ||
372 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | ||
373 | |||
374 | dma_params = &ssc_dma_params[id][dir]; | ||
375 | dma_params->ssc_base = ssc_p->ssc.base; | ||
376 | dma_params->substream = substream; | ||
377 | |||
378 | ssc_p->dma_params[dir] = dma_params; | ||
379 | |||
380 | /* | ||
381 | * The cpu_dai->dma_data field is only used to communicate the | ||
382 | * appropriate DMA parameters to the pcm driver hw_params() | ||
383 | * function. It should not be used for other purposes | ||
384 | * as it is common to all substreams. | ||
385 | */ | ||
386 | rtd->dai->cpu_dai->dma_data = dma_params; | ||
387 | |||
388 | channels = params_channels(params); | ||
389 | |||
390 | /* | ||
391 | * Determine sample size in bits and the PDC increment. | ||
392 | */ | ||
393 | switch(params_format(params)) { | ||
394 | case SNDRV_PCM_FORMAT_S8: | ||
395 | bits = 8; | ||
396 | dma_params->pdc_xfer_size = 1; | ||
397 | break; | ||
398 | case SNDRV_PCM_FORMAT_S16_LE: | ||
399 | bits = 16; | ||
400 | dma_params->pdc_xfer_size = 2; | ||
401 | break; | ||
402 | case SNDRV_PCM_FORMAT_S24_LE: | ||
403 | bits = 24; | ||
404 | dma_params->pdc_xfer_size = 4; | ||
405 | break; | ||
406 | case SNDRV_PCM_FORMAT_S32_LE: | ||
407 | bits = 32; | ||
408 | dma_params->pdc_xfer_size = 4; | ||
409 | break; | ||
410 | default: | ||
411 | printk(KERN_WARNING "at91-ssc: unsupported PCM format\n"); | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | /* | ||
416 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
417 | * to the size of the Frame Mode Register FSLEN field. | ||
418 | */ | ||
419 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | ||
420 | && bits > 16) { | ||
421 | printk(KERN_WARNING | ||
422 | "at91-ssc: sample size %d is too large for I2S\n", bits); | ||
423 | return -EINVAL; | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * Compute SSC register settings. | ||
428 | */ | ||
429 | switch (ssc_p->daifmt | ||
430 | & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { | ||
431 | |||
432 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: | ||
433 | /* | ||
434 | * I2S format, SSC provides BCLK and LRC clocks. | ||
435 | * | ||
436 | * The SSC transmit and receive clocks are generated from the | ||
437 | * MCK divider, and the BCLK signal is output on the SSC TK line. | ||
438 | */ | ||
439 | rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) | ||
440 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
441 | | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START) | ||
442 | | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | ||
443 | | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | ||
444 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | ||
445 | |||
446 | rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
447 | | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS) | ||
448 | | (((bits - 1) << 16) & AT91_SSC_FSLEN) | ||
449 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
450 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
451 | | (( 0 << 5) & AT91_SSC_LOOP) | ||
452 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
453 | |||
454 | tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) | ||
455 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
456 | | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START) | ||
457 | | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI) | ||
458 | | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | ||
459 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | ||
460 | |||
461 | tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
462 | | (( 0 << 23) & AT91_SSC_FSDEN) | ||
463 | | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS) | ||
464 | | (((bits - 1) << 16) & AT91_SSC_FSLEN) | ||
465 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
466 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
467 | | (( 0 << 5) & AT91_SSC_DATDEF) | ||
468 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
469 | break; | ||
470 | |||
471 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | ||
472 | /* | ||
473 | * I2S format, CODEC supplies BCLK and LRC clocks. | ||
474 | * | ||
475 | * The SSC transmit clock is obtained from the BCLK signal on | ||
476 | * on the TK line, and the SSC receive clock is generated from the | ||
477 | * transmit clock. | ||
478 | * | ||
479 | * For single channel data, one sample is transferred on the falling | ||
480 | * edge of the LRC clock. For two channel data, one sample is | ||
481 | * transferred on both edges of the LRC clock. | ||
482 | */ | ||
483 | start_event = channels == 1 | ||
484 | ? AT91_SSC_START_FALLING_RF | ||
485 | : AT91_SSC_START_EDGE_RF; | ||
486 | |||
487 | rcmr = (( 0 << 24) & AT91_SSC_PERIOD) | ||
488 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
489 | | (( start_event ) & AT91_SSC_START) | ||
490 | | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | ||
491 | | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | ||
492 | | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS); | ||
493 | |||
494 | rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
495 | | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS) | ||
496 | | (( 0 << 16) & AT91_SSC_FSLEN) | ||
497 | | (( 0 << 8) & AT91_SSC_DATNB) | ||
498 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
499 | | (( 0 << 5) & AT91_SSC_LOOP) | ||
500 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
501 | |||
502 | tcmr = (( 0 << 24) & AT91_SSC_PERIOD) | ||
503 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
504 | | (( start_event ) & AT91_SSC_START) | ||
505 | | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI) | ||
506 | | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | ||
507 | | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS); | ||
508 | |||
509 | tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
510 | | (( 0 << 23) & AT91_SSC_FSDEN) | ||
511 | | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS) | ||
512 | | (( 0 << 16) & AT91_SSC_FSLEN) | ||
513 | | (( 0 << 8) & AT91_SSC_DATNB) | ||
514 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
515 | | (( 0 << 5) & AT91_SSC_DATDEF) | ||
516 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
517 | break; | ||
518 | |||
519 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | ||
520 | /* | ||
521 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | ||
522 | * | ||
523 | * The SSC transmit and receive clocks are generated from the | ||
524 | * MCK divider, and the BCLK signal is output on the SSC TK line. | ||
525 | */ | ||
526 | rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD) | ||
527 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
528 | | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | ||
529 | | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | ||
530 | | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO) | ||
531 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | ||
532 | |||
533 | rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
534 | | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | ||
535 | | (( 0 << 16) & AT91_SSC_FSLEN) | ||
536 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
537 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
538 | | (( 0 << 5) & AT91_SSC_LOOP) | ||
539 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
540 | |||
541 | tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD) | ||
542 | | (( 1 << 16) & AT91_SSC_STTDLY) | ||
543 | | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START) | ||
544 | | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI) | ||
545 | | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO) | ||
546 | | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS); | ||
547 | |||
548 | tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE) | ||
549 | | (( 0 << 23) & AT91_SSC_FSDEN) | ||
550 | | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS) | ||
551 | | (( 0 << 16) & AT91_SSC_FSLEN) | ||
552 | | (((channels - 1) << 8) & AT91_SSC_DATNB) | ||
553 | | (( 1 << 7) & AT91_SSC_MSBF) | ||
554 | | (( 0 << 5) & AT91_SSC_DATDEF) | ||
555 | | (((bits - 1) << 0) & AT91_SSC_DATALEN); | ||
556 | |||
557 | |||
558 | |||
559 | break; | ||
560 | |||
561 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: | ||
562 | default: | ||
563 | printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n", | ||
564 | ssc_p->daifmt); | ||
565 | return -EINVAL; | ||
566 | break; | ||
567 | } | ||
568 | DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr); | ||
569 | |||
570 | if (!ssc_p->initialized) { | ||
571 | |||
572 | /* Enable PMC peripheral clock for this SSC */ | ||
573 | DBG("Starting pid %d clock\n", ssc_p->ssc.pid); | ||
574 | at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid); | ||
575 | |||
576 | /* Reset the SSC and its PDC registers */ | ||
577 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST); | ||
578 | |||
579 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0); | ||
580 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0); | ||
581 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0); | ||
582 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0); | ||
583 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0); | ||
584 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0); | ||
585 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0); | ||
586 | at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0); | ||
587 | |||
588 | if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt, | ||
589 | 0, ssc_p->name, ssc_p)) < 0) { | ||
590 | printk(KERN_WARNING "at91-ssc: request_irq failure\n"); | ||
591 | |||
592 | DBG("Stopping pid %d clock\n", ssc_p->ssc.pid); | ||
593 | at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid); | ||
594 | return ret; | ||
595 | } | ||
596 | |||
597 | ssc_p->initialized = 1; | ||
598 | } | ||
599 | |||
600 | /* set SSC clock mode register */ | ||
601 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div); | ||
602 | |||
603 | /* set receive clock mode and format */ | ||
604 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr); | ||
605 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr); | ||
606 | |||
607 | /* set transmit clock mode and format */ | ||
608 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr); | ||
609 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr); | ||
610 | |||
611 | DBG("hw_params: SSC initialized\n"); | ||
612 | return 0; | ||
613 | } | ||
614 | |||
615 | |||
616 | static int at91_ssc_prepare(struct snd_pcm_substream *substream) | ||
617 | { | ||
618 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
619 | struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
620 | struct at91_pcm_dma_params *dma_params; | ||
621 | int dir; | ||
622 | |||
623 | dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | ||
624 | dma_params = ssc_p->dma_params[dir]; | ||
625 | |||
626 | at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR, | ||
627 | dma_params->mask->ssc_enable); | ||
628 | |||
629 | DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit", | ||
630 | at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR)); | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | |||
635 | #ifdef CONFIG_PM | ||
636 | static int at91_ssc_suspend(struct platform_device *pdev, | ||
637 | struct snd_soc_dai *cpu_dai) | ||
638 | { | ||
639 | struct at91_ssc_info *ssc_p; | ||
640 | |||
641 | if(!cpu_dai->active) | ||
642 | return 0; | ||
643 | |||
644 | ssc_p = &ssc_info[cpu_dai->id]; | ||
645 | |||
646 | /* Save the status register before disabling transmit and receive. */ | ||
647 | ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR); | ||
648 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, | ||
649 | AT91_SSC_TXDIS | AT91_SSC_RXDIS); | ||
650 | |||
651 | /* Save the current interrupt mask, then disable unmasked interrupts. */ | ||
652 | ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR); | ||
653 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr); | ||
654 | |||
655 | ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR); | ||
656 | ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR); | ||
657 | ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR); | ||
658 | ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR); | ||
659 | ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR); | ||
660 | |||
661 | return 0; | ||
662 | } | ||
663 | |||
664 | static int at91_ssc_resume(struct platform_device *pdev, | ||
665 | struct snd_soc_dai *cpu_dai) | ||
666 | { | ||
667 | struct at91_ssc_info *ssc_p; | ||
668 | |||
669 | if(!cpu_dai->active) | ||
670 | return 0; | ||
671 | |||
672 | ssc_p = &ssc_info[cpu_dai->id]; | ||
673 | |||
674 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr); | ||
675 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr); | ||
676 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr); | ||
677 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr); | ||
678 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr); | ||
679 | |||
680 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr); | ||
681 | |||
682 | at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, | ||
683 | ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) | | ||
684 | ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0)); | ||
685 | |||
686 | return 0; | ||
687 | } | ||
688 | |||
689 | #else | ||
690 | #define at91_ssc_suspend NULL | ||
691 | #define at91_ssc_resume NULL | ||
692 | #endif | ||
693 | |||
694 | #define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
695 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\ | ||
696 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
697 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | ||
698 | SNDRV_PCM_RATE_96000) | ||
699 | |||
700 | #define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
701 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
702 | |||
703 | struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = { | ||
704 | { .name = "at91-ssc0", | ||
705 | .id = 0, | ||
706 | .type = SND_SOC_DAI_PCM, | ||
707 | .suspend = at91_ssc_suspend, | ||
708 | .resume = at91_ssc_resume, | ||
709 | .playback = { | ||
710 | .channels_min = 1, | ||
711 | .channels_max = 2, | ||
712 | .rates = AT91_SSC_RATES, | ||
713 | .formats = AT91_SSC_FORMATS,}, | ||
714 | .capture = { | ||
715 | .channels_min = 1, | ||
716 | .channels_max = 2, | ||
717 | .rates = AT91_SSC_RATES, | ||
718 | .formats = AT91_SSC_FORMATS,}, | ||
719 | .ops = { | ||
720 | .startup = at91_ssc_startup, | ||
721 | .shutdown = at91_ssc_shutdown, | ||
722 | .prepare = at91_ssc_prepare, | ||
723 | .hw_params = at91_ssc_hw_params,}, | ||
724 | .dai_ops = { | ||
725 | .set_sysclk = at91_ssc_set_dai_sysclk, | ||
726 | .set_fmt = at91_ssc_set_dai_fmt, | ||
727 | .set_clkdiv = at91_ssc_set_dai_clkdiv,}, | ||
728 | .private_data = &ssc_info[0].ssc, | ||
729 | }, | ||
730 | #if NUM_SSC_DEVICES == 3 | ||
731 | { .name = "at91-ssc1", | ||
732 | .id = 1, | ||
733 | .type = SND_SOC_DAI_PCM, | ||
734 | .suspend = at91_ssc_suspend, | ||
735 | .resume = at91_ssc_resume, | ||
736 | .playback = { | ||
737 | .channels_min = 1, | ||
738 | .channels_max = 2, | ||
739 | .rates = AT91_SSC_RATES, | ||
740 | .formats = AT91_SSC_FORMATS,}, | ||
741 | .capture = { | ||
742 | .channels_min = 1, | ||
743 | .channels_max = 2, | ||
744 | .rates = AT91_SSC_RATES, | ||
745 | .formats = AT91_SSC_FORMATS,}, | ||
746 | .ops = { | ||
747 | .startup = at91_ssc_startup, | ||
748 | .shutdown = at91_ssc_shutdown, | ||
749 | .prepare = at91_ssc_prepare, | ||
750 | .hw_params = at91_ssc_hw_params,}, | ||
751 | .dai_ops = { | ||
752 | .set_sysclk = at91_ssc_set_dai_sysclk, | ||
753 | .set_fmt = at91_ssc_set_dai_fmt, | ||
754 | .set_clkdiv = at91_ssc_set_dai_clkdiv,}, | ||
755 | .private_data = &ssc_info[1].ssc, | ||
756 | }, | ||
757 | { .name = "at91-ssc2", | ||
758 | .id = 2, | ||
759 | .type = SND_SOC_DAI_PCM, | ||
760 | .suspend = at91_ssc_suspend, | ||
761 | .resume = at91_ssc_resume, | ||
762 | .playback = { | ||
763 | .channels_min = 1, | ||
764 | .channels_max = 2, | ||
765 | .rates = AT91_SSC_RATES, | ||
766 | .formats = AT91_SSC_FORMATS,}, | ||
767 | .capture = { | ||
768 | .channels_min = 1, | ||
769 | .channels_max = 2, | ||
770 | .rates = AT91_SSC_RATES, | ||
771 | .formats = AT91_SSC_FORMATS,}, | ||
772 | .ops = { | ||
773 | .startup = at91_ssc_startup, | ||
774 | .shutdown = at91_ssc_shutdown, | ||
775 | .prepare = at91_ssc_prepare, | ||
776 | .hw_params = at91_ssc_hw_params,}, | ||
777 | .dai_ops = { | ||
778 | .set_sysclk = at91_ssc_set_dai_sysclk, | ||
779 | .set_fmt = at91_ssc_set_dai_fmt, | ||
780 | .set_clkdiv = at91_ssc_set_dai_clkdiv,}, | ||
781 | .private_data = &ssc_info[2].ssc, | ||
782 | }, | ||
783 | #endif | ||
784 | }; | ||
785 | |||
786 | EXPORT_SYMBOL_GPL(at91_ssc_dai); | ||
787 | |||
788 | /* Module information */ | ||
789 | MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com"); | ||
790 | MODULE_DESCRIPTION("AT91 SSC ASoC Interface"); | ||
791 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h deleted file mode 100644 index 6b7bf382d06f..000000000000 --- a/sound/soc/at91/at91-ssc.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC | ||
3 | * | ||
4 | * Author: Frank Mandarino <fmandarino@endrelia.com> | ||
5 | * Endrelia Technologies Inc. | ||
6 | * Created: Jan 9, 2007 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _AT91_SSC_H | ||
14 | #define _AT91_SSC_H | ||
15 | |||
16 | /* SSC system clock ids */ | ||
17 | #define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ | ||
18 | |||
19 | /* SSC divider ids */ | ||
20 | #define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */ | ||
21 | #define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ | ||
22 | #define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ | ||
23 | |||
24 | extern struct snd_soc_dai at91_ssc_dai[]; | ||
25 | |||
26 | #endif /* _AT91_SSC_H */ | ||
27 | |||
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig new file mode 100644 index 000000000000..a608d7009dbd --- /dev/null +++ b/sound/soc/atmel/Kconfig | |||
@@ -0,0 +1,43 @@ | |||
1 | config SND_ATMEL_SOC | ||
2 | tristate "SoC Audio for the Atmel System-on-Chip" | ||
3 | depends on ARCH_AT91 || AVR32 | ||
4 | help | ||
5 | Say Y or M if you want to add support for codecs attached to | ||
6 | the ATMEL SSC interface. You will also need | ||
7 | to select the audio interfaces to support below. | ||
8 | |||
9 | config SND_ATMEL_SOC_SSC | ||
10 | tristate | ||
11 | depends on SND_ATMEL_SOC | ||
12 | help | ||
13 | Say Y or M if you want to add support for codecs the | ||
14 | ATMEL SSC interface. You will also needs to select the individual | ||
15 | machine drivers to support below. | ||
16 | |||
17 | config SND_AT91_SOC_SAM9G20_WM8731 | ||
18 | tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board" | ||
19 | depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC | ||
20 | select SND_ATMEL_SOC_SSC | ||
21 | select SND_SOC_WM8731 | ||
22 | help | ||
23 | Say Y if you want to add support for SoC audio on WM8731-based | ||
24 | AT91sam9g20 evaluation board. | ||
25 | |||
26 | config SND_AT32_SOC_PLAYPAQ | ||
27 | tristate "SoC Audio support for PlayPaq with WM8510" | ||
28 | depends on SND_ATMEL_SOC && BOARD_PLAYPAQ | ||
29 | select SND_ATMEL_SOC_SSC | ||
30 | select SND_SOC_WM8510 | ||
31 | help | ||
32 | Say Y or M here if you want to add support for SoC audio | ||
33 | on the LRS PlayPaq. | ||
34 | |||
35 | config SND_AT32_SOC_PLAYPAQ_SLAVE | ||
36 | bool "Run CODEC on PlayPaq in slave mode" | ||
37 | depends on SND_AT32_SOC_PLAYPAQ | ||
38 | default n | ||
39 | help | ||
40 | Say Y if you want to run with the AT32 SSC generating the BCLK | ||
41 | and FRAME signals on the PlayPaq. Unless you want to play | ||
42 | with the AT32 as the SSC master, you probably want to say N here, | ||
43 | as this will give you better sound quality. | ||
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile new file mode 100644 index 000000000000..f54a7cc68e66 --- /dev/null +++ b/sound/soc/atmel/Makefile | |||
@@ -0,0 +1,15 @@ | |||
1 | # AT91 Platform Support | ||
2 | snd-soc-atmel-pcm-objs := atmel-pcm.o | ||
3 | snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o | ||
4 | |||
5 | obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o | ||
6 | obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o | ||
7 | |||
8 | # AT91 Machine Support | ||
9 | snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o | ||
10 | |||
11 | # AT32 Machine Support | ||
12 | snd-soc-playpaq-objs := playpaq_wm8510.o | ||
13 | |||
14 | obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o | ||
15 | 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 new file mode 100644 index 000000000000..1fac5efd285b --- /dev/null +++ b/sound/soc/atmel/atmel-pcm.c | |||
@@ -0,0 +1,494 @@ | |||
1 | /* | ||
2 | * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC. | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People | ||
5 | * Copyright (C) 2008 Atmel | ||
6 | * | ||
7 | * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
8 | * | ||
9 | * Based on at91-pcm. by: | ||
10 | * Frank Mandarino <fmandarino@endrelia.com> | ||
11 | * Copyright 2006 Endrelia Technologies Inc. | ||
12 | * | ||
13 | * Based on pxa2xx-pcm.c by: | ||
14 | * | ||
15 | * Author: Nicolas Pitre | ||
16 | * Created: Nov 30, 2004 | ||
17 | * Copyright: (C) 2004 MontaVista Software, Inc. | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #include <linux/module.h> | ||
35 | #include <linux/init.h> | ||
36 | #include <linux/platform_device.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/dma-mapping.h> | ||
39 | #include <linux/atmel_pdc.h> | ||
40 | #include <linux/atmel-ssc.h> | ||
41 | |||
42 | #include <sound/core.h> | ||
43 | #include <sound/pcm.h> | ||
44 | #include <sound/pcm_params.h> | ||
45 | #include <sound/soc.h> | ||
46 | |||
47 | #include <mach/hardware.h> | ||
48 | |||
49 | #include "atmel-pcm.h" | ||
50 | |||
51 | |||
52 | /*--------------------------------------------------------------------------*\ | ||
53 | * Hardware definition | ||
54 | \*--------------------------------------------------------------------------*/ | ||
55 | /* TODO: These values were taken from the AT91 platform driver, check | ||
56 | * them against real values for AT32 | ||
57 | */ | ||
58 | static const struct snd_pcm_hardware atmel_pcm_hardware = { | ||
59 | .info = SNDRV_PCM_INFO_MMAP | | ||
60 | SNDRV_PCM_INFO_MMAP_VALID | | ||
61 | SNDRV_PCM_INFO_INTERLEAVED | | ||
62 | SNDRV_PCM_INFO_PAUSE, | ||
63 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
64 | .period_bytes_min = 32, | ||
65 | .period_bytes_max = 8192, | ||
66 | .periods_min = 2, | ||
67 | .periods_max = 1024, | ||
68 | .buffer_bytes_max = 32 * 1024, | ||
69 | }; | ||
70 | |||
71 | |||
72 | /*--------------------------------------------------------------------------*\ | ||
73 | * Data types | ||
74 | \*--------------------------------------------------------------------------*/ | ||
75 | struct atmel_runtime_data { | ||
76 | struct atmel_pcm_dma_params *params; | ||
77 | dma_addr_t dma_buffer; /* physical address of dma buffer */ | ||
78 | dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */ | ||
79 | size_t period_size; | ||
80 | |||
81 | dma_addr_t period_ptr; /* physical address of next period */ | ||
82 | int periods; /* period index of period_ptr */ | ||
83 | |||
84 | /* PDC register save */ | ||
85 | u32 pdc_xpr_save; | ||
86 | u32 pdc_xcr_save; | ||
87 | u32 pdc_xnpr_save; | ||
88 | u32 pdc_xncr_save; | ||
89 | }; | ||
90 | |||
91 | |||
92 | /*--------------------------------------------------------------------------*\ | ||
93 | * Helper functions | ||
94 | \*--------------------------------------------------------------------------*/ | ||
95 | static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, | ||
96 | int stream) | ||
97 | { | ||
98 | struct snd_pcm_substream *substream = pcm->streams[stream].substream; | ||
99 | struct snd_dma_buffer *buf = &substream->dma_buffer; | ||
100 | size_t size = atmel_pcm_hardware.buffer_bytes_max; | ||
101 | |||
102 | buf->dev.type = SNDRV_DMA_TYPE_DEV; | ||
103 | buf->dev.dev = pcm->card->dev; | ||
104 | buf->private_data = NULL; | ||
105 | buf->area = dma_alloc_coherent(pcm->card->dev, size, | ||
106 | &buf->addr, GFP_KERNEL); | ||
107 | pr_debug("atmel-pcm:" | ||
108 | "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | ||
109 | (void *) buf->area, | ||
110 | (void *) buf->addr, | ||
111 | size); | ||
112 | |||
113 | if (!buf->area) | ||
114 | return -ENOMEM; | ||
115 | |||
116 | buf->bytes = size; | ||
117 | return 0; | ||
118 | } | ||
119 | /*--------------------------------------------------------------------------*\ | ||
120 | * ISR | ||
121 | \*--------------------------------------------------------------------------*/ | ||
122 | static void atmel_pcm_dma_irq(u32 ssc_sr, | ||
123 | struct snd_pcm_substream *substream) | ||
124 | { | ||
125 | struct atmel_runtime_data *prtd = substream->runtime->private_data; | ||
126 | struct atmel_pcm_dma_params *params = prtd->params; | ||
127 | static int count; | ||
128 | |||
129 | count++; | ||
130 | |||
131 | if (ssc_sr & params->mask->ssc_endbuf) { | ||
132 | pr_warning("atmel-pcm: buffer %s on %s" | ||
133 | " (SSC_SR=%#x, count=%d)\n", | ||
134 | substream->stream == SNDRV_PCM_STREAM_PLAYBACK | ||
135 | ? "underrun" : "overrun", | ||
136 | params->name, ssc_sr, count); | ||
137 | |||
138 | /* re-start the PDC */ | ||
139 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
140 | params->mask->pdc_disable); | ||
141 | prtd->period_ptr += prtd->period_size; | ||
142 | if (prtd->period_ptr >= prtd->dma_buffer_end) | ||
143 | prtd->period_ptr = prtd->dma_buffer; | ||
144 | |||
145 | ssc_writex(params->ssc->regs, params->pdc->xpr, | ||
146 | prtd->period_ptr); | ||
147 | ssc_writex(params->ssc->regs, params->pdc->xcr, | ||
148 | prtd->period_size / params->pdc_xfer_size); | ||
149 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
150 | params->mask->pdc_enable); | ||
151 | } | ||
152 | |||
153 | if (ssc_sr & params->mask->ssc_endx) { | ||
154 | /* Load the PDC next pointer and counter registers */ | ||
155 | prtd->period_ptr += prtd->period_size; | ||
156 | if (prtd->period_ptr >= prtd->dma_buffer_end) | ||
157 | prtd->period_ptr = prtd->dma_buffer; | ||
158 | |||
159 | ssc_writex(params->ssc->regs, params->pdc->xnpr, | ||
160 | prtd->period_ptr); | ||
161 | ssc_writex(params->ssc->regs, params->pdc->xncr, | ||
162 | prtd->period_size / params->pdc_xfer_size); | ||
163 | } | ||
164 | |||
165 | snd_pcm_period_elapsed(substream); | ||
166 | } | ||
167 | |||
168 | |||
169 | /*--------------------------------------------------------------------------*\ | ||
170 | * PCM operations | ||
171 | \*--------------------------------------------------------------------------*/ | ||
172 | static int atmel_pcm_hw_params(struct snd_pcm_substream *substream, | ||
173 | struct snd_pcm_hw_params *params) | ||
174 | { | ||
175 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
176 | struct atmel_runtime_data *prtd = runtime->private_data; | ||
177 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
178 | |||
179 | /* this may get called several times by oss emulation | ||
180 | * with different params */ | ||
181 | |||
182 | snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); | ||
183 | runtime->dma_bytes = params_buffer_bytes(params); | ||
184 | |||
185 | prtd->params = rtd->dai->cpu_dai->dma_data; | ||
186 | prtd->params->dma_intr_handler = atmel_pcm_dma_irq; | ||
187 | |||
188 | prtd->dma_buffer = runtime->dma_addr; | ||
189 | prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes; | ||
190 | prtd->period_size = params_period_bytes(params); | ||
191 | |||
192 | pr_debug("atmel-pcm: " | ||
193 | "hw_params: DMA for %s initialized " | ||
194 | "(dma_bytes=%u, period_size=%u)\n", | ||
195 | prtd->params->name, | ||
196 | runtime->dma_bytes, | ||
197 | prtd->period_size); | ||
198 | return 0; | ||
199 | } | ||
200 | |||
201 | static int atmel_pcm_hw_free(struct snd_pcm_substream *substream) | ||
202 | { | ||
203 | struct atmel_runtime_data *prtd = substream->runtime->private_data; | ||
204 | struct atmel_pcm_dma_params *params = prtd->params; | ||
205 | |||
206 | if (params != NULL) { | ||
207 | ssc_writex(params->ssc->regs, SSC_PDC_PTCR, | ||
208 | params->mask->pdc_disable); | ||
209 | prtd->params->dma_intr_handler = NULL; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int atmel_pcm_prepare(struct snd_pcm_substream *substream) | ||
216 | { | ||
217 | struct atmel_runtime_data *prtd = substream->runtime->private_data; | ||
218 | struct atmel_pcm_dma_params *params = prtd->params; | ||
219 | |||
220 | ssc_writex(params->ssc->regs, SSC_IDR, | ||
221 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
222 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
223 | params->mask->pdc_disable); | ||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int atmel_pcm_trigger(struct snd_pcm_substream *substream, | ||
228 | int cmd) | ||
229 | { | ||
230 | struct snd_pcm_runtime *rtd = substream->runtime; | ||
231 | struct atmel_runtime_data *prtd = rtd->private_data; | ||
232 | struct atmel_pcm_dma_params *params = prtd->params; | ||
233 | int ret = 0; | ||
234 | |||
235 | pr_debug("atmel-pcm:buffer_size = %ld," | ||
236 | "dma_area = %p, dma_bytes = %u\n", | ||
237 | rtd->buffer_size, rtd->dma_area, rtd->dma_bytes); | ||
238 | |||
239 | switch (cmd) { | ||
240 | case SNDRV_PCM_TRIGGER_START: | ||
241 | prtd->period_ptr = prtd->dma_buffer; | ||
242 | |||
243 | ssc_writex(params->ssc->regs, params->pdc->xpr, | ||
244 | prtd->period_ptr); | ||
245 | ssc_writex(params->ssc->regs, params->pdc->xcr, | ||
246 | prtd->period_size / params->pdc_xfer_size); | ||
247 | |||
248 | prtd->period_ptr += prtd->period_size; | ||
249 | ssc_writex(params->ssc->regs, params->pdc->xnpr, | ||
250 | prtd->period_ptr); | ||
251 | ssc_writex(params->ssc->regs, params->pdc->xncr, | ||
252 | prtd->period_size / params->pdc_xfer_size); | ||
253 | |||
254 | pr_debug("atmel-pcm: trigger: " | ||
255 | "period_ptr=%lx, xpr=%u, " | ||
256 | "xcr=%u, xnpr=%u, xncr=%u\n", | ||
257 | (unsigned long)prtd->period_ptr, | ||
258 | ssc_readx(params->ssc->regs, params->pdc->xpr), | ||
259 | ssc_readx(params->ssc->regs, params->pdc->xcr), | ||
260 | ssc_readx(params->ssc->regs, params->pdc->xnpr), | ||
261 | ssc_readx(params->ssc->regs, params->pdc->xncr)); | ||
262 | |||
263 | ssc_writex(params->ssc->regs, SSC_IER, | ||
264 | params->mask->ssc_endx | params->mask->ssc_endbuf); | ||
265 | ssc_writex(params->ssc->regs, SSC_PDC_PTCR, | ||
266 | params->mask->pdc_enable); | ||
267 | |||
268 | pr_debug("sr=%u imr=%u\n", | ||
269 | ssc_readx(params->ssc->regs, SSC_SR), | ||
270 | ssc_readx(params->ssc->regs, SSC_IER)); | ||
271 | break; /* SNDRV_PCM_TRIGGER_START */ | ||
272 | |||
273 | case SNDRV_PCM_TRIGGER_STOP: | ||
274 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
275 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
276 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
277 | params->mask->pdc_disable); | ||
278 | break; | ||
279 | |||
280 | case SNDRV_PCM_TRIGGER_RESUME: | ||
281 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
282 | ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, | ||
283 | params->mask->pdc_enable); | ||
284 | break; | ||
285 | |||
286 | default: | ||
287 | ret = -EINVAL; | ||
288 | } | ||
289 | |||
290 | return ret; | ||
291 | } | ||
292 | |||
293 | static snd_pcm_uframes_t atmel_pcm_pointer( | ||
294 | struct snd_pcm_substream *substream) | ||
295 | { | ||
296 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
297 | struct atmel_runtime_data *prtd = runtime->private_data; | ||
298 | struct atmel_pcm_dma_params *params = prtd->params; | ||
299 | dma_addr_t ptr; | ||
300 | snd_pcm_uframes_t x; | ||
301 | |||
302 | ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr); | ||
303 | x = bytes_to_frames(runtime, ptr - prtd->dma_buffer); | ||
304 | |||
305 | if (x == runtime->buffer_size) | ||
306 | x = 0; | ||
307 | |||
308 | return x; | ||
309 | } | ||
310 | |||
311 | static int atmel_pcm_open(struct snd_pcm_substream *substream) | ||
312 | { | ||
313 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
314 | struct atmel_runtime_data *prtd; | ||
315 | int ret = 0; | ||
316 | |||
317 | snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware); | ||
318 | |||
319 | /* ensure that buffer size is a multiple of period size */ | ||
320 | ret = snd_pcm_hw_constraint_integer(runtime, | ||
321 | SNDRV_PCM_HW_PARAM_PERIODS); | ||
322 | if (ret < 0) | ||
323 | goto out; | ||
324 | |||
325 | prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL); | ||
326 | if (prtd == NULL) { | ||
327 | ret = -ENOMEM; | ||
328 | goto out; | ||
329 | } | ||
330 | runtime->private_data = prtd; | ||
331 | |||
332 | out: | ||
333 | return ret; | ||
334 | } | ||
335 | |||
336 | static int atmel_pcm_close(struct snd_pcm_substream *substream) | ||
337 | { | ||
338 | struct atmel_runtime_data *prtd = substream->runtime->private_data; | ||
339 | |||
340 | kfree(prtd); | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int atmel_pcm_mmap(struct snd_pcm_substream *substream, | ||
345 | struct vm_area_struct *vma) | ||
346 | { | ||
347 | return remap_pfn_range(vma, vma->vm_start, | ||
348 | substream->dma_buffer.addr >> PAGE_SHIFT, | ||
349 | vma->vm_end - vma->vm_start, vma->vm_page_prot); | ||
350 | } | ||
351 | |||
352 | struct snd_pcm_ops atmel_pcm_ops = { | ||
353 | .open = atmel_pcm_open, | ||
354 | .close = atmel_pcm_close, | ||
355 | .ioctl = snd_pcm_lib_ioctl, | ||
356 | .hw_params = atmel_pcm_hw_params, | ||
357 | .hw_free = atmel_pcm_hw_free, | ||
358 | .prepare = atmel_pcm_prepare, | ||
359 | .trigger = atmel_pcm_trigger, | ||
360 | .pointer = atmel_pcm_pointer, | ||
361 | .mmap = atmel_pcm_mmap, | ||
362 | }; | ||
363 | |||
364 | |||
365 | /*--------------------------------------------------------------------------*\ | ||
366 | * ASoC platform driver | ||
367 | \*--------------------------------------------------------------------------*/ | ||
368 | static u64 atmel_pcm_dmamask = 0xffffffff; | ||
369 | |||
370 | static int atmel_pcm_new(struct snd_card *card, | ||
371 | struct snd_soc_dai *dai, struct snd_pcm *pcm) | ||
372 | { | ||
373 | int ret = 0; | ||
374 | |||
375 | if (!card->dev->dma_mask) | ||
376 | card->dev->dma_mask = &atmel_pcm_dmamask; | ||
377 | if (!card->dev->coherent_dma_mask) | ||
378 | card->dev->coherent_dma_mask = 0xffffffff; | ||
379 | |||
380 | if (dai->playback.channels_min) { | ||
381 | ret = atmel_pcm_preallocate_dma_buffer(pcm, | ||
382 | SNDRV_PCM_STREAM_PLAYBACK); | ||
383 | if (ret) | ||
384 | goto out; | ||
385 | } | ||
386 | |||
387 | if (dai->capture.channels_min) { | ||
388 | pr_debug("at32-pcm:" | ||
389 | "Allocating PCM capture DMA buffer\n"); | ||
390 | ret = atmel_pcm_preallocate_dma_buffer(pcm, | ||
391 | SNDRV_PCM_STREAM_CAPTURE); | ||
392 | if (ret) | ||
393 | goto out; | ||
394 | } | ||
395 | out: | ||
396 | return ret; | ||
397 | } | ||
398 | |||
399 | static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm) | ||
400 | { | ||
401 | struct snd_pcm_substream *substream; | ||
402 | struct snd_dma_buffer *buf; | ||
403 | int stream; | ||
404 | |||
405 | for (stream = 0; stream < 2; stream++) { | ||
406 | substream = pcm->streams[stream].substream; | ||
407 | if (!substream) | ||
408 | continue; | ||
409 | |||
410 | buf = &substream->dma_buffer; | ||
411 | if (!buf->area) | ||
412 | continue; | ||
413 | dma_free_coherent(pcm->card->dev, buf->bytes, | ||
414 | buf->area, buf->addr); | ||
415 | buf->area = NULL; | ||
416 | } | ||
417 | } | ||
418 | |||
419 | #ifdef CONFIG_PM | ||
420 | static int atmel_pcm_suspend(struct snd_soc_dai *dai) | ||
421 | { | ||
422 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
423 | struct atmel_runtime_data *prtd; | ||
424 | struct atmel_pcm_dma_params *params; | ||
425 | |||
426 | if (!runtime) | ||
427 | return 0; | ||
428 | |||
429 | prtd = runtime->private_data; | ||
430 | params = prtd->params; | ||
431 | |||
432 | /* disable the PDC and save the PDC registers */ | ||
433 | |||
434 | ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable); | ||
435 | |||
436 | prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr); | ||
437 | prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr); | ||
438 | prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr); | ||
439 | prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr); | ||
440 | |||
441 | return 0; | ||
442 | } | ||
443 | |||
444 | static int atmel_pcm_resume(struct snd_soc_dai *dai) | ||
445 | { | ||
446 | struct snd_pcm_runtime *runtime = dai->runtime; | ||
447 | struct atmel_runtime_data *prtd; | ||
448 | struct atmel_pcm_dma_params *params; | ||
449 | |||
450 | if (!runtime) | ||
451 | return 0; | ||
452 | |||
453 | prtd = runtime->private_data; | ||
454 | params = prtd->params; | ||
455 | |||
456 | /* restore the PDC registers and enable the PDC */ | ||
457 | ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save); | ||
458 | ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save); | ||
459 | ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save); | ||
460 | ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save); | ||
461 | |||
462 | ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable); | ||
463 | return 0; | ||
464 | } | ||
465 | #else | ||
466 | #define atmel_pcm_suspend NULL | ||
467 | #define atmel_pcm_resume NULL | ||
468 | #endif | ||
469 | |||
470 | struct snd_soc_platform atmel_soc_platform = { | ||
471 | .name = "atmel-audio", | ||
472 | .pcm_ops = &atmel_pcm_ops, | ||
473 | .pcm_new = atmel_pcm_new, | ||
474 | .pcm_free = atmel_pcm_free_dma_buffers, | ||
475 | .suspend = atmel_pcm_suspend, | ||
476 | .resume = atmel_pcm_resume, | ||
477 | }; | ||
478 | EXPORT_SYMBOL_GPL(atmel_soc_platform); | ||
479 | |||
480 | static int __init atmel_pcm_modinit(void) | ||
481 | { | ||
482 | return snd_soc_register_platform(&atmel_soc_platform); | ||
483 | } | ||
484 | module_init(atmel_pcm_modinit); | ||
485 | |||
486 | static void __exit atmel_pcm_modexit(void) | ||
487 | { | ||
488 | snd_soc_unregister_platform(&atmel_soc_platform); | ||
489 | } | ||
490 | module_exit(atmel_pcm_modexit); | ||
491 | |||
492 | MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); | ||
493 | MODULE_DESCRIPTION("Atmel PCM module"); | ||
494 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h new file mode 100644 index 000000000000..ec9b2824b663 --- /dev/null +++ b/sound/soc/atmel/atmel-pcm.h | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC. | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People | ||
5 | * Copyright (C) 2008 Atmel | ||
6 | * | ||
7 | * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
8 | * | ||
9 | * Based on at91-pcm. by: | ||
10 | * Frank Mandarino <fmandarino@endrelia.com> | ||
11 | * Copyright 2006 Endrelia Technologies Inc. | ||
12 | * | ||
13 | * Based on pxa2xx-pcm.c by: | ||
14 | * | ||
15 | * Author: Nicolas Pitre | ||
16 | * Created: Nov 30, 2004 | ||
17 | * Copyright: (C) 2004 MontaVista Software, Inc. | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or modify | ||
20 | * it under the terms of the GNU General Public License as published by | ||
21 | * the Free Software Foundation; either version 2 of the License, or | ||
22 | * (at your option) any later version. | ||
23 | * | ||
24 | * This program is distributed in the hope that it will be useful, | ||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
27 | * GNU General Public License for more details. | ||
28 | * | ||
29 | * You should have received a copy of the GNU General Public License | ||
30 | * along with this program; if not, write to the Free Software | ||
31 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
32 | */ | ||
33 | |||
34 | #ifndef _ATMEL_PCM_H | ||
35 | #define _ATMEL_PCM_H | ||
36 | |||
37 | #include <linux/atmel-ssc.h> | ||
38 | |||
39 | /* | ||
40 | * Registers and status bits that are required by the PCM driver. | ||
41 | */ | ||
42 | struct atmel_pdc_regs { | ||
43 | unsigned int xpr; /* PDC recv/trans pointer */ | ||
44 | unsigned int xcr; /* PDC recv/trans counter */ | ||
45 | unsigned int xnpr; /* PDC next recv/trans pointer */ | ||
46 | unsigned int xncr; /* PDC next recv/trans counter */ | ||
47 | unsigned int ptcr; /* PDC transfer control */ | ||
48 | }; | ||
49 | |||
50 | struct atmel_ssc_mask { | ||
51 | u32 ssc_enable; /* SSC recv/trans enable */ | ||
52 | u32 ssc_disable; /* SSC recv/trans disable */ | ||
53 | u32 ssc_endx; /* SSC ENDTX or ENDRX */ | ||
54 | u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */ | ||
55 | u32 pdc_enable; /* PDC recv/trans enable */ | ||
56 | u32 pdc_disable; /* PDC recv/trans disable */ | ||
57 | }; | ||
58 | |||
59 | /* | ||
60 | * This structure, shared between the PCM driver and the interface, | ||
61 | * contains all information required by the PCM driver to perform the | ||
62 | * PDC DMA operation. All fields except dma_intr_handler() are initialized | ||
63 | * by the interface. The dms_intr_handler() pointer is set by the PCM | ||
64 | * driver and called by the interface SSC interrupt handler if it is | ||
65 | * non-NULL. | ||
66 | */ | ||
67 | struct atmel_pcm_dma_params { | ||
68 | char *name; /* stream identifier */ | ||
69 | int pdc_xfer_size; /* PDC counter increment in bytes */ | ||
70 | struct ssc_device *ssc; /* SSC device for stream */ | ||
71 | struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */ | ||
72 | struct atmel_ssc_mask *mask; /* SSC & PDC status bits */ | ||
73 | struct snd_pcm_substream *substream; | ||
74 | void (*dma_intr_handler)(u32, struct snd_pcm_substream *); | ||
75 | }; | ||
76 | |||
77 | extern struct snd_soc_platform atmel_soc_platform; | ||
78 | |||
79 | |||
80 | /* | ||
81 | * SSC register access (since ssc_writel() / ssc_readl() require literal name) | ||
82 | */ | ||
83 | #define ssc_readx(base, reg) (__raw_readl((base) + (reg))) | ||
84 | #define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg)) | ||
85 | |||
86 | #endif /* _ATMEL_PCM_H */ | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c new file mode 100644 index 000000000000..c5d67900d666 --- /dev/null +++ b/sound/soc/atmel/atmel_ssc_dai.c | |||
@@ -0,0 +1,790 @@ | |||
1 | /* | ||
2 | * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People | ||
5 | * Copyright (C) 2008 Atmel | ||
6 | * | ||
7 | * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
8 | * ATMEL CORP. | ||
9 | * | ||
10 | * Based on at91-ssc.c by | ||
11 | * Frank Mandarino <fmandarino@endrelia.com> | ||
12 | * Based on pxa2xx Platform drivers by | ||
13 | * Liam Girdwood <liam.girdwood@wolfsonmicro.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/interrupt.h> | ||
33 | #include <linux/device.h> | ||
34 | #include <linux/delay.h> | ||
35 | #include <linux/clk.h> | ||
36 | #include <linux/atmel_pdc.h> | ||
37 | |||
38 | #include <linux/atmel-ssc.h> | ||
39 | #include <sound/core.h> | ||
40 | #include <sound/pcm.h> | ||
41 | #include <sound/pcm_params.h> | ||
42 | #include <sound/initval.h> | ||
43 | #include <sound/soc.h> | ||
44 | |||
45 | #include <mach/hardware.h> | ||
46 | |||
47 | #include "atmel-pcm.h" | ||
48 | #include "atmel_ssc_dai.h" | ||
49 | |||
50 | |||
51 | #if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20) | ||
52 | #define NUM_SSC_DEVICES 1 | ||
53 | #else | ||
54 | #define NUM_SSC_DEVICES 3 | ||
55 | #endif | ||
56 | |||
57 | /* | ||
58 | * SSC PDC registers required by the PCM DMA engine. | ||
59 | */ | ||
60 | static struct atmel_pdc_regs pdc_tx_reg = { | ||
61 | .xpr = ATMEL_PDC_TPR, | ||
62 | .xcr = ATMEL_PDC_TCR, | ||
63 | .xnpr = ATMEL_PDC_TNPR, | ||
64 | .xncr = ATMEL_PDC_TNCR, | ||
65 | }; | ||
66 | |||
67 | static struct atmel_pdc_regs pdc_rx_reg = { | ||
68 | .xpr = ATMEL_PDC_RPR, | ||
69 | .xcr = ATMEL_PDC_RCR, | ||
70 | .xnpr = ATMEL_PDC_RNPR, | ||
71 | .xncr = ATMEL_PDC_RNCR, | ||
72 | }; | ||
73 | |||
74 | /* | ||
75 | * SSC & PDC status bits for transmit and receive. | ||
76 | */ | ||
77 | static struct atmel_ssc_mask ssc_tx_mask = { | ||
78 | .ssc_enable = SSC_BIT(CR_TXEN), | ||
79 | .ssc_disable = SSC_BIT(CR_TXDIS), | ||
80 | .ssc_endx = SSC_BIT(SR_ENDTX), | ||
81 | .ssc_endbuf = SSC_BIT(SR_TXBUFE), | ||
82 | .pdc_enable = ATMEL_PDC_TXTEN, | ||
83 | .pdc_disable = ATMEL_PDC_TXTDIS, | ||
84 | }; | ||
85 | |||
86 | static struct atmel_ssc_mask ssc_rx_mask = { | ||
87 | .ssc_enable = SSC_BIT(CR_RXEN), | ||
88 | .ssc_disable = SSC_BIT(CR_RXDIS), | ||
89 | .ssc_endx = SSC_BIT(SR_ENDRX), | ||
90 | .ssc_endbuf = SSC_BIT(SR_RXBUFF), | ||
91 | .pdc_enable = ATMEL_PDC_RXTEN, | ||
92 | .pdc_disable = ATMEL_PDC_RXTDIS, | ||
93 | }; | ||
94 | |||
95 | |||
96 | /* | ||
97 | * DMA parameters. | ||
98 | */ | ||
99 | static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = { | ||
100 | {{ | ||
101 | .name = "SSC0 PCM out", | ||
102 | .pdc = &pdc_tx_reg, | ||
103 | .mask = &ssc_tx_mask, | ||
104 | }, | ||
105 | { | ||
106 | .name = "SSC0 PCM in", | ||
107 | .pdc = &pdc_rx_reg, | ||
108 | .mask = &ssc_rx_mask, | ||
109 | } }, | ||
110 | #if NUM_SSC_DEVICES == 3 | ||
111 | {{ | ||
112 | .name = "SSC1 PCM out", | ||
113 | .pdc = &pdc_tx_reg, | ||
114 | .mask = &ssc_tx_mask, | ||
115 | }, | ||
116 | { | ||
117 | .name = "SSC1 PCM in", | ||
118 | .pdc = &pdc_rx_reg, | ||
119 | .mask = &ssc_rx_mask, | ||
120 | } }, | ||
121 | {{ | ||
122 | .name = "SSC2 PCM out", | ||
123 | .pdc = &pdc_tx_reg, | ||
124 | .mask = &ssc_tx_mask, | ||
125 | }, | ||
126 | { | ||
127 | .name = "SSC2 PCM in", | ||
128 | .pdc = &pdc_rx_reg, | ||
129 | .mask = &ssc_rx_mask, | ||
130 | } }, | ||
131 | #endif | ||
132 | }; | ||
133 | |||
134 | |||
135 | static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = { | ||
136 | { | ||
137 | .name = "ssc0", | ||
138 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock), | ||
139 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
140 | .initialized = 0, | ||
141 | }, | ||
142 | #if NUM_SSC_DEVICES == 3 | ||
143 | { | ||
144 | .name = "ssc1", | ||
145 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock), | ||
146 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
147 | .initialized = 0, | ||
148 | }, | ||
149 | { | ||
150 | .name = "ssc2", | ||
151 | .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock), | ||
152 | .dir_mask = SSC_DIR_MASK_UNUSED, | ||
153 | .initialized = 0, | ||
154 | }, | ||
155 | #endif | ||
156 | }; | ||
157 | |||
158 | |||
159 | /* | ||
160 | * SSC interrupt handler. Passes PDC interrupts to the DMA | ||
161 | * interrupt handler in the PCM driver. | ||
162 | */ | ||
163 | static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id) | ||
164 | { | ||
165 | struct atmel_ssc_info *ssc_p = dev_id; | ||
166 | struct atmel_pcm_dma_params *dma_params; | ||
167 | u32 ssc_sr; | ||
168 | u32 ssc_substream_mask; | ||
169 | int i; | ||
170 | |||
171 | ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR) | ||
172 | & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR); | ||
173 | |||
174 | /* | ||
175 | * Loop through the substreams attached to this SSC. If | ||
176 | * a DMA-related interrupt occurred on that substream, call | ||
177 | * the DMA interrupt handler function, if one has been | ||
178 | * registered in the dma_params structure by the PCM driver. | ||
179 | */ | ||
180 | for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) { | ||
181 | dma_params = ssc_p->dma_params[i]; | ||
182 | |||
183 | if ((dma_params != NULL) && | ||
184 | (dma_params->dma_intr_handler != NULL)) { | ||
185 | ssc_substream_mask = (dma_params->mask->ssc_endx | | ||
186 | dma_params->mask->ssc_endbuf); | ||
187 | if (ssc_sr & ssc_substream_mask) { | ||
188 | dma_params->dma_intr_handler(ssc_sr, | ||
189 | dma_params-> | ||
190 | substream); | ||
191 | } | ||
192 | } | ||
193 | } | ||
194 | |||
195 | return IRQ_HANDLED; | ||
196 | } | ||
197 | |||
198 | |||
199 | /*-------------------------------------------------------------------------*\ | ||
200 | * DAI functions | ||
201 | \*-------------------------------------------------------------------------*/ | ||
202 | /* | ||
203 | * Startup. Only that one substream allowed in each direction. | ||
204 | */ | ||
205 | static int atmel_ssc_startup(struct snd_pcm_substream *substream, | ||
206 | struct snd_soc_dai *dai) | ||
207 | { | ||
208 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
209 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
210 | int dir_mask; | ||
211 | |||
212 | pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n", | ||
213 | ssc_readl(ssc_p->ssc->regs, SR)); | ||
214 | |||
215 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
216 | dir_mask = SSC_DIR_MASK_PLAYBACK; | ||
217 | else | ||
218 | dir_mask = SSC_DIR_MASK_CAPTURE; | ||
219 | |||
220 | spin_lock_irq(&ssc_p->lock); | ||
221 | if (ssc_p->dir_mask & dir_mask) { | ||
222 | spin_unlock_irq(&ssc_p->lock); | ||
223 | return -EBUSY; | ||
224 | } | ||
225 | ssc_p->dir_mask |= dir_mask; | ||
226 | spin_unlock_irq(&ssc_p->lock); | ||
227 | |||
228 | return 0; | ||
229 | } | ||
230 | |||
231 | /* | ||
232 | * Shutdown. Clear DMA parameters and shutdown the SSC if there | ||
233 | * are no other substreams open. | ||
234 | */ | ||
235 | static void atmel_ssc_shutdown(struct snd_pcm_substream *substream, | ||
236 | struct snd_soc_dai *dai) | ||
237 | { | ||
238 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
239 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
240 | struct atmel_pcm_dma_params *dma_params; | ||
241 | int dir, dir_mask; | ||
242 | |||
243 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
244 | dir = 0; | ||
245 | else | ||
246 | dir = 1; | ||
247 | |||
248 | dma_params = ssc_p->dma_params[dir]; | ||
249 | |||
250 | if (dma_params != NULL) { | ||
251 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable); | ||
252 | pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n", | ||
253 | (dir ? "receive" : "transmit"), | ||
254 | ssc_readl(ssc_p->ssc->regs, SR)); | ||
255 | |||
256 | dma_params->ssc = NULL; | ||
257 | dma_params->substream = NULL; | ||
258 | ssc_p->dma_params[dir] = NULL; | ||
259 | } | ||
260 | |||
261 | dir_mask = 1 << dir; | ||
262 | |||
263 | spin_lock_irq(&ssc_p->lock); | ||
264 | ssc_p->dir_mask &= ~dir_mask; | ||
265 | if (!ssc_p->dir_mask) { | ||
266 | if (ssc_p->initialized) { | ||
267 | /* Shutdown the SSC clock. */ | ||
268 | pr_debug("atmel_ssc_dau: Stopping clock\n"); | ||
269 | clk_disable(ssc_p->ssc->clk); | ||
270 | |||
271 | free_irq(ssc_p->ssc->irq, ssc_p); | ||
272 | ssc_p->initialized = 0; | ||
273 | } | ||
274 | |||
275 | /* Reset the SSC */ | ||
276 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | ||
277 | /* Clear the SSC dividers */ | ||
278 | ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0; | ||
279 | } | ||
280 | spin_unlock_irq(&ssc_p->lock); | ||
281 | } | ||
282 | |||
283 | |||
284 | /* | ||
285 | * Record the DAI format for use in hw_params(). | ||
286 | */ | ||
287 | static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
288 | unsigned int fmt) | ||
289 | { | ||
290 | struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
291 | |||
292 | ssc_p->daifmt = fmt; | ||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | /* | ||
297 | * Record SSC clock dividers for use in hw_params(). | ||
298 | */ | ||
299 | static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | ||
300 | int div_id, int div) | ||
301 | { | ||
302 | struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id]; | ||
303 | |||
304 | switch (div_id) { | ||
305 | case ATMEL_SSC_CMR_DIV: | ||
306 | /* | ||
307 | * The same master clock divider is used for both | ||
308 | * transmit and receive, so if a value has already | ||
309 | * been set, it must match this value. | ||
310 | */ | ||
311 | if (ssc_p->cmr_div == 0) | ||
312 | ssc_p->cmr_div = div; | ||
313 | else | ||
314 | if (div != ssc_p->cmr_div) | ||
315 | return -EBUSY; | ||
316 | break; | ||
317 | |||
318 | case ATMEL_SSC_TCMR_PERIOD: | ||
319 | ssc_p->tcmr_period = div; | ||
320 | break; | ||
321 | |||
322 | case ATMEL_SSC_RCMR_PERIOD: | ||
323 | ssc_p->rcmr_period = div; | ||
324 | break; | ||
325 | |||
326 | default: | ||
327 | return -EINVAL; | ||
328 | } | ||
329 | |||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | /* | ||
334 | * Configure the SSC. | ||
335 | */ | ||
336 | static int atmel_ssc_hw_params(struct snd_pcm_substream *substream, | ||
337 | struct snd_pcm_hw_params *params, | ||
338 | struct snd_soc_dai *dai) | ||
339 | { | ||
340 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
341 | int id = rtd->dai->cpu_dai->id; | ||
342 | struct atmel_ssc_info *ssc_p = &ssc_info[id]; | ||
343 | struct atmel_pcm_dma_params *dma_params; | ||
344 | int dir, channels, bits; | ||
345 | u32 tfmr, rfmr, tcmr, rcmr; | ||
346 | int start_event; | ||
347 | int ret; | ||
348 | |||
349 | /* | ||
350 | * Currently, there is only one set of dma params for | ||
351 | * each direction. If more are added, this code will | ||
352 | * have to be changed to select the proper set. | ||
353 | */ | ||
354 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
355 | dir = 0; | ||
356 | else | ||
357 | dir = 1; | ||
358 | |||
359 | dma_params = &ssc_dma_params[id][dir]; | ||
360 | dma_params->ssc = ssc_p->ssc; | ||
361 | dma_params->substream = substream; | ||
362 | |||
363 | ssc_p->dma_params[dir] = dma_params; | ||
364 | |||
365 | /* | ||
366 | * The cpu_dai->dma_data field is only used to communicate the | ||
367 | * appropriate DMA parameters to the pcm driver hw_params() | ||
368 | * function. It should not be used for other purposes | ||
369 | * as it is common to all substreams. | ||
370 | */ | ||
371 | rtd->dai->cpu_dai->dma_data = dma_params; | ||
372 | |||
373 | channels = params_channels(params); | ||
374 | |||
375 | /* | ||
376 | * Determine sample size in bits and the PDC increment. | ||
377 | */ | ||
378 | switch (params_format(params)) { | ||
379 | case SNDRV_PCM_FORMAT_S8: | ||
380 | bits = 8; | ||
381 | dma_params->pdc_xfer_size = 1; | ||
382 | break; | ||
383 | case SNDRV_PCM_FORMAT_S16_LE: | ||
384 | bits = 16; | ||
385 | dma_params->pdc_xfer_size = 2; | ||
386 | break; | ||
387 | case SNDRV_PCM_FORMAT_S24_LE: | ||
388 | bits = 24; | ||
389 | dma_params->pdc_xfer_size = 4; | ||
390 | break; | ||
391 | case SNDRV_PCM_FORMAT_S32_LE: | ||
392 | bits = 32; | ||
393 | dma_params->pdc_xfer_size = 4; | ||
394 | break; | ||
395 | default: | ||
396 | printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format"); | ||
397 | return -EINVAL; | ||
398 | } | ||
399 | |||
400 | /* | ||
401 | * The SSC only supports up to 16-bit samples in I2S format, due | ||
402 | * to the size of the Frame Mode Register FSLEN field. | ||
403 | */ | ||
404 | if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S | ||
405 | && bits > 16) { | ||
406 | printk(KERN_WARNING | ||
407 | "atmel_ssc_dai: sample size %d" | ||
408 | "is too large for I2S\n", bits); | ||
409 | return -EINVAL; | ||
410 | } | ||
411 | |||
412 | /* | ||
413 | * Compute SSC register settings. | ||
414 | */ | ||
415 | switch (ssc_p->daifmt | ||
416 | & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) { | ||
417 | |||
418 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS: | ||
419 | /* | ||
420 | * I2S format, SSC provides BCLK and LRC clocks. | ||
421 | * | ||
422 | * The SSC transmit and receive clocks are generated | ||
423 | * from the MCK divider, and the BCLK signal | ||
424 | * is output on the SSC TK line. | ||
425 | */ | ||
426 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | ||
427 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
428 | | SSC_BF(RCMR_START, SSC_START_FALLING_RF) | ||
429 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
430 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
431 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
432 | |||
433 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
434 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
435 | | SSC_BF(RFMR_FSLEN, (bits - 1)) | ||
436 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
437 | | SSC_BIT(RFMR_MSBF) | ||
438 | | SSC_BF(RFMR_LOOP, 0) | ||
439 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
440 | |||
441 | tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | ||
442 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
443 | | SSC_BF(TCMR_START, SSC_START_FALLING_RF) | ||
444 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
445 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
446 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
447 | |||
448 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
449 | | SSC_BF(TFMR_FSDEN, 0) | ||
450 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) | ||
451 | | SSC_BF(TFMR_FSLEN, (bits - 1)) | ||
452 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
453 | | SSC_BIT(TFMR_MSBF) | ||
454 | | SSC_BF(TFMR_DATDEF, 0) | ||
455 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
456 | break; | ||
457 | |||
458 | case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM: | ||
459 | /* | ||
460 | * I2S format, CODEC supplies BCLK and LRC clocks. | ||
461 | * | ||
462 | * The SSC transmit clock is obtained from the BCLK signal on | ||
463 | * on the TK line, and the SSC receive clock is | ||
464 | * generated from the transmit clock. | ||
465 | * | ||
466 | * For single channel data, one sample is transferred | ||
467 | * on the falling edge of the LRC clock. | ||
468 | * For two channel data, one sample is | ||
469 | * transferred on both edges of the LRC clock. | ||
470 | */ | ||
471 | start_event = ((channels == 1) | ||
472 | ? SSC_START_FALLING_RF | ||
473 | : SSC_START_EDGE_RF); | ||
474 | |||
475 | rcmr = SSC_BF(RCMR_PERIOD, 0) | ||
476 | | SSC_BF(RCMR_STTDLY, START_DELAY) | ||
477 | | SSC_BF(RCMR_START, start_event) | ||
478 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
479 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
480 | | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK); | ||
481 | |||
482 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
483 | | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) | ||
484 | | SSC_BF(RFMR_FSLEN, 0) | ||
485 | | SSC_BF(RFMR_DATNB, 0) | ||
486 | | SSC_BIT(RFMR_MSBF) | ||
487 | | SSC_BF(RFMR_LOOP, 0) | ||
488 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
489 | |||
490 | tcmr = SSC_BF(TCMR_PERIOD, 0) | ||
491 | | SSC_BF(TCMR_STTDLY, START_DELAY) | ||
492 | | SSC_BF(TCMR_START, start_event) | ||
493 | | SSC_BF(TCMR_CKI, SSC_CKI_FALLING) | ||
494 | | SSC_BF(TCMR_CKO, SSC_CKO_NONE) | ||
495 | | SSC_BF(TCMR_CKS, SSC_CKS_PIN); | ||
496 | |||
497 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
498 | | SSC_BF(TFMR_FSDEN, 0) | ||
499 | | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) | ||
500 | | SSC_BF(TFMR_FSLEN, 0) | ||
501 | | SSC_BF(TFMR_DATNB, 0) | ||
502 | | SSC_BIT(TFMR_MSBF) | ||
503 | | SSC_BF(TFMR_DATDEF, 0) | ||
504 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
505 | break; | ||
506 | |||
507 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS: | ||
508 | /* | ||
509 | * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks. | ||
510 | * | ||
511 | * The SSC transmit and receive clocks are generated from the | ||
512 | * MCK divider, and the BCLK signal is output | ||
513 | * on the SSC TK line. | ||
514 | */ | ||
515 | rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) | ||
516 | | SSC_BF(RCMR_STTDLY, 1) | ||
517 | | SSC_BF(RCMR_START, SSC_START_RISING_RF) | ||
518 | | SSC_BF(RCMR_CKI, SSC_CKI_RISING) | ||
519 | | SSC_BF(RCMR_CKO, SSC_CKO_NONE) | ||
520 | | SSC_BF(RCMR_CKS, SSC_CKS_DIV); | ||
521 | |||
522 | rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
523 | | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) | ||
524 | | SSC_BF(RFMR_FSLEN, 0) | ||
525 | | SSC_BF(RFMR_DATNB, (channels - 1)) | ||
526 | | SSC_BIT(RFMR_MSBF) | ||
527 | | SSC_BF(RFMR_LOOP, 0) | ||
528 | | SSC_BF(RFMR_DATLEN, (bits - 1)); | ||
529 | |||
530 | tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) | ||
531 | | SSC_BF(TCMR_STTDLY, 1) | ||
532 | | SSC_BF(TCMR_START, SSC_START_RISING_RF) | ||
533 | | SSC_BF(TCMR_CKI, SSC_CKI_RISING) | ||
534 | | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) | ||
535 | | SSC_BF(TCMR_CKS, SSC_CKS_DIV); | ||
536 | |||
537 | tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) | ||
538 | | SSC_BF(TFMR_FSDEN, 0) | ||
539 | | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) | ||
540 | | SSC_BF(TFMR_FSLEN, 0) | ||
541 | | SSC_BF(TFMR_DATNB, (channels - 1)) | ||
542 | | SSC_BIT(TFMR_MSBF) | ||
543 | | SSC_BF(TFMR_DATDEF, 0) | ||
544 | | SSC_BF(TFMR_DATLEN, (bits - 1)); | ||
545 | break; | ||
546 | |||
547 | case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM: | ||
548 | default: | ||
549 | printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n", | ||
550 | ssc_p->daifmt); | ||
551 | return -EINVAL; | ||
552 | break; | ||
553 | } | ||
554 | pr_debug("atmel_ssc_hw_params: " | ||
555 | "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", | ||
556 | rcmr, rfmr, tcmr, tfmr); | ||
557 | |||
558 | if (!ssc_p->initialized) { | ||
559 | |||
560 | /* Enable PMC peripheral clock for this SSC */ | ||
561 | pr_debug("atmel_ssc_dai: Starting clock\n"); | ||
562 | clk_enable(ssc_p->ssc->clk); | ||
563 | |||
564 | /* Reset the SSC and its PDC registers */ | ||
565 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST)); | ||
566 | |||
567 | ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0); | ||
568 | ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0); | ||
569 | ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0); | ||
570 | ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0); | ||
571 | |||
572 | ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0); | ||
573 | ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0); | ||
574 | ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0); | ||
575 | ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0); | ||
576 | |||
577 | ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0, | ||
578 | ssc_p->name, ssc_p); | ||
579 | if (ret < 0) { | ||
580 | printk(KERN_WARNING | ||
581 | "atmel_ssc_dai: request_irq failure\n"); | ||
582 | pr_debug("Atmel_ssc_dai: Stoping clock\n"); | ||
583 | clk_disable(ssc_p->ssc->clk); | ||
584 | return ret; | ||
585 | } | ||
586 | |||
587 | ssc_p->initialized = 1; | ||
588 | } | ||
589 | |||
590 | /* set SSC clock mode register */ | ||
591 | ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div); | ||
592 | |||
593 | /* set receive clock mode and format */ | ||
594 | ssc_writel(ssc_p->ssc->regs, RCMR, rcmr); | ||
595 | ssc_writel(ssc_p->ssc->regs, RFMR, rfmr); | ||
596 | |||
597 | /* set transmit clock mode and format */ | ||
598 | ssc_writel(ssc_p->ssc->regs, TCMR, tcmr); | ||
599 | ssc_writel(ssc_p->ssc->regs, TFMR, tfmr); | ||
600 | |||
601 | pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n"); | ||
602 | return 0; | ||
603 | } | ||
604 | |||
605 | |||
606 | static int atmel_ssc_prepare(struct snd_pcm_substream *substream, | ||
607 | struct snd_soc_dai *dai) | ||
608 | { | ||
609 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
610 | struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id]; | ||
611 | struct atmel_pcm_dma_params *dma_params; | ||
612 | int dir; | ||
613 | |||
614 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
615 | dir = 0; | ||
616 | else | ||
617 | dir = 1; | ||
618 | |||
619 | dma_params = ssc_p->dma_params[dir]; | ||
620 | |||
621 | ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable); | ||
622 | |||
623 | pr_debug("%s enabled SSC_SR=0x%08x\n", | ||
624 | dir ? "receive" : "transmit", | ||
625 | ssc_readl(ssc_p->ssc->regs, SR)); | ||
626 | return 0; | ||
627 | } | ||
628 | |||
629 | |||
630 | #ifdef CONFIG_PM | ||
631 | static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai) | ||
632 | { | ||
633 | struct atmel_ssc_info *ssc_p; | ||
634 | |||
635 | if (!cpu_dai->active) | ||
636 | return 0; | ||
637 | |||
638 | ssc_p = &ssc_info[cpu_dai->id]; | ||
639 | |||
640 | /* Save the status register before disabling transmit and receive */ | ||
641 | ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR); | ||
642 | ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS)); | ||
643 | |||
644 | /* Save the current interrupt mask, then disable unmasked interrupts */ | ||
645 | ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR); | ||
646 | ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr); | ||
647 | |||
648 | ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR); | ||
649 | ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR); | ||
650 | ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR); | ||
651 | ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR); | ||
652 | ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR); | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | |||
658 | |||
659 | static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai) | ||
660 | { | ||
661 | struct atmel_ssc_info *ssc_p; | ||
662 | u32 cr; | ||
663 | |||
664 | if (!cpu_dai->active) | ||
665 | return 0; | ||
666 | |||
667 | ssc_p = &ssc_info[cpu_dai->id]; | ||
668 | |||
669 | /* restore SSC register settings */ | ||
670 | ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr); | ||
671 | ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr); | ||
672 | ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr); | ||
673 | ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr); | ||
674 | ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr); | ||
675 | |||
676 | /* re-enable interrupts */ | ||
677 | ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr); | ||
678 | |||
679 | /* Re-enable recieve and transmit as appropriate */ | ||
680 | cr = 0; | ||
681 | cr |= | ||
682 | (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0; | ||
683 | cr |= | ||
684 | (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0; | ||
685 | ssc_writel(ssc_p->ssc->regs, CR, cr); | ||
686 | |||
687 | return 0; | ||
688 | } | ||
689 | #else /* CONFIG_PM */ | ||
690 | # define atmel_ssc_suspend NULL | ||
691 | # define atmel_ssc_resume NULL | ||
692 | #endif /* CONFIG_PM */ | ||
693 | |||
694 | |||
695 | #define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000) | ||
696 | |||
697 | #define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
698 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
699 | |||
700 | struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = { | ||
701 | { .name = "atmel-ssc0", | ||
702 | .id = 0, | ||
703 | .suspend = atmel_ssc_suspend, | ||
704 | .resume = atmel_ssc_resume, | ||
705 | .playback = { | ||
706 | .channels_min = 1, | ||
707 | .channels_max = 2, | ||
708 | .rates = ATMEL_SSC_RATES, | ||
709 | .formats = ATMEL_SSC_FORMATS,}, | ||
710 | .capture = { | ||
711 | .channels_min = 1, | ||
712 | .channels_max = 2, | ||
713 | .rates = ATMEL_SSC_RATES, | ||
714 | .formats = ATMEL_SSC_FORMATS,}, | ||
715 | .ops = { | ||
716 | .startup = atmel_ssc_startup, | ||
717 | .shutdown = atmel_ssc_shutdown, | ||
718 | .prepare = atmel_ssc_prepare, | ||
719 | .hw_params = atmel_ssc_hw_params, | ||
720 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
721 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
722 | .private_data = &ssc_info[0], | ||
723 | }, | ||
724 | #if NUM_SSC_DEVICES == 3 | ||
725 | { .name = "atmel-ssc1", | ||
726 | .id = 1, | ||
727 | .suspend = atmel_ssc_suspend, | ||
728 | .resume = atmel_ssc_resume, | ||
729 | .playback = { | ||
730 | .channels_min = 1, | ||
731 | .channels_max = 2, | ||
732 | .rates = ATMEL_SSC_RATES, | ||
733 | .formats = ATMEL_SSC_FORMATS,}, | ||
734 | .capture = { | ||
735 | .channels_min = 1, | ||
736 | .channels_max = 2, | ||
737 | .rates = ATMEL_SSC_RATES, | ||
738 | .formats = ATMEL_SSC_FORMATS,}, | ||
739 | .ops = { | ||
740 | .startup = atmel_ssc_startup, | ||
741 | .shutdown = atmel_ssc_shutdown, | ||
742 | .prepare = atmel_ssc_prepare, | ||
743 | .hw_params = atmel_ssc_hw_params, | ||
744 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
745 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
746 | .private_data = &ssc_info[1], | ||
747 | }, | ||
748 | { .name = "atmel-ssc2", | ||
749 | .id = 2, | ||
750 | .suspend = atmel_ssc_suspend, | ||
751 | .resume = atmel_ssc_resume, | ||
752 | .playback = { | ||
753 | .channels_min = 1, | ||
754 | .channels_max = 2, | ||
755 | .rates = ATMEL_SSC_RATES, | ||
756 | .formats = ATMEL_SSC_FORMATS,}, | ||
757 | .capture = { | ||
758 | .channels_min = 1, | ||
759 | .channels_max = 2, | ||
760 | .rates = ATMEL_SSC_RATES, | ||
761 | .formats = ATMEL_SSC_FORMATS,}, | ||
762 | .ops = { | ||
763 | .startup = atmel_ssc_startup, | ||
764 | .shutdown = atmel_ssc_shutdown, | ||
765 | .prepare = atmel_ssc_prepare, | ||
766 | .hw_params = atmel_ssc_hw_params, | ||
767 | .set_fmt = atmel_ssc_set_dai_fmt, | ||
768 | .set_clkdiv = atmel_ssc_set_dai_clkdiv,}, | ||
769 | .private_data = &ssc_info[2], | ||
770 | }, | ||
771 | #endif | ||
772 | }; | ||
773 | EXPORT_SYMBOL_GPL(atmel_ssc_dai); | ||
774 | |||
775 | static int __init atmel_ssc_modinit(void) | ||
776 | { | ||
777 | return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); | ||
778 | } | ||
779 | module_init(atmel_ssc_modinit); | ||
780 | |||
781 | static void __exit atmel_ssc_modexit(void) | ||
782 | { | ||
783 | snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai)); | ||
784 | } | ||
785 | module_exit(atmel_ssc_modexit); | ||
786 | |||
787 | /* Module information */ | ||
788 | MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com"); | ||
789 | MODULE_DESCRIPTION("ATMEL SSC ASoC Interface"); | ||
790 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h new file mode 100644 index 000000000000..a828746e8a2f --- /dev/null +++ b/sound/soc/atmel/atmel_ssc_dai.h | |||
@@ -0,0 +1,121 @@ | |||
1 | /* | ||
2 | * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC | ||
3 | * | ||
4 | * Copyright (C) 2005 SAN People | ||
5 | * Copyright (C) 2008 Atmel | ||
6 | * | ||
7 | * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
8 | * ATMEL CORP. | ||
9 | * | ||
10 | * Based on at91-ssc.c by | ||
11 | * Frank Mandarino <fmandarino@endrelia.com> | ||
12 | * Based on pxa2xx Platform drivers by | ||
13 | * Liam Girdwood <liam.girdwood@wolfsonmicro.com> | ||
14 | * | ||
15 | * This program is free software; you can redistribute it and/or modify | ||
16 | * it under the terms of the GNU General Public License as published by | ||
17 | * the Free Software Foundation; either version 2 of the License, or | ||
18 | * (at your option) any later version. | ||
19 | * | ||
20 | * This program is distributed in the hope that it will be useful, | ||
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
23 | * GNU General Public License for more details. | ||
24 | * | ||
25 | * You should have received a copy of the GNU General Public License | ||
26 | * along with this program; if not, write to the Free Software | ||
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
28 | */ | ||
29 | |||
30 | #ifndef _ATMEL_SSC_DAI_H | ||
31 | #define _ATMEL_SSC_DAI_H | ||
32 | |||
33 | #include <linux/types.h> | ||
34 | #include <linux/atmel-ssc.h> | ||
35 | |||
36 | #include "atmel-pcm.h" | ||
37 | |||
38 | /* SSC system clock ids */ | ||
39 | #define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */ | ||
40 | |||
41 | /* SSC divider ids */ | ||
42 | #define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */ | ||
43 | #define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */ | ||
44 | #define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */ | ||
45 | /* | ||
46 | * SSC direction masks | ||
47 | */ | ||
48 | #define SSC_DIR_MASK_UNUSED 0 | ||
49 | #define SSC_DIR_MASK_PLAYBACK 1 | ||
50 | #define SSC_DIR_MASK_CAPTURE 2 | ||
51 | |||
52 | /* | ||
53 | * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These | ||
54 | * are expected to be used with SSC_BF | ||
55 | */ | ||
56 | /* START bit field values */ | ||
57 | #define SSC_START_CONTINUOUS 0 | ||
58 | #define SSC_START_TX_RX 1 | ||
59 | #define SSC_START_LOW_RF 2 | ||
60 | #define SSC_START_HIGH_RF 3 | ||
61 | #define SSC_START_FALLING_RF 4 | ||
62 | #define SSC_START_RISING_RF 5 | ||
63 | #define SSC_START_LEVEL_RF 6 | ||
64 | #define SSC_START_EDGE_RF 7 | ||
65 | #define SSS_START_COMPARE_0 8 | ||
66 | |||
67 | /* CKI bit field values */ | ||
68 | #define SSC_CKI_FALLING 0 | ||
69 | #define SSC_CKI_RISING 1 | ||
70 | |||
71 | /* CKO bit field values */ | ||
72 | #define SSC_CKO_NONE 0 | ||
73 | #define SSC_CKO_CONTINUOUS 1 | ||
74 | #define SSC_CKO_TRANSFER 2 | ||
75 | |||
76 | /* CKS bit field values */ | ||
77 | #define SSC_CKS_DIV 0 | ||
78 | #define SSC_CKS_CLOCK 1 | ||
79 | #define SSC_CKS_PIN 2 | ||
80 | |||
81 | /* FSEDGE bit field values */ | ||
82 | #define SSC_FSEDGE_POSITIVE 0 | ||
83 | #define SSC_FSEDGE_NEGATIVE 1 | ||
84 | |||
85 | /* FSOS bit field values */ | ||
86 | #define SSC_FSOS_NONE 0 | ||
87 | #define SSC_FSOS_NEGATIVE 1 | ||
88 | #define SSC_FSOS_POSITIVE 2 | ||
89 | #define SSC_FSOS_LOW 3 | ||
90 | #define SSC_FSOS_HIGH 4 | ||
91 | #define SSC_FSOS_TOGGLE 5 | ||
92 | |||
93 | #define START_DELAY 1 | ||
94 | |||
95 | struct atmel_ssc_state { | ||
96 | u32 ssc_cmr; | ||
97 | u32 ssc_rcmr; | ||
98 | u32 ssc_rfmr; | ||
99 | u32 ssc_tcmr; | ||
100 | u32 ssc_tfmr; | ||
101 | u32 ssc_sr; | ||
102 | u32 ssc_imr; | ||
103 | }; | ||
104 | |||
105 | |||
106 | struct atmel_ssc_info { | ||
107 | char *name; | ||
108 | struct ssc_device *ssc; | ||
109 | spinlock_t lock; /* lock for dir_mask */ | ||
110 | unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */ | ||
111 | unsigned short initialized; /* true if SSC has been initialized */ | ||
112 | unsigned short daifmt; | ||
113 | unsigned short cmr_div; | ||
114 | unsigned short tcmr_period; | ||
115 | unsigned short rcmr_period; | ||
116 | struct atmel_pcm_dma_params *dma_params[2]; | ||
117 | struct atmel_ssc_state ssc_state; | ||
118 | }; | ||
119 | extern struct snd_soc_dai atmel_ssc_dai[]; | ||
120 | |||
121 | #endif /* _AT91_SSC_DAI_H */ | ||
diff --git a/sound/soc/at32/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c index b1966e4dfcd3..43dd8cee83c6 100644 --- a/sound/soc/at32/playpaq_wm8510.c +++ b/sound/soc/atmel/playpaq_wm8510.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/moduleparam.h> | 24 | #include <linux/moduleparam.h> |
25 | #include <linux/version.h> | ||
26 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
27 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
28 | #include <linux/clk.h> | 27 | #include <linux/clk.h> |
@@ -40,8 +39,8 @@ | |||
40 | #include <mach/portmux.h> | 39 | #include <mach/portmux.h> |
41 | 40 | ||
42 | #include "../codecs/wm8510.h" | 41 | #include "../codecs/wm8510.h" |
43 | #include "at32-pcm.h" | 42 | #include "atmel-pcm.h" |
44 | #include "at32-ssc.h" | 43 | #include "atmel_ssc_dai.h" |
45 | 44 | ||
46 | 45 | ||
47 | /*-------------------------------------------------------------------------*\ | 46 | /*-------------------------------------------------------------------------*\ |
@@ -362,8 +361,9 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = { | |||
362 | 361 | ||
363 | 362 | ||
364 | 363 | ||
365 | static struct snd_soc_machine snd_soc_machine_playpaq = { | 364 | static struct snd_soc_card snd_soc_playpaq = { |
366 | .name = "LRS_PlayPaq_WM8510", | 365 | .name = "LRS_PlayPaq_WM8510", |
366 | .platform = &at32_soc_platform, | ||
367 | .dai_link = &playpaq_wm8510_dai, | 367 | .dai_link = &playpaq_wm8510_dai, |
368 | .num_links = 1, | 368 | .num_links = 1, |
369 | }; | 369 | }; |
@@ -378,8 +378,7 @@ static struct wm8510_setup_data playpaq_wm8510_setup = { | |||
378 | 378 | ||
379 | 379 | ||
380 | static struct snd_soc_device playpaq_wm8510_snd_devdata = { | 380 | static struct snd_soc_device playpaq_wm8510_snd_devdata = { |
381 | .machine = &snd_soc_machine_playpaq, | 381 | .card = &snd_soc_playpaq, |
382 | .platform = &at32_soc_platform, | ||
383 | .codec_dev = &soc_codec_dev_wm8510, | 382 | .codec_dev = &soc_codec_dev_wm8510, |
384 | .codec_data = &playpaq_wm8510_setup, | 383 | .codec_data = &playpaq_wm8510_setup, |
385 | }; | 384 | }; |
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c new file mode 100644 index 000000000000..1fb59a9d3719 --- /dev/null +++ b/sound/soc/atmel/sam9g20_wm8731.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based | ||
3 | * ATMEL AT91SAM9G20ek board. | ||
4 | * | ||
5 | * Copyright (C) 2005 SAN People | ||
6 | * Copyright (C) 2008 Atmel | ||
7 | * | ||
8 | * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com> | ||
9 | * | ||
10 | * Based on ati_b1_wm8731.c by: | ||
11 | * Frank Mandarino <fmandarino@endrelia.com> | ||
12 | * Copyright 2006 Endrelia Technologies Inc. | ||
13 | * Based on corgi.c by: | ||
14 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
15 | * Copyright 2005 Openedhand Ltd. | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/kernel.h> | ||
35 | #include <linux/clk.h> | ||
36 | #include <linux/timer.h> | ||
37 | #include <linux/interrupt.h> | ||
38 | #include <linux/platform_device.h> | ||
39 | |||
40 | #include <linux/atmel-ssc.h> | ||
41 | |||
42 | #include <sound/core.h> | ||
43 | #include <sound/pcm.h> | ||
44 | #include <sound/pcm_params.h> | ||
45 | #include <sound/soc.h> | ||
46 | #include <sound/soc-dapm.h> | ||
47 | |||
48 | #include <mach/hardware.h> | ||
49 | #include <mach/gpio.h> | ||
50 | |||
51 | #include "../codecs/wm8731.h" | ||
52 | #include "atmel-pcm.h" | ||
53 | #include "atmel_ssc_dai.h" | ||
54 | |||
55 | |||
56 | static int at91sam9g20ek_startup(struct snd_pcm_substream *substream) | ||
57 | { | ||
58 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
59 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
60 | int ret; | ||
61 | |||
62 | /* codec system clock is supplied by PCK0, set to 12MHz */ | ||
63 | ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK, | ||
64 | 12000000, SND_SOC_CLOCK_IN); | ||
65 | if (ret < 0) | ||
66 | return ret; | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | |||
71 | static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream) | ||
72 | { | ||
73 | struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream); | ||
74 | |||
75 | dev_dbg(rtd->socdev->dev, "shutdown"); | ||
76 | } | ||
77 | |||
78 | static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream, | ||
79 | struct snd_pcm_hw_params *params) | ||
80 | { | ||
81 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
82 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
83 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
84 | struct atmel_ssc_info *ssc_p = cpu_dai->private_data; | ||
85 | struct ssc_device *ssc = ssc_p->ssc; | ||
86 | int ret; | ||
87 | |||
88 | unsigned int rate; | ||
89 | int cmr_div, period; | ||
90 | |||
91 | if (ssc == NULL) { | ||
92 | printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n"); | ||
93 | return -EINVAL; | ||
94 | } | ||
95 | |||
96 | /* set codec DAI configuration */ | ||
97 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
98 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
99 | if (ret < 0) | ||
100 | return ret; | ||
101 | |||
102 | /* set cpu DAI configuration */ | ||
103 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
104 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
105 | if (ret < 0) | ||
106 | return ret; | ||
107 | |||
108 | /* | ||
109 | * The SSC clock dividers depend on the sample rate. The CMR.DIV | ||
110 | * field divides the system master clock MCK to drive the SSC TK | ||
111 | * signal which provides the codec BCLK. The TCMR.PERIOD and | ||
112 | * RCMR.PERIOD fields further divide the BCLK signal to drive | ||
113 | * the SSC TF and RF signals which provide the codec DACLRC and | ||
114 | * ADCLRC clocks. | ||
115 | * | ||
116 | * The dividers were determined through trial and error, where a | ||
117 | * CMR.DIV value is chosen such that the resulting BCLK value is | ||
118 | * divisible, or almost divisible, by (2 * sample rate), and then | ||
119 | * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1. | ||
120 | */ | ||
121 | rate = params_rate(params); | ||
122 | |||
123 | switch (rate) { | ||
124 | case 8000: | ||
125 | cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */ | ||
126 | period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */ | ||
127 | break; | ||
128 | case 11025: | ||
129 | cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */ | ||
130 | period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */ | ||
131 | break; | ||
132 | case 16000: | ||
133 | cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */ | ||
134 | period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */ | ||
135 | break; | ||
136 | case 22050: | ||
137 | cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */ | ||
138 | period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */ | ||
139 | break; | ||
140 | case 32000: | ||
141 | cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */ | ||
142 | period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */ | ||
143 | break; | ||
144 | case 44100: | ||
145 | cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ | ||
146 | period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */ | ||
147 | break; | ||
148 | case 48000: | ||
149 | cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */ | ||
150 | period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */ | ||
151 | break; | ||
152 | case 88200: | ||
153 | cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */ | ||
154 | period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */ | ||
155 | break; | ||
156 | case 96000: | ||
157 | cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */ | ||
158 | period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */ | ||
159 | break; | ||
160 | default: | ||
161 | printk(KERN_WARNING "unsupported rate %d" | ||
162 | " on at91sam9g20ek board\n", rate); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | /* set the MCK divider for BCLK */ | ||
167 | ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div); | ||
168 | if (ret < 0) | ||
169 | return ret; | ||
170 | |||
171 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
172 | /* set the BCLK divider for DACLRC */ | ||
173 | ret = snd_soc_dai_set_clkdiv(cpu_dai, | ||
174 | ATMEL_SSC_TCMR_PERIOD, period); | ||
175 | } else { | ||
176 | /* set the BCLK divider for ADCLRC */ | ||
177 | ret = snd_soc_dai_set_clkdiv(cpu_dai, | ||
178 | ATMEL_SSC_RCMR_PERIOD, period); | ||
179 | } | ||
180 | if (ret < 0) | ||
181 | return ret; | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static struct snd_soc_ops at91sam9g20ek_ops = { | ||
187 | .startup = at91sam9g20ek_startup, | ||
188 | .hw_params = at91sam9g20ek_hw_params, | ||
189 | .shutdown = at91sam9g20ek_shutdown, | ||
190 | }; | ||
191 | |||
192 | |||
193 | static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = { | ||
194 | SND_SOC_DAPM_MIC("Int Mic", NULL), | ||
195 | SND_SOC_DAPM_SPK("Ext Spk", NULL), | ||
196 | }; | ||
197 | |||
198 | static const struct snd_soc_dapm_route intercon[] = { | ||
199 | |||
200 | /* speaker connected to LHPOUT */ | ||
201 | {"Ext Spk", NULL, "LHPOUT"}, | ||
202 | |||
203 | /* mic is connected to Mic Jack, with WM8731 Mic Bias */ | ||
204 | {"MICIN", NULL, "Mic Bias"}, | ||
205 | {"Mic Bias", NULL, "Int Mic"}, | ||
206 | }; | ||
207 | |||
208 | /* | ||
209 | * Logic for a wm8731 as connected on a at91sam9g20ek board. | ||
210 | */ | ||
211 | static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec) | ||
212 | { | ||
213 | printk(KERN_DEBUG | ||
214 | "at91sam9g20ek_wm8731 " | ||
215 | ": at91sam9g20ek_wm8731_init() called\n"); | ||
216 | |||
217 | /* Add specific widgets */ | ||
218 | snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets, | ||
219 | ARRAY_SIZE(at91sam9g20ek_dapm_widgets)); | ||
220 | /* Set up specific audio path interconnects */ | ||
221 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
222 | |||
223 | /* not connected */ | ||
224 | snd_soc_dapm_disable_pin(codec, "RLINEIN"); | ||
225 | snd_soc_dapm_disable_pin(codec, "LLINEIN"); | ||
226 | |||
227 | /* always connected */ | ||
228 | snd_soc_dapm_enable_pin(codec, "Int Mic"); | ||
229 | snd_soc_dapm_enable_pin(codec, "Ext Spk"); | ||
230 | |||
231 | snd_soc_dapm_sync(codec); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static struct snd_soc_dai_link at91sam9g20ek_dai = { | ||
237 | .name = "WM8731", | ||
238 | .stream_name = "WM8731 PCM", | ||
239 | .cpu_dai = &atmel_ssc_dai[0], | ||
240 | .codec_dai = &wm8731_dai, | ||
241 | .init = at91sam9g20ek_wm8731_init, | ||
242 | .ops = &at91sam9g20ek_ops, | ||
243 | }; | ||
244 | |||
245 | static struct snd_soc_card snd_soc_at91sam9g20ek = { | ||
246 | .name = "WM8731", | ||
247 | .platform = &atmel_soc_platform, | ||
248 | .dai_link = &at91sam9g20ek_dai, | ||
249 | .num_links = 1, | ||
250 | }; | ||
251 | |||
252 | static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = { | ||
253 | .i2c_bus = 0, | ||
254 | .i2c_address = 0x1b, | ||
255 | }; | ||
256 | |||
257 | static struct snd_soc_device at91sam9g20ek_snd_devdata = { | ||
258 | .card = &snd_soc_at91sam9g20ek, | ||
259 | .codec_dev = &soc_codec_dev_wm8731, | ||
260 | .codec_data = &at91sam9g20ek_wm8731_setup, | ||
261 | }; | ||
262 | |||
263 | static struct platform_device *at91sam9g20ek_snd_device; | ||
264 | |||
265 | static int __init at91sam9g20ek_init(void) | ||
266 | { | ||
267 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; | ||
268 | struct ssc_device *ssc = NULL; | ||
269 | int ret; | ||
270 | |||
271 | /* | ||
272 | * Request SSC device | ||
273 | */ | ||
274 | ssc = ssc_request(0); | ||
275 | if (IS_ERR(ssc)) { | ||
276 | ret = PTR_ERR(ssc); | ||
277 | ssc = NULL; | ||
278 | goto err_ssc; | ||
279 | } | ||
280 | ssc_p->ssc = ssc; | ||
281 | |||
282 | at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1); | ||
283 | if (!at91sam9g20ek_snd_device) { | ||
284 | printk(KERN_DEBUG | ||
285 | "platform device allocation failed\n"); | ||
286 | ret = -ENOMEM; | ||
287 | } | ||
288 | |||
289 | platform_set_drvdata(at91sam9g20ek_snd_device, | ||
290 | &at91sam9g20ek_snd_devdata); | ||
291 | at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev; | ||
292 | |||
293 | ret = platform_device_add(at91sam9g20ek_snd_device); | ||
294 | if (ret) { | ||
295 | printk(KERN_DEBUG | ||
296 | "platform device allocation failed\n"); | ||
297 | platform_device_put(at91sam9g20ek_snd_device); | ||
298 | } | ||
299 | |||
300 | return ret; | ||
301 | |||
302 | err_ssc: | ||
303 | return ret; | ||
304 | } | ||
305 | |||
306 | static void __exit at91sam9g20ek_exit(void) | ||
307 | { | ||
308 | struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data; | ||
309 | struct ssc_device *ssc; | ||
310 | |||
311 | if (ssc_p != NULL) { | ||
312 | ssc = ssc_p->ssc; | ||
313 | if (ssc != NULL) | ||
314 | ssc_free(ssc); | ||
315 | ssc_p->ssc = NULL; | ||
316 | } | ||
317 | |||
318 | platform_device_unregister(at91sam9g20ek_snd_device); | ||
319 | at91sam9g20ek_snd_device = NULL; | ||
320 | } | ||
321 | |||
322 | module_init(at91sam9g20ek_init); | ||
323 | module_exit(at91sam9g20ek_exit); | ||
324 | |||
325 | /* Module information */ | ||
326 | MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>"); | ||
327 | MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731"); | ||
328 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c index 1466d9328800..74c823d60f91 100644 --- a/sound/soc/au1x/dbdma2.c +++ b/sound/soc/au1x/dbdma2.c | |||
@@ -406,11 +406,12 @@ static int __init au1xpsc_audio_dbdma_init(void) | |||
406 | { | 406 | { |
407 | au1xpsc_audio_pcmdma[PCM_TX] = NULL; | 407 | au1xpsc_audio_pcmdma[PCM_TX] = NULL; |
408 | au1xpsc_audio_pcmdma[PCM_RX] = NULL; | 408 | au1xpsc_audio_pcmdma[PCM_RX] = NULL; |
409 | return 0; | 409 | return snd_soc_register_platform(&au1xpsc_soc_platform); |
410 | } | 410 | } |
411 | 411 | ||
412 | static void __exit au1xpsc_audio_dbdma_exit(void) | 412 | static void __exit au1xpsc_audio_dbdma_exit(void) |
413 | { | 413 | { |
414 | snd_soc_unregister_platform(&au1xpsc_soc_platform); | ||
414 | } | 415 | } |
415 | 416 | ||
416 | module_init(au1xpsc_audio_dbdma_init); | 417 | module_init(au1xpsc_audio_dbdma_init); |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 57facbad6825..f0e30aec7f23 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -160,7 +160,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = { | |||
160 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 160 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
161 | 161 | ||
162 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | 162 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, |
163 | struct snd_pcm_hw_params *params) | 163 | struct snd_pcm_hw_params *params, |
164 | struct snd_soc_dai *dai) | ||
164 | { | 165 | { |
165 | /* FIXME */ | 166 | /* FIXME */ |
166 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | 167 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; |
@@ -210,7 +211,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | |||
210 | } | 211 | } |
211 | 212 | ||
212 | static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, | 213 | static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream, |
213 | int cmd) | 214 | int cmd, struct snd_soc_dai *dai) |
214 | { | 215 | { |
215 | /* FIXME */ | 216 | /* FIXME */ |
216 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; | 217 | struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; |
@@ -313,8 +314,7 @@ static void au1xpsc_ac97_remove(struct platform_device *pdev, | |||
313 | au1xpsc_ac97_workdata = NULL; | 314 | au1xpsc_ac97_workdata = NULL; |
314 | } | 315 | } |
315 | 316 | ||
316 | static int au1xpsc_ac97_suspend(struct platform_device *pdev, | 317 | static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai) |
317 | struct snd_soc_dai *dai) | ||
318 | { | 318 | { |
319 | /* save interesting registers and disable PSC */ | 319 | /* save interesting registers and disable PSC */ |
320 | au1xpsc_ac97_workdata->pm[0] = | 320 | au1xpsc_ac97_workdata->pm[0] = |
@@ -328,8 +328,7 @@ static int au1xpsc_ac97_suspend(struct platform_device *pdev, | |||
328 | return 0; | 328 | return 0; |
329 | } | 329 | } |
330 | 330 | ||
331 | static int au1xpsc_ac97_resume(struct platform_device *pdev, | 331 | static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) |
332 | struct snd_soc_dai *dai) | ||
333 | { | 332 | { |
334 | /* restore PSC clock config */ | 333 | /* restore PSC clock config */ |
335 | au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, | 334 | au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, |
@@ -345,7 +344,7 @@ static int au1xpsc_ac97_resume(struct platform_device *pdev, | |||
345 | 344 | ||
346 | struct snd_soc_dai au1xpsc_ac97_dai = { | 345 | struct snd_soc_dai au1xpsc_ac97_dai = { |
347 | .name = "au1xpsc_ac97", | 346 | .name = "au1xpsc_ac97", |
348 | .type = SND_SOC_DAI_AC97, | 347 | .ac97_control = 1, |
349 | .probe = au1xpsc_ac97_probe, | 348 | .probe = au1xpsc_ac97_probe, |
350 | .remove = au1xpsc_ac97_remove, | 349 | .remove = au1xpsc_ac97_remove, |
351 | .suspend = au1xpsc_ac97_suspend, | 350 | .suspend = au1xpsc_ac97_suspend, |
@@ -372,11 +371,12 @@ EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai); | |||
372 | static int __init au1xpsc_ac97_init(void) | 371 | static int __init au1xpsc_ac97_init(void) |
373 | { | 372 | { |
374 | au1xpsc_ac97_workdata = NULL; | 373 | au1xpsc_ac97_workdata = NULL; |
375 | return 0; | 374 | return snd_soc_register_dai(&au1xpsc_ac97_dai); |
376 | } | 375 | } |
377 | 376 | ||
378 | static void __exit au1xpsc_ac97_exit(void) | 377 | static void __exit au1xpsc_ac97_exit(void) |
379 | { | 378 | { |
379 | snd_soc_unregister_dai(&au1xpsc_ac97_dai); | ||
380 | } | 380 | } |
381 | 381 | ||
382 | module_init(au1xpsc_ac97_init); | 382 | module_init(au1xpsc_ac97_init); |
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c index 9384702c7ebd..f916de4400ed 100644 --- a/sound/soc/au1x/psc-i2s.c +++ b/sound/soc/au1x/psc-i2s.c | |||
@@ -116,7 +116,8 @@ out: | |||
116 | } | 116 | } |
117 | 117 | ||
118 | static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, | 118 | static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream, |
119 | struct snd_pcm_hw_params *params) | 119 | struct snd_pcm_hw_params *params, |
120 | struct snd_soc_dai *dai) | ||
120 | { | 121 | { |
121 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; | 122 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; |
122 | 123 | ||
@@ -240,7 +241,8 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype) | |||
240 | return 0; | 241 | return 0; |
241 | } | 242 | } |
242 | 243 | ||
243 | static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 244 | static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
245 | struct snd_soc_dai *dai) | ||
244 | { | 246 | { |
245 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; | 247 | struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata; |
246 | int ret, stype = SUBSTREAM_TYPE(substream); | 248 | int ret, stype = SUBSTREAM_TYPE(substream); |
@@ -337,8 +339,7 @@ static void au1xpsc_i2s_remove(struct platform_device *pdev, | |||
337 | au1xpsc_i2s_workdata = NULL; | 339 | au1xpsc_i2s_workdata = NULL; |
338 | } | 340 | } |
339 | 341 | ||
340 | static int au1xpsc_i2s_suspend(struct platform_device *pdev, | 342 | static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai) |
341 | struct snd_soc_dai *cpu_dai) | ||
342 | { | 343 | { |
343 | /* save interesting register and disable PSC */ | 344 | /* save interesting register and disable PSC */ |
344 | au1xpsc_i2s_workdata->pm[0] = | 345 | au1xpsc_i2s_workdata->pm[0] = |
@@ -352,8 +353,7 @@ static int au1xpsc_i2s_suspend(struct platform_device *pdev, | |||
352 | return 0; | 353 | return 0; |
353 | } | 354 | } |
354 | 355 | ||
355 | static int au1xpsc_i2s_resume(struct platform_device *pdev, | 356 | static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai) |
356 | struct snd_soc_dai *cpu_dai) | ||
357 | { | 357 | { |
358 | /* select I2S mode and PSC clock */ | 358 | /* select I2S mode and PSC clock */ |
359 | au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); | 359 | au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); |
@@ -369,7 +369,6 @@ static int au1xpsc_i2s_resume(struct platform_device *pdev, | |||
369 | 369 | ||
370 | struct snd_soc_dai au1xpsc_i2s_dai = { | 370 | struct snd_soc_dai au1xpsc_i2s_dai = { |
371 | .name = "au1xpsc_i2s", | 371 | .name = "au1xpsc_i2s", |
372 | .type = SND_SOC_DAI_I2S, | ||
373 | .probe = au1xpsc_i2s_probe, | 372 | .probe = au1xpsc_i2s_probe, |
374 | .remove = au1xpsc_i2s_remove, | 373 | .remove = au1xpsc_i2s_remove, |
375 | .suspend = au1xpsc_i2s_suspend, | 374 | .suspend = au1xpsc_i2s_suspend, |
@@ -389,8 +388,6 @@ struct snd_soc_dai au1xpsc_i2s_dai = { | |||
389 | .ops = { | 388 | .ops = { |
390 | .trigger = au1xpsc_i2s_trigger, | 389 | .trigger = au1xpsc_i2s_trigger, |
391 | .hw_params = au1xpsc_i2s_hw_params, | 390 | .hw_params = au1xpsc_i2s_hw_params, |
392 | }, | ||
393 | .dai_ops = { | ||
394 | .set_fmt = au1xpsc_i2s_set_fmt, | 391 | .set_fmt = au1xpsc_i2s_set_fmt, |
395 | }, | 392 | }, |
396 | }; | 393 | }; |
@@ -399,11 +396,12 @@ EXPORT_SYMBOL(au1xpsc_i2s_dai); | |||
399 | static int __init au1xpsc_i2s_init(void) | 396 | static int __init au1xpsc_i2s_init(void) |
400 | { | 397 | { |
401 | au1xpsc_i2s_workdata = NULL; | 398 | au1xpsc_i2s_workdata = NULL; |
402 | return 0; | 399 | return snd_soc_register_dai(&au1xpsc_i2s_dai); |
403 | } | 400 | } |
404 | 401 | ||
405 | static void __exit au1xpsc_i2s_exit(void) | 402 | static void __exit au1xpsc_i2s_exit(void) |
406 | { | 403 | { |
404 | snd_soc_unregister_dai(&au1xpsc_i2s_dai); | ||
407 | } | 405 | } |
408 | 406 | ||
409 | module_init(au1xpsc_i2s_init); | 407 | module_init(au1xpsc_i2s_init); |
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c index f75ae7f62c3d..27683eb7905e 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 = { | |||
42 | .ops = NULL, | 42 | .ops = NULL, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct snd_soc_machine au1xpsc_sample_ac97_machine = { | 45 | static struct snd_soc_card au1xpsc_sample_ac97_machine = { |
46 | .name = "Au1xxx PSC AC97 Audio", | 46 | .name = "Au1xxx PSC AC97 Audio", |
47 | .dai_link = &au1xpsc_sample_ac97_dai, | 47 | .dai_link = &au1xpsc_sample_ac97_dai, |
48 | .num_links = 1, | 48 | .num_links = 1, |
49 | }; | 49 | }; |
50 | 50 | ||
51 | static struct snd_soc_device au1xpsc_sample_ac97_devdata = { | 51 | static struct snd_soc_device au1xpsc_sample_ac97_devdata = { |
52 | .machine = &au1xpsc_sample_ac97_machine, | 52 | .card = &au1xpsc_sample_ac97_machine, |
53 | .platform = &au1xpsc_soc_platform, /* see dbdma2.c */ | 53 | .platform = &au1xpsc_soc_platform, /* see dbdma2.c */ |
54 | .codec_dev = &soc_codec_dev_ac97, | 54 | .codec_dev = &soc_codec_dev_ac97, |
55 | }; | 55 | }; |
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig index dc006206f622..0a2f8f9eff53 100644 --- a/sound/soc/blackfin/Kconfig +++ b/sound/soc/blackfin/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_BF5XX_I2S | 1 | config SND_BF5XX_I2S |
2 | tristate "SoC I2S Audio for the ADI BF5xx chip" | 2 | tristate "SoC I2S Audio for the ADI BF5xx chip" |
3 | depends on BLACKFIN && SND_SOC | 3 | depends on BLACKFIN |
4 | help | 4 | help |
5 | Say Y or M if you want to add support for codecs attached to | 5 | Say Y or M if you want to add support for codecs attached to |
6 | the Blackfin SPORT (synchronous serial ports) interface in I2S | 6 | the Blackfin SPORT (synchronous serial ports) interface in I2S |
@@ -13,7 +13,6 @@ config SND_BF5XX_SOC_SSM2602 | |||
13 | select SND_BF5XX_SOC_I2S | 13 | select SND_BF5XX_SOC_I2S |
14 | select SND_SOC_SSM2602 | 14 | select SND_SOC_SSM2602 |
15 | select I2C | 15 | select I2C |
16 | select I2C_BLACKFIN_TWI | ||
17 | help | 16 | help |
18 | Say Y if you want to add support for SoC audio on BF527-EZKIT. | 17 | Say Y if you want to add support for SoC audio on BF527-EZKIT. |
19 | 18 | ||
@@ -35,7 +34,7 @@ config SND_BFIN_AD73311_SE | |||
35 | 34 | ||
36 | config SND_BF5XX_AC97 | 35 | config SND_BF5XX_AC97 |
37 | tristate "SoC AC97 Audio for the ADI BF5xx chip" | 36 | tristate "SoC AC97 Audio for the ADI BF5xx chip" |
38 | depends on BLACKFIN && SND_SOC | 37 | depends on BLACKFIN |
39 | help | 38 | help |
40 | Say Y or M if you want to add support for codecs attached to | 39 | Say Y or M if you want to add support for codecs attached to |
41 | the Blackfin SPORT (synchronous serial ports) interface in slot 16 | 40 | the Blackfin SPORT (synchronous serial ports) interface in slot 16 |
@@ -47,7 +46,7 @@ config SND_BF5XX_AC97 | |||
47 | properly with this driver. This driver is known to work with the | 46 | properly with this driver. This driver is known to work with the |
48 | Analog Devices line of AC97 codecs. | 47 | Analog Devices line of AC97 codecs. |
49 | 48 | ||
50 | config SND_MMAP_SUPPORT | 49 | config SND_BF5XX_MMAP_SUPPORT |
51 | bool "Enable MMAP Support" | 50 | bool "Enable MMAP Support" |
52 | depends on SND_BF5XX_AC97 | 51 | depends on SND_BF5XX_AC97 |
53 | default y | 52 | default y |
@@ -55,9 +54,17 @@ config SND_MMAP_SUPPORT | |||
55 | Say y if you want AC97 driver to support mmap mode. | 54 | Say y if you want AC97 driver to support mmap mode. |
56 | We introduce an intermediate buffer to simulate mmap. | 55 | We introduce an intermediate buffer to simulate mmap. |
57 | 56 | ||
57 | config SND_BF5XX_MULTICHAN_SUPPORT | ||
58 | bool "Enable Multichannel Support" | ||
59 | depends on SND_BF5XX_AC97 | ||
60 | default n | ||
61 | help | ||
62 | Say y if you want AC97 driver to support up to 5.1 channel audio. | ||
63 | this mode will consume much more memory for DMA. | ||
64 | |||
58 | config SND_BF5XX_SOC_SPORT | 65 | config SND_BF5XX_SOC_SPORT |
59 | tristate | 66 | tristate |
60 | 67 | ||
61 | config SND_BF5XX_SOC_I2S | 68 | config SND_BF5XX_SOC_I2S |
62 | tristate | 69 | tristate |
63 | select SND_BF5XX_SOC_SPORT | 70 | select SND_BF5XX_SOC_SPORT |
@@ -80,7 +87,7 @@ config SND_BF5XX_SPORT_NUM | |||
80 | int "Set a SPORT for Sound chip" | 87 | int "Set a SPORT for Sound chip" |
81 | depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) | 88 | depends on (SND_BF5XX_I2S || SND_BF5XX_AC97) |
82 | range 0 3 if BF54x | 89 | range 0 3 if BF54x |
83 | range 0 1 if (BF53x || BF561) | 90 | range 0 1 if !BF54x |
84 | default 0 | 91 | default 0 |
85 | help | 92 | help |
86 | Set the correct SPORT for sound chip. | 93 | Set the correct SPORT for sound chip. |
@@ -90,12 +97,13 @@ config SND_BF5XX_HAVE_COLD_RESET | |||
90 | depends on SND_BF5XX_AC97 | 97 | depends on SND_BF5XX_AC97 |
91 | default y if BFIN548_EZKIT | 98 | default y if BFIN548_EZKIT |
92 | default n if !BFIN548_EZKIT | 99 | default n if !BFIN548_EZKIT |
93 | 100 | ||
94 | config SND_BF5XX_RESET_GPIO_NUM | 101 | config SND_BF5XX_RESET_GPIO_NUM |
95 | int "Set a GPIO for cold reset" | 102 | int "Set a GPIO for cold reset" |
96 | depends on SND_BF5XX_HAVE_COLD_RESET | 103 | depends on SND_BF5XX_HAVE_COLD_RESET |
97 | range 0 159 | 104 | range 0 159 |
98 | default 19 if BFIN548_EZKIT | 105 | default 19 if BFIN548_EZKIT |
99 | default 5 if BFIN537_STAMP | 106 | default 5 if BFIN537_STAMP |
107 | default 0 | ||
100 | help | 108 | help |
101 | Set the correct GPIO for RESET the sound chip. | 109 | 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 25e50d2ea1ec..8067cfafa3a7 100644 --- a/sound/soc/blackfin/bf5xx-ac97-pcm.c +++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c | |||
@@ -43,24 +43,34 @@ | |||
43 | #include "bf5xx-ac97.h" | 43 | #include "bf5xx-ac97.h" |
44 | #include "bf5xx-sport.h" | 44 | #include "bf5xx-sport.h" |
45 | 45 | ||
46 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 46 | static unsigned int ac97_chan_mask[] = { |
47 | SP_FL, /* Mono */ | ||
48 | SP_STEREO, /* Stereo */ | ||
49 | SP_2DOT1, /* 2.1*/ | ||
50 | SP_QUAD,/*Quadraquic*/ | ||
51 | SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */ | ||
52 | SP_5DOT1, /* 5.1 */ | ||
53 | }; | ||
54 | |||
55 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
47 | static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, | 56 | static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, |
48 | snd_pcm_uframes_t count) | 57 | snd_pcm_uframes_t count) |
49 | { | 58 | { |
50 | struct snd_pcm_runtime *runtime = substream->runtime; | 59 | struct snd_pcm_runtime *runtime = substream->runtime; |
51 | struct sport_device *sport = runtime->private_data; | 60 | struct sport_device *sport = runtime->private_data; |
61 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; | ||
52 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 62 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
53 | bf5xx_pcm_to_ac97( | 63 | bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf + |
54 | (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos, | 64 | sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos * |
55 | (__u32 *)runtime->dma_area + sport->tx_pos, count); | 65 | runtime->channels, count, chan_mask); |
56 | sport->tx_pos += runtime->period_size; | 66 | sport->tx_pos += runtime->period_size; |
57 | if (sport->tx_pos >= runtime->buffer_size) | 67 | if (sport->tx_pos >= runtime->buffer_size) |
58 | sport->tx_pos %= runtime->buffer_size; | 68 | sport->tx_pos %= runtime->buffer_size; |
59 | sport->tx_delay_pos = sport->tx_pos; | 69 | sport->tx_delay_pos = sport->tx_pos; |
60 | } else { | 70 | } else { |
61 | bf5xx_ac97_to_pcm( | 71 | bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf + |
62 | (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos, | 72 | sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos * |
63 | (__u32 *)runtime->dma_area + sport->rx_pos, count); | 73 | runtime->channels, count); |
64 | sport->rx_pos += runtime->period_size; | 74 | sport->rx_pos += runtime->period_size; |
65 | if (sport->rx_pos >= runtime->buffer_size) | 75 | if (sport->rx_pos >= runtime->buffer_size) |
66 | sport->rx_pos %= runtime->buffer_size; | 76 | sport->rx_pos %= runtime->buffer_size; |
@@ -71,7 +81,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream, | |||
71 | static void bf5xx_dma_irq(void *data) | 81 | static void bf5xx_dma_irq(void *data) |
72 | { | 82 | { |
73 | struct snd_pcm_substream *pcm = data; | 83 | struct snd_pcm_substream *pcm = data; |
74 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 84 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
75 | struct snd_pcm_runtime *runtime = pcm->runtime; | 85 | struct snd_pcm_runtime *runtime = pcm->runtime; |
76 | struct sport_device *sport = runtime->private_data; | 86 | struct sport_device *sport = runtime->private_data; |
77 | bf5xx_mmap_copy(pcm, runtime->period_size); | 87 | bf5xx_mmap_copy(pcm, runtime->period_size); |
@@ -90,17 +100,14 @@ static void bf5xx_dma_irq(void *data) | |||
90 | * The total rx/tx buffer is for ac97 frame to hold all pcm data | 100 | * The total rx/tx buffer is for ac97 frame to hold all pcm data |
91 | * is 0x20000 * sizeof(struct ac97_frame) / 4. | 101 | * is 0x20000 * sizeof(struct ac97_frame) / 4. |
92 | */ | 102 | */ |
93 | #ifdef CONFIG_SND_MMAP_SUPPORT | ||
94 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | 103 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { |
95 | .info = SNDRV_PCM_INFO_INTERLEAVED | | 104 | .info = SNDRV_PCM_INFO_INTERLEAVED | |
105 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
96 | SNDRV_PCM_INFO_MMAP | | 106 | SNDRV_PCM_INFO_MMAP | |
97 | SNDRV_PCM_INFO_MMAP_VALID | | 107 | SNDRV_PCM_INFO_MMAP_VALID | |
98 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
99 | #else | ||
100 | static const struct snd_pcm_hardware bf5xx_pcm_hardware = { | ||
101 | .info = SNDRV_PCM_INFO_INTERLEAVED | | ||
102 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
103 | #endif | 108 | #endif |
109 | SNDRV_PCM_INFO_BLOCK_TRANSFER, | ||
110 | |||
104 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 111 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
105 | .period_bytes_min = 32, | 112 | .period_bytes_min = 32, |
106 | .period_bytes_max = 0x10000, | 113 | .period_bytes_max = 0x10000, |
@@ -123,10 +130,20 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream, | |||
123 | 130 | ||
124 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) | 131 | static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream) |
125 | { | 132 | { |
133 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
126 | struct snd_pcm_runtime *runtime = substream->runtime; | 134 | struct snd_pcm_runtime *runtime = substream->runtime; |
135 | struct sport_device *sport = runtime->private_data; | ||
127 | 136 | ||
128 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 137 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
129 | memset(runtime->dma_area, 0, runtime->buffer_size); | 138 | sport->once = 0; |
139 | if (runtime->dma_area) | ||
140 | memset(runtime->dma_area, 0, runtime->buffer_size); | ||
141 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * | ||
142 | sizeof(struct ac97_frame)); | ||
143 | } else | ||
144 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * | ||
145 | sizeof(struct ac97_frame)); | ||
146 | #endif | ||
130 | snd_pcm_lib_free_pages(substream); | 147 | snd_pcm_lib_free_pages(substream); |
131 | return 0; | 148 | return 0; |
132 | } | 149 | } |
@@ -139,7 +156,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream) | |||
139 | /* An intermediate buffer is introduced for implementing mmap for | 156 | /* An intermediate buffer is introduced for implementing mmap for |
140 | * SPORT working in TMD mode(include AC97). | 157 | * SPORT working in TMD mode(include AC97). |
141 | */ | 158 | */ |
142 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 159 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
143 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 160 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
144 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); | 161 | sport_set_tx_callback(sport, bf5xx_dma_irq, substream); |
145 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, | 162 | sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods, |
@@ -173,24 +190,24 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
173 | switch (cmd) { | 190 | switch (cmd) { |
174 | case SNDRV_PCM_TRIGGER_START: | 191 | case SNDRV_PCM_TRIGGER_START: |
175 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 192 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
193 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) | ||
176 | bf5xx_mmap_copy(substream, runtime->period_size); | 194 | bf5xx_mmap_copy(substream, runtime->period_size); |
177 | snd_pcm_period_elapsed(substream); | ||
178 | sport->tx_delay_pos = 0; | 195 | sport->tx_delay_pos = 0; |
196 | #endif | ||
179 | sport_tx_start(sport); | 197 | sport_tx_start(sport); |
180 | } | 198 | } else |
181 | else | ||
182 | sport_rx_start(sport); | 199 | sport_rx_start(sport); |
183 | break; | 200 | break; |
184 | case SNDRV_PCM_TRIGGER_STOP: | 201 | case SNDRV_PCM_TRIGGER_STOP: |
185 | case SNDRV_PCM_TRIGGER_SUSPEND: | 202 | case SNDRV_PCM_TRIGGER_SUSPEND: |
186 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | 203 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: |
187 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 204 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
188 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 205 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
189 | sport->tx_pos = 0; | 206 | sport->tx_pos = 0; |
190 | #endif | 207 | #endif |
191 | sport_tx_stop(sport); | 208 | sport_tx_stop(sport); |
192 | } else { | 209 | } else { |
193 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 210 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
194 | sport->rx_pos = 0; | 211 | sport->rx_pos = 0; |
195 | #endif | 212 | #endif |
196 | sport_rx_stop(sport); | 213 | sport_rx_stop(sport); |
@@ -208,7 +225,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream) | |||
208 | struct sport_device *sport = runtime->private_data; | 225 | struct sport_device *sport = runtime->private_data; |
209 | unsigned int curr; | 226 | unsigned int curr; |
210 | 227 | ||
211 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 228 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
212 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 229 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
213 | curr = sport->tx_delay_pos; | 230 | curr = sport->tx_delay_pos; |
214 | else | 231 | else |
@@ -249,22 +266,7 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream) | |||
249 | return ret; | 266 | return ret; |
250 | } | 267 | } |
251 | 268 | ||
252 | static int bf5xx_pcm_close(struct snd_pcm_substream *substream) | 269 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
253 | { | ||
254 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
255 | struct sport_device *sport = runtime->private_data; | ||
256 | |||
257 | pr_debug("%s enter\n", __func__); | ||
258 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
259 | sport->once = 0; | ||
260 | memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | ||
261 | } else | ||
262 | memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame)); | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #ifdef CONFIG_SND_MMAP_SUPPORT | ||
268 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, | 270 | static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream, |
269 | struct vm_area_struct *vma) | 271 | struct vm_area_struct *vma) |
270 | { | 272 | { |
@@ -281,32 +283,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, | |||
281 | void __user *buf, snd_pcm_uframes_t count) | 283 | void __user *buf, snd_pcm_uframes_t count) |
282 | { | 284 | { |
283 | struct snd_pcm_runtime *runtime = substream->runtime; | 285 | struct snd_pcm_runtime *runtime = substream->runtime; |
284 | 286 | unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1]; | |
285 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", | 287 | pr_debug("%s copy pos:0x%lx count:0x%lx\n", |
286 | substream->stream ? "Capture" : "Playback", pos, count); | 288 | substream->stream ? "Capture" : "Playback", pos, count); |
287 | 289 | ||
288 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 290 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
289 | bf5xx_pcm_to_ac97( | 291 | bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos, |
290 | (struct ac97_frame *)runtime->dma_area + pos, | 292 | (__u16 *)buf, count, chan_mask); |
291 | buf, count); | ||
292 | else | 293 | else |
293 | bf5xx_ac97_to_pcm( | 294 | bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos, |
294 | (struct ac97_frame *)runtime->dma_area + pos, | 295 | (__u16 *)buf, count); |
295 | buf, count); | ||
296 | return 0; | 296 | return 0; |
297 | } | 297 | } |
298 | #endif | 298 | #endif |
299 | 299 | ||
300 | struct snd_pcm_ops bf5xx_pcm_ac97_ops = { | 300 | struct snd_pcm_ops bf5xx_pcm_ac97_ops = { |
301 | .open = bf5xx_pcm_open, | 301 | .open = bf5xx_pcm_open, |
302 | .close = bf5xx_pcm_close, | ||
303 | .ioctl = snd_pcm_lib_ioctl, | 302 | .ioctl = snd_pcm_lib_ioctl, |
304 | .hw_params = bf5xx_pcm_hw_params, | 303 | .hw_params = bf5xx_pcm_hw_params, |
305 | .hw_free = bf5xx_pcm_hw_free, | 304 | .hw_free = bf5xx_pcm_hw_free, |
306 | .prepare = bf5xx_pcm_prepare, | 305 | .prepare = bf5xx_pcm_prepare, |
307 | .trigger = bf5xx_pcm_trigger, | 306 | .trigger = bf5xx_pcm_trigger, |
308 | .pointer = bf5xx_pcm_pointer, | 307 | .pointer = bf5xx_pcm_pointer, |
309 | #ifdef CONFIG_SND_MMAP_SUPPORT | 308 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
310 | .mmap = bf5xx_pcm_mmap, | 309 | .mmap = bf5xx_pcm_mmap, |
311 | #else | 310 | #else |
312 | .copy = bf5xx_pcm_copy, | 311 | .copy = bf5xx_pcm_copy, |
@@ -344,7 +343,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
344 | * Need to allocate local buffer when enable | 343 | * Need to allocate local buffer when enable |
345 | * MMAP for SPORT working in TMD mode (include AC97). | 344 | * MMAP for SPORT working in TMD mode (include AC97). |
346 | */ | 345 | */ |
347 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 346 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
348 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 347 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
349 | if (!sport_handle->tx_dma_buf) { | 348 | if (!sport_handle->tx_dma_buf) { |
350 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ | 349 | sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \ |
@@ -381,7 +380,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
381 | struct snd_pcm_substream *substream; | 380 | struct snd_pcm_substream *substream; |
382 | struct snd_dma_buffer *buf; | 381 | struct snd_dma_buffer *buf; |
383 | int stream; | 382 | int stream; |
384 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 383 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
385 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * | 384 | size_t size = bf5xx_pcm_hardware.buffer_bytes_max * |
386 | sizeof(struct ac97_frame) / 4; | 385 | sizeof(struct ac97_frame) / 4; |
387 | #endif | 386 | #endif |
@@ -395,7 +394,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm) | |||
395 | continue; | 394 | continue; |
396 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); | 395 | dma_free_coherent(NULL, buf->bytes, buf->area, 0); |
397 | buf->area = NULL; | 396 | buf->area = NULL; |
398 | #if defined(CONFIG_SND_MMAP_SUPPORT) | 397 | #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT) |
399 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 398 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
400 | if (sport_handle->tx_dma_buf) | 399 | if (sport_handle->tx_dma_buf) |
401 | dma_free_coherent(NULL, size, \ | 400 | dma_free_coherent(NULL, size, \ |
@@ -452,6 +451,18 @@ struct snd_soc_platform bf5xx_ac97_soc_platform = { | |||
452 | }; | 451 | }; |
453 | EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); | 452 | EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform); |
454 | 453 | ||
454 | static int __init bfin_ac97_init(void) | ||
455 | { | ||
456 | return snd_soc_register_platform(&bf5xx_ac97_soc_platform); | ||
457 | } | ||
458 | module_init(bfin_ac97_init); | ||
459 | |||
460 | static void __exit bfin_ac97_exit(void) | ||
461 | { | ||
462 | snd_soc_unregister_platform(&bf5xx_ac97_soc_platform); | ||
463 | } | ||
464 | module_exit(bfin_ac97_exit); | ||
465 | |||
455 | MODULE_AUTHOR("Cliff Cai"); | 466 | MODULE_AUTHOR("Cliff Cai"); |
456 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); | 467 | MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module"); |
457 | MODULE_LICENSE("GPL"); | 468 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 5e5aafb6485f..3be2be60576d 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -54,71 +54,103 @@ | |||
54 | static int *cmd_count; | 54 | static int *cmd_count; |
55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; | 55 | static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; |
56 | 56 | ||
57 | #if defined(CONFIG_BF54x) | 57 | static u16 sport_req[][7] = { |
58 | PIN_REQ_SPORT_0, | ||
59 | #ifdef PIN_REQ_SPORT_1 | ||
60 | PIN_REQ_SPORT_1, | ||
61 | #endif | ||
62 | #ifdef PIN_REQ_SPORT_2 | ||
63 | PIN_REQ_SPORT_2, | ||
64 | #endif | ||
65 | #ifdef PIN_REQ_SPORT_3 | ||
66 | PIN_REQ_SPORT_3, | ||
67 | #endif | ||
68 | }; | ||
69 | |||
58 | static struct sport_param sport_params[4] = { | 70 | static struct sport_param sport_params[4] = { |
59 | { | 71 | { |
60 | .dma_rx_chan = CH_SPORT0_RX, | 72 | .dma_rx_chan = CH_SPORT0_RX, |
61 | .dma_tx_chan = CH_SPORT0_TX, | 73 | .dma_tx_chan = CH_SPORT0_TX, |
62 | .err_irq = IRQ_SPORT0_ERR, | 74 | .err_irq = IRQ_SPORT0_ERROR, |
63 | .regs = (struct sport_register *)SPORT0_TCR1, | 75 | .regs = (struct sport_register *)SPORT0_TCR1, |
64 | }, | 76 | }, |
77 | #ifdef PIN_REQ_SPORT_1 | ||
65 | { | 78 | { |
66 | .dma_rx_chan = CH_SPORT1_RX, | 79 | .dma_rx_chan = CH_SPORT1_RX, |
67 | .dma_tx_chan = CH_SPORT1_TX, | 80 | .dma_tx_chan = CH_SPORT1_TX, |
68 | .err_irq = IRQ_SPORT1_ERR, | 81 | .err_irq = IRQ_SPORT1_ERROR, |
69 | .regs = (struct sport_register *)SPORT1_TCR1, | 82 | .regs = (struct sport_register *)SPORT1_TCR1, |
70 | }, | 83 | }, |
84 | #endif | ||
85 | #ifdef PIN_REQ_SPORT_2 | ||
71 | { | 86 | { |
72 | .dma_rx_chan = CH_SPORT2_RX, | 87 | .dma_rx_chan = CH_SPORT2_RX, |
73 | .dma_tx_chan = CH_SPORT2_TX, | 88 | .dma_tx_chan = CH_SPORT2_TX, |
74 | .err_irq = IRQ_SPORT2_ERR, | 89 | .err_irq = IRQ_SPORT2_ERROR, |
75 | .regs = (struct sport_register *)SPORT2_TCR1, | 90 | .regs = (struct sport_register *)SPORT2_TCR1, |
76 | }, | 91 | }, |
92 | #endif | ||
93 | #ifdef PIN_REQ_SPORT_3 | ||
77 | { | 94 | { |
78 | .dma_rx_chan = CH_SPORT3_RX, | 95 | .dma_rx_chan = CH_SPORT3_RX, |
79 | .dma_tx_chan = CH_SPORT3_TX, | 96 | .dma_tx_chan = CH_SPORT3_TX, |
80 | .err_irq = IRQ_SPORT3_ERR, | 97 | .err_irq = IRQ_SPORT3_ERROR, |
81 | .regs = (struct sport_register *)SPORT3_TCR1, | 98 | .regs = (struct sport_register *)SPORT3_TCR1, |
82 | } | 99 | } |
83 | }; | ||
84 | #else | ||
85 | static struct sport_param sport_params[2] = { | ||
86 | { | ||
87 | .dma_rx_chan = CH_SPORT0_RX, | ||
88 | .dma_tx_chan = CH_SPORT0_TX, | ||
89 | .err_irq = IRQ_SPORT0_ERROR, | ||
90 | .regs = (struct sport_register *)SPORT0_TCR1, | ||
91 | }, | ||
92 | { | ||
93 | .dma_rx_chan = CH_SPORT1_RX, | ||
94 | .dma_tx_chan = CH_SPORT1_TX, | ||
95 | .err_irq = IRQ_SPORT1_ERROR, | ||
96 | .regs = (struct sport_register *)SPORT1_TCR1, | ||
97 | } | ||
98 | }; | ||
99 | #endif | 100 | #endif |
101 | }; | ||
100 | 102 | ||
101 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ | 103 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, |
102 | size_t count) | 104 | size_t count, unsigned int chan_mask) |
103 | { | 105 | { |
104 | while (count--) { | 106 | while (count--) { |
105 | dst->ac97_tag = TAG_VALID | TAG_PCM; | 107 | dst->ac97_tag = TAG_VALID; |
106 | (dst++)->ac97_pcm = *src++; | 108 | if (chan_mask & SP_FL) { |
109 | dst->ac97_pcm_r = *src++; | ||
110 | dst->ac97_tag |= TAG_PCM_RIGHT; | ||
111 | } | ||
112 | if (chan_mask & SP_FR) { | ||
113 | dst->ac97_pcm_l = *src++; | ||
114 | dst->ac97_tag |= TAG_PCM_LEFT; | ||
115 | |||
116 | } | ||
117 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
118 | if (chan_mask & SP_SR) { | ||
119 | dst->ac97_sl = *src++; | ||
120 | dst->ac97_tag |= TAG_PCM_SL; | ||
121 | } | ||
122 | if (chan_mask & SP_SL) { | ||
123 | dst->ac97_sr = *src++; | ||
124 | dst->ac97_tag |= TAG_PCM_SR; | ||
125 | } | ||
126 | if (chan_mask & SP_LFE) { | ||
127 | dst->ac97_lfe = *src++; | ||
128 | dst->ac97_tag |= TAG_PCM_LFE; | ||
129 | } | ||
130 | if (chan_mask & SP_FC) { | ||
131 | dst->ac97_center = *src++; | ||
132 | dst->ac97_tag |= TAG_PCM_CENTER; | ||
133 | } | ||
134 | #endif | ||
135 | dst++; | ||
107 | } | 136 | } |
108 | } | 137 | } |
109 | EXPORT_SYMBOL(bf5xx_pcm_to_ac97); | 138 | EXPORT_SYMBOL(bf5xx_pcm_to_ac97); |
110 | 139 | ||
111 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ | 140 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, |
112 | size_t count) | 141 | size_t count) |
113 | { | 142 | { |
114 | while (count--) | 143 | while (count--) { |
115 | *(dst++) = (src++)->ac97_pcm; | 144 | *(dst++) = src->ac97_pcm_l; |
145 | *(dst++) = src->ac97_pcm_r; | ||
146 | src++; | ||
147 | } | ||
116 | } | 148 | } |
117 | EXPORT_SYMBOL(bf5xx_ac97_to_pcm); | 149 | EXPORT_SYMBOL(bf5xx_ac97_to_pcm); |
118 | 150 | ||
119 | static unsigned int sport_tx_curr_frag(struct sport_device *sport) | 151 | static unsigned int sport_tx_curr_frag(struct sport_device *sport) |
120 | { | 152 | { |
121 | return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \ | 153 | return sport->tx_curr_frag = sport_curr_offset_tx(sport) / |
122 | sport->tx_fragsize; | 154 | sport->tx_fragsize; |
123 | } | 155 | } |
124 | 156 | ||
@@ -130,7 +162,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data) | |||
130 | 162 | ||
131 | sport_incfrag(sport, &nextfrag, 1); | 163 | sport_incfrag(sport, &nextfrag, 1); |
132 | 164 | ||
133 | nextwrite = (struct ac97_frame *)(sport->tx_buf + \ | 165 | nextwrite = (struct ac97_frame *)(sport->tx_buf + |
134 | nextfrag * sport->tx_fragsize); | 166 | nextfrag * sport->tx_fragsize); |
135 | pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", | 167 | pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n", |
136 | sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); | 168 | sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]); |
@@ -237,8 +269,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = { | |||
237 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 269 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
238 | 270 | ||
239 | #ifdef CONFIG_PM | 271 | #ifdef CONFIG_PM |
240 | static int bf5xx_ac97_suspend(struct platform_device *pdev, | 272 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
241 | struct snd_soc_dai *dai) | ||
242 | { | 273 | { |
243 | struct sport_device *sport = | 274 | struct sport_device *sport = |
244 | (struct sport_device *)dai->private_data; | 275 | (struct sport_device *)dai->private_data; |
@@ -253,8 +284,7 @@ static int bf5xx_ac97_suspend(struct platform_device *pdev, | |||
253 | return 0; | 284 | return 0; |
254 | } | 285 | } |
255 | 286 | ||
256 | static int bf5xx_ac97_resume(struct platform_device *pdev, | 287 | static int bf5xx_ac97_resume(struct snd_soc_dai *dai) |
257 | struct snd_soc_dai *dai) | ||
258 | { | 288 | { |
259 | int ret; | 289 | int ret; |
260 | struct sport_device *sport = | 290 | struct sport_device *sport = |
@@ -297,20 +327,15 @@ static int bf5xx_ac97_resume(struct platform_device *pdev, | |||
297 | static int bf5xx_ac97_probe(struct platform_device *pdev, | 327 | static int bf5xx_ac97_probe(struct platform_device *pdev, |
298 | struct snd_soc_dai *dai) | 328 | struct snd_soc_dai *dai) |
299 | { | 329 | { |
300 | int ret; | 330 | int ret = 0; |
301 | #if defined(CONFIG_BF54x) | ||
302 | u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1, | ||
303 | PIN_REQ_SPORT_2, PIN_REQ_SPORT_3}; | ||
304 | #else | ||
305 | u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1}; | ||
306 | #endif | ||
307 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); | 331 | cmd_count = (int *)get_zeroed_page(GFP_KERNEL); |
308 | if (cmd_count == NULL) | 332 | if (cmd_count == NULL) |
309 | return -ENOMEM; | 333 | return -ENOMEM; |
310 | 334 | ||
311 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { | 335 | if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) { |
312 | pr_err("Requesting Peripherals failed\n"); | 336 | pr_err("Requesting Peripherals failed\n"); |
313 | return -EFAULT; | 337 | ret = -EFAULT; |
338 | goto peripheral_err; | ||
314 | } | 339 | } |
315 | 340 | ||
316 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 341 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
@@ -318,54 +343,54 @@ static int bf5xx_ac97_probe(struct platform_device *pdev, | |||
318 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 343 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { |
319 | pr_err("Failed to request GPIO_%d for reset\n", | 344 | pr_err("Failed to request GPIO_%d for reset\n", |
320 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 345 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
321 | peripheral_free_list(&sport_req[sport_num][0]); | 346 | ret = -1; |
322 | return -1; | 347 | goto gpio_err; |
323 | } | 348 | } |
324 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | 349 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); |
325 | #endif | 350 | #endif |
326 | sport_handle = sport_init(&sport_params[sport_num], 2, \ | 351 | sport_handle = sport_init(&sport_params[sport_num], 2, \ |
327 | sizeof(struct ac97_frame), NULL); | 352 | sizeof(struct ac97_frame), NULL); |
328 | if (!sport_handle) { | 353 | if (!sport_handle) { |
329 | peripheral_free_list(&sport_req[sport_num][0]); | 354 | ret = -ENODEV; |
330 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 355 | goto sport_err; |
331 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
332 | #endif | ||
333 | return -ENODEV; | ||
334 | } | 356 | } |
335 | /*SPORT works in TDM mode to simulate AC97 transfers*/ | 357 | /*SPORT works in TDM mode to simulate AC97 transfers*/ |
336 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); | 358 | ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1); |
337 | if (ret) { | 359 | if (ret) { |
338 | pr_err("SPORT is busy!\n"); | 360 | pr_err("SPORT is busy!\n"); |
339 | kfree(sport_handle); | 361 | ret = -EBUSY; |
340 | peripheral_free_list(&sport_req[sport_num][0]); | 362 | goto sport_config_err; |
341 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
342 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
343 | #endif | ||
344 | return -EBUSY; | ||
345 | } | 363 | } |
346 | 364 | ||
347 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); | 365 | ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1)); |
348 | if (ret) { | 366 | if (ret) { |
349 | pr_err("SPORT is busy!\n"); | 367 | pr_err("SPORT is busy!\n"); |
350 | kfree(sport_handle); | 368 | ret = -EBUSY; |
351 | peripheral_free_list(&sport_req[sport_num][0]); | 369 | goto sport_config_err; |
352 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
353 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
354 | #endif | ||
355 | return -EBUSY; | ||
356 | } | 370 | } |
357 | 371 | ||
358 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); | 372 | ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1)); |
359 | if (ret) { | 373 | if (ret) { |
360 | pr_err("SPORT is busy!\n"); | 374 | pr_err("SPORT is busy!\n"); |
361 | kfree(sport_handle); | 375 | ret = -EBUSY; |
362 | peripheral_free_list(&sport_req[sport_num][0]); | 376 | goto sport_config_err; |
363 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
364 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
365 | #endif | ||
366 | return -EBUSY; | ||
367 | } | 377 | } |
378 | |||
368 | return 0; | 379 | return 0; |
380 | |||
381 | sport_config_err: | ||
382 | kfree(sport_handle); | ||
383 | sport_err: | ||
384 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | ||
385 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
386 | #endif | ||
387 | gpio_err: | ||
388 | peripheral_free_list(&sport_req[sport_num][0]); | ||
389 | peripheral_err: | ||
390 | free_page((unsigned long)cmd_count); | ||
391 | cmd_count = NULL; | ||
392 | |||
393 | return ret; | ||
369 | } | 394 | } |
370 | 395 | ||
371 | static void bf5xx_ac97_remove(struct platform_device *pdev, | 396 | static void bf5xx_ac97_remove(struct platform_device *pdev, |
@@ -373,6 +398,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
373 | { | 398 | { |
374 | free_page((unsigned long)cmd_count); | 399 | free_page((unsigned long)cmd_count); |
375 | cmd_count = NULL; | 400 | cmd_count = NULL; |
401 | peripheral_free_list(&sport_req[sport_num][0]); | ||
376 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 402 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
377 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 403 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); |
378 | #endif | 404 | #endif |
@@ -381,7 +407,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev, | |||
381 | struct snd_soc_dai bfin_ac97_dai = { | 407 | struct snd_soc_dai bfin_ac97_dai = { |
382 | .name = "bf5xx-ac97", | 408 | .name = "bf5xx-ac97", |
383 | .id = 0, | 409 | .id = 0, |
384 | .type = SND_SOC_DAI_AC97, | 410 | .ac97_control = 1, |
385 | .probe = bf5xx_ac97_probe, | 411 | .probe = bf5xx_ac97_probe, |
386 | .remove = bf5xx_ac97_remove, | 412 | .remove = bf5xx_ac97_remove, |
387 | .suspend = bf5xx_ac97_suspend, | 413 | .suspend = bf5xx_ac97_suspend, |
@@ -389,7 +415,11 @@ struct snd_soc_dai bfin_ac97_dai = { | |||
389 | .playback = { | 415 | .playback = { |
390 | .stream_name = "AC97 Playback", | 416 | .stream_name = "AC97 Playback", |
391 | .channels_min = 2, | 417 | .channels_min = 2, |
418 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
419 | .channels_max = 6, | ||
420 | #else | ||
392 | .channels_max = 2, | 421 | .channels_max = 2, |
422 | #endif | ||
393 | .rates = SNDRV_PCM_RATE_48000, | 423 | .rates = SNDRV_PCM_RATE_48000, |
394 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 424 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
395 | .capture = { | 425 | .capture = { |
@@ -401,6 +431,18 @@ struct snd_soc_dai bfin_ac97_dai = { | |||
401 | }; | 431 | }; |
402 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); | 432 | EXPORT_SYMBOL_GPL(bfin_ac97_dai); |
403 | 433 | ||
434 | static int __init bfin_ac97_init(void) | ||
435 | { | ||
436 | return snd_soc_register_dai(&bfin_ac97_dai); | ||
437 | } | ||
438 | module_init(bfin_ac97_init); | ||
439 | |||
440 | static void __exit bfin_ac97_exit(void) | ||
441 | { | ||
442 | snd_soc_unregister_dai(&bfin_ac97_dai); | ||
443 | } | ||
444 | module_exit(bfin_ac97_exit); | ||
445 | |||
404 | MODULE_AUTHOR("Roy Huang"); | 446 | MODULE_AUTHOR("Roy Huang"); |
405 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); | 447 | MODULE_DESCRIPTION("AC97 driver for ADI Blackfin"); |
406 | MODULE_LICENSE("GPL"); | 448 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h index 3f77cc558dc0..3f2a911fe0cb 100644 --- a/sound/soc/blackfin/bf5xx-ac97.h +++ b/sound/soc/blackfin/bf5xx-ac97.h | |||
@@ -16,21 +16,46 @@ struct ac97_frame { | |||
16 | u16 ac97_tag; /* slot 0 */ | 16 | u16 ac97_tag; /* slot 0 */ |
17 | u16 ac97_addr; /* slot 1 */ | 17 | u16 ac97_addr; /* slot 1 */ |
18 | u16 ac97_data; /* slot 2 */ | 18 | u16 ac97_data; /* slot 2 */ |
19 | u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */ | 19 | u16 ac97_pcm_l; /*slot 3:front left*/ |
20 | u16 ac97_pcm_r; /*slot 4:front left*/ | ||
21 | #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT) | ||
22 | u16 ac97_mdm_l1; | ||
23 | u16 ac97_center; /*slot 6:center*/ | ||
24 | u16 ac97_sl; /*slot 7:surround left*/ | ||
25 | u16 ac97_sr; /*slot 8:surround right*/ | ||
26 | u16 ac97_lfe; /*slot 9:lfe*/ | ||
27 | #endif | ||
20 | } __attribute__ ((packed)); | 28 | } __attribute__ ((packed)); |
21 | 29 | ||
30 | /* Speaker location */ | ||
31 | #define SP_FL 0x0001 | ||
32 | #define SP_FR 0x0010 | ||
33 | #define SP_FC 0x0002 | ||
34 | #define SP_LFE 0x0020 | ||
35 | #define SP_SL 0x0004 | ||
36 | #define SP_SR 0x0040 | ||
37 | |||
38 | #define SP_STEREO (SP_FL | SP_FR) | ||
39 | #define SP_2DOT1 (SP_FL | SP_FR | SP_LFE) | ||
40 | #define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR) | ||
41 | #define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR) | ||
42 | |||
22 | #define TAG_VALID 0x8000 | 43 | #define TAG_VALID 0x8000 |
23 | #define TAG_CMD 0x6000 | 44 | #define TAG_CMD 0x6000 |
24 | #define TAG_PCM_LEFT 0x1000 | 45 | #define TAG_PCM_LEFT 0x1000 |
25 | #define TAG_PCM_RIGHT 0x0800 | 46 | #define TAG_PCM_RIGHT 0x0800 |
26 | #define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT) | 47 | #define TAG_PCM_MDM_L1 0x0400 |
48 | #define TAG_PCM_CENTER 0x0200 | ||
49 | #define TAG_PCM_SL 0x0100 | ||
50 | #define TAG_PCM_SR 0x0080 | ||
51 | #define TAG_PCM_LFE 0x0040 | ||
27 | 52 | ||
28 | extern struct snd_soc_dai bfin_ac97_dai; | 53 | extern struct snd_soc_dai bfin_ac97_dai; |
29 | 54 | ||
30 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \ | 55 | void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \ |
31 | size_t count); | 56 | size_t count, unsigned int chan_mask); |
32 | 57 | ||
33 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \ | 58 | void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \ |
34 | size_t count); | 59 | size_t count); |
35 | 60 | ||
36 | #endif | 61 | #endif |
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index 124425d22320..d8f591273778 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include "bf5xx-ac97-pcm.h" | 43 | #include "bf5xx-ac97-pcm.h" |
44 | #include "bf5xx-ac97.h" | 44 | #include "bf5xx-ac97.h" |
45 | 45 | ||
46 | static struct snd_soc_machine bf5xx_board; | 46 | static struct snd_soc_card bf5xx_board; |
47 | 47 | ||
48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) | 48 | static int bf5xx_board_startup(struct snd_pcm_substream *substream) |
49 | { | 49 | { |
@@ -67,15 +67,15 @@ static struct snd_soc_dai_link bf5xx_board_dai = { | |||
67 | .ops = &bf5xx_board_ops, | 67 | .ops = &bf5xx_board_ops, |
68 | }; | 68 | }; |
69 | 69 | ||
70 | static struct snd_soc_machine bf5xx_board = { | 70 | static struct snd_soc_card bf5xx_board = { |
71 | .name = "bf5xx-board", | 71 | .name = "bf5xx-board", |
72 | .platform = &bf5xx_ac97_soc_platform, | ||
72 | .dai_link = &bf5xx_board_dai, | 73 | .dai_link = &bf5xx_board_dai, |
73 | .num_links = 1, | 74 | .num_links = 1, |
74 | }; | 75 | }; |
75 | 76 | ||
76 | static struct snd_soc_device bf5xx_board_snd_devdata = { | 77 | static struct snd_soc_device bf5xx_board_snd_devdata = { |
77 | .machine = &bf5xx_board, | 78 | .card = &bf5xx_board, |
78 | .platform = &bf5xx_ac97_soc_platform, | ||
79 | .codec_dev = &soc_codec_dev_ad1980, | 79 | .codec_dev = &soc_codec_dev_ad1980, |
80 | }; | 80 | }; |
81 | 81 | ||
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c index 622c9b909532..7f2a5e199075 100644 --- a/sound/soc/blackfin/bf5xx-ad73311.c +++ b/sound/soc/blackfin/bf5xx-ad73311.c | |||
@@ -65,7 +65,7 @@ | |||
65 | 65 | ||
66 | #define GPIO_SE CONFIG_SND_BFIN_AD73311_SE | 66 | #define GPIO_SE CONFIG_SND_BFIN_AD73311_SE |
67 | 67 | ||
68 | static struct snd_soc_machine bf5xx_ad73311; | 68 | static struct snd_soc_card bf5xx_ad73311; |
69 | 69 | ||
70 | static int snd_ad73311_startup(void) | 70 | static int snd_ad73311_startup(void) |
71 | { | 71 | { |
@@ -168,7 +168,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream, | |||
168 | params_format(params)); | 168 | params_format(params)); |
169 | 169 | ||
170 | /* set cpu DAI configuration */ | 170 | /* set cpu DAI configuration */ |
171 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | | 171 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | |
172 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 172 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
173 | if (ret < 0) | 173 | if (ret < 0) |
174 | return ret; | 174 | return ret; |
@@ -190,16 +190,16 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai = { | |||
190 | .ops = &bf5xx_ad73311_ops, | 190 | .ops = &bf5xx_ad73311_ops, |
191 | }; | 191 | }; |
192 | 192 | ||
193 | static struct snd_soc_machine bf5xx_ad73311 = { | 193 | static struct snd_soc_card bf5xx_ad73311 = { |
194 | .name = "bf5xx_ad73311", | 194 | .name = "bf5xx_ad73311", |
195 | .platform = &bf5xx_i2s_soc_platform, | ||
195 | .probe = bf5xx_probe, | 196 | .probe = bf5xx_probe, |
196 | .dai_link = &bf5xx_ad73311_dai, | 197 | .dai_link = &bf5xx_ad73311_dai, |
197 | .num_links = 1, | 198 | .num_links = 1, |
198 | }; | 199 | }; |
199 | 200 | ||
200 | static struct snd_soc_device bf5xx_ad73311_snd_devdata = { | 201 | static struct snd_soc_device bf5xx_ad73311_snd_devdata = { |
201 | .machine = &bf5xx_ad73311, | 202 | .card = &bf5xx_ad73311, |
202 | .platform = &bf5xx_i2s_soc_platform, | ||
203 | .codec_dev = &soc_codec_dev_ad73311, | 203 | .codec_dev = &soc_codec_dev_ad73311, |
204 | }; | 204 | }; |
205 | 205 | ||
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c index 61fccf925192..53d290b3ea47 100644 --- a/sound/soc/blackfin/bf5xx-i2s-pcm.c +++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c | |||
@@ -283,6 +283,18 @@ struct snd_soc_platform bf5xx_i2s_soc_platform = { | |||
283 | }; | 283 | }; |
284 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); | 284 | EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform); |
285 | 285 | ||
286 | static int __init bfin_i2s_init(void) | ||
287 | { | ||
288 | return snd_soc_register_platform(&bf5xx_i2s_soc_platform); | ||
289 | } | ||
290 | module_init(bfin_i2s_init); | ||
291 | |||
292 | static void __exit bfin_i2s_exit(void) | ||
293 | { | ||
294 | snd_soc_unregister_platform(&bf5xx_i2s_soc_platform); | ||
295 | } | ||
296 | module_exit(bfin_i2s_exit); | ||
297 | |||
286 | MODULE_AUTHOR("Cliff Cai"); | 298 | MODULE_AUTHOR("Cliff Cai"); |
287 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); | 299 | MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module"); |
288 | MODULE_LICENSE("GPL"); | 300 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c index e020c160ee44..d1d95d2393fe 100644 --- a/sound/soc/blackfin/bf5xx-i2s.c +++ b/sound/soc/blackfin/bf5xx-i2s.c | |||
@@ -132,7 +132,8 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
132 | return ret; | 132 | return ret; |
133 | } | 133 | } |
134 | 134 | ||
135 | static int bf5xx_i2s_startup(struct snd_pcm_substream *substream) | 135 | static int bf5xx_i2s_startup(struct snd_pcm_substream *substream, |
136 | struct snd_soc_dai *dai) | ||
136 | { | 137 | { |
137 | pr_debug("%s enter\n", __func__); | 138 | pr_debug("%s enter\n", __func__); |
138 | 139 | ||
@@ -142,7 +143,8 @@ static int bf5xx_i2s_startup(struct snd_pcm_substream *substream) | |||
142 | } | 143 | } |
143 | 144 | ||
144 | static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | 145 | static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, |
145 | struct snd_pcm_hw_params *params) | 146 | struct snd_pcm_hw_params *params, |
147 | struct snd_soc_dai *dai) | ||
146 | { | 148 | { |
147 | int ret = 0; | 149 | int ret = 0; |
148 | 150 | ||
@@ -193,7 +195,8 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
193 | return 0; | 195 | return 0; |
194 | } | 196 | } |
195 | 197 | ||
196 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream) | 198 | static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream, |
199 | struct snd_soc_dai *dai) | ||
197 | { | 200 | { |
198 | pr_debug("%s enter\n", __func__); | 201 | pr_debug("%s enter\n", __func__); |
199 | bf5xx_i2s.counter--; | 202 | bf5xx_i2s.counter--; |
@@ -219,16 +222,14 @@ static int bf5xx_i2s_probe(struct platform_device *pdev, | |||
219 | return 0; | 222 | return 0; |
220 | } | 223 | } |
221 | 224 | ||
222 | static void bf5xx_i2s_remove(struct platform_device *pdev, | 225 | static void bf5xx_i2s_remove(struct snd_soc_dai *dai) |
223 | struct snd_soc_dai *dai) | ||
224 | { | 226 | { |
225 | pr_debug("%s enter\n", __func__); | 227 | pr_debug("%s enter\n", __func__); |
226 | peripheral_free_list(&sport_req[sport_num][0]); | 228 | peripheral_free_list(&sport_req[sport_num][0]); |
227 | } | 229 | } |
228 | 230 | ||
229 | #ifdef CONFIG_PM | 231 | #ifdef CONFIG_PM |
230 | static int bf5xx_i2s_suspend(struct platform_device *dev, | 232 | static int bf5xx_i2s_suspend(struct snd_soc_dai *dai) |
231 | struct snd_soc_dai *dai) | ||
232 | { | 233 | { |
233 | struct sport_device *sport = | 234 | struct sport_device *sport = |
234 | (struct sport_device *)dai->private_data; | 235 | (struct sport_device *)dai->private_data; |
@@ -289,7 +290,6 @@ static int bf5xx_i2s_resume(struct platform_device *pdev, | |||
289 | struct snd_soc_dai bf5xx_i2s_dai = { | 290 | struct snd_soc_dai bf5xx_i2s_dai = { |
290 | .name = "bf5xx-i2s", | 291 | .name = "bf5xx-i2s", |
291 | .id = 0, | 292 | .id = 0, |
292 | .type = SND_SOC_DAI_I2S, | ||
293 | .probe = bf5xx_i2s_probe, | 293 | .probe = bf5xx_i2s_probe, |
294 | .remove = bf5xx_i2s_remove, | 294 | .remove = bf5xx_i2s_remove, |
295 | .suspend = bf5xx_i2s_suspend, | 295 | .suspend = bf5xx_i2s_suspend, |
@@ -307,13 +307,24 @@ struct snd_soc_dai bf5xx_i2s_dai = { | |||
307 | .ops = { | 307 | .ops = { |
308 | .startup = bf5xx_i2s_startup, | 308 | .startup = bf5xx_i2s_startup, |
309 | .shutdown = bf5xx_i2s_shutdown, | 309 | .shutdown = bf5xx_i2s_shutdown, |
310 | .hw_params = bf5xx_i2s_hw_params,}, | 310 | .hw_params = bf5xx_i2s_hw_params, |
311 | .dai_ops = { | ||
312 | .set_fmt = bf5xx_i2s_set_dai_fmt, | 311 | .set_fmt = bf5xx_i2s_set_dai_fmt, |
313 | }, | 312 | }, |
314 | }; | 313 | }; |
315 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); | 314 | EXPORT_SYMBOL_GPL(bf5xx_i2s_dai); |
316 | 315 | ||
316 | static int __init bfin_i2s_init(void) | ||
317 | { | ||
318 | return snd_soc_register_dai(&bf5xx_i2s_dai); | ||
319 | } | ||
320 | module_init(bfin_i2s_init); | ||
321 | |||
322 | static void __exit bfin_i2s_exit(void) | ||
323 | { | ||
324 | snd_soc_unregister_dai(&bf5xx_i2s_dai); | ||
325 | } | ||
326 | module_exit(bfin_i2s_exit); | ||
327 | |||
317 | /* Module information */ | 328 | /* Module information */ |
318 | MODULE_AUTHOR("Cliff Cai"); | 329 | MODULE_AUTHOR("Cliff Cai"); |
319 | MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); | 330 | MODULE_DESCRIPTION("I2S driver for ADI Blackfin"); |
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h index fcadcc081f7f..2e63dea73e9c 100644 --- a/sound/soc/blackfin/bf5xx-sport.h +++ b/sound/soc/blackfin/bf5xx-sport.h | |||
@@ -116,7 +116,7 @@ struct sport_device { | |||
116 | void *err_data; | 116 | void *err_data; |
117 | unsigned char *tx_dma_buf; | 117 | unsigned char *tx_dma_buf; |
118 | unsigned char *rx_dma_buf; | 118 | unsigned char *rx_dma_buf; |
119 | #ifdef CONFIG_SND_MMAP_SUPPORT | 119 | #ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT |
120 | dma_addr_t tx_dma_phy; | 120 | dma_addr_t tx_dma_phy; |
121 | dma_addr_t rx_dma_phy; | 121 | dma_addr_t rx_dma_phy; |
122 | int tx_pos;/*pcm sample count*/ | 122 | int tx_pos;/*pcm sample count*/ |
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c index e15f67fd7769..bc0cdded7116 100644 --- a/sound/soc/blackfin/bf5xx-ssm2602.c +++ b/sound/soc/blackfin/bf5xx-ssm2602.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include "bf5xx-i2s-pcm.h" | 44 | #include "bf5xx-i2s-pcm.h" |
45 | #include "bf5xx-i2s.h" | 45 | #include "bf5xx-i2s.h" |
46 | 46 | ||
47 | static struct snd_soc_machine bf5xx_ssm2602; | 47 | static struct snd_soc_card bf5xx_ssm2602; |
48 | 48 | ||
49 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) | 49 | static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream) |
50 | { | 50 | { |
@@ -92,17 +92,17 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
92 | */ | 92 | */ |
93 | 93 | ||
94 | /* set codec DAI configuration */ | 94 | /* set codec DAI configuration */ |
95 | ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 95 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | |
96 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 96 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
97 | if (ret < 0) | 97 | if (ret < 0) |
98 | return ret; | 98 | return ret; |
99 | /* set cpu DAI configuration */ | 99 | /* set cpu DAI configuration */ |
100 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | 100 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | |
101 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); | 101 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM); |
102 | if (ret < 0) | 102 | if (ret < 0) |
103 | return ret; | 103 | return ret; |
104 | 104 | ||
105 | ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk, | 105 | ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk, |
106 | SND_SOC_CLOCK_IN); | 106 | SND_SOC_CLOCK_IN); |
107 | if (ret < 0) | 107 | if (ret < 0) |
108 | return ret; | 108 | return ret; |
@@ -135,15 +135,15 @@ static struct ssm2602_setup_data bf5xx_ssm2602_setup = { | |||
135 | .i2c_address = 0x1b, | 135 | .i2c_address = 0x1b, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static struct snd_soc_machine bf5xx_ssm2602 = { | 138 | static struct snd_soc_card bf5xx_ssm2602 = { |
139 | .name = "bf5xx_ssm2602", | 139 | .name = "bf5xx_ssm2602", |
140 | .platform = &bf5xx_i2s_soc_platform, | ||
140 | .dai_link = &bf5xx_ssm2602_dai, | 141 | .dai_link = &bf5xx_ssm2602_dai, |
141 | .num_links = 1, | 142 | .num_links = 1, |
142 | }; | 143 | }; |
143 | 144 | ||
144 | static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { | 145 | static struct snd_soc_device bf5xx_ssm2602_snd_devdata = { |
145 | .machine = &bf5xx_ssm2602, | 146 | .card = &bf5xx_ssm2602, |
146 | .platform = &bf5xx_i2s_soc_platform, | ||
147 | .codec_dev = &soc_codec_dev_ssm2602, | 147 | .codec_dev = &soc_codec_dev_ssm2602, |
148 | .codec_data = &bf5xx_ssm2602_setup, | 148 | .codec_data = &bf5xx_ssm2602_setup, |
149 | }; | 149 | }; |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 38a0e3b620a7..c41289b5f586 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -1,31 +1,40 @@ | |||
1 | config SND_SOC_ALL_CODECS | 1 | config SND_SOC_ALL_CODECS |
2 | tristate "Build all ASoC CODEC drivers" | 2 | tristate "Build all ASoC CODEC drivers" |
3 | depends on I2C | 3 | select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS |
4 | select SPI | 4 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
5 | select SPI_MASTER | 5 | select SND_SOC_AD73311 if I2C |
6 | select SND_SOC_AD73311 | 6 | select SND_SOC_AK4535 if I2C |
7 | select SND_SOC_AK4535 | 7 | select SND_SOC_CS4270 if I2C |
8 | select SND_SOC_CS4270 | 8 | select SND_SOC_PCM3008 |
9 | select SND_SOC_SSM2602 | 9 | select SND_SOC_SSM2602 if I2C |
10 | select SND_SOC_TLV320AIC23 | 10 | select SND_SOC_TLV320AIC23 if I2C |
11 | select SND_SOC_TLV320AIC26 | 11 | select SND_SOC_TLV320AIC26 if SPI_MASTER |
12 | select SND_SOC_TLV320AIC3X | 12 | select SND_SOC_TLV320AIC3X if I2C |
13 | select SND_SOC_UDA1380 | 13 | select SND_SOC_TWL4030 if TWL4030_CORE |
14 | select SND_SOC_WM8510 | 14 | select SND_SOC_UDA134X |
15 | select SND_SOC_WM8580 | 15 | select SND_SOC_UDA1380 if I2C |
16 | select SND_SOC_WM8731 | 16 | select SND_SOC_WM8350 if MFD_WM8350 |
17 | select SND_SOC_WM8750 | 17 | select SND_SOC_WM8510 if (I2C || SPI_MASTER) |
18 | select SND_SOC_WM8753 | 18 | select SND_SOC_WM8580 if I2C |
19 | select SND_SOC_WM8900 | 19 | select SND_SOC_WM8728 if (I2C || SPI_MASTER) |
20 | select SND_SOC_WM8903 | 20 | select SND_SOC_WM8731 if (I2C || SPI_MASTER) |
21 | select SND_SOC_WM8971 | 21 | select SND_SOC_WM8750 if (I2C || SPI_MASTER) |
22 | select SND_SOC_WM8990 | 22 | select SND_SOC_WM8753 if (I2C || SPI_MASTER) |
23 | select SND_SOC_WM8900 if I2C | ||
24 | select SND_SOC_WM8903 if I2C | ||
25 | select SND_SOC_WM8971 if I2C | ||
26 | select SND_SOC_WM8990 if I2C | ||
27 | select SND_SOC_WM9712 if SND_SOC_AC97_BUS | ||
28 | select SND_SOC_WM9713 if SND_SOC_AC97_BUS | ||
23 | help | 29 | help |
24 | Normally ASoC codec drivers are only built if a machine driver which | 30 | Normally ASoC codec drivers are only built if a machine driver which |
25 | uses them is also built since they are only usable with a machine | 31 | uses them is also built since they are only usable with a machine |
26 | driver. Selecting this option will allow these drivers to be built | 32 | driver. Selecting this option will allow these drivers to be built |
27 | without an explicit machine driver for test and development purposes. | 33 | without an explicit machine driver for test and development purposes. |
28 | 34 | ||
35 | Support for the bus types used to access the codecs to be built must | ||
36 | be selected separately. | ||
37 | |||
29 | If unsure select "N". | 38 | If unsure select "N". |
30 | 39 | ||
31 | 40 | ||
@@ -60,6 +69,12 @@ config SND_SOC_CS4270_VD33_ERRATA | |||
60 | bool | 69 | bool |
61 | depends on SND_SOC_CS4270 | 70 | depends on SND_SOC_CS4270 |
62 | 71 | ||
72 | config SND_SOC_L3 | ||
73 | tristate | ||
74 | |||
75 | config SND_SOC_PCM3008 | ||
76 | tristate | ||
77 | |||
63 | config SND_SOC_SSM2602 | 78 | config SND_SOC_SSM2602 |
64 | tristate | 79 | tristate |
65 | 80 | ||
@@ -75,15 +90,29 @@ config SND_SOC_TLV320AIC3X | |||
75 | tristate | 90 | tristate |
76 | depends on I2C | 91 | depends on I2C |
77 | 92 | ||
93 | config SND_SOC_TWL4030 | ||
94 | tristate | ||
95 | depends on TWL4030_CORE | ||
96 | |||
97 | config SND_SOC_UDA134X | ||
98 | tristate | ||
99 | select SND_SOC_L3 | ||
100 | |||
78 | config SND_SOC_UDA1380 | 101 | config SND_SOC_UDA1380 |
79 | tristate | 102 | tristate |
80 | 103 | ||
104 | config SND_SOC_WM8350 | ||
105 | tristate | ||
106 | |||
81 | config SND_SOC_WM8510 | 107 | config SND_SOC_WM8510 |
82 | tristate | 108 | tristate |
83 | 109 | ||
84 | config SND_SOC_WM8580 | 110 | config SND_SOC_WM8580 |
85 | tristate | 111 | tristate |
86 | 112 | ||
113 | config SND_SOC_WM8728 | ||
114 | tristate | ||
115 | |||
87 | config SND_SOC_WM8731 | 116 | config SND_SOC_WM8731 |
88 | tristate | 117 | tristate |
89 | 118 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 90f0a585fc70..c4ddc9aa2bbd 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -3,13 +3,19 @@ snd-soc-ad1980-objs := ad1980.o | |||
3 | snd-soc-ad73311-objs := ad73311.o | 3 | snd-soc-ad73311-objs := ad73311.o |
4 | snd-soc-ak4535-objs := ak4535.o | 4 | snd-soc-ak4535-objs := ak4535.o |
5 | snd-soc-cs4270-objs := cs4270.o | 5 | snd-soc-cs4270-objs := cs4270.o |
6 | snd-soc-l3-objs := l3.o | ||
7 | snd-soc-pcm3008-objs := pcm3008.o | ||
6 | snd-soc-ssm2602-objs := ssm2602.o | 8 | snd-soc-ssm2602-objs := ssm2602.o |
7 | snd-soc-tlv320aic23-objs := tlv320aic23.o | 9 | snd-soc-tlv320aic23-objs := tlv320aic23.o |
8 | snd-soc-tlv320aic26-objs := tlv320aic26.o | 10 | snd-soc-tlv320aic26-objs := tlv320aic26.o |
9 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o | 11 | snd-soc-tlv320aic3x-objs := tlv320aic3x.o |
12 | snd-soc-twl4030-objs := twl4030.o | ||
13 | snd-soc-uda134x-objs := uda134x.o | ||
10 | snd-soc-uda1380-objs := uda1380.o | 14 | snd-soc-uda1380-objs := uda1380.o |
15 | snd-soc-wm8350-objs := wm8350.o | ||
11 | snd-soc-wm8510-objs := wm8510.o | 16 | snd-soc-wm8510-objs := wm8510.o |
12 | snd-soc-wm8580-objs := wm8580.o | 17 | snd-soc-wm8580-objs := wm8580.o |
18 | snd-soc-wm8728-objs := wm8728.o | ||
13 | snd-soc-wm8731-objs := wm8731.o | 19 | snd-soc-wm8731-objs := wm8731.o |
14 | snd-soc-wm8750-objs := wm8750.o | 20 | snd-soc-wm8750-objs := wm8750.o |
15 | snd-soc-wm8753-objs := wm8753.o | 21 | snd-soc-wm8753-objs := wm8753.o |
@@ -25,13 +31,19 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | |||
25 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 31 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
26 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o | 32 | obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o |
27 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o | 33 | obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o |
34 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | ||
35 | obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | ||
28 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 36 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
29 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o | 37 | obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o |
30 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o | 38 | obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o |
31 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o | 39 | obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o |
40 | obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o | ||
41 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | ||
32 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 42 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
43 | obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o | ||
33 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o | 44 | obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o |
34 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o | 45 | obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o |
46 | obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o | ||
35 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o | 47 | obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o |
36 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o | 48 | obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o |
37 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o | 49 | obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index bd1ebdc6c86c..fb53e6511af2 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -24,7 +24,8 @@ | |||
24 | 24 | ||
25 | #define AC97_VERSION "0.6" | 25 | #define AC97_VERSION "0.6" |
26 | 26 | ||
27 | static int ac97_prepare(struct snd_pcm_substream *substream) | 27 | static int ac97_prepare(struct snd_pcm_substream *substream, |
28 | struct snd_soc_dai *dai) | ||
28 | { | 29 | { |
29 | struct snd_pcm_runtime *runtime = substream->runtime; | 30 | struct snd_pcm_runtime *runtime = substream->runtime; |
30 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 31 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -42,7 +43,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream) | |||
42 | 43 | ||
43 | struct snd_soc_dai ac97_dai = { | 44 | struct snd_soc_dai ac97_dai = { |
44 | .name = "AC97 HiFi", | 45 | .name = "AC97 HiFi", |
45 | .type = SND_SOC_DAI_AC97, | 46 | .ac97_control = 1, |
46 | .playback = { | 47 | .playback = { |
47 | .stream_name = "AC97 Playback", | 48 | .stream_name = "AC97 Playback", |
48 | .channels_min = 1, | 49 | .channels_min = 1, |
@@ -113,7 +114,7 @@ static int ac97_soc_probe(struct platform_device *pdev) | |||
113 | if (ret < 0) | 114 | if (ret < 0) |
114 | goto bus_err; | 115 | goto bus_err; |
115 | 116 | ||
116 | ret = snd_soc_register_card(socdev); | 117 | ret = snd_soc_init_card(socdev); |
117 | if (ret < 0) | 118 | if (ret < 0) |
118 | goto bus_err; | 119 | goto bus_err; |
119 | return 0; | 120 | return 0; |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 1397b8e06c0b..73fdbb4d4a3d 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -85,6 +85,9 @@ SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0), | |||
85 | SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), | 85 | SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), |
86 | SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), | 86 | SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), |
87 | 87 | ||
88 | SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1), | ||
89 | SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1), | ||
90 | |||
88 | SOC_ENUM("Capture Source", ad1980_cap_src), | 91 | SOC_ENUM("Capture Source", ad1980_cap_src), |
89 | 92 | ||
90 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), | 93 | SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0), |
@@ -142,10 +145,11 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
142 | 145 | ||
143 | struct snd_soc_dai ad1980_dai = { | 146 | struct snd_soc_dai ad1980_dai = { |
144 | .name = "AC97", | 147 | .name = "AC97", |
148 | .ac97_control = 1, | ||
145 | .playback = { | 149 | .playback = { |
146 | .stream_name = "Playback", | 150 | .stream_name = "Playback", |
147 | .channels_min = 2, | 151 | .channels_min = 2, |
148 | .channels_max = 2, | 152 | .channels_max = 6, |
149 | .rates = SNDRV_PCM_RATE_48000, | 153 | .rates = SNDRV_PCM_RATE_48000, |
150 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, | 154 | .formats = SNDRV_PCM_FMTBIT_S16_LE, }, |
151 | .capture = { | 155 | .capture = { |
@@ -192,6 +196,7 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
192 | struct snd_soc_codec *codec; | 196 | struct snd_soc_codec *codec; |
193 | int ret = 0; | 197 | int ret = 0; |
194 | u16 vendor_id2; | 198 | u16 vendor_id2; |
199 | u16 ext_status; | ||
195 | 200 | ||
196 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 201 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
197 | 202 | ||
@@ -234,7 +239,7 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
234 | 239 | ||
235 | ret = ad1980_reset(codec, 0); | 240 | ret = ad1980_reset(codec, 0); |
236 | if (ret < 0) { | 241 | if (ret < 0) { |
237 | printk(KERN_ERR "AC97 link error\n"); | 242 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); |
238 | goto reset_err; | 243 | goto reset_err; |
239 | } | 244 | } |
240 | 245 | ||
@@ -253,12 +258,19 @@ static int ad1980_soc_probe(struct platform_device *pdev) | |||
253 | "supported\n"); | 258 | "supported\n"); |
254 | } | 259 | } |
255 | 260 | ||
256 | ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */ | 261 | /* unmute captures and playbacks volume */ |
257 | ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */ | 262 | ac97_write(codec, AC97_MASTER, 0x0000); |
258 | ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */ | 263 | ac97_write(codec, AC97_PCM, 0x0000); |
264 | ac97_write(codec, AC97_REC_GAIN, 0x0000); | ||
265 | ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); | ||
266 | ac97_write(codec, AC97_SURROUND_MASTER, 0x0000); | ||
267 | |||
268 | /*power on LFE/CENTER/Surround DACs*/ | ||
269 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); | ||
270 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); | ||
259 | 271 | ||
260 | ad1980_add_controls(codec); | 272 | ad1980_add_controls(codec); |
261 | ret = snd_soc_register_card(socdev); | 273 | ret = snd_soc_init_card(socdev); |
262 | if (ret < 0) { | 274 | if (ret < 0) { |
263 | printk(KERN_ERR "ad1980: failed to register card\n"); | 275 | printk(KERN_ERR "ad1980: failed to register card\n"); |
264 | goto reset_err; | 276 | goto reset_err; |
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c index 37af8607b00a..b09289a1e55a 100644 --- a/sound/soc/codecs/ad73311.c +++ b/sound/soc/codecs/ad73311.c | |||
@@ -8,14 +8,10 @@ | |||
8 | * under the terms of the GNU General Public License as published by the | 8 | * under the terms of the GNU General Public License as published by the |
9 | * Free Software Foundation; either version 2 of the License, or (at your | 9 | * Free Software Foundation; either version 2 of the License, or (at your |
10 | * option) any later version. | 10 | * option) any later version. |
11 | * | ||
12 | * Revision history | ||
13 | * 25th Sep 2008 Initial version. | ||
14 | */ | 11 | */ |
15 | 12 | ||
16 | #include <linux/init.h> | 13 | #include <linux/init.h> |
17 | #include <linux/module.h> | 14 | #include <linux/module.h> |
18 | #include <linux/version.h> | ||
19 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
20 | #include <linux/device.h> | 16 | #include <linux/device.h> |
21 | #include <sound/core.h> | 17 | #include <sound/core.h> |
@@ -68,7 +64,7 @@ static int ad73311_soc_probe(struct platform_device *pdev) | |||
68 | goto pcm_err; | 64 | goto pcm_err; |
69 | } | 65 | } |
70 | 66 | ||
71 | ret = snd_soc_register_card(socdev); | 67 | ret = snd_soc_init_card(socdev); |
72 | if (ret < 0) { | 68 | if (ret < 0) { |
73 | printk(KERN_ERR "ad73311: failed to register card\n"); | 69 | printk(KERN_ERR "ad73311: failed to register card\n"); |
74 | goto register_err; | 70 | goto register_err; |
@@ -102,6 +98,18 @@ struct snd_soc_codec_device soc_codec_dev_ad73311 = { | |||
102 | }; | 98 | }; |
103 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); | 99 | EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311); |
104 | 100 | ||
101 | static int __init ad73311_init(void) | ||
102 | { | ||
103 | return snd_soc_register_dai(&ad73311_dai); | ||
104 | } | ||
105 | module_init(ad73311_init); | ||
106 | |||
107 | static void __exit ad73311_exit(void) | ||
108 | { | ||
109 | snd_soc_unregister_dai(&ad73311_dai); | ||
110 | } | ||
111 | module_exit(ad73311_exit); | ||
112 | |||
105 | MODULE_DESCRIPTION("ASoC ad73311 driver"); | 113 | MODULE_DESCRIPTION("ASoC ad73311 driver"); |
106 | MODULE_AUTHOR("Cliff Cai "); | 114 | MODULE_AUTHOR("Cliff Cai "); |
107 | MODULE_LICENSE("GPL"); | 115 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 2a89b5888e11..81300d8d42ca 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -339,7 +339,8 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
339 | } | 339 | } |
340 | 340 | ||
341 | static int ak4535_hw_params(struct snd_pcm_substream *substream, | 341 | static int ak4535_hw_params(struct snd_pcm_substream *substream, |
342 | struct snd_pcm_hw_params *params) | 342 | struct snd_pcm_hw_params *params, |
343 | struct snd_soc_dai *dai) | ||
343 | { | 344 | { |
344 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 345 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
345 | struct snd_soc_device *socdev = rtd->socdev; | 346 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -451,8 +452,6 @@ struct snd_soc_dai ak4535_dai = { | |||
451 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 452 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
452 | .ops = { | 453 | .ops = { |
453 | .hw_params = ak4535_hw_params, | 454 | .hw_params = ak4535_hw_params, |
454 | }, | ||
455 | .dai_ops = { | ||
456 | .set_fmt = ak4535_set_dai_fmt, | 455 | .set_fmt = ak4535_set_dai_fmt, |
457 | .digital_mute = ak4535_mute, | 456 | .digital_mute = ak4535_mute, |
458 | .set_sysclk = ak4535_set_dai_sysclk, | 457 | .set_sysclk = ak4535_set_dai_sysclk, |
@@ -513,7 +512,7 @@ static int ak4535_init(struct snd_soc_device *socdev) | |||
513 | 512 | ||
514 | ak4535_add_controls(codec); | 513 | ak4535_add_controls(codec); |
515 | ak4535_add_widgets(codec); | 514 | ak4535_add_widgets(codec); |
516 | ret = snd_soc_register_card(socdev); | 515 | ret = snd_soc_init_card(socdev); |
517 | if (ret < 0) { | 516 | if (ret < 0) { |
518 | printk(KERN_ERR "ak4535: failed to register card\n"); | 517 | printk(KERN_ERR "ak4535: failed to register card\n"); |
519 | goto card_err; | 518 | goto card_err; |
@@ -689,6 +688,18 @@ struct snd_soc_codec_device soc_codec_dev_ak4535 = { | |||
689 | }; | 688 | }; |
690 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); | 689 | EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535); |
691 | 690 | ||
691 | static int __init ak4535_modinit(void) | ||
692 | { | ||
693 | return snd_soc_register_dai(&ak4535_dai); | ||
694 | } | ||
695 | module_init(ak4535_modinit); | ||
696 | |||
697 | static void __exit ak4535_exit(void) | ||
698 | { | ||
699 | snd_soc_unregister_dai(&ak4535_dai); | ||
700 | } | ||
701 | module_exit(ak4535_exit); | ||
702 | |||
692 | MODULE_DESCRIPTION("Soc AK4535 driver"); | 703 | MODULE_DESCRIPTION("Soc AK4535 driver"); |
693 | MODULE_AUTHOR("Richard Purdie"); | 704 | MODULE_AUTHOR("Richard Purdie"); |
694 | MODULE_LICENSE("GPL"); | 705 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 0bbd94501d7e..f1aa0c34421c 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -360,13 +360,14 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg, | |||
360 | /* | 360 | /* |
361 | * Program the CS4270 with the given hardware parameters. | 361 | * Program the CS4270 with the given hardware parameters. |
362 | * | 362 | * |
363 | * The .dai_ops functions are used to provide board-specific data, like | 363 | * The .ops functions are used to provide board-specific data, like |
364 | * input frequencies, to this driver. This function takes that information, | 364 | * input frequencies, to this driver. This function takes that information, |
365 | * combines it with the hardware parameters provided, and programs the | 365 | * combines it with the hardware parameters provided, and programs the |
366 | * hardware accordingly. | 366 | * hardware accordingly. |
367 | */ | 367 | */ |
368 | static int cs4270_hw_params(struct snd_pcm_substream *substream, | 368 | static int cs4270_hw_params(struct snd_pcm_substream *substream, |
369 | struct snd_pcm_hw_params *params) | 369 | struct snd_pcm_hw_params *params, |
370 | struct snd_soc_dai *dai) | ||
370 | { | 371 | { |
371 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 372 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
372 | struct snd_soc_device *socdev = rtd->socdev; | 373 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -450,6 +451,19 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
450 | return ret; | 451 | return ret; |
451 | } | 452 | } |
452 | 453 | ||
454 | /* Disable automatic volume control. It's enabled by default, and | ||
455 | * it causes volume change commands to be delayed, sometimes until | ||
456 | * after playback has started. | ||
457 | */ | ||
458 | |||
459 | reg = cs4270_read_reg_cache(codec, CS4270_TRANS); | ||
460 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | ||
461 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | ||
462 | if (ret < 0) { | ||
463 | printk(KERN_ERR "I2C write failed\n"); | ||
464 | return ret; | ||
465 | } | ||
466 | |||
453 | /* Thaw and power-up the codec */ | 467 | /* Thaw and power-up the codec */ |
454 | 468 | ||
455 | ret = snd_soc_write(codec, CS4270_PWRCTL, 0); | 469 | ret = snd_soc_write(codec, CS4270_PWRCTL, 0); |
@@ -697,10 +711,10 @@ static int cs4270_probe(struct platform_device *pdev) | |||
697 | if (codec->control_data) { | 711 | if (codec->control_data) { |
698 | /* Initialize codec ops */ | 712 | /* Initialize codec ops */ |
699 | cs4270_dai.ops.hw_params = cs4270_hw_params; | 713 | cs4270_dai.ops.hw_params = cs4270_hw_params; |
700 | cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk; | 714 | cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk; |
701 | cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt; | 715 | cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt; |
702 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | 716 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE |
703 | cs4270_dai.dai_ops.digital_mute = cs4270_mute; | 717 | cs4270_dai.ops.digital_mute = cs4270_mute; |
704 | #endif | 718 | #endif |
705 | } else | 719 | } else |
706 | printk(KERN_INFO "cs4270: no I2C device found, " | 720 | printk(KERN_INFO "cs4270: no I2C device found, " |
@@ -709,7 +723,7 @@ static int cs4270_probe(struct platform_device *pdev) | |||
709 | printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); | 723 | printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n"); |
710 | #endif | 724 | #endif |
711 | 725 | ||
712 | ret = snd_soc_register_card(socdev); | 726 | ret = snd_soc_init_card(socdev); |
713 | if (ret < 0) { | 727 | if (ret < 0) { |
714 | printk(KERN_ERR "cs4270: failed to register card\n"); | 728 | printk(KERN_ERR "cs4270: failed to register card\n"); |
715 | goto error_del_driver; | 729 | goto error_del_driver; |
@@ -760,6 +774,18 @@ struct snd_soc_codec_device soc_codec_device_cs4270 = { | |||
760 | }; | 774 | }; |
761 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); | 775 | EXPORT_SYMBOL_GPL(soc_codec_device_cs4270); |
762 | 776 | ||
777 | static int __init cs4270_init(void) | ||
778 | { | ||
779 | return snd_soc_register_dai(&cs4270_dai); | ||
780 | } | ||
781 | module_init(cs4270_init); | ||
782 | |||
783 | static void __exit cs4270_exit(void) | ||
784 | { | ||
785 | snd_soc_unregister_dai(&cs4270_dai); | ||
786 | } | ||
787 | module_exit(cs4270_exit); | ||
788 | |||
763 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 789 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
764 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | 790 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); |
765 | MODULE_LICENSE("GPL"); | 791 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c new file mode 100644 index 000000000000..5353af58862c --- /dev/null +++ b/sound/soc/codecs/l3.c | |||
@@ -0,0 +1,91 @@ | |||
1 | /* | ||
2 | * L3 code | ||
3 | * | ||
4 | * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * | ||
11 | * based on: | ||
12 | * | ||
13 | * L3 bus algorithm module. | ||
14 | * | ||
15 | * Copyright (C) 2001 Russell King, All Rights Reserved. | ||
16 | * | ||
17 | * | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/delay.h> | ||
23 | |||
24 | #include <sound/l3.h> | ||
25 | |||
26 | /* | ||
27 | * Send one byte of data to the chip. Data is latched into the chip on | ||
28 | * the rising edge of the clock. | ||
29 | */ | ||
30 | static void sendbyte(struct l3_pins *adap, unsigned int byte) | ||
31 | { | ||
32 | int i; | ||
33 | |||
34 | for (i = 0; i < 8; i++) { | ||
35 | adap->setclk(0); | ||
36 | udelay(adap->data_hold); | ||
37 | adap->setdat(byte & 1); | ||
38 | udelay(adap->data_setup); | ||
39 | adap->setclk(1); | ||
40 | udelay(adap->clock_high); | ||
41 | byte >>= 1; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | /* | ||
46 | * Send a set of bytes to the chip. We need to pulse the MODE line | ||
47 | * between each byte, but never at the start nor at the end of the | ||
48 | * transfer. | ||
49 | */ | ||
50 | static void sendbytes(struct l3_pins *adap, const u8 *buf, | ||
51 | int len) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | for (i = 0; i < len; i++) { | ||
56 | if (i) { | ||
57 | udelay(adap->mode_hold); | ||
58 | adap->setmode(0); | ||
59 | udelay(adap->mode); | ||
60 | } | ||
61 | adap->setmode(1); | ||
62 | udelay(adap->mode_setup); | ||
63 | sendbyte(adap, buf[i]); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len) | ||
68 | { | ||
69 | adap->setclk(1); | ||
70 | adap->setdat(1); | ||
71 | adap->setmode(1); | ||
72 | udelay(adap->mode); | ||
73 | |||
74 | adap->setmode(0); | ||
75 | udelay(adap->mode_setup); | ||
76 | sendbyte(adap, addr); | ||
77 | udelay(adap->mode_hold); | ||
78 | |||
79 | sendbytes(adap, data, len); | ||
80 | |||
81 | adap->setclk(1); | ||
82 | adap->setdat(1); | ||
83 | adap->setmode(0); | ||
84 | |||
85 | return len; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(l3_write); | ||
88 | |||
89 | MODULE_DESCRIPTION("L3 bit-banging driver"); | ||
90 | MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>"); | ||
91 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c new file mode 100644 index 000000000000..9a3e67e5319c --- /dev/null +++ b/sound/soc/codecs/pcm3008.c | |||
@@ -0,0 +1,212 @@ | |||
1 | /* | ||
2 | * ALSA Soc PCM3008 codec support | ||
3 | * | ||
4 | * Author: Hugo Villeneuve | ||
5 | * Copyright (C) 2008 Lyrtech inc | ||
6 | * | ||
7 | * Based on AC97 Soc codec, original copyright follow: | ||
8 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | * Generic PCM3008 support. | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/kernel.h> | ||
20 | #include <linux/device.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/initval.h> | ||
25 | #include <sound/soc.h> | ||
26 | |||
27 | #include "pcm3008.h" | ||
28 | |||
29 | #define PCM3008_VERSION "0.2" | ||
30 | |||
31 | #define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ | ||
32 | SNDRV_PCM_RATE_48000) | ||
33 | |||
34 | struct snd_soc_dai pcm3008_dai = { | ||
35 | .name = "PCM3008 HiFi", | ||
36 | .playback = { | ||
37 | .stream_name = "PCM3008 Playback", | ||
38 | .channels_min = 1, | ||
39 | .channels_max = 2, | ||
40 | .rates = PCM3008_RATES, | ||
41 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
42 | }, | ||
43 | .capture = { | ||
44 | .stream_name = "PCM3008 Capture", | ||
45 | .channels_min = 1, | ||
46 | .channels_max = 2, | ||
47 | .rates = PCM3008_RATES, | ||
48 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
49 | }, | ||
50 | }; | ||
51 | EXPORT_SYMBOL_GPL(pcm3008_dai); | ||
52 | |||
53 | static void pcm3008_gpio_free(struct pcm3008_setup_data *setup) | ||
54 | { | ||
55 | gpio_free(setup->dem0_pin); | ||
56 | gpio_free(setup->dem1_pin); | ||
57 | gpio_free(setup->pdad_pin); | ||
58 | gpio_free(setup->pdda_pin); | ||
59 | } | ||
60 | |||
61 | static int pcm3008_soc_probe(struct platform_device *pdev) | ||
62 | { | ||
63 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
64 | struct snd_soc_codec *codec; | ||
65 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
66 | int ret = 0; | ||
67 | |||
68 | printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION); | ||
69 | |||
70 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
71 | if (!socdev->codec) | ||
72 | return -ENOMEM; | ||
73 | |||
74 | codec = socdev->codec; | ||
75 | mutex_init(&codec->mutex); | ||
76 | |||
77 | codec->name = "PCM3008"; | ||
78 | codec->owner = THIS_MODULE; | ||
79 | codec->dai = &pcm3008_dai; | ||
80 | codec->num_dai = 1; | ||
81 | codec->write = NULL; | ||
82 | codec->read = NULL; | ||
83 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
84 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
85 | |||
86 | /* Register PCMs. */ | ||
87 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
88 | if (ret < 0) { | ||
89 | printk(KERN_ERR "pcm3008: failed to create pcms\n"); | ||
90 | goto pcm_err; | ||
91 | } | ||
92 | |||
93 | /* Register Card. */ | ||
94 | ret = snd_soc_init_card(socdev); | ||
95 | if (ret < 0) { | ||
96 | printk(KERN_ERR "pcm3008: failed to register card\n"); | ||
97 | goto card_err; | ||
98 | } | ||
99 | |||
100 | /* DEM1 DEM0 DE-EMPHASIS_MODE | ||
101 | * Low Low De-emphasis 44.1 kHz ON | ||
102 | * Low High De-emphasis OFF | ||
103 | * High Low De-emphasis 48 kHz ON | ||
104 | * High High De-emphasis 32 kHz ON | ||
105 | */ | ||
106 | |||
107 | /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */ | ||
108 | ret = gpio_request(setup->dem0_pin, "codec_dem0"); | ||
109 | if (ret == 0) | ||
110 | ret = gpio_direction_output(setup->dem0_pin, 1); | ||
111 | if (ret != 0) | ||
112 | goto gpio_err; | ||
113 | |||
114 | /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */ | ||
115 | ret = gpio_request(setup->dem1_pin, "codec_dem1"); | ||
116 | if (ret == 0) | ||
117 | ret = gpio_direction_output(setup->dem1_pin, 0); | ||
118 | if (ret != 0) | ||
119 | goto gpio_err; | ||
120 | |||
121 | /* Configure PDAD GPIO. */ | ||
122 | ret = gpio_request(setup->pdad_pin, "codec_pdad"); | ||
123 | if (ret == 0) | ||
124 | ret = gpio_direction_output(setup->pdad_pin, 1); | ||
125 | if (ret != 0) | ||
126 | goto gpio_err; | ||
127 | |||
128 | /* Configure PDDA GPIO. */ | ||
129 | ret = gpio_request(setup->pdda_pin, "codec_pdda"); | ||
130 | if (ret == 0) | ||
131 | ret = gpio_direction_output(setup->pdda_pin, 1); | ||
132 | if (ret != 0) | ||
133 | goto gpio_err; | ||
134 | |||
135 | return ret; | ||
136 | |||
137 | gpio_err: | ||
138 | pcm3008_gpio_free(setup); | ||
139 | card_err: | ||
140 | snd_soc_free_pcms(socdev); | ||
141 | pcm_err: | ||
142 | kfree(socdev->codec); | ||
143 | |||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static int pcm3008_soc_remove(struct platform_device *pdev) | ||
148 | { | ||
149 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
150 | struct snd_soc_codec *codec = socdev->codec; | ||
151 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
152 | |||
153 | if (!codec) | ||
154 | return 0; | ||
155 | |||
156 | pcm3008_gpio_free(setup); | ||
157 | snd_soc_free_pcms(socdev); | ||
158 | kfree(socdev->codec); | ||
159 | |||
160 | return 0; | ||
161 | } | ||
162 | |||
163 | #ifdef CONFIG_PM | ||
164 | static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg) | ||
165 | { | ||
166 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
167 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
168 | |||
169 | gpio_set_value(setup->pdad_pin, 0); | ||
170 | gpio_set_value(setup->pdda_pin, 0); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int pcm3008_soc_resume(struct platform_device *pdev) | ||
176 | { | ||
177 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
178 | struct pcm3008_setup_data *setup = socdev->codec_data; | ||
179 | |||
180 | gpio_set_value(setup->pdad_pin, 1); | ||
181 | gpio_set_value(setup->pdda_pin, 1); | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | #else | ||
186 | #define pcm3008_soc_suspend NULL | ||
187 | #define pcm3008_soc_resume NULL | ||
188 | #endif | ||
189 | |||
190 | struct snd_soc_codec_device soc_codec_dev_pcm3008 = { | ||
191 | .probe = pcm3008_soc_probe, | ||
192 | .remove = pcm3008_soc_remove, | ||
193 | .suspend = pcm3008_soc_suspend, | ||
194 | .resume = pcm3008_soc_resume, | ||
195 | }; | ||
196 | EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008); | ||
197 | |||
198 | static int __init pcm3008_init(void) | ||
199 | { | ||
200 | return snd_soc_register_dai(&pcm3008_dai); | ||
201 | } | ||
202 | module_init(pcm3008_init); | ||
203 | |||
204 | static void __exit pcm3008_exit(void) | ||
205 | { | ||
206 | snd_soc_unregister_dai(&pcm3008_dai); | ||
207 | } | ||
208 | module_exit(pcm3008_exit); | ||
209 | |||
210 | MODULE_DESCRIPTION("Soc PCM3008 driver"); | ||
211 | MODULE_AUTHOR("Hugo Villeneuve"); | ||
212 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h new file mode 100644 index 000000000000..d04e87d3c060 --- /dev/null +++ b/sound/soc/codecs/pcm3008.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * PCM3008 ALSA SoC Layer | ||
3 | * | ||
4 | * Author: Hugo Villeneuve | ||
5 | * Copyright (C) 2008 Lyrtech inc | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #ifndef __LINUX_SND_SOC_PCM3008_H | ||
13 | #define __LINUX_SND_SOC_PCM3008_H | ||
14 | |||
15 | struct pcm3008_setup_data { | ||
16 | unsigned dem0_pin; | ||
17 | unsigned dem1_pin; | ||
18 | unsigned pdad_pin; | ||
19 | unsigned pdda_pin; | ||
20 | }; | ||
21 | |||
22 | extern struct snd_soc_codec_device soc_codec_dev_pcm3008; | ||
23 | extern struct snd_soc_dai pcm3008_dai; | ||
24 | |||
25 | #endif | ||
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 44ef0dacd564..cac373616768 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -285,16 +285,23 @@ static inline int get_coeff(int mclk, int rate) | |||
285 | } | 285 | } |
286 | 286 | ||
287 | static int ssm2602_hw_params(struct snd_pcm_substream *substream, | 287 | static int ssm2602_hw_params(struct snd_pcm_substream *substream, |
288 | struct snd_pcm_hw_params *params) | 288 | struct snd_pcm_hw_params *params, |
289 | struct snd_soc_dai *dai) | ||
289 | { | 290 | { |
290 | u16 srate; | 291 | u16 srate; |
291 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 292 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
292 | struct snd_soc_device *socdev = rtd->socdev; | 293 | struct snd_soc_device *socdev = rtd->socdev; |
293 | struct snd_soc_codec *codec = socdev->codec; | 294 | struct snd_soc_codec *codec = socdev->codec; |
294 | struct ssm2602_priv *ssm2602 = codec->private_data; | 295 | struct ssm2602_priv *ssm2602 = codec->private_data; |
296 | struct i2c_client *i2c = codec->control_data; | ||
295 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; | 297 | u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3; |
296 | int i = get_coeff(ssm2602->sysclk, params_rate(params)); | 298 | int i = get_coeff(ssm2602->sysclk, params_rate(params)); |
297 | 299 | ||
300 | if (substream == ssm2602->slave_substream) { | ||
301 | dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n"); | ||
302 | return 0; | ||
303 | } | ||
304 | |||
298 | /*no match is found*/ | 305 | /*no match is found*/ |
299 | if (i == ARRAY_SIZE(coeff_div)) | 306 | if (i == ARRAY_SIZE(coeff_div)) |
300 | return -EINVAL; | 307 | return -EINVAL; |
@@ -324,19 +331,26 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream, | |||
324 | return 0; | 331 | return 0; |
325 | } | 332 | } |
326 | 333 | ||
327 | static int ssm2602_startup(struct snd_pcm_substream *substream) | 334 | static int ssm2602_startup(struct snd_pcm_substream *substream, |
335 | struct snd_soc_dai *dai) | ||
328 | { | 336 | { |
329 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 337 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
330 | struct snd_soc_device *socdev = rtd->socdev; | 338 | struct snd_soc_device *socdev = rtd->socdev; |
331 | struct snd_soc_codec *codec = socdev->codec; | 339 | struct snd_soc_codec *codec = socdev->codec; |
332 | struct ssm2602_priv *ssm2602 = codec->private_data; | 340 | struct ssm2602_priv *ssm2602 = codec->private_data; |
341 | struct i2c_client *i2c = codec->control_data; | ||
333 | struct snd_pcm_runtime *master_runtime; | 342 | struct snd_pcm_runtime *master_runtime; |
334 | 343 | ||
335 | /* The DAI has shared clocks so if we already have a playback or | 344 | /* The DAI has shared clocks so if we already have a playback or |
336 | * capture going then constrain this substream to match it. | 345 | * capture going then constrain this substream to match it. |
346 | * TODO: the ssm2602 allows pairs of non-matching PB/REC rates | ||
337 | */ | 347 | */ |
338 | if (ssm2602->master_substream) { | 348 | if (ssm2602->master_substream) { |
339 | master_runtime = ssm2602->master_substream->runtime; | 349 | master_runtime = ssm2602->master_substream->runtime; |
350 | dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", | ||
351 | master_runtime->sample_bits, | ||
352 | master_runtime->rate); | ||
353 | |||
340 | snd_pcm_hw_constraint_minmax(substream->runtime, | 354 | snd_pcm_hw_constraint_minmax(substream->runtime, |
341 | SNDRV_PCM_HW_PARAM_RATE, | 355 | SNDRV_PCM_HW_PARAM_RATE, |
342 | master_runtime->rate, | 356 | master_runtime->rate, |
@@ -354,7 +368,8 @@ static int ssm2602_startup(struct snd_pcm_substream *substream) | |||
354 | return 0; | 368 | return 0; |
355 | } | 369 | } |
356 | 370 | ||
357 | static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream) | 371 | static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream, |
372 | struct snd_soc_dai *dai) | ||
358 | { | 373 | { |
359 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 374 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
360 | struct snd_soc_device *socdev = rtd->socdev; | 375 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -365,14 +380,21 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream) | |||
365 | return 0; | 380 | return 0; |
366 | } | 381 | } |
367 | 382 | ||
368 | static void ssm2602_shutdown(struct snd_pcm_substream *substream) | 383 | static void ssm2602_shutdown(struct snd_pcm_substream *substream, |
384 | struct snd_soc_dai *dai) | ||
369 | { | 385 | { |
370 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 386 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
371 | struct snd_soc_device *socdev = rtd->socdev; | 387 | struct snd_soc_device *socdev = rtd->socdev; |
372 | struct snd_soc_codec *codec = socdev->codec; | 388 | struct snd_soc_codec *codec = socdev->codec; |
389 | struct ssm2602_priv *ssm2602 = codec->private_data; | ||
373 | /* deactivate */ | 390 | /* deactivate */ |
374 | if (!codec->active) | 391 | if (!codec->active) |
375 | ssm2602_write(codec, SSM2602_ACTIVE, 0); | 392 | ssm2602_write(codec, SSM2602_ACTIVE, 0); |
393 | |||
394 | if (ssm2602->master_substream == substream) | ||
395 | ssm2602->master_substream = ssm2602->slave_substream; | ||
396 | |||
397 | ssm2602->slave_substream = NULL; | ||
376 | } | 398 | } |
377 | 399 | ||
378 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) | 400 | static int ssm2602_mute(struct snd_soc_dai *dai, int mute) |
@@ -432,10 +454,10 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
432 | iface |= 0x0001; | 454 | iface |= 0x0001; |
433 | break; | 455 | break; |
434 | case SND_SOC_DAIFMT_DSP_A: | 456 | case SND_SOC_DAIFMT_DSP_A: |
435 | iface |= 0x0003; | 457 | iface |= 0x0013; |
436 | break; | 458 | break; |
437 | case SND_SOC_DAIFMT_DSP_B: | 459 | case SND_SOC_DAIFMT_DSP_B: |
438 | iface |= 0x0013; | 460 | iface |= 0x0003; |
439 | break; | 461 | break; |
440 | default: | 462 | default: |
441 | return -EINVAL; | 463 | return -EINVAL; |
@@ -496,6 +518,9 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec, | |||
496 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | 518 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ |
497 | SNDRV_PCM_RATE_96000) | 519 | SNDRV_PCM_RATE_96000) |
498 | 520 | ||
521 | #define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
522 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
523 | |||
499 | struct snd_soc_dai ssm2602_dai = { | 524 | struct snd_soc_dai ssm2602_dai = { |
500 | .name = "SSM2602", | 525 | .name = "SSM2602", |
501 | .playback = { | 526 | .playback = { |
@@ -503,20 +528,18 @@ struct snd_soc_dai ssm2602_dai = { | |||
503 | .channels_min = 2, | 528 | .channels_min = 2, |
504 | .channels_max = 2, | 529 | .channels_max = 2, |
505 | .rates = SSM2602_RATES, | 530 | .rates = SSM2602_RATES, |
506 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, | 531 | .formats = SSM2602_FORMATS,}, |
507 | .capture = { | 532 | .capture = { |
508 | .stream_name = "Capture", | 533 | .stream_name = "Capture", |
509 | .channels_min = 2, | 534 | .channels_min = 2, |
510 | .channels_max = 2, | 535 | .channels_max = 2, |
511 | .rates = SSM2602_RATES, | 536 | .rates = SSM2602_RATES, |
512 | .formats = SNDRV_PCM_FMTBIT_S32_LE,}, | 537 | .formats = SSM2602_FORMATS,}, |
513 | .ops = { | 538 | .ops = { |
514 | .startup = ssm2602_startup, | 539 | .startup = ssm2602_startup, |
515 | .prepare = ssm2602_pcm_prepare, | 540 | .prepare = ssm2602_pcm_prepare, |
516 | .hw_params = ssm2602_hw_params, | 541 | .hw_params = ssm2602_hw_params, |
517 | .shutdown = ssm2602_shutdown, | 542 | .shutdown = ssm2602_shutdown, |
518 | }, | ||
519 | .dai_ops = { | ||
520 | .digital_mute = ssm2602_mute, | 543 | .digital_mute = ssm2602_mute, |
521 | .set_sysclk = ssm2602_set_dai_sysclk, | 544 | .set_sysclk = ssm2602_set_dai_sysclk, |
522 | .set_fmt = ssm2602_set_dai_fmt, | 545 | .set_fmt = ssm2602_set_dai_fmt, |
@@ -601,7 +624,7 @@ static int ssm2602_init(struct snd_soc_device *socdev) | |||
601 | 624 | ||
602 | ssm2602_add_controls(codec); | 625 | ssm2602_add_controls(codec); |
603 | ssm2602_add_widgets(codec); | 626 | ssm2602_add_widgets(codec); |
604 | ret = snd_soc_register_card(socdev); | 627 | ret = snd_soc_init_card(socdev); |
605 | if (ret < 0) { | 628 | if (ret < 0) { |
606 | pr_err("ssm2602: failed to register card\n"); | 629 | pr_err("ssm2602: failed to register card\n"); |
607 | goto card_err; | 630 | goto card_err; |
@@ -770,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_ssm2602 = { | |||
770 | }; | 793 | }; |
771 | EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); | 794 | EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602); |
772 | 795 | ||
796 | static int __init ssm2602_modinit(void) | ||
797 | { | ||
798 | return snd_soc_register_dai(&ssm2602_dai); | ||
799 | } | ||
800 | module_init(ssm2602_modinit); | ||
801 | |||
802 | static void __exit ssm2602_exit(void) | ||
803 | { | ||
804 | snd_soc_unregister_dai(&ssm2602_dai); | ||
805 | } | ||
806 | module_exit(ssm2602_exit); | ||
807 | |||
773 | MODULE_DESCRIPTION("ASoC ssm2602 driver"); | 808 | MODULE_DESCRIPTION("ASoC ssm2602 driver"); |
774 | MODULE_AUTHOR("Cliff Cai"); | 809 | MODULE_AUTHOR("Cliff Cai"); |
775 | MODULE_LICENSE("GPL"); | 810 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index 44308dac9e18..cfdea007c4cb 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c | |||
@@ -37,12 +37,6 @@ | |||
37 | 37 | ||
38 | #define AIC23_VERSION "0.1" | 38 | #define AIC23_VERSION "0.1" |
39 | 39 | ||
40 | struct tlv320aic23_srate_reg_info { | ||
41 | u32 sample_rate; | ||
42 | u8 control; /* SR3, SR2, SR1, SR0 and BOSR */ | ||
43 | u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */ | ||
44 | }; | ||
45 | |||
46 | /* | 40 | /* |
47 | * AIC23 register cache | 41 | * AIC23 register cache |
48 | */ | 42 | */ |
@@ -261,20 +255,156 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
261 | 255 | ||
262 | }; | 256 | }; |
263 | 257 | ||
264 | /* tlv320aic23 related */ | 258 | /* AIC23 driver data */ |
265 | static const struct tlv320aic23_srate_reg_info srate_reg_info[] = { | 259 | struct aic23 { |
266 | {4000, 0x06, 1}, /* 4000 */ | 260 | struct snd_soc_codec codec; |
267 | {8000, 0x06, 0}, /* 8000 */ | 261 | int mclk; |
268 | {16000, 0x0C, 1}, /* 16000 */ | 262 | int requested_adc; |
269 | {22050, 0x11, 1}, /* 22050 */ | 263 | int requested_dac; |
270 | {24000, 0x00, 1}, /* 24000 */ | 264 | }; |
271 | {32000, 0x0C, 0}, /* 32000 */ | 265 | |
272 | {44100, 0x11, 0}, /* 44100 */ | 266 | /* |
273 | {48000, 0x00, 0}, /* 48000 */ | 267 | * Common Crystals used |
274 | {88200, 0x1F, 0}, /* 88200 */ | 268 | * 11.2896 Mhz /128 = *88.2k /192 = 58.8k |
275 | {96000, 0x0E, 0}, /* 96000 */ | 269 | * 12.0000 Mhz /125 = *96k /136 = 88.235K |
270 | * 12.2880 Mhz /128 = *96k /192 = 64k | ||
271 | * 16.9344 Mhz /128 = 132.3k /192 = *88.2k | ||
272 | * 18.4320 Mhz /128 = 144k /192 = *96k | ||
273 | */ | ||
274 | |||
275 | /* | ||
276 | * Normal BOSR 0-256/2 = 128, 1-384/2 = 192 | ||
277 | * USB BOSR 0-250/2 = 125, 1-272/2 = 136 | ||
278 | */ | ||
279 | static const int bosr_usb_divisor_table[] = { | ||
280 | 128, 125, 192, 136 | ||
281 | }; | ||
282 | #define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7)) | ||
283 | #define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15)) | ||
284 | static const unsigned short sr_valid_mask[] = { | ||
285 | LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/ | ||
286 | LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/ | ||
287 | LOWER_GROUP, /* Usb, bosr - 0*/ | ||
288 | UPPER_GROUP, /* Usb, bosr - 1*/ | ||
289 | }; | ||
290 | /* | ||
291 | * Every divisor is a factor of 11*12 | ||
292 | */ | ||
293 | #define SR_MULT (11*12) | ||
294 | #define A(x) (x) ? (SR_MULT/x) : 0 | ||
295 | static const unsigned char sr_adc_mult_table[] = { | ||
296 | A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1), | ||
297 | A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1) | ||
298 | }; | ||
299 | static const unsigned char sr_dac_mult_table[] = { | ||
300 | A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1), | ||
301 | A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1) | ||
276 | }; | 302 | }; |
277 | 303 | ||
304 | static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc, | ||
305 | int dac, int dac_l, int dac_h, int need_dac) | ||
306 | { | ||
307 | if ((adc >= adc_l) && (adc <= adc_h) && | ||
308 | (dac >= dac_l) && (dac <= dac_h)) { | ||
309 | int diff_adc = need_adc - adc; | ||
310 | int diff_dac = need_dac - dac; | ||
311 | return abs(diff_adc) + abs(diff_dac); | ||
312 | } | ||
313 | return UINT_MAX; | ||
314 | } | ||
315 | |||
316 | static int find_rate(int mclk, u32 need_adc, u32 need_dac) | ||
317 | { | ||
318 | int i, j; | ||
319 | int best_i = -1; | ||
320 | int best_j = -1; | ||
321 | int best_div = 0; | ||
322 | unsigned best_score = UINT_MAX; | ||
323 | int adc_l, adc_h, dac_l, dac_h; | ||
324 | |||
325 | need_adc *= SR_MULT; | ||
326 | need_dac *= SR_MULT; | ||
327 | /* | ||
328 | * rates given are +/- 1/32 | ||
329 | */ | ||
330 | adc_l = need_adc - (need_adc >> 5); | ||
331 | adc_h = need_adc + (need_adc >> 5); | ||
332 | dac_l = need_dac - (need_dac >> 5); | ||
333 | dac_h = need_dac + (need_dac >> 5); | ||
334 | for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) { | ||
335 | int base = mclk / bosr_usb_divisor_table[i]; | ||
336 | int mask = sr_valid_mask[i]; | ||
337 | for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table); | ||
338 | j++, mask >>= 1) { | ||
339 | int adc; | ||
340 | int dac; | ||
341 | int score; | ||
342 | if ((mask & 1) == 0) | ||
343 | continue; | ||
344 | adc = base * sr_adc_mult_table[j]; | ||
345 | dac = base * sr_dac_mult_table[j]; | ||
346 | score = get_score(adc, adc_l, adc_h, need_adc, | ||
347 | dac, dac_l, dac_h, need_dac); | ||
348 | if (best_score > score) { | ||
349 | best_score = score; | ||
350 | best_i = i; | ||
351 | best_j = j; | ||
352 | best_div = 0; | ||
353 | } | ||
354 | score = get_score((adc >> 1), adc_l, adc_h, need_adc, | ||
355 | (dac >> 1), dac_l, dac_h, need_dac); | ||
356 | /* prefer to have a /2 */ | ||
357 | if ((score != UINT_MAX) && (best_score >= score)) { | ||
358 | best_score = score; | ||
359 | best_i = i; | ||
360 | best_j = j; | ||
361 | best_div = 1; | ||
362 | } | ||
363 | } | ||
364 | } | ||
365 | return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT); | ||
366 | } | ||
367 | |||
368 | #ifdef DEBUG | ||
369 | static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk, | ||
370 | u32 *sample_rate_adc, u32 *sample_rate_dac) | ||
371 | { | ||
372 | int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE); | ||
373 | int sr = (src >> 2) & 0x0f; | ||
374 | int val = (mclk / bosr_usb_divisor_table[src & 3]); | ||
375 | int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; | ||
376 | int dac = (val * sr_dac_mult_table[sr]) / SR_MULT; | ||
377 | if (src & TLV320AIC23_CLKIN_HALF) { | ||
378 | adc >>= 1; | ||
379 | dac >>= 1; | ||
380 | } | ||
381 | *sample_rate_adc = adc; | ||
382 | *sample_rate_dac = dac; | ||
383 | } | ||
384 | #endif | ||
385 | |||
386 | static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, | ||
387 | u32 sample_rate_adc, u32 sample_rate_dac) | ||
388 | { | ||
389 | /* Search for the right sample rate */ | ||
390 | int data = find_rate(mclk, sample_rate_adc, sample_rate_dac); | ||
391 | if (data < 0) { | ||
392 | printk(KERN_ERR "%s:Invalid rate %u,%u requested\n", | ||
393 | __func__, sample_rate_adc, sample_rate_dac); | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | tlv320aic23_write(codec, TLV320AIC23_SRATE, data); | ||
397 | #ifdef DEBUG | ||
398 | { | ||
399 | u32 adc, dac; | ||
400 | get_current_sample_rates(codec, mclk, &adc, &dac); | ||
401 | printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n", | ||
402 | adc, dac, data); | ||
403 | } | ||
404 | #endif | ||
405 | return 0; | ||
406 | } | ||
407 | |||
278 | static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) | 408 | static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) |
279 | { | 409 | { |
280 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, | 410 | snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, |
@@ -288,32 +418,36 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) | |||
288 | } | 418 | } |
289 | 419 | ||
290 | static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | 420 | static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, |
291 | struct snd_pcm_hw_params *params) | 421 | struct snd_pcm_hw_params *params, |
422 | struct snd_soc_dai *dai) | ||
292 | { | 423 | { |
293 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 424 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
294 | struct snd_soc_device *socdev = rtd->socdev; | 425 | struct snd_soc_device *socdev = rtd->socdev; |
295 | struct snd_soc_codec *codec = socdev->codec; | 426 | struct snd_soc_codec *codec = socdev->codec; |
296 | u16 iface_reg, data; | 427 | u16 iface_reg; |
297 | u8 count = 0; | 428 | int ret; |
429 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
430 | u32 sample_rate_adc = aic23->requested_adc; | ||
431 | u32 sample_rate_dac = aic23->requested_dac; | ||
432 | u32 sample_rate = params_rate(params); | ||
433 | |||
434 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
435 | aic23->requested_dac = sample_rate_dac = sample_rate; | ||
436 | if (!sample_rate_adc) | ||
437 | sample_rate_adc = sample_rate; | ||
438 | } else { | ||
439 | aic23->requested_adc = sample_rate_adc = sample_rate; | ||
440 | if (!sample_rate_dac) | ||
441 | sample_rate_dac = sample_rate; | ||
442 | } | ||
443 | ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc, | ||
444 | sample_rate_dac); | ||
445 | if (ret < 0) | ||
446 | return ret; | ||
298 | 447 | ||
299 | iface_reg = | 448 | iface_reg = |
300 | tlv320aic23_read_reg_cache(codec, | 449 | tlv320aic23_read_reg_cache(codec, |
301 | TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); | 450 | TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); |
302 | |||
303 | /* Search for the right sample rate */ | ||
304 | /* Verify what happens if the rate is not supported | ||
305 | * now it goes to 96Khz */ | ||
306 | while ((srate_reg_info[count].sample_rate != params_rate(params)) && | ||
307 | (count < ARRAY_SIZE(srate_reg_info))) { | ||
308 | count++; | ||
309 | } | ||
310 | |||
311 | data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) | | ||
312 | (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) | | ||
313 | TLV320AIC23_USB_CLK_ON; | ||
314 | |||
315 | tlv320aic23_write(codec, TLV320AIC23_SRATE, data); | ||
316 | |||
317 | switch (params_format(params)) { | 451 | switch (params_format(params)) { |
318 | case SNDRV_PCM_FORMAT_S16_LE: | 452 | case SNDRV_PCM_FORMAT_S16_LE: |
319 | break; | 453 | break; |
@@ -332,7 +466,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, | |||
332 | return 0; | 466 | return 0; |
333 | } | 467 | } |
334 | 468 | ||
335 | static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream) | 469 | static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, |
470 | struct snd_soc_dai *dai) | ||
336 | { | 471 | { |
337 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 472 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
338 | struct snd_soc_device *socdev = rtd->socdev; | 473 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -344,17 +479,23 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream) | |||
344 | return 0; | 479 | return 0; |
345 | } | 480 | } |
346 | 481 | ||
347 | static void tlv320aic23_shutdown(struct snd_pcm_substream *substream) | 482 | static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, |
483 | struct snd_soc_dai *dai) | ||
348 | { | 484 | { |
349 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 485 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
350 | struct snd_soc_device *socdev = rtd->socdev; | 486 | struct snd_soc_device *socdev = rtd->socdev; |
351 | struct snd_soc_codec *codec = socdev->codec; | 487 | struct snd_soc_codec *codec = socdev->codec; |
488 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
352 | 489 | ||
353 | /* deactivate */ | 490 | /* deactivate */ |
354 | if (!codec->active) { | 491 | if (!codec->active) { |
355 | udelay(50); | 492 | udelay(50); |
356 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); | 493 | tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); |
357 | } | 494 | } |
495 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
496 | aic23->requested_dac = 0; | ||
497 | else | ||
498 | aic23->requested_adc = 0; | ||
358 | } | 499 | } |
359 | 500 | ||
360 | static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) | 501 | static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) |
@@ -400,7 +541,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
400 | case SND_SOC_DAIFMT_I2S: | 541 | case SND_SOC_DAIFMT_I2S: |
401 | iface_reg |= TLV320AIC23_FOR_I2S; | 542 | iface_reg |= TLV320AIC23_FOR_I2S; |
402 | break; | 543 | break; |
403 | case SND_SOC_DAIFMT_DSP_A: | 544 | case SND_SOC_DAIFMT_DSP_B: |
404 | iface_reg |= TLV320AIC23_FOR_DSP; | 545 | iface_reg |= TLV320AIC23_FOR_DSP; |
405 | break; | 546 | break; |
406 | case SND_SOC_DAIFMT_RIGHT_J: | 547 | case SND_SOC_DAIFMT_RIGHT_J: |
@@ -422,12 +563,9 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
422 | int clk_id, unsigned int freq, int dir) | 563 | int clk_id, unsigned int freq, int dir) |
423 | { | 564 | { |
424 | struct snd_soc_codec *codec = codec_dai->codec; | 565 | struct snd_soc_codec *codec = codec_dai->codec; |
425 | 566 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | |
426 | switch (freq) { | 567 | aic23->mclk = freq; |
427 | case 12000000: | 568 | return 0; |
428 | return 0; | ||
429 | } | ||
430 | return -EINVAL; | ||
431 | } | 569 | } |
432 | 570 | ||
433 | static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, | 571 | static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, |
@@ -478,12 +616,10 @@ struct snd_soc_dai tlv320aic23_dai = { | |||
478 | .prepare = tlv320aic23_pcm_prepare, | 616 | .prepare = tlv320aic23_pcm_prepare, |
479 | .hw_params = tlv320aic23_hw_params, | 617 | .hw_params = tlv320aic23_hw_params, |
480 | .shutdown = tlv320aic23_shutdown, | 618 | .shutdown = tlv320aic23_shutdown, |
481 | }, | 619 | .digital_mute = tlv320aic23_mute, |
482 | .dai_ops = { | 620 | .set_fmt = tlv320aic23_set_dai_fmt, |
483 | .digital_mute = tlv320aic23_mute, | 621 | .set_sysclk = tlv320aic23_set_dai_sysclk, |
484 | .set_fmt = tlv320aic23_set_dai_fmt, | 622 | } |
485 | .set_sysclk = tlv320aic23_set_dai_sysclk, | ||
486 | } | ||
487 | }; | 623 | }; |
488 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); | 624 | EXPORT_SYMBOL_GPL(tlv320aic23_dai); |
489 | 625 | ||
@@ -584,7 +720,7 @@ static int tlv320aic23_init(struct snd_soc_device *socdev) | |||
584 | 720 | ||
585 | tlv320aic23_add_controls(codec); | 721 | tlv320aic23_add_controls(codec); |
586 | tlv320aic23_add_widgets(codec); | 722 | tlv320aic23_add_widgets(codec); |
587 | ret = snd_soc_register_card(socdev); | 723 | ret = snd_soc_init_card(socdev); |
588 | if (ret < 0) { | 724 | if (ret < 0) { |
589 | printk(KERN_ERR "tlv320aic23: failed to register card\n"); | 725 | printk(KERN_ERR "tlv320aic23: failed to register card\n"); |
590 | goto card_err; | 726 | goto card_err; |
@@ -659,14 +795,15 @@ static int tlv320aic23_probe(struct platform_device *pdev) | |||
659 | { | 795 | { |
660 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 796 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
661 | struct snd_soc_codec *codec; | 797 | struct snd_soc_codec *codec; |
798 | struct aic23 *aic23; | ||
662 | int ret = 0; | 799 | int ret = 0; |
663 | 800 | ||
664 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); | 801 | printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); |
665 | 802 | ||
666 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 803 | aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); |
667 | if (codec == NULL) | 804 | if (aic23 == NULL) |
668 | return -ENOMEM; | 805 | return -ENOMEM; |
669 | 806 | codec = &aic23->codec; | |
670 | socdev->codec = codec; | 807 | socdev->codec = codec; |
671 | mutex_init(&codec->mutex); | 808 | mutex_init(&codec->mutex); |
672 | INIT_LIST_HEAD(&codec->dapm_widgets); | 809 | INIT_LIST_HEAD(&codec->dapm_widgets); |
@@ -687,6 +824,7 @@ static int tlv320aic23_remove(struct platform_device *pdev) | |||
687 | { | 824 | { |
688 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 825 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
689 | struct snd_soc_codec *codec = socdev->codec; | 826 | struct snd_soc_codec *codec = socdev->codec; |
827 | struct aic23 *aic23 = container_of(codec, struct aic23, codec); | ||
690 | 828 | ||
691 | if (codec->control_data) | 829 | if (codec->control_data) |
692 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); | 830 | tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); |
@@ -697,7 +835,7 @@ static int tlv320aic23_remove(struct platform_device *pdev) | |||
697 | i2c_del_driver(&tlv320aic23_i2c_driver); | 835 | i2c_del_driver(&tlv320aic23_i2c_driver); |
698 | #endif | 836 | #endif |
699 | kfree(codec->reg_cache); | 837 | kfree(codec->reg_cache); |
700 | kfree(codec); | 838 | kfree(aic23); |
701 | 839 | ||
702 | return 0; | 840 | return 0; |
703 | } | 841 | } |
@@ -709,6 +847,18 @@ struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = { | |||
709 | }; | 847 | }; |
710 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); | 848 | EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23); |
711 | 849 | ||
850 | static int __init tlv320aic23_modinit(void) | ||
851 | { | ||
852 | return snd_soc_register_dai(&tlv320aic23_dai); | ||
853 | } | ||
854 | module_init(tlv320aic23_modinit); | ||
855 | |||
856 | static void __exit tlv320aic23_exit(void) | ||
857 | { | ||
858 | snd_soc_unregister_dai(&tlv320aic23_dai); | ||
859 | } | ||
860 | module_exit(tlv320aic23_exit); | ||
861 | |||
712 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); | 862 | MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); |
713 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | 863 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); |
714 | MODULE_LICENSE("GPL"); | 864 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index bed8a9e63ddc..29f2f1a017fd 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -125,7 +125,8 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg, | |||
125 | * Digital Audio Interface Operations | 125 | * Digital Audio Interface Operations |
126 | */ | 126 | */ |
127 | static int aic26_hw_params(struct snd_pcm_substream *substream, | 127 | static int aic26_hw_params(struct snd_pcm_substream *substream, |
128 | struct snd_pcm_hw_params *params) | 128 | struct snd_pcm_hw_params *params, |
129 | struct snd_soc_dai *dai) | ||
129 | { | 130 | { |
130 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
131 | struct snd_soc_device *socdev = rtd->socdev; | 132 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -287,8 +288,6 @@ struct snd_soc_dai aic26_dai = { | |||
287 | }, | 288 | }, |
288 | .ops = { | 289 | .ops = { |
289 | .hw_params = aic26_hw_params, | 290 | .hw_params = aic26_hw_params, |
290 | }, | ||
291 | .dai_ops = { | ||
292 | .digital_mute = aic26_mute, | 291 | .digital_mute = aic26_mute, |
293 | .set_sysclk = aic26_set_sysclk, | 292 | .set_sysclk = aic26_set_sysclk, |
294 | .set_fmt = aic26_set_fmt, | 293 | .set_fmt = aic26_set_fmt, |
@@ -360,7 +359,7 @@ static int aic26_probe(struct platform_device *pdev) | |||
360 | 359 | ||
361 | /* CODEC is setup, we can register the card now */ | 360 | /* CODEC is setup, we can register the card now */ |
362 | dev_dbg(&pdev->dev, "Registering card\n"); | 361 | dev_dbg(&pdev->dev, "Registering card\n"); |
363 | ret = snd_soc_register_card(socdev); | 362 | ret = snd_soc_init_card(socdev); |
364 | if (ret < 0) { | 363 | if (ret < 0) { |
365 | dev_err(&pdev->dev, "aic26: failed to register card\n"); | 364 | dev_err(&pdev->dev, "aic26: failed to register card\n"); |
366 | goto card_err; | 365 | goto card_err; |
@@ -427,7 +426,7 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set); | |||
427 | static int aic26_spi_probe(struct spi_device *spi) | 426 | static int aic26_spi_probe(struct spi_device *spi) |
428 | { | 427 | { |
429 | struct aic26 *aic26; | 428 | struct aic26 *aic26; |
430 | int rc, i, reg; | 429 | int ret, i, reg; |
431 | 430 | ||
432 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); | 431 | dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n"); |
433 | 432 | ||
@@ -457,6 +456,14 @@ static int aic26_spi_probe(struct spi_device *spi) | |||
457 | aic26->codec.reg_cache_size = AIC26_NUM_REGS; | 456 | aic26->codec.reg_cache_size = AIC26_NUM_REGS; |
458 | aic26->codec.reg_cache = aic26->reg_cache; | 457 | aic26->codec.reg_cache = aic26->reg_cache; |
459 | 458 | ||
459 | aic26_dai.dev = &spi->dev; | ||
460 | ret = snd_soc_register_dai(&aic26_dai); | ||
461 | if (ret != 0) { | ||
462 | dev_err(&spi->dev, "Failed to register DAI: %d\n", ret); | ||
463 | kfree(aic26); | ||
464 | return ret; | ||
465 | } | ||
466 | |||
460 | /* Reset the codec to power on defaults */ | 467 | /* Reset the codec to power on defaults */ |
461 | aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); | 468 | aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00); |
462 | 469 | ||
@@ -475,8 +482,8 @@ static int aic26_spi_probe(struct spi_device *spi) | |||
475 | 482 | ||
476 | /* Register the sysfs files for debugging */ | 483 | /* Register the sysfs files for debugging */ |
477 | /* Create SysFS files */ | 484 | /* Create SysFS files */ |
478 | rc = device_create_file(&spi->dev, &dev_attr_keyclick); | 485 | ret = device_create_file(&spi->dev, &dev_attr_keyclick); |
479 | if (rc) | 486 | if (ret) |
480 | dev_info(&spi->dev, "error creating sysfs files\n"); | 487 | dev_info(&spi->dev, "error creating sysfs files\n"); |
481 | 488 | ||
482 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) | 489 | #if defined(CONFIG_SND_SOC_OF_SIMPLE) |
@@ -493,6 +500,7 @@ static int aic26_spi_remove(struct spi_device *spi) | |||
493 | { | 500 | { |
494 | struct aic26 *aic26 = dev_get_drvdata(&spi->dev); | 501 | struct aic26 *aic26 = dev_get_drvdata(&spi->dev); |
495 | 502 | ||
503 | snd_soc_unregister_dai(&aic26_dai); | ||
496 | kfree(aic26); | 504 | kfree(aic26); |
497 | 505 | ||
498 | return 0; | 506 | return 0; |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index cff276ee261e..b47a749c5ea2 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -253,11 +253,17 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
253 | 253 | ||
254 | SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, | 254 | SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL, |
255 | DACR1_2_RLOPM_VOL, 0, 0x7f, 1), | 255 | DACR1_2_RLOPM_VOL, 0, 0x7f, 1), |
256 | SOC_DOUBLE_R("Line DAC Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3, | 256 | SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0), |
257 | 0x01, 0), | 257 | SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0), |
258 | SOC_DOUBLE_R("Line PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, | 258 | SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL, |
259 | PGAR_2_RLOPM_VOL, 0, 0x7f, 1), | 259 | DACR1_2_LLOPM_VOL, 0, 0x7f, 1), |
260 | SOC_DOUBLE_R("Line Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, | 260 | SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL, |
261 | 0, 0x7f, 1), | ||
262 | SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL, | ||
263 | 0, 0x7f, 1), | ||
264 | SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL, | ||
265 | LINE2R_2_LLOPM_VOL, 0, 0x7f, 1), | ||
266 | SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL, | ||
261 | LINE2R_2_RLOPM_VOL, 0, 0x7f, 1), | 267 | LINE2R_2_RLOPM_VOL, 0, 0x7f, 1), |
262 | 268 | ||
263 | SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, | 269 | SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL, |
@@ -272,8 +278,12 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
272 | DACR1_2_HPROUT_VOL, 0, 0x7f, 1), | 278 | DACR1_2_HPROUT_VOL, 0, 0x7f, 1), |
273 | SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, | 279 | SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3, |
274 | 0x01, 0), | 280 | 0x01, 0), |
275 | SOC_DOUBLE_R("HP PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, | 281 | SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL, |
276 | PGAR_2_HPROUT_VOL, 0, 0x7f, 1), | 282 | PGAR_2_HPROUT_VOL, 0, 0x7f, 1), |
283 | SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL, | ||
284 | 0, 0x7f, 1), | ||
285 | SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL, | ||
286 | 0, 0x7f, 1), | ||
277 | SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, | 287 | SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL, |
278 | LINE2R_2_HPROUT_VOL, 0, 0x7f, 1), | 288 | LINE2R_2_HPROUT_VOL, 0, 0x7f, 1), |
279 | 289 | ||
@@ -281,8 +291,10 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = { | |||
281 | DACR1_2_HPRCOM_VOL, 0, 0x7f, 1), | 291 | DACR1_2_HPRCOM_VOL, 0, 0x7f, 1), |
282 | SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, | 292 | SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3, |
283 | 0x01, 0), | 293 | 0x01, 0), |
284 | SOC_DOUBLE_R("HPCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, | 294 | SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL, |
285 | PGAR_2_HPRCOM_VOL, 0, 0x7f, 1), | 295 | 0, 0x7f, 1), |
296 | SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL, | ||
297 | 0, 0x7f, 1), | ||
286 | SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, | 298 | SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL, |
287 | LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1), | 299 | LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1), |
288 | 300 | ||
@@ -333,7 +345,8 @@ SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]); | |||
333 | 345 | ||
334 | /* Left DAC_L1 Mixer */ | 346 | /* Left DAC_L1 Mixer */ |
335 | static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { | 347 | static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { |
336 | SOC_DAPM_SINGLE("Line Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), | 348 | SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0), |
349 | SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0), | ||
337 | SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), | 350 | SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0), |
338 | SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), | 351 | SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0), |
339 | SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), | 352 | SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0), |
@@ -341,7 +354,8 @@ static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = { | |||
341 | 354 | ||
342 | /* Right DAC_R1 Mixer */ | 355 | /* Right DAC_R1 Mixer */ |
343 | static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { | 356 | static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { |
344 | SOC_DAPM_SINGLE("Line Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), | 357 | SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0), |
358 | SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0), | ||
345 | SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), | 359 | SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0), |
346 | SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), | 360 | SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0), |
347 | SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), | 361 | SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0), |
@@ -350,14 +364,18 @@ static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = { | |||
350 | /* Left PGA Mixer */ | 364 | /* Left PGA Mixer */ |
351 | static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = { | 365 | static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = { |
352 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1), | 366 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1), |
367 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1), | ||
353 | SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1), | 368 | SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1), |
354 | SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1), | 369 | SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1), |
370 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1), | ||
355 | }; | 371 | }; |
356 | 372 | ||
357 | /* Right PGA Mixer */ | 373 | /* Right PGA Mixer */ |
358 | static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { | 374 | static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = { |
359 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1), | 375 | SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1), |
376 | SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1), | ||
360 | SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1), | 377 | SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1), |
378 | SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1), | ||
361 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), | 379 | SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1), |
362 | }; | 380 | }; |
363 | 381 | ||
@@ -379,34 +397,42 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]); | |||
379 | 397 | ||
380 | /* Left PGA Bypass Mixer */ | 398 | /* Left PGA Bypass Mixer */ |
381 | static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = { | 399 | static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = { |
382 | SOC_DAPM_SINGLE("Line Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), | 400 | SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0), |
401 | SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0), | ||
383 | SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), | 402 | SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0), |
384 | SOC_DAPM_SINGLE("HP Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), | 403 | SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0), |
385 | SOC_DAPM_SINGLE("HPCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), | 404 | SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0), |
405 | SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0), | ||
406 | SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0), | ||
386 | }; | 407 | }; |
387 | 408 | ||
388 | /* Right PGA Bypass Mixer */ | 409 | /* Right PGA Bypass Mixer */ |
389 | static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = { | 410 | static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = { |
390 | SOC_DAPM_SINGLE("Line Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), | 411 | SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0), |
412 | SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0), | ||
391 | SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), | 413 | SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0), |
392 | SOC_DAPM_SINGLE("HP Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), | 414 | SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0), |
393 | SOC_DAPM_SINGLE("HPCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), | 415 | SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0), |
416 | SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0), | ||
417 | SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0), | ||
394 | }; | 418 | }; |
395 | 419 | ||
396 | /* Left Line2 Bypass Mixer */ | 420 | /* Left Line2 Bypass Mixer */ |
397 | static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = { | 421 | static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = { |
398 | SOC_DAPM_SINGLE("Line Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), | 422 | SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0), |
423 | SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0), | ||
399 | SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), | 424 | SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0), |
400 | SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), | 425 | SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0), |
401 | SOC_DAPM_SINGLE("HPCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), | 426 | SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0), |
402 | }; | 427 | }; |
403 | 428 | ||
404 | /* Right Line2 Bypass Mixer */ | 429 | /* Right Line2 Bypass Mixer */ |
405 | static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = { | 430 | static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = { |
406 | SOC_DAPM_SINGLE("Line Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), | 431 | SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0), |
432 | SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0), | ||
407 | SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), | 433 | SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0), |
408 | SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), | 434 | SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0), |
409 | SOC_DAPM_SINGLE("HPCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), | 435 | SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0), |
410 | }; | 436 | }; |
411 | 437 | ||
412 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | 438 | static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { |
@@ -439,22 +465,26 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = { | |||
439 | /* Mono Output */ | 465 | /* Mono Output */ |
440 | SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), | 466 | SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0), |
441 | 467 | ||
442 | /* Left Inputs to Left ADC */ | 468 | /* Inputs to Left ADC */ |
443 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), | 469 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0), |
444 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, | 470 | SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0, |
445 | &aic3x_left_pga_mixer_controls[0], | 471 | &aic3x_left_pga_mixer_controls[0], |
446 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), | 472 | ARRAY_SIZE(aic3x_left_pga_mixer_controls)), |
447 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, | 473 | SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0, |
448 | &aic3x_left_line1_mux_controls), | 474 | &aic3x_left_line1_mux_controls), |
475 | SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0, | ||
476 | &aic3x_left_line1_mux_controls), | ||
449 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, | 477 | SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0, |
450 | &aic3x_left_line2_mux_controls), | 478 | &aic3x_left_line2_mux_controls), |
451 | 479 | ||
452 | /* Right Inputs to Right ADC */ | 480 | /* Inputs to Right ADC */ |
453 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", | 481 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", |
454 | LINE1R_2_RADC_CTRL, 2, 0), | 482 | LINE1R_2_RADC_CTRL, 2, 0), |
455 | SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, | 483 | SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0, |
456 | &aic3x_right_pga_mixer_controls[0], | 484 | &aic3x_right_pga_mixer_controls[0], |
457 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), | 485 | ARRAY_SIZE(aic3x_right_pga_mixer_controls)), |
486 | SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0, | ||
487 | &aic3x_right_line1_mux_controls), | ||
458 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, | 488 | SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0, |
459 | &aic3x_right_line1_mux_controls), | 489 | &aic3x_right_line1_mux_controls), |
460 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, | 490 | SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0, |
@@ -531,7 +561,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
531 | {"Left DAC Mux", "DAC_L2", "Left DAC"}, | 561 | {"Left DAC Mux", "DAC_L2", "Left DAC"}, |
532 | {"Left DAC Mux", "DAC_L3", "Left DAC"}, | 562 | {"Left DAC Mux", "DAC_L3", "Left DAC"}, |
533 | 563 | ||
534 | {"Left DAC_L1 Mixer", "Line Switch", "Left DAC Mux"}, | 564 | {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"}, |
565 | {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"}, | ||
535 | {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"}, | 566 | {"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"}, |
536 | {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"}, | 567 | {"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"}, |
537 | {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"}, | 568 | {"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"}, |
@@ -557,7 +588,8 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
557 | {"Right DAC Mux", "DAC_R2", "Right DAC"}, | 588 | {"Right DAC Mux", "DAC_R2", "Right DAC"}, |
558 | {"Right DAC Mux", "DAC_R3", "Right DAC"}, | 589 | {"Right DAC Mux", "DAC_R3", "Right DAC"}, |
559 | 590 | ||
560 | {"Right DAC_R1 Mixer", "Line Switch", "Right DAC Mux"}, | 591 | {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"}, |
592 | {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"}, | ||
561 | {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"}, | 593 | {"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"}, |
562 | {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"}, | 594 | {"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"}, |
563 | {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"}, | 595 | {"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"}, |
@@ -592,8 +624,10 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
592 | {"Left Line2L Mux", "differential", "LINE2L"}, | 624 | {"Left Line2L Mux", "differential", "LINE2L"}, |
593 | 625 | ||
594 | {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, | 626 | {"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"}, |
627 | {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"}, | ||
595 | {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, | 628 | {"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"}, |
596 | {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, | 629 | {"Left PGA Mixer", "Mic3L Switch", "MIC3L"}, |
630 | {"Left PGA Mixer", "Mic3R Switch", "MIC3R"}, | ||
597 | 631 | ||
598 | {"Left ADC", NULL, "Left PGA Mixer"}, | 632 | {"Left ADC", NULL, "Left PGA Mixer"}, |
599 | {"Left ADC", NULL, "GPIO1 dmic modclk"}, | 633 | {"Left ADC", NULL, "GPIO1 dmic modclk"}, |
@@ -605,18 +639,23 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
605 | {"Right Line2R Mux", "single-ended", "LINE2R"}, | 639 | {"Right Line2R Mux", "single-ended", "LINE2R"}, |
606 | {"Right Line2R Mux", "differential", "LINE2R"}, | 640 | {"Right Line2R Mux", "differential", "LINE2R"}, |
607 | 641 | ||
642 | {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"}, | ||
608 | {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, | 643 | {"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"}, |
609 | {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, | 644 | {"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"}, |
645 | {"Right PGA Mixer", "Mic3L Switch", "MIC3L"}, | ||
610 | {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, | 646 | {"Right PGA Mixer", "Mic3R Switch", "MIC3R"}, |
611 | 647 | ||
612 | {"Right ADC", NULL, "Right PGA Mixer"}, | 648 | {"Right ADC", NULL, "Right PGA Mixer"}, |
613 | {"Right ADC", NULL, "GPIO1 dmic modclk"}, | 649 | {"Right ADC", NULL, "GPIO1 dmic modclk"}, |
614 | 650 | ||
615 | /* Left PGA Bypass */ | 651 | /* Left PGA Bypass */ |
616 | {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"}, | 652 | {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"}, |
653 | {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"}, | ||
617 | {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"}, | 654 | {"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"}, |
618 | {"Left PGA Bypass Mixer", "HP Switch", "Left PGA Mixer"}, | 655 | {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"}, |
619 | {"Left PGA Bypass Mixer", "HPCOM Switch", "Left PGA Mixer"}, | 656 | {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"}, |
657 | {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"}, | ||
658 | {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"}, | ||
620 | 659 | ||
621 | {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"}, | 660 | {"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"}, |
622 | {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"}, | 661 | {"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"}, |
@@ -627,10 +666,13 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
627 | {"Left HP Out", NULL, "Left PGA Bypass Mixer"}, | 666 | {"Left HP Out", NULL, "Left PGA Bypass Mixer"}, |
628 | 667 | ||
629 | /* Right PGA Bypass */ | 668 | /* Right PGA Bypass */ |
630 | {"Right PGA Bypass Mixer", "Line Switch", "Right PGA Mixer"}, | 669 | {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"}, |
670 | {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"}, | ||
631 | {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"}, | 671 | {"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"}, |
632 | {"Right PGA Bypass Mixer", "HP Switch", "Right PGA Mixer"}, | 672 | {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"}, |
633 | {"Right PGA Bypass Mixer", "HPCOM Switch", "Right PGA Mixer"}, | 673 | {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"}, |
674 | {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"}, | ||
675 | {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"}, | ||
634 | 676 | ||
635 | {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"}, | 677 | {"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"}, |
636 | {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"}, | 678 | {"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"}, |
@@ -643,10 +685,11 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
643 | {"Right HP Out", NULL, "Right PGA Bypass Mixer"}, | 685 | {"Right HP Out", NULL, "Right PGA Bypass Mixer"}, |
644 | 686 | ||
645 | /* Left Line2 Bypass */ | 687 | /* Left Line2 Bypass */ |
646 | {"Left Line2 Bypass Mixer", "Line Switch", "Left Line2L Mux"}, | 688 | {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"}, |
689 | {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"}, | ||
647 | {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"}, | 690 | {"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"}, |
648 | {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"}, | 691 | {"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"}, |
649 | {"Left Line2 Bypass Mixer", "HPCOM Switch", "Left Line2L Mux"}, | 692 | {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"}, |
650 | 693 | ||
651 | {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"}, | 694 | {"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"}, |
652 | {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"}, | 695 | {"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"}, |
@@ -657,10 +700,11 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
657 | {"Left HP Out", NULL, "Left Line2 Bypass Mixer"}, | 700 | {"Left HP Out", NULL, "Left Line2 Bypass Mixer"}, |
658 | 701 | ||
659 | /* Right Line2 Bypass */ | 702 | /* Right Line2 Bypass */ |
660 | {"Right Line2 Bypass Mixer", "Line Switch", "Right Line2R Mux"}, | 703 | {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"}, |
704 | {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"}, | ||
661 | {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"}, | 705 | {"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"}, |
662 | {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"}, | 706 | {"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"}, |
663 | {"Right Line2 Bypass Mixer", "HPCOM Switch", "Right Line2R Mux"}, | 707 | {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"}, |
664 | 708 | ||
665 | {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"}, | 709 | {"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"}, |
666 | {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"}, | 710 | {"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"}, |
@@ -694,7 +738,8 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec) | |||
694 | } | 738 | } |
695 | 739 | ||
696 | static int aic3x_hw_params(struct snd_pcm_substream *substream, | 740 | static int aic3x_hw_params(struct snd_pcm_substream *substream, |
697 | struct snd_pcm_hw_params *params) | 741 | struct snd_pcm_hw_params *params, |
742 | struct snd_soc_dai *dai) | ||
698 | { | 743 | { |
699 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 744 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
700 | struct snd_soc_device *socdev = rtd->socdev; | 745 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -846,6 +891,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
846 | struct snd_soc_codec *codec = codec_dai->codec; | 891 | struct snd_soc_codec *codec = codec_dai->codec; |
847 | struct aic3x_priv *aic3x = codec->private_data; | 892 | struct aic3x_priv *aic3x = codec->private_data; |
848 | u8 iface_areg, iface_breg; | 893 | u8 iface_areg, iface_breg; |
894 | int delay = 0; | ||
849 | 895 | ||
850 | iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; | 896 | iface_areg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLA) & 0x3f; |
851 | iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; | 897 | iface_breg = aic3x_read_reg_cache(codec, AIC3X_ASD_INTF_CTRLB) & 0x3f; |
@@ -871,6 +917,8 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
871 | SND_SOC_DAIFMT_INV_MASK)) { | 917 | SND_SOC_DAIFMT_INV_MASK)) { |
872 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): | 918 | case (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF): |
873 | break; | 919 | break; |
920 | case (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF): | ||
921 | delay = 1; | ||
874 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): | 922 | case (SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_IB_NF): |
875 | iface_breg |= (0x01 << 6); | 923 | iface_breg |= (0x01 << 6); |
876 | break; | 924 | break; |
@@ -887,6 +935,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
887 | /* set iface */ | 935 | /* set iface */ |
888 | aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); | 936 | aic3x_write(codec, AIC3X_ASD_INTF_CTRLA, iface_areg); |
889 | aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); | 937 | aic3x_write(codec, AIC3X_ASD_INTF_CTRLB, iface_breg); |
938 | aic3x_write(codec, AIC3X_ASD_INTF_CTRLC, delay); | ||
890 | 939 | ||
891 | return 0; | 940 | return 0; |
892 | } | 941 | } |
@@ -981,14 +1030,41 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio) | |||
981 | } | 1030 | } |
982 | EXPORT_SYMBOL_GPL(aic3x_get_gpio); | 1031 | EXPORT_SYMBOL_GPL(aic3x_get_gpio); |
983 | 1032 | ||
1033 | void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, | ||
1034 | int headset_debounce, int button_debounce) | ||
1035 | { | ||
1036 | u8 val; | ||
1037 | |||
1038 | val = ((detect & AIC3X_HEADSET_DETECT_MASK) | ||
1039 | << AIC3X_HEADSET_DETECT_SHIFT) | | ||
1040 | ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK) | ||
1041 | << AIC3X_HEADSET_DEBOUNCE_SHIFT) | | ||
1042 | ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK) | ||
1043 | << AIC3X_BUTTON_DEBOUNCE_SHIFT); | ||
1044 | |||
1045 | if (detect & AIC3X_HEADSET_DETECT_MASK) | ||
1046 | val |= AIC3X_HEADSET_DETECT_ENABLED; | ||
1047 | |||
1048 | aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val); | ||
1049 | } | ||
1050 | EXPORT_SYMBOL_GPL(aic3x_set_headset_detection); | ||
1051 | |||
984 | int aic3x_headset_detected(struct snd_soc_codec *codec) | 1052 | int aic3x_headset_detected(struct snd_soc_codec *codec) |
985 | { | 1053 | { |
986 | u8 val; | 1054 | u8 val; |
987 | aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val); | 1055 | aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val); |
988 | return (val >> 2) & 1; | 1056 | return (val >> 4) & 1; |
989 | } | 1057 | } |
990 | EXPORT_SYMBOL_GPL(aic3x_headset_detected); | 1058 | EXPORT_SYMBOL_GPL(aic3x_headset_detected); |
991 | 1059 | ||
1060 | int aic3x_button_pressed(struct snd_soc_codec *codec) | ||
1061 | { | ||
1062 | u8 val; | ||
1063 | aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val); | ||
1064 | return (val >> 5) & 1; | ||
1065 | } | ||
1066 | EXPORT_SYMBOL_GPL(aic3x_button_pressed); | ||
1067 | |||
992 | #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 | 1068 | #define AIC3X_RATES SNDRV_PCM_RATE_8000_96000 |
993 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | 1069 | #define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ |
994 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) | 1070 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) |
@@ -1009,8 +1085,6 @@ struct snd_soc_dai aic3x_dai = { | |||
1009 | .formats = AIC3X_FORMATS,}, | 1085 | .formats = AIC3X_FORMATS,}, |
1010 | .ops = { | 1086 | .ops = { |
1011 | .hw_params = aic3x_hw_params, | 1087 | .hw_params = aic3x_hw_params, |
1012 | }, | ||
1013 | .dai_ops = { | ||
1014 | .digital_mute = aic3x_mute, | 1088 | .digital_mute = aic3x_mute, |
1015 | .set_sysclk = aic3x_set_dai_sysclk, | 1089 | .set_sysclk = aic3x_set_dai_sysclk, |
1016 | .set_fmt = aic3x_set_dai_fmt, | 1090 | .set_fmt = aic3x_set_dai_fmt, |
@@ -1152,7 +1226,7 @@ static int aic3x_init(struct snd_soc_device *socdev) | |||
1152 | 1226 | ||
1153 | aic3x_add_controls(codec); | 1227 | aic3x_add_controls(codec); |
1154 | aic3x_add_widgets(codec); | 1228 | aic3x_add_widgets(codec); |
1155 | ret = snd_soc_register_card(socdev); | 1229 | ret = snd_soc_init_card(socdev); |
1156 | if (ret < 0) { | 1230 | if (ret < 0) { |
1157 | printk(KERN_ERR "aic3x: failed to register card\n"); | 1231 | printk(KERN_ERR "aic3x: failed to register card\n"); |
1158 | goto card_err; | 1232 | goto card_err; |
@@ -1341,6 +1415,18 @@ struct snd_soc_codec_device soc_codec_dev_aic3x = { | |||
1341 | }; | 1415 | }; |
1342 | EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); | 1416 | EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x); |
1343 | 1417 | ||
1418 | static int __init aic3x_modinit(void) | ||
1419 | { | ||
1420 | return snd_soc_register_dai(&aic3x_dai); | ||
1421 | } | ||
1422 | module_init(aic3x_modinit); | ||
1423 | |||
1424 | static void __exit aic3x_exit(void) | ||
1425 | { | ||
1426 | snd_soc_unregister_dai(&aic3x_dai); | ||
1427 | } | ||
1428 | module_exit(aic3x_exit); | ||
1429 | |||
1344 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); | 1430 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); |
1345 | MODULE_AUTHOR("Vladimir Barinov"); | 1431 | MODULE_AUTHOR("Vladimir Barinov"); |
1346 | MODULE_LICENSE("GPL"); | 1432 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 00a195aa02e4..ac827e578c4d 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h | |||
@@ -35,11 +35,15 @@ | |||
35 | #define AIC3X_ASD_INTF_CTRLA 8 | 35 | #define AIC3X_ASD_INTF_CTRLA 8 |
36 | /* Audio serial data interface control register B */ | 36 | /* Audio serial data interface control register B */ |
37 | #define AIC3X_ASD_INTF_CTRLB 9 | 37 | #define AIC3X_ASD_INTF_CTRLB 9 |
38 | /* Audio serial data interface control register C */ | ||
39 | #define AIC3X_ASD_INTF_CTRLC 10 | ||
38 | /* Audio overflow status and PLL R value programming register */ | 40 | /* Audio overflow status and PLL R value programming register */ |
39 | #define AIC3X_OVRF_STATUS_AND_PLLR_REG 11 | 41 | #define AIC3X_OVRF_STATUS_AND_PLLR_REG 11 |
40 | /* Audio codec digital filter control register */ | 42 | /* Audio codec digital filter control register */ |
41 | #define AIC3X_CODEC_DFILT_CTRL 12 | 43 | #define AIC3X_CODEC_DFILT_CTRL 12 |
42 | 44 | /* Headset/button press detection register */ | |
45 | #define AIC3X_HEADSET_DETECT_CTRL_A 13 | ||
46 | #define AIC3X_HEADSET_DETECT_CTRL_B 14 | ||
43 | /* ADC PGA Gain control registers */ | 47 | /* ADC PGA Gain control registers */ |
44 | #define LADC_VOL 15 | 48 | #define LADC_VOL 15 |
45 | #define RADC_VOL 16 | 49 | #define RADC_VOL 16 |
@@ -48,7 +52,9 @@ | |||
48 | #define MIC3LR_2_RADC_CTRL 18 | 52 | #define MIC3LR_2_RADC_CTRL 18 |
49 | /* Line1 Input control registers */ | 53 | /* Line1 Input control registers */ |
50 | #define LINE1L_2_LADC_CTRL 19 | 54 | #define LINE1L_2_LADC_CTRL 19 |
55 | #define LINE1R_2_LADC_CTRL 21 | ||
51 | #define LINE1R_2_RADC_CTRL 22 | 56 | #define LINE1R_2_RADC_CTRL 22 |
57 | #define LINE1L_2_RADC_CTRL 24 | ||
52 | /* Line2 Input control registers */ | 58 | /* Line2 Input control registers */ |
53 | #define LINE2L_2_LADC_CTRL 20 | 59 | #define LINE2L_2_LADC_CTRL 20 |
54 | #define LINE2R_2_RADC_CTRL 23 | 60 | #define LINE2R_2_RADC_CTRL 23 |
@@ -79,6 +85,8 @@ | |||
79 | #define LINE2L_2_HPLOUT_VOL 45 | 85 | #define LINE2L_2_HPLOUT_VOL 45 |
80 | #define LINE2R_2_HPROUT_VOL 62 | 86 | #define LINE2R_2_HPROUT_VOL 62 |
81 | #define PGAL_2_HPLOUT_VOL 46 | 87 | #define PGAL_2_HPLOUT_VOL 46 |
88 | #define PGAL_2_HPROUT_VOL 60 | ||
89 | #define PGAR_2_HPLOUT_VOL 49 | ||
82 | #define PGAR_2_HPROUT_VOL 63 | 90 | #define PGAR_2_HPROUT_VOL 63 |
83 | #define DACL1_2_HPLOUT_VOL 47 | 91 | #define DACL1_2_HPLOUT_VOL 47 |
84 | #define DACR1_2_HPROUT_VOL 64 | 92 | #define DACR1_2_HPROUT_VOL 64 |
@@ -88,6 +96,8 @@ | |||
88 | #define LINE2L_2_HPLCOM_VOL 52 | 96 | #define LINE2L_2_HPLCOM_VOL 52 |
89 | #define LINE2R_2_HPRCOM_VOL 69 | 97 | #define LINE2R_2_HPRCOM_VOL 69 |
90 | #define PGAL_2_HPLCOM_VOL 53 | 98 | #define PGAL_2_HPLCOM_VOL 53 |
99 | #define PGAR_2_HPLCOM_VOL 56 | ||
100 | #define PGAL_2_HPRCOM_VOL 67 | ||
91 | #define PGAR_2_HPRCOM_VOL 70 | 101 | #define PGAR_2_HPRCOM_VOL 70 |
92 | #define DACL1_2_HPLCOM_VOL 54 | 102 | #define DACL1_2_HPLCOM_VOL 54 |
93 | #define DACR1_2_HPRCOM_VOL 71 | 103 | #define DACR1_2_HPRCOM_VOL 71 |
@@ -103,11 +113,17 @@ | |||
103 | #define MONOLOPM_CTRL 79 | 113 | #define MONOLOPM_CTRL 79 |
104 | /* Line Output Plus/Minus control registers */ | 114 | /* Line Output Plus/Minus control registers */ |
105 | #define LINE2L_2_LLOPM_VOL 80 | 115 | #define LINE2L_2_LLOPM_VOL 80 |
116 | #define LINE2L_2_RLOPM_VOL 87 | ||
117 | #define LINE2R_2_LLOPM_VOL 83 | ||
106 | #define LINE2R_2_RLOPM_VOL 90 | 118 | #define LINE2R_2_RLOPM_VOL 90 |
107 | #define PGAL_2_LLOPM_VOL 81 | 119 | #define PGAL_2_LLOPM_VOL 81 |
120 | #define PGAL_2_RLOPM_VOL 88 | ||
121 | #define PGAR_2_LLOPM_VOL 84 | ||
108 | #define PGAR_2_RLOPM_VOL 91 | 122 | #define PGAR_2_RLOPM_VOL 91 |
109 | #define DACL1_2_LLOPM_VOL 82 | 123 | #define DACL1_2_LLOPM_VOL 82 |
124 | #define DACL1_2_RLOPM_VOL 89 | ||
110 | #define DACR1_2_RLOPM_VOL 92 | 125 | #define DACR1_2_RLOPM_VOL 92 |
126 | #define DACR1_2_LLOPM_VOL 85 | ||
111 | #define LLOPM_CTRL 86 | 127 | #define LLOPM_CTRL 86 |
112 | #define RLOPM_CTRL 93 | 128 | #define RLOPM_CTRL 93 |
113 | /* GPIO/IRQ registers */ | 129 | /* GPIO/IRQ registers */ |
@@ -221,7 +237,49 @@ enum { | |||
221 | 237 | ||
222 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); | 238 | void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state); |
223 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); | 239 | int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio); |
240 | |||
241 | /* headset detection / button API */ | ||
242 | |||
243 | /* The AIC3x supports detection of stereo headsets (GND + left + right signal) | ||
244 | * and cellular headsets (GND + speaker output + microphone input). | ||
245 | * It is recommended to enable MIC bias for this function to work properly. | ||
246 | * For more information, please refer to the datasheet. */ | ||
247 | enum { | ||
248 | AIC3X_HEADSET_DETECT_OFF = 0, | ||
249 | AIC3X_HEADSET_DETECT_STEREO = 1, | ||
250 | AIC3X_HEADSET_DETECT_CELLULAR = 2, | ||
251 | AIC3X_HEADSET_DETECT_BOTH = 3 | ||
252 | }; | ||
253 | |||
254 | enum { | ||
255 | AIC3X_HEADSET_DEBOUNCE_16MS = 0, | ||
256 | AIC3X_HEADSET_DEBOUNCE_32MS = 1, | ||
257 | AIC3X_HEADSET_DEBOUNCE_64MS = 2, | ||
258 | AIC3X_HEADSET_DEBOUNCE_128MS = 3, | ||
259 | AIC3X_HEADSET_DEBOUNCE_256MS = 4, | ||
260 | AIC3X_HEADSET_DEBOUNCE_512MS = 5 | ||
261 | }; | ||
262 | |||
263 | enum { | ||
264 | AIC3X_BUTTON_DEBOUNCE_0MS = 0, | ||
265 | AIC3X_BUTTON_DEBOUNCE_8MS = 1, | ||
266 | AIC3X_BUTTON_DEBOUNCE_16MS = 2, | ||
267 | AIC3X_BUTTON_DEBOUNCE_32MS = 3 | ||
268 | }; | ||
269 | |||
270 | #define AIC3X_HEADSET_DETECT_ENABLED 0x80 | ||
271 | #define AIC3X_HEADSET_DETECT_SHIFT 5 | ||
272 | #define AIC3X_HEADSET_DETECT_MASK 3 | ||
273 | #define AIC3X_HEADSET_DEBOUNCE_SHIFT 2 | ||
274 | #define AIC3X_HEADSET_DEBOUNCE_MASK 7 | ||
275 | #define AIC3X_BUTTON_DEBOUNCE_SHIFT 0 | ||
276 | #define AIC3X_BUTTON_DEBOUNCE_MASK 3 | ||
277 | |||
278 | /* see the enums above for valid parameters to this function */ | ||
279 | void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect, | ||
280 | int headset_debounce, int button_debounce); | ||
224 | int aic3x_headset_detected(struct snd_soc_codec *codec); | 281 | int aic3x_headset_detected(struct snd_soc_codec *codec); |
282 | int aic3x_button_pressed(struct snd_soc_codec *codec); | ||
225 | 283 | ||
226 | struct aic3x_setup_data { | 284 | struct aic3x_setup_data { |
227 | int i2c_bus; | 285 | int i2c_bus; |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c new file mode 100644 index 000000000000..51848880504a --- /dev/null +++ b/sound/soc/codecs/twl4030.c | |||
@@ -0,0 +1,1317 @@ | |||
1 | /* | ||
2 | * ALSA SoC TWL4030 codec driver | ||
3 | * | ||
4 | * Author: Steve Sakoman, <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/module.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/pm.h> | ||
27 | #include <linux/i2c.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <linux/i2c/twl4030.h> | ||
30 | #include <sound/core.h> | ||
31 | #include <sound/pcm.h> | ||
32 | #include <sound/pcm_params.h> | ||
33 | #include <sound/soc.h> | ||
34 | #include <sound/soc-dapm.h> | ||
35 | #include <sound/initval.h> | ||
36 | #include <sound/tlv.h> | ||
37 | |||
38 | #include "twl4030.h" | ||
39 | |||
40 | /* | ||
41 | * twl4030 register cache & default register settings | ||
42 | */ | ||
43 | static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = { | ||
44 | 0x00, /* this register not used */ | ||
45 | 0x93, /* REG_CODEC_MODE (0x1) */ | ||
46 | 0xc3, /* REG_OPTION (0x2) */ | ||
47 | 0x00, /* REG_UNKNOWN (0x3) */ | ||
48 | 0x00, /* REG_MICBIAS_CTL (0x4) */ | ||
49 | 0x20, /* REG_ANAMICL (0x5) */ | ||
50 | 0x00, /* REG_ANAMICR (0x6) */ | ||
51 | 0x00, /* REG_AVADC_CTL (0x7) */ | ||
52 | 0x00, /* REG_ADCMICSEL (0x8) */ | ||
53 | 0x00, /* REG_DIGMIXING (0x9) */ | ||
54 | 0x0c, /* REG_ATXL1PGA (0xA) */ | ||
55 | 0x0c, /* REG_ATXR1PGA (0xB) */ | ||
56 | 0x00, /* REG_AVTXL2PGA (0xC) */ | ||
57 | 0x00, /* REG_AVTXR2PGA (0xD) */ | ||
58 | 0x01, /* REG_AUDIO_IF (0xE) */ | ||
59 | 0x00, /* REG_VOICE_IF (0xF) */ | ||
60 | 0x00, /* REG_ARXR1PGA (0x10) */ | ||
61 | 0x00, /* REG_ARXL1PGA (0x11) */ | ||
62 | 0x6c, /* REG_ARXR2PGA (0x12) */ | ||
63 | 0x6c, /* REG_ARXL2PGA (0x13) */ | ||
64 | 0x00, /* REG_VRXPGA (0x14) */ | ||
65 | 0x00, /* REG_VSTPGA (0x15) */ | ||
66 | 0x00, /* REG_VRX2ARXPGA (0x16) */ | ||
67 | 0x0c, /* REG_AVDAC_CTL (0x17) */ | ||
68 | 0x00, /* REG_ARX2VTXPGA (0x18) */ | ||
69 | 0x00, /* REG_ARXL1_APGA_CTL (0x19) */ | ||
70 | 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */ | ||
71 | 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */ | ||
72 | 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */ | ||
73 | 0x00, /* REG_ATX2ARXPGA (0x1D) */ | ||
74 | 0x00, /* REG_BT_IF (0x1E) */ | ||
75 | 0x00, /* REG_BTPGA (0x1F) */ | ||
76 | 0x00, /* REG_BTSTPGA (0x20) */ | ||
77 | 0x00, /* REG_EAR_CTL (0x21) */ | ||
78 | 0x24, /* REG_HS_SEL (0x22) */ | ||
79 | 0x0a, /* REG_HS_GAIN_SET (0x23) */ | ||
80 | 0x00, /* REG_HS_POPN_SET (0x24) */ | ||
81 | 0x00, /* REG_PREDL_CTL (0x25) */ | ||
82 | 0x00, /* REG_PREDR_CTL (0x26) */ | ||
83 | 0x00, /* REG_PRECKL_CTL (0x27) */ | ||
84 | 0x00, /* REG_PRECKR_CTL (0x28) */ | ||
85 | 0x00, /* REG_HFL_CTL (0x29) */ | ||
86 | 0x00, /* REG_HFR_CTL (0x2A) */ | ||
87 | 0x00, /* REG_ALC_CTL (0x2B) */ | ||
88 | 0x00, /* REG_ALC_SET1 (0x2C) */ | ||
89 | 0x00, /* REG_ALC_SET2 (0x2D) */ | ||
90 | 0x00, /* REG_BOOST_CTL (0x2E) */ | ||
91 | 0x00, /* REG_SOFTVOL_CTL (0x2F) */ | ||
92 | 0x00, /* REG_DTMF_FREQSEL (0x30) */ | ||
93 | 0x00, /* REG_DTMF_TONEXT1H (0x31) */ | ||
94 | 0x00, /* REG_DTMF_TONEXT1L (0x32) */ | ||
95 | 0x00, /* REG_DTMF_TONEXT2H (0x33) */ | ||
96 | 0x00, /* REG_DTMF_TONEXT2L (0x34) */ | ||
97 | 0x00, /* REG_DTMF_TONOFF (0x35) */ | ||
98 | 0x00, /* REG_DTMF_WANONOFF (0x36) */ | ||
99 | 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */ | ||
100 | 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */ | ||
101 | 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */ | ||
102 | 0x16, /* REG_APLL_CTL (0x3A) */ | ||
103 | 0x00, /* REG_DTMF_CTL (0x3B) */ | ||
104 | 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */ | ||
105 | 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */ | ||
106 | 0x00, /* REG_MISC_SET_1 (0x3E) */ | ||
107 | 0x00, /* REG_PCMBTMUX (0x3F) */ | ||
108 | 0x00, /* not used (0x40) */ | ||
109 | 0x00, /* not used (0x41) */ | ||
110 | 0x00, /* not used (0x42) */ | ||
111 | 0x00, /* REG_RX_PATH_SEL (0x43) */ | ||
112 | 0x00, /* REG_VDL_APGA_CTL (0x44) */ | ||
113 | 0x00, /* REG_VIBRA_CTL (0x45) */ | ||
114 | 0x00, /* REG_VIBRA_SET (0x46) */ | ||
115 | 0x00, /* REG_VIBRA_PWM_SET (0x47) */ | ||
116 | 0x00, /* REG_ANAMIC_GAIN (0x48) */ | ||
117 | 0x00, /* REG_MISC_SET_2 (0x49) */ | ||
118 | }; | ||
119 | |||
120 | /* | ||
121 | * read twl4030 register cache | ||
122 | */ | ||
123 | static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec, | ||
124 | unsigned int reg) | ||
125 | { | ||
126 | u8 *cache = codec->reg_cache; | ||
127 | |||
128 | return cache[reg]; | ||
129 | } | ||
130 | |||
131 | /* | ||
132 | * write twl4030 register cache | ||
133 | */ | ||
134 | static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec, | ||
135 | u8 reg, u8 value) | ||
136 | { | ||
137 | u8 *cache = codec->reg_cache; | ||
138 | |||
139 | if (reg >= TWL4030_CACHEREGNUM) | ||
140 | return; | ||
141 | cache[reg] = value; | ||
142 | } | ||
143 | |||
144 | /* | ||
145 | * write to the twl4030 register space | ||
146 | */ | ||
147 | static int twl4030_write(struct snd_soc_codec *codec, | ||
148 | unsigned int reg, unsigned int value) | ||
149 | { | ||
150 | twl4030_write_reg_cache(codec, reg, value); | ||
151 | return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg); | ||
152 | } | ||
153 | |||
154 | static void twl4030_clear_codecpdz(struct snd_soc_codec *codec) | ||
155 | { | ||
156 | u8 mode; | ||
157 | |||
158 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | ||
159 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, | ||
160 | mode & ~TWL4030_CODECPDZ); | ||
161 | |||
162 | /* REVISIT: this delay is present in TI sample drivers */ | ||
163 | /* but there seems to be no TRM requirement for it */ | ||
164 | udelay(10); | ||
165 | } | ||
166 | |||
167 | static void twl4030_set_codecpdz(struct snd_soc_codec *codec) | ||
168 | { | ||
169 | u8 mode; | ||
170 | |||
171 | mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE); | ||
172 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, | ||
173 | mode | TWL4030_CODECPDZ); | ||
174 | |||
175 | /* REVISIT: this delay is present in TI sample drivers */ | ||
176 | /* but there seems to be no TRM requirement for it */ | ||
177 | udelay(10); | ||
178 | } | ||
179 | |||
180 | static void twl4030_init_chip(struct snd_soc_codec *codec) | ||
181 | { | ||
182 | int i; | ||
183 | |||
184 | /* clear CODECPDZ prior to setting register defaults */ | ||
185 | twl4030_clear_codecpdz(codec); | ||
186 | |||
187 | /* set all audio section registers to reasonable defaults */ | ||
188 | for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) | ||
189 | twl4030_write(codec, i, twl4030_reg[i]); | ||
190 | |||
191 | } | ||
192 | |||
193 | /* Earpiece */ | ||
194 | static const char *twl4030_earpiece_texts[] = | ||
195 | {"Off", "DACL1", "DACL2", "Invalid", "DACR1"}; | ||
196 | |||
197 | static const struct soc_enum twl4030_earpiece_enum = | ||
198 | SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1, | ||
199 | ARRAY_SIZE(twl4030_earpiece_texts), | ||
200 | twl4030_earpiece_texts); | ||
201 | |||
202 | static const struct snd_kcontrol_new twl4030_dapm_earpiece_control = | ||
203 | SOC_DAPM_ENUM("Route", twl4030_earpiece_enum); | ||
204 | |||
205 | /* PreDrive Left */ | ||
206 | static const char *twl4030_predrivel_texts[] = | ||
207 | {"Off", "DACL1", "DACL2", "Invalid", "DACR2"}; | ||
208 | |||
209 | static const struct soc_enum twl4030_predrivel_enum = | ||
210 | SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1, | ||
211 | ARRAY_SIZE(twl4030_predrivel_texts), | ||
212 | twl4030_predrivel_texts); | ||
213 | |||
214 | static const struct snd_kcontrol_new twl4030_dapm_predrivel_control = | ||
215 | SOC_DAPM_ENUM("Route", twl4030_predrivel_enum); | ||
216 | |||
217 | /* PreDrive Right */ | ||
218 | static const char *twl4030_predriver_texts[] = | ||
219 | {"Off", "DACR1", "DACR2", "Invalid", "DACL2"}; | ||
220 | |||
221 | static const struct soc_enum twl4030_predriver_enum = | ||
222 | SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1, | ||
223 | ARRAY_SIZE(twl4030_predriver_texts), | ||
224 | twl4030_predriver_texts); | ||
225 | |||
226 | static const struct snd_kcontrol_new twl4030_dapm_predriver_control = | ||
227 | SOC_DAPM_ENUM("Route", twl4030_predriver_enum); | ||
228 | |||
229 | /* Headset Left */ | ||
230 | static const char *twl4030_hsol_texts[] = | ||
231 | {"Off", "DACL1", "DACL2"}; | ||
232 | |||
233 | static const struct soc_enum twl4030_hsol_enum = | ||
234 | SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1, | ||
235 | ARRAY_SIZE(twl4030_hsol_texts), | ||
236 | twl4030_hsol_texts); | ||
237 | |||
238 | static const struct snd_kcontrol_new twl4030_dapm_hsol_control = | ||
239 | SOC_DAPM_ENUM("Route", twl4030_hsol_enum); | ||
240 | |||
241 | /* Headset Right */ | ||
242 | static const char *twl4030_hsor_texts[] = | ||
243 | {"Off", "DACR1", "DACR2"}; | ||
244 | |||
245 | static const struct soc_enum twl4030_hsor_enum = | ||
246 | SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4, | ||
247 | ARRAY_SIZE(twl4030_hsor_texts), | ||
248 | twl4030_hsor_texts); | ||
249 | |||
250 | static const struct snd_kcontrol_new twl4030_dapm_hsor_control = | ||
251 | SOC_DAPM_ENUM("Route", twl4030_hsor_enum); | ||
252 | |||
253 | /* Carkit Left */ | ||
254 | static const char *twl4030_carkitl_texts[] = | ||
255 | {"Off", "DACL1", "DACL2"}; | ||
256 | |||
257 | static const struct soc_enum twl4030_carkitl_enum = | ||
258 | SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1, | ||
259 | ARRAY_SIZE(twl4030_carkitl_texts), | ||
260 | twl4030_carkitl_texts); | ||
261 | |||
262 | static const struct snd_kcontrol_new twl4030_dapm_carkitl_control = | ||
263 | SOC_DAPM_ENUM("Route", twl4030_carkitl_enum); | ||
264 | |||
265 | /* Carkit Right */ | ||
266 | static const char *twl4030_carkitr_texts[] = | ||
267 | {"Off", "DACR1", "DACR2"}; | ||
268 | |||
269 | static const struct soc_enum twl4030_carkitr_enum = | ||
270 | SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1, | ||
271 | ARRAY_SIZE(twl4030_carkitr_texts), | ||
272 | twl4030_carkitr_texts); | ||
273 | |||
274 | static const struct snd_kcontrol_new twl4030_dapm_carkitr_control = | ||
275 | SOC_DAPM_ENUM("Route", twl4030_carkitr_enum); | ||
276 | |||
277 | /* Handsfree Left */ | ||
278 | static const char *twl4030_handsfreel_texts[] = | ||
279 | {"Voice", "DACL1", "DACL2", "DACR2"}; | ||
280 | |||
281 | static const struct soc_enum twl4030_handsfreel_enum = | ||
282 | SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0, | ||
283 | ARRAY_SIZE(twl4030_handsfreel_texts), | ||
284 | twl4030_handsfreel_texts); | ||
285 | |||
286 | static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control = | ||
287 | SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum); | ||
288 | |||
289 | /* Handsfree Right */ | ||
290 | static const char *twl4030_handsfreer_texts[] = | ||
291 | {"Voice", "DACR1", "DACR2", "DACL2"}; | ||
292 | |||
293 | static const struct soc_enum twl4030_handsfreer_enum = | ||
294 | SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0, | ||
295 | ARRAY_SIZE(twl4030_handsfreer_texts), | ||
296 | twl4030_handsfreer_texts); | ||
297 | |||
298 | static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control = | ||
299 | SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum); | ||
300 | |||
301 | static int outmixer_event(struct snd_soc_dapm_widget *w, | ||
302 | struct snd_kcontrol *kcontrol, int event) | ||
303 | { | ||
304 | struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; | ||
305 | int ret = 0; | ||
306 | int val; | ||
307 | |||
308 | switch (e->reg) { | ||
309 | case TWL4030_REG_PREDL_CTL: | ||
310 | case TWL4030_REG_PREDR_CTL: | ||
311 | case TWL4030_REG_EAR_CTL: | ||
312 | val = w->value >> e->shift_l; | ||
313 | if (val == 3) { | ||
314 | printk(KERN_WARNING | ||
315 | "Invalid MUX setting for register 0x%02x (%d)\n", | ||
316 | e->reg, val); | ||
317 | ret = -1; | ||
318 | } | ||
319 | break; | ||
320 | } | ||
321 | |||
322 | return ret; | ||
323 | } | ||
324 | |||
325 | static int handsfree_event(struct snd_soc_dapm_widget *w, | ||
326 | struct snd_kcontrol *kcontrol, int event) | ||
327 | { | ||
328 | struct soc_enum *e = (struct soc_enum *)w->kcontrols->private_value; | ||
329 | unsigned char hs_ctl; | ||
330 | |||
331 | hs_ctl = twl4030_read_reg_cache(w->codec, e->reg); | ||
332 | |||
333 | if (hs_ctl & TWL4030_HF_CTL_REF_EN) { | ||
334 | hs_ctl |= TWL4030_HF_CTL_RAMP_EN; | ||
335 | twl4030_write(w->codec, e->reg, hs_ctl); | ||
336 | hs_ctl |= TWL4030_HF_CTL_LOOP_EN; | ||
337 | twl4030_write(w->codec, e->reg, hs_ctl); | ||
338 | hs_ctl |= TWL4030_HF_CTL_HB_EN; | ||
339 | twl4030_write(w->codec, e->reg, hs_ctl); | ||
340 | } else { | ||
341 | hs_ctl &= ~(TWL4030_HF_CTL_RAMP_EN | TWL4030_HF_CTL_LOOP_EN | ||
342 | | TWL4030_HF_CTL_HB_EN); | ||
343 | twl4030_write(w->codec, e->reg, hs_ctl); | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | /* | ||
350 | * Some of the gain controls in TWL (mostly those which are associated with | ||
351 | * the outputs) are implemented in an interesting way: | ||
352 | * 0x0 : Power down (mute) | ||
353 | * 0x1 : 6dB | ||
354 | * 0x2 : 0 dB | ||
355 | * 0x3 : -6 dB | ||
356 | * Inverting not going to help with these. | ||
357 | * Custom volsw and volsw_2r get/put functions to handle these gain bits. | ||
358 | */ | ||
359 | #define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\ | ||
360 | xinvert, tlv_array) \ | ||
361 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | ||
362 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
363 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
364 | .tlv.p = (tlv_array), \ | ||
365 | .info = snd_soc_info_volsw, \ | ||
366 | .get = snd_soc_get_volsw_twl4030, \ | ||
367 | .put = snd_soc_put_volsw_twl4030, \ | ||
368 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | ||
369 | {.reg = xreg, .shift = shift_left, .rshift = shift_right,\ | ||
370 | .max = xmax, .invert = xinvert} } | ||
371 | #define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\ | ||
372 | xinvert, tlv_array) \ | ||
373 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | ||
374 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
375 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
376 | .tlv.p = (tlv_array), \ | ||
377 | .info = snd_soc_info_volsw_2r, \ | ||
378 | .get = snd_soc_get_volsw_r2_twl4030,\ | ||
379 | .put = snd_soc_put_volsw_r2_twl4030, \ | ||
380 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | ||
381 | {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ | ||
382 | .rshift = xshift, .max = xmax, .invert = xinvert} } | ||
383 | #define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \ | ||
384 | SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \ | ||
385 | xinvert, tlv_array) | ||
386 | |||
387 | static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol, | ||
388 | struct snd_ctl_elem_value *ucontrol) | ||
389 | { | ||
390 | struct soc_mixer_control *mc = | ||
391 | (struct soc_mixer_control *)kcontrol->private_value; | ||
392 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
393 | unsigned int reg = mc->reg; | ||
394 | unsigned int shift = mc->shift; | ||
395 | unsigned int rshift = mc->rshift; | ||
396 | int max = mc->max; | ||
397 | int mask = (1 << fls(max)) - 1; | ||
398 | |||
399 | ucontrol->value.integer.value[0] = | ||
400 | (snd_soc_read(codec, reg) >> shift) & mask; | ||
401 | if (ucontrol->value.integer.value[0]) | ||
402 | ucontrol->value.integer.value[0] = | ||
403 | max + 1 - ucontrol->value.integer.value[0]; | ||
404 | |||
405 | if (shift != rshift) { | ||
406 | ucontrol->value.integer.value[1] = | ||
407 | (snd_soc_read(codec, reg) >> rshift) & mask; | ||
408 | if (ucontrol->value.integer.value[1]) | ||
409 | ucontrol->value.integer.value[1] = | ||
410 | max + 1 - ucontrol->value.integer.value[1]; | ||
411 | } | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol, | ||
417 | struct snd_ctl_elem_value *ucontrol) | ||
418 | { | ||
419 | struct soc_mixer_control *mc = | ||
420 | (struct soc_mixer_control *)kcontrol->private_value; | ||
421 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
422 | unsigned int reg = mc->reg; | ||
423 | unsigned int shift = mc->shift; | ||
424 | unsigned int rshift = mc->rshift; | ||
425 | int max = mc->max; | ||
426 | int mask = (1 << fls(max)) - 1; | ||
427 | unsigned short val, val2, val_mask; | ||
428 | |||
429 | val = (ucontrol->value.integer.value[0] & mask); | ||
430 | |||
431 | val_mask = mask << shift; | ||
432 | if (val) | ||
433 | val = max + 1 - val; | ||
434 | val = val << shift; | ||
435 | if (shift != rshift) { | ||
436 | val2 = (ucontrol->value.integer.value[1] & mask); | ||
437 | val_mask |= mask << rshift; | ||
438 | if (val2) | ||
439 | val2 = max + 1 - val2; | ||
440 | val |= val2 << rshift; | ||
441 | } | ||
442 | return snd_soc_update_bits(codec, reg, val_mask, val); | ||
443 | } | ||
444 | |||
445 | static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | ||
446 | struct snd_ctl_elem_value *ucontrol) | ||
447 | { | ||
448 | struct soc_mixer_control *mc = | ||
449 | (struct soc_mixer_control *)kcontrol->private_value; | ||
450 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
451 | unsigned int reg = mc->reg; | ||
452 | unsigned int reg2 = mc->rreg; | ||
453 | unsigned int shift = mc->shift; | ||
454 | int max = mc->max; | ||
455 | int mask = (1<<fls(max))-1; | ||
456 | |||
457 | ucontrol->value.integer.value[0] = | ||
458 | (snd_soc_read(codec, reg) >> shift) & mask; | ||
459 | ucontrol->value.integer.value[1] = | ||
460 | (snd_soc_read(codec, reg2) >> shift) & mask; | ||
461 | |||
462 | if (ucontrol->value.integer.value[0]) | ||
463 | ucontrol->value.integer.value[0] = | ||
464 | max + 1 - ucontrol->value.integer.value[0]; | ||
465 | if (ucontrol->value.integer.value[1]) | ||
466 | ucontrol->value.integer.value[1] = | ||
467 | max + 1 - ucontrol->value.integer.value[1]; | ||
468 | |||
469 | return 0; | ||
470 | } | ||
471 | |||
472 | static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol, | ||
473 | struct snd_ctl_elem_value *ucontrol) | ||
474 | { | ||
475 | struct soc_mixer_control *mc = | ||
476 | (struct soc_mixer_control *)kcontrol->private_value; | ||
477 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
478 | unsigned int reg = mc->reg; | ||
479 | unsigned int reg2 = mc->rreg; | ||
480 | unsigned int shift = mc->shift; | ||
481 | int max = mc->max; | ||
482 | int mask = (1 << fls(max)) - 1; | ||
483 | int err; | ||
484 | unsigned short val, val2, val_mask; | ||
485 | |||
486 | val_mask = mask << shift; | ||
487 | val = (ucontrol->value.integer.value[0] & mask); | ||
488 | val2 = (ucontrol->value.integer.value[1] & mask); | ||
489 | |||
490 | if (val) | ||
491 | val = max + 1 - val; | ||
492 | if (val2) | ||
493 | val2 = max + 1 - val2; | ||
494 | |||
495 | val = val << shift; | ||
496 | val2 = val2 << shift; | ||
497 | |||
498 | err = snd_soc_update_bits(codec, reg, val_mask, val); | ||
499 | if (err < 0) | ||
500 | return err; | ||
501 | |||
502 | err = snd_soc_update_bits(codec, reg2, val_mask, val2); | ||
503 | return err; | ||
504 | } | ||
505 | |||
506 | static int twl4030_get_left_input(struct snd_kcontrol *kcontrol, | ||
507 | struct snd_ctl_elem_value *ucontrol) | ||
508 | { | ||
509 | struct snd_soc_codec *codec = kcontrol->private_data; | ||
510 | u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | ||
511 | int result = 0; | ||
512 | |||
513 | /* one bit must be set a time */ | ||
514 | reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN | ||
515 | | TWL4030_MAINMIC_EN; | ||
516 | if (reg != 0) { | ||
517 | result++; | ||
518 | while ((reg & 1) == 0) { | ||
519 | result++; | ||
520 | reg >>= 1; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | ucontrol->value.integer.value[0] = result; | ||
525 | return 0; | ||
526 | } | ||
527 | |||
528 | static int twl4030_put_left_input(struct snd_kcontrol *kcontrol, | ||
529 | struct snd_ctl_elem_value *ucontrol) | ||
530 | { | ||
531 | struct snd_soc_codec *codec = kcontrol->private_data; | ||
532 | int value = ucontrol->value.integer.value[0]; | ||
533 | u8 anamicl, micbias, avadc_ctl; | ||
534 | |||
535 | anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | ||
536 | anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN | ||
537 | | TWL4030_MAINMIC_EN); | ||
538 | micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL); | ||
539 | micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN); | ||
540 | avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL); | ||
541 | |||
542 | switch (value) { | ||
543 | case 1: | ||
544 | anamicl |= TWL4030_MAINMIC_EN; | ||
545 | micbias |= TWL4030_MICBIAS1_EN; | ||
546 | break; | ||
547 | case 2: | ||
548 | anamicl |= TWL4030_HSMIC_EN; | ||
549 | micbias |= TWL4030_HSMICBIAS_EN; | ||
550 | break; | ||
551 | case 3: | ||
552 | anamicl |= TWL4030_AUXL_EN; | ||
553 | break; | ||
554 | case 4: | ||
555 | anamicl |= TWL4030_CKMIC_EN; | ||
556 | break; | ||
557 | default: | ||
558 | break; | ||
559 | } | ||
560 | |||
561 | /* If some input is selected, enable amp and ADC */ | ||
562 | if (value != 0) { | ||
563 | anamicl |= TWL4030_MICAMPL_EN; | ||
564 | avadc_ctl |= TWL4030_ADCL_EN; | ||
565 | } else { | ||
566 | anamicl &= ~TWL4030_MICAMPL_EN; | ||
567 | avadc_ctl &= ~TWL4030_ADCL_EN; | ||
568 | } | ||
569 | |||
570 | twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl); | ||
571 | twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias); | ||
572 | twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl); | ||
573 | |||
574 | return 1; | ||
575 | } | ||
576 | |||
577 | static int twl4030_get_right_input(struct snd_kcontrol *kcontrol, | ||
578 | struct snd_ctl_elem_value *ucontrol) | ||
579 | { | ||
580 | struct snd_soc_codec *codec = kcontrol->private_data; | ||
581 | u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR); | ||
582 | int value = 0; | ||
583 | |||
584 | reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN; | ||
585 | switch (reg) { | ||
586 | case TWL4030_SUBMIC_EN: | ||
587 | value = 1; | ||
588 | break; | ||
589 | case TWL4030_AUXR_EN: | ||
590 | value = 2; | ||
591 | break; | ||
592 | default: | ||
593 | break; | ||
594 | } | ||
595 | |||
596 | ucontrol->value.integer.value[0] = value; | ||
597 | return 0; | ||
598 | } | ||
599 | |||
600 | static int twl4030_put_right_input(struct snd_kcontrol *kcontrol, | ||
601 | struct snd_ctl_elem_value *ucontrol) | ||
602 | { | ||
603 | struct snd_soc_codec *codec = kcontrol->private_data; | ||
604 | int value = ucontrol->value.integer.value[0]; | ||
605 | u8 anamicr, micbias, avadc_ctl; | ||
606 | |||
607 | anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR); | ||
608 | anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN); | ||
609 | micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL); | ||
610 | micbias &= ~TWL4030_MICBIAS2_EN; | ||
611 | avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL); | ||
612 | |||
613 | switch (value) { | ||
614 | case 1: | ||
615 | anamicr |= TWL4030_SUBMIC_EN; | ||
616 | micbias |= TWL4030_MICBIAS2_EN; | ||
617 | break; | ||
618 | case 2: | ||
619 | anamicr |= TWL4030_AUXR_EN; | ||
620 | break; | ||
621 | default: | ||
622 | break; | ||
623 | } | ||
624 | |||
625 | if (value != 0) { | ||
626 | anamicr |= TWL4030_MICAMPR_EN; | ||
627 | avadc_ctl |= TWL4030_ADCR_EN; | ||
628 | } else { | ||
629 | anamicr &= ~TWL4030_MICAMPR_EN; | ||
630 | avadc_ctl &= ~TWL4030_ADCR_EN; | ||
631 | } | ||
632 | |||
633 | twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr); | ||
634 | twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias); | ||
635 | twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl); | ||
636 | |||
637 | return 1; | ||
638 | } | ||
639 | |||
640 | static const char *twl4030_left_in_sel[] = { | ||
641 | "None", | ||
642 | "Main Mic", | ||
643 | "Headset Mic", | ||
644 | "Line In", | ||
645 | "Carkit Mic", | ||
646 | }; | ||
647 | |||
648 | static const char *twl4030_right_in_sel[] = { | ||
649 | "None", | ||
650 | "Sub Mic", | ||
651 | "Line In", | ||
652 | }; | ||
653 | |||
654 | static const struct soc_enum twl4030_left_input_mux = | ||
655 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel), | ||
656 | twl4030_left_in_sel); | ||
657 | |||
658 | static const struct soc_enum twl4030_right_input_mux = | ||
659 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel), | ||
660 | twl4030_right_in_sel); | ||
661 | |||
662 | /* | ||
663 | * FGAIN volume control: | ||
664 | * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB) | ||
665 | */ | ||
666 | static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1); | ||
667 | |||
668 | /* | ||
669 | * CGAIN volume control: | ||
670 | * 0 dB to 12 dB in 6 dB steps | ||
671 | * value 2 and 3 means 12 dB | ||
672 | */ | ||
673 | static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0); | ||
674 | |||
675 | /* | ||
676 | * Analog playback gain | ||
677 | * -24 dB to 12 dB in 2 dB steps | ||
678 | */ | ||
679 | static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0); | ||
680 | |||
681 | /* | ||
682 | * Gain controls tied to outputs | ||
683 | * -6 dB to 6 dB in 6 dB steps (mute instead of -12) | ||
684 | */ | ||
685 | static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1); | ||
686 | |||
687 | /* | ||
688 | * Capture gain after the ADCs | ||
689 | * from 0 dB to 31 dB in 1 dB steps | ||
690 | */ | ||
691 | static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0); | ||
692 | |||
693 | /* | ||
694 | * Gain control for input amplifiers | ||
695 | * 0 dB to 30 dB in 6 dB steps | ||
696 | */ | ||
697 | static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0); | ||
698 | |||
699 | static const struct snd_kcontrol_new twl4030_snd_controls[] = { | ||
700 | /* Common playback gain controls */ | ||
701 | SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume", | ||
702 | TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, | ||
703 | 0, 0x3f, 0, digital_fine_tlv), | ||
704 | SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume", | ||
705 | TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, | ||
706 | 0, 0x3f, 0, digital_fine_tlv), | ||
707 | |||
708 | SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume", | ||
709 | TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA, | ||
710 | 6, 0x2, 0, digital_coarse_tlv), | ||
711 | SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume", | ||
712 | TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA, | ||
713 | 6, 0x2, 0, digital_coarse_tlv), | ||
714 | |||
715 | SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume", | ||
716 | TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL, | ||
717 | 3, 0x12, 1, analog_tlv), | ||
718 | SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume", | ||
719 | TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, | ||
720 | 3, 0x12, 1, analog_tlv), | ||
721 | SOC_DOUBLE_R("DAC1 Analog Playback Switch", | ||
722 | TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL, | ||
723 | 1, 1, 0), | ||
724 | SOC_DOUBLE_R("DAC2 Analog Playback Switch", | ||
725 | TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL, | ||
726 | 1, 1, 0), | ||
727 | |||
728 | /* Separate output gain controls */ | ||
729 | SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume", | ||
730 | TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL, | ||
731 | 4, 3, 0, output_tvl), | ||
732 | |||
733 | SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume", | ||
734 | TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl), | ||
735 | |||
736 | SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume", | ||
737 | TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL, | ||
738 | 4, 3, 0, output_tvl), | ||
739 | |||
740 | SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume", | ||
741 | TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl), | ||
742 | |||
743 | /* Common capture gain controls */ | ||
744 | SOC_DOUBLE_R_TLV("Capture Volume", | ||
745 | TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA, | ||
746 | 0, 0x1f, 0, digital_capture_tlv), | ||
747 | |||
748 | SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN, | ||
749 | 0, 3, 5, 0, input_gain_tlv), | ||
750 | |||
751 | /* Input source controls */ | ||
752 | SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux, | ||
753 | twl4030_get_left_input, twl4030_put_left_input), | ||
754 | SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux, | ||
755 | twl4030_get_right_input, twl4030_put_right_input), | ||
756 | }; | ||
757 | |||
758 | /* add non dapm controls */ | ||
759 | static int twl4030_add_controls(struct snd_soc_codec *codec) | ||
760 | { | ||
761 | int err, i; | ||
762 | |||
763 | for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) { | ||
764 | err = snd_ctl_add(codec->card, | ||
765 | snd_soc_cnew(&twl4030_snd_controls[i], | ||
766 | codec, NULL)); | ||
767 | if (err < 0) | ||
768 | return err; | ||
769 | } | ||
770 | |||
771 | return 0; | ||
772 | } | ||
773 | |||
774 | static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | ||
775 | SND_SOC_DAPM_INPUT("INL"), | ||
776 | SND_SOC_DAPM_INPUT("INR"), | ||
777 | |||
778 | SND_SOC_DAPM_OUTPUT("OUTL"), | ||
779 | SND_SOC_DAPM_OUTPUT("OUTR"), | ||
780 | SND_SOC_DAPM_OUTPUT("EARPIECE"), | ||
781 | SND_SOC_DAPM_OUTPUT("PREDRIVEL"), | ||
782 | SND_SOC_DAPM_OUTPUT("PREDRIVER"), | ||
783 | SND_SOC_DAPM_OUTPUT("HSOL"), | ||
784 | SND_SOC_DAPM_OUTPUT("HSOR"), | ||
785 | SND_SOC_DAPM_OUTPUT("CARKITL"), | ||
786 | SND_SOC_DAPM_OUTPUT("CARKITR"), | ||
787 | SND_SOC_DAPM_OUTPUT("HFL"), | ||
788 | SND_SOC_DAPM_OUTPUT("HFR"), | ||
789 | |||
790 | /* DACs */ | ||
791 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front Playback", | ||
792 | TWL4030_REG_AVDAC_CTL, 0, 0), | ||
793 | SND_SOC_DAPM_DAC("DAC Left1", "Left Front Playback", | ||
794 | TWL4030_REG_AVDAC_CTL, 1, 0), | ||
795 | SND_SOC_DAPM_DAC("DAC Right2", "Right Rear Playback", | ||
796 | TWL4030_REG_AVDAC_CTL, 2, 0), | ||
797 | SND_SOC_DAPM_DAC("DAC Left2", "Left Rear Playback", | ||
798 | TWL4030_REG_AVDAC_CTL, 3, 0), | ||
799 | |||
800 | /* Analog PGAs */ | ||
801 | SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL, | ||
802 | 0, 0, NULL, 0), | ||
803 | SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL, | ||
804 | 0, 0, NULL, 0), | ||
805 | SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL, | ||
806 | 0, 0, NULL, 0), | ||
807 | SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL, | ||
808 | 0, 0, NULL, 0), | ||
809 | |||
810 | /* Output MUX controls */ | ||
811 | /* Earpiece */ | ||
812 | SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0, | ||
813 | &twl4030_dapm_earpiece_control, outmixer_event, | ||
814 | SND_SOC_DAPM_PRE_REG), | ||
815 | /* PreDrivL/R */ | ||
816 | SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0, | ||
817 | &twl4030_dapm_predrivel_control, outmixer_event, | ||
818 | SND_SOC_DAPM_PRE_REG), | ||
819 | SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0, | ||
820 | &twl4030_dapm_predriver_control, outmixer_event, | ||
821 | SND_SOC_DAPM_PRE_REG), | ||
822 | /* HeadsetL/R */ | ||
823 | SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0, | ||
824 | &twl4030_dapm_hsol_control), | ||
825 | SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0, | ||
826 | &twl4030_dapm_hsor_control), | ||
827 | /* CarkitL/R */ | ||
828 | SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0, | ||
829 | &twl4030_dapm_carkitl_control), | ||
830 | SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0, | ||
831 | &twl4030_dapm_carkitr_control), | ||
832 | /* HandsfreeL/R */ | ||
833 | SND_SOC_DAPM_MUX_E("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0, | ||
834 | &twl4030_dapm_handsfreel_control, handsfree_event, | ||
835 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
836 | SND_SOC_DAPM_MUX_E("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0, | ||
837 | &twl4030_dapm_handsfreer_control, handsfree_event, | ||
838 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
839 | |||
840 | SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0), | ||
841 | SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0), | ||
842 | }; | ||
843 | |||
844 | static const struct snd_soc_dapm_route intercon[] = { | ||
845 | {"ARXL1_APGA", NULL, "DAC Left1"}, | ||
846 | {"ARXR1_APGA", NULL, "DAC Right1"}, | ||
847 | {"ARXL2_APGA", NULL, "DAC Left2"}, | ||
848 | {"ARXR2_APGA", NULL, "DAC Right2"}, | ||
849 | |||
850 | /* Internal playback routings */ | ||
851 | /* Earpiece */ | ||
852 | {"Earpiece Mux", "DACL1", "ARXL1_APGA"}, | ||
853 | {"Earpiece Mux", "DACL2", "ARXL2_APGA"}, | ||
854 | {"Earpiece Mux", "DACR1", "ARXR1_APGA"}, | ||
855 | /* PreDrivL */ | ||
856 | {"PredriveL Mux", "DACL1", "ARXL1_APGA"}, | ||
857 | {"PredriveL Mux", "DACL2", "ARXL2_APGA"}, | ||
858 | {"PredriveL Mux", "DACR2", "ARXR2_APGA"}, | ||
859 | /* PreDrivR */ | ||
860 | {"PredriveR Mux", "DACR1", "ARXR1_APGA"}, | ||
861 | {"PredriveR Mux", "DACR2", "ARXR2_APGA"}, | ||
862 | {"PredriveR Mux", "DACL2", "ARXL2_APGA"}, | ||
863 | /* HeadsetL */ | ||
864 | {"HeadsetL Mux", "DACL1", "ARXL1_APGA"}, | ||
865 | {"HeadsetL Mux", "DACL2", "ARXL2_APGA"}, | ||
866 | /* HeadsetR */ | ||
867 | {"HeadsetR Mux", "DACR1", "ARXR1_APGA"}, | ||
868 | {"HeadsetR Mux", "DACR2", "ARXR2_APGA"}, | ||
869 | /* CarkitL */ | ||
870 | {"CarkitL Mux", "DACL1", "ARXL1_APGA"}, | ||
871 | {"CarkitL Mux", "DACL2", "ARXL2_APGA"}, | ||
872 | /* CarkitR */ | ||
873 | {"CarkitR Mux", "DACR1", "ARXR1_APGA"}, | ||
874 | {"CarkitR Mux", "DACR2", "ARXR2_APGA"}, | ||
875 | /* HandsfreeL */ | ||
876 | {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"}, | ||
877 | {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"}, | ||
878 | {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"}, | ||
879 | /* HandsfreeR */ | ||
880 | {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"}, | ||
881 | {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"}, | ||
882 | {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"}, | ||
883 | |||
884 | /* outputs */ | ||
885 | {"OUTL", NULL, "ARXL2_APGA"}, | ||
886 | {"OUTR", NULL, "ARXR2_APGA"}, | ||
887 | {"EARPIECE", NULL, "Earpiece Mux"}, | ||
888 | {"PREDRIVEL", NULL, "PredriveL Mux"}, | ||
889 | {"PREDRIVER", NULL, "PredriveR Mux"}, | ||
890 | {"HSOL", NULL, "HeadsetL Mux"}, | ||
891 | {"HSOR", NULL, "HeadsetR Mux"}, | ||
892 | {"CARKITL", NULL, "CarkitL Mux"}, | ||
893 | {"CARKITR", NULL, "CarkitR Mux"}, | ||
894 | {"HFL", NULL, "HandsfreeL Mux"}, | ||
895 | {"HFR", NULL, "HandsfreeR Mux"}, | ||
896 | |||
897 | /* inputs */ | ||
898 | {"ADCL", NULL, "INL"}, | ||
899 | {"ADCR", NULL, "INR"}, | ||
900 | }; | ||
901 | |||
902 | static int twl4030_add_widgets(struct snd_soc_codec *codec) | ||
903 | { | ||
904 | snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets, | ||
905 | ARRAY_SIZE(twl4030_dapm_widgets)); | ||
906 | |||
907 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
908 | |||
909 | snd_soc_dapm_new_widgets(codec); | ||
910 | return 0; | ||
911 | } | ||
912 | |||
913 | static void twl4030_power_up(struct snd_soc_codec *codec) | ||
914 | { | ||
915 | u8 anamicl, regmisc1, byte, popn; | ||
916 | int i = 0; | ||
917 | |||
918 | /* set CODECPDZ to turn on codec */ | ||
919 | twl4030_set_codecpdz(codec); | ||
920 | |||
921 | /* initiate offset cancellation */ | ||
922 | anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL); | ||
923 | twl4030_write(codec, TWL4030_REG_ANAMICL, | ||
924 | anamicl | TWL4030_CNCL_OFFSET_START); | ||
925 | |||
926 | /* wait for offset cancellation to complete */ | ||
927 | do { | ||
928 | /* this takes a little while, so don't slam i2c */ | ||
929 | udelay(2000); | ||
930 | twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte, | ||
931 | TWL4030_REG_ANAMICL); | ||
932 | } while ((i++ < 100) && | ||
933 | ((byte & TWL4030_CNCL_OFFSET_START) == | ||
934 | TWL4030_CNCL_OFFSET_START)); | ||
935 | |||
936 | /* anti-pop when changing analog gain */ | ||
937 | regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1); | ||
938 | twl4030_write(codec, TWL4030_REG_MISC_SET_1, | ||
939 | regmisc1 | TWL4030_SMOOTH_ANAVOL_EN); | ||
940 | |||
941 | /* toggle CODECPDZ as per TRM */ | ||
942 | twl4030_clear_codecpdz(codec); | ||
943 | twl4030_set_codecpdz(codec); | ||
944 | |||
945 | /* program anti-pop with bias ramp delay */ | ||
946 | popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | ||
947 | popn &= TWL4030_RAMP_DELAY; | ||
948 | popn |= TWL4030_RAMP_DELAY_645MS; | ||
949 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
950 | popn |= TWL4030_VMID_EN; | ||
951 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
952 | |||
953 | /* enable anti-pop ramp */ | ||
954 | popn |= TWL4030_RAMP_EN; | ||
955 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
956 | } | ||
957 | |||
958 | static void twl4030_power_down(struct snd_soc_codec *codec) | ||
959 | { | ||
960 | u8 popn; | ||
961 | |||
962 | /* disable anti-pop ramp */ | ||
963 | popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); | ||
964 | popn &= ~TWL4030_RAMP_EN; | ||
965 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
966 | |||
967 | /* disable bias out */ | ||
968 | popn &= ~TWL4030_VMID_EN; | ||
969 | twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn); | ||
970 | |||
971 | /* power down */ | ||
972 | twl4030_clear_codecpdz(codec); | ||
973 | } | ||
974 | |||
975 | static int twl4030_set_bias_level(struct snd_soc_codec *codec, | ||
976 | enum snd_soc_bias_level level) | ||
977 | { | ||
978 | switch (level) { | ||
979 | case SND_SOC_BIAS_ON: | ||
980 | twl4030_power_up(codec); | ||
981 | break; | ||
982 | case SND_SOC_BIAS_PREPARE: | ||
983 | /* TODO: develop a twl4030_prepare function */ | ||
984 | break; | ||
985 | case SND_SOC_BIAS_STANDBY: | ||
986 | /* TODO: develop a twl4030_standby function */ | ||
987 | twl4030_power_down(codec); | ||
988 | break; | ||
989 | case SND_SOC_BIAS_OFF: | ||
990 | twl4030_power_down(codec); | ||
991 | break; | ||
992 | } | ||
993 | codec->bias_level = level; | ||
994 | |||
995 | return 0; | ||
996 | } | ||
997 | |||
998 | static int twl4030_hw_params(struct snd_pcm_substream *substream, | ||
999 | struct snd_pcm_hw_params *params, | ||
1000 | struct snd_soc_dai *dai) | ||
1001 | { | ||
1002 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
1003 | struct snd_soc_device *socdev = rtd->socdev; | ||
1004 | struct snd_soc_codec *codec = socdev->codec; | ||
1005 | u8 mode, old_mode, format, old_format; | ||
1006 | |||
1007 | |||
1008 | /* bit rate */ | ||
1009 | old_mode = twl4030_read_reg_cache(codec, | ||
1010 | TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ; | ||
1011 | mode = old_mode & ~TWL4030_APLL_RATE; | ||
1012 | |||
1013 | switch (params_rate(params)) { | ||
1014 | case 8000: | ||
1015 | mode |= TWL4030_APLL_RATE_8000; | ||
1016 | break; | ||
1017 | case 11025: | ||
1018 | mode |= TWL4030_APLL_RATE_11025; | ||
1019 | break; | ||
1020 | case 12000: | ||
1021 | mode |= TWL4030_APLL_RATE_12000; | ||
1022 | break; | ||
1023 | case 16000: | ||
1024 | mode |= TWL4030_APLL_RATE_16000; | ||
1025 | break; | ||
1026 | case 22050: | ||
1027 | mode |= TWL4030_APLL_RATE_22050; | ||
1028 | break; | ||
1029 | case 24000: | ||
1030 | mode |= TWL4030_APLL_RATE_24000; | ||
1031 | break; | ||
1032 | case 32000: | ||
1033 | mode |= TWL4030_APLL_RATE_32000; | ||
1034 | break; | ||
1035 | case 44100: | ||
1036 | mode |= TWL4030_APLL_RATE_44100; | ||
1037 | break; | ||
1038 | case 48000: | ||
1039 | mode |= TWL4030_APLL_RATE_48000; | ||
1040 | break; | ||
1041 | default: | ||
1042 | printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n", | ||
1043 | params_rate(params)); | ||
1044 | return -EINVAL; | ||
1045 | } | ||
1046 | |||
1047 | if (mode != old_mode) { | ||
1048 | /* change rate and set CODECPDZ */ | ||
1049 | twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); | ||
1050 | twl4030_set_codecpdz(codec); | ||
1051 | } | ||
1052 | |||
1053 | /* sample size */ | ||
1054 | old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | ||
1055 | format = old_format; | ||
1056 | format &= ~TWL4030_DATA_WIDTH; | ||
1057 | switch (params_format(params)) { | ||
1058 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1059 | format |= TWL4030_DATA_WIDTH_16S_16W; | ||
1060 | break; | ||
1061 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1062 | format |= TWL4030_DATA_WIDTH_32S_24W; | ||
1063 | break; | ||
1064 | default: | ||
1065 | printk(KERN_ERR "TWL4030 hw params: unknown format %d\n", | ||
1066 | params_format(params)); | ||
1067 | return -EINVAL; | ||
1068 | } | ||
1069 | |||
1070 | if (format != old_format) { | ||
1071 | |||
1072 | /* clear CODECPDZ before changing format (codec requirement) */ | ||
1073 | twl4030_clear_codecpdz(codec); | ||
1074 | |||
1075 | /* change format */ | ||
1076 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); | ||
1077 | |||
1078 | /* set CODECPDZ afterwards */ | ||
1079 | twl4030_set_codecpdz(codec); | ||
1080 | } | ||
1081 | return 0; | ||
1082 | } | ||
1083 | |||
1084 | static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
1085 | int clk_id, unsigned int freq, int dir) | ||
1086 | { | ||
1087 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1088 | u8 infreq; | ||
1089 | |||
1090 | switch (freq) { | ||
1091 | case 19200000: | ||
1092 | infreq = TWL4030_APLL_INFREQ_19200KHZ; | ||
1093 | break; | ||
1094 | case 26000000: | ||
1095 | infreq = TWL4030_APLL_INFREQ_26000KHZ; | ||
1096 | break; | ||
1097 | case 38400000: | ||
1098 | infreq = TWL4030_APLL_INFREQ_38400KHZ; | ||
1099 | break; | ||
1100 | default: | ||
1101 | printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", | ||
1102 | freq); | ||
1103 | return -EINVAL; | ||
1104 | } | ||
1105 | |||
1106 | infreq |= TWL4030_APLL_EN; | ||
1107 | twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq); | ||
1108 | |||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1112 | static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
1113 | unsigned int fmt) | ||
1114 | { | ||
1115 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1116 | u8 old_format, format; | ||
1117 | |||
1118 | /* get format */ | ||
1119 | old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF); | ||
1120 | format = old_format; | ||
1121 | |||
1122 | /* set master/slave audio interface */ | ||
1123 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
1124 | case SND_SOC_DAIFMT_CBM_CFM: | ||
1125 | format &= ~(TWL4030_AIF_SLAVE_EN); | ||
1126 | format &= ~(TWL4030_CLK256FS_EN); | ||
1127 | break; | ||
1128 | case SND_SOC_DAIFMT_CBS_CFS: | ||
1129 | format |= TWL4030_AIF_SLAVE_EN; | ||
1130 | format |= TWL4030_CLK256FS_EN; | ||
1131 | break; | ||
1132 | default: | ||
1133 | return -EINVAL; | ||
1134 | } | ||
1135 | |||
1136 | /* interface format */ | ||
1137 | format &= ~TWL4030_AIF_FORMAT; | ||
1138 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
1139 | case SND_SOC_DAIFMT_I2S: | ||
1140 | format |= TWL4030_AIF_FORMAT_CODEC; | ||
1141 | break; | ||
1142 | default: | ||
1143 | return -EINVAL; | ||
1144 | } | ||
1145 | |||
1146 | if (format != old_format) { | ||
1147 | |||
1148 | /* clear CODECPDZ before changing format (codec requirement) */ | ||
1149 | twl4030_clear_codecpdz(codec); | ||
1150 | |||
1151 | /* change format */ | ||
1152 | twl4030_write(codec, TWL4030_REG_AUDIO_IF, format); | ||
1153 | |||
1154 | /* set CODECPDZ afterwards */ | ||
1155 | twl4030_set_codecpdz(codec); | ||
1156 | } | ||
1157 | |||
1158 | return 0; | ||
1159 | } | ||
1160 | |||
1161 | #define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000) | ||
1162 | #define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE) | ||
1163 | |||
1164 | struct snd_soc_dai twl4030_dai = { | ||
1165 | .name = "twl4030", | ||
1166 | .playback = { | ||
1167 | .stream_name = "Playback", | ||
1168 | .channels_min = 2, | ||
1169 | .channels_max = 2, | ||
1170 | .rates = TWL4030_RATES, | ||
1171 | .formats = TWL4030_FORMATS,}, | ||
1172 | .capture = { | ||
1173 | .stream_name = "Capture", | ||
1174 | .channels_min = 2, | ||
1175 | .channels_max = 2, | ||
1176 | .rates = TWL4030_RATES, | ||
1177 | .formats = TWL4030_FORMATS,}, | ||
1178 | .ops = { | ||
1179 | .hw_params = twl4030_hw_params, | ||
1180 | .set_sysclk = twl4030_set_dai_sysclk, | ||
1181 | .set_fmt = twl4030_set_dai_fmt, | ||
1182 | } | ||
1183 | }; | ||
1184 | EXPORT_SYMBOL_GPL(twl4030_dai); | ||
1185 | |||
1186 | static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) | ||
1187 | { | ||
1188 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1189 | struct snd_soc_codec *codec = socdev->codec; | ||
1190 | |||
1191 | twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1192 | |||
1193 | return 0; | ||
1194 | } | ||
1195 | |||
1196 | static int twl4030_resume(struct platform_device *pdev) | ||
1197 | { | ||
1198 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1199 | struct snd_soc_codec *codec = socdev->codec; | ||
1200 | |||
1201 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1202 | twl4030_set_bias_level(codec, codec->suspend_bias_level); | ||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | /* | ||
1207 | * initialize the driver | ||
1208 | * register the mixer and dsp interfaces with the kernel | ||
1209 | */ | ||
1210 | |||
1211 | static int twl4030_init(struct snd_soc_device *socdev) | ||
1212 | { | ||
1213 | struct snd_soc_codec *codec = socdev->codec; | ||
1214 | int ret = 0; | ||
1215 | |||
1216 | printk(KERN_INFO "TWL4030 Audio Codec init \n"); | ||
1217 | |||
1218 | codec->name = "twl4030"; | ||
1219 | codec->owner = THIS_MODULE; | ||
1220 | codec->read = twl4030_read_reg_cache; | ||
1221 | codec->write = twl4030_write; | ||
1222 | codec->set_bias_level = twl4030_set_bias_level; | ||
1223 | codec->dai = &twl4030_dai; | ||
1224 | codec->num_dai = 1; | ||
1225 | codec->reg_cache_size = sizeof(twl4030_reg); | ||
1226 | codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg), | ||
1227 | GFP_KERNEL); | ||
1228 | if (codec->reg_cache == NULL) | ||
1229 | return -ENOMEM; | ||
1230 | |||
1231 | /* register pcms */ | ||
1232 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1233 | if (ret < 0) { | ||
1234 | printk(KERN_ERR "twl4030: failed to create pcms\n"); | ||
1235 | goto pcm_err; | ||
1236 | } | ||
1237 | |||
1238 | twl4030_init_chip(codec); | ||
1239 | |||
1240 | /* power on device */ | ||
1241 | twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1242 | |||
1243 | twl4030_add_controls(codec); | ||
1244 | twl4030_add_widgets(codec); | ||
1245 | |||
1246 | ret = snd_soc_init_card(socdev); | ||
1247 | if (ret < 0) { | ||
1248 | printk(KERN_ERR "twl4030: failed to register card\n"); | ||
1249 | goto card_err; | ||
1250 | } | ||
1251 | |||
1252 | return ret; | ||
1253 | |||
1254 | card_err: | ||
1255 | snd_soc_free_pcms(socdev); | ||
1256 | snd_soc_dapm_free(socdev); | ||
1257 | pcm_err: | ||
1258 | kfree(codec->reg_cache); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | static struct snd_soc_device *twl4030_socdev; | ||
1263 | |||
1264 | static int twl4030_probe(struct platform_device *pdev) | ||
1265 | { | ||
1266 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1267 | struct snd_soc_codec *codec; | ||
1268 | |||
1269 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
1270 | if (codec == NULL) | ||
1271 | return -ENOMEM; | ||
1272 | |||
1273 | socdev->codec = codec; | ||
1274 | mutex_init(&codec->mutex); | ||
1275 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1276 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1277 | |||
1278 | twl4030_socdev = socdev; | ||
1279 | twl4030_init(socdev); | ||
1280 | |||
1281 | return 0; | ||
1282 | } | ||
1283 | |||
1284 | static int twl4030_remove(struct platform_device *pdev) | ||
1285 | { | ||
1286 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1287 | struct snd_soc_codec *codec = socdev->codec; | ||
1288 | |||
1289 | printk(KERN_INFO "TWL4030 Audio Codec remove\n"); | ||
1290 | kfree(codec); | ||
1291 | |||
1292 | return 0; | ||
1293 | } | ||
1294 | |||
1295 | struct snd_soc_codec_device soc_codec_dev_twl4030 = { | ||
1296 | .probe = twl4030_probe, | ||
1297 | .remove = twl4030_remove, | ||
1298 | .suspend = twl4030_suspend, | ||
1299 | .resume = twl4030_resume, | ||
1300 | }; | ||
1301 | EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030); | ||
1302 | |||
1303 | static int __init twl4030_modinit(void) | ||
1304 | { | ||
1305 | return snd_soc_register_dai(&twl4030_dai); | ||
1306 | } | ||
1307 | module_init(twl4030_modinit); | ||
1308 | |||
1309 | static void __exit twl4030_exit(void) | ||
1310 | { | ||
1311 | snd_soc_unregister_dai(&twl4030_dai); | ||
1312 | } | ||
1313 | module_exit(twl4030_exit); | ||
1314 | |||
1315 | MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); | ||
1316 | MODULE_AUTHOR("Steve Sakoman"); | ||
1317 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h new file mode 100644 index 000000000000..54615c76802b --- /dev/null +++ b/sound/soc/codecs/twl4030.h | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * ALSA SoC TWL4030 codec driver | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef __TWL4030_AUDIO_H__ | ||
23 | #define __TWL4030_AUDIO_H__ | ||
24 | |||
25 | #define TWL4030_REG_CODEC_MODE 0x1 | ||
26 | #define TWL4030_REG_OPTION 0x2 | ||
27 | #define TWL4030_REG_UNKNOWN 0x3 | ||
28 | #define TWL4030_REG_MICBIAS_CTL 0x4 | ||
29 | #define TWL4030_REG_ANAMICL 0x5 | ||
30 | #define TWL4030_REG_ANAMICR 0x6 | ||
31 | #define TWL4030_REG_AVADC_CTL 0x7 | ||
32 | #define TWL4030_REG_ADCMICSEL 0x8 | ||
33 | #define TWL4030_REG_DIGMIXING 0x9 | ||
34 | #define TWL4030_REG_ATXL1PGA 0xA | ||
35 | #define TWL4030_REG_ATXR1PGA 0xB | ||
36 | #define TWL4030_REG_AVTXL2PGA 0xC | ||
37 | #define TWL4030_REG_AVTXR2PGA 0xD | ||
38 | #define TWL4030_REG_AUDIO_IF 0xE | ||
39 | #define TWL4030_REG_VOICE_IF 0xF | ||
40 | #define TWL4030_REG_ARXR1PGA 0x10 | ||
41 | #define TWL4030_REG_ARXL1PGA 0x11 | ||
42 | #define TWL4030_REG_ARXR2PGA 0x12 | ||
43 | #define TWL4030_REG_ARXL2PGA 0x13 | ||
44 | #define TWL4030_REG_VRXPGA 0x14 | ||
45 | #define TWL4030_REG_VSTPGA 0x15 | ||
46 | #define TWL4030_REG_VRX2ARXPGA 0x16 | ||
47 | #define TWL4030_REG_AVDAC_CTL 0x17 | ||
48 | #define TWL4030_REG_ARX2VTXPGA 0x18 | ||
49 | #define TWL4030_REG_ARXL1_APGA_CTL 0x19 | ||
50 | #define TWL4030_REG_ARXR1_APGA_CTL 0x1A | ||
51 | #define TWL4030_REG_ARXL2_APGA_CTL 0x1B | ||
52 | #define TWL4030_REG_ARXR2_APGA_CTL 0x1C | ||
53 | #define TWL4030_REG_ATX2ARXPGA 0x1D | ||
54 | #define TWL4030_REG_BT_IF 0x1E | ||
55 | #define TWL4030_REG_BTPGA 0x1F | ||
56 | #define TWL4030_REG_BTSTPGA 0x20 | ||
57 | #define TWL4030_REG_EAR_CTL 0x21 | ||
58 | #define TWL4030_REG_HS_SEL 0x22 | ||
59 | #define TWL4030_REG_HS_GAIN_SET 0x23 | ||
60 | #define TWL4030_REG_HS_POPN_SET 0x24 | ||
61 | #define TWL4030_REG_PREDL_CTL 0x25 | ||
62 | #define TWL4030_REG_PREDR_CTL 0x26 | ||
63 | #define TWL4030_REG_PRECKL_CTL 0x27 | ||
64 | #define TWL4030_REG_PRECKR_CTL 0x28 | ||
65 | #define TWL4030_REG_HFL_CTL 0x29 | ||
66 | #define TWL4030_REG_HFR_CTL 0x2A | ||
67 | #define TWL4030_REG_ALC_CTL 0x2B | ||
68 | #define TWL4030_REG_ALC_SET1 0x2C | ||
69 | #define TWL4030_REG_ALC_SET2 0x2D | ||
70 | #define TWL4030_REG_BOOST_CTL 0x2E | ||
71 | #define TWL4030_REG_SOFTVOL_CTL 0x2F | ||
72 | #define TWL4030_REG_DTMF_FREQSEL 0x30 | ||
73 | #define TWL4030_REG_DTMF_TONEXT1H 0x31 | ||
74 | #define TWL4030_REG_DTMF_TONEXT1L 0x32 | ||
75 | #define TWL4030_REG_DTMF_TONEXT2H 0x33 | ||
76 | #define TWL4030_REG_DTMF_TONEXT2L 0x34 | ||
77 | #define TWL4030_REG_DTMF_TONOFF 0x35 | ||
78 | #define TWL4030_REG_DTMF_WANONOFF 0x36 | ||
79 | #define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37 | ||
80 | #define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38 | ||
81 | #define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39 | ||
82 | #define TWL4030_REG_APLL_CTL 0x3A | ||
83 | #define TWL4030_REG_DTMF_CTL 0x3B | ||
84 | #define TWL4030_REG_DTMF_PGA_CTL2 0x3C | ||
85 | #define TWL4030_REG_DTMF_PGA_CTL1 0x3D | ||
86 | #define TWL4030_REG_MISC_SET_1 0x3E | ||
87 | #define TWL4030_REG_PCMBTMUX 0x3F | ||
88 | #define TWL4030_REG_RX_PATH_SEL 0x43 | ||
89 | #define TWL4030_REG_VDL_APGA_CTL 0x44 | ||
90 | #define TWL4030_REG_VIBRA_CTL 0x45 | ||
91 | #define TWL4030_REG_VIBRA_SET 0x46 | ||
92 | #define TWL4030_REG_VIBRA_PWM_SET 0x47 | ||
93 | #define TWL4030_REG_ANAMIC_GAIN 0x48 | ||
94 | #define TWL4030_REG_MISC_SET_2 0x49 | ||
95 | |||
96 | #define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1) | ||
97 | |||
98 | /* Bitfield Definitions */ | ||
99 | |||
100 | /* TWL4030_CODEC_MODE (0x01) Fields */ | ||
101 | |||
102 | #define TWL4030_APLL_RATE 0xF0 | ||
103 | #define TWL4030_APLL_RATE_8000 0x00 | ||
104 | #define TWL4030_APLL_RATE_11025 0x10 | ||
105 | #define TWL4030_APLL_RATE_12000 0x20 | ||
106 | #define TWL4030_APLL_RATE_16000 0x40 | ||
107 | #define TWL4030_APLL_RATE_22050 0x50 | ||
108 | #define TWL4030_APLL_RATE_24000 0x60 | ||
109 | #define TWL4030_APLL_RATE_32000 0x80 | ||
110 | #define TWL4030_APLL_RATE_44100 0x90 | ||
111 | #define TWL4030_APLL_RATE_48000 0xA0 | ||
112 | #define TWL4030_SEL_16K 0x04 | ||
113 | #define TWL4030_CODECPDZ 0x02 | ||
114 | #define TWL4030_OPT_MODE 0x01 | ||
115 | |||
116 | /* TWL4030_REG_MICBIAS_CTL (0x04) Fields */ | ||
117 | |||
118 | #define TWL4030_MICBIAS2_CTL 0x40 | ||
119 | #define TWL4030_MICBIAS1_CTL 0x20 | ||
120 | #define TWL4030_HSMICBIAS_EN 0x04 | ||
121 | #define TWL4030_MICBIAS2_EN 0x02 | ||
122 | #define TWL4030_MICBIAS1_EN 0x01 | ||
123 | |||
124 | /* ANAMICL (0x05) Fields */ | ||
125 | |||
126 | #define TWL4030_CNCL_OFFSET_START 0x80 | ||
127 | #define TWL4030_OFFSET_CNCL_SEL 0x60 | ||
128 | #define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00 | ||
129 | #define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20 | ||
130 | #define TWL4030_OFFSET_CNCL_SEL_VRX 0x40 | ||
131 | #define TWL4030_OFFSET_CNCL_SEL_ALL 0x60 | ||
132 | #define TWL4030_MICAMPL_EN 0x10 | ||
133 | #define TWL4030_CKMIC_EN 0x08 | ||
134 | #define TWL4030_AUXL_EN 0x04 | ||
135 | #define TWL4030_HSMIC_EN 0x02 | ||
136 | #define TWL4030_MAINMIC_EN 0x01 | ||
137 | |||
138 | /* ANAMICR (0x06) Fields */ | ||
139 | |||
140 | #define TWL4030_MICAMPR_EN 0x10 | ||
141 | #define TWL4030_AUXR_EN 0x04 | ||
142 | #define TWL4030_SUBMIC_EN 0x01 | ||
143 | |||
144 | /* AVADC_CTL (0x07) Fields */ | ||
145 | |||
146 | #define TWL4030_ADCL_EN 0x08 | ||
147 | #define TWL4030_AVADC_CLK_PRIORITY 0x04 | ||
148 | #define TWL4030_ADCR_EN 0x02 | ||
149 | |||
150 | /* AUDIO_IF (0x0E) Fields */ | ||
151 | |||
152 | #define TWL4030_AIF_SLAVE_EN 0x80 | ||
153 | #define TWL4030_DATA_WIDTH 0x60 | ||
154 | #define TWL4030_DATA_WIDTH_16S_16W 0x00 | ||
155 | #define TWL4030_DATA_WIDTH_32S_16W 0x40 | ||
156 | #define TWL4030_DATA_WIDTH_32S_24W 0x60 | ||
157 | #define TWL4030_AIF_FORMAT 0x18 | ||
158 | #define TWL4030_AIF_FORMAT_CODEC 0x00 | ||
159 | #define TWL4030_AIF_FORMAT_LEFT 0x08 | ||
160 | #define TWL4030_AIF_FORMAT_RIGHT 0x10 | ||
161 | #define TWL4030_AIF_FORMAT_TDM 0x18 | ||
162 | #define TWL4030_AIF_TRI_EN 0x04 | ||
163 | #define TWL4030_CLK256FS_EN 0x02 | ||
164 | #define TWL4030_AIF_EN 0x01 | ||
165 | |||
166 | /* HS_GAIN_SET (0x23) Fields */ | ||
167 | |||
168 | #define TWL4030_HSR_GAIN 0x0C | ||
169 | #define TWL4030_HSR_GAIN_PWR_DOWN 0x00 | ||
170 | #define TWL4030_HSR_GAIN_PLUS_6DB 0x04 | ||
171 | #define TWL4030_HSR_GAIN_0DB 0x08 | ||
172 | #define TWL4030_HSR_GAIN_MINUS_6DB 0x0C | ||
173 | #define TWL4030_HSL_GAIN 0x03 | ||
174 | #define TWL4030_HSL_GAIN_PWR_DOWN 0x00 | ||
175 | #define TWL4030_HSL_GAIN_PLUS_6DB 0x01 | ||
176 | #define TWL4030_HSL_GAIN_0DB 0x02 | ||
177 | #define TWL4030_HSL_GAIN_MINUS_6DB 0x03 | ||
178 | |||
179 | /* HS_POPN_SET (0x24) Fields */ | ||
180 | |||
181 | #define TWL4030_VMID_EN 0x40 | ||
182 | #define TWL4030_EXTMUTE 0x20 | ||
183 | #define TWL4030_RAMP_DELAY 0x1C | ||
184 | #define TWL4030_RAMP_DELAY_20MS 0x00 | ||
185 | #define TWL4030_RAMP_DELAY_40MS 0x04 | ||
186 | #define TWL4030_RAMP_DELAY_81MS 0x08 | ||
187 | #define TWL4030_RAMP_DELAY_161MS 0x0C | ||
188 | #define TWL4030_RAMP_DELAY_323MS 0x10 | ||
189 | #define TWL4030_RAMP_DELAY_645MS 0x14 | ||
190 | #define TWL4030_RAMP_DELAY_1291MS 0x18 | ||
191 | #define TWL4030_RAMP_DELAY_2581MS 0x1C | ||
192 | #define TWL4030_RAMP_EN 0x02 | ||
193 | |||
194 | /* HFL_CTL (0x29, 0x2A) Fields */ | ||
195 | #define TWL4030_HF_CTL_HB_EN 0x04 | ||
196 | #define TWL4030_HF_CTL_LOOP_EN 0x08 | ||
197 | #define TWL4030_HF_CTL_RAMP_EN 0x10 | ||
198 | #define TWL4030_HF_CTL_REF_EN 0x20 | ||
199 | |||
200 | /* APLL_CTL (0x3A) Fields */ | ||
201 | |||
202 | #define TWL4030_APLL_EN 0x10 | ||
203 | #define TWL4030_APLL_INFREQ 0x0F | ||
204 | #define TWL4030_APLL_INFREQ_19200KHZ 0x05 | ||
205 | #define TWL4030_APLL_INFREQ_26000KHZ 0x06 | ||
206 | #define TWL4030_APLL_INFREQ_38400KHZ 0x0F | ||
207 | |||
208 | /* REG_MISC_SET_1 (0x3E) Fields */ | ||
209 | |||
210 | #define TWL4030_CLK64_EN 0x80 | ||
211 | #define TWL4030_SCRAMBLE_EN 0x40 | ||
212 | #define TWL4030_FMLOOP_EN 0x20 | ||
213 | #define TWL4030_SMOOTH_ANAVOL_EN 0x02 | ||
214 | #define TWL4030_DIGMIC_LR_SWAP_EN 0x01 | ||
215 | |||
216 | extern struct snd_soc_dai twl4030_dai; | ||
217 | extern struct snd_soc_codec_device soc_codec_dev_twl4030; | ||
218 | |||
219 | #endif /* End of __TWL4030_AUDIO_H__ */ | ||
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c new file mode 100644 index 000000000000..a2c5064a774b --- /dev/null +++ b/sound/soc/codecs/uda134x.c | |||
@@ -0,0 +1,668 @@ | |||
1 | /* | ||
2 | * uda134x.c -- UDA134X ALSA SoC Codec driver | ||
3 | * | ||
4 | * Modifications by Christian Pellegrin <chripell@evolware.org> | ||
5 | * | ||
6 | * Copyright 2007 Dension Audio Systems Ltd. | ||
7 | * Author: Zoltan Devai | ||
8 | * | ||
9 | * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License version 2 as | ||
13 | * published by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/soc-dapm.h> | ||
22 | #include <sound/initval.h> | ||
23 | |||
24 | #include <sound/uda134x.h> | ||
25 | #include <sound/l3.h> | ||
26 | |||
27 | #include "uda134x.h" | ||
28 | |||
29 | |||
30 | #define POWER_OFF_ON_STANDBY 1 | ||
31 | /* | ||
32 | ALSA SOC usually puts the device in standby mode when it's not used | ||
33 | for sometime. If you define POWER_OFF_ON_STANDBY the driver will | ||
34 | turn off the ADC/DAC when this callback is invoked and turn it back | ||
35 | on when needed. Unfortunately this will result in a very light bump | ||
36 | (it can be audible only with good earphones). If this bothers you | ||
37 | just comment this line, you will have slightly higher power | ||
38 | consumption . Please note that sending the L3 command for ADC is | ||
39 | enough to make the bump, so it doesn't make difference if you | ||
40 | completely take off power from the codec. | ||
41 | */ | ||
42 | |||
43 | #define UDA134X_RATES SNDRV_PCM_RATE_8000_48000 | ||
44 | #define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \ | ||
45 | SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE) | ||
46 | |||
47 | struct uda134x_priv { | ||
48 | int sysclk; | ||
49 | int dai_fmt; | ||
50 | |||
51 | struct snd_pcm_substream *master_substream; | ||
52 | struct snd_pcm_substream *slave_substream; | ||
53 | }; | ||
54 | |||
55 | /* In-data addresses are hard-coded into the reg-cache values */ | ||
56 | static const char uda134x_reg[UDA134X_REGS_NUM] = { | ||
57 | /* Extended address registers */ | ||
58 | 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
59 | /* Status, data regs */ | ||
60 | 0x00, 0x83, 0x00, 0x40, 0x80, 0x00, | ||
61 | }; | ||
62 | |||
63 | /* | ||
64 | * The codec has no support for reading its registers except for peak level... | ||
65 | */ | ||
66 | static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec, | ||
67 | unsigned int reg) | ||
68 | { | ||
69 | u8 *cache = codec->reg_cache; | ||
70 | |||
71 | if (reg >= UDA134X_REGS_NUM) | ||
72 | return -1; | ||
73 | return cache[reg]; | ||
74 | } | ||
75 | |||
76 | /* | ||
77 | * Write the register cache | ||
78 | */ | ||
79 | static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec, | ||
80 | u8 reg, unsigned int value) | ||
81 | { | ||
82 | u8 *cache = codec->reg_cache; | ||
83 | |||
84 | if (reg >= UDA134X_REGS_NUM) | ||
85 | return; | ||
86 | cache[reg] = value; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * Write to the uda134x registers | ||
91 | * | ||
92 | */ | ||
93 | static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg, | ||
94 | unsigned int value) | ||
95 | { | ||
96 | int ret; | ||
97 | u8 addr; | ||
98 | u8 data = value; | ||
99 | struct uda134x_platform_data *pd = codec->control_data; | ||
100 | |||
101 | pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value); | ||
102 | |||
103 | if (reg >= UDA134X_REGS_NUM) { | ||
104 | printk(KERN_ERR "%s unkown register: reg: %d", | ||
105 | __func__, reg); | ||
106 | return -EINVAL; | ||
107 | } | ||
108 | |||
109 | uda134x_write_reg_cache(codec, reg, value); | ||
110 | |||
111 | switch (reg) { | ||
112 | case UDA134X_STATUS0: | ||
113 | case UDA134X_STATUS1: | ||
114 | addr = UDA134X_STATUS_ADDR; | ||
115 | break; | ||
116 | case UDA134X_DATA000: | ||
117 | case UDA134X_DATA001: | ||
118 | case UDA134X_DATA010: | ||
119 | addr = UDA134X_DATA0_ADDR; | ||
120 | break; | ||
121 | case UDA134X_DATA1: | ||
122 | addr = UDA134X_DATA1_ADDR; | ||
123 | break; | ||
124 | default: | ||
125 | /* It's an extended address register */ | ||
126 | addr = (reg | UDA134X_EXTADDR_PREFIX); | ||
127 | |||
128 | ret = l3_write(&pd->l3, | ||
129 | UDA134X_DATA0_ADDR, &addr, 1); | ||
130 | if (ret != 1) | ||
131 | return -EIO; | ||
132 | |||
133 | addr = UDA134X_DATA0_ADDR; | ||
134 | data = (value | UDA134X_EXTDATA_PREFIX); | ||
135 | break; | ||
136 | } | ||
137 | |||
138 | ret = l3_write(&pd->l3, | ||
139 | addr, &data, 1); | ||
140 | if (ret != 1) | ||
141 | return -EIO; | ||
142 | |||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static inline void uda134x_reset(struct snd_soc_codec *codec) | ||
147 | { | ||
148 | u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0); | ||
149 | uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6)); | ||
150 | msleep(1); | ||
151 | uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6)); | ||
152 | } | ||
153 | |||
154 | static int uda134x_mute(struct snd_soc_dai *dai, int mute) | ||
155 | { | ||
156 | struct snd_soc_codec *codec = dai->codec; | ||
157 | u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010); | ||
158 | |||
159 | pr_debug("%s mute: %d\n", __func__, mute); | ||
160 | |||
161 | if (mute) | ||
162 | mute_reg |= (1<<2); | ||
163 | else | ||
164 | mute_reg &= ~(1<<2); | ||
165 | |||
166 | uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2)); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int uda134x_startup(struct snd_pcm_substream *substream, | ||
172 | struct snd_soc_dai *dai) | ||
173 | { | ||
174 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
175 | struct snd_soc_device *socdev = rtd->socdev; | ||
176 | struct snd_soc_codec *codec = socdev->codec; | ||
177 | struct uda134x_priv *uda134x = codec->private_data; | ||
178 | struct snd_pcm_runtime *master_runtime; | ||
179 | |||
180 | if (uda134x->master_substream) { | ||
181 | master_runtime = uda134x->master_substream->runtime; | ||
182 | |||
183 | pr_debug("%s constraining to %d bits at %d\n", __func__, | ||
184 | master_runtime->sample_bits, | ||
185 | master_runtime->rate); | ||
186 | |||
187 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
188 | SNDRV_PCM_HW_PARAM_RATE, | ||
189 | master_runtime->rate, | ||
190 | master_runtime->rate); | ||
191 | |||
192 | snd_pcm_hw_constraint_minmax(substream->runtime, | ||
193 | SNDRV_PCM_HW_PARAM_SAMPLE_BITS, | ||
194 | master_runtime->sample_bits, | ||
195 | master_runtime->sample_bits); | ||
196 | |||
197 | uda134x->slave_substream = substream; | ||
198 | } else | ||
199 | uda134x->master_substream = substream; | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static void uda134x_shutdown(struct snd_pcm_substream *substream, | ||
205 | struct snd_soc_dai *dai) | ||
206 | { | ||
207 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
208 | struct snd_soc_device *socdev = rtd->socdev; | ||
209 | struct snd_soc_codec *codec = socdev->codec; | ||
210 | struct uda134x_priv *uda134x = codec->private_data; | ||
211 | |||
212 | if (uda134x->master_substream == substream) | ||
213 | uda134x->master_substream = uda134x->slave_substream; | ||
214 | |||
215 | uda134x->slave_substream = NULL; | ||
216 | } | ||
217 | |||
218 | static int uda134x_hw_params(struct snd_pcm_substream *substream, | ||
219 | struct snd_pcm_hw_params *params, | ||
220 | struct snd_soc_dai *dai) | ||
221 | { | ||
222 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
223 | struct snd_soc_device *socdev = rtd->socdev; | ||
224 | struct snd_soc_codec *codec = socdev->codec; | ||
225 | struct uda134x_priv *uda134x = codec->private_data; | ||
226 | u8 hw_params; | ||
227 | |||
228 | if (substream == uda134x->slave_substream) { | ||
229 | pr_debug("%s ignoring hw_params for slave substream\n", | ||
230 | __func__); | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0); | ||
235 | hw_params &= STATUS0_SYSCLK_MASK; | ||
236 | hw_params &= STATUS0_DAIFMT_MASK; | ||
237 | |||
238 | pr_debug("%s sysclk: %d, rate:%d\n", __func__, | ||
239 | uda134x->sysclk, params_rate(params)); | ||
240 | |||
241 | /* set SYSCLK / fs ratio */ | ||
242 | switch (uda134x->sysclk / params_rate(params)) { | ||
243 | case 512: | ||
244 | break; | ||
245 | case 384: | ||
246 | hw_params |= (1<<4); | ||
247 | break; | ||
248 | case 256: | ||
249 | hw_params |= (1<<5); | ||
250 | break; | ||
251 | default: | ||
252 | printk(KERN_ERR "%s unsupported fs\n", __func__); | ||
253 | return -EINVAL; | ||
254 | } | ||
255 | |||
256 | pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__, | ||
257 | uda134x->dai_fmt, params_format(params)); | ||
258 | |||
259 | /* set DAI format and word length */ | ||
260 | switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
261 | case SND_SOC_DAIFMT_I2S: | ||
262 | break; | ||
263 | case SND_SOC_DAIFMT_RIGHT_J: | ||
264 | switch (params_format(params)) { | ||
265 | case SNDRV_PCM_FORMAT_S16_LE: | ||
266 | hw_params |= (1<<1); | ||
267 | break; | ||
268 | case SNDRV_PCM_FORMAT_S18_3LE: | ||
269 | hw_params |= (1<<2); | ||
270 | break; | ||
271 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
272 | hw_params |= ((1<<2) | (1<<1)); | ||
273 | break; | ||
274 | default: | ||
275 | printk(KERN_ERR "%s unsupported format (right)\n", | ||
276 | __func__); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | break; | ||
280 | case SND_SOC_DAIFMT_LEFT_J: | ||
281 | hw_params |= (1<<3); | ||
282 | break; | ||
283 | default: | ||
284 | printk(KERN_ERR "%s unsupported format\n", __func__); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | uda134x_write(codec, UDA134X_STATUS0, hw_params); | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
294 | int clk_id, unsigned int freq, int dir) | ||
295 | { | ||
296 | struct snd_soc_codec *codec = codec_dai->codec; | ||
297 | struct uda134x_priv *uda134x = codec->private_data; | ||
298 | |||
299 | pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__, | ||
300 | clk_id, freq, dir); | ||
301 | |||
302 | /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable | ||
303 | because the codec is slave. Of course limitations of the clock | ||
304 | master (the IIS controller) apply. | ||
305 | We'll error out on set_hw_params if it's not OK */ | ||
306 | if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) { | ||
307 | uda134x->sysclk = freq; | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | printk(KERN_ERR "%s unsupported sysclk\n", __func__); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
316 | unsigned int fmt) | ||
317 | { | ||
318 | struct snd_soc_codec *codec = codec_dai->codec; | ||
319 | struct uda134x_priv *uda134x = codec->private_data; | ||
320 | |||
321 | pr_debug("%s fmt: %08X\n", __func__, fmt); | ||
322 | |||
323 | /* codec supports only full slave mode */ | ||
324 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) { | ||
325 | printk(KERN_ERR "%s unsupported slave mode\n", __func__); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | /* no support for clock inversion */ | ||
330 | if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) { | ||
331 | printk(KERN_ERR "%s unsupported clock inversion\n", __func__); | ||
332 | return -EINVAL; | ||
333 | } | ||
334 | |||
335 | /* We can't setup DAI format here as it depends on the word bit num */ | ||
336 | /* so let's just store the value for later */ | ||
337 | uda134x->dai_fmt = fmt; | ||
338 | |||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | static int uda134x_set_bias_level(struct snd_soc_codec *codec, | ||
343 | enum snd_soc_bias_level level) | ||
344 | { | ||
345 | u8 reg; | ||
346 | struct uda134x_platform_data *pd = codec->control_data; | ||
347 | int i; | ||
348 | u8 *cache = codec->reg_cache; | ||
349 | |||
350 | pr_debug("%s bias level %d\n", __func__, level); | ||
351 | |||
352 | switch (level) { | ||
353 | case SND_SOC_BIAS_ON: | ||
354 | /* ADC, DAC on */ | ||
355 | reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); | ||
356 | uda134x_write(codec, UDA134X_STATUS1, reg | 0x03); | ||
357 | break; | ||
358 | case SND_SOC_BIAS_PREPARE: | ||
359 | /* power on */ | ||
360 | if (pd->power) { | ||
361 | pd->power(1); | ||
362 | /* Sync reg_cache with the hardware */ | ||
363 | for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) | ||
364 | codec->write(codec, i, *cache++); | ||
365 | } | ||
366 | break; | ||
367 | case SND_SOC_BIAS_STANDBY: | ||
368 | /* ADC, DAC power off */ | ||
369 | reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1); | ||
370 | uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03)); | ||
371 | break; | ||
372 | case SND_SOC_BIAS_OFF: | ||
373 | /* power off */ | ||
374 | if (pd->power) | ||
375 | pd->power(0); | ||
376 | break; | ||
377 | } | ||
378 | codec->bias_level = level; | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1", | ||
383 | "Minimum2", "Maximum"}; | ||
384 | static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; | ||
385 | static const char *uda134x_mixmode[] = {"Differential", "Analog1", | ||
386 | "Analog2", "Both"}; | ||
387 | |||
388 | static const struct soc_enum uda134x_mixer_enum[] = { | ||
389 | SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting), | ||
390 | SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph), | ||
391 | SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode), | ||
392 | }; | ||
393 | |||
394 | static const struct snd_kcontrol_new uda1341_snd_controls[] = { | ||
395 | SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), | ||
396 | SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0), | ||
397 | SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1), | ||
398 | SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1), | ||
399 | |||
400 | SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0), | ||
401 | SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0), | ||
402 | |||
403 | SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), | ||
404 | SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), | ||
405 | |||
406 | SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), | ||
407 | SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), | ||
408 | SOC_ENUM("Input Mux", uda134x_mixer_enum[2]), | ||
409 | |||
410 | SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0), | ||
411 | SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1), | ||
412 | SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0), | ||
413 | |||
414 | SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0), | ||
415 | SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0), | ||
416 | SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0), | ||
417 | SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0), | ||
418 | SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0), | ||
419 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), | ||
420 | }; | ||
421 | |||
422 | static const struct snd_kcontrol_new uda1340_snd_controls[] = { | ||
423 | SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1), | ||
424 | |||
425 | SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0), | ||
426 | SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0), | ||
427 | |||
428 | SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]), | ||
429 | SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]), | ||
430 | |||
431 | SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0), | ||
432 | }; | ||
433 | |||
434 | static int uda134x_add_controls(struct snd_soc_codec *codec) | ||
435 | { | ||
436 | int err, i, n; | ||
437 | const struct snd_kcontrol_new *ctrls; | ||
438 | struct uda134x_platform_data *pd = codec->control_data; | ||
439 | |||
440 | switch (pd->model) { | ||
441 | case UDA134X_UDA1340: | ||
442 | case UDA134X_UDA1344: | ||
443 | n = ARRAY_SIZE(uda1340_snd_controls); | ||
444 | ctrls = uda1340_snd_controls; | ||
445 | break; | ||
446 | case UDA134X_UDA1341: | ||
447 | n = ARRAY_SIZE(uda1341_snd_controls); | ||
448 | ctrls = uda1341_snd_controls; | ||
449 | break; | ||
450 | default: | ||
451 | printk(KERN_ERR "%s unkown codec type: %d", | ||
452 | __func__, pd->model); | ||
453 | return -EINVAL; | ||
454 | } | ||
455 | |||
456 | for (i = 0; i < n; i++) { | ||
457 | err = snd_ctl_add(codec->card, | ||
458 | snd_soc_cnew(&ctrls[i], | ||
459 | codec, NULL)); | ||
460 | if (err < 0) | ||
461 | return err; | ||
462 | } | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | struct snd_soc_dai uda134x_dai = { | ||
468 | .name = "UDA134X", | ||
469 | /* playback capabilities */ | ||
470 | .playback = { | ||
471 | .stream_name = "Playback", | ||
472 | .channels_min = 1, | ||
473 | .channels_max = 2, | ||
474 | .rates = UDA134X_RATES, | ||
475 | .formats = UDA134X_FORMATS, | ||
476 | }, | ||
477 | /* capture capabilities */ | ||
478 | .capture = { | ||
479 | .stream_name = "Capture", | ||
480 | .channels_min = 1, | ||
481 | .channels_max = 2, | ||
482 | .rates = UDA134X_RATES, | ||
483 | .formats = UDA134X_FORMATS, | ||
484 | }, | ||
485 | /* pcm operations */ | ||
486 | .ops = { | ||
487 | .startup = uda134x_startup, | ||
488 | .shutdown = uda134x_shutdown, | ||
489 | .hw_params = uda134x_hw_params, | ||
490 | .digital_mute = uda134x_mute, | ||
491 | .set_sysclk = uda134x_set_dai_sysclk, | ||
492 | .set_fmt = uda134x_set_dai_fmt, | ||
493 | } | ||
494 | }; | ||
495 | EXPORT_SYMBOL(uda134x_dai); | ||
496 | |||
497 | |||
498 | static int uda134x_soc_probe(struct platform_device *pdev) | ||
499 | { | ||
500 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
501 | struct snd_soc_codec *codec; | ||
502 | struct uda134x_priv *uda134x; | ||
503 | void *codec_setup_data = socdev->codec_data; | ||
504 | int ret = -ENOMEM; | ||
505 | struct uda134x_platform_data *pd; | ||
506 | |||
507 | printk(KERN_INFO "UDA134X SoC Audio Codec\n"); | ||
508 | |||
509 | if (!codec_setup_data) { | ||
510 | printk(KERN_ERR "UDA134X SoC codec: " | ||
511 | "missing L3 bitbang function\n"); | ||
512 | return -ENODEV; | ||
513 | } | ||
514 | |||
515 | pd = codec_setup_data; | ||
516 | switch (pd->model) { | ||
517 | case UDA134X_UDA1340: | ||
518 | case UDA134X_UDA1341: | ||
519 | case UDA134X_UDA1344: | ||
520 | break; | ||
521 | default: | ||
522 | printk(KERN_ERR "UDA134X SoC codec: " | ||
523 | "unsupported model %d\n", | ||
524 | pd->model); | ||
525 | return -EINVAL; | ||
526 | } | ||
527 | |||
528 | socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
529 | if (socdev->codec == NULL) | ||
530 | return ret; | ||
531 | |||
532 | codec = socdev->codec; | ||
533 | |||
534 | uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); | ||
535 | if (uda134x == NULL) | ||
536 | goto priv_err; | ||
537 | codec->private_data = uda134x; | ||
538 | |||
539 | codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), | ||
540 | GFP_KERNEL); | ||
541 | if (codec->reg_cache == NULL) | ||
542 | goto reg_err; | ||
543 | |||
544 | mutex_init(&codec->mutex); | ||
545 | |||
546 | codec->reg_cache_size = sizeof(uda134x_reg); | ||
547 | codec->reg_cache_step = 1; | ||
548 | |||
549 | codec->name = "UDA134X"; | ||
550 | codec->owner = THIS_MODULE; | ||
551 | codec->dai = &uda134x_dai; | ||
552 | codec->num_dai = 1; | ||
553 | codec->read = uda134x_read_reg_cache; | ||
554 | codec->write = uda134x_write; | ||
555 | #ifdef POWER_OFF_ON_STANDBY | ||
556 | codec->set_bias_level = uda134x_set_bias_level; | ||
557 | #endif | ||
558 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
559 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
560 | |||
561 | codec->control_data = codec_setup_data; | ||
562 | |||
563 | if (pd->power) | ||
564 | pd->power(1); | ||
565 | |||
566 | uda134x_reset(codec); | ||
567 | |||
568 | /* register pcms */ | ||
569 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
570 | if (ret < 0) { | ||
571 | printk(KERN_ERR "UDA134X: failed to register pcms\n"); | ||
572 | goto pcm_err; | ||
573 | } | ||
574 | |||
575 | ret = uda134x_add_controls(codec); | ||
576 | if (ret < 0) { | ||
577 | printk(KERN_ERR "UDA134X: failed to register controls\n"); | ||
578 | goto pcm_err; | ||
579 | } | ||
580 | |||
581 | ret = snd_soc_init_card(socdev); | ||
582 | if (ret < 0) { | ||
583 | printk(KERN_ERR "UDA134X: failed to register card\n"); | ||
584 | goto card_err; | ||
585 | } | ||
586 | |||
587 | return 0; | ||
588 | |||
589 | card_err: | ||
590 | snd_soc_free_pcms(socdev); | ||
591 | snd_soc_dapm_free(socdev); | ||
592 | pcm_err: | ||
593 | kfree(codec->reg_cache); | ||
594 | reg_err: | ||
595 | kfree(codec->private_data); | ||
596 | priv_err: | ||
597 | kfree(codec); | ||
598 | return ret; | ||
599 | } | ||
600 | |||
601 | /* power down chip */ | ||
602 | static int uda134x_soc_remove(struct platform_device *pdev) | ||
603 | { | ||
604 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
605 | struct snd_soc_codec *codec = socdev->codec; | ||
606 | |||
607 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
608 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
609 | |||
610 | snd_soc_free_pcms(socdev); | ||
611 | snd_soc_dapm_free(socdev); | ||
612 | |||
613 | kfree(codec->private_data); | ||
614 | kfree(codec->reg_cache); | ||
615 | kfree(codec); | ||
616 | |||
617 | return 0; | ||
618 | } | ||
619 | |||
620 | #if defined(CONFIG_PM) | ||
621 | static int uda134x_soc_suspend(struct platform_device *pdev, | ||
622 | pm_message_t state) | ||
623 | { | ||
624 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
625 | struct snd_soc_codec *codec = socdev->codec; | ||
626 | |||
627 | uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
628 | uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
629 | return 0; | ||
630 | } | ||
631 | |||
632 | static int uda134x_soc_resume(struct platform_device *pdev) | ||
633 | { | ||
634 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
635 | struct snd_soc_codec *codec = socdev->codec; | ||
636 | |||
637 | uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
638 | uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); | ||
639 | return 0; | ||
640 | } | ||
641 | #else | ||
642 | #define uda134x_soc_suspend NULL | ||
643 | #define uda134x_soc_resume NULL | ||
644 | #endif /* CONFIG_PM */ | ||
645 | |||
646 | struct snd_soc_codec_device soc_codec_dev_uda134x = { | ||
647 | .probe = uda134x_soc_probe, | ||
648 | .remove = uda134x_soc_remove, | ||
649 | .suspend = uda134x_soc_suspend, | ||
650 | .resume = uda134x_soc_resume, | ||
651 | }; | ||
652 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x); | ||
653 | |||
654 | static int __init uda134x_init(void) | ||
655 | { | ||
656 | return snd_soc_register_dai(&uda134x_dai); | ||
657 | } | ||
658 | module_init(uda134x_init); | ||
659 | |||
660 | static void __exit uda134x_exit(void) | ||
661 | { | ||
662 | snd_soc_unregister_dai(&uda134x_dai); | ||
663 | } | ||
664 | module_exit(uda134x_exit); | ||
665 | |||
666 | MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); | ||
667 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); | ||
668 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h new file mode 100644 index 000000000000..94f440490b31 --- /dev/null +++ b/sound/soc/codecs/uda134x.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef _UDA134X_CODEC_H | ||
2 | #define _UDA134X_CODEC_H | ||
3 | |||
4 | #define UDA134X_L3ADDR 5 | ||
5 | #define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0) | ||
6 | #define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1) | ||
7 | #define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2) | ||
8 | |||
9 | #define UDA134X_EXTADDR_PREFIX 0xC0 | ||
10 | #define UDA134X_EXTDATA_PREFIX 0xE0 | ||
11 | |||
12 | /* UDA134X registers */ | ||
13 | #define UDA134X_EA000 0 | ||
14 | #define UDA134X_EA001 1 | ||
15 | #define UDA134X_EA010 2 | ||
16 | #define UDA134X_EA011 3 | ||
17 | #define UDA134X_EA100 4 | ||
18 | #define UDA134X_EA101 5 | ||
19 | #define UDA134X_EA110 6 | ||
20 | #define UDA134X_EA111 7 | ||
21 | #define UDA134X_STATUS0 8 | ||
22 | #define UDA134X_STATUS1 9 | ||
23 | #define UDA134X_DATA000 10 | ||
24 | #define UDA134X_DATA001 11 | ||
25 | #define UDA134X_DATA010 12 | ||
26 | #define UDA134X_DATA1 13 | ||
27 | |||
28 | #define UDA134X_REGS_NUM 14 | ||
29 | |||
30 | #define STATUS0_DAIFMT_MASK (~(7<<1)) | ||
31 | #define STATUS0_SYSCLK_MASK (~(3<<4)) | ||
32 | |||
33 | extern struct snd_soc_dai uda134x_dai; | ||
34 | extern struct snd_soc_codec_device soc_codec_dev_uda134x; | ||
35 | |||
36 | #endif | ||
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c index a69ee72a7af5..e6bf0844fbf3 100644 --- a/sound/soc/codecs/uda1380.c +++ b/sound/soc/codecs/uda1380.c | |||
@@ -407,7 +407,8 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
407 | * when the DAI is being clocked by the CPU DAI. It's up to the | 407 | * when the DAI is being clocked by the CPU DAI. It's up to the |
408 | * machine and cpu DAI driver to do this before we are called. | 408 | * machine and cpu DAI driver to do this before we are called. |
409 | */ | 409 | */ |
410 | static int uda1380_pcm_prepare(struct snd_pcm_substream *substream) | 410 | static int uda1380_pcm_prepare(struct snd_pcm_substream *substream, |
411 | struct snd_soc_dai *dai) | ||
411 | { | 412 | { |
412 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 413 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
413 | struct snd_soc_device *socdev = rtd->socdev; | 414 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -439,7 +440,8 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream) | |||
439 | } | 440 | } |
440 | 441 | ||
441 | static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | 442 | static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, |
442 | struct snd_pcm_hw_params *params) | 443 | struct snd_pcm_hw_params *params, |
444 | struct snd_soc_dai *dai) | ||
443 | { | 445 | { |
444 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 446 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
445 | struct snd_soc_device *socdev = rtd->socdev; | 447 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -477,7 +479,8 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream, | |||
477 | return 0; | 479 | return 0; |
478 | } | 480 | } |
479 | 481 | ||
480 | static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream) | 482 | static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream, |
483 | struct snd_soc_dai *dai) | ||
481 | { | 484 | { |
482 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 485 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
483 | struct snd_soc_device *socdev = rtd->socdev; | 486 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -560,8 +563,6 @@ struct snd_soc_dai uda1380_dai[] = { | |||
560 | .hw_params = uda1380_pcm_hw_params, | 563 | .hw_params = uda1380_pcm_hw_params, |
561 | .shutdown = uda1380_pcm_shutdown, | 564 | .shutdown = uda1380_pcm_shutdown, |
562 | .prepare = uda1380_pcm_prepare, | 565 | .prepare = uda1380_pcm_prepare, |
563 | }, | ||
564 | .dai_ops = { | ||
565 | .digital_mute = uda1380_mute, | 566 | .digital_mute = uda1380_mute, |
566 | .set_fmt = uda1380_set_dai_fmt, | 567 | .set_fmt = uda1380_set_dai_fmt, |
567 | }, | 568 | }, |
@@ -579,8 +580,6 @@ struct snd_soc_dai uda1380_dai[] = { | |||
579 | .hw_params = uda1380_pcm_hw_params, | 580 | .hw_params = uda1380_pcm_hw_params, |
580 | .shutdown = uda1380_pcm_shutdown, | 581 | .shutdown = uda1380_pcm_shutdown, |
581 | .prepare = uda1380_pcm_prepare, | 582 | .prepare = uda1380_pcm_prepare, |
582 | }, | ||
583 | .dai_ops = { | ||
584 | .digital_mute = uda1380_mute, | 583 | .digital_mute = uda1380_mute, |
585 | .set_fmt = uda1380_set_dai_fmt, | 584 | .set_fmt = uda1380_set_dai_fmt, |
586 | }, | 585 | }, |
@@ -598,8 +597,6 @@ struct snd_soc_dai uda1380_dai[] = { | |||
598 | .hw_params = uda1380_pcm_hw_params, | 597 | .hw_params = uda1380_pcm_hw_params, |
599 | .shutdown = uda1380_pcm_shutdown, | 598 | .shutdown = uda1380_pcm_shutdown, |
600 | .prepare = uda1380_pcm_prepare, | 599 | .prepare = uda1380_pcm_prepare, |
601 | }, | ||
602 | .dai_ops = { | ||
603 | .set_fmt = uda1380_set_dai_fmt, | 600 | .set_fmt = uda1380_set_dai_fmt, |
604 | }, | 601 | }, |
605 | }, | 602 | }, |
@@ -680,7 +677,7 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk) | |||
680 | /* uda1380 init */ | 677 | /* uda1380 init */ |
681 | uda1380_add_controls(codec); | 678 | uda1380_add_controls(codec); |
682 | uda1380_add_widgets(codec); | 679 | uda1380_add_widgets(codec); |
683 | ret = snd_soc_register_card(socdev); | 680 | ret = snd_soc_init_card(socdev); |
684 | if (ret < 0) { | 681 | if (ret < 0) { |
685 | pr_err("uda1380: failed to register card\n"); | 682 | pr_err("uda1380: failed to register card\n"); |
686 | goto card_err; | 683 | goto card_err; |
@@ -844,6 +841,18 @@ struct snd_soc_codec_device soc_codec_dev_uda1380 = { | |||
844 | }; | 841 | }; |
845 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); | 842 | EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380); |
846 | 843 | ||
844 | static int __init uda1380_modinit(void) | ||
845 | { | ||
846 | return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | ||
847 | } | ||
848 | module_init(uda1380_modinit); | ||
849 | |||
850 | static void __exit uda1380_exit(void) | ||
851 | { | ||
852 | snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai)); | ||
853 | } | ||
854 | module_exit(uda1380_exit); | ||
855 | |||
847 | MODULE_AUTHOR("Giorgio Padrin"); | 856 | MODULE_AUTHOR("Giorgio Padrin"); |
848 | MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); | 857 | MODULE_DESCRIPTION("Audio support for codec Philips UDA1380"); |
849 | MODULE_LICENSE("GPL"); | 858 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c new file mode 100644 index 000000000000..e3989d406f54 --- /dev/null +++ b/sound/soc/codecs/wm8350.c | |||
@@ -0,0 +1,1583 @@ | |||
1 | /* | ||
2 | * wm8350.c -- WM8350 ALSA SoC audio driver | ||
3 | * | ||
4 | * Copyright (C) 2007, 2008 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Author: Liam Girdwood <lg@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/platform_device.h> | ||
19 | #include <linux/mfd/wm8350/audio.h> | ||
20 | #include <linux/mfd/wm8350/core.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/pcm.h> | ||
24 | #include <sound/pcm_params.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dapm.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/tlv.h> | ||
29 | |||
30 | #include "wm8350.h" | ||
31 | |||
32 | #define WM8350_OUTn_0dB 0x39 | ||
33 | |||
34 | #define WM8350_RAMP_NONE 0 | ||
35 | #define WM8350_RAMP_UP 1 | ||
36 | #define WM8350_RAMP_DOWN 2 | ||
37 | |||
38 | /* We only include the analogue supplies here; the digital supplies | ||
39 | * need to be available well before this driver can be probed. | ||
40 | */ | ||
41 | static const char *supply_names[] = { | ||
42 | "AVDD", | ||
43 | "HPVDD", | ||
44 | }; | ||
45 | |||
46 | struct wm8350_output { | ||
47 | u16 active; | ||
48 | u16 left_vol; | ||
49 | u16 right_vol; | ||
50 | u16 ramp; | ||
51 | u16 mute; | ||
52 | }; | ||
53 | |||
54 | struct wm8350_data { | ||
55 | struct snd_soc_codec codec; | ||
56 | struct wm8350_output out1; | ||
57 | struct wm8350_output out2; | ||
58 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
59 | }; | ||
60 | |||
61 | static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, | ||
62 | unsigned int reg) | ||
63 | { | ||
64 | struct wm8350 *wm8350 = codec->control_data; | ||
65 | return wm8350->reg_cache[reg]; | ||
66 | } | ||
67 | |||
68 | static unsigned int wm8350_codec_read(struct snd_soc_codec *codec, | ||
69 | unsigned int reg) | ||
70 | { | ||
71 | struct wm8350 *wm8350 = codec->control_data; | ||
72 | return wm8350_reg_read(wm8350, reg); | ||
73 | } | ||
74 | |||
75 | static int wm8350_codec_write(struct snd_soc_codec *codec, unsigned int reg, | ||
76 | unsigned int value) | ||
77 | { | ||
78 | struct wm8350 *wm8350 = codec->control_data; | ||
79 | return wm8350_reg_write(wm8350, reg, value); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. | ||
84 | */ | ||
85 | static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) | ||
86 | { | ||
87 | struct wm8350_data *wm8350_data = codec->private_data; | ||
88 | struct wm8350_output *out1 = &wm8350_data->out1; | ||
89 | struct wm8350 *wm8350 = codec->control_data; | ||
90 | int left_complete = 0, right_complete = 0; | ||
91 | u16 reg, val; | ||
92 | |||
93 | /* left channel */ | ||
94 | reg = wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME); | ||
95 | val = (reg & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; | ||
96 | |||
97 | if (out1->ramp == WM8350_RAMP_UP) { | ||
98 | /* ramp step up */ | ||
99 | if (val < out1->left_vol) { | ||
100 | val++; | ||
101 | reg &= ~WM8350_OUT1L_VOL_MASK; | ||
102 | wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, | ||
103 | reg | (val << WM8350_OUT1L_VOL_SHIFT)); | ||
104 | } else | ||
105 | left_complete = 1; | ||
106 | } else if (out1->ramp == WM8350_RAMP_DOWN) { | ||
107 | /* ramp step down */ | ||
108 | if (val > 0) { | ||
109 | val--; | ||
110 | reg &= ~WM8350_OUT1L_VOL_MASK; | ||
111 | wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, | ||
112 | reg | (val << WM8350_OUT1L_VOL_SHIFT)); | ||
113 | } else | ||
114 | left_complete = 1; | ||
115 | } else | ||
116 | return 1; | ||
117 | |||
118 | /* right channel */ | ||
119 | reg = wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME); | ||
120 | val = (reg & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; | ||
121 | if (out1->ramp == WM8350_RAMP_UP) { | ||
122 | /* ramp step up */ | ||
123 | if (val < out1->right_vol) { | ||
124 | val++; | ||
125 | reg &= ~WM8350_OUT1R_VOL_MASK; | ||
126 | wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, | ||
127 | reg | (val << WM8350_OUT1R_VOL_SHIFT)); | ||
128 | } else | ||
129 | right_complete = 1; | ||
130 | } else if (out1->ramp == WM8350_RAMP_DOWN) { | ||
131 | /* ramp step down */ | ||
132 | if (val > 0) { | ||
133 | val--; | ||
134 | reg &= ~WM8350_OUT1R_VOL_MASK; | ||
135 | wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, | ||
136 | reg | (val << WM8350_OUT1R_VOL_SHIFT)); | ||
137 | } else | ||
138 | right_complete = 1; | ||
139 | } | ||
140 | |||
141 | /* only hit the update bit if either volume has changed this step */ | ||
142 | if (!left_complete || !right_complete) | ||
143 | wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU); | ||
144 | |||
145 | return left_complete & right_complete; | ||
146 | } | ||
147 | |||
148 | /* | ||
149 | * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. | ||
150 | */ | ||
151 | static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) | ||
152 | { | ||
153 | struct wm8350_data *wm8350_data = codec->private_data; | ||
154 | struct wm8350_output *out2 = &wm8350_data->out2; | ||
155 | struct wm8350 *wm8350 = codec->control_data; | ||
156 | int left_complete = 0, right_complete = 0; | ||
157 | u16 reg, val; | ||
158 | |||
159 | /* left channel */ | ||
160 | reg = wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME); | ||
161 | val = (reg & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; | ||
162 | if (out2->ramp == WM8350_RAMP_UP) { | ||
163 | /* ramp step up */ | ||
164 | if (val < out2->left_vol) { | ||
165 | val++; | ||
166 | reg &= ~WM8350_OUT2L_VOL_MASK; | ||
167 | wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, | ||
168 | reg | (val << WM8350_OUT1L_VOL_SHIFT)); | ||
169 | } else | ||
170 | left_complete = 1; | ||
171 | } else if (out2->ramp == WM8350_RAMP_DOWN) { | ||
172 | /* ramp step down */ | ||
173 | if (val > 0) { | ||
174 | val--; | ||
175 | reg &= ~WM8350_OUT2L_VOL_MASK; | ||
176 | wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, | ||
177 | reg | (val << WM8350_OUT1L_VOL_SHIFT)); | ||
178 | } else | ||
179 | left_complete = 1; | ||
180 | } else | ||
181 | return 1; | ||
182 | |||
183 | /* right channel */ | ||
184 | reg = wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME); | ||
185 | val = (reg & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; | ||
186 | if (out2->ramp == WM8350_RAMP_UP) { | ||
187 | /* ramp step up */ | ||
188 | if (val < out2->right_vol) { | ||
189 | val++; | ||
190 | reg &= ~WM8350_OUT2R_VOL_MASK; | ||
191 | wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, | ||
192 | reg | (val << WM8350_OUT1R_VOL_SHIFT)); | ||
193 | } else | ||
194 | right_complete = 1; | ||
195 | } else if (out2->ramp == WM8350_RAMP_DOWN) { | ||
196 | /* ramp step down */ | ||
197 | if (val > 0) { | ||
198 | val--; | ||
199 | reg &= ~WM8350_OUT2R_VOL_MASK; | ||
200 | wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, | ||
201 | reg | (val << WM8350_OUT1R_VOL_SHIFT)); | ||
202 | } else | ||
203 | right_complete = 1; | ||
204 | } | ||
205 | |||
206 | /* only hit the update bit if either volume has changed this step */ | ||
207 | if (!left_complete || !right_complete) | ||
208 | wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU); | ||
209 | |||
210 | return left_complete & right_complete; | ||
211 | } | ||
212 | |||
213 | /* | ||
214 | * This work ramps both output PGAs at stream start/stop time to | ||
215 | * minimise pop associated with DAPM power switching. | ||
216 | * It's best to enable Zero Cross when ramping occurs to minimise any | ||
217 | * zipper noises. | ||
218 | */ | ||
219 | static void wm8350_pga_work(struct work_struct *work) | ||
220 | { | ||
221 | struct snd_soc_codec *codec = | ||
222 | container_of(work, struct snd_soc_codec, delayed_work.work); | ||
223 | struct wm8350_data *wm8350_data = codec->private_data; | ||
224 | struct wm8350_output *out1 = &wm8350_data->out1, | ||
225 | *out2 = &wm8350_data->out2; | ||
226 | int i, out1_complete, out2_complete; | ||
227 | |||
228 | /* do we need to ramp at all ? */ | ||
229 | if (out1->ramp == WM8350_RAMP_NONE && out2->ramp == WM8350_RAMP_NONE) | ||
230 | return; | ||
231 | |||
232 | /* PGA volumes have 6 bits of resolution to ramp */ | ||
233 | for (i = 0; i <= 63; i++) { | ||
234 | out1_complete = 1, out2_complete = 1; | ||
235 | if (out1->ramp != WM8350_RAMP_NONE) | ||
236 | out1_complete = wm8350_out1_ramp_step(codec); | ||
237 | if (out2->ramp != WM8350_RAMP_NONE) | ||
238 | out2_complete = wm8350_out2_ramp_step(codec); | ||
239 | |||
240 | /* ramp finished ? */ | ||
241 | if (out1_complete && out2_complete) | ||
242 | break; | ||
243 | |||
244 | /* we need to delay longer on the up ramp */ | ||
245 | if (out1->ramp == WM8350_RAMP_UP || | ||
246 | out2->ramp == WM8350_RAMP_UP) { | ||
247 | /* delay is longer over 0dB as increases are larger */ | ||
248 | if (i >= WM8350_OUTn_0dB) | ||
249 | schedule_timeout_interruptible(msecs_to_jiffies | ||
250 | (2)); | ||
251 | else | ||
252 | schedule_timeout_interruptible(msecs_to_jiffies | ||
253 | (1)); | ||
254 | } else | ||
255 | udelay(50); /* doesn't matter if we delay longer */ | ||
256 | } | ||
257 | |||
258 | out1->ramp = WM8350_RAMP_NONE; | ||
259 | out2->ramp = WM8350_RAMP_NONE; | ||
260 | } | ||
261 | |||
262 | /* | ||
263 | * WM8350 Controls | ||
264 | */ | ||
265 | |||
266 | static int pga_event(struct snd_soc_dapm_widget *w, | ||
267 | struct snd_kcontrol *kcontrol, int event) | ||
268 | { | ||
269 | struct snd_soc_codec *codec = w->codec; | ||
270 | struct wm8350_data *wm8350_data = codec->private_data; | ||
271 | struct wm8350_output *out; | ||
272 | |||
273 | switch (w->shift) { | ||
274 | case 0: | ||
275 | case 1: | ||
276 | out = &wm8350_data->out1; | ||
277 | break; | ||
278 | case 2: | ||
279 | case 3: | ||
280 | out = &wm8350_data->out2; | ||
281 | break; | ||
282 | |||
283 | default: | ||
284 | BUG(); | ||
285 | return -1; | ||
286 | } | ||
287 | |||
288 | switch (event) { | ||
289 | case SND_SOC_DAPM_POST_PMU: | ||
290 | out->ramp = WM8350_RAMP_UP; | ||
291 | out->active = 1; | ||
292 | |||
293 | if (!delayed_work_pending(&codec->delayed_work)) | ||
294 | schedule_delayed_work(&codec->delayed_work, | ||
295 | msecs_to_jiffies(1)); | ||
296 | break; | ||
297 | |||
298 | case SND_SOC_DAPM_PRE_PMD: | ||
299 | out->ramp = WM8350_RAMP_DOWN; | ||
300 | out->active = 0; | ||
301 | |||
302 | if (!delayed_work_pending(&codec->delayed_work)) | ||
303 | schedule_delayed_work(&codec->delayed_work, | ||
304 | msecs_to_jiffies(1)); | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol, | ||
312 | struct snd_ctl_elem_value *ucontrol) | ||
313 | { | ||
314 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
315 | struct wm8350_data *wm8350_priv = codec->private_data; | ||
316 | struct wm8350_output *out = NULL; | ||
317 | struct soc_mixer_control *mc = | ||
318 | (struct soc_mixer_control *)kcontrol->private_value; | ||
319 | int ret; | ||
320 | unsigned int reg = mc->reg; | ||
321 | u16 val; | ||
322 | |||
323 | /* For OUT1 and OUT2 we shadow the values and only actually write | ||
324 | * them out when active in order to ensure the amplifier comes on | ||
325 | * as quietly as possible. */ | ||
326 | switch (reg) { | ||
327 | case WM8350_LOUT1_VOLUME: | ||
328 | out = &wm8350_priv->out1; | ||
329 | break; | ||
330 | case WM8350_LOUT2_VOLUME: | ||
331 | out = &wm8350_priv->out2; | ||
332 | break; | ||
333 | default: | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | if (out) { | ||
338 | out->left_vol = ucontrol->value.integer.value[0]; | ||
339 | out->right_vol = ucontrol->value.integer.value[1]; | ||
340 | if (!out->active) | ||
341 | return 1; | ||
342 | } | ||
343 | |||
344 | ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); | ||
345 | if (ret < 0) | ||
346 | return ret; | ||
347 | |||
348 | /* now hit the volume update bits (always bit 8) */ | ||
349 | val = wm8350_codec_read(codec, reg); | ||
350 | wm8350_codec_write(codec, reg, val | WM8350_OUT1_VU); | ||
351 | return 1; | ||
352 | } | ||
353 | |||
354 | static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol, | ||
355 | struct snd_ctl_elem_value *ucontrol) | ||
356 | { | ||
357 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
358 | struct wm8350_data *wm8350_priv = codec->private_data; | ||
359 | struct wm8350_output *out1 = &wm8350_priv->out1; | ||
360 | struct wm8350_output *out2 = &wm8350_priv->out2; | ||
361 | struct soc_mixer_control *mc = | ||
362 | (struct soc_mixer_control *)kcontrol->private_value; | ||
363 | unsigned int reg = mc->reg; | ||
364 | |||
365 | /* If these are cached registers use the cache */ | ||
366 | switch (reg) { | ||
367 | case WM8350_LOUT1_VOLUME: | ||
368 | ucontrol->value.integer.value[0] = out1->left_vol; | ||
369 | ucontrol->value.integer.value[1] = out1->right_vol; | ||
370 | return 0; | ||
371 | |||
372 | case WM8350_LOUT2_VOLUME: | ||
373 | ucontrol->value.integer.value[0] = out2->left_vol; | ||
374 | ucontrol->value.integer.value[1] = out2->right_vol; | ||
375 | return 0; | ||
376 | |||
377 | default: | ||
378 | break; | ||
379 | } | ||
380 | |||
381 | return snd_soc_get_volsw_2r(kcontrol, ucontrol); | ||
382 | } | ||
383 | |||
384 | /* double control with volume update */ | ||
385 | #define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \ | ||
386 | xinvert, tlv_array) \ | ||
387 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
388 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ | ||
389 | SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | ||
390 | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \ | ||
391 | .tlv.p = (tlv_array), \ | ||
392 | .info = snd_soc_info_volsw_2r, \ | ||
393 | .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \ | ||
394 | .private_value = (unsigned long)&(struct soc_mixer_control) \ | ||
395 | {.reg = reg_left, .rreg = reg_right, .shift = xshift, \ | ||
396 | .rshift = xshift, .max = xmax, .invert = xinvert}, } | ||
397 | |||
398 | static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; | ||
399 | static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; | ||
400 | static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; | ||
401 | static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; | ||
402 | static const char *wm8350_dacfilter[] = { "Normal", "Sloping" }; | ||
403 | static const char *wm8350_adcfilter[] = { "None", "High Pass" }; | ||
404 | static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; | ||
405 | static const char *wm8350_lr[] = { "Left", "Right" }; | ||
406 | |||
407 | static const struct soc_enum wm8350_enum[] = { | ||
408 | SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 4, 4, wm8350_deemp), | ||
409 | SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), | ||
410 | SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), | ||
411 | SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), | ||
412 | SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter), | ||
413 | SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), | ||
414 | SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), | ||
415 | SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), | ||
416 | SOC_ENUM_SINGLE(WM8350_INPUT_MIXER_VOLUME, 15, 2, wm8350_lr), | ||
417 | }; | ||
418 | |||
419 | static DECLARE_TLV_DB_LINEAR(pre_amp_tlv, -1200, 3525); | ||
420 | static DECLARE_TLV_DB_LINEAR(out_pga_tlv, -5700, 600); | ||
421 | static DECLARE_TLV_DB_SCALE(dac_pcm_tlv, -7163, 36, 1); | ||
422 | static DECLARE_TLV_DB_SCALE(adc_pcm_tlv, -12700, 50, 1); | ||
423 | static DECLARE_TLV_DB_SCALE(out_mix_tlv, -1500, 300, 1); | ||
424 | |||
425 | static const unsigned int capture_sd_tlv[] = { | ||
426 | TLV_DB_RANGE_HEAD(2), | ||
427 | 0, 12, TLV_DB_SCALE_ITEM(-3600, 300, 1), | ||
428 | 13, 15, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
429 | }; | ||
430 | |||
431 | static const struct snd_kcontrol_new wm8350_snd_controls[] = { | ||
432 | SOC_ENUM("Playback Deemphasis", wm8350_enum[0]), | ||
433 | SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]), | ||
434 | SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume", | ||
435 | WM8350_DAC_DIGITAL_VOLUME_L, | ||
436 | WM8350_DAC_DIGITAL_VOLUME_R, | ||
437 | 0, 255, 0, dac_pcm_tlv), | ||
438 | SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), | ||
439 | SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), | ||
440 | SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), | ||
441 | SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), | ||
442 | SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), | ||
443 | SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]), | ||
444 | SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", | ||
445 | WM8350_ADC_DIGITAL_VOLUME_L, | ||
446 | WM8350_ADC_DIGITAL_VOLUME_R, | ||
447 | 0, 255, 0, adc_pcm_tlv), | ||
448 | SOC_DOUBLE_TLV("Capture Sidetone Volume", | ||
449 | WM8350_ADC_DIVIDER, | ||
450 | 8, 4, 15, 1, capture_sd_tlv), | ||
451 | SOC_WM8350_DOUBLE_R_TLV("Capture Volume", | ||
452 | WM8350_LEFT_INPUT_VOLUME, | ||
453 | WM8350_RIGHT_INPUT_VOLUME, | ||
454 | 2, 63, 0, pre_amp_tlv), | ||
455 | SOC_DOUBLE_R("Capture ZC Switch", | ||
456 | WM8350_LEFT_INPUT_VOLUME, | ||
457 | WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0), | ||
458 | SOC_SINGLE_TLV("Left Input Left Sidetone Volume", | ||
459 | WM8350_OUTPUT_LEFT_MIXER_VOLUME, 1, 7, 0, out_mix_tlv), | ||
460 | SOC_SINGLE_TLV("Left Input Right Sidetone Volume", | ||
461 | WM8350_OUTPUT_LEFT_MIXER_VOLUME, | ||
462 | 5, 7, 0, out_mix_tlv), | ||
463 | SOC_SINGLE_TLV("Left Input Bypass Volume", | ||
464 | WM8350_OUTPUT_LEFT_MIXER_VOLUME, | ||
465 | 9, 7, 0, out_mix_tlv), | ||
466 | SOC_SINGLE_TLV("Right Input Left Sidetone Volume", | ||
467 | WM8350_OUTPUT_RIGHT_MIXER_VOLUME, | ||
468 | 1, 7, 0, out_mix_tlv), | ||
469 | SOC_SINGLE_TLV("Right Input Right Sidetone Volume", | ||
470 | WM8350_OUTPUT_RIGHT_MIXER_VOLUME, | ||
471 | 5, 7, 0, out_mix_tlv), | ||
472 | SOC_SINGLE_TLV("Right Input Bypass Volume", | ||
473 | WM8350_OUTPUT_RIGHT_MIXER_VOLUME, | ||
474 | 13, 7, 0, out_mix_tlv), | ||
475 | SOC_SINGLE("Left Input Mixer +20dB Switch", | ||
476 | WM8350_INPUT_MIXER_VOLUME_L, 0, 1, 0), | ||
477 | SOC_SINGLE("Right Input Mixer +20dB Switch", | ||
478 | WM8350_INPUT_MIXER_VOLUME_R, 0, 1, 0), | ||
479 | SOC_SINGLE_TLV("Out4 Capture Volume", | ||
480 | WM8350_INPUT_MIXER_VOLUME, | ||
481 | 1, 7, 0, out_mix_tlv), | ||
482 | SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume", | ||
483 | WM8350_LOUT1_VOLUME, | ||
484 | WM8350_ROUT1_VOLUME, | ||
485 | 2, 63, 0, out_pga_tlv), | ||
486 | SOC_DOUBLE_R("Out1 Playback ZC Switch", | ||
487 | WM8350_LOUT1_VOLUME, | ||
488 | WM8350_ROUT1_VOLUME, 13, 1, 0), | ||
489 | SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume", | ||
490 | WM8350_LOUT2_VOLUME, | ||
491 | WM8350_ROUT2_VOLUME, | ||
492 | 2, 63, 0, out_pga_tlv), | ||
493 | SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME, | ||
494 | WM8350_ROUT2_VOLUME, 13, 1, 0), | ||
495 | SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0), | ||
496 | SOC_SINGLE_TLV("Out2 Beep Volume", WM8350_BEEP_VOLUME, | ||
497 | 5, 7, 0, out_mix_tlv), | ||
498 | |||
499 | SOC_DOUBLE_R("Out1 Playback Switch", | ||
500 | WM8350_LOUT1_VOLUME, | ||
501 | WM8350_ROUT1_VOLUME, | ||
502 | 14, 1, 1), | ||
503 | SOC_DOUBLE_R("Out2 Playback Switch", | ||
504 | WM8350_LOUT2_VOLUME, | ||
505 | WM8350_ROUT2_VOLUME, | ||
506 | 14, 1, 1), | ||
507 | }; | ||
508 | |||
509 | /* | ||
510 | * DAPM Controls | ||
511 | */ | ||
512 | |||
513 | /* Left Playback Mixer */ | ||
514 | static const struct snd_kcontrol_new wm8350_left_play_mixer_controls[] = { | ||
515 | SOC_DAPM_SINGLE("Playback Switch", | ||
516 | WM8350_LEFT_MIXER_CONTROL, 11, 1, 0), | ||
517 | SOC_DAPM_SINGLE("Left Bypass Switch", | ||
518 | WM8350_LEFT_MIXER_CONTROL, 2, 1, 0), | ||
519 | SOC_DAPM_SINGLE("Right Playback Switch", | ||
520 | WM8350_LEFT_MIXER_CONTROL, 12, 1, 0), | ||
521 | SOC_DAPM_SINGLE("Left Sidetone Switch", | ||
522 | WM8350_LEFT_MIXER_CONTROL, 0, 1, 0), | ||
523 | SOC_DAPM_SINGLE("Right Sidetone Switch", | ||
524 | WM8350_LEFT_MIXER_CONTROL, 1, 1, 0), | ||
525 | }; | ||
526 | |||
527 | /* Right Playback Mixer */ | ||
528 | static const struct snd_kcontrol_new wm8350_right_play_mixer_controls[] = { | ||
529 | SOC_DAPM_SINGLE("Playback Switch", | ||
530 | WM8350_RIGHT_MIXER_CONTROL, 12, 1, 0), | ||
531 | SOC_DAPM_SINGLE("Right Bypass Switch", | ||
532 | WM8350_RIGHT_MIXER_CONTROL, 3, 1, 0), | ||
533 | SOC_DAPM_SINGLE("Left Playback Switch", | ||
534 | WM8350_RIGHT_MIXER_CONTROL, 11, 1, 0), | ||
535 | SOC_DAPM_SINGLE("Left Sidetone Switch", | ||
536 | WM8350_RIGHT_MIXER_CONTROL, 0, 1, 0), | ||
537 | SOC_DAPM_SINGLE("Right Sidetone Switch", | ||
538 | WM8350_RIGHT_MIXER_CONTROL, 1, 1, 0), | ||
539 | }; | ||
540 | |||
541 | /* Out4 Mixer */ | ||
542 | static const struct snd_kcontrol_new wm8350_out4_mixer_controls[] = { | ||
543 | SOC_DAPM_SINGLE("Right Playback Switch", | ||
544 | WM8350_OUT4_MIXER_CONTROL, 12, 1, 0), | ||
545 | SOC_DAPM_SINGLE("Left Playback Switch", | ||
546 | WM8350_OUT4_MIXER_CONTROL, 11, 1, 0), | ||
547 | SOC_DAPM_SINGLE("Right Capture Switch", | ||
548 | WM8350_OUT4_MIXER_CONTROL, 9, 1, 0), | ||
549 | SOC_DAPM_SINGLE("Out3 Playback Switch", | ||
550 | WM8350_OUT4_MIXER_CONTROL, 2, 1, 0), | ||
551 | SOC_DAPM_SINGLE("Right Mixer Switch", | ||
552 | WM8350_OUT4_MIXER_CONTROL, 1, 1, 0), | ||
553 | SOC_DAPM_SINGLE("Left Mixer Switch", | ||
554 | WM8350_OUT4_MIXER_CONTROL, 0, 1, 0), | ||
555 | }; | ||
556 | |||
557 | /* Out3 Mixer */ | ||
558 | static const struct snd_kcontrol_new wm8350_out3_mixer_controls[] = { | ||
559 | SOC_DAPM_SINGLE("Left Playback Switch", | ||
560 | WM8350_OUT3_MIXER_CONTROL, 11, 1, 0), | ||
561 | SOC_DAPM_SINGLE("Left Capture Switch", | ||
562 | WM8350_OUT3_MIXER_CONTROL, 8, 1, 0), | ||
563 | SOC_DAPM_SINGLE("Out4 Playback Switch", | ||
564 | WM8350_OUT3_MIXER_CONTROL, 3, 1, 0), | ||
565 | SOC_DAPM_SINGLE("Left Mixer Switch", | ||
566 | WM8350_OUT3_MIXER_CONTROL, 0, 1, 0), | ||
567 | }; | ||
568 | |||
569 | /* Left Input Mixer */ | ||
570 | static const struct snd_kcontrol_new wm8350_left_capt_mixer_controls[] = { | ||
571 | SOC_DAPM_SINGLE_TLV("L2 Capture Volume", | ||
572 | WM8350_INPUT_MIXER_VOLUME_L, 1, 7, 0, out_mix_tlv), | ||
573 | SOC_DAPM_SINGLE_TLV("L3 Capture Volume", | ||
574 | WM8350_INPUT_MIXER_VOLUME_L, 9, 7, 0, out_mix_tlv), | ||
575 | SOC_DAPM_SINGLE("PGA Capture Switch", | ||
576 | WM8350_LEFT_INPUT_VOLUME, 14, 1, 0), | ||
577 | }; | ||
578 | |||
579 | /* Right Input Mixer */ | ||
580 | static const struct snd_kcontrol_new wm8350_right_capt_mixer_controls[] = { | ||
581 | SOC_DAPM_SINGLE_TLV("L2 Capture Volume", | ||
582 | WM8350_INPUT_MIXER_VOLUME_R, 5, 7, 0, out_mix_tlv), | ||
583 | SOC_DAPM_SINGLE_TLV("L3 Capture Volume", | ||
584 | WM8350_INPUT_MIXER_VOLUME_R, 13, 7, 0, out_mix_tlv), | ||
585 | SOC_DAPM_SINGLE("PGA Capture Switch", | ||
586 | WM8350_RIGHT_INPUT_VOLUME, 14, 1, 0), | ||
587 | }; | ||
588 | |||
589 | /* Left Mic Mixer */ | ||
590 | static const struct snd_kcontrol_new wm8350_left_mic_mixer_controls[] = { | ||
591 | SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 1, 1, 0), | ||
592 | SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 0, 1, 0), | ||
593 | SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 2, 1, 0), | ||
594 | }; | ||
595 | |||
596 | /* Right Mic Mixer */ | ||
597 | static const struct snd_kcontrol_new wm8350_right_mic_mixer_controls[] = { | ||
598 | SOC_DAPM_SINGLE("INN Capture Switch", WM8350_INPUT_CONTROL, 9, 1, 0), | ||
599 | SOC_DAPM_SINGLE("INP Capture Switch", WM8350_INPUT_CONTROL, 8, 1, 0), | ||
600 | SOC_DAPM_SINGLE("IN2 Capture Switch", WM8350_INPUT_CONTROL, 10, 1, 0), | ||
601 | }; | ||
602 | |||
603 | /* Beep Switch */ | ||
604 | static const struct snd_kcontrol_new wm8350_beep_switch_controls = | ||
605 | SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1); | ||
606 | |||
607 | /* Out4 Capture Mux */ | ||
608 | static const struct snd_kcontrol_new wm8350_out4_capture_controls = | ||
609 | SOC_DAPM_ENUM("Route", wm8350_enum[8]); | ||
610 | |||
611 | static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { | ||
612 | |||
613 | SND_SOC_DAPM_PGA("IN3R PGA", WM8350_POWER_MGMT_2, 11, 0, NULL, 0), | ||
614 | SND_SOC_DAPM_PGA("IN3L PGA", WM8350_POWER_MGMT_2, 10, 0, NULL, 0), | ||
615 | SND_SOC_DAPM_PGA_E("Right Out2 PGA", WM8350_POWER_MGMT_3, 3, 0, NULL, | ||
616 | 0, pga_event, | ||
617 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
618 | SND_SOC_DAPM_PGA_E("Left Out2 PGA", WM8350_POWER_MGMT_3, 2, 0, NULL, 0, | ||
619 | pga_event, | ||
620 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
621 | SND_SOC_DAPM_PGA_E("Right Out1 PGA", WM8350_POWER_MGMT_3, 1, 0, NULL, | ||
622 | 0, pga_event, | ||
623 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
624 | SND_SOC_DAPM_PGA_E("Left Out1 PGA", WM8350_POWER_MGMT_3, 0, 0, NULL, 0, | ||
625 | pga_event, | ||
626 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
627 | |||
628 | SND_SOC_DAPM_MIXER("Right Capture Mixer", WM8350_POWER_MGMT_2, | ||
629 | 7, 0, &wm8350_right_capt_mixer_controls[0], | ||
630 | ARRAY_SIZE(wm8350_right_capt_mixer_controls)), | ||
631 | |||
632 | SND_SOC_DAPM_MIXER("Left Capture Mixer", WM8350_POWER_MGMT_2, | ||
633 | 6, 0, &wm8350_left_capt_mixer_controls[0], | ||
634 | ARRAY_SIZE(wm8350_left_capt_mixer_controls)), | ||
635 | |||
636 | SND_SOC_DAPM_MIXER("Out4 Mixer", WM8350_POWER_MGMT_2, 5, 0, | ||
637 | &wm8350_out4_mixer_controls[0], | ||
638 | ARRAY_SIZE(wm8350_out4_mixer_controls)), | ||
639 | |||
640 | SND_SOC_DAPM_MIXER("Out3 Mixer", WM8350_POWER_MGMT_2, 4, 0, | ||
641 | &wm8350_out3_mixer_controls[0], | ||
642 | ARRAY_SIZE(wm8350_out3_mixer_controls)), | ||
643 | |||
644 | SND_SOC_DAPM_MIXER("Right Playback Mixer", WM8350_POWER_MGMT_2, 1, 0, | ||
645 | &wm8350_right_play_mixer_controls[0], | ||
646 | ARRAY_SIZE(wm8350_right_play_mixer_controls)), | ||
647 | |||
648 | SND_SOC_DAPM_MIXER("Left Playback Mixer", WM8350_POWER_MGMT_2, 0, 0, | ||
649 | &wm8350_left_play_mixer_controls[0], | ||
650 | ARRAY_SIZE(wm8350_left_play_mixer_controls)), | ||
651 | |||
652 | SND_SOC_DAPM_MIXER("Left Mic Mixer", WM8350_POWER_MGMT_2, 8, 0, | ||
653 | &wm8350_left_mic_mixer_controls[0], | ||
654 | ARRAY_SIZE(wm8350_left_mic_mixer_controls)), | ||
655 | |||
656 | SND_SOC_DAPM_MIXER("Right Mic Mixer", WM8350_POWER_MGMT_2, 9, 0, | ||
657 | &wm8350_right_mic_mixer_controls[0], | ||
658 | ARRAY_SIZE(wm8350_right_mic_mixer_controls)), | ||
659 | |||
660 | /* virtual mixer for Beep and Out2R */ | ||
661 | SND_SOC_DAPM_MIXER("Out2 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
662 | |||
663 | SND_SOC_DAPM_SWITCH("Beep", WM8350_POWER_MGMT_3, 7, 0, | ||
664 | &wm8350_beep_switch_controls), | ||
665 | |||
666 | SND_SOC_DAPM_ADC("Right ADC", "Right Capture", | ||
667 | WM8350_POWER_MGMT_4, 3, 0), | ||
668 | SND_SOC_DAPM_ADC("Left ADC", "Left Capture", | ||
669 | WM8350_POWER_MGMT_4, 2, 0), | ||
670 | SND_SOC_DAPM_DAC("Right DAC", "Right Playback", | ||
671 | WM8350_POWER_MGMT_4, 5, 0), | ||
672 | SND_SOC_DAPM_DAC("Left DAC", "Left Playback", | ||
673 | WM8350_POWER_MGMT_4, 4, 0), | ||
674 | |||
675 | SND_SOC_DAPM_MICBIAS("Mic Bias", WM8350_POWER_MGMT_1, 4, 0), | ||
676 | |||
677 | SND_SOC_DAPM_MUX("Out4 Capture Channel", SND_SOC_NOPM, 0, 0, | ||
678 | &wm8350_out4_capture_controls), | ||
679 | |||
680 | SND_SOC_DAPM_OUTPUT("OUT1R"), | ||
681 | SND_SOC_DAPM_OUTPUT("OUT1L"), | ||
682 | SND_SOC_DAPM_OUTPUT("OUT2R"), | ||
683 | SND_SOC_DAPM_OUTPUT("OUT2L"), | ||
684 | SND_SOC_DAPM_OUTPUT("OUT3"), | ||
685 | SND_SOC_DAPM_OUTPUT("OUT4"), | ||
686 | |||
687 | SND_SOC_DAPM_INPUT("IN1RN"), | ||
688 | SND_SOC_DAPM_INPUT("IN1RP"), | ||
689 | SND_SOC_DAPM_INPUT("IN2R"), | ||
690 | SND_SOC_DAPM_INPUT("IN1LP"), | ||
691 | SND_SOC_DAPM_INPUT("IN1LN"), | ||
692 | SND_SOC_DAPM_INPUT("IN2L"), | ||
693 | SND_SOC_DAPM_INPUT("IN3R"), | ||
694 | SND_SOC_DAPM_INPUT("IN3L"), | ||
695 | }; | ||
696 | |||
697 | static const struct snd_soc_dapm_route audio_map[] = { | ||
698 | |||
699 | /* left playback mixer */ | ||
700 | {"Left Playback Mixer", "Playback Switch", "Left DAC"}, | ||
701 | {"Left Playback Mixer", "Left Bypass Switch", "IN3L PGA"}, | ||
702 | {"Left Playback Mixer", "Right Playback Switch", "Right DAC"}, | ||
703 | {"Left Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"}, | ||
704 | {"Left Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"}, | ||
705 | |||
706 | /* right playback mixer */ | ||
707 | {"Right Playback Mixer", "Playback Switch", "Right DAC"}, | ||
708 | {"Right Playback Mixer", "Right Bypass Switch", "IN3R PGA"}, | ||
709 | {"Right Playback Mixer", "Left Playback Switch", "Left DAC"}, | ||
710 | {"Right Playback Mixer", "Left Sidetone Switch", "Left Mic Mixer"}, | ||
711 | {"Right Playback Mixer", "Right Sidetone Switch", "Right Mic Mixer"}, | ||
712 | |||
713 | /* out4 playback mixer */ | ||
714 | {"Out4 Mixer", "Right Playback Switch", "Right DAC"}, | ||
715 | {"Out4 Mixer", "Left Playback Switch", "Left DAC"}, | ||
716 | {"Out4 Mixer", "Right Capture Switch", "Right Capture Mixer"}, | ||
717 | {"Out4 Mixer", "Out3 Playback Switch", "Out3 Mixer"}, | ||
718 | {"Out4 Mixer", "Right Mixer Switch", "Right Playback Mixer"}, | ||
719 | {"Out4 Mixer", "Left Mixer Switch", "Left Playback Mixer"}, | ||
720 | {"OUT4", NULL, "Out4 Mixer"}, | ||
721 | |||
722 | /* out3 playback mixer */ | ||
723 | {"Out3 Mixer", "Left Playback Switch", "Left DAC"}, | ||
724 | {"Out3 Mixer", "Left Capture Switch", "Left Capture Mixer"}, | ||
725 | {"Out3 Mixer", "Left Mixer Switch", "Left Playback Mixer"}, | ||
726 | {"Out3 Mixer", "Out4 Playback Switch", "Out4 Mixer"}, | ||
727 | {"OUT3", NULL, "Out3 Mixer"}, | ||
728 | |||
729 | /* out2 */ | ||
730 | {"Right Out2 PGA", NULL, "Right Playback Mixer"}, | ||
731 | {"Left Out2 PGA", NULL, "Left Playback Mixer"}, | ||
732 | {"OUT2L", NULL, "Left Out2 PGA"}, | ||
733 | {"OUT2R", NULL, "Right Out2 PGA"}, | ||
734 | |||
735 | /* out1 */ | ||
736 | {"Right Out1 PGA", NULL, "Right Playback Mixer"}, | ||
737 | {"Left Out1 PGA", NULL, "Left Playback Mixer"}, | ||
738 | {"OUT1L", NULL, "Left Out1 PGA"}, | ||
739 | {"OUT1R", NULL, "Right Out1 PGA"}, | ||
740 | |||
741 | /* ADCs */ | ||
742 | {"Left ADC", NULL, "Left Capture Mixer"}, | ||
743 | {"Right ADC", NULL, "Right Capture Mixer"}, | ||
744 | |||
745 | /* Left capture mixer */ | ||
746 | {"Left Capture Mixer", "L2 Capture Volume", "IN2L"}, | ||
747 | {"Left Capture Mixer", "L3 Capture Volume", "IN3L PGA"}, | ||
748 | {"Left Capture Mixer", "PGA Capture Switch", "Left Mic Mixer"}, | ||
749 | {"Left Capture Mixer", NULL, "Out4 Capture Channel"}, | ||
750 | |||
751 | /* Right capture mixer */ | ||
752 | {"Right Capture Mixer", "L2 Capture Volume", "IN2R"}, | ||
753 | {"Right Capture Mixer", "L3 Capture Volume", "IN3R PGA"}, | ||
754 | {"Right Capture Mixer", "PGA Capture Switch", "Right Mic Mixer"}, | ||
755 | {"Right Capture Mixer", NULL, "Out4 Capture Channel"}, | ||
756 | |||
757 | /* L3 Inputs */ | ||
758 | {"IN3L PGA", NULL, "IN3L"}, | ||
759 | {"IN3R PGA", NULL, "IN3R"}, | ||
760 | |||
761 | /* Left Mic mixer */ | ||
762 | {"Left Mic Mixer", "INN Capture Switch", "IN1LN"}, | ||
763 | {"Left Mic Mixer", "INP Capture Switch", "IN1LP"}, | ||
764 | {"Left Mic Mixer", "IN2 Capture Switch", "IN2L"}, | ||
765 | |||
766 | /* Right Mic mixer */ | ||
767 | {"Right Mic Mixer", "INN Capture Switch", "IN1RN"}, | ||
768 | {"Right Mic Mixer", "INP Capture Switch", "IN1RP"}, | ||
769 | {"Right Mic Mixer", "IN2 Capture Switch", "IN2R"}, | ||
770 | |||
771 | /* out 4 capture */ | ||
772 | {"Out4 Capture Channel", NULL, "Out4 Mixer"}, | ||
773 | |||
774 | /* Beep */ | ||
775 | {"Beep", NULL, "IN3R PGA"}, | ||
776 | }; | ||
777 | |||
778 | static int wm8350_add_controls(struct snd_soc_codec *codec) | ||
779 | { | ||
780 | int err, i; | ||
781 | |||
782 | for (i = 0; i < ARRAY_SIZE(wm8350_snd_controls); i++) { | ||
783 | err = snd_ctl_add(codec->card, | ||
784 | snd_soc_cnew(&wm8350_snd_controls[i], | ||
785 | codec, NULL)); | ||
786 | if (err < 0) | ||
787 | return err; | ||
788 | } | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int wm8350_add_widgets(struct snd_soc_codec *codec) | ||
794 | { | ||
795 | int ret; | ||
796 | |||
797 | ret = snd_soc_dapm_new_controls(codec, | ||
798 | wm8350_dapm_widgets, | ||
799 | ARRAY_SIZE(wm8350_dapm_widgets)); | ||
800 | if (ret != 0) { | ||
801 | dev_err(codec->dev, "dapm control register failed\n"); | ||
802 | return ret; | ||
803 | } | ||
804 | |||
805 | /* set up audio paths */ | ||
806 | ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
807 | if (ret != 0) { | ||
808 | dev_err(codec->dev, "DAPM route register failed\n"); | ||
809 | return ret; | ||
810 | } | ||
811 | |||
812 | return snd_soc_dapm_new_widgets(codec); | ||
813 | } | ||
814 | |||
815 | static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, | ||
816 | int clk_id, unsigned int freq, int dir) | ||
817 | { | ||
818 | struct snd_soc_codec *codec = codec_dai->codec; | ||
819 | struct wm8350 *wm8350 = codec->control_data; | ||
820 | u16 fll_4; | ||
821 | |||
822 | switch (clk_id) { | ||
823 | case WM8350_MCLK_SEL_MCLK: | ||
824 | wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_1, | ||
825 | WM8350_MCLK_SEL); | ||
826 | break; | ||
827 | case WM8350_MCLK_SEL_PLL_MCLK: | ||
828 | case WM8350_MCLK_SEL_PLL_DAC: | ||
829 | case WM8350_MCLK_SEL_PLL_ADC: | ||
830 | case WM8350_MCLK_SEL_PLL_32K: | ||
831 | wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_1, | ||
832 | WM8350_MCLK_SEL); | ||
833 | fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & | ||
834 | ~WM8350_FLL_CLK_SRC_MASK; | ||
835 | wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, fll_4 | clk_id); | ||
836 | break; | ||
837 | } | ||
838 | |||
839 | /* MCLK direction */ | ||
840 | if (dir == WM8350_MCLK_DIR_OUT) | ||
841 | wm8350_set_bits(wm8350, WM8350_CLOCK_CONTROL_2, | ||
842 | WM8350_MCLK_DIR); | ||
843 | else | ||
844 | wm8350_clear_bits(wm8350, WM8350_CLOCK_CONTROL_2, | ||
845 | WM8350_MCLK_DIR); | ||
846 | |||
847 | return 0; | ||
848 | } | ||
849 | |||
850 | static int wm8350_set_clkdiv(struct snd_soc_dai *codec_dai, int div_id, int div) | ||
851 | { | ||
852 | struct snd_soc_codec *codec = codec_dai->codec; | ||
853 | u16 val; | ||
854 | |||
855 | switch (div_id) { | ||
856 | case WM8350_ADC_CLKDIV: | ||
857 | val = wm8350_codec_read(codec, WM8350_ADC_DIVIDER) & | ||
858 | ~WM8350_ADC_CLKDIV_MASK; | ||
859 | wm8350_codec_write(codec, WM8350_ADC_DIVIDER, val | div); | ||
860 | break; | ||
861 | case WM8350_DAC_CLKDIV: | ||
862 | val = wm8350_codec_read(codec, WM8350_DAC_CLOCK_CONTROL) & | ||
863 | ~WM8350_DAC_CLKDIV_MASK; | ||
864 | wm8350_codec_write(codec, WM8350_DAC_CLOCK_CONTROL, val | div); | ||
865 | break; | ||
866 | case WM8350_BCLK_CLKDIV: | ||
867 | val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & | ||
868 | ~WM8350_BCLK_DIV_MASK; | ||
869 | wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); | ||
870 | break; | ||
871 | case WM8350_OPCLK_CLKDIV: | ||
872 | val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & | ||
873 | ~WM8350_OPCLK_DIV_MASK; | ||
874 | wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); | ||
875 | break; | ||
876 | case WM8350_SYS_CLKDIV: | ||
877 | val = wm8350_codec_read(codec, WM8350_CLOCK_CONTROL_1) & | ||
878 | ~WM8350_MCLK_DIV_MASK; | ||
879 | wm8350_codec_write(codec, WM8350_CLOCK_CONTROL_1, val | div); | ||
880 | break; | ||
881 | case WM8350_DACLR_CLKDIV: | ||
882 | val = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) & | ||
883 | ~WM8350_DACLRC_RATE_MASK; | ||
884 | wm8350_codec_write(codec, WM8350_DAC_LR_RATE, val | div); | ||
885 | break; | ||
886 | case WM8350_ADCLR_CLKDIV: | ||
887 | val = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) & | ||
888 | ~WM8350_ADCLRC_RATE_MASK; | ||
889 | wm8350_codec_write(codec, WM8350_ADC_LR_RATE, val | div); | ||
890 | break; | ||
891 | default: | ||
892 | return -EINVAL; | ||
893 | } | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static int wm8350_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | ||
899 | { | ||
900 | struct snd_soc_codec *codec = codec_dai->codec; | ||
901 | u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & | ||
902 | ~(WM8350_AIF_BCLK_INV | WM8350_AIF_LRCLK_INV | WM8350_AIF_FMT_MASK); | ||
903 | u16 master = wm8350_codec_read(codec, WM8350_AI_DAC_CONTROL) & | ||
904 | ~WM8350_BCLK_MSTR; | ||
905 | u16 dac_lrc = wm8350_codec_read(codec, WM8350_DAC_LR_RATE) & | ||
906 | ~WM8350_DACLRC_ENA; | ||
907 | u16 adc_lrc = wm8350_codec_read(codec, WM8350_ADC_LR_RATE) & | ||
908 | ~WM8350_ADCLRC_ENA; | ||
909 | |||
910 | /* set master/slave audio interface */ | ||
911 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
912 | case SND_SOC_DAIFMT_CBM_CFM: | ||
913 | master |= WM8350_BCLK_MSTR; | ||
914 | dac_lrc |= WM8350_DACLRC_ENA; | ||
915 | adc_lrc |= WM8350_ADCLRC_ENA; | ||
916 | break; | ||
917 | case SND_SOC_DAIFMT_CBS_CFS: | ||
918 | break; | ||
919 | default: | ||
920 | return -EINVAL; | ||
921 | } | ||
922 | |||
923 | /* interface format */ | ||
924 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
925 | case SND_SOC_DAIFMT_I2S: | ||
926 | iface |= 0x2 << 8; | ||
927 | break; | ||
928 | case SND_SOC_DAIFMT_RIGHT_J: | ||
929 | break; | ||
930 | case SND_SOC_DAIFMT_LEFT_J: | ||
931 | iface |= 0x1 << 8; | ||
932 | break; | ||
933 | case SND_SOC_DAIFMT_DSP_A: | ||
934 | iface |= 0x3 << 8; | ||
935 | break; | ||
936 | case SND_SOC_DAIFMT_DSP_B: | ||
937 | iface |= 0x3 << 8; /* lg not sure which mode */ | ||
938 | break; | ||
939 | default: | ||
940 | return -EINVAL; | ||
941 | } | ||
942 | |||
943 | /* clock inversion */ | ||
944 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
945 | case SND_SOC_DAIFMT_NB_NF: | ||
946 | break; | ||
947 | case SND_SOC_DAIFMT_IB_IF: | ||
948 | iface |= WM8350_AIF_LRCLK_INV | WM8350_AIF_BCLK_INV; | ||
949 | break; | ||
950 | case SND_SOC_DAIFMT_IB_NF: | ||
951 | iface |= WM8350_AIF_BCLK_INV; | ||
952 | break; | ||
953 | case SND_SOC_DAIFMT_NB_IF: | ||
954 | iface |= WM8350_AIF_LRCLK_INV; | ||
955 | break; | ||
956 | default: | ||
957 | return -EINVAL; | ||
958 | } | ||
959 | |||
960 | wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); | ||
961 | wm8350_codec_write(codec, WM8350_AI_DAC_CONTROL, master); | ||
962 | wm8350_codec_write(codec, WM8350_DAC_LR_RATE, dac_lrc); | ||
963 | wm8350_codec_write(codec, WM8350_ADC_LR_RATE, adc_lrc); | ||
964 | return 0; | ||
965 | } | ||
966 | |||
967 | static int wm8350_pcm_trigger(struct snd_pcm_substream *substream, | ||
968 | int cmd, struct snd_soc_dai *codec_dai) | ||
969 | { | ||
970 | struct snd_soc_codec *codec = codec_dai->codec; | ||
971 | int master = wm8350_codec_cache_read(codec, WM8350_AI_DAC_CONTROL) & | ||
972 | WM8350_BCLK_MSTR; | ||
973 | int enabled = 0; | ||
974 | |||
975 | /* Check that the DACs or ADCs are enabled since they are | ||
976 | * required for LRC in master mode. The DACs or ADCs need a | ||
977 | * valid audio path i.e. pin -> ADC or DAC -> pin before | ||
978 | * the LRC will be enabled in master mode. */ | ||
979 | if (!master && cmd != SNDRV_PCM_TRIGGER_START) | ||
980 | return 0; | ||
981 | |||
982 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { | ||
983 | enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) & | ||
984 | (WM8350_ADCR_ENA | WM8350_ADCL_ENA); | ||
985 | } else { | ||
986 | enabled = wm8350_codec_cache_read(codec, WM8350_POWER_MGMT_4) & | ||
987 | (WM8350_DACR_ENA | WM8350_DACL_ENA); | ||
988 | } | ||
989 | |||
990 | if (!enabled) { | ||
991 | dev_err(codec->dev, | ||
992 | "%s: invalid audio path - no clocks available\n", | ||
993 | __func__); | ||
994 | return -EINVAL; | ||
995 | } | ||
996 | return 0; | ||
997 | } | ||
998 | |||
999 | static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream, | ||
1000 | struct snd_pcm_hw_params *params, | ||
1001 | struct snd_soc_dai *codec_dai) | ||
1002 | { | ||
1003 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1004 | u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & | ||
1005 | ~WM8350_AIF_WL_MASK; | ||
1006 | |||
1007 | /* bit size */ | ||
1008 | switch (params_format(params)) { | ||
1009 | case SNDRV_PCM_FORMAT_S16_LE: | ||
1010 | break; | ||
1011 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
1012 | iface |= 0x1 << 10; | ||
1013 | break; | ||
1014 | case SNDRV_PCM_FORMAT_S24_LE: | ||
1015 | iface |= 0x2 << 10; | ||
1016 | break; | ||
1017 | case SNDRV_PCM_FORMAT_S32_LE: | ||
1018 | iface |= 0x3 << 10; | ||
1019 | break; | ||
1020 | } | ||
1021 | |||
1022 | wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | static int wm8350_mute(struct snd_soc_dai *dai, int mute) | ||
1027 | { | ||
1028 | struct snd_soc_codec *codec = dai->codec; | ||
1029 | struct wm8350 *wm8350 = codec->control_data; | ||
1030 | |||
1031 | if (mute) | ||
1032 | wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); | ||
1033 | else | ||
1034 | wm8350_clear_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); | ||
1035 | return 0; | ||
1036 | } | ||
1037 | |||
1038 | /* FLL divisors */ | ||
1039 | struct _fll_div { | ||
1040 | int div; /* FLL_OUTDIV */ | ||
1041 | int n; | ||
1042 | int k; | ||
1043 | int ratio; /* FLL_FRATIO */ | ||
1044 | }; | ||
1045 | |||
1046 | /* The size in bits of the fll divide multiplied by 10 | ||
1047 | * to allow rounding later */ | ||
1048 | #define FIXED_FLL_SIZE ((1 << 16) * 10) | ||
1049 | |||
1050 | static inline int fll_factors(struct _fll_div *fll_div, unsigned int input, | ||
1051 | unsigned int output) | ||
1052 | { | ||
1053 | u64 Kpart; | ||
1054 | unsigned int t1, t2, K, Nmod; | ||
1055 | |||
1056 | if (output >= 2815250 && output <= 3125000) | ||
1057 | fll_div->div = 0x4; | ||
1058 | else if (output >= 5625000 && output <= 6250000) | ||
1059 | fll_div->div = 0x3; | ||
1060 | else if (output >= 11250000 && output <= 12500000) | ||
1061 | fll_div->div = 0x2; | ||
1062 | else if (output >= 22500000 && output <= 25000000) | ||
1063 | fll_div->div = 0x1; | ||
1064 | else { | ||
1065 | printk(KERN_ERR "wm8350: fll freq %d out of range\n", output); | ||
1066 | return -EINVAL; | ||
1067 | } | ||
1068 | |||
1069 | if (input > 48000) | ||
1070 | fll_div->ratio = 1; | ||
1071 | else | ||
1072 | fll_div->ratio = 8; | ||
1073 | |||
1074 | t1 = output * (1 << (fll_div->div + 1)); | ||
1075 | t2 = input * fll_div->ratio; | ||
1076 | |||
1077 | fll_div->n = t1 / t2; | ||
1078 | Nmod = t1 % t2; | ||
1079 | |||
1080 | if (Nmod) { | ||
1081 | Kpart = FIXED_FLL_SIZE * (long long)Nmod; | ||
1082 | do_div(Kpart, t2); | ||
1083 | K = Kpart & 0xFFFFFFFF; | ||
1084 | |||
1085 | /* Check if we need to round */ | ||
1086 | if ((K % 10) >= 5) | ||
1087 | K += 5; | ||
1088 | |||
1089 | /* Move down to proper range now rounding is done */ | ||
1090 | K /= 10; | ||
1091 | fll_div->k = K; | ||
1092 | } else | ||
1093 | fll_div->k = 0; | ||
1094 | |||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | static int wm8350_set_fll(struct snd_soc_dai *codec_dai, | ||
1099 | int pll_id, unsigned int freq_in, | ||
1100 | unsigned int freq_out) | ||
1101 | { | ||
1102 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1103 | struct wm8350 *wm8350 = codec->control_data; | ||
1104 | struct _fll_div fll_div; | ||
1105 | int ret = 0; | ||
1106 | u16 fll_1, fll_4; | ||
1107 | |||
1108 | /* power down FLL - we need to do this for reconfiguration */ | ||
1109 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, | ||
1110 | WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); | ||
1111 | |||
1112 | if (freq_out == 0 || freq_in == 0) | ||
1113 | return ret; | ||
1114 | |||
1115 | ret = fll_factors(&fll_div, freq_in, freq_out); | ||
1116 | if (ret < 0) | ||
1117 | return ret; | ||
1118 | dev_dbg(wm8350->dev, | ||
1119 | "FLL in %d FLL out %d N 0x%x K 0x%x div %d ratio %d", | ||
1120 | freq_in, freq_out, fll_div.n, fll_div.k, fll_div.div, | ||
1121 | fll_div.ratio); | ||
1122 | |||
1123 | /* set up N.K & dividers */ | ||
1124 | fll_1 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_1) & | ||
1125 | ~(WM8350_FLL_OUTDIV_MASK | WM8350_FLL_RSP_RATE_MASK | 0xc000); | ||
1126 | wm8350_codec_write(codec, WM8350_FLL_CONTROL_1, | ||
1127 | fll_1 | (fll_div.div << 8) | 0x50); | ||
1128 | wm8350_codec_write(codec, WM8350_FLL_CONTROL_2, | ||
1129 | (fll_div.ratio << 11) | (fll_div. | ||
1130 | n & WM8350_FLL_N_MASK)); | ||
1131 | wm8350_codec_write(codec, WM8350_FLL_CONTROL_3, fll_div.k); | ||
1132 | fll_4 = wm8350_codec_read(codec, WM8350_FLL_CONTROL_4) & | ||
1133 | ~(WM8350_FLL_FRAC | WM8350_FLL_SLOW_LOCK_REF); | ||
1134 | wm8350_codec_write(codec, WM8350_FLL_CONTROL_4, | ||
1135 | fll_4 | (fll_div.k ? WM8350_FLL_FRAC : 0) | | ||
1136 | (fll_div.ratio == 8 ? WM8350_FLL_SLOW_LOCK_REF : 0)); | ||
1137 | |||
1138 | /* power FLL on */ | ||
1139 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); | ||
1140 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); | ||
1141 | |||
1142 | return 0; | ||
1143 | } | ||
1144 | |||
1145 | static int wm8350_set_bias_level(struct snd_soc_codec *codec, | ||
1146 | enum snd_soc_bias_level level) | ||
1147 | { | ||
1148 | struct wm8350 *wm8350 = codec->control_data; | ||
1149 | struct wm8350_data *priv = codec->private_data; | ||
1150 | struct wm8350_audio_platform_data *platform = | ||
1151 | wm8350->codec.platform_data; | ||
1152 | u16 pm1; | ||
1153 | int ret; | ||
1154 | |||
1155 | switch (level) { | ||
1156 | case SND_SOC_BIAS_ON: | ||
1157 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & | ||
1158 | ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); | ||
1159 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1160 | pm1 | WM8350_VMID_50K | | ||
1161 | platform->codec_current_on << 14); | ||
1162 | break; | ||
1163 | |||
1164 | case SND_SOC_BIAS_PREPARE: | ||
1165 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1); | ||
1166 | pm1 &= ~WM8350_VMID_MASK; | ||
1167 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1168 | pm1 | WM8350_VMID_50K); | ||
1169 | break; | ||
1170 | |||
1171 | case SND_SOC_BIAS_STANDBY: | ||
1172 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
1173 | ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), | ||
1174 | priv->supplies); | ||
1175 | if (ret != 0) | ||
1176 | return ret; | ||
1177 | |||
1178 | /* Enable the system clock */ | ||
1179 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, | ||
1180 | WM8350_SYSCLK_ENA); | ||
1181 | |||
1182 | /* mute DAC & outputs */ | ||
1183 | wm8350_set_bits(wm8350, WM8350_DAC_MUTE, | ||
1184 | WM8350_DAC_MUTE_ENA); | ||
1185 | |||
1186 | /* discharge cap memory */ | ||
1187 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, | ||
1188 | platform->dis_out1 | | ||
1189 | (platform->dis_out2 << 2) | | ||
1190 | (platform->dis_out3 << 4) | | ||
1191 | (platform->dis_out4 << 6)); | ||
1192 | |||
1193 | /* wait for discharge */ | ||
1194 | schedule_timeout_interruptible(msecs_to_jiffies | ||
1195 | (platform-> | ||
1196 | cap_discharge_msecs)); | ||
1197 | |||
1198 | /* enable antipop */ | ||
1199 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, | ||
1200 | (platform->vmid_s_curve << 8)); | ||
1201 | |||
1202 | /* ramp up vmid */ | ||
1203 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1204 | (platform-> | ||
1205 | codec_current_charge << 14) | | ||
1206 | WM8350_VMID_5K | WM8350_VMIDEN | | ||
1207 | WM8350_VBUFEN); | ||
1208 | |||
1209 | /* wait for vmid */ | ||
1210 | schedule_timeout_interruptible(msecs_to_jiffies | ||
1211 | (platform-> | ||
1212 | vmid_charge_msecs)); | ||
1213 | |||
1214 | /* turn on vmid 300k */ | ||
1215 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & | ||
1216 | ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); | ||
1217 | pm1 |= WM8350_VMID_300K | | ||
1218 | (platform->codec_current_standby << 14); | ||
1219 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1220 | pm1); | ||
1221 | |||
1222 | |||
1223 | /* enable analogue bias */ | ||
1224 | pm1 |= WM8350_BIASEN; | ||
1225 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); | ||
1226 | |||
1227 | /* disable antipop */ | ||
1228 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0); | ||
1229 | |||
1230 | } else { | ||
1231 | /* turn on vmid 300k and reduce current */ | ||
1232 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & | ||
1233 | ~(WM8350_VMID_MASK | WM8350_CODEC_ISEL_MASK); | ||
1234 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1235 | pm1 | WM8350_VMID_300K | | ||
1236 | (platform-> | ||
1237 | codec_current_standby << 14)); | ||
1238 | |||
1239 | } | ||
1240 | break; | ||
1241 | |||
1242 | case SND_SOC_BIAS_OFF: | ||
1243 | |||
1244 | /* mute DAC & enable outputs */ | ||
1245 | wm8350_set_bits(wm8350, WM8350_DAC_MUTE, WM8350_DAC_MUTE_ENA); | ||
1246 | |||
1247 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_3, | ||
1248 | WM8350_OUT1L_ENA | WM8350_OUT1R_ENA | | ||
1249 | WM8350_OUT2L_ENA | WM8350_OUT2R_ENA); | ||
1250 | |||
1251 | /* enable anti pop S curve */ | ||
1252 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, | ||
1253 | (platform->vmid_s_curve << 8)); | ||
1254 | |||
1255 | /* turn off vmid */ | ||
1256 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & | ||
1257 | ~WM8350_VMIDEN; | ||
1258 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); | ||
1259 | |||
1260 | /* wait */ | ||
1261 | schedule_timeout_interruptible(msecs_to_jiffies | ||
1262 | (platform-> | ||
1263 | vmid_discharge_msecs)); | ||
1264 | |||
1265 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, | ||
1266 | (platform->vmid_s_curve << 8) | | ||
1267 | platform->dis_out1 | | ||
1268 | (platform->dis_out2 << 2) | | ||
1269 | (platform->dis_out3 << 4) | | ||
1270 | (platform->dis_out4 << 6)); | ||
1271 | |||
1272 | /* turn off VBuf and drain */ | ||
1273 | pm1 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_1) & | ||
1274 | ~(WM8350_VBUFEN | WM8350_VMID_MASK); | ||
1275 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, | ||
1276 | pm1 | WM8350_OUTPUT_DRAIN_EN); | ||
1277 | |||
1278 | /* wait */ | ||
1279 | schedule_timeout_interruptible(msecs_to_jiffies | ||
1280 | (platform->drain_msecs)); | ||
1281 | |||
1282 | pm1 &= ~WM8350_BIASEN; | ||
1283 | wm8350_reg_write(wm8350, WM8350_POWER_MGMT_1, pm1); | ||
1284 | |||
1285 | /* disable anti-pop */ | ||
1286 | wm8350_reg_write(wm8350, WM8350_ANTI_POP_CONTROL, 0); | ||
1287 | |||
1288 | wm8350_clear_bits(wm8350, WM8350_LOUT1_VOLUME, | ||
1289 | WM8350_OUT1L_ENA); | ||
1290 | wm8350_clear_bits(wm8350, WM8350_ROUT1_VOLUME, | ||
1291 | WM8350_OUT1R_ENA); | ||
1292 | wm8350_clear_bits(wm8350, WM8350_LOUT2_VOLUME, | ||
1293 | WM8350_OUT2L_ENA); | ||
1294 | wm8350_clear_bits(wm8350, WM8350_ROUT2_VOLUME, | ||
1295 | WM8350_OUT2R_ENA); | ||
1296 | |||
1297 | /* disable clock gen */ | ||
1298 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, | ||
1299 | WM8350_SYSCLK_ENA); | ||
1300 | |||
1301 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), | ||
1302 | priv->supplies); | ||
1303 | break; | ||
1304 | } | ||
1305 | codec->bias_level = level; | ||
1306 | return 0; | ||
1307 | } | ||
1308 | |||
1309 | static int wm8350_suspend(struct platform_device *pdev, pm_message_t state) | ||
1310 | { | ||
1311 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1312 | struct snd_soc_codec *codec = socdev->codec; | ||
1313 | |||
1314 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | static int wm8350_resume(struct platform_device *pdev) | ||
1319 | { | ||
1320 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1321 | struct snd_soc_codec *codec = socdev->codec; | ||
1322 | |||
1323 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1324 | |||
1325 | if (codec->suspend_bias_level == SND_SOC_BIAS_ON) | ||
1326 | wm8350_set_bias_level(codec, SND_SOC_BIAS_ON); | ||
1327 | |||
1328 | return 0; | ||
1329 | } | ||
1330 | |||
1331 | static struct snd_soc_codec *wm8350_codec; | ||
1332 | |||
1333 | static int wm8350_probe(struct platform_device *pdev) | ||
1334 | { | ||
1335 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1336 | struct snd_soc_codec *codec; | ||
1337 | struct wm8350 *wm8350; | ||
1338 | struct wm8350_data *priv; | ||
1339 | int ret; | ||
1340 | struct wm8350_output *out1; | ||
1341 | struct wm8350_output *out2; | ||
1342 | |||
1343 | BUG_ON(!wm8350_codec); | ||
1344 | |||
1345 | socdev->codec = wm8350_codec; | ||
1346 | codec = socdev->codec; | ||
1347 | wm8350 = codec->control_data; | ||
1348 | priv = codec->private_data; | ||
1349 | |||
1350 | /* Enable the codec */ | ||
1351 | wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | ||
1352 | |||
1353 | /* Enable robust clocking mode in ADC */ | ||
1354 | wm8350_codec_write(codec, WM8350_SECURITY, 0xa7); | ||
1355 | wm8350_codec_write(codec, 0xde, 0x13); | ||
1356 | wm8350_codec_write(codec, WM8350_SECURITY, 0); | ||
1357 | |||
1358 | /* read OUT1 & OUT2 volumes */ | ||
1359 | out1 = &priv->out1; | ||
1360 | out2 = &priv->out2; | ||
1361 | out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) & | ||
1362 | WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; | ||
1363 | out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) & | ||
1364 | WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; | ||
1365 | out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) & | ||
1366 | WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; | ||
1367 | out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) & | ||
1368 | WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; | ||
1369 | wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0); | ||
1370 | wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0); | ||
1371 | wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0); | ||
1372 | wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0); | ||
1373 | |||
1374 | /* Latch VU bits & mute */ | ||
1375 | wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, | ||
1376 | WM8350_OUT1_VU | WM8350_OUT1L_MUTE); | ||
1377 | wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, | ||
1378 | WM8350_OUT2_VU | WM8350_OUT2L_MUTE); | ||
1379 | wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME, | ||
1380 | WM8350_OUT1_VU | WM8350_OUT1R_MUTE); | ||
1381 | wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, | ||
1382 | WM8350_OUT2_VU | WM8350_OUT2R_MUTE); | ||
1383 | |||
1384 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1385 | if (ret < 0) { | ||
1386 | dev_err(&pdev->dev, "failed to create pcms\n"); | ||
1387 | return ret; | ||
1388 | } | ||
1389 | |||
1390 | wm8350_add_controls(codec); | ||
1391 | wm8350_add_widgets(codec); | ||
1392 | |||
1393 | wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1394 | |||
1395 | ret = snd_soc_init_card(socdev); | ||
1396 | if (ret < 0) { | ||
1397 | dev_err(&pdev->dev, "failed to register card\n"); | ||
1398 | goto card_err; | ||
1399 | } | ||
1400 | |||
1401 | return 0; | ||
1402 | |||
1403 | card_err: | ||
1404 | snd_soc_free_pcms(socdev); | ||
1405 | snd_soc_dapm_free(socdev); | ||
1406 | return ret; | ||
1407 | } | ||
1408 | |||
1409 | static int wm8350_remove(struct platform_device *pdev) | ||
1410 | { | ||
1411 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1412 | struct snd_soc_codec *codec = socdev->codec; | ||
1413 | struct wm8350 *wm8350 = codec->control_data; | ||
1414 | int ret; | ||
1415 | |||
1416 | /* cancel any work waiting to be queued. */ | ||
1417 | ret = cancel_delayed_work(&codec->delayed_work); | ||
1418 | |||
1419 | /* if there was any work waiting then we run it now and | ||
1420 | * wait for its completion */ | ||
1421 | if (ret) { | ||
1422 | schedule_delayed_work(&codec->delayed_work, 0); | ||
1423 | flush_scheduled_work(); | ||
1424 | } | ||
1425 | |||
1426 | wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1427 | |||
1428 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | ||
1429 | |||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | #define WM8350_RATES (SNDRV_PCM_RATE_8000_96000) | ||
1434 | |||
1435 | #define WM8350_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
1436 | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
1437 | SNDRV_PCM_FMTBIT_S24_LE) | ||
1438 | |||
1439 | struct snd_soc_dai wm8350_dai = { | ||
1440 | .name = "WM8350", | ||
1441 | .playback = { | ||
1442 | .stream_name = "Playback", | ||
1443 | .channels_min = 1, | ||
1444 | .channels_max = 2, | ||
1445 | .rates = WM8350_RATES, | ||
1446 | .formats = WM8350_FORMATS, | ||
1447 | }, | ||
1448 | .capture = { | ||
1449 | .stream_name = "Capture", | ||
1450 | .channels_min = 1, | ||
1451 | .channels_max = 2, | ||
1452 | .rates = WM8350_RATES, | ||
1453 | .formats = WM8350_FORMATS, | ||
1454 | }, | ||
1455 | .ops = { | ||
1456 | .hw_params = wm8350_pcm_hw_params, | ||
1457 | .digital_mute = wm8350_mute, | ||
1458 | .trigger = wm8350_pcm_trigger, | ||
1459 | .set_fmt = wm8350_set_dai_fmt, | ||
1460 | .set_sysclk = wm8350_set_dai_sysclk, | ||
1461 | .set_pll = wm8350_set_fll, | ||
1462 | .set_clkdiv = wm8350_set_clkdiv, | ||
1463 | }, | ||
1464 | }; | ||
1465 | EXPORT_SYMBOL_GPL(wm8350_dai); | ||
1466 | |||
1467 | struct snd_soc_codec_device soc_codec_dev_wm8350 = { | ||
1468 | .probe = wm8350_probe, | ||
1469 | .remove = wm8350_remove, | ||
1470 | .suspend = wm8350_suspend, | ||
1471 | .resume = wm8350_resume, | ||
1472 | }; | ||
1473 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8350); | ||
1474 | |||
1475 | static int wm8350_codec_probe(struct platform_device *pdev) | ||
1476 | { | ||
1477 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
1478 | struct wm8350_data *priv; | ||
1479 | struct snd_soc_codec *codec; | ||
1480 | int ret, i; | ||
1481 | |||
1482 | if (wm8350->codec.platform_data == NULL) { | ||
1483 | dev_err(&pdev->dev, "No audio platform data supplied\n"); | ||
1484 | return -EINVAL; | ||
1485 | } | ||
1486 | |||
1487 | priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL); | ||
1488 | if (priv == NULL) | ||
1489 | return -ENOMEM; | ||
1490 | |||
1491 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
1492 | priv->supplies[i].supply = supply_names[i]; | ||
1493 | |||
1494 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | ||
1495 | priv->supplies); | ||
1496 | if (ret != 0) | ||
1497 | goto err_priv; | ||
1498 | |||
1499 | codec = &priv->codec; | ||
1500 | wm8350->codec.codec = codec; | ||
1501 | |||
1502 | wm8350_dai.dev = &pdev->dev; | ||
1503 | |||
1504 | mutex_init(&codec->mutex); | ||
1505 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1506 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1507 | codec->dev = &pdev->dev; | ||
1508 | codec->name = "WM8350"; | ||
1509 | codec->owner = THIS_MODULE; | ||
1510 | codec->read = wm8350_codec_read; | ||
1511 | codec->write = wm8350_codec_write; | ||
1512 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1513 | codec->set_bias_level = wm8350_set_bias_level; | ||
1514 | codec->dai = &wm8350_dai; | ||
1515 | codec->num_dai = 1; | ||
1516 | codec->reg_cache_size = WM8350_MAX_REGISTER; | ||
1517 | codec->private_data = priv; | ||
1518 | codec->control_data = wm8350; | ||
1519 | |||
1520 | /* Put the codec into reset if it wasn't already */ | ||
1521 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | ||
1522 | |||
1523 | INIT_DELAYED_WORK(&codec->delayed_work, wm8350_pga_work); | ||
1524 | ret = snd_soc_register_codec(codec); | ||
1525 | if (ret != 0) | ||
1526 | goto err_supply; | ||
1527 | |||
1528 | wm8350_codec = codec; | ||
1529 | |||
1530 | ret = snd_soc_register_dai(&wm8350_dai); | ||
1531 | if (ret != 0) | ||
1532 | goto err_codec; | ||
1533 | return 0; | ||
1534 | |||
1535 | err_codec: | ||
1536 | snd_soc_unregister_codec(codec); | ||
1537 | err_supply: | ||
1538 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1539 | err_priv: | ||
1540 | kfree(priv); | ||
1541 | wm8350_codec = NULL; | ||
1542 | return ret; | ||
1543 | } | ||
1544 | |||
1545 | static int __devexit wm8350_codec_remove(struct platform_device *pdev) | ||
1546 | { | ||
1547 | struct wm8350 *wm8350 = platform_get_drvdata(pdev); | ||
1548 | struct snd_soc_codec *codec = wm8350->codec.codec; | ||
1549 | struct wm8350_data *priv = codec->private_data; | ||
1550 | |||
1551 | snd_soc_unregister_dai(&wm8350_dai); | ||
1552 | snd_soc_unregister_codec(codec); | ||
1553 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1554 | kfree(priv); | ||
1555 | wm8350_codec = NULL; | ||
1556 | return 0; | ||
1557 | } | ||
1558 | |||
1559 | static struct platform_driver wm8350_codec_driver = { | ||
1560 | .driver = { | ||
1561 | .name = "wm8350-codec", | ||
1562 | .owner = THIS_MODULE, | ||
1563 | }, | ||
1564 | .probe = wm8350_codec_probe, | ||
1565 | .remove = __devexit_p(wm8350_codec_remove), | ||
1566 | }; | ||
1567 | |||
1568 | static __init int wm8350_init(void) | ||
1569 | { | ||
1570 | return platform_driver_register(&wm8350_codec_driver); | ||
1571 | } | ||
1572 | module_init(wm8350_init); | ||
1573 | |||
1574 | static __exit void wm8350_exit(void) | ||
1575 | { | ||
1576 | platform_driver_unregister(&wm8350_codec_driver); | ||
1577 | } | ||
1578 | module_exit(wm8350_exit); | ||
1579 | |||
1580 | MODULE_DESCRIPTION("ASoC WM8350 driver"); | ||
1581 | MODULE_AUTHOR("Liam Girdwood"); | ||
1582 | MODULE_LICENSE("GPL"); | ||
1583 | MODULE_ALIAS("platform:wm8350-codec"); | ||
diff --git a/sound/soc/codecs/wm8350.h b/sound/soc/codecs/wm8350.h new file mode 100644 index 000000000000..cc2887aa6c38 --- /dev/null +++ b/sound/soc/codecs/wm8350.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * wm8350.h - WM8903 audio codec interface | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _WM8350_H | ||
13 | #define _WM8350_H | ||
14 | |||
15 | #include <sound/soc.h> | ||
16 | |||
17 | extern struct snd_soc_dai wm8350_dai; | ||
18 | extern struct snd_soc_codec_device soc_codec_dev_wm8350; | ||
19 | |||
20 | #endif | ||
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index d8ca2da8d634..40f8238df717 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -463,7 +463,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
463 | } | 463 | } |
464 | 464 | ||
465 | static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, | 465 | static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream, |
466 | struct snd_pcm_hw_params *params) | 466 | struct snd_pcm_hw_params *params, |
467 | struct snd_soc_dai *dai) | ||
467 | { | 468 | { |
468 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 469 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
469 | struct snd_soc_device *socdev = rtd->socdev; | 470 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -585,8 +586,6 @@ struct snd_soc_dai wm8510_dai = { | |||
585 | .formats = WM8510_FORMATS,}, | 586 | .formats = WM8510_FORMATS,}, |
586 | .ops = { | 587 | .ops = { |
587 | .hw_params = wm8510_pcm_hw_params, | 588 | .hw_params = wm8510_pcm_hw_params, |
588 | }, | ||
589 | .dai_ops = { | ||
590 | .digital_mute = wm8510_mute, | 589 | .digital_mute = wm8510_mute, |
591 | .set_fmt = wm8510_set_dai_fmt, | 590 | .set_fmt = wm8510_set_dai_fmt, |
592 | .set_clkdiv = wm8510_set_dai_clkdiv, | 591 | .set_clkdiv = wm8510_set_dai_clkdiv, |
@@ -659,7 +658,7 @@ static int wm8510_init(struct snd_soc_device *socdev) | |||
659 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 658 | wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
660 | wm8510_add_controls(codec); | 659 | wm8510_add_controls(codec); |
661 | wm8510_add_widgets(codec); | 660 | wm8510_add_widgets(codec); |
662 | ret = snd_soc_register_card(socdev); | 661 | ret = snd_soc_init_card(socdev); |
663 | if (ret < 0) { | 662 | if (ret < 0) { |
664 | printk(KERN_ERR "wm8510: failed to register card\n"); | 663 | printk(KERN_ERR "wm8510: failed to register card\n"); |
665 | goto card_err; | 664 | goto card_err; |
@@ -890,6 +889,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8510 = { | |||
890 | }; | 889 | }; |
891 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); | 890 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510); |
892 | 891 | ||
892 | static int __init wm8510_modinit(void) | ||
893 | { | ||
894 | return snd_soc_register_dai(&wm8510_dai); | ||
895 | } | ||
896 | module_init(wm8510_modinit); | ||
897 | |||
898 | static void __exit wm8510_exit(void) | ||
899 | { | ||
900 | snd_soc_unregister_dai(&wm8510_dai); | ||
901 | } | ||
902 | module_exit(wm8510_exit); | ||
903 | |||
893 | MODULE_DESCRIPTION("ASoC WM8510 driver"); | 904 | MODULE_DESCRIPTION("ASoC WM8510 driver"); |
894 | MODULE_AUTHOR("Liam Girdwood"); | 905 | MODULE_AUTHOR("Liam Girdwood"); |
895 | MODULE_LICENSE("GPL"); | 906 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 627ebfb4209b..d004e5845298 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, | |||
548 | * Set PCM DAI bit size and sample rate. | 548 | * Set PCM DAI bit size and sample rate. |
549 | */ | 549 | */ |
550 | static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | 550 | static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, |
551 | struct snd_pcm_hw_params *params) | 551 | struct snd_pcm_hw_params *params, |
552 | struct snd_soc_dai *dai) | ||
552 | { | 553 | { |
553 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 554 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
554 | struct snd_soc_dai_link *dai = rtd->dai; | ||
555 | struct snd_soc_device *socdev = rtd->socdev; | 555 | struct snd_soc_device *socdev = rtd->socdev; |
556 | struct snd_soc_codec *codec = socdev->codec; | 556 | struct snd_soc_codec *codec = socdev->codec; |
557 | u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id); | 557 | u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id); |
558 | 558 | ||
559 | paifb &= ~WM8580_AIF_LENGTH_MASK; | 559 | paifb &= ~WM8580_AIF_LENGTH_MASK; |
560 | /* bit size */ | 560 | /* bit size */ |
@@ -574,7 +574,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream, | |||
574 | return -EINVAL; | 574 | return -EINVAL; |
575 | } | 575 | } |
576 | 576 | ||
577 | wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb); | 577 | wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb); |
578 | return 0; | 578 | return 0; |
579 | } | 579 | } |
580 | 580 | ||
@@ -798,8 +798,6 @@ struct snd_soc_dai wm8580_dai[] = { | |||
798 | }, | 798 | }, |
799 | .ops = { | 799 | .ops = { |
800 | .hw_params = wm8580_paif_hw_params, | 800 | .hw_params = wm8580_paif_hw_params, |
801 | }, | ||
802 | .dai_ops = { | ||
803 | .set_fmt = wm8580_set_paif_dai_fmt, | 801 | .set_fmt = wm8580_set_paif_dai_fmt, |
804 | .set_clkdiv = wm8580_set_dai_clkdiv, | 802 | .set_clkdiv = wm8580_set_dai_clkdiv, |
805 | .set_pll = wm8580_set_dai_pll, | 803 | .set_pll = wm8580_set_dai_pll, |
@@ -818,8 +816,6 @@ struct snd_soc_dai wm8580_dai[] = { | |||
818 | }, | 816 | }, |
819 | .ops = { | 817 | .ops = { |
820 | .hw_params = wm8580_paif_hw_params, | 818 | .hw_params = wm8580_paif_hw_params, |
821 | }, | ||
822 | .dai_ops = { | ||
823 | .set_fmt = wm8580_set_paif_dai_fmt, | 819 | .set_fmt = wm8580_set_paif_dai_fmt, |
824 | .set_clkdiv = wm8580_set_dai_clkdiv, | 820 | .set_clkdiv = wm8580_set_dai_clkdiv, |
825 | .set_pll = wm8580_set_dai_pll, | 821 | .set_pll = wm8580_set_dai_pll, |
@@ -873,7 +869,7 @@ static int wm8580_init(struct snd_soc_device *socdev) | |||
873 | wm8580_add_controls(codec); | 869 | wm8580_add_controls(codec); |
874 | wm8580_add_widgets(codec); | 870 | wm8580_add_widgets(codec); |
875 | 871 | ||
876 | ret = snd_soc_register_card(socdev); | 872 | ret = snd_soc_init_card(socdev); |
877 | if (ret < 0) { | 873 | if (ret < 0) { |
878 | printk(KERN_ERR "wm8580: failed to register card\n"); | 874 | printk(KERN_ERR "wm8580: failed to register card\n"); |
879 | goto card_err; | 875 | goto card_err; |
@@ -900,85 +896,85 @@ static struct snd_soc_device *wm8580_socdev; | |||
900 | * low = 0x1a | 896 | * low = 0x1a |
901 | * high = 0x1b | 897 | * high = 0x1b |
902 | */ | 898 | */ |
903 | static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; | ||
904 | |||
905 | /* Magic definition of all other variables and things */ | ||
906 | I2C_CLIENT_INSMOD; | ||
907 | 899 | ||
908 | static struct i2c_driver wm8580_i2c_driver; | 900 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
909 | static struct i2c_client client_template; | 901 | const struct i2c_device_id *id) |
910 | |||
911 | static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind) | ||
912 | { | 902 | { |
913 | struct snd_soc_device *socdev = wm8580_socdev; | 903 | struct snd_soc_device *socdev = wm8580_socdev; |
914 | struct wm8580_setup_data *setup = socdev->codec_data; | ||
915 | struct snd_soc_codec *codec = socdev->codec; | 904 | struct snd_soc_codec *codec = socdev->codec; |
916 | struct i2c_client *i2c; | ||
917 | int ret; | 905 | int ret; |
918 | 906 | ||
919 | if (addr != setup->i2c_address) | ||
920 | return -ENODEV; | ||
921 | |||
922 | client_template.adapter = adap; | ||
923 | client_template.addr = addr; | ||
924 | |||
925 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
926 | if (i2c == NULL) { | ||
927 | kfree(codec); | ||
928 | return -ENOMEM; | ||
929 | } | ||
930 | i2c_set_clientdata(i2c, codec); | 907 | i2c_set_clientdata(i2c, codec); |
931 | codec->control_data = i2c; | 908 | codec->control_data = i2c; |
932 | 909 | ||
933 | ret = i2c_attach_client(i2c); | ||
934 | if (ret < 0) { | ||
935 | dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr); | ||
936 | goto err; | ||
937 | } | ||
938 | |||
939 | ret = wm8580_init(socdev); | 910 | ret = wm8580_init(socdev); |
940 | if (ret < 0) { | 911 | if (ret < 0) |
941 | dev_err(&i2c->dev, "failed to initialise WM8580\n"); | 912 | dev_err(&i2c->dev, "failed to initialise WM8580\n"); |
942 | goto err; | ||
943 | } | ||
944 | |||
945 | return ret; | ||
946 | |||
947 | err: | ||
948 | kfree(codec); | ||
949 | kfree(i2c); | ||
950 | return ret; | 913 | return ret; |
951 | } | 914 | } |
952 | 915 | ||
953 | static int wm8580_i2c_detach(struct i2c_client *client) | 916 | static int wm8580_i2c_remove(struct i2c_client *client) |
954 | { | 917 | { |
955 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 918 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
956 | i2c_detach_client(client); | ||
957 | kfree(codec->reg_cache); | 919 | kfree(codec->reg_cache); |
958 | kfree(client); | ||
959 | return 0; | 920 | return 0; |
960 | } | 921 | } |
961 | 922 | ||
962 | static int wm8580_i2c_attach(struct i2c_adapter *adap) | 923 | static const struct i2c_device_id wm8580_i2c_id[] = { |
963 | { | 924 | { "wm8580", 0 }, |
964 | return i2c_probe(adap, &addr_data, wm8580_codec_probe); | 925 | { } |
965 | } | 926 | }; |
927 | MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | ||
966 | 928 | ||
967 | /* corgi i2c codec control layer */ | ||
968 | static struct i2c_driver wm8580_i2c_driver = { | 929 | static struct i2c_driver wm8580_i2c_driver = { |
969 | .driver = { | 930 | .driver = { |
970 | .name = "WM8580 I2C Codec", | 931 | .name = "WM8580 I2C Codec", |
971 | .owner = THIS_MODULE, | 932 | .owner = THIS_MODULE, |
972 | }, | 933 | }, |
973 | .attach_adapter = wm8580_i2c_attach, | 934 | .probe = wm8580_i2c_probe, |
974 | .detach_client = wm8580_i2c_detach, | 935 | .remove = wm8580_i2c_remove, |
975 | .command = NULL, | 936 | .id_table = wm8580_i2c_id, |
976 | }; | 937 | }; |
977 | 938 | ||
978 | static struct i2c_client client_template = { | 939 | static int wm8580_add_i2c_device(struct platform_device *pdev, |
979 | .name = "WM8580", | 940 | const struct wm8580_setup_data *setup) |
980 | .driver = &wm8580_i2c_driver, | 941 | { |
981 | }; | 942 | struct i2c_board_info info; |
943 | struct i2c_adapter *adapter; | ||
944 | struct i2c_client *client; | ||
945 | int ret; | ||
946 | |||
947 | ret = i2c_add_driver(&wm8580_i2c_driver); | ||
948 | if (ret != 0) { | ||
949 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
950 | return ret; | ||
951 | } | ||
952 | |||
953 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
954 | info.addr = setup->i2c_address; | ||
955 | strlcpy(info.type, "wm8580", I2C_NAME_SIZE); | ||
956 | |||
957 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
958 | if (!adapter) { | ||
959 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
960 | setup->i2c_bus); | ||
961 | goto err_driver; | ||
962 | } | ||
963 | |||
964 | client = i2c_new_device(adapter, &info); | ||
965 | i2c_put_adapter(adapter); | ||
966 | if (!client) { | ||
967 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
968 | (unsigned int)info.addr); | ||
969 | goto err_driver; | ||
970 | } | ||
971 | |||
972 | return 0; | ||
973 | |||
974 | err_driver: | ||
975 | i2c_del_driver(&wm8580_i2c_driver); | ||
976 | return -ENODEV; | ||
977 | } | ||
982 | #endif | 978 | #endif |
983 | 979 | ||
984 | static int wm8580_probe(struct platform_device *pdev) | 980 | static int wm8580_probe(struct platform_device *pdev) |
@@ -1011,11 +1007,8 @@ static int wm8580_probe(struct platform_device *pdev) | |||
1011 | 1007 | ||
1012 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1008 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1013 | if (setup->i2c_address) { | 1009 | if (setup->i2c_address) { |
1014 | normal_i2c[0] = setup->i2c_address; | ||
1015 | codec->hw_write = (hw_write_t)i2c_master_send; | 1010 | codec->hw_write = (hw_write_t)i2c_master_send; |
1016 | ret = i2c_add_driver(&wm8580_i2c_driver); | 1011 | ret = wm8580_add_i2c_device(pdev, setup); |
1017 | if (ret != 0) | ||
1018 | printk(KERN_ERR "can't add i2c driver"); | ||
1019 | } | 1012 | } |
1020 | #else | 1013 | #else |
1021 | /* Add other interfaces here */ | 1014 | /* Add other interfaces here */ |
@@ -1034,6 +1027,7 @@ static int wm8580_remove(struct platform_device *pdev) | |||
1034 | snd_soc_free_pcms(socdev); | 1027 | snd_soc_free_pcms(socdev); |
1035 | snd_soc_dapm_free(socdev); | 1028 | snd_soc_dapm_free(socdev); |
1036 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1029 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1030 | i2c_unregister_device(codec->control_data); | ||
1037 | i2c_del_driver(&wm8580_i2c_driver); | 1031 | i2c_del_driver(&wm8580_i2c_driver); |
1038 | #endif | 1032 | #endif |
1039 | kfree(codec->private_data); | 1033 | kfree(codec->private_data); |
@@ -1048,6 +1042,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = { | |||
1048 | }; | 1042 | }; |
1049 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); | 1043 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580); |
1050 | 1044 | ||
1045 | static int __init wm8580_modinit(void) | ||
1046 | { | ||
1047 | return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
1048 | } | ||
1049 | module_init(wm8580_modinit); | ||
1050 | |||
1051 | static void __exit wm8580_exit(void) | ||
1052 | { | ||
1053 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | ||
1054 | } | ||
1055 | module_exit(wm8580_exit); | ||
1056 | |||
1051 | MODULE_DESCRIPTION("ASoC WM8580 driver"); | 1057 | MODULE_DESCRIPTION("ASoC WM8580 driver"); |
1052 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1058 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
1053 | MODULE_LICENSE("GPL"); | 1059 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h index 589ddaba21d7..09e4422f6f2f 100644 --- a/sound/soc/codecs/wm8580.h +++ b/sound/soc/codecs/wm8580.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define WM8580_CLKSRC_NONE 5 | 29 | #define WM8580_CLKSRC_NONE 5 |
30 | 30 | ||
31 | struct wm8580_setup_data { | 31 | struct wm8580_setup_data { |
32 | int i2c_bus; | ||
32 | unsigned short i2c_address; | 33 | unsigned short i2c_address; |
33 | }; | 34 | }; |
34 | 35 | ||
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c new file mode 100644 index 000000000000..80b11983e137 --- /dev/null +++ b/sound/soc/codecs/wm8728.c | |||
@@ -0,0 +1,585 @@ | |||
1 | /* | ||
2 | * wm8728.c -- WM8728 ALSA SoC Audio driver | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/pm.h> | ||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/spi/spi.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/pcm_params.h> | ||
24 | #include <sound/soc.h> | ||
25 | #include <sound/soc-dapm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/tlv.h> | ||
28 | |||
29 | #include "wm8728.h" | ||
30 | |||
31 | struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
32 | |||
33 | /* | ||
34 | * We can't read the WM8728 register space so we cache them instead. | ||
35 | * Note that the defaults here aren't the physical defaults, we latch | ||
36 | * the volume update bits, mute the output and enable infinite zero | ||
37 | * detect. | ||
38 | */ | ||
39 | static const u16 wm8728_reg_defaults[] = { | ||
40 | 0x1ff, | ||
41 | 0x1ff, | ||
42 | 0x001, | ||
43 | 0x100, | ||
44 | }; | ||
45 | |||
46 | static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec, | ||
47 | unsigned int reg) | ||
48 | { | ||
49 | u16 *cache = codec->reg_cache; | ||
50 | BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); | ||
51 | return cache[reg]; | ||
52 | } | ||
53 | |||
54 | static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec, | ||
55 | u16 reg, unsigned int value) | ||
56 | { | ||
57 | u16 *cache = codec->reg_cache; | ||
58 | BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults)); | ||
59 | cache[reg] = value; | ||
60 | } | ||
61 | |||
62 | /* | ||
63 | * write to the WM8728 register space | ||
64 | */ | ||
65 | static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg, | ||
66 | unsigned int value) | ||
67 | { | ||
68 | u8 data[2]; | ||
69 | |||
70 | /* data is | ||
71 | * D15..D9 WM8728 register offset | ||
72 | * D8...D0 register data | ||
73 | */ | ||
74 | data[0] = (reg << 1) | ((value >> 8) & 0x0001); | ||
75 | data[1] = value & 0x00ff; | ||
76 | |||
77 | wm8728_write_reg_cache(codec, reg, value); | ||
78 | |||
79 | if (codec->hw_write(codec->control_data, data, 2) == 2) | ||
80 | return 0; | ||
81 | else | ||
82 | return -EIO; | ||
83 | } | ||
84 | |||
85 | static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); | ||
86 | |||
87 | static const struct snd_kcontrol_new wm8728_snd_controls[] = { | ||
88 | |||
89 | SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL, | ||
90 | 0, 255, 0, wm8728_tlv), | ||
91 | |||
92 | SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0), | ||
93 | }; | ||
94 | |||
95 | static int wm8728_add_controls(struct snd_soc_codec *codec) | ||
96 | { | ||
97 | int err, i; | ||
98 | |||
99 | for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) { | ||
100 | err = snd_ctl_add(codec->card, | ||
101 | snd_soc_cnew(&wm8728_snd_controls[i], | ||
102 | codec, NULL)); | ||
103 | if (err < 0) | ||
104 | return err; | ||
105 | } | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | /* | ||
111 | * DAPM controls. | ||
112 | */ | ||
113 | static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = { | ||
114 | SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0), | ||
115 | SND_SOC_DAPM_OUTPUT("VOUTL"), | ||
116 | SND_SOC_DAPM_OUTPUT("VOUTR"), | ||
117 | }; | ||
118 | |||
119 | static const struct snd_soc_dapm_route intercon[] = { | ||
120 | {"VOUTL", NULL, "DAC"}, | ||
121 | {"VOUTR", NULL, "DAC"}, | ||
122 | }; | ||
123 | |||
124 | static int wm8728_add_widgets(struct snd_soc_codec *codec) | ||
125 | { | ||
126 | snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets, | ||
127 | ARRAY_SIZE(wm8728_dapm_widgets)); | ||
128 | |||
129 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
130 | |||
131 | snd_soc_dapm_new_widgets(codec); | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | static int wm8728_mute(struct snd_soc_dai *dai, int mute) | ||
137 | { | ||
138 | struct snd_soc_codec *codec = dai->codec; | ||
139 | u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); | ||
140 | |||
141 | if (mute) | ||
142 | wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); | ||
143 | else | ||
144 | wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static int wm8728_hw_params(struct snd_pcm_substream *substream, | ||
150 | struct snd_pcm_hw_params *params, | ||
151 | struct snd_soc_dai *dai) | ||
152 | { | ||
153 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
154 | struct snd_soc_device *socdev = rtd->socdev; | ||
155 | struct snd_soc_codec *codec = socdev->codec; | ||
156 | u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); | ||
157 | |||
158 | dac &= ~0x18; | ||
159 | |||
160 | switch (params_format(params)) { | ||
161 | case SNDRV_PCM_FORMAT_S16_LE: | ||
162 | break; | ||
163 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
164 | dac |= 0x10; | ||
165 | break; | ||
166 | case SNDRV_PCM_FORMAT_S24_LE: | ||
167 | dac |= 0x08; | ||
168 | break; | ||
169 | default: | ||
170 | return -EINVAL; | ||
171 | } | ||
172 | |||
173 | wm8728_write(codec, WM8728_DACCTL, dac); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
179 | unsigned int fmt) | ||
180 | { | ||
181 | struct snd_soc_codec *codec = codec_dai->codec; | ||
182 | u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); | ||
183 | |||
184 | /* Currently only I2S is supported by the driver, though the | ||
185 | * hardware is more flexible. | ||
186 | */ | ||
187 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
188 | case SND_SOC_DAIFMT_I2S: | ||
189 | iface |= 1; | ||
190 | break; | ||
191 | default: | ||
192 | return -EINVAL; | ||
193 | } | ||
194 | |||
195 | /* The hardware only support full slave mode */ | ||
196 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
197 | case SND_SOC_DAIFMT_CBS_CFS: | ||
198 | break; | ||
199 | default: | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
204 | case SND_SOC_DAIFMT_NB_NF: | ||
205 | iface &= ~0x22; | ||
206 | break; | ||
207 | case SND_SOC_DAIFMT_IB_NF: | ||
208 | iface |= 0x20; | ||
209 | iface &= ~0x02; | ||
210 | break; | ||
211 | case SND_SOC_DAIFMT_NB_IF: | ||
212 | iface |= 0x02; | ||
213 | iface &= ~0x20; | ||
214 | break; | ||
215 | case SND_SOC_DAIFMT_IB_IF: | ||
216 | iface |= 0x22; | ||
217 | break; | ||
218 | default: | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | wm8728_write(codec, WM8728_IFCTL, iface); | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static int wm8728_set_bias_level(struct snd_soc_codec *codec, | ||
227 | enum snd_soc_bias_level level) | ||
228 | { | ||
229 | u16 reg; | ||
230 | int i; | ||
231 | |||
232 | switch (level) { | ||
233 | case SND_SOC_BIAS_ON: | ||
234 | case SND_SOC_BIAS_PREPARE: | ||
235 | case SND_SOC_BIAS_STANDBY: | ||
236 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | ||
237 | /* Power everything up... */ | ||
238 | reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); | ||
239 | wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); | ||
240 | |||
241 | /* ..then sync in the register cache. */ | ||
242 | for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) | ||
243 | wm8728_write(codec, i, | ||
244 | wm8728_read_reg_cache(codec, i)); | ||
245 | } | ||
246 | break; | ||
247 | |||
248 | case SND_SOC_BIAS_OFF: | ||
249 | reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); | ||
250 | wm8728_write(codec, WM8728_DACCTL, reg | 0x4); | ||
251 | break; | ||
252 | } | ||
253 | codec->bias_level = level; | ||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | #define WM8728_RATES (SNDRV_PCM_RATE_8000_192000) | ||
258 | |||
259 | #define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | ||
260 | SNDRV_PCM_FMTBIT_S24_LE) | ||
261 | |||
262 | struct snd_soc_dai wm8728_dai = { | ||
263 | .name = "WM8728", | ||
264 | .playback = { | ||
265 | .stream_name = "Playback", | ||
266 | .channels_min = 2, | ||
267 | .channels_max = 2, | ||
268 | .rates = WM8728_RATES, | ||
269 | .formats = WM8728_FORMATS, | ||
270 | }, | ||
271 | .ops = { | ||
272 | .hw_params = wm8728_hw_params, | ||
273 | .digital_mute = wm8728_mute, | ||
274 | .set_fmt = wm8728_set_dai_fmt, | ||
275 | } | ||
276 | }; | ||
277 | EXPORT_SYMBOL_GPL(wm8728_dai); | ||
278 | |||
279 | static int wm8728_suspend(struct platform_device *pdev, pm_message_t state) | ||
280 | { | ||
281 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
282 | struct snd_soc_codec *codec = socdev->codec; | ||
283 | |||
284 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int wm8728_resume(struct platform_device *pdev) | ||
290 | { | ||
291 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
292 | struct snd_soc_codec *codec = socdev->codec; | ||
293 | |||
294 | wm8728_set_bias_level(codec, codec->suspend_bias_level); | ||
295 | |||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | /* | ||
300 | * initialise the WM8728 driver | ||
301 | * register the mixer and dsp interfaces with the kernel | ||
302 | */ | ||
303 | static int wm8728_init(struct snd_soc_device *socdev) | ||
304 | { | ||
305 | struct snd_soc_codec *codec = socdev->codec; | ||
306 | int ret = 0; | ||
307 | |||
308 | codec->name = "WM8728"; | ||
309 | codec->owner = THIS_MODULE; | ||
310 | codec->read = wm8728_read_reg_cache; | ||
311 | codec->write = wm8728_write; | ||
312 | codec->set_bias_level = wm8728_set_bias_level; | ||
313 | codec->dai = &wm8728_dai; | ||
314 | codec->num_dai = 1; | ||
315 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
316 | codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults); | ||
317 | codec->reg_cache = kmemdup(wm8728_reg_defaults, | ||
318 | sizeof(wm8728_reg_defaults), | ||
319 | GFP_KERNEL); | ||
320 | if (codec->reg_cache == NULL) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | /* register pcms */ | ||
324 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
325 | if (ret < 0) { | ||
326 | printk(KERN_ERR "wm8728: failed to create pcms\n"); | ||
327 | goto pcm_err; | ||
328 | } | ||
329 | |||
330 | /* power on device */ | ||
331 | wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
332 | |||
333 | wm8728_add_controls(codec); | ||
334 | wm8728_add_widgets(codec); | ||
335 | ret = snd_soc_init_card(socdev); | ||
336 | if (ret < 0) { | ||
337 | printk(KERN_ERR "wm8728: failed to register card\n"); | ||
338 | goto card_err; | ||
339 | } | ||
340 | |||
341 | return ret; | ||
342 | |||
343 | card_err: | ||
344 | snd_soc_free_pcms(socdev); | ||
345 | snd_soc_dapm_free(socdev); | ||
346 | pcm_err: | ||
347 | kfree(codec->reg_cache); | ||
348 | return ret; | ||
349 | } | ||
350 | |||
351 | static struct snd_soc_device *wm8728_socdev; | ||
352 | |||
353 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
354 | |||
355 | /* | ||
356 | * WM8728 2 wire address is determined by GPIO5 | ||
357 | * state during powerup. | ||
358 | * low = 0x1a | ||
359 | * high = 0x1b | ||
360 | */ | ||
361 | |||
362 | static int wm8728_i2c_probe(struct i2c_client *i2c, | ||
363 | const struct i2c_device_id *id) | ||
364 | { | ||
365 | struct snd_soc_device *socdev = wm8728_socdev; | ||
366 | struct snd_soc_codec *codec = socdev->codec; | ||
367 | int ret; | ||
368 | |||
369 | i2c_set_clientdata(i2c, codec); | ||
370 | codec->control_data = i2c; | ||
371 | |||
372 | ret = wm8728_init(socdev); | ||
373 | if (ret < 0) | ||
374 | pr_err("failed to initialise WM8728\n"); | ||
375 | |||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | static int wm8728_i2c_remove(struct i2c_client *client) | ||
380 | { | ||
381 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
382 | kfree(codec->reg_cache); | ||
383 | return 0; | ||
384 | } | ||
385 | |||
386 | static const struct i2c_device_id wm8728_i2c_id[] = { | ||
387 | { "wm8728", 0 }, | ||
388 | { } | ||
389 | }; | ||
390 | MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | ||
391 | |||
392 | static struct i2c_driver wm8728_i2c_driver = { | ||
393 | .driver = { | ||
394 | .name = "WM8728 I2C Codec", | ||
395 | .owner = THIS_MODULE, | ||
396 | }, | ||
397 | .probe = wm8728_i2c_probe, | ||
398 | .remove = wm8728_i2c_remove, | ||
399 | .id_table = wm8728_i2c_id, | ||
400 | }; | ||
401 | |||
402 | static int wm8728_add_i2c_device(struct platform_device *pdev, | ||
403 | const struct wm8728_setup_data *setup) | ||
404 | { | ||
405 | struct i2c_board_info info; | ||
406 | struct i2c_adapter *adapter; | ||
407 | struct i2c_client *client; | ||
408 | int ret; | ||
409 | |||
410 | ret = i2c_add_driver(&wm8728_i2c_driver); | ||
411 | if (ret != 0) { | ||
412 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
413 | return ret; | ||
414 | } | ||
415 | |||
416 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
417 | info.addr = setup->i2c_address; | ||
418 | strlcpy(info.type, "wm8728", I2C_NAME_SIZE); | ||
419 | |||
420 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
421 | if (!adapter) { | ||
422 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
423 | setup->i2c_bus); | ||
424 | goto err_driver; | ||
425 | } | ||
426 | |||
427 | client = i2c_new_device(adapter, &info); | ||
428 | i2c_put_adapter(adapter); | ||
429 | if (!client) { | ||
430 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
431 | (unsigned int)info.addr); | ||
432 | goto err_driver; | ||
433 | } | ||
434 | |||
435 | return 0; | ||
436 | |||
437 | err_driver: | ||
438 | i2c_del_driver(&wm8728_i2c_driver); | ||
439 | return -ENODEV; | ||
440 | } | ||
441 | #endif | ||
442 | |||
443 | #if defined(CONFIG_SPI_MASTER) | ||
444 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | ||
445 | { | ||
446 | struct snd_soc_device *socdev = wm8728_socdev; | ||
447 | struct snd_soc_codec *codec = socdev->codec; | ||
448 | int ret; | ||
449 | |||
450 | codec->control_data = spi; | ||
451 | |||
452 | ret = wm8728_init(socdev); | ||
453 | if (ret < 0) | ||
454 | dev_err(&spi->dev, "failed to initialise WM8728\n"); | ||
455 | |||
456 | return ret; | ||
457 | } | ||
458 | |||
459 | static int __devexit wm8728_spi_remove(struct spi_device *spi) | ||
460 | { | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static struct spi_driver wm8728_spi_driver = { | ||
465 | .driver = { | ||
466 | .name = "wm8728", | ||
467 | .bus = &spi_bus_type, | ||
468 | .owner = THIS_MODULE, | ||
469 | }, | ||
470 | .probe = wm8728_spi_probe, | ||
471 | .remove = __devexit_p(wm8728_spi_remove), | ||
472 | }; | ||
473 | |||
474 | static int wm8728_spi_write(struct spi_device *spi, const char *data, int len) | ||
475 | { | ||
476 | struct spi_transfer t; | ||
477 | struct spi_message m; | ||
478 | u8 msg[2]; | ||
479 | |||
480 | if (len <= 0) | ||
481 | return 0; | ||
482 | |||
483 | msg[0] = data[0]; | ||
484 | msg[1] = data[1]; | ||
485 | |||
486 | spi_message_init(&m); | ||
487 | memset(&t, 0, (sizeof t)); | ||
488 | |||
489 | t.tx_buf = &msg[0]; | ||
490 | t.len = len; | ||
491 | |||
492 | spi_message_add_tail(&t, &m); | ||
493 | spi_sync(spi, &m); | ||
494 | |||
495 | return len; | ||
496 | } | ||
497 | #endif /* CONFIG_SPI_MASTER */ | ||
498 | |||
499 | static int wm8728_probe(struct platform_device *pdev) | ||
500 | { | ||
501 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
502 | struct wm8728_setup_data *setup; | ||
503 | struct snd_soc_codec *codec; | ||
504 | int ret = 0; | ||
505 | |||
506 | setup = socdev->codec_data; | ||
507 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
508 | if (codec == NULL) | ||
509 | return -ENOMEM; | ||
510 | |||
511 | socdev->codec = codec; | ||
512 | mutex_init(&codec->mutex); | ||
513 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
514 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
515 | |||
516 | wm8728_socdev = socdev; | ||
517 | ret = -ENODEV; | ||
518 | |||
519 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
520 | if (setup->i2c_address) { | ||
521 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
522 | ret = wm8728_add_i2c_device(pdev, setup); | ||
523 | } | ||
524 | #endif | ||
525 | #if defined(CONFIG_SPI_MASTER) | ||
526 | if (setup->spi) { | ||
527 | codec->hw_write = (hw_write_t)wm8728_spi_write; | ||
528 | ret = spi_register_driver(&wm8728_spi_driver); | ||
529 | if (ret != 0) | ||
530 | printk(KERN_ERR "can't add spi driver"); | ||
531 | } | ||
532 | #endif | ||
533 | |||
534 | if (ret != 0) | ||
535 | kfree(codec); | ||
536 | |||
537 | return ret; | ||
538 | } | ||
539 | |||
540 | /* power down chip */ | ||
541 | static int wm8728_remove(struct platform_device *pdev) | ||
542 | { | ||
543 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
544 | struct snd_soc_codec *codec = socdev->codec; | ||
545 | |||
546 | if (codec->control_data) | ||
547 | wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
548 | |||
549 | snd_soc_free_pcms(socdev); | ||
550 | snd_soc_dapm_free(socdev); | ||
551 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
552 | i2c_unregister_device(codec->control_data); | ||
553 | i2c_del_driver(&wm8728_i2c_driver); | ||
554 | #endif | ||
555 | #if defined(CONFIG_SPI_MASTER) | ||
556 | spi_unregister_driver(&wm8728_spi_driver); | ||
557 | #endif | ||
558 | kfree(codec); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | struct snd_soc_codec_device soc_codec_dev_wm8728 = { | ||
564 | .probe = wm8728_probe, | ||
565 | .remove = wm8728_remove, | ||
566 | .suspend = wm8728_suspend, | ||
567 | .resume = wm8728_resume, | ||
568 | }; | ||
569 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728); | ||
570 | |||
571 | static int __init wm8728_modinit(void) | ||
572 | { | ||
573 | return snd_soc_register_dai(&wm8728_dai); | ||
574 | } | ||
575 | module_init(wm8728_modinit); | ||
576 | |||
577 | static void __exit wm8728_exit(void) | ||
578 | { | ||
579 | snd_soc_unregister_dai(&wm8728_dai); | ||
580 | } | ||
581 | module_exit(wm8728_exit); | ||
582 | |||
583 | MODULE_DESCRIPTION("ASoC WM8728 driver"); | ||
584 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
585 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h new file mode 100644 index 000000000000..d269c132474b --- /dev/null +++ b/sound/soc/codecs/wm8728.h | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * wm8728.h -- WM8728 ASoC codec driver | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef _WM8728_H | ||
14 | #define _WM8728_H | ||
15 | |||
16 | #define WM8728_DACLVOL 0x00 | ||
17 | #define WM8728_DACRVOL 0x01 | ||
18 | #define WM8728_DACCTL 0x02 | ||
19 | #define WM8728_IFCTL 0x03 | ||
20 | |||
21 | struct wm8728_setup_data { | ||
22 | int spi; | ||
23 | int i2c_bus; | ||
24 | unsigned short i2c_address; | ||
25 | }; | ||
26 | |||
27 | extern struct snd_soc_dai wm8728_dai; | ||
28 | extern struct snd_soc_codec_device soc_codec_dev_wm8728; | ||
29 | |||
30 | #endif | ||
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 7f8a7e36b33e..c444b9f2701e 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -264,7 +264,8 @@ static inline int get_coeff(int mclk, int rate) | |||
264 | } | 264 | } |
265 | 265 | ||
266 | static int wm8731_hw_params(struct snd_pcm_substream *substream, | 266 | static int wm8731_hw_params(struct snd_pcm_substream *substream, |
267 | struct snd_pcm_hw_params *params) | 267 | struct snd_pcm_hw_params *params, |
268 | struct snd_soc_dai *dai) | ||
268 | { | 269 | { |
269 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 270 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
270 | struct snd_soc_device *socdev = rtd->socdev; | 271 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -293,7 +294,8 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream, | |||
293 | return 0; | 294 | return 0; |
294 | } | 295 | } |
295 | 296 | ||
296 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream) | 297 | static int wm8731_pcm_prepare(struct snd_pcm_substream *substream, |
298 | struct snd_soc_dai *dai) | ||
297 | { | 299 | { |
298 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 300 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
299 | struct snd_soc_device *socdev = rtd->socdev; | 301 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -305,7 +307,8 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream) | |||
305 | return 0; | 307 | return 0; |
306 | } | 308 | } |
307 | 309 | ||
308 | static void wm8731_shutdown(struct snd_pcm_substream *substream) | 310 | static void wm8731_shutdown(struct snd_pcm_substream *substream, |
311 | struct snd_soc_dai *dai) | ||
309 | { | 312 | { |
310 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 313 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
311 | struct snd_soc_device *socdev = rtd->socdev; | 314 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -461,8 +464,6 @@ struct snd_soc_dai wm8731_dai = { | |||
461 | .prepare = wm8731_pcm_prepare, | 464 | .prepare = wm8731_pcm_prepare, |
462 | .hw_params = wm8731_hw_params, | 465 | .hw_params = wm8731_hw_params, |
463 | .shutdown = wm8731_shutdown, | 466 | .shutdown = wm8731_shutdown, |
464 | }, | ||
465 | .dai_ops = { | ||
466 | .digital_mute = wm8731_mute, | 467 | .digital_mute = wm8731_mute, |
467 | .set_sysclk = wm8731_set_dai_sysclk, | 468 | .set_sysclk = wm8731_set_dai_sysclk, |
468 | .set_fmt = wm8731_set_dai_fmt, | 469 | .set_fmt = wm8731_set_dai_fmt, |
@@ -544,7 +545,7 @@ static int wm8731_init(struct snd_soc_device *socdev) | |||
544 | 545 | ||
545 | wm8731_add_controls(codec); | 546 | wm8731_add_controls(codec); |
546 | wm8731_add_widgets(codec); | 547 | wm8731_add_widgets(codec); |
547 | ret = snd_soc_register_card(socdev); | 548 | ret = snd_soc_init_card(socdev); |
548 | if (ret < 0) { | 549 | if (ret < 0) { |
549 | printk(KERN_ERR "wm8731: failed to register card\n"); | 550 | printk(KERN_ERR "wm8731: failed to register card\n"); |
550 | goto card_err; | 551 | goto card_err; |
@@ -792,6 +793,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = { | |||
792 | }; | 793 | }; |
793 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | 794 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); |
794 | 795 | ||
796 | static int __init wm8731_modinit(void) | ||
797 | { | ||
798 | return snd_soc_register_dai(&wm8731_dai); | ||
799 | } | ||
800 | module_init(wm8731_modinit); | ||
801 | |||
802 | static void __exit wm8731_exit(void) | ||
803 | { | ||
804 | snd_soc_unregister_dai(&wm8731_dai); | ||
805 | } | ||
806 | module_exit(wm8731_exit); | ||
807 | |||
795 | MODULE_DESCRIPTION("ASoC WM8731 driver"); | 808 | MODULE_DESCRIPTION("ASoC WM8731 driver"); |
796 | MODULE_AUTHOR("Richard Purdie"); | 809 | MODULE_AUTHOR("Richard Purdie"); |
797 | MODULE_LICENSE("GPL"); | 810 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 9b7296ee5b08..5997fa68e0d5 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -614,7 +614,8 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
614 | } | 614 | } |
615 | 615 | ||
616 | static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, | 616 | static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream, |
617 | struct snd_pcm_hw_params *params) | 617 | struct snd_pcm_hw_params *params, |
618 | struct snd_soc_dai *dai) | ||
618 | { | 619 | { |
619 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 620 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
620 | struct snd_soc_device *socdev = rtd->socdev; | 621 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -709,8 +710,6 @@ struct snd_soc_dai wm8750_dai = { | |||
709 | .formats = WM8750_FORMATS,}, | 710 | .formats = WM8750_FORMATS,}, |
710 | .ops = { | 711 | .ops = { |
711 | .hw_params = wm8750_pcm_hw_params, | 712 | .hw_params = wm8750_pcm_hw_params, |
712 | }, | ||
713 | .dai_ops = { | ||
714 | .digital_mute = wm8750_mute, | 713 | .digital_mute = wm8750_mute, |
715 | .set_fmt = wm8750_set_dai_fmt, | 714 | .set_fmt = wm8750_set_dai_fmt, |
716 | .set_sysclk = wm8750_set_dai_sysclk, | 715 | .set_sysclk = wm8750_set_dai_sysclk, |
@@ -819,7 +818,7 @@ static int wm8750_init(struct snd_soc_device *socdev) | |||
819 | 818 | ||
820 | wm8750_add_controls(codec); | 819 | wm8750_add_controls(codec); |
821 | wm8750_add_widgets(codec); | 820 | wm8750_add_widgets(codec); |
822 | ret = snd_soc_register_card(socdev); | 821 | ret = snd_soc_init_card(socdev); |
823 | if (ret < 0) { | 822 | if (ret < 0) { |
824 | printk(KERN_ERR "wm8750: failed to register card\n"); | 823 | printk(KERN_ERR "wm8750: failed to register card\n"); |
825 | goto card_err; | 824 | goto card_err; |
@@ -1086,6 +1085,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = { | |||
1086 | }; | 1085 | }; |
1087 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); | 1086 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); |
1088 | 1087 | ||
1088 | static int __init wm8750_modinit(void) | ||
1089 | { | ||
1090 | return snd_soc_register_dai(&wm8750_dai); | ||
1091 | } | ||
1092 | module_init(wm8750_modinit); | ||
1093 | |||
1094 | static void __exit wm8750_exit(void) | ||
1095 | { | ||
1096 | snd_soc_unregister_dai(&wm8750_dai); | ||
1097 | } | ||
1098 | module_exit(wm8750_exit); | ||
1099 | |||
1089 | MODULE_DESCRIPTION("ASoC WM8750 driver"); | 1100 | MODULE_DESCRIPTION("ASoC WM8750 driver"); |
1090 | MODULE_AUTHOR("Liam Girdwood"); | 1101 | MODULE_AUTHOR("Liam Girdwood"); |
1091 | MODULE_LICENSE("GPL"); | 1102 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index d426eaa22185..6c21b50c9375 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -922,7 +922,8 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
922 | * Set PCM DAI bit size and sample rate. | 922 | * Set PCM DAI bit size and sample rate. |
923 | */ | 923 | */ |
924 | static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, | 924 | static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream, |
925 | struct snd_pcm_hw_params *params) | 925 | struct snd_pcm_hw_params *params, |
926 | struct snd_soc_dai *dai) | ||
926 | { | 927 | { |
927 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 928 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
928 | struct snd_soc_device *socdev = rtd->socdev; | 929 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1155,7 +1156,8 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1155 | * Set PCM DAI bit size and sample rate. | 1156 | * Set PCM DAI bit size and sample rate. |
1156 | */ | 1157 | */ |
1157 | static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, | 1158 | static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream, |
1158 | struct snd_pcm_hw_params *params) | 1159 | struct snd_pcm_hw_params *params, |
1160 | struct snd_soc_dai *dai) | ||
1159 | { | 1161 | { |
1160 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1162 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1161 | struct snd_soc_device *socdev = rtd->socdev; | 1163 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1323,16 +1325,15 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1323 | .channels_min = 1, | 1325 | .channels_min = 1, |
1324 | .channels_max = 2, | 1326 | .channels_max = 2, |
1325 | .rates = WM8753_RATES, | 1327 | .rates = WM8753_RATES, |
1326 | .formats = WM8753_FORMATS,}, | 1328 | .formats = WM8753_FORMATS}, |
1327 | .capture = { /* dummy for fast DAI switching */ | 1329 | .capture = { /* dummy for fast DAI switching */ |
1328 | .stream_name = "Capture", | 1330 | .stream_name = "Capture", |
1329 | .channels_min = 1, | 1331 | .channels_min = 1, |
1330 | .channels_max = 2, | 1332 | .channels_max = 2, |
1331 | .rates = WM8753_RATES, | 1333 | .rates = WM8753_RATES, |
1332 | .formats = WM8753_FORMATS,}, | 1334 | .formats = WM8753_FORMATS}, |
1333 | .ops = { | 1335 | .ops = { |
1334 | .hw_params = wm8753_i2s_hw_params,}, | 1336 | .hw_params = wm8753_i2s_hw_params, |
1335 | .dai_ops = { | ||
1336 | .digital_mute = wm8753_mute, | 1337 | .digital_mute = wm8753_mute, |
1337 | .set_fmt = wm8753_mode1h_set_dai_fmt, | 1338 | .set_fmt = wm8753_mode1h_set_dai_fmt, |
1338 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1339 | .set_clkdiv = wm8753_set_dai_clkdiv, |
@@ -1356,8 +1357,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1356 | .rates = WM8753_RATES, | 1357 | .rates = WM8753_RATES, |
1357 | .formats = WM8753_FORMATS,}, | 1358 | .formats = WM8753_FORMATS,}, |
1358 | .ops = { | 1359 | .ops = { |
1359 | .hw_params = wm8753_pcm_hw_params,}, | 1360 | .hw_params = wm8753_pcm_hw_params, |
1360 | .dai_ops = { | ||
1361 | .digital_mute = wm8753_mute, | 1361 | .digital_mute = wm8753_mute, |
1362 | .set_fmt = wm8753_mode1v_set_dai_fmt, | 1362 | .set_fmt = wm8753_mode1v_set_dai_fmt, |
1363 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1363 | .set_clkdiv = wm8753_set_dai_clkdiv, |
@@ -1385,8 +1385,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1385 | .rates = WM8753_RATES, | 1385 | .rates = WM8753_RATES, |
1386 | .formats = WM8753_FORMATS,}, | 1386 | .formats = WM8753_FORMATS,}, |
1387 | .ops = { | 1387 | .ops = { |
1388 | .hw_params = wm8753_pcm_hw_params,}, | 1388 | .hw_params = wm8753_pcm_hw_params, |
1389 | .dai_ops = { | ||
1390 | .digital_mute = wm8753_mute, | 1389 | .digital_mute = wm8753_mute, |
1391 | .set_fmt = wm8753_mode2_set_dai_fmt, | 1390 | .set_fmt = wm8753_mode2_set_dai_fmt, |
1392 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1391 | .set_clkdiv = wm8753_set_dai_clkdiv, |
@@ -1410,8 +1409,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1410 | .rates = WM8753_RATES, | 1409 | .rates = WM8753_RATES, |
1411 | .formats = WM8753_FORMATS,}, | 1410 | .formats = WM8753_FORMATS,}, |
1412 | .ops = { | 1411 | .ops = { |
1413 | .hw_params = wm8753_i2s_hw_params,}, | 1412 | .hw_params = wm8753_i2s_hw_params, |
1414 | .dai_ops = { | ||
1415 | .digital_mute = wm8753_mute, | 1413 | .digital_mute = wm8753_mute, |
1416 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1414 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
1417 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1415 | .set_clkdiv = wm8753_set_dai_clkdiv, |
@@ -1439,8 +1437,7 @@ static const struct snd_soc_dai wm8753_all_dai[] = { | |||
1439 | .rates = WM8753_RATES, | 1437 | .rates = WM8753_RATES, |
1440 | .formats = WM8753_FORMATS,}, | 1438 | .formats = WM8753_FORMATS,}, |
1441 | .ops = { | 1439 | .ops = { |
1442 | .hw_params = wm8753_i2s_hw_params,}, | 1440 | .hw_params = wm8753_i2s_hw_params, |
1443 | .dai_ops = { | ||
1444 | .digital_mute = wm8753_mute, | 1441 | .digital_mute = wm8753_mute, |
1445 | .set_fmt = wm8753_mode3_4_set_dai_fmt, | 1442 | .set_fmt = wm8753_mode3_4_set_dai_fmt, |
1446 | .set_clkdiv = wm8753_set_dai_clkdiv, | 1443 | .set_clkdiv = wm8753_set_dai_clkdiv, |
@@ -1608,7 +1605,7 @@ static int wm8753_init(struct snd_soc_device *socdev) | |||
1608 | 1605 | ||
1609 | wm8753_add_controls(codec); | 1606 | wm8753_add_controls(codec); |
1610 | wm8753_add_widgets(codec); | 1607 | wm8753_add_widgets(codec); |
1611 | ret = snd_soc_register_card(socdev); | 1608 | ret = snd_soc_init_card(socdev); |
1612 | if (ret < 0) { | 1609 | if (ret < 0) { |
1613 | printk(KERN_ERR "wm8753: failed to register card\n"); | 1610 | printk(KERN_ERR "wm8753: failed to register card\n"); |
1614 | goto card_err; | 1611 | goto card_err; |
@@ -1877,6 +1874,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = { | |||
1877 | }; | 1874 | }; |
1878 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); | 1875 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753); |
1879 | 1876 | ||
1877 | static int __init wm8753_modinit(void) | ||
1878 | { | ||
1879 | return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1880 | } | ||
1881 | module_init(wm8753_modinit); | ||
1882 | |||
1883 | static void __exit wm8753_exit(void) | ||
1884 | { | ||
1885 | snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai)); | ||
1886 | } | ||
1887 | module_exit(wm8753_exit); | ||
1888 | |||
1880 | MODULE_DESCRIPTION("ASoC WM8753 driver"); | 1889 | MODULE_DESCRIPTION("ASoC WM8753 driver"); |
1881 | MODULE_AUTHOR("Liam Girdwood"); | 1890 | MODULE_AUTHOR("Liam Girdwood"); |
1882 | MODULE_LICENSE("GPL"); | 1891 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c index 3b326c9b5586..6767de10ded0 100644 --- a/sound/soc/codecs/wm8900.c +++ b/sound/soc/codecs/wm8900.c | |||
@@ -138,6 +138,10 @@ | |||
138 | struct snd_soc_codec_device soc_codec_dev_wm8900; | 138 | struct snd_soc_codec_device soc_codec_dev_wm8900; |
139 | 139 | ||
140 | struct wm8900_priv { | 140 | struct wm8900_priv { |
141 | struct snd_soc_codec codec; | ||
142 | |||
143 | u16 reg_cache[WM8900_MAXREG]; | ||
144 | |||
141 | u32 fll_in; /* FLL input frequency */ | 145 | u32 fll_in; /* FLL input frequency */ |
142 | u32 fll_out; /* FLL output frequency */ | 146 | u32 fll_out; /* FLL output frequency */ |
143 | }; | 147 | }; |
@@ -727,7 +731,8 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec) | |||
727 | } | 731 | } |
728 | 732 | ||
729 | static int wm8900_hw_params(struct snd_pcm_substream *substream, | 733 | static int wm8900_hw_params(struct snd_pcm_substream *substream, |
730 | struct snd_pcm_hw_params *params) | 734 | struct snd_pcm_hw_params *params, |
735 | struct snd_soc_dai *dai) | ||
731 | { | 736 | { |
732 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 737 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
733 | struct snd_soc_device *socdev = rtd->socdev; | 738 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1117,8 +1122,6 @@ struct snd_soc_dai wm8900_dai = { | |||
1117 | }, | 1122 | }, |
1118 | .ops = { | 1123 | .ops = { |
1119 | .hw_params = wm8900_hw_params, | 1124 | .hw_params = wm8900_hw_params, |
1120 | }, | ||
1121 | .dai_ops = { | ||
1122 | .set_clkdiv = wm8900_set_dai_clkdiv, | 1125 | .set_clkdiv = wm8900_set_dai_clkdiv, |
1123 | .set_pll = wm8900_set_dai_pll, | 1126 | .set_pll = wm8900_set_dai_pll, |
1124 | .set_fmt = wm8900_set_dai_fmt, | 1127 | .set_fmt = wm8900_set_dai_fmt, |
@@ -1283,16 +1286,28 @@ static int wm8900_resume(struct platform_device *pdev) | |||
1283 | return 0; | 1286 | return 0; |
1284 | } | 1287 | } |
1285 | 1288 | ||
1286 | /* | 1289 | static struct snd_soc_codec *wm8900_codec; |
1287 | * initialise the WM8900 driver | 1290 | |
1288 | * register the mixer and dsp interfaces with the kernel | 1291 | static int wm8900_i2c_probe(struct i2c_client *i2c, |
1289 | */ | 1292 | const struct i2c_device_id *id) |
1290 | static int wm8900_init(struct snd_soc_device *socdev) | ||
1291 | { | 1293 | { |
1292 | struct snd_soc_codec *codec = socdev->codec; | 1294 | struct wm8900_priv *wm8900; |
1293 | int ret = 0; | 1295 | struct snd_soc_codec *codec; |
1294 | unsigned int reg; | 1296 | unsigned int reg; |
1295 | struct i2c_client *i2c_client = socdev->codec->control_data; | 1297 | int ret; |
1298 | |||
1299 | wm8900 = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1300 | if (wm8900 == NULL) | ||
1301 | return -ENOMEM; | ||
1302 | |||
1303 | codec = &wm8900->codec; | ||
1304 | codec->private_data = wm8900; | ||
1305 | codec->reg_cache = &wm8900->reg_cache[0]; | ||
1306 | codec->reg_cache_size = WM8900_MAXREG; | ||
1307 | |||
1308 | mutex_init(&codec->mutex); | ||
1309 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1310 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1296 | 1311 | ||
1297 | codec->name = "WM8900"; | 1312 | codec->name = "WM8900"; |
1298 | codec->owner = THIS_MODULE; | 1313 | codec->owner = THIS_MODULE; |
@@ -1300,33 +1315,28 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1300 | codec->write = wm8900_write; | 1315 | codec->write = wm8900_write; |
1301 | codec->dai = &wm8900_dai; | 1316 | codec->dai = &wm8900_dai; |
1302 | codec->num_dai = 1; | 1317 | codec->num_dai = 1; |
1303 | codec->reg_cache_size = WM8900_MAXREG; | 1318 | codec->hw_write = (hw_write_t)i2c_master_send; |
1304 | codec->reg_cache = kmemdup(wm8900_reg_defaults, | 1319 | codec->control_data = i2c; |
1305 | sizeof(wm8900_reg_defaults), GFP_KERNEL); | 1320 | codec->set_bias_level = wm8900_set_bias_level; |
1306 | 1321 | codec->dev = &i2c->dev; | |
1307 | if (codec->reg_cache == NULL) | ||
1308 | return -ENOMEM; | ||
1309 | 1322 | ||
1310 | reg = wm8900_read(codec, WM8900_REG_ID); | 1323 | reg = wm8900_read(codec, WM8900_REG_ID); |
1311 | if (reg != 0x8900) { | 1324 | if (reg != 0x8900) { |
1312 | dev_err(&i2c_client->dev, "Device is not a WM8900 - ID %x\n", | 1325 | dev_err(&i2c->dev, "Device is not a WM8900 - ID %x\n", reg); |
1313 | reg); | 1326 | ret = -ENODEV; |
1314 | return -ENODEV; | 1327 | goto err; |
1315 | } | ||
1316 | |||
1317 | codec->private_data = kzalloc(sizeof(struct wm8900_priv), GFP_KERNEL); | ||
1318 | if (codec->private_data == NULL) { | ||
1319 | ret = -ENOMEM; | ||
1320 | goto priv_err; | ||
1321 | } | 1328 | } |
1322 | 1329 | ||
1323 | /* Read back from the chip */ | 1330 | /* Read back from the chip */ |
1324 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); | 1331 | reg = wm8900_chip_read(codec, WM8900_REG_POWER1); |
1325 | reg = (reg >> 12) & 0xf; | 1332 | reg = (reg >> 12) & 0xf; |
1326 | dev_info(&i2c_client->dev, "WM8900 revision %d\n", reg); | 1333 | dev_info(&i2c->dev, "WM8900 revision %d\n", reg); |
1327 | 1334 | ||
1328 | wm8900_reset(codec); | 1335 | wm8900_reset(codec); |
1329 | 1336 | ||
1337 | /* Turn the chip on */ | ||
1338 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1339 | |||
1330 | /* Latch the volume update bits */ | 1340 | /* Latch the volume update bits */ |
1331 | wm8900_write(codec, WM8900_REG_LINVOL, | 1341 | wm8900_write(codec, WM8900_REG_LINVOL, |
1332 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); | 1342 | wm8900_read(codec, WM8900_REG_LINVOL) | 0x100); |
@@ -1352,160 +1362,98 @@ static int wm8900_init(struct snd_soc_device *socdev) | |||
1352 | /* Set the DAC and mixer output bias */ | 1362 | /* Set the DAC and mixer output bias */ |
1353 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); | 1363 | wm8900_write(codec, WM8900_REG_OUTBIASCTL, 0x81); |
1354 | 1364 | ||
1355 | /* Register pcms */ | 1365 | wm8900_dai.dev = &i2c->dev; |
1356 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1357 | if (ret < 0) { | ||
1358 | dev_err(&i2c_client->dev, "Failed to register new PCMs\n"); | ||
1359 | goto pcm_err; | ||
1360 | } | ||
1361 | |||
1362 | /* Turn the chip on */ | ||
1363 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
1364 | wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1365 | |||
1366 | wm8900_add_controls(codec); | ||
1367 | wm8900_add_widgets(codec); | ||
1368 | |||
1369 | ret = snd_soc_register_card(socdev); | ||
1370 | if (ret < 0) { | ||
1371 | dev_err(&i2c_client->dev, "Failed to register card\n"); | ||
1372 | goto card_err; | ||
1373 | } | ||
1374 | return ret; | ||
1375 | |||
1376 | card_err: | ||
1377 | snd_soc_free_pcms(socdev); | ||
1378 | snd_soc_dapm_free(socdev); | ||
1379 | pcm_err: | ||
1380 | kfree(codec->reg_cache); | ||
1381 | priv_err: | ||
1382 | kfree(codec->private_data); | ||
1383 | return ret; | ||
1384 | } | ||
1385 | 1366 | ||
1386 | static struct snd_soc_device *wm8900_socdev; | 1367 | wm8900_codec = codec; |
1387 | 1368 | ||
1388 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1369 | ret = snd_soc_register_codec(codec); |
1389 | 1370 | if (ret != 0) { | |
1390 | static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; | 1371 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1391 | |||
1392 | /* Magic definition of all other variables and things */ | ||
1393 | I2C_CLIENT_INSMOD; | ||
1394 | |||
1395 | static struct i2c_driver wm8900_i2c_driver; | ||
1396 | static struct i2c_client client_template; | ||
1397 | |||
1398 | /* If the i2c layer weren't so broken, we could pass this kind of data | ||
1399 | around */ | ||
1400 | static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind) | ||
1401 | { | ||
1402 | struct snd_soc_device *socdev = wm8900_socdev; | ||
1403 | struct wm8900_setup_data *setup = socdev->codec_data; | ||
1404 | struct snd_soc_codec *codec = socdev->codec; | ||
1405 | struct i2c_client *i2c; | ||
1406 | int ret; | ||
1407 | |||
1408 | if (addr != setup->i2c_address) | ||
1409 | return -ENODEV; | ||
1410 | |||
1411 | dev_err(&adap->dev, "Probe on %x\n", addr); | ||
1412 | |||
1413 | client_template.adapter = adap; | ||
1414 | client_template.addr = addr; | ||
1415 | |||
1416 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
1417 | if (i2c == NULL) { | ||
1418 | kfree(codec); | ||
1419 | return -ENOMEM; | ||
1420 | } | ||
1421 | i2c_set_clientdata(i2c, codec); | ||
1422 | codec->control_data = i2c; | ||
1423 | |||
1424 | ret = i2c_attach_client(i2c); | ||
1425 | if (ret < 0) { | ||
1426 | dev_err(&adap->dev, | ||
1427 | "failed to attach codec at addr %x\n", addr); | ||
1428 | goto err; | 1372 | goto err; |
1429 | } | 1373 | } |
1430 | 1374 | ||
1431 | ret = wm8900_init(socdev); | 1375 | ret = snd_soc_register_dai(&wm8900_dai); |
1432 | if (ret < 0) { | 1376 | if (ret != 0) { |
1433 | dev_err(&adap->dev, "failed to initialise WM8900\n"); | 1377 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); |
1434 | goto err; | 1378 | goto err_codec; |
1435 | } | 1379 | } |
1380 | |||
1436 | return ret; | 1381 | return ret; |
1437 | 1382 | ||
1383 | err_codec: | ||
1384 | snd_soc_unregister_codec(codec); | ||
1438 | err: | 1385 | err: |
1439 | kfree(codec); | 1386 | kfree(wm8900); |
1440 | kfree(i2c); | 1387 | wm8900_codec = NULL; |
1441 | return ret; | 1388 | return ret; |
1442 | } | 1389 | } |
1443 | 1390 | ||
1444 | static int wm8900_i2c_detach(struct i2c_client *client) | 1391 | static int wm8900_i2c_remove(struct i2c_client *client) |
1445 | { | 1392 | { |
1446 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 1393 | snd_soc_unregister_dai(&wm8900_dai); |
1447 | i2c_detach_client(client); | 1394 | snd_soc_unregister_codec(wm8900_codec); |
1448 | kfree(codec->reg_cache); | 1395 | |
1449 | kfree(client); | 1396 | wm8900_set_bias_level(wm8900_codec, SND_SOC_BIAS_OFF); |
1397 | |||
1398 | wm8900_dai.dev = NULL; | ||
1399 | kfree(wm8900_codec->private_data); | ||
1400 | wm8900_codec = NULL; | ||
1401 | |||
1450 | return 0; | 1402 | return 0; |
1451 | } | 1403 | } |
1452 | 1404 | ||
1453 | static int wm8900_i2c_attach(struct i2c_adapter *adap) | 1405 | static const struct i2c_device_id wm8900_i2c_id[] = { |
1454 | { | 1406 | { "wm8900", 0 }, |
1455 | return i2c_probe(adap, &addr_data, wm8900_codec_probe); | 1407 | { } |
1456 | } | 1408 | }; |
1409 | MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id); | ||
1457 | 1410 | ||
1458 | /* corgi i2c codec control layer */ | ||
1459 | static struct i2c_driver wm8900_i2c_driver = { | 1411 | static struct i2c_driver wm8900_i2c_driver = { |
1460 | .driver = { | 1412 | .driver = { |
1461 | .name = "WM8900 I2C codec", | 1413 | .name = "WM8900", |
1462 | .owner = THIS_MODULE, | 1414 | .owner = THIS_MODULE, |
1463 | }, | 1415 | }, |
1464 | .attach_adapter = wm8900_i2c_attach, | 1416 | .probe = wm8900_i2c_probe, |
1465 | .detach_client = wm8900_i2c_detach, | 1417 | .remove = wm8900_i2c_remove, |
1466 | .command = NULL, | 1418 | .id_table = wm8900_i2c_id, |
1467 | }; | ||
1468 | |||
1469 | static struct i2c_client client_template = { | ||
1470 | .name = "WM8900", | ||
1471 | .driver = &wm8900_i2c_driver, | ||
1472 | }; | 1419 | }; |
1473 | #endif | ||
1474 | 1420 | ||
1475 | static int wm8900_probe(struct platform_device *pdev) | 1421 | static int wm8900_probe(struct platform_device *pdev) |
1476 | { | 1422 | { |
1477 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1478 | struct wm8900_setup_data *setup; | ||
1479 | struct snd_soc_codec *codec; | 1424 | struct snd_soc_codec *codec; |
1480 | int ret = 0; | 1425 | int ret = 0; |
1481 | 1426 | ||
1482 | dev_info(&pdev->dev, "WM8900 Audio Codec\n"); | 1427 | if (!wm8900_codec) { |
1483 | 1428 | dev_err(&pdev->dev, "I2C client not yet instantiated\n"); | |
1484 | setup = socdev->codec_data; | 1429 | return -ENODEV; |
1485 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1430 | } |
1486 | if (codec == NULL) | ||
1487 | return -ENOMEM; | ||
1488 | |||
1489 | mutex_init(&codec->mutex); | ||
1490 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1491 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1492 | 1431 | ||
1432 | codec = wm8900_codec; | ||
1493 | socdev->codec = codec; | 1433 | socdev->codec = codec; |
1494 | 1434 | ||
1495 | codec->set_bias_level = wm8900_set_bias_level; | 1435 | /* Register pcms */ |
1436 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1437 | if (ret < 0) { | ||
1438 | dev_err(&pdev->dev, "Failed to register new PCMs\n"); | ||
1439 | goto pcm_err; | ||
1440 | } | ||
1496 | 1441 | ||
1497 | wm8900_socdev = socdev; | 1442 | wm8900_add_controls(codec); |
1498 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1443 | wm8900_add_widgets(codec); |
1499 | if (setup->i2c_address) { | 1444 | |
1500 | normal_i2c[0] = setup->i2c_address; | 1445 | ret = snd_soc_init_card(socdev); |
1501 | codec->hw_write = (hw_write_t)i2c_master_send; | 1446 | if (ret < 0) { |
1502 | ret = i2c_add_driver(&wm8900_i2c_driver); | 1447 | dev_err(&pdev->dev, "Failed to register card\n"); |
1503 | if (ret != 0) | 1448 | goto card_err; |
1504 | printk(KERN_ERR "can't add i2c driver"); | ||
1505 | } | 1449 | } |
1506 | #else | 1450 | |
1507 | #error Non-I2C interfaces not yet supported | 1451 | return ret; |
1508 | #endif | 1452 | |
1453 | card_err: | ||
1454 | snd_soc_free_pcms(socdev); | ||
1455 | snd_soc_dapm_free(socdev); | ||
1456 | pcm_err: | ||
1509 | return ret; | 1457 | return ret; |
1510 | } | 1458 | } |
1511 | 1459 | ||
@@ -1513,17 +1461,9 @@ static int wm8900_probe(struct platform_device *pdev) | |||
1513 | static int wm8900_remove(struct platform_device *pdev) | 1461 | static int wm8900_remove(struct platform_device *pdev) |
1514 | { | 1462 | { |
1515 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1463 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1516 | struct snd_soc_codec *codec = socdev->codec; | ||
1517 | |||
1518 | if (codec->control_data) | ||
1519 | wm8900_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1520 | 1464 | ||
1521 | snd_soc_free_pcms(socdev); | 1465 | snd_soc_free_pcms(socdev); |
1522 | snd_soc_dapm_free(socdev); | 1466 | snd_soc_dapm_free(socdev); |
1523 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | ||
1524 | i2c_del_driver(&wm8900_i2c_driver); | ||
1525 | #endif | ||
1526 | kfree(codec); | ||
1527 | 1467 | ||
1528 | return 0; | 1468 | return 0; |
1529 | } | 1469 | } |
@@ -1536,6 +1476,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8900 = { | |||
1536 | }; | 1476 | }; |
1537 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); | 1477 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900); |
1538 | 1478 | ||
1479 | static int __init wm8900_modinit(void) | ||
1480 | { | ||
1481 | return i2c_add_driver(&wm8900_i2c_driver); | ||
1482 | } | ||
1483 | module_init(wm8900_modinit); | ||
1484 | |||
1485 | static void __exit wm8900_exit(void) | ||
1486 | { | ||
1487 | i2c_del_driver(&wm8900_i2c_driver); | ||
1488 | } | ||
1489 | module_exit(wm8900_exit); | ||
1490 | |||
1539 | MODULE_DESCRIPTION("ASoC WM8900 driver"); | 1491 | MODULE_DESCRIPTION("ASoC WM8900 driver"); |
1540 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | 1492 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); |
1541 | MODULE_LICENSE("GPL"); | 1493 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h index ba450d99e902..fd15007d10c7 100644 --- a/sound/soc/codecs/wm8900.h +++ b/sound/soc/codecs/wm8900.h | |||
@@ -52,12 +52,6 @@ | |||
52 | #define WM8900_DAC_CLKDIV_5_5 0x14 | 52 | #define WM8900_DAC_CLKDIV_5_5 0x14 |
53 | #define WM8900_DAC_CLKDIV_6 0x18 | 53 | #define WM8900_DAC_CLKDIV_6 0x18 |
54 | 54 | ||
55 | #define WM8900_ | ||
56 | |||
57 | struct wm8900_setup_data { | ||
58 | unsigned short i2c_address; | ||
59 | }; | ||
60 | |||
61 | extern struct snd_soc_dai wm8900_dai; | 55 | extern struct snd_soc_dai wm8900_dai; |
62 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; | 56 | extern struct snd_soc_codec_device soc_codec_dev_wm8900; |
63 | 57 | ||
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index ce40d7877605..bde74546db4a 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -33,19 +33,6 @@ | |||
33 | 33 | ||
34 | #include "wm8903.h" | 34 | #include "wm8903.h" |
35 | 35 | ||
36 | struct wm8903_priv { | ||
37 | int sysclk; | ||
38 | |||
39 | /* Reference counts */ | ||
40 | int charge_pump_users; | ||
41 | int class_w_users; | ||
42 | int playback_active; | ||
43 | int capture_active; | ||
44 | |||
45 | struct snd_pcm_substream *master_substream; | ||
46 | struct snd_pcm_substream *slave_substream; | ||
47 | }; | ||
48 | |||
49 | /* Register defaults at reset */ | 36 | /* Register defaults at reset */ |
50 | static u16 wm8903_reg_defaults[] = { | 37 | static u16 wm8903_reg_defaults[] = { |
51 | 0x8903, /* R0 - SW Reset and ID */ | 38 | 0x8903, /* R0 - SW Reset and ID */ |
@@ -223,6 +210,23 @@ static u16 wm8903_reg_defaults[] = { | |||
223 | 0x0000, /* R172 - Analogue Output Bias 0 */ | 210 | 0x0000, /* R172 - Analogue Output Bias 0 */ |
224 | }; | 211 | }; |
225 | 212 | ||
213 | struct wm8903_priv { | ||
214 | struct snd_soc_codec codec; | ||
215 | u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)]; | ||
216 | |||
217 | int sysclk; | ||
218 | |||
219 | /* Reference counts */ | ||
220 | int charge_pump_users; | ||
221 | int class_w_users; | ||
222 | int playback_active; | ||
223 | int capture_active; | ||
224 | |||
225 | struct snd_pcm_substream *master_substream; | ||
226 | struct snd_pcm_substream *slave_substream; | ||
227 | }; | ||
228 | |||
229 | |||
226 | static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, | 230 | static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, |
227 | unsigned int reg) | 231 | unsigned int reg) |
228 | { | 232 | { |
@@ -360,6 +364,8 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache) | |||
360 | static void wm8903_reset(struct snd_soc_codec *codec) | 364 | static void wm8903_reset(struct snd_soc_codec *codec) |
361 | { | 365 | { |
362 | wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); | 366 | wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); |
367 | memcpy(codec->reg_cache, wm8903_reg_defaults, | ||
368 | sizeof(wm8903_reg_defaults)); | ||
363 | } | 369 | } |
364 | 370 | ||
365 | #define WM8903_OUTPUT_SHORT 0x8 | 371 | #define WM8903_OUTPUT_SHORT 0x8 |
@@ -392,6 +398,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w, | |||
392 | break; | 398 | break; |
393 | default: | 399 | default: |
394 | BUG(); | 400 | BUG(); |
401 | return -EINVAL; /* Spurious warning from some compilers */ | ||
395 | } | 402 | } |
396 | 403 | ||
397 | switch (w->shift) { | 404 | switch (w->shift) { |
@@ -403,6 +410,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w, | |||
403 | break; | 410 | break; |
404 | default: | 411 | default: |
405 | BUG(); | 412 | BUG(); |
413 | return -EINVAL; /* Spurious warning from some compilers */ | ||
406 | } | 414 | } |
407 | 415 | ||
408 | if (event & SND_SOC_DAPM_PRE_PMU) { | 416 | if (event & SND_SOC_DAPM_PRE_PMU) { |
@@ -773,14 +781,14 @@ static const struct snd_kcontrol_new left_output_mixer[] = { | |||
773 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), | 781 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), |
774 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), | 782 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), |
775 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 783 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), |
776 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 784 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0), |
777 | }; | 785 | }; |
778 | 786 | ||
779 | static const struct snd_kcontrol_new right_output_mixer[] = { | 787 | static const struct snd_kcontrol_new right_output_mixer[] = { |
780 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), | 788 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), |
781 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), | 789 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), |
782 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 790 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), |
783 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 791 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0), |
784 | }; | 792 | }; |
785 | 793 | ||
786 | static const struct snd_kcontrol_new left_speaker_mixer[] = { | 794 | static const struct snd_kcontrol_new left_speaker_mixer[] = { |
@@ -788,7 +796,7 @@ SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0), | |||
788 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), | 796 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), |
789 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), | 797 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), |
790 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, | 798 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, |
791 | 1, 1, 0), | 799 | 0, 1, 0), |
792 | }; | 800 | }; |
793 | 801 | ||
794 | static const struct snd_kcontrol_new right_speaker_mixer[] = { | 802 | static const struct snd_kcontrol_new right_speaker_mixer[] = { |
@@ -797,7 +805,7 @@ SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0), | |||
797 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 805 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, |
798 | 1, 1, 0), | 806 | 1, 1, 0), |
799 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 807 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, |
800 | 1, 1, 0), | 808 | 0, 1, 0), |
801 | }; | 809 | }; |
802 | 810 | ||
803 | static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { | 811 | static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { |
@@ -989,6 +997,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
989 | 997 | ||
990 | case SND_SOC_BIAS_STANDBY: | 998 | case SND_SOC_BIAS_STANDBY: |
991 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 999 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
1000 | wm8903_write(codec, WM8903_CLOCK_RATES_2, | ||
1001 | WM8903_CLK_SYS_ENA); | ||
1002 | |||
992 | wm8903_run_sequence(codec, 0); | 1003 | wm8903_run_sequence(codec, 0); |
993 | wm8903_sync_reg_cache(codec, codec->reg_cache); | 1004 | wm8903_sync_reg_cache(codec, codec->reg_cache); |
994 | 1005 | ||
@@ -1019,6 +1030,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1019 | 1030 | ||
1020 | case SND_SOC_BIAS_OFF: | 1031 | case SND_SOC_BIAS_OFF: |
1021 | wm8903_run_sequence(codec, 32); | 1032 | wm8903_run_sequence(codec, 32); |
1033 | reg = wm8903_read(codec, WM8903_CLOCK_RATES_2); | ||
1034 | reg &= ~WM8903_CLK_SYS_ENA; | ||
1035 | wm8903_write(codec, WM8903_CLOCK_RATES_2, reg); | ||
1022 | break; | 1036 | break; |
1023 | } | 1037 | } |
1024 | 1038 | ||
@@ -1257,7 +1271,8 @@ static struct { | |||
1257 | { 0, 0 }, | 1271 | { 0, 0 }, |
1258 | }; | 1272 | }; |
1259 | 1273 | ||
1260 | static int wm8903_startup(struct snd_pcm_substream *substream) | 1274 | static int wm8903_startup(struct snd_pcm_substream *substream, |
1275 | struct snd_soc_dai *dai) | ||
1261 | { | 1276 | { |
1262 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1263 | struct snd_soc_device *socdev = rtd->socdev; | 1278 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1298,7 +1313,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream) | |||
1298 | return 0; | 1313 | return 0; |
1299 | } | 1314 | } |
1300 | 1315 | ||
1301 | static void wm8903_shutdown(struct snd_pcm_substream *substream) | 1316 | static void wm8903_shutdown(struct snd_pcm_substream *substream, |
1317 | struct snd_soc_dai *dai) | ||
1302 | { | 1318 | { |
1303 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1319 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1304 | struct snd_soc_device *socdev = rtd->socdev; | 1320 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1317,7 +1333,8 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream) | |||
1317 | } | 1333 | } |
1318 | 1334 | ||
1319 | static int wm8903_hw_params(struct snd_pcm_substream *substream, | 1335 | static int wm8903_hw_params(struct snd_pcm_substream *substream, |
1320 | struct snd_pcm_hw_params *params) | 1336 | struct snd_pcm_hw_params *params, |
1337 | struct snd_soc_dai *dai) | ||
1321 | { | 1338 | { |
1322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1323 | struct snd_soc_device *socdev = rtd->socdev; | 1340 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1515,8 +1532,6 @@ struct snd_soc_dai wm8903_dai = { | |||
1515 | .startup = wm8903_startup, | 1532 | .startup = wm8903_startup, |
1516 | .shutdown = wm8903_shutdown, | 1533 | .shutdown = wm8903_shutdown, |
1517 | .hw_params = wm8903_hw_params, | 1534 | .hw_params = wm8903_hw_params, |
1518 | }, | ||
1519 | .dai_ops = { | ||
1520 | .digital_mute = wm8903_digital_mute, | 1535 | .digital_mute = wm8903_digital_mute, |
1521 | .set_fmt = wm8903_set_dai_fmt, | 1536 | .set_fmt = wm8903_set_dai_fmt, |
1522 | .set_sysclk = wm8903_set_dai_sysclk | 1537 | .set_sysclk = wm8903_set_dai_sysclk |
@@ -1560,39 +1575,48 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1560 | return 0; | 1575 | return 0; |
1561 | } | 1576 | } |
1562 | 1577 | ||
1563 | /* | 1578 | static struct snd_soc_codec *wm8903_codec; |
1564 | * initialise the WM8903 driver | 1579 | |
1565 | * register the mixer and dsp interfaces with the kernel | 1580 | static int wm8903_i2c_probe(struct i2c_client *i2c, |
1566 | */ | 1581 | const struct i2c_device_id *id) |
1567 | static int wm8903_init(struct snd_soc_device *socdev) | ||
1568 | { | 1582 | { |
1569 | struct snd_soc_codec *codec = socdev->codec; | 1583 | struct wm8903_priv *wm8903; |
1570 | struct i2c_client *i2c = codec->control_data; | 1584 | struct snd_soc_codec *codec; |
1571 | int ret = 0; | 1585 | int ret; |
1572 | u16 val; | 1586 | u16 val; |
1573 | 1587 | ||
1574 | val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); | 1588 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); |
1575 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | 1589 | if (wm8903 == NULL) |
1576 | dev_err(&i2c->dev, | 1590 | return -ENOMEM; |
1577 | "Device with ID register %x is not a WM8903\n", val); | 1591 | |
1578 | return -ENODEV; | 1592 | codec = &wm8903->codec; |
1579 | } | ||
1580 | 1593 | ||
1594 | mutex_init(&codec->mutex); | ||
1595 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1596 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1597 | |||
1598 | codec->dev = &i2c->dev; | ||
1581 | codec->name = "WM8903"; | 1599 | codec->name = "WM8903"; |
1582 | codec->owner = THIS_MODULE; | 1600 | codec->owner = THIS_MODULE; |
1583 | codec->read = wm8903_read; | 1601 | codec->read = wm8903_read; |
1584 | codec->write = wm8903_write; | 1602 | codec->write = wm8903_write; |
1603 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1585 | codec->bias_level = SND_SOC_BIAS_OFF; | 1604 | codec->bias_level = SND_SOC_BIAS_OFF; |
1586 | codec->set_bias_level = wm8903_set_bias_level; | 1605 | codec->set_bias_level = wm8903_set_bias_level; |
1587 | codec->dai = &wm8903_dai; | 1606 | codec->dai = &wm8903_dai; |
1588 | codec->num_dai = 1; | 1607 | codec->num_dai = 1; |
1589 | codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults); | 1608 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); |
1590 | codec->reg_cache = kmemdup(wm8903_reg_defaults, | 1609 | codec->reg_cache = &wm8903->reg_cache[0]; |
1591 | sizeof(wm8903_reg_defaults), | 1610 | codec->private_data = wm8903; |
1592 | GFP_KERNEL); | 1611 | |
1593 | if (codec->reg_cache == NULL) { | 1612 | i2c_set_clientdata(i2c, codec); |
1594 | dev_err(&i2c->dev, "Failed to allocate register cache\n"); | 1613 | codec->control_data = i2c; |
1595 | return -ENOMEM; | 1614 | |
1615 | val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); | ||
1616 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | ||
1617 | dev_err(&i2c->dev, | ||
1618 | "Device with ID register %x is not a WM8903\n", val); | ||
1619 | return -ENODEV; | ||
1596 | } | 1620 | } |
1597 | 1621 | ||
1598 | val = wm8903_read(codec, WM8903_REVISION_NUMBER); | 1622 | val = wm8903_read(codec, WM8903_REVISION_NUMBER); |
@@ -1601,16 +1625,6 @@ static int wm8903_init(struct snd_soc_device *socdev) | |||
1601 | 1625 | ||
1602 | wm8903_reset(codec); | 1626 | wm8903_reset(codec); |
1603 | 1627 | ||
1604 | /* register pcms */ | ||
1605 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1606 | if (ret < 0) { | ||
1607 | dev_err(&i2c->dev, "failed to create pcms\n"); | ||
1608 | goto pcm_err; | ||
1609 | } | ||
1610 | |||
1611 | /* SYSCLK is required for pretty much anything */ | ||
1612 | wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA); | ||
1613 | |||
1614 | /* power on device */ | 1628 | /* power on device */ |
1615 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1629 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1616 | 1630 | ||
@@ -1645,47 +1659,45 @@ static int wm8903_init(struct snd_soc_device *socdev) | |||
1645 | val |= WM8903_DAC_MUTEMODE; | 1659 | val |= WM8903_DAC_MUTEMODE; |
1646 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); | 1660 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); |
1647 | 1661 | ||
1648 | wm8903_add_controls(codec); | 1662 | wm8903_dai.dev = &i2c->dev; |
1649 | wm8903_add_widgets(codec); | 1663 | wm8903_codec = codec; |
1650 | ret = snd_soc_register_card(socdev); | 1664 | |
1651 | if (ret < 0) { | 1665 | ret = snd_soc_register_codec(codec); |
1652 | dev_err(&i2c->dev, "wm8903: failed to register card\n"); | 1666 | if (ret != 0) { |
1653 | goto card_err; | 1667 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1668 | goto err; | ||
1669 | } | ||
1670 | |||
1671 | ret = snd_soc_register_dai(&wm8903_dai); | ||
1672 | if (ret != 0) { | ||
1673 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | ||
1674 | goto err_codec; | ||
1654 | } | 1675 | } |
1655 | 1676 | ||
1656 | return ret; | 1677 | return ret; |
1657 | 1678 | ||
1658 | card_err: | 1679 | err_codec: |
1659 | snd_soc_free_pcms(socdev); | 1680 | snd_soc_unregister_codec(codec); |
1660 | snd_soc_dapm_free(socdev); | 1681 | err: |
1661 | pcm_err: | 1682 | wm8903_codec = NULL; |
1662 | kfree(codec->reg_cache); | 1683 | kfree(wm8903); |
1663 | return ret; | 1684 | return ret; |
1664 | } | 1685 | } |
1665 | 1686 | ||
1666 | static struct snd_soc_device *wm8903_socdev; | 1687 | static int wm8903_i2c_remove(struct i2c_client *client) |
1667 | |||
1668 | static int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1669 | const struct i2c_device_id *id) | ||
1670 | { | 1688 | { |
1671 | struct snd_soc_device *socdev = wm8903_socdev; | 1689 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
1672 | struct snd_soc_codec *codec = socdev->codec; | ||
1673 | int ret; | ||
1674 | 1690 | ||
1675 | i2c_set_clientdata(i2c, codec); | 1691 | snd_soc_unregister_dai(&wm8903_dai); |
1676 | codec->control_data = i2c; | 1692 | snd_soc_unregister_codec(codec); |
1677 | 1693 | ||
1678 | ret = wm8903_init(socdev); | 1694 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1679 | if (ret < 0) | ||
1680 | dev_err(&i2c->dev, "Device initialisation failed\n"); | ||
1681 | 1695 | ||
1682 | return ret; | 1696 | kfree(codec->private_data); |
1683 | } | 1697 | |
1698 | wm8903_codec = NULL; | ||
1699 | wm8903_dai.dev = NULL; | ||
1684 | 1700 | ||
1685 | static int wm8903_i2c_remove(struct i2c_client *client) | ||
1686 | { | ||
1687 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
1688 | kfree(codec->reg_cache); | ||
1689 | return 0; | 1701 | return 0; |
1690 | } | 1702 | } |
1691 | 1703 | ||
@@ -1709,75 +1721,37 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
1709 | static int wm8903_probe(struct platform_device *pdev) | 1721 | static int wm8903_probe(struct platform_device *pdev) |
1710 | { | 1722 | { |
1711 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1723 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1712 | struct wm8903_setup_data *setup; | ||
1713 | struct snd_soc_codec *codec; | ||
1714 | struct wm8903_priv *wm8903; | ||
1715 | struct i2c_board_info board_info; | ||
1716 | struct i2c_adapter *adapter; | ||
1717 | struct i2c_client *i2c_client; | ||
1718 | int ret = 0; | 1724 | int ret = 0; |
1719 | 1725 | ||
1720 | setup = socdev->codec_data; | 1726 | if (!wm8903_codec) { |
1721 | 1727 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | |
1722 | if (!setup->i2c_address) { | 1728 | goto err; |
1723 | dev_err(&pdev->dev, "No codec address provided\n"); | ||
1724 | return -ENODEV; | ||
1725 | } | 1729 | } |
1726 | 1730 | ||
1727 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1731 | socdev->codec = wm8903_codec; |
1728 | if (codec == NULL) | ||
1729 | return -ENOMEM; | ||
1730 | 1732 | ||
1731 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | 1733 | /* register pcms */ |
1732 | if (wm8903 == NULL) { | 1734 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1733 | ret = -ENOMEM; | 1735 | if (ret < 0) { |
1734 | goto err_codec; | 1736 | dev_err(&pdev->dev, "failed to create pcms\n"); |
1737 | goto err; | ||
1735 | } | 1738 | } |
1736 | 1739 | ||
1737 | codec->private_data = wm8903; | 1740 | wm8903_add_controls(socdev->codec); |
1738 | socdev->codec = codec; | 1741 | wm8903_add_widgets(socdev->codec); |
1739 | mutex_init(&codec->mutex); | ||
1740 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1741 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1742 | |||
1743 | wm8903_socdev = socdev; | ||
1744 | 1742 | ||
1745 | codec->hw_write = (hw_write_t)i2c_master_send; | 1743 | ret = snd_soc_init_card(socdev); |
1746 | ret = i2c_add_driver(&wm8903_i2c_driver); | 1744 | if (ret < 0) { |
1747 | if (ret != 0) { | 1745 | dev_err(&pdev->dev, "wm8903: failed to register card\n"); |
1748 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 1746 | goto card_err; |
1749 | goto err_priv; | ||
1750 | } else { | ||
1751 | memset(&board_info, 0, sizeof(board_info)); | ||
1752 | strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE); | ||
1753 | board_info.addr = setup->i2c_address; | ||
1754 | |||
1755 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1756 | if (!adapter) { | ||
1757 | dev_err(&pdev->dev, "Can't get I2C bus %d\n", | ||
1758 | setup->i2c_bus); | ||
1759 | ret = -ENODEV; | ||
1760 | goto err_adapter; | ||
1761 | } | ||
1762 | |||
1763 | i2c_client = i2c_new_device(adapter, &board_info); | ||
1764 | i2c_put_adapter(adapter); | ||
1765 | if (i2c_client == NULL) { | ||
1766 | dev_err(&pdev->dev, | ||
1767 | "I2C driver registration failed\n"); | ||
1768 | ret = -ENODEV; | ||
1769 | goto err_adapter; | ||
1770 | } | ||
1771 | } | 1747 | } |
1772 | 1748 | ||
1773 | return ret; | 1749 | return ret; |
1774 | 1750 | ||
1775 | err_adapter: | 1751 | card_err: |
1776 | i2c_del_driver(&wm8903_i2c_driver); | 1752 | snd_soc_free_pcms(socdev); |
1777 | err_priv: | 1753 | snd_soc_dapm_free(socdev); |
1778 | kfree(codec->private_data); | 1754 | err: |
1779 | err_codec: | ||
1780 | kfree(codec); | ||
1781 | return ret; | 1755 | return ret; |
1782 | } | 1756 | } |
1783 | 1757 | ||
@@ -1792,10 +1766,6 @@ static int wm8903_remove(struct platform_device *pdev) | |||
1792 | 1766 | ||
1793 | snd_soc_free_pcms(socdev); | 1767 | snd_soc_free_pcms(socdev); |
1794 | snd_soc_dapm_free(socdev); | 1768 | snd_soc_dapm_free(socdev); |
1795 | i2c_unregister_device(socdev->codec->control_data); | ||
1796 | i2c_del_driver(&wm8903_i2c_driver); | ||
1797 | kfree(codec->private_data); | ||
1798 | kfree(codec); | ||
1799 | 1769 | ||
1800 | return 0; | 1770 | return 0; |
1801 | } | 1771 | } |
@@ -1808,6 +1778,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8903 = { | |||
1808 | }; | 1778 | }; |
1809 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); | 1779 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); |
1810 | 1780 | ||
1781 | static int __init wm8903_modinit(void) | ||
1782 | { | ||
1783 | return i2c_add_driver(&wm8903_i2c_driver); | ||
1784 | } | ||
1785 | module_init(wm8903_modinit); | ||
1786 | |||
1787 | static void __exit wm8903_exit(void) | ||
1788 | { | ||
1789 | i2c_del_driver(&wm8903_i2c_driver); | ||
1790 | } | ||
1791 | module_exit(wm8903_exit); | ||
1792 | |||
1811 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 1793 | MODULE_DESCRIPTION("ASoC WM8903 driver"); |
1812 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 1794 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); |
1813 | MODULE_LICENSE("GPL"); | 1795 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h index cec622f2f660..0ea27e2b9963 100644 --- a/sound/soc/codecs/wm8903.h +++ b/sound/soc/codecs/wm8903.h | |||
@@ -18,11 +18,6 @@ | |||
18 | extern struct snd_soc_dai wm8903_dai; | 18 | extern struct snd_soc_dai wm8903_dai; |
19 | extern struct snd_soc_codec_device soc_codec_dev_wm8903; | 19 | extern struct snd_soc_codec_device soc_codec_dev_wm8903; |
20 | 20 | ||
21 | struct wm8903_setup_data { | ||
22 | int i2c_bus; | ||
23 | int i2c_address; | ||
24 | }; | ||
25 | |||
26 | #define WM8903_MCLK_DIV_2 1 | 21 | #define WM8903_MCLK_DIV_2 1 |
27 | #define WM8903_CLK_SYS 2 | 22 | #define WM8903_CLK_SYS 2 |
28 | #define WM8903_BCLK 3 | 23 | #define WM8903_BCLK 3 |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index f41a578ddd4f..88ead7f8dd98 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -541,7 +541,8 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
541 | } | 541 | } |
542 | 542 | ||
543 | static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, | 543 | static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream, |
544 | struct snd_pcm_hw_params *params) | 544 | struct snd_pcm_hw_params *params, |
545 | struct snd_soc_dai *dai) | ||
545 | { | 546 | { |
546 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 547 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
547 | struct snd_soc_device *socdev = rtd->socdev; | 548 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -634,8 +635,6 @@ struct snd_soc_dai wm8971_dai = { | |||
634 | .formats = WM8971_FORMATS,}, | 635 | .formats = WM8971_FORMATS,}, |
635 | .ops = { | 636 | .ops = { |
636 | .hw_params = wm8971_pcm_hw_params, | 637 | .hw_params = wm8971_pcm_hw_params, |
637 | }, | ||
638 | .dai_ops = { | ||
639 | .digital_mute = wm8971_mute, | 638 | .digital_mute = wm8971_mute, |
640 | .set_fmt = wm8971_set_dai_fmt, | 639 | .set_fmt = wm8971_set_dai_fmt, |
641 | .set_sysclk = wm8971_set_dai_sysclk, | 640 | .set_sysclk = wm8971_set_dai_sysclk, |
@@ -748,7 +747,7 @@ static int wm8971_init(struct snd_soc_device *socdev) | |||
748 | 747 | ||
749 | wm8971_add_controls(codec); | 748 | wm8971_add_controls(codec); |
750 | wm8971_add_widgets(codec); | 749 | wm8971_add_widgets(codec); |
751 | ret = snd_soc_register_card(socdev); | 750 | ret = snd_soc_init_card(socdev); |
752 | if (ret < 0) { | 751 | if (ret < 0) { |
753 | printk(KERN_ERR "wm8971: failed to register card\n"); | 752 | printk(KERN_ERR "wm8971: failed to register card\n"); |
754 | goto card_err; | 753 | goto card_err; |
@@ -936,6 +935,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8971 = { | |||
936 | 935 | ||
937 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); | 936 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971); |
938 | 937 | ||
938 | static int __init wm8971_modinit(void) | ||
939 | { | ||
940 | return snd_soc_register_dai(&wm8971_dai); | ||
941 | } | ||
942 | module_init(wm8971_modinit); | ||
943 | |||
944 | static void __exit wm8971_exit(void) | ||
945 | { | ||
946 | snd_soc_unregister_dai(&wm8971_dai); | ||
947 | } | ||
948 | module_exit(wm8971_exit); | ||
949 | |||
939 | MODULE_DESCRIPTION("ASoC WM8971 driver"); | 950 | MODULE_DESCRIPTION("ASoC WM8971 driver"); |
940 | MODULE_AUTHOR("Lab126"); | 951 | MODULE_AUTHOR("Lab126"); |
941 | MODULE_LICENSE("GPL"); | 952 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 572d22b0880b..5b5afc144478 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -106,6 +106,7 @@ static const u16 wm8990_reg[] = { | |||
106 | 0x0008, /* R60 - PLL1 */ | 106 | 0x0008, /* R60 - PLL1 */ |
107 | 0x0031, /* R61 - PLL2 */ | 107 | 0x0031, /* R61 - PLL2 */ |
108 | 0x0026, /* R62 - PLL3 */ | 108 | 0x0026, /* R62 - PLL3 */ |
109 | 0x0000, /* R63 - Driver internal */ | ||
109 | }; | 110 | }; |
110 | 111 | ||
111 | /* | 112 | /* |
@@ -126,10 +127,9 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec, | |||
126 | unsigned int reg, unsigned int value) | 127 | unsigned int reg, unsigned int value) |
127 | { | 128 | { |
128 | u16 *cache = codec->reg_cache; | 129 | u16 *cache = codec->reg_cache; |
129 | BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1); | ||
130 | 130 | ||
131 | /* Reset register is uncached */ | 131 | /* Reset register and reserved registers are uncached */ |
132 | if (reg == 0) | 132 | if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1) |
133 | return; | 133 | return; |
134 | 134 | ||
135 | cache[reg] = value; | 135 | cache[reg] = value; |
@@ -1172,7 +1172,8 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
1172 | * Set PCM DAI bit size and sample rate. | 1172 | * Set PCM DAI bit size and sample rate. |
1173 | */ | 1173 | */ |
1174 | static int wm8990_hw_params(struct snd_pcm_substream *substream, | 1174 | static int wm8990_hw_params(struct snd_pcm_substream *substream, |
1175 | struct snd_pcm_hw_params *params) | 1175 | struct snd_pcm_hw_params *params, |
1176 | struct snd_soc_dai *dai) | ||
1176 | { | 1177 | { |
1177 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1178 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1178 | struct snd_soc_device *socdev = rtd->socdev; | 1179 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1222,8 +1223,14 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1222 | switch (level) { | 1223 | switch (level) { |
1223 | case SND_SOC_BIAS_ON: | 1224 | case SND_SOC_BIAS_ON: |
1224 | break; | 1225 | break; |
1226 | |||
1225 | case SND_SOC_BIAS_PREPARE: | 1227 | case SND_SOC_BIAS_PREPARE: |
1228 | /* VMID=2*50k */ | ||
1229 | val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & | ||
1230 | ~WM8990_VMID_MODE_MASK; | ||
1231 | wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2); | ||
1226 | break; | 1232 | break; |
1233 | |||
1227 | case SND_SOC_BIAS_STANDBY: | 1234 | case SND_SOC_BIAS_STANDBY: |
1228 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 1235 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
1229 | /* Enable all output discharge bits */ | 1236 | /* Enable all output discharge bits */ |
@@ -1272,10 +1279,17 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec, | |||
1272 | 1279 | ||
1273 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ | 1280 | /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ |
1274 | wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); | 1281 | wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); |
1275 | } else { | ||
1276 | /* ON -> standby */ | ||
1277 | 1282 | ||
1283 | /* Enable workaround for ADC clocking issue. */ | ||
1284 | wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2); | ||
1285 | wm8990_write(codec, WM8990_EXT_CTL1, 0xa003); | ||
1286 | wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0); | ||
1278 | } | 1287 | } |
1288 | |||
1289 | /* VMID=2*250k */ | ||
1290 | val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) & | ||
1291 | ~WM8990_VMID_MODE_MASK; | ||
1292 | wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4); | ||
1279 | break; | 1293 | break; |
1280 | 1294 | ||
1281 | case SND_SOC_BIAS_OFF: | 1295 | case SND_SOC_BIAS_OFF: |
@@ -1349,8 +1363,7 @@ struct snd_soc_dai wm8990_dai = { | |||
1349 | .rates = WM8990_RATES, | 1363 | .rates = WM8990_RATES, |
1350 | .formats = WM8990_FORMATS,}, | 1364 | .formats = WM8990_FORMATS,}, |
1351 | .ops = { | 1365 | .ops = { |
1352 | .hw_params = wm8990_hw_params,}, | 1366 | .hw_params = wm8990_hw_params, |
1353 | .dai_ops = { | ||
1354 | .digital_mute = wm8990_mute, | 1367 | .digital_mute = wm8990_mute, |
1355 | .set_fmt = wm8990_set_dai_fmt, | 1368 | .set_fmt = wm8990_set_dai_fmt, |
1356 | .set_clkdiv = wm8990_set_dai_clkdiv, | 1369 | .set_clkdiv = wm8990_set_dai_clkdiv, |
@@ -1449,7 +1462,7 @@ static int wm8990_init(struct snd_soc_device *socdev) | |||
1449 | 1462 | ||
1450 | wm8990_add_controls(codec); | 1463 | wm8990_add_controls(codec); |
1451 | wm8990_add_widgets(codec); | 1464 | wm8990_add_widgets(codec); |
1452 | ret = snd_soc_register_card(socdev); | 1465 | ret = snd_soc_init_card(socdev); |
1453 | if (ret < 0) { | 1466 | if (ret < 0) { |
1454 | printk(KERN_ERR "wm8990: failed to register card\n"); | 1467 | printk(KERN_ERR "wm8990: failed to register card\n"); |
1455 | goto card_err; | 1468 | goto card_err; |
@@ -1630,6 +1643,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8990 = { | |||
1630 | }; | 1643 | }; |
1631 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); | 1644 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); |
1632 | 1645 | ||
1646 | static int __init wm8990_modinit(void) | ||
1647 | { | ||
1648 | return snd_soc_register_dai(&wm8990_dai); | ||
1649 | } | ||
1650 | module_init(wm8990_modinit); | ||
1651 | |||
1652 | static void __exit wm8990_exit(void) | ||
1653 | { | ||
1654 | snd_soc_unregister_dai(&wm8990_dai); | ||
1655 | } | ||
1656 | module_exit(wm8990_exit); | ||
1657 | |||
1633 | MODULE_DESCRIPTION("ASoC WM8990 driver"); | 1658 | MODULE_DESCRIPTION("ASoC WM8990 driver"); |
1634 | MODULE_AUTHOR("Liam Girdwood"); | 1659 | MODULE_AUTHOR("Liam Girdwood"); |
1635 | MODULE_LICENSE("GPL"); | 1660 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h index 0e192f3b0788..7114ddc88b4b 100644 --- a/sound/soc/codecs/wm8990.h +++ b/sound/soc/codecs/wm8990.h | |||
@@ -80,8 +80,8 @@ | |||
80 | #define WM8990_PLL3 0x3E | 80 | #define WM8990_PLL3 0x3E |
81 | #define WM8990_INTDRIVBITS 0x3F | 81 | #define WM8990_INTDRIVBITS 0x3F |
82 | 82 | ||
83 | #define WM8990_REGISTER_COUNT 60 | 83 | #define WM8990_EXT_ACCESS_ENA 0x75 |
84 | #define WM8990_MAX_REGISTER 0x3F | 84 | #define WM8990_EXT_CTL1 0x7a |
85 | 85 | ||
86 | /* | 86 | /* |
87 | * Field Definitions. | 87 | * Field Definitions. |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index ffb471e420e2..af83d629078a 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -487,7 +487,8 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
487 | return 0; | 487 | return 0; |
488 | } | 488 | } |
489 | 489 | ||
490 | static int ac97_prepare(struct snd_pcm_substream *substream) | 490 | static int ac97_prepare(struct snd_pcm_substream *substream, |
491 | struct snd_soc_dai *dai) | ||
491 | { | 492 | { |
492 | struct snd_pcm_runtime *runtime = substream->runtime; | 493 | struct snd_pcm_runtime *runtime = substream->runtime; |
493 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 494 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -507,7 +508,8 @@ static int ac97_prepare(struct snd_pcm_substream *substream) | |||
507 | return ac97_write(codec, reg, runtime->rate); | 508 | return ac97_write(codec, reg, runtime->rate); |
508 | } | 509 | } |
509 | 510 | ||
510 | static int ac97_aux_prepare(struct snd_pcm_substream *substream) | 511 | static int ac97_aux_prepare(struct snd_pcm_substream *substream, |
512 | struct snd_soc_dai *dai) | ||
511 | { | 513 | { |
512 | struct snd_pcm_runtime *runtime = substream->runtime; | 514 | struct snd_pcm_runtime *runtime = substream->runtime; |
513 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 515 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -533,7 +535,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream) | |||
533 | struct snd_soc_dai wm9712_dai[] = { | 535 | struct snd_soc_dai wm9712_dai[] = { |
534 | { | 536 | { |
535 | .name = "AC97 HiFi", | 537 | .name = "AC97 HiFi", |
536 | .type = SND_SOC_DAI_AC97_BUS, | 538 | .ac97_control = 1, |
537 | .playback = { | 539 | .playback = { |
538 | .stream_name = "HiFi Playback", | 540 | .stream_name = "HiFi Playback", |
539 | .channels_min = 1, | 541 | .channels_min = 1, |
@@ -688,7 +690,7 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
688 | 690 | ||
689 | ret = wm9712_reset(codec, 0); | 691 | ret = wm9712_reset(codec, 0); |
690 | if (ret < 0) { | 692 | if (ret < 0) { |
691 | printk(KERN_ERR "AC97 link error\n"); | 693 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); |
692 | goto reset_err; | 694 | goto reset_err; |
693 | } | 695 | } |
694 | 696 | ||
@@ -698,7 +700,7 @@ static int wm9712_soc_probe(struct platform_device *pdev) | |||
698 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 700 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
699 | wm9712_add_controls(codec); | 701 | wm9712_add_controls(codec); |
700 | wm9712_add_widgets(codec); | 702 | wm9712_add_widgets(codec); |
701 | ret = snd_soc_register_card(socdev); | 703 | ret = snd_soc_init_card(socdev); |
702 | if (ret < 0) { | 704 | if (ret < 0) { |
703 | printk(KERN_ERR "wm9712: failed to register card\n"); | 705 | printk(KERN_ERR "wm9712: failed to register card\n"); |
704 | goto reset_err; | 706 | goto reset_err; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index 945b32ed9884..f3ca8aaf0139 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -928,11 +928,10 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
928 | } | 928 | } |
929 | 929 | ||
930 | static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, | 930 | static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, |
931 | struct snd_pcm_hw_params *params) | 931 | struct snd_pcm_hw_params *params, |
932 | struct snd_soc_dai *dai) | ||
932 | { | 933 | { |
933 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 934 | struct snd_soc_codec *codec = dai->codec; |
934 | struct snd_soc_device *socdev = rtd->socdev; | ||
935 | struct snd_soc_codec *codec = socdev->codec; | ||
936 | u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; | 935 | u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3; |
937 | 936 | ||
938 | switch (params_format(params)) { | 937 | switch (params_format(params)) { |
@@ -954,11 +953,10 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream, | |||
954 | return 0; | 953 | return 0; |
955 | } | 954 | } |
956 | 955 | ||
957 | static void wm9713_voiceshutdown(struct snd_pcm_substream *substream) | 956 | static void wm9713_voiceshutdown(struct snd_pcm_substream *substream, |
957 | struct snd_soc_dai *dai) | ||
958 | { | 958 | { |
959 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 959 | struct snd_soc_codec *codec = dai->codec; |
960 | struct snd_soc_device *socdev = rtd->socdev; | ||
961 | struct snd_soc_codec *codec = socdev->codec; | ||
962 | u16 status; | 960 | u16 status; |
963 | 961 | ||
964 | /* Gracefully shut down the voice interface. */ | 962 | /* Gracefully shut down the voice interface. */ |
@@ -969,12 +967,11 @@ static void wm9713_voiceshutdown(struct snd_pcm_substream *substream) | |||
969 | ac97_write(codec, AC97_EXTENDED_MID, status); | 967 | ac97_write(codec, AC97_EXTENDED_MID, status); |
970 | } | 968 | } |
971 | 969 | ||
972 | static int ac97_hifi_prepare(struct snd_pcm_substream *substream) | 970 | static int ac97_hifi_prepare(struct snd_pcm_substream *substream, |
971 | struct snd_soc_dai *dai) | ||
973 | { | 972 | { |
973 | struct snd_soc_codec *codec = dai->codec; | ||
974 | struct snd_pcm_runtime *runtime = substream->runtime; | 974 | struct snd_pcm_runtime *runtime = substream->runtime; |
975 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
976 | struct snd_soc_device *socdev = rtd->socdev; | ||
977 | struct snd_soc_codec *codec = socdev->codec; | ||
978 | int reg; | 975 | int reg; |
979 | u16 vra; | 976 | u16 vra; |
980 | 977 | ||
@@ -989,12 +986,11 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream) | |||
989 | return ac97_write(codec, reg, runtime->rate); | 986 | return ac97_write(codec, reg, runtime->rate); |
990 | } | 987 | } |
991 | 988 | ||
992 | static int ac97_aux_prepare(struct snd_pcm_substream *substream) | 989 | static int ac97_aux_prepare(struct snd_pcm_substream *substream, |
990 | struct snd_soc_dai *dai) | ||
993 | { | 991 | { |
992 | struct snd_soc_codec *codec = dai->codec; | ||
994 | struct snd_pcm_runtime *runtime = substream->runtime; | 993 | struct snd_pcm_runtime *runtime = substream->runtime; |
995 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
996 | struct snd_soc_device *socdev = rtd->socdev; | ||
997 | struct snd_soc_codec *codec = socdev->codec; | ||
998 | u16 vra, xsle; | 994 | u16 vra, xsle; |
999 | 995 | ||
1000 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); | 996 | vra = ac97_read(codec, AC97_EXTENDED_STATUS); |
@@ -1028,7 +1024,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream) | |||
1028 | struct snd_soc_dai wm9713_dai[] = { | 1024 | struct snd_soc_dai wm9713_dai[] = { |
1029 | { | 1025 | { |
1030 | .name = "AC97 HiFi", | 1026 | .name = "AC97 HiFi", |
1031 | .type = SND_SOC_DAI_AC97_BUS, | 1027 | .ac97_control = 1, |
1032 | .playback = { | 1028 | .playback = { |
1033 | .stream_name = "HiFi Playback", | 1029 | .stream_name = "HiFi Playback", |
1034 | .channels_min = 1, | 1030 | .channels_min = 1, |
@@ -1042,8 +1038,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1042 | .rates = WM9713_RATES, | 1038 | .rates = WM9713_RATES, |
1043 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 1039 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
1044 | .ops = { | 1040 | .ops = { |
1045 | .prepare = ac97_hifi_prepare,}, | 1041 | .prepare = ac97_hifi_prepare, |
1046 | .dai_ops = { | ||
1047 | .set_clkdiv = wm9713_set_dai_clkdiv, | 1042 | .set_clkdiv = wm9713_set_dai_clkdiv, |
1048 | .set_pll = wm9713_set_dai_pll,}, | 1043 | .set_pll = wm9713_set_dai_pll,}, |
1049 | }, | 1044 | }, |
@@ -1056,8 +1051,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1056 | .rates = WM9713_RATES, | 1051 | .rates = WM9713_RATES, |
1057 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | 1052 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, |
1058 | .ops = { | 1053 | .ops = { |
1059 | .prepare = ac97_aux_prepare,}, | 1054 | .prepare = ac97_aux_prepare, |
1060 | .dai_ops = { | ||
1061 | .set_clkdiv = wm9713_set_dai_clkdiv, | 1055 | .set_clkdiv = wm9713_set_dai_clkdiv, |
1062 | .set_pll = wm9713_set_dai_pll,}, | 1056 | .set_pll = wm9713_set_dai_pll,}, |
1063 | }, | 1057 | }, |
@@ -1077,8 +1071,7 @@ struct snd_soc_dai wm9713_dai[] = { | |||
1077 | .formats = WM9713_PCM_FORMATS,}, | 1071 | .formats = WM9713_PCM_FORMATS,}, |
1078 | .ops = { | 1072 | .ops = { |
1079 | .hw_params = wm9713_pcm_hw_params, | 1073 | .hw_params = wm9713_pcm_hw_params, |
1080 | .shutdown = wm9713_voiceshutdown,}, | 1074 | .shutdown = wm9713_voiceshutdown, |
1081 | .dai_ops = { | ||
1082 | .set_clkdiv = wm9713_set_dai_clkdiv, | 1075 | .set_clkdiv = wm9713_set_dai_clkdiv, |
1083 | .set_pll = wm9713_set_dai_pll, | 1076 | .set_pll = wm9713_set_dai_pll, |
1084 | .set_fmt = wm9713_set_dai_fmt, | 1077 | .set_fmt = wm9713_set_dai_fmt, |
@@ -1097,6 +1090,8 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | |||
1097 | } | 1090 | } |
1098 | 1091 | ||
1099 | soc_ac97_ops.reset(codec->ac97); | 1092 | soc_ac97_ops.reset(codec->ac97); |
1093 | if (soc_ac97_ops.warm_reset) | ||
1094 | soc_ac97_ops.warm_reset(codec->ac97); | ||
1100 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1095 | if (ac97_read(codec, 0) != wm9713_reg[0]) |
1101 | return -EIO; | 1096 | return -EIO; |
1102 | return 0; | 1097 | return 0; |
@@ -1240,7 +1235,7 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1240 | wm9713_reset(codec, 0); | 1235 | wm9713_reset(codec, 0); |
1241 | ret = wm9713_reset(codec, 1); | 1236 | ret = wm9713_reset(codec, 1); |
1242 | if (ret < 0) { | 1237 | if (ret < 0) { |
1243 | printk(KERN_ERR "AC97 link error\n"); | 1238 | printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n"); |
1244 | goto reset_err; | 1239 | goto reset_err; |
1245 | } | 1240 | } |
1246 | 1241 | ||
@@ -1252,7 +1247,7 @@ static int wm9713_soc_probe(struct platform_device *pdev) | |||
1252 | 1247 | ||
1253 | wm9713_add_controls(codec); | 1248 | wm9713_add_controls(codec); |
1254 | wm9713_add_widgets(codec); | 1249 | wm9713_add_widgets(codec); |
1255 | ret = snd_soc_register_card(socdev); | 1250 | ret = snd_soc_init_card(socdev); |
1256 | if (ret < 0) | 1251 | if (ret < 0) |
1257 | goto reset_err; | 1252 | goto reset_err; |
1258 | return 0; | 1253 | return 0; |
@@ -1288,7 +1283,6 @@ static int wm9713_soc_remove(struct platform_device *pdev) | |||
1288 | snd_soc_free_ac97_codec(codec); | 1283 | snd_soc_free_ac97_codec(codec); |
1289 | kfree(codec->private_data); | 1284 | kfree(codec->private_data); |
1290 | kfree(codec->reg_cache); | 1285 | kfree(codec->reg_cache); |
1291 | kfree(codec->dai); | ||
1292 | kfree(codec); | 1286 | kfree(codec); |
1293 | return 0; | 1287 | return 0; |
1294 | } | 1288 | } |
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig index 8f7e33834902..b502741692d6 100644 --- a/sound/soc/davinci/Kconfig +++ b/sound/soc/davinci/Kconfig | |||
@@ -17,3 +17,13 @@ config SND_DAVINCI_SOC_EVM | |||
17 | help | 17 | help |
18 | Say Y if you want to add support for SoC audio on TI | 18 | Say Y if you want to add support for SoC audio on TI |
19 | DaVinci EVM platform. | 19 | DaVinci EVM platform. |
20 | |||
21 | config SND_DAVINCI_SOC_SFFSDR | ||
22 | tristate "SoC Audio support for SFFSDR" | ||
23 | depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR | ||
24 | select SND_DAVINCI_SOC_I2S | ||
25 | select SND_SOC_PCM3008 | ||
26 | select SFFSDR_FPGA | ||
27 | help | ||
28 | Say Y if you want to add support for SoC audio on | ||
29 | Lyrtech SFFSDR board. | ||
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile index ca772e5b4637..ca8bae1fc3f6 100644 --- a/sound/soc/davinci/Makefile +++ b/sound/soc/davinci/Makefile | |||
@@ -7,5 +7,7 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o | |||
7 | 7 | ||
8 | # DAVINCI Machine Support | 8 | # DAVINCI Machine Support |
9 | snd-soc-evm-objs := davinci-evm.o | 9 | snd-soc-evm-objs := davinci-evm.o |
10 | snd-soc-sffsdr-objs := davinci-sffsdr.o | ||
10 | 11 | ||
11 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o | 12 | obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o |
13 | 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 9e6062cd6b59..01b948bb55a1 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -28,6 +28,8 @@ | |||
28 | 28 | ||
29 | #define EVM_CODEC_CLOCK 22579200 | 29 | #define EVM_CODEC_CLOCK 22579200 |
30 | 30 | ||
31 | #define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \ | ||
32 | SND_SOC_DAIFMT_CBM_CFM | SND_SOC_DAIFMT_IB_NF) | ||
31 | static int evm_hw_params(struct snd_pcm_substream *substream, | 33 | static int evm_hw_params(struct snd_pcm_substream *substream, |
32 | struct snd_pcm_hw_params *params) | 34 | struct snd_pcm_hw_params *params) |
33 | { | 35 | { |
@@ -37,14 +39,12 @@ static int evm_hw_params(struct snd_pcm_substream *substream, | |||
37 | int ret = 0; | 39 | int ret = 0; |
38 | 40 | ||
39 | /* set codec DAI configuration */ | 41 | /* set codec DAI configuration */ |
40 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | 42 | ret = snd_soc_dai_set_fmt(codec_dai, AUDIO_FORMAT); |
41 | SND_SOC_DAIFMT_CBM_CFM); | ||
42 | if (ret < 0) | 43 | if (ret < 0) |
43 | return ret; | 44 | return ret; |
44 | 45 | ||
45 | /* set cpu DAI configuration */ | 46 | /* set cpu DAI configuration */ |
46 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_CBM_CFM | | 47 | ret = snd_soc_dai_set_fmt(cpu_dai, AUDIO_FORMAT); |
47 | SND_SOC_DAIFMT_IB_NF); | ||
48 | if (ret < 0) | 48 | if (ret < 0) |
49 | return ret; | 49 | return ret; |
50 | 50 | ||
@@ -128,8 +128,9 @@ static struct snd_soc_dai_link evm_dai = { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | /* davinci-evm audio machine driver */ | 130 | /* davinci-evm audio machine driver */ |
131 | static struct snd_soc_machine snd_soc_machine_evm = { | 131 | static struct snd_soc_card snd_soc_card_evm = { |
132 | .name = "DaVinci EVM", | 132 | .name = "DaVinci EVM", |
133 | .platform = &davinci_soc_platform, | ||
133 | .dai_link = &evm_dai, | 134 | .dai_link = &evm_dai, |
134 | .num_links = 1, | 135 | .num_links = 1, |
135 | }; | 136 | }; |
@@ -142,8 +143,7 @@ static struct aic3x_setup_data evm_aic3x_setup = { | |||
142 | 143 | ||
143 | /* evm audio subsystem */ | 144 | /* evm audio subsystem */ |
144 | static struct snd_soc_device evm_snd_devdata = { | 145 | static struct snd_soc_device evm_snd_devdata = { |
145 | .machine = &snd_soc_machine_evm, | 146 | .card = &snd_soc_card_evm, |
146 | .platform = &davinci_soc_platform, | ||
147 | .codec_dev = &soc_codec_dev_aic3x, | 147 | .codec_dev = &soc_codec_dev_aic3x, |
148 | .codec_data = &evm_aic3x_setup, | 148 | .codec_data = &evm_aic3x_setup, |
149 | }; | 149 | }; |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index abb5fedb0b1e..0fee779e3c76 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) | 59 | #define DAVINCI_MCBSP_PCR_CLKXP (1 << 1) |
60 | #define DAVINCI_MCBSP_PCR_FSRP (1 << 2) | 60 | #define DAVINCI_MCBSP_PCR_FSRP (1 << 2) |
61 | #define DAVINCI_MCBSP_PCR_FSXP (1 << 3) | 61 | #define DAVINCI_MCBSP_PCR_FSXP (1 << 3) |
62 | #define DAVINCI_MCBSP_PCR_SCLKME (1 << 7) | ||
62 | #define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) | 63 | #define DAVINCI_MCBSP_PCR_CLKRM (1 << 8) |
63 | #define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) | 64 | #define DAVINCI_MCBSP_PCR_CLKXM (1 << 9) |
64 | #define DAVINCI_MCBSP_PCR_FSRM (1 << 10) | 65 | #define DAVINCI_MCBSP_PCR_FSRM (1 << 10) |
@@ -110,16 +111,59 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream) | |||
110 | { | 111 | { |
111 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 112 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
112 | struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; | 113 | struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data; |
114 | struct snd_soc_device *socdev = rtd->socdev; | ||
115 | struct snd_soc_platform *platform = socdev->card->platform; | ||
113 | u32 w; | 116 | u32 w; |
117 | int ret; | ||
114 | 118 | ||
115 | /* Start the sample generator and enable transmitter/receiver */ | 119 | /* Start the sample generator and enable transmitter/receiver */ |
116 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | 120 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |
117 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); | 121 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1); |
118 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 122 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
123 | |||
124 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
125 | /* Stop the DMA to avoid data loss */ | ||
126 | /* while the transmitter is out of reset to handle XSYNCERR */ | ||
127 | if (platform->pcm_ops->trigger) { | ||
128 | ret = platform->pcm_ops->trigger(substream, | ||
129 | SNDRV_PCM_TRIGGER_STOP); | ||
130 | if (ret < 0) | ||
131 | printk(KERN_DEBUG "Playback DMA stop failed\n"); | ||
132 | } | ||
133 | |||
134 | /* Enable the transmitter */ | ||
135 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
119 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); | 136 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); |
120 | else | 137 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
138 | |||
139 | /* wait for any unexpected frame sync error to occur */ | ||
140 | udelay(100); | ||
141 | |||
142 | /* Disable the transmitter to clear any outstanding XSYNCERR */ | ||
143 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
144 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0); | ||
145 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | ||
146 | |||
147 | /* Restart the DMA */ | ||
148 | if (platform->pcm_ops->trigger) { | ||
149 | ret = platform->pcm_ops->trigger(substream, | ||
150 | SNDRV_PCM_TRIGGER_START); | ||
151 | if (ret < 0) | ||
152 | printk(KERN_DEBUG "Playback DMA start failed\n"); | ||
153 | } | ||
154 | /* Enable the transmitter */ | ||
155 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
156 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1); | ||
157 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | ||
158 | |||
159 | } else { | ||
160 | |||
161 | /* Enable the reciever */ | ||
162 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | ||
121 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); | 163 | MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1); |
122 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | 164 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
165 | } | ||
166 | |||
123 | 167 | ||
124 | /* Start frame sync */ | 168 | /* Start frame sync */ |
125 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); | 169 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |
@@ -144,7 +188,8 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream) | |||
144 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); | 188 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
145 | } | 189 | } |
146 | 190 | ||
147 | static int davinci_i2s_startup(struct snd_pcm_substream *substream) | 191 | static int davinci_i2s_startup(struct snd_pcm_substream *substream, |
192 | struct snd_soc_dai *dai) | ||
148 | { | 193 | { |
149 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 194 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
150 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 195 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -155,61 +200,138 @@ static int davinci_i2s_startup(struct snd_pcm_substream *substream) | |||
155 | return 0; | 200 | return 0; |
156 | } | 201 | } |
157 | 202 | ||
203 | #define DEFAULT_BITPERSAMPLE 16 | ||
204 | |||
158 | static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, | 205 | static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, |
159 | unsigned int fmt) | 206 | unsigned int fmt) |
160 | { | 207 | { |
161 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | 208 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; |
162 | u32 w; | 209 | unsigned int pcr; |
210 | unsigned int srgr; | ||
211 | unsigned int rcr; | ||
212 | unsigned int xcr; | ||
213 | srgr = DAVINCI_MCBSP_SRGR_FSGM | | ||
214 | DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) | | ||
215 | DAVINCI_MCBSP_SRGR_FWID(DEFAULT_BITPERSAMPLE - 1); | ||
163 | 216 | ||
164 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | 217 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { |
165 | case SND_SOC_DAIFMT_CBS_CFS: | 218 | case SND_SOC_DAIFMT_CBS_CFS: |
166 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, | 219 | /* cpu is master */ |
167 | DAVINCI_MCBSP_PCR_FSXM | | 220 | pcr = DAVINCI_MCBSP_PCR_FSXM | |
168 | DAVINCI_MCBSP_PCR_FSRM | | 221 | DAVINCI_MCBSP_PCR_FSRM | |
169 | DAVINCI_MCBSP_PCR_CLKXM | | 222 | DAVINCI_MCBSP_PCR_CLKXM | |
170 | DAVINCI_MCBSP_PCR_CLKRM); | 223 | DAVINCI_MCBSP_PCR_CLKRM; |
171 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, | 224 | break; |
172 | DAVINCI_MCBSP_SRGR_FSGM); | 225 | case SND_SOC_DAIFMT_CBM_CFS: |
226 | /* McBSP CLKR pin is the input for the Sample Rate Generator. | ||
227 | * McBSP FSR and FSX are driven by the Sample Rate Generator. */ | ||
228 | pcr = DAVINCI_MCBSP_PCR_SCLKME | | ||
229 | DAVINCI_MCBSP_PCR_FSXM | | ||
230 | DAVINCI_MCBSP_PCR_FSRM; | ||
173 | break; | 231 | break; |
174 | case SND_SOC_DAIFMT_CBM_CFM: | 232 | case SND_SOC_DAIFMT_CBM_CFM: |
175 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0); | 233 | /* codec is master */ |
234 | pcr = 0; | ||
176 | break; | 235 | break; |
177 | default: | 236 | default: |
237 | printk(KERN_ERR "%s:bad master\n", __func__); | ||
178 | return -EINVAL; | 238 | return -EINVAL; |
179 | } | 239 | } |
180 | 240 | ||
181 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | 241 | rcr = DAVINCI_MCBSP_RCR_RFRLEN1(1); |
182 | case SND_SOC_DAIFMT_IB_NF: | 242 | xcr = DAVINCI_MCBSP_XCR_XFIG | DAVINCI_MCBSP_XCR_XFRLEN1(1); |
183 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); | 243 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { |
184 | MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP | | 244 | case SND_SOC_DAIFMT_DSP_B: |
185 | DAVINCI_MCBSP_PCR_CLKRP, 1); | ||
186 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w); | ||
187 | break; | 245 | break; |
188 | case SND_SOC_DAIFMT_NB_IF: | 246 | case SND_SOC_DAIFMT_I2S: |
189 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); | 247 | /* Davinci doesn't support TRUE I2S, but some codecs will have |
190 | MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_FSXP | | 248 | * the left and right channels contiguous. This allows |
191 | DAVINCI_MCBSP_PCR_FSRP, 1); | 249 | * dsp_a mode to be used with an inverted normal frame clk. |
192 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w); | 250 | * If your codec is master and does not have contiguous |
251 | * channels, then you will have sound on only one channel. | ||
252 | * Try using a different mode, or codec as slave. | ||
253 | * | ||
254 | * The TLV320AIC33 is an example of a codec where this works. | ||
255 | * It has a variable bit clock frequency allowing it to have | ||
256 | * valid data on every bit clock. | ||
257 | * | ||
258 | * The TLV320AIC23 is an example of a codec where this does not | ||
259 | * work. It has a fixed bit clock frequency with progressively | ||
260 | * more empty bit clock slots between channels as the sample | ||
261 | * rate is lowered. | ||
262 | */ | ||
263 | fmt ^= SND_SOC_DAIFMT_NB_IF; | ||
264 | case SND_SOC_DAIFMT_DSP_A: | ||
265 | rcr |= DAVINCI_MCBSP_RCR_RDATDLY(1); | ||
266 | xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); | ||
267 | break; | ||
268 | default: | ||
269 | printk(KERN_ERR "%s:bad format\n", __func__); | ||
270 | return -EINVAL; | ||
271 | } | ||
272 | |||
273 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
274 | case SND_SOC_DAIFMT_NB_NF: | ||
275 | /* CLKRP Receive clock polarity, | ||
276 | * 1 - sampled on rising edge of CLKR | ||
277 | * valid on rising edge | ||
278 | * CLKXP Transmit clock polarity, | ||
279 | * 1 - clocked on falling edge of CLKX | ||
280 | * valid on rising edge | ||
281 | * FSRP Receive frame sync pol, 0 - active high | ||
282 | * FSXP Transmit frame sync pol, 0 - active high | ||
283 | */ | ||
284 | pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP); | ||
193 | break; | 285 | break; |
194 | case SND_SOC_DAIFMT_IB_IF: | 286 | case SND_SOC_DAIFMT_IB_IF: |
195 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_PCR_REG); | 287 | /* CLKRP Receive clock polarity, |
196 | MOD_REG_BIT(w, DAVINCI_MCBSP_PCR_CLKXP | | 288 | * 0 - sampled on falling edge of CLKR |
197 | DAVINCI_MCBSP_PCR_CLKRP | | 289 | * valid on falling edge |
198 | DAVINCI_MCBSP_PCR_FSXP | | 290 | * CLKXP Transmit clock polarity, |
199 | DAVINCI_MCBSP_PCR_FSRP, 1); | 291 | * 0 - clocked on rising edge of CLKX |
200 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, w); | 292 | * valid on falling edge |
293 | * FSRP Receive frame sync pol, 1 - active low | ||
294 | * FSXP Transmit frame sync pol, 1 - active low | ||
295 | */ | ||
296 | pcr |= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); | ||
201 | break; | 297 | break; |
202 | case SND_SOC_DAIFMT_NB_NF: | 298 | case SND_SOC_DAIFMT_NB_IF: |
299 | /* CLKRP Receive clock polarity, | ||
300 | * 1 - sampled on rising edge of CLKR | ||
301 | * valid on rising edge | ||
302 | * CLKXP Transmit clock polarity, | ||
303 | * 1 - clocked on falling edge of CLKX | ||
304 | * valid on rising edge | ||
305 | * FSRP Receive frame sync pol, 1 - active low | ||
306 | * FSXP Transmit frame sync pol, 1 - active low | ||
307 | */ | ||
308 | pcr |= (DAVINCI_MCBSP_PCR_CLKXP | DAVINCI_MCBSP_PCR_CLKRP | | ||
309 | DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP); | ||
310 | break; | ||
311 | case SND_SOC_DAIFMT_IB_NF: | ||
312 | /* CLKRP Receive clock polarity, | ||
313 | * 0 - sampled on falling edge of CLKR | ||
314 | * valid on falling edge | ||
315 | * CLKXP Transmit clock polarity, | ||
316 | * 0 - clocked on rising edge of CLKX | ||
317 | * valid on falling edge | ||
318 | * FSRP Receive frame sync pol, 0 - active high | ||
319 | * FSXP Transmit frame sync pol, 0 - active high | ||
320 | */ | ||
203 | break; | 321 | break; |
204 | default: | 322 | default: |
205 | return -EINVAL; | 323 | return -EINVAL; |
206 | } | 324 | } |
207 | 325 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr); | |
326 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr); | ||
327 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, rcr); | ||
328 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, xcr); | ||
208 | return 0; | 329 | return 0; |
209 | } | 330 | } |
210 | 331 | ||
211 | static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | 332 | static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, |
212 | struct snd_pcm_hw_params *params) | 333 | struct snd_pcm_hw_params *params, |
334 | struct snd_soc_dai *dai) | ||
213 | { | 335 | { |
214 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 336 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
215 | struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; | 337 | struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data; |
@@ -219,25 +341,20 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
219 | u32 w; | 341 | u32 w; |
220 | 342 | ||
221 | /* general line settings */ | 343 | /* general line settings */ |
222 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, | 344 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); |
223 | DAVINCI_MCBSP_SPCR_RINTM(3) | | 345 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
224 | DAVINCI_MCBSP_SPCR_XINTM(3) | | 346 | w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE; |
225 | DAVINCI_MCBSP_SPCR_FREE); | 347 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
226 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, | 348 | } else { |
227 | DAVINCI_MCBSP_RCR_RFRLEN1(1) | | 349 | w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE; |
228 | DAVINCI_MCBSP_RCR_RDATDLY(1)); | 350 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w); |
229 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, | 351 | } |
230 | DAVINCI_MCBSP_XCR_XFRLEN1(1) | | ||
231 | DAVINCI_MCBSP_XCR_XDATDLY(1) | | ||
232 | DAVINCI_MCBSP_XCR_XFIG); | ||
233 | 352 | ||
234 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); | 353 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS); |
235 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG); | 354 | w = DAVINCI_MCBSP_SRGR_FSGM; |
236 | MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); | 355 | MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FWID(snd_interval_value(i) - 1), 1); |
237 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); | ||
238 | 356 | ||
239 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); | 357 | i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_FRAME_BITS); |
240 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG); | ||
241 | MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); | 358 | MOD_REG_BIT(w, DAVINCI_MCBSP_SRGR_FPER(snd_interval_value(i) - 1), 1); |
242 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); | 359 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, w); |
243 | 360 | ||
@@ -260,20 +377,24 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream, | |||
260 | return -EINVAL; | 377 | return -EINVAL; |
261 | } | 378 | } |
262 | 379 | ||
263 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); | 380 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { |
264 | MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | | 381 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG); |
265 | DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1); | 382 | MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | |
266 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w); | 383 | DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1); |
384 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w); | ||
267 | 385 | ||
268 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); | 386 | } else { |
269 | MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | | 387 | w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG); |
270 | DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); | 388 | MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) | |
271 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w); | 389 | DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1); |
390 | davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w); | ||
272 | 391 | ||
392 | } | ||
273 | return 0; | 393 | return 0; |
274 | } | 394 | } |
275 | 395 | ||
276 | static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 396 | static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
397 | struct snd_soc_dai *dai) | ||
277 | { | 398 | { |
278 | int ret = 0; | 399 | int ret = 0; |
279 | 400 | ||
@@ -299,8 +420,8 @@ static int davinci_i2s_probe(struct platform_device *pdev, | |||
299 | struct snd_soc_dai *dai) | 420 | struct snd_soc_dai *dai) |
300 | { | 421 | { |
301 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 422 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
302 | struct snd_soc_machine *machine = socdev->machine; | 423 | struct snd_soc_card *card = socdev->card; |
303 | struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; | 424 | struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai; |
304 | struct davinci_mcbsp_dev *dev; | 425 | struct davinci_mcbsp_dev *dev; |
305 | struct resource *mem, *ioarea; | 426 | struct resource *mem, *ioarea; |
306 | struct evm_snd_platform_data *pdata; | 427 | struct evm_snd_platform_data *pdata; |
@@ -361,8 +482,8 @@ static void davinci_i2s_remove(struct platform_device *pdev, | |||
361 | struct snd_soc_dai *dai) | 482 | struct snd_soc_dai *dai) |
362 | { | 483 | { |
363 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 484 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
364 | struct snd_soc_machine *machine = socdev->machine; | 485 | struct snd_soc_card *card = socdev->card; |
365 | struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai; | 486 | struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai; |
366 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; | 487 | struct davinci_mcbsp_dev *dev = cpu_dai->private_data; |
367 | struct resource *mem; | 488 | struct resource *mem; |
368 | 489 | ||
@@ -381,7 +502,6 @@ static void davinci_i2s_remove(struct platform_device *pdev, | |||
381 | struct snd_soc_dai davinci_i2s_dai = { | 502 | struct snd_soc_dai davinci_i2s_dai = { |
382 | .name = "davinci-i2s", | 503 | .name = "davinci-i2s", |
383 | .id = 0, | 504 | .id = 0, |
384 | .type = SND_SOC_DAI_I2S, | ||
385 | .probe = davinci_i2s_probe, | 505 | .probe = davinci_i2s_probe, |
386 | .remove = davinci_i2s_remove, | 506 | .remove = davinci_i2s_remove, |
387 | .playback = { | 507 | .playback = { |
@@ -397,13 +517,24 @@ struct snd_soc_dai davinci_i2s_dai = { | |||
397 | .ops = { | 517 | .ops = { |
398 | .startup = davinci_i2s_startup, | 518 | .startup = davinci_i2s_startup, |
399 | .trigger = davinci_i2s_trigger, | 519 | .trigger = davinci_i2s_trigger, |
400 | .hw_params = davinci_i2s_hw_params,}, | 520 | .hw_params = davinci_i2s_hw_params, |
401 | .dai_ops = { | ||
402 | .set_fmt = davinci_i2s_set_dai_fmt, | 521 | .set_fmt = davinci_i2s_set_dai_fmt, |
403 | }, | 522 | }, |
404 | }; | 523 | }; |
405 | EXPORT_SYMBOL_GPL(davinci_i2s_dai); | 524 | EXPORT_SYMBOL_GPL(davinci_i2s_dai); |
406 | 525 | ||
526 | static int __init davinci_i2s_init(void) | ||
527 | { | ||
528 | return snd_soc_register_dai(&davinci_i2s_dai); | ||
529 | } | ||
530 | module_init(davinci_i2s_init); | ||
531 | |||
532 | static void __exit davinci_i2s_exit(void) | ||
533 | { | ||
534 | snd_soc_unregister_dai(&davinci_i2s_dai); | ||
535 | } | ||
536 | module_exit(davinci_i2s_exit); | ||
537 | |||
407 | MODULE_AUTHOR("Vladimir Barinov"); | 538 | MODULE_AUTHOR("Vladimir Barinov"); |
408 | MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); | 539 | MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface"); |
409 | MODULE_LICENSE("GPL"); | 540 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 76feaa657375..74abc9b4f1cc 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | #include <linux/kernel.h> | ||
17 | 18 | ||
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
@@ -24,13 +25,6 @@ | |||
24 | 25 | ||
25 | #include "davinci-pcm.h" | 26 | #include "davinci-pcm.h" |
26 | 27 | ||
27 | #define DAVINCI_PCM_DEBUG 0 | ||
28 | #if DAVINCI_PCM_DEBUG | ||
29 | #define DPRINTK(x...) printk(KERN_DEBUG x) | ||
30 | #else | ||
31 | #define DPRINTK(x...) | ||
32 | #endif | ||
33 | |||
34 | static struct snd_pcm_hardware davinci_pcm_hardware = { | 28 | static struct snd_pcm_hardware davinci_pcm_hardware = { |
35 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | | 29 | .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | |
36 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | | 30 | SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | |
@@ -78,8 +72,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) | |||
78 | dma_offset = prtd->period * period_size; | 72 | dma_offset = prtd->period * period_size; |
79 | dma_pos = runtime->dma_addr + dma_offset; | 73 | dma_pos = runtime->dma_addr + dma_offset; |
80 | 74 | ||
81 | DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x " | 75 | pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " |
82 | "period_size=%x\n", lch, dma_pos, period_size); | 76 | "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size); |
83 | 77 | ||
84 | data_type = prtd->params->data_type; | 78 | data_type = prtd->params->data_type; |
85 | count = period_size / data_type; | 79 | count = period_size / data_type; |
@@ -112,7 +106,7 @@ static void davinci_pcm_dma_irq(int lch, u16 ch_status, void *data) | |||
112 | struct snd_pcm_substream *substream = data; | 106 | struct snd_pcm_substream *substream = data; |
113 | struct davinci_runtime_data *prtd = substream->runtime->private_data; | 107 | struct davinci_runtime_data *prtd = substream->runtime->private_data; |
114 | 108 | ||
115 | DPRINTK("lch=%d, status=0x%x\n", lch, ch_status); | 109 | pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status); |
116 | 110 | ||
117 | if (unlikely(ch_status != DMA_COMPLETE)) | 111 | if (unlikely(ch_status != DMA_COMPLETE)) |
118 | return; | 112 | return; |
@@ -316,8 +310,8 @@ static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) | |||
316 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, | 310 | buf->area = dma_alloc_writecombine(pcm->card->dev, size, |
317 | &buf->addr, GFP_KERNEL); | 311 | &buf->addr, GFP_KERNEL); |
318 | 312 | ||
319 | DPRINTK("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n", | 313 | pr_debug("davinci_pcm: preallocate_dma_buffer: area=%p, addr=%p, " |
320 | (void *) buf->area, (void *) buf->addr, size); | 314 | "size=%d\n", (void *) buf->area, (void *) buf->addr, size); |
321 | 315 | ||
322 | if (!buf->area) | 316 | if (!buf->area) |
323 | return -ENOMEM; | 317 | return -ENOMEM; |
@@ -384,6 +378,18 @@ struct snd_soc_platform davinci_soc_platform = { | |||
384 | }; | 378 | }; |
385 | EXPORT_SYMBOL_GPL(davinci_soc_platform); | 379 | EXPORT_SYMBOL_GPL(davinci_soc_platform); |
386 | 380 | ||
381 | static int __init davinci_soc_platform_init(void) | ||
382 | { | ||
383 | return snd_soc_register_platform(&davinci_soc_platform); | ||
384 | } | ||
385 | module_init(davinci_soc_platform_init); | ||
386 | |||
387 | static void __exit davinci_soc_platform_exit(void) | ||
388 | { | ||
389 | snd_soc_unregister_platform(&davinci_soc_platform); | ||
390 | } | ||
391 | module_exit(davinci_soc_platform_exit); | ||
392 | |||
387 | MODULE_AUTHOR("Vladimir Barinov"); | 393 | MODULE_AUTHOR("Vladimir Barinov"); |
388 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | 394 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); |
389 | MODULE_LICENSE("GPL"); | 395 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c new file mode 100644 index 000000000000..f67579d52765 --- /dev/null +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * ASoC driver for Lyrtech SFFSDR board. | ||
3 | * | ||
4 | * Author: Hugo Villeneuve | ||
5 | * Copyright (C) 2008 Lyrtech inc | ||
6 | * | ||
7 | * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow: | ||
8 | * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/timer.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <sound/core.h> | ||
22 | #include <sound/pcm.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <sound/soc-dapm.h> | ||
25 | |||
26 | #include <asm/dma.h> | ||
27 | #include <asm/plat-sffsdr/sffsdr-fpga.h> | ||
28 | |||
29 | #include <mach/mcbsp.h> | ||
30 | #include <mach/edma.h> | ||
31 | |||
32 | #include "../codecs/pcm3008.h" | ||
33 | #include "davinci-pcm.h" | ||
34 | #include "davinci-i2s.h" | ||
35 | |||
36 | static int sffsdr_hw_params(struct snd_pcm_substream *substream, | ||
37 | struct snd_pcm_hw_params *params, | ||
38 | struct snd_soc_dai *dai) | ||
39 | { | ||
40 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
41 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
42 | int fs; | ||
43 | int ret = 0; | ||
44 | |||
45 | /* Set cpu DAI configuration: | ||
46 | * CLKX and CLKR are the inputs for the Sample Rate Generator. | ||
47 | * FSX and FSR are outputs, driven by the sample Rate Generator. */ | ||
48 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
49 | SND_SOC_DAIFMT_RIGHT_J | | ||
50 | SND_SOC_DAIFMT_CBM_CFS | | ||
51 | SND_SOC_DAIFMT_IB_NF); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | /* Fsref can be 32000, 44100 or 48000. */ | ||
56 | fs = params_rate(params); | ||
57 | |||
58 | pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs); | ||
59 | |||
60 | return sffsdr_fpga_set_codec_fs(fs); | ||
61 | } | ||
62 | |||
63 | static struct snd_soc_ops sffsdr_ops = { | ||
64 | .hw_params = sffsdr_hw_params, | ||
65 | }; | ||
66 | |||
67 | /* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */ | ||
68 | static struct snd_soc_dai_link sffsdr_dai = { | ||
69 | .name = "PCM3008", /* Codec name */ | ||
70 | .stream_name = "PCM3008 HiFi", | ||
71 | .cpu_dai = &davinci_i2s_dai, | ||
72 | .codec_dai = &pcm3008_dai, | ||
73 | .ops = &sffsdr_ops, | ||
74 | }; | ||
75 | |||
76 | /* davinci-sffsdr audio machine driver */ | ||
77 | static struct snd_soc_card snd_soc_sffsdr = { | ||
78 | .name = "DaVinci SFFSDR", | ||
79 | .platform = &davinci_soc_platform, | ||
80 | .dai_link = &sffsdr_dai, | ||
81 | .num_links = 1, | ||
82 | }; | ||
83 | |||
84 | /* sffsdr audio private data */ | ||
85 | static struct pcm3008_setup_data sffsdr_pcm3008_setup = { | ||
86 | .dem0_pin = GPIO(45), | ||
87 | .dem1_pin = GPIO(46), | ||
88 | .pdad_pin = GPIO(47), | ||
89 | .pdda_pin = GPIO(38), | ||
90 | }; | ||
91 | |||
92 | /* sffsdr audio subsystem */ | ||
93 | static struct snd_soc_device sffsdr_snd_devdata = { | ||
94 | .card = &snd_soc_sffsdr, | ||
95 | .codec_dev = &soc_codec_dev_pcm3008, | ||
96 | .codec_data = &sffsdr_pcm3008_setup, | ||
97 | }; | ||
98 | |||
99 | static struct resource sffsdr_snd_resources[] = { | ||
100 | { | ||
101 | .start = DAVINCI_MCBSP_BASE, | ||
102 | .end = DAVINCI_MCBSP_BASE + SZ_8K - 1, | ||
103 | .flags = IORESOURCE_MEM, | ||
104 | }, | ||
105 | }; | ||
106 | |||
107 | static struct evm_snd_platform_data sffsdr_snd_data = { | ||
108 | .tx_dma_ch = DAVINCI_DMA_MCBSP_TX, | ||
109 | .rx_dma_ch = DAVINCI_DMA_MCBSP_RX, | ||
110 | }; | ||
111 | |||
112 | static struct platform_device *sffsdr_snd_device; | ||
113 | |||
114 | static int __init sffsdr_init(void) | ||
115 | { | ||
116 | int ret; | ||
117 | |||
118 | sffsdr_snd_device = platform_device_alloc("soc-audio", 0); | ||
119 | if (!sffsdr_snd_device) { | ||
120 | printk(KERN_ERR "platform device allocation failed\n"); | ||
121 | return -ENOMEM; | ||
122 | } | ||
123 | |||
124 | platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata); | ||
125 | sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev; | ||
126 | sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data; | ||
127 | |||
128 | ret = platform_device_add_resources(sffsdr_snd_device, | ||
129 | sffsdr_snd_resources, | ||
130 | ARRAY_SIZE(sffsdr_snd_resources)); | ||
131 | if (ret) { | ||
132 | printk(KERN_ERR "platform device add ressources failed\n"); | ||
133 | goto error; | ||
134 | } | ||
135 | |||
136 | ret = platform_device_add(sffsdr_snd_device); | ||
137 | if (ret) | ||
138 | goto error; | ||
139 | |||
140 | return ret; | ||
141 | |||
142 | error: | ||
143 | platform_device_put(sffsdr_snd_device); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static void __exit sffsdr_exit(void) | ||
148 | { | ||
149 | platform_device_unregister(sffsdr_snd_device); | ||
150 | } | ||
151 | |||
152 | module_init(sffsdr_init); | ||
153 | module_exit(sffsdr_exit); | ||
154 | |||
155 | MODULE_AUTHOR("Hugo Villeneuve"); | ||
156 | MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver"); | ||
157 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8d73edc56102..95c12b26fe37 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig | |||
@@ -20,7 +20,7 @@ config SND_SOC_MPC8610_HPCD | |||
20 | 20 | ||
21 | config SND_SOC_MPC5200_I2S | 21 | config SND_SOC_MPC5200_I2S |
22 | tristate "Freescale MPC5200 PSC in I2S mode driver" | 22 | tristate "Freescale MPC5200 PSC in I2S mode driver" |
23 | depends on SND_SOC && PPC_MPC52xx && PPC_BESTCOMM | 23 | depends on PPC_MPC52xx && PPC_BESTCOMM |
24 | select SND_SOC_OF_SIMPLE | 24 | select SND_SOC_OF_SIMPLE |
25 | select PPC_BESTCOMM_GEN_BD | 25 | select PPC_BESTCOMM_GEN_BD |
26 | help | 26 | help |
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index d2d3da9729f2..64993eda5679 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) | |||
284 | * fsl_dma_new: initialize this PCM driver. | 284 | * fsl_dma_new: initialize this PCM driver. |
285 | * | 285 | * |
286 | * This function is called when the codec driver calls snd_soc_new_pcms(), | 286 | * This function is called when the codec driver calls snd_soc_new_pcms(), |
287 | * once for each .dai_link in the machine driver's snd_soc_machine | 287 | * once for each .dai_link in the machine driver's snd_soc_card |
288 | * structure. | 288 | * structure. |
289 | */ | 289 | */ |
290 | static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, | 290 | static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai, |
@@ -853,6 +853,18 @@ int fsl_dma_configure(struct fsl_dma_info *dma_info) | |||
853 | } | 853 | } |
854 | EXPORT_SYMBOL_GPL(fsl_dma_configure); | 854 | EXPORT_SYMBOL_GPL(fsl_dma_configure); |
855 | 855 | ||
856 | static int __init fsl_soc_platform_init(void) | ||
857 | { | ||
858 | return snd_soc_register_platform(&fsl_soc_platform); | ||
859 | } | ||
860 | module_init(fsl_soc_platform_init); | ||
861 | |||
862 | static void __exit fsl_soc_platform_exit(void) | ||
863 | { | ||
864 | snd_soc_unregister_platform(&fsl_soc_platform); | ||
865 | } | ||
866 | module_exit(fsl_soc_platform_exit); | ||
867 | |||
856 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 868 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
857 | MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); | 869 | MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module"); |
858 | MODULE_LICENSE("GPL"); | 870 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 157a7895ffa1..c6d6eb71dc1d 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -266,7 +266,8 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id) | |||
266 | * If this is the first stream open, then grab the IRQ and program most of | 266 | * If this is the first stream open, then grab the IRQ and program most of |
267 | * the SSI registers. | 267 | * the SSI registers. |
268 | */ | 268 | */ |
269 | static int fsl_ssi_startup(struct snd_pcm_substream *substream) | 269 | static int fsl_ssi_startup(struct snd_pcm_substream *substream, |
270 | struct snd_soc_dai *dai) | ||
270 | { | 271 | { |
271 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 272 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
272 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 273 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; |
@@ -411,7 +412,8 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream) | |||
411 | * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the | 412 | * Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the |
412 | * clock master. | 413 | * clock master. |
413 | */ | 414 | */ |
414 | static int fsl_ssi_prepare(struct snd_pcm_substream *substream) | 415 | static int fsl_ssi_prepare(struct snd_pcm_substream *substream, |
416 | struct snd_soc_dai *dai) | ||
415 | { | 417 | { |
416 | struct snd_pcm_runtime *runtime = substream->runtime; | 418 | struct snd_pcm_runtime *runtime = substream->runtime; |
417 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 419 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
@@ -441,7 +443,8 @@ static int fsl_ssi_prepare(struct snd_pcm_substream *substream) | |||
441 | * The DMA channel is in external master start and pause mode, which | 443 | * The DMA channel is in external master start and pause mode, which |
442 | * means the SSI completely controls the flow of data. | 444 | * means the SSI completely controls the flow of data. |
443 | */ | 445 | */ |
444 | static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd) | 446 | static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd, |
447 | struct snd_soc_dai *dai) | ||
445 | { | 448 | { |
446 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 449 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
447 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 450 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; |
@@ -490,7 +493,8 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd) | |||
490 | * | 493 | * |
491 | * Shutdown the SSI if there are no other substreams open. | 494 | * Shutdown the SSI if there are no other substreams open. |
492 | */ | 495 | */ |
493 | static void fsl_ssi_shutdown(struct snd_pcm_substream *substream) | 496 | static void fsl_ssi_shutdown(struct snd_pcm_substream *substream, |
497 | struct snd_soc_dai *dai) | ||
494 | { | 498 | { |
495 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 499 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
496 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; | 500 | struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data; |
@@ -578,8 +582,6 @@ static struct snd_soc_dai fsl_ssi_dai_template = { | |||
578 | .prepare = fsl_ssi_prepare, | 582 | .prepare = fsl_ssi_prepare, |
579 | .shutdown = fsl_ssi_shutdown, | 583 | .shutdown = fsl_ssi_shutdown, |
580 | .trigger = fsl_ssi_trigger, | 584 | .trigger = fsl_ssi_trigger, |
581 | }, | ||
582 | .dai_ops = { | ||
583 | .set_sysclk = fsl_ssi_set_sysclk, | 585 | .set_sysclk = fsl_ssi_set_sysclk, |
584 | .set_fmt = fsl_ssi_set_fmt, | 586 | .set_fmt = fsl_ssi_set_fmt, |
585 | }, | 587 | }, |
@@ -671,6 +673,14 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info) | |||
671 | fsl_ssi_dai->private_data = ssi_private; | 673 | fsl_ssi_dai->private_data = ssi_private; |
672 | fsl_ssi_dai->name = ssi_private->name; | 674 | fsl_ssi_dai->name = ssi_private->name; |
673 | fsl_ssi_dai->id = ssi_info->id; | 675 | fsl_ssi_dai->id = ssi_info->id; |
676 | fsl_ssi_dai->dev = ssi_info->dev; | ||
677 | |||
678 | ret = snd_soc_register_dai(fsl_ssi_dai); | ||
679 | if (ret != 0) { | ||
680 | dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret); | ||
681 | kfree(fsl_ssi_dai); | ||
682 | return NULL; | ||
683 | } | ||
674 | 684 | ||
675 | return fsl_ssi_dai; | 685 | return fsl_ssi_dai; |
676 | } | 686 | } |
@@ -688,6 +698,8 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai) | |||
688 | 698 | ||
689 | device_remove_file(ssi_private->dev, &ssi_private->dev_attr); | 699 | device_remove_file(ssi_private->dev, &ssi_private->dev_attr); |
690 | 700 | ||
701 | snd_soc_unregister_dai(&ssi_private->cpu_dai); | ||
702 | |||
691 | kfree(ssi_private); | 703 | kfree(ssi_private); |
692 | } | 704 | } |
693 | EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai); | 705 | 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 94a02eaa4825..9eb1ce185bd0 100644 --- a/sound/soc/fsl/mpc5200_psc_i2s.c +++ b/sound/soc/fsl/mpc5200_psc_i2s.c | |||
@@ -187,7 +187,8 @@ static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream) | |||
187 | * If this is the first stream open, then grab the IRQ and program most of | 187 | * If this is the first stream open, then grab the IRQ and program most of |
188 | * the PSC registers. | 188 | * the PSC registers. |
189 | */ | 189 | */ |
190 | static int psc_i2s_startup(struct snd_pcm_substream *substream) | 190 | static int psc_i2s_startup(struct snd_pcm_substream *substream, |
191 | struct snd_soc_dai *dai) | ||
191 | { | 192 | { |
192 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 193 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
193 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; | 194 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; |
@@ -220,7 +221,8 @@ static int psc_i2s_startup(struct snd_pcm_substream *substream) | |||
220 | } | 221 | } |
221 | 222 | ||
222 | static int psc_i2s_hw_params(struct snd_pcm_substream *substream, | 223 | static int psc_i2s_hw_params(struct snd_pcm_substream *substream, |
223 | struct snd_pcm_hw_params *params) | 224 | struct snd_pcm_hw_params *params, |
225 | struct snd_soc_dai *dai) | ||
224 | { | 226 | { |
225 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 227 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
226 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; | 228 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; |
@@ -256,7 +258,8 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream, | |||
256 | return 0; | 258 | return 0; |
257 | } | 259 | } |
258 | 260 | ||
259 | static int psc_i2s_hw_free(struct snd_pcm_substream *substream) | 261 | static int psc_i2s_hw_free(struct snd_pcm_substream *substream, |
262 | struct snd_soc_dai *dai) | ||
260 | { | 263 | { |
261 | snd_pcm_set_runtime_buffer(substream, NULL); | 264 | snd_pcm_set_runtime_buffer(substream, NULL); |
262 | return 0; | 265 | return 0; |
@@ -268,7 +271,8 @@ static int psc_i2s_hw_free(struct snd_pcm_substream *substream) | |||
268 | * This function is called by ALSA to start, stop, pause, and resume the DMA | 271 | * This function is called by ALSA to start, stop, pause, and resume the DMA |
269 | * transfer of data. | 272 | * transfer of data. |
270 | */ | 273 | */ |
271 | static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 274 | static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
275 | struct snd_soc_dai *dai) | ||
272 | { | 276 | { |
273 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
274 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; | 278 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; |
@@ -383,7 +387,8 @@ static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | |||
383 | * | 387 | * |
384 | * Shutdown the PSC if there are no other substreams open. | 388 | * Shutdown the PSC if there are no other substreams open. |
385 | */ | 389 | */ |
386 | static void psc_i2s_shutdown(struct snd_pcm_substream *substream) | 390 | static void psc_i2s_shutdown(struct snd_pcm_substream *substream, |
391 | struct snd_soc_dai *dai) | ||
387 | { | 392 | { |
388 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 393 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
389 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; | 394 | struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data; |
@@ -464,7 +469,6 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format) | |||
464 | * psc_i2s_dai_template: template CPU Digital Audio Interface | 469 | * psc_i2s_dai_template: template CPU Digital Audio Interface |
465 | */ | 470 | */ |
466 | static struct snd_soc_dai psc_i2s_dai_template = { | 471 | static struct snd_soc_dai psc_i2s_dai_template = { |
467 | .type = SND_SOC_DAI_I2S, | ||
468 | .playback = { | 472 | .playback = { |
469 | .channels_min = 2, | 473 | .channels_min = 2, |
470 | .channels_max = 2, | 474 | .channels_max = 2, |
@@ -483,8 +487,6 @@ static struct snd_soc_dai psc_i2s_dai_template = { | |||
483 | .hw_free = psc_i2s_hw_free, | 487 | .hw_free = psc_i2s_hw_free, |
484 | .shutdown = psc_i2s_shutdown, | 488 | .shutdown = psc_i2s_shutdown, |
485 | .trigger = psc_i2s_trigger, | 489 | .trigger = psc_i2s_trigger, |
486 | }, | ||
487 | .dai_ops = { | ||
488 | .set_sysclk = psc_i2s_set_sysclk, | 490 | .set_sysclk = psc_i2s_set_sysclk, |
489 | .set_fmt = psc_i2s_set_fmt, | 491 | .set_fmt = psc_i2s_set_fmt, |
490 | }, | 492 | }, |
@@ -826,6 +828,8 @@ static int __devinit psc_i2s_of_probe(struct of_device *op, | |||
826 | if (rc) | 828 | if (rc) |
827 | dev_info(psc_i2s->dev, "error creating sysfs files\n"); | 829 | dev_info(psc_i2s->dev, "error creating sysfs files\n"); |
828 | 830 | ||
831 | snd_soc_register_platform(&psc_i2s_pcm_soc_platform); | ||
832 | |||
829 | /* Tell the ASoC OF helpers about it */ | 833 | /* Tell the ASoC OF helpers about it */ |
830 | of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node, | 834 | of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node, |
831 | &psc_i2s->dai); | 835 | &psc_i2s->dai); |
@@ -839,6 +843,8 @@ static int __devexit psc_i2s_of_remove(struct of_device *op) | |||
839 | 843 | ||
840 | dev_dbg(&op->dev, "psc_i2s_remove()\n"); | 844 | dev_dbg(&op->dev, "psc_i2s_remove()\n"); |
841 | 845 | ||
846 | snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform); | ||
847 | |||
842 | bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task); | 848 | bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task); |
843 | bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task); | 849 | bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task); |
844 | 850 | ||
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index 94f89debde1f..bcec3f60bad9 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c | |||
@@ -29,7 +29,7 @@ | |||
29 | struct mpc8610_hpcd_data { | 29 | struct mpc8610_hpcd_data { |
30 | struct snd_soc_device sound_devdata; | 30 | struct snd_soc_device sound_devdata; |
31 | struct snd_soc_dai_link dai; | 31 | struct snd_soc_dai_link dai; |
32 | struct snd_soc_machine machine; | 32 | struct snd_soc_card machine; |
33 | unsigned int dai_format; | 33 | unsigned int dai_format; |
34 | unsigned int codec_clk_direction; | 34 | unsigned int codec_clk_direction; |
35 | unsigned int cpu_clk_direction; | 35 | unsigned int cpu_clk_direction; |
@@ -185,7 +185,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = { | |||
185 | /** | 185 | /** |
186 | * mpc8610_hpcd_machine: ASoC machine data | 186 | * mpc8610_hpcd_machine: ASoC machine data |
187 | */ | 187 | */ |
188 | static struct snd_soc_machine mpc8610_hpcd_machine = { | 188 | static struct snd_soc_card mpc8610_hpcd_machine = { |
189 | .probe = mpc8610_hpcd_machine_probe, | 189 | .probe = mpc8610_hpcd_machine_probe, |
190 | .remove = mpc8610_hpcd_machine_remove, | 190 | .remove = mpc8610_hpcd_machine_remove, |
191 | .name = "MPC8610 HPCD", | 191 | .name = "MPC8610 HPCD", |
@@ -465,9 +465,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev, | |||
465 | goto error; | 465 | goto error; |
466 | } | 466 | } |
467 | 467 | ||
468 | machine_data->sound_devdata.machine = &mpc8610_hpcd_machine; | 468 | machine_data->sound_devdata.card = &mpc8610_hpcd_machine; |
469 | machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; | 469 | machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270; |
470 | machine_data->sound_devdata.platform = &fsl_soc_platform; | 470 | machine_data->machine.platform = &fsl_soc_platform; |
471 | 471 | ||
472 | sound_device->dev.platform_data = machine_data; | 472 | sound_device->dev.platform_data = machine_data; |
473 | 473 | ||
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c index 0382fdac51cd..8bc5cd9e972f 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 { | |||
31 | int id; | 31 | int id; |
32 | struct list_head list; | 32 | struct list_head list; |
33 | struct snd_soc_device device; | 33 | struct snd_soc_device device; |
34 | struct snd_soc_machine machine; | 34 | struct snd_soc_card card; |
35 | struct snd_soc_dai_link dai_link; | 35 | struct snd_soc_dai_link dai_link; |
36 | struct platform_device *pdev; | 36 | struct platform_device *pdev; |
37 | struct device_node *platform_node; | 37 | struct device_node *platform_node; |
@@ -58,9 +58,9 @@ of_snd_soc_get_device(struct device_node *codec_node) | |||
58 | /* Initialize the structure and add it to the global list */ | 58 | /* Initialize the structure and add it to the global list */ |
59 | of_soc->codec_node = codec_node; | 59 | of_soc->codec_node = codec_node; |
60 | of_soc->id = of_snd_soc_next_index++; | 60 | of_soc->id = of_snd_soc_next_index++; |
61 | of_soc->machine.dai_link = &of_soc->dai_link; | 61 | of_soc->card.dai_link = &of_soc->dai_link; |
62 | of_soc->machine.num_links = 1; | 62 | of_soc->card.num_links = 1; |
63 | of_soc->device.machine = &of_soc->machine; | 63 | of_soc->device.card = &of_soc->card; |
64 | of_soc->dai_link.ops = &of_snd_soc_ops; | 64 | of_soc->dai_link.ops = &of_snd_soc_ops; |
65 | list_add(&of_soc->list, &of_snd_soc_device_list); | 65 | list_add(&of_soc->list, &of_snd_soc_device_list); |
66 | 66 | ||
@@ -158,8 +158,8 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform, | |||
158 | 158 | ||
159 | of_soc->platform_node = node; | 159 | of_soc->platform_node = node; |
160 | of_soc->dai_link.cpu_dai = cpu_dai; | 160 | of_soc->dai_link.cpu_dai = cpu_dai; |
161 | of_soc->device.platform = platform; | 161 | of_soc->card.platform = platform; |
162 | of_soc->machine.name = of_soc->dai_link.cpu_dai->name; | 162 | of_soc->card.name = of_soc->dai_link.cpu_dai->name; |
163 | 163 | ||
164 | /* Now try to register the SoC device */ | 164 | /* Now try to register the SoC device */ |
165 | of_snd_soc_register_device(of_soc); | 165 | of_snd_soc_register_device(of_soc); |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index 8b7766b998d7..a7b1d77b2105 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_OMAP_SOC | 1 | config SND_OMAP_SOC |
2 | tristate "SoC Audio for the Texas Instruments OMAP chips" | 2 | tristate "SoC Audio for the Texas Instruments OMAP chips" |
3 | depends on ARCH_OMAP && SND_SOC | 3 | depends on ARCH_OMAP |
4 | 4 | ||
5 | config SND_OMAP_SOC_MCBSP | 5 | config SND_OMAP_SOC_MCBSP |
6 | tristate | 6 | tristate |
@@ -21,3 +21,36 @@ config SND_OMAP_SOC_OSK5912 | |||
21 | select SND_SOC_TLV320AIC23 | 21 | select SND_SOC_TLV320AIC23 |
22 | help | 22 | help |
23 | Say Y if you want to add support for SoC audio on osk5912. | 23 | Say Y if you want to add support for SoC audio on osk5912. |
24 | |||
25 | config SND_OMAP_SOC_OVERO | ||
26 | tristate "SoC Audio support for Gumstix Overo" | ||
27 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO | ||
28 | select SND_OMAP_SOC_MCBSP | ||
29 | select SND_SOC_TWL4030 | ||
30 | help | ||
31 | Say Y if you want to add support for SoC audio on the Gumstix Overo. | ||
32 | |||
33 | config SND_OMAP_SOC_OMAP2EVM | ||
34 | tristate "SoC Audio support for OMAP2EVM board" | ||
35 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM | ||
36 | select SND_OMAP_SOC_MCBSP | ||
37 | select SND_SOC_TWL4030 | ||
38 | help | ||
39 | Say Y if you want to add support for SoC audio on the omap2evm board. | ||
40 | |||
41 | config SND_OMAP_SOC_SDP3430 | ||
42 | tristate "SoC Audio support for Texas Instruments SDP3430" | ||
43 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP | ||
44 | select SND_OMAP_SOC_MCBSP | ||
45 | select SND_SOC_TWL4030 | ||
46 | help | ||
47 | Say Y if you want to add support for SoC audio on Texas Instruments | ||
48 | SDP3430. | ||
49 | |||
50 | config SND_OMAP_SOC_OMAP3_PANDORA | ||
51 | tristate "SoC Audio support for OMAP3 Pandora" | ||
52 | depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA | ||
53 | select SND_OMAP_SOC_MCBSP | ||
54 | select SND_SOC_TWL4030 | ||
55 | help | ||
56 | 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 e09d1f297f64..76fedd96e365 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -8,6 +8,14 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o | |||
8 | # OMAP Machine Support | 8 | # OMAP Machine Support |
9 | snd-soc-n810-objs := n810.o | 9 | snd-soc-n810-objs := n810.o |
10 | snd-soc-osk5912-objs := osk5912.o | 10 | snd-soc-osk5912-objs := osk5912.o |
11 | snd-soc-overo-objs := overo.o | ||
12 | snd-soc-omap2evm-objs := omap2evm.o | ||
13 | snd-soc-sdp3430-objs := sdp3430.o | ||
14 | snd-soc-omap3pandora-objs := omap3pandora.o | ||
11 | 15 | ||
12 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 16 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
13 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 17 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
18 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | ||
19 | obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o | ||
20 | obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o | ||
21 | 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 fae3ad36e0bf..25593fee9121 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c | |||
@@ -70,9 +70,13 @@ static void n810_ext_control(struct snd_soc_codec *codec) | |||
70 | 70 | ||
71 | static int n810_startup(struct snd_pcm_substream *substream) | 71 | static int n810_startup(struct snd_pcm_substream *substream) |
72 | { | 72 | { |
73 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
73 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 74 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
74 | struct snd_soc_codec *codec = rtd->socdev->codec; | 75 | struct snd_soc_codec *codec = rtd->socdev->codec; |
75 | 76 | ||
77 | snd_pcm_hw_constraint_minmax(runtime, | ||
78 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | ||
79 | |||
76 | n810_ext_control(codec); | 80 | n810_ext_control(codec); |
77 | return clk_enable(sys_clkout2); | 81 | return clk_enable(sys_clkout2); |
78 | } | 82 | } |
@@ -282,8 +286,9 @@ static struct snd_soc_dai_link n810_dai = { | |||
282 | }; | 286 | }; |
283 | 287 | ||
284 | /* Audio machine driver */ | 288 | /* Audio machine driver */ |
285 | static struct snd_soc_machine snd_soc_machine_n810 = { | 289 | static struct snd_soc_card snd_soc_n810 = { |
286 | .name = "N810", | 290 | .name = "N810", |
291 | .platform = &omap_soc_platform, | ||
287 | .dai_link = &n810_dai, | 292 | .dai_link = &n810_dai, |
288 | .num_links = 1, | 293 | .num_links = 1, |
289 | }; | 294 | }; |
@@ -298,8 +303,7 @@ static struct aic3x_setup_data n810_aic33_setup = { | |||
298 | 303 | ||
299 | /* Audio subsystem */ | 304 | /* Audio subsystem */ |
300 | static struct snd_soc_device n810_snd_devdata = { | 305 | static struct snd_soc_device n810_snd_devdata = { |
301 | .machine = &snd_soc_machine_n810, | 306 | .card = &snd_soc_n810, |
302 | .platform = &omap_soc_platform, | ||
303 | .codec_dev = &soc_codec_dev_aic3x, | 307 | .codec_dev = &soc_codec_dev_aic3x, |
304 | .codec_data = &n810_aic33_setup, | 308 | .codec_data = &n810_aic33_setup, |
305 | }; | 309 | }; |
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c index 8485a8a9d0ff..ec5e18a78758 100644 --- a/sound/soc/omap/omap-mcbsp.c +++ b/sound/soc/omap/omap-mcbsp.c | |||
@@ -36,9 +36,7 @@ | |||
36 | #include "omap-mcbsp.h" | 36 | #include "omap-mcbsp.h" |
37 | #include "omap-pcm.h" | 37 | #include "omap-pcm.h" |
38 | 38 | ||
39 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \ | 39 | #define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000) |
40 | SNDRV_PCM_RATE_48000 | \ | ||
41 | SNDRV_PCM_RATE_KNOT) | ||
42 | 40 | ||
43 | struct omap_mcbsp_data { | 41 | struct omap_mcbsp_data { |
44 | unsigned int bus_id; | 42 | unsigned int bus_id; |
@@ -140,7 +138,8 @@ static const unsigned long omap34xx_mcbsp_port[][2] = { | |||
140 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; | 138 | static const unsigned long omap34xx_mcbsp_port[][2] = {}; |
141 | #endif | 139 | #endif |
142 | 140 | ||
143 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) | 141 | static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream, |
142 | struct snd_soc_dai *dai) | ||
144 | { | 143 | { |
145 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 144 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
146 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 145 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -153,7 +152,8 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream) | |||
153 | return err; | 152 | return err; |
154 | } | 153 | } |
155 | 154 | ||
156 | static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) | 155 | static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream, |
156 | struct snd_soc_dai *dai) | ||
157 | { | 157 | { |
158 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 158 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
159 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 159 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -165,7 +165,8 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream) | |||
165 | } | 165 | } |
166 | } | 166 | } |
167 | 167 | ||
168 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) | 168 | static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd, |
169 | struct snd_soc_dai *dai) | ||
169 | { | 170 | { |
170 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 171 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
171 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 172 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -194,14 +195,15 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd) | |||
194 | } | 195 | } |
195 | 196 | ||
196 | static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | 197 | static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, |
197 | struct snd_pcm_hw_params *params) | 198 | struct snd_pcm_hw_params *params, |
199 | struct snd_soc_dai *dai) | ||
198 | { | 200 | { |
199 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 201 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
200 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 202 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
201 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); | 203 | struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data); |
202 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; | 204 | struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; |
203 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; | 205 | int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; |
204 | int wlen; | 206 | int wlen, channels; |
205 | unsigned long port; | 207 | unsigned long port; |
206 | 208 | ||
207 | if (cpu_class_is_omap1()) { | 209 | if (cpu_class_is_omap1()) { |
@@ -230,12 +232,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
230 | return 0; | 232 | return 0; |
231 | } | 233 | } |
232 | 234 | ||
233 | switch (params_channels(params)) { | 235 | channels = params_channels(params); |
236 | switch (channels) { | ||
234 | case 2: | 237 | case 2: |
235 | /* Set 1 word per (McBPSP) frame and use dual-phase frames */ | 238 | /* Use dual-phase frames */ |
236 | regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE; | 239 | regs->rcr2 |= RPHASE; |
240 | regs->xcr2 |= XPHASE; | ||
241 | case 1: | ||
242 | /* Set 1 word per (McBSP) frame */ | ||
243 | regs->rcr2 |= RFRLEN2(1 - 1); | ||
237 | regs->rcr1 |= RFRLEN1(1 - 1); | 244 | regs->rcr1 |= RFRLEN1(1 - 1); |
238 | regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE; | 245 | regs->xcr2 |= XFRLEN2(1 - 1); |
239 | regs->xcr1 |= XFRLEN1(1 - 1); | 246 | regs->xcr1 |= XFRLEN1(1 - 1); |
240 | break; | 247 | break; |
241 | default: | 248 | default: |
@@ -263,9 +270,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream, | |||
263 | regs->srgr2 |= FPER(wlen * 2 - 1); | 270 | regs->srgr2 |= FPER(wlen * 2 - 1); |
264 | regs->srgr1 |= FWID(wlen - 1); | 271 | regs->srgr1 |= FWID(wlen - 1); |
265 | break; | 272 | break; |
266 | case SND_SOC_DAIFMT_DSP_A: | 273 | case SND_SOC_DAIFMT_DSP_B: |
267 | regs->srgr2 |= FPER(wlen * 2 - 1); | 274 | regs->srgr2 |= FPER(wlen * channels - 1); |
268 | regs->srgr1 |= FWID(wlen * 2 - 2); | 275 | regs->srgr1 |= FWID(wlen * channels - 2); |
269 | break; | 276 | break; |
270 | } | 277 | } |
271 | 278 | ||
@@ -302,7 +309,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai, | |||
302 | regs->rcr2 |= RDATDLY(1); | 309 | regs->rcr2 |= RDATDLY(1); |
303 | regs->xcr2 |= XDATDLY(1); | 310 | regs->xcr2 |= XDATDLY(1); |
304 | break; | 311 | break; |
305 | case SND_SOC_DAIFMT_DSP_A: | 312 | case SND_SOC_DAIFMT_DSP_B: |
306 | /* 0-bit data delay */ | 313 | /* 0-bit data delay */ |
307 | regs->rcr2 |= RDATDLY(0); | 314 | regs->rcr2 |= RDATDLY(0); |
308 | regs->xcr2 |= XDATDLY(0); | 315 | regs->xcr2 |= XDATDLY(0); |
@@ -452,17 +459,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
452 | 459 | ||
453 | #define OMAP_MCBSP_DAI_BUILDER(link_id) \ | 460 | #define OMAP_MCBSP_DAI_BUILDER(link_id) \ |
454 | { \ | 461 | { \ |
455 | .name = "omap-mcbsp-dai-(link_id)", \ | 462 | .name = "omap-mcbsp-dai-"#link_id, \ |
456 | .id = (link_id), \ | 463 | .id = (link_id), \ |
457 | .type = SND_SOC_DAI_I2S, \ | ||
458 | .playback = { \ | 464 | .playback = { \ |
459 | .channels_min = 2, \ | 465 | .channels_min = 1, \ |
460 | .channels_max = 2, \ | 466 | .channels_max = 2, \ |
461 | .rates = OMAP_MCBSP_RATES, \ | 467 | .rates = OMAP_MCBSP_RATES, \ |
462 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 468 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
463 | }, \ | 469 | }, \ |
464 | .capture = { \ | 470 | .capture = { \ |
465 | .channels_min = 2, \ | 471 | .channels_min = 1, \ |
466 | .channels_max = 2, \ | 472 | .channels_max = 2, \ |
467 | .rates = OMAP_MCBSP_RATES, \ | 473 | .rates = OMAP_MCBSP_RATES, \ |
468 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ | 474 | .formats = SNDRV_PCM_FMTBIT_S16_LE, \ |
@@ -472,8 +478,6 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
472 | .shutdown = omap_mcbsp_dai_shutdown, \ | 478 | .shutdown = omap_mcbsp_dai_shutdown, \ |
473 | .trigger = omap_mcbsp_dai_trigger, \ | 479 | .trigger = omap_mcbsp_dai_trigger, \ |
474 | .hw_params = omap_mcbsp_dai_hw_params, \ | 480 | .hw_params = omap_mcbsp_dai_hw_params, \ |
475 | }, \ | ||
476 | .dai_ops = { \ | ||
477 | .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ | 481 | .set_fmt = omap_mcbsp_dai_set_dai_fmt, \ |
478 | .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ | 482 | .set_clkdiv = omap_mcbsp_dai_set_clkdiv, \ |
479 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ | 483 | .set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \ |
@@ -495,6 +499,19 @@ struct snd_soc_dai omap_mcbsp_dai[] = { | |||
495 | 499 | ||
496 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); | 500 | EXPORT_SYMBOL_GPL(omap_mcbsp_dai); |
497 | 501 | ||
502 | static int __init snd_omap_mcbsp_init(void) | ||
503 | { | ||
504 | return snd_soc_register_dais(omap_mcbsp_dai, | ||
505 | ARRAY_SIZE(omap_mcbsp_dai)); | ||
506 | } | ||
507 | module_init(snd_omap_mcbsp_init); | ||
508 | |||
509 | static void __exit snd_omap_mcbsp_exit(void) | ||
510 | { | ||
511 | snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai)); | ||
512 | } | ||
513 | module_exit(snd_omap_mcbsp_exit); | ||
514 | |||
498 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); | 515 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); |
499 | MODULE_DESCRIPTION("OMAP I2S SoC Interface"); | 516 | MODULE_DESCRIPTION("OMAP I2S SoC Interface"); |
500 | MODULE_LICENSE("GPL"); | 517 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c index e9084fdd2082..b0362dfd5b71 100644 --- a/sound/soc/omap/omap-pcm.c +++ b/sound/soc/omap/omap-pcm.c | |||
@@ -97,7 +97,7 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream, | |||
97 | prtd->dma_data = dma_data; | 97 | prtd->dma_data = dma_data; |
98 | err = omap_request_dma(dma_data->dma_req, dma_data->name, | 98 | err = omap_request_dma(dma_data->dma_req, dma_data->name, |
99 | omap_pcm_dma_irq, substream, &prtd->dma_ch); | 99 | omap_pcm_dma_irq, substream, &prtd->dma_ch); |
100 | if (!err & !cpu_is_omap1510()) { | 100 | if (!err && !cpu_is_omap1510()) { |
101 | /* | 101 | /* |
102 | * Link channel with itself so DMA doesn't need any | 102 | * Link channel with itself so DMA doesn't need any |
103 | * reprogramming while looping the buffer | 103 | * reprogramming while looping the buffer |
@@ -233,7 +233,7 @@ static int omap_pcm_open(struct snd_pcm_substream *substream) | |||
233 | if (ret < 0) | 233 | if (ret < 0) |
234 | goto out; | 234 | goto out; |
235 | 235 | ||
236 | prtd = kzalloc(sizeof(prtd), GFP_KERNEL); | 236 | prtd = kzalloc(sizeof(*prtd), GFP_KERNEL); |
237 | if (prtd == NULL) { | 237 | if (prtd == NULL) { |
238 | ret = -ENOMEM; | 238 | ret = -ENOMEM; |
239 | goto out; | 239 | goto out; |
@@ -354,6 +354,18 @@ struct snd_soc_platform omap_soc_platform = { | |||
354 | }; | 354 | }; |
355 | EXPORT_SYMBOL_GPL(omap_soc_platform); | 355 | EXPORT_SYMBOL_GPL(omap_soc_platform); |
356 | 356 | ||
357 | static int __init omap_soc_platform_init(void) | ||
358 | { | ||
359 | return snd_soc_register_platform(&omap_soc_platform); | ||
360 | } | ||
361 | module_init(omap_soc_platform_init); | ||
362 | |||
363 | static void __exit omap_soc_platform_exit(void) | ||
364 | { | ||
365 | snd_soc_unregister_platform(&omap_soc_platform); | ||
366 | } | ||
367 | module_exit(omap_soc_platform_exit); | ||
368 | |||
357 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); | 369 | MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>"); |
358 | MODULE_DESCRIPTION("OMAP PCM DMA module"); | 370 | MODULE_DESCRIPTION("OMAP PCM DMA module"); |
359 | MODULE_LICENSE("GPL"); | 371 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c new file mode 100644 index 000000000000..0c2322dcf02a --- /dev/null +++ b/sound/soc/omap/omap2evm.c | |||
@@ -0,0 +1,151 @@ | |||
1 | /* | ||
2 | * omap2evm.c -- SoC audio machine driver for omap2evm board | ||
3 | * | ||
4 | * Author: Arun KS <arunks@mistralsolutions.com> | ||
5 | * | ||
6 | * Based on sound/soc/omap/overo.c by Steve Sakoman | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * version 2 as published by the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, but | ||
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
20 | * 02110-1301 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | #include <linux/clk.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/soc-dapm.h> | ||
30 | |||
31 | #include <asm/mach-types.h> | ||
32 | #include <mach/hardware.h> | ||
33 | #include <mach/gpio.h> | ||
34 | #include <mach/mcbsp.h> | ||
35 | |||
36 | #include "omap-mcbsp.h" | ||
37 | #include "omap-pcm.h" | ||
38 | #include "../codecs/twl4030.h" | ||
39 | |||
40 | static int omap2evm_hw_params(struct snd_pcm_substream *substream, | ||
41 | struct snd_pcm_hw_params *params, | ||
42 | struct snd_soc_dai *dai) | ||
43 | { | ||
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
45 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
46 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
47 | int ret; | ||
48 | |||
49 | /* Set codec DAI configuration */ | ||
50 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
51 | SND_SOC_DAIFMT_I2S | | ||
52 | SND_SOC_DAIFMT_NB_NF | | ||
53 | SND_SOC_DAIFMT_CBM_CFM); | ||
54 | if (ret < 0) { | ||
55 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* Set cpu DAI configuration */ | ||
60 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
61 | SND_SOC_DAIFMT_I2S | | ||
62 | SND_SOC_DAIFMT_NB_NF | | ||
63 | SND_SOC_DAIFMT_CBM_CFM); | ||
64 | if (ret < 0) { | ||
65 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | /* Set the codec system clock for DAC and ADC */ | ||
70 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
71 | SND_SOC_CLOCK_IN); | ||
72 | if (ret < 0) { | ||
73 | printk(KERN_ERR "can't set codec system clock\n"); | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static struct snd_soc_ops omap2evm_ops = { | ||
81 | .hw_params = omap2evm_hw_params, | ||
82 | }; | ||
83 | |||
84 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
85 | static struct snd_soc_dai_link omap2evm_dai = { | ||
86 | .name = "TWL4030", | ||
87 | .stream_name = "TWL4030", | ||
88 | .cpu_dai = &omap_mcbsp_dai[0], | ||
89 | .codec_dai = &twl4030_dai, | ||
90 | .ops = &omap2evm_ops, | ||
91 | }; | ||
92 | |||
93 | /* Audio machine driver */ | ||
94 | static struct snd_soc_card snd_soc_omap2evm = { | ||
95 | .name = "omap2evm", | ||
96 | .platform = &omap_soc_platform, | ||
97 | .dai_link = &omap2evm_dai, | ||
98 | .num_links = 1, | ||
99 | }; | ||
100 | |||
101 | /* Audio subsystem */ | ||
102 | static struct snd_soc_device omap2evm_snd_devdata = { | ||
103 | .card = &snd_soc_omap2evm, | ||
104 | .codec_dev = &soc_codec_dev_twl4030, | ||
105 | }; | ||
106 | |||
107 | static struct platform_device *omap2evm_snd_device; | ||
108 | |||
109 | static int __init omap2evm_soc_init(void) | ||
110 | { | ||
111 | int ret; | ||
112 | |||
113 | if (!machine_is_omap2evm()) { | ||
114 | pr_debug("Not omap2evm!\n"); | ||
115 | return -ENODEV; | ||
116 | } | ||
117 | printk(KERN_INFO "omap2evm SoC init\n"); | ||
118 | |||
119 | omap2evm_snd_device = platform_device_alloc("soc-audio", -1); | ||
120 | if (!omap2evm_snd_device) { | ||
121 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata); | ||
126 | omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev; | ||
127 | *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
128 | |||
129 | ret = platform_device_add(omap2evm_snd_device); | ||
130 | if (ret) | ||
131 | goto err1; | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | err1: | ||
136 | printk(KERN_ERR "Unable to add platform device\n"); | ||
137 | platform_device_put(omap2evm_snd_device); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | module_init(omap2evm_soc_init); | ||
142 | |||
143 | static void __exit omap2evm_soc_exit(void) | ||
144 | { | ||
145 | platform_device_unregister(omap2evm_snd_device); | ||
146 | } | ||
147 | module_exit(omap2evm_soc_exit); | ||
148 | |||
149 | MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); | ||
150 | MODULE_DESCRIPTION("ALSA SoC omap2evm"); | ||
151 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c new file mode 100644 index 000000000000..fd24a4acd2f5 --- /dev/null +++ b/sound/soc/omap/omap3beagle.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * omap3beagle.c -- SoC audio for OMAP3 Beagle | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/gpio.h> | ||
32 | #include <mach/mcbsp.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | #include "../codecs/twl4030.h" | ||
37 | |||
38 | static int omap3beagle_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
44 | int ret; | ||
45 | |||
46 | /* Set codec DAI configuration */ | ||
47 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
48 | SND_SOC_DAIFMT_I2S | | ||
49 | SND_SOC_DAIFMT_NB_NF | | ||
50 | SND_SOC_DAIFMT_CBM_CFM); | ||
51 | if (ret < 0) { | ||
52 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | /* Set cpu DAI configuration */ | ||
57 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
58 | SND_SOC_DAIFMT_I2S | | ||
59 | SND_SOC_DAIFMT_NB_NF | | ||
60 | SND_SOC_DAIFMT_CBM_CFM); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | /* Set the codec system clock for DAC and ADC */ | ||
67 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
68 | SND_SOC_CLOCK_IN); | ||
69 | if (ret < 0) { | ||
70 | printk(KERN_ERR "can't set codec system clock\n"); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_ops omap3beagle_ops = { | ||
78 | .hw_params = omap3beagle_hw_params, | ||
79 | }; | ||
80 | |||
81 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
82 | static struct snd_soc_dai_link omap3beagle_dai = { | ||
83 | .name = "TWL4030", | ||
84 | .stream_name = "TWL4030", | ||
85 | .cpu_dai = &omap_mcbsp_dai[0], | ||
86 | .codec_dai = &twl4030_dai, | ||
87 | .ops = &omap3beagle_ops, | ||
88 | }; | ||
89 | |||
90 | /* Audio machine driver */ | ||
91 | static struct snd_soc_card snd_soc_omap3beagle = { | ||
92 | .name = "omap3beagle", | ||
93 | .platform = &omap_soc_platform, | ||
94 | .dai_link = &omap3beagle_dai, | ||
95 | .num_links = 1, | ||
96 | }; | ||
97 | |||
98 | /* Audio subsystem */ | ||
99 | static struct snd_soc_device omap3beagle_snd_devdata = { | ||
100 | .card = &snd_soc_omap3beagle, | ||
101 | .codec_dev = &soc_codec_dev_twl4030, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device *omap3beagle_snd_device; | ||
105 | |||
106 | static int __init omap3beagle_soc_init(void) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | if (!machine_is_omap3_beagle()) { | ||
111 | pr_debug("Not OMAP3 Beagle!\n"); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | pr_info("OMAP3 Beagle SoC init\n"); | ||
115 | |||
116 | omap3beagle_snd_device = platform_device_alloc("soc-audio", -1); | ||
117 | if (!omap3beagle_snd_device) { | ||
118 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
119 | return -ENOMEM; | ||
120 | } | ||
121 | |||
122 | platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata); | ||
123 | omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev; | ||
124 | *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
125 | |||
126 | ret = platform_device_add(omap3beagle_snd_device); | ||
127 | if (ret) | ||
128 | goto err1; | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err1: | ||
133 | printk(KERN_ERR "Unable to add platform device\n"); | ||
134 | platform_device_put(omap3beagle_snd_device); | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static void __exit omap3beagle_soc_exit(void) | ||
140 | { | ||
141 | platform_device_unregister(omap3beagle_snd_device); | ||
142 | } | ||
143 | |||
144 | module_init(omap3beagle_soc_init); | ||
145 | module_exit(omap3beagle_soc_exit); | ||
146 | |||
147 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
148 | MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle"); | ||
149 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c new file mode 100644 index 000000000000..bd91594496b1 --- /dev/null +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -0,0 +1,311 @@ | |||
1 | /* | ||
2 | * omap3pandora.c -- SoC audio for Pandora Handheld Console | ||
3 | * | ||
4 | * Author: Gražvydas Ignotas <notasas@gmail.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/delay.h> | ||
26 | |||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | |||
32 | #include <asm/mach-types.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | #include "../codecs/twl4030.h" | ||
37 | |||
38 | #define OMAP3_PANDORA_DAC_POWER_GPIO 118 | ||
39 | #define OMAP3_PANDORA_AMP_POWER_GPIO 14 | ||
40 | |||
41 | #define PREFIX "ASoC omap3pandora: " | ||
42 | |||
43 | static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, | ||
44 | struct snd_soc_dai *cpu_dai, unsigned int fmt) | ||
45 | { | ||
46 | int ret; | ||
47 | |||
48 | /* Set codec DAI configuration */ | ||
49 | ret = snd_soc_dai_set_fmt(codec_dai, fmt); | ||
50 | if (ret < 0) { | ||
51 | pr_err(PREFIX "can't set codec DAI configuration\n"); | ||
52 | return ret; | ||
53 | } | ||
54 | |||
55 | /* Set cpu DAI configuration */ | ||
56 | ret = snd_soc_dai_set_fmt(cpu_dai, fmt); | ||
57 | if (ret < 0) { | ||
58 | pr_err(PREFIX "can't set cpu DAI configuration\n"); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | /* Set the codec system clock for DAC and ADC */ | ||
63 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
64 | SND_SOC_CLOCK_IN); | ||
65 | if (ret < 0) { | ||
66 | pr_err(PREFIX "can't set codec system clock\n"); | ||
67 | return ret; | ||
68 | } | ||
69 | |||
70 | /* Set McBSP clock to external */ | ||
71 | ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0, | ||
72 | SND_SOC_CLOCK_IN); | ||
73 | if (ret < 0) { | ||
74 | pr_err(PREFIX "can't set cpu system clock\n"); | ||
75 | return ret; | ||
76 | } | ||
77 | |||
78 | ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8); | ||
79 | if (ret < 0) { | ||
80 | pr_err(PREFIX "can't set SRG clock divider\n"); | ||
81 | return ret; | ||
82 | } | ||
83 | |||
84 | return 0; | ||
85 | } | ||
86 | |||
87 | static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, | ||
88 | struct snd_pcm_hw_params *params) | ||
89 | { | ||
90 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
91 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
92 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
93 | |||
94 | return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, | ||
95 | SND_SOC_DAIFMT_I2S | | ||
96 | SND_SOC_DAIFMT_IB_NF | | ||
97 | SND_SOC_DAIFMT_CBS_CFS); | ||
98 | } | ||
99 | |||
100 | static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream, | ||
101 | struct snd_pcm_hw_params *params) | ||
102 | { | ||
103 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
104 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
105 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
106 | |||
107 | return omap3pandora_cmn_hw_params(codec_dai, cpu_dai, | ||
108 | SND_SOC_DAIFMT_I2S | | ||
109 | SND_SOC_DAIFMT_NB_NF | | ||
110 | SND_SOC_DAIFMT_CBS_CFS); | ||
111 | } | ||
112 | |||
113 | static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w, | ||
114 | struct snd_kcontrol *k, int event) | ||
115 | { | ||
116 | if (SND_SOC_DAPM_EVENT_ON(event)) { | ||
117 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1); | ||
118 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1); | ||
119 | } else { | ||
120 | gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0); | ||
121 | mdelay(1); | ||
122 | gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0); | ||
123 | } | ||
124 | |||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * Audio paths on Pandora board: | ||
130 | * | ||
131 | * |O| ---> PCM DAC +-> AMP -> Headphone Jack | ||
132 | * |M| A +--------> Line Out | ||
133 | * |A| <~~clk~~+ | ||
134 | * |P| <--- TWL4030 <--------- Line In and MICs | ||
135 | */ | ||
136 | static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { | ||
137 | SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0), | ||
138 | SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, | ||
139 | 0, 0, NULL, 0, omap3pandora_hp_event, | ||
140 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
141 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
142 | SND_SOC_DAPM_LINE("Line Out", NULL), | ||
143 | }; | ||
144 | |||
145 | static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = { | ||
146 | SND_SOC_DAPM_MIC("Mic (Internal)", NULL), | ||
147 | SND_SOC_DAPM_MIC("Mic (external)", NULL), | ||
148 | SND_SOC_DAPM_LINE("Line In", NULL), | ||
149 | }; | ||
150 | |||
151 | static const struct snd_soc_dapm_route omap3pandora_out_map[] = { | ||
152 | {"Headphone Amplifier", NULL, "PCM DAC"}, | ||
153 | {"Line Out", NULL, "PCM DAC"}, | ||
154 | {"Headphone Jack", NULL, "Headphone Amplifier"}, | ||
155 | }; | ||
156 | |||
157 | static const struct snd_soc_dapm_route omap3pandora_in_map[] = { | ||
158 | {"INL", NULL, "Line In"}, | ||
159 | {"INR", NULL, "Line In"}, | ||
160 | {"INL", NULL, "Mic (Internal)"}, | ||
161 | {"INR", NULL, "Mic (external)"}, | ||
162 | }; | ||
163 | |||
164 | static int omap3pandora_out_init(struct snd_soc_codec *codec) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, | ||
169 | ARRAY_SIZE(omap3pandora_out_dapm_widgets)); | ||
170 | if (ret < 0) | ||
171 | return ret; | ||
172 | |||
173 | snd_soc_dapm_add_routes(codec, omap3pandora_out_map, | ||
174 | ARRAY_SIZE(omap3pandora_out_map)); | ||
175 | |||
176 | return snd_soc_dapm_sync(codec); | ||
177 | } | ||
178 | |||
179 | static int omap3pandora_in_init(struct snd_soc_codec *codec) | ||
180 | { | ||
181 | int ret; | ||
182 | |||
183 | ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets, | ||
184 | ARRAY_SIZE(omap3pandora_in_dapm_widgets)); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | |||
188 | snd_soc_dapm_add_routes(codec, omap3pandora_in_map, | ||
189 | ARRAY_SIZE(omap3pandora_in_map)); | ||
190 | |||
191 | return snd_soc_dapm_sync(codec); | ||
192 | } | ||
193 | |||
194 | static struct snd_soc_ops omap3pandora_out_ops = { | ||
195 | .hw_params = omap3pandora_out_hw_params, | ||
196 | }; | ||
197 | |||
198 | static struct snd_soc_ops omap3pandora_in_ops = { | ||
199 | .hw_params = omap3pandora_in_hw_params, | ||
200 | }; | ||
201 | |||
202 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
203 | static struct snd_soc_dai_link omap3pandora_dai[] = { | ||
204 | { | ||
205 | .name = "PCM1773", | ||
206 | .stream_name = "HiFi Out", | ||
207 | .cpu_dai = &omap_mcbsp_dai[0], | ||
208 | .codec_dai = &twl4030_dai, | ||
209 | .ops = &omap3pandora_out_ops, | ||
210 | .init = omap3pandora_out_init, | ||
211 | }, { | ||
212 | .name = "TWL4030", | ||
213 | .stream_name = "Line/Mic In", | ||
214 | .cpu_dai = &omap_mcbsp_dai[1], | ||
215 | .codec_dai = &twl4030_dai, | ||
216 | .ops = &omap3pandora_in_ops, | ||
217 | .init = omap3pandora_in_init, | ||
218 | } | ||
219 | }; | ||
220 | |||
221 | /* SoC card */ | ||
222 | static struct snd_soc_card snd_soc_card_omap3pandora = { | ||
223 | .name = "omap3pandora", | ||
224 | .platform = &omap_soc_platform, | ||
225 | .dai_link = omap3pandora_dai, | ||
226 | .num_links = ARRAY_SIZE(omap3pandora_dai), | ||
227 | }; | ||
228 | |||
229 | /* Audio subsystem */ | ||
230 | static struct snd_soc_device omap3pandora_snd_data = { | ||
231 | .card = &snd_soc_card_omap3pandora, | ||
232 | .codec_dev = &soc_codec_dev_twl4030, | ||
233 | }; | ||
234 | |||
235 | static struct platform_device *omap3pandora_snd_device; | ||
236 | |||
237 | static int __init omap3pandora_soc_init(void) | ||
238 | { | ||
239 | int ret; | ||
240 | |||
241 | if (!machine_is_omap3_pandora()) { | ||
242 | pr_debug(PREFIX "Not OMAP3 Pandora\n"); | ||
243 | return -ENODEV; | ||
244 | } | ||
245 | pr_info("OMAP3 Pandora SoC init\n"); | ||
246 | |||
247 | ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power"); | ||
248 | if (ret) { | ||
249 | pr_err(PREFIX "Failed to get DAC power GPIO\n"); | ||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0); | ||
254 | if (ret) { | ||
255 | pr_err(PREFIX "Failed to set DAC power GPIO direction\n"); | ||
256 | goto fail0; | ||
257 | } | ||
258 | |||
259 | ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power"); | ||
260 | if (ret) { | ||
261 | pr_err(PREFIX "Failed to get amp power GPIO\n"); | ||
262 | goto fail0; | ||
263 | } | ||
264 | |||
265 | ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0); | ||
266 | if (ret) { | ||
267 | pr_err(PREFIX "Failed to set amp power GPIO direction\n"); | ||
268 | goto fail1; | ||
269 | } | ||
270 | |||
271 | omap3pandora_snd_device = platform_device_alloc("soc-audio", -1); | ||
272 | if (omap3pandora_snd_device == NULL) { | ||
273 | pr_err(PREFIX "Platform device allocation failed\n"); | ||
274 | ret = -ENOMEM; | ||
275 | goto fail1; | ||
276 | } | ||
277 | |||
278 | platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data); | ||
279 | omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev; | ||
280 | *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */ | ||
281 | *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */ | ||
282 | |||
283 | ret = platform_device_add(omap3pandora_snd_device); | ||
284 | if (ret) { | ||
285 | pr_err(PREFIX "Unable to add platform device\n"); | ||
286 | goto fail2; | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | |||
291 | fail2: | ||
292 | platform_device_put(omap3pandora_snd_device); | ||
293 | fail1: | ||
294 | gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); | ||
295 | fail0: | ||
296 | gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); | ||
297 | return ret; | ||
298 | } | ||
299 | module_init(omap3pandora_soc_init); | ||
300 | |||
301 | static void __exit omap3pandora_soc_exit(void) | ||
302 | { | ||
303 | platform_device_unregister(omap3pandora_snd_device); | ||
304 | gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO); | ||
305 | gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO); | ||
306 | } | ||
307 | module_exit(omap3pandora_soc_exit); | ||
308 | |||
309 | MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>"); | ||
310 | MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora"); | ||
311 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c index 0fe733796898..cd41a948df7b 100644 --- a/sound/soc/omap/osk5912.c +++ b/sound/soc/omap/osk5912.c | |||
@@ -61,7 +61,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream, | |||
61 | 61 | ||
62 | /* Set codec DAI configuration */ | 62 | /* Set codec DAI configuration */ |
63 | err = snd_soc_dai_set_fmt(codec_dai, | 63 | err = snd_soc_dai_set_fmt(codec_dai, |
64 | SND_SOC_DAIFMT_DSP_A | | 64 | SND_SOC_DAIFMT_DSP_B | |
65 | SND_SOC_DAIFMT_NB_IF | | 65 | SND_SOC_DAIFMT_NB_IF | |
66 | SND_SOC_DAIFMT_CBM_CFM); | 66 | SND_SOC_DAIFMT_CBM_CFM); |
67 | if (err < 0) { | 67 | if (err < 0) { |
@@ -71,7 +71,7 @@ static int osk_hw_params(struct snd_pcm_substream *substream, | |||
71 | 71 | ||
72 | /* Set cpu DAI configuration */ | 72 | /* Set cpu DAI configuration */ |
73 | err = snd_soc_dai_set_fmt(cpu_dai, | 73 | err = snd_soc_dai_set_fmt(cpu_dai, |
74 | SND_SOC_DAIFMT_DSP_A | | 74 | SND_SOC_DAIFMT_DSP_B | |
75 | SND_SOC_DAIFMT_NB_IF | | 75 | SND_SOC_DAIFMT_NB_IF | |
76 | SND_SOC_DAIFMT_CBM_CFM); | 76 | SND_SOC_DAIFMT_CBM_CFM); |
77 | if (err < 0) { | 77 | if (err < 0) { |
@@ -143,16 +143,16 @@ static struct snd_soc_dai_link osk_dai = { | |||
143 | }; | 143 | }; |
144 | 144 | ||
145 | /* Audio machine driver */ | 145 | /* Audio machine driver */ |
146 | static struct snd_soc_machine snd_soc_machine_osk = { | 146 | static struct snd_soc_card snd_soc_card_osk = { |
147 | .name = "OSK5912", | 147 | .name = "OSK5912", |
148 | .platform = &omap_soc_platform, | ||
148 | .dai_link = &osk_dai, | 149 | .dai_link = &osk_dai, |
149 | .num_links = 1, | 150 | .num_links = 1, |
150 | }; | 151 | }; |
151 | 152 | ||
152 | /* Audio subsystem */ | 153 | /* Audio subsystem */ |
153 | static struct snd_soc_device osk_snd_devdata = { | 154 | static struct snd_soc_device osk_snd_devdata = { |
154 | .machine = &snd_soc_machine_osk, | 155 | .card = &snd_soc_card_osk, |
155 | .platform = &omap_soc_platform, | ||
156 | .codec_dev = &soc_codec_dev_tlv320aic23, | 156 | .codec_dev = &soc_codec_dev_tlv320aic23, |
157 | }; | 157 | }; |
158 | 158 | ||
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c new file mode 100644 index 000000000000..a72dc4e159e5 --- /dev/null +++ b/sound/soc/omap/overo.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * overo.c -- SoC audio for Gumstix Overo | ||
3 | * | ||
4 | * Author: Steve Sakoman <steve@sakoman.com> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but | ||
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
18 | * 02110-1301 USA | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #include <linux/clk.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/soc-dapm.h> | ||
28 | |||
29 | #include <asm/mach-types.h> | ||
30 | #include <mach/hardware.h> | ||
31 | #include <mach/gpio.h> | ||
32 | #include <mach/mcbsp.h> | ||
33 | |||
34 | #include "omap-mcbsp.h" | ||
35 | #include "omap-pcm.h" | ||
36 | #include "../codecs/twl4030.h" | ||
37 | |||
38 | static int overo_hw_params(struct snd_pcm_substream *substream, | ||
39 | struct snd_pcm_hw_params *params) | ||
40 | { | ||
41 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
42 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
43 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
44 | int ret; | ||
45 | |||
46 | /* Set codec DAI configuration */ | ||
47 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
48 | SND_SOC_DAIFMT_I2S | | ||
49 | SND_SOC_DAIFMT_NB_NF | | ||
50 | SND_SOC_DAIFMT_CBM_CFM); | ||
51 | if (ret < 0) { | ||
52 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
53 | return ret; | ||
54 | } | ||
55 | |||
56 | /* Set cpu DAI configuration */ | ||
57 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
58 | SND_SOC_DAIFMT_I2S | | ||
59 | SND_SOC_DAIFMT_NB_NF | | ||
60 | SND_SOC_DAIFMT_CBM_CFM); | ||
61 | if (ret < 0) { | ||
62 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
63 | return ret; | ||
64 | } | ||
65 | |||
66 | /* Set the codec system clock for DAC and ADC */ | ||
67 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
68 | SND_SOC_CLOCK_IN); | ||
69 | if (ret < 0) { | ||
70 | printk(KERN_ERR "can't set codec system clock\n"); | ||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | return 0; | ||
75 | } | ||
76 | |||
77 | static struct snd_soc_ops overo_ops = { | ||
78 | .hw_params = overo_hw_params, | ||
79 | }; | ||
80 | |||
81 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
82 | static struct snd_soc_dai_link overo_dai = { | ||
83 | .name = "TWL4030", | ||
84 | .stream_name = "TWL4030", | ||
85 | .cpu_dai = &omap_mcbsp_dai[0], | ||
86 | .codec_dai = &twl4030_dai, | ||
87 | .ops = &overo_ops, | ||
88 | }; | ||
89 | |||
90 | /* Audio machine driver */ | ||
91 | static struct snd_soc_card snd_soc_card_overo = { | ||
92 | .name = "overo", | ||
93 | .platform = &omap_soc_platform, | ||
94 | .dai_link = &overo_dai, | ||
95 | .num_links = 1, | ||
96 | }; | ||
97 | |||
98 | /* Audio subsystem */ | ||
99 | static struct snd_soc_device overo_snd_devdata = { | ||
100 | .card = &snd_soc_card_overo, | ||
101 | .codec_dev = &soc_codec_dev_twl4030, | ||
102 | }; | ||
103 | |||
104 | static struct platform_device *overo_snd_device; | ||
105 | |||
106 | static int __init overo_soc_init(void) | ||
107 | { | ||
108 | int ret; | ||
109 | |||
110 | if (!machine_is_overo()) { | ||
111 | pr_debug("Not Overo!\n"); | ||
112 | return -ENODEV; | ||
113 | } | ||
114 | printk(KERN_INFO "overo SoC init\n"); | ||
115 | |||
116 | overo_snd_device = platform_device_alloc("soc-audio", -1); | ||
117 | if (!overo_snd_device) { | ||
118 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
119 | return -ENOMEM; | ||
120 | } | ||
121 | |||
122 | platform_set_drvdata(overo_snd_device, &overo_snd_devdata); | ||
123 | overo_snd_devdata.dev = &overo_snd_device->dev; | ||
124 | *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
125 | |||
126 | ret = platform_device_add(overo_snd_device); | ||
127 | if (ret) | ||
128 | goto err1; | ||
129 | |||
130 | return 0; | ||
131 | |||
132 | err1: | ||
133 | printk(KERN_ERR "Unable to add platform device\n"); | ||
134 | platform_device_put(overo_snd_device); | ||
135 | |||
136 | return ret; | ||
137 | } | ||
138 | module_init(overo_soc_init); | ||
139 | |||
140 | static void __exit overo_soc_exit(void) | ||
141 | { | ||
142 | platform_device_unregister(overo_snd_device); | ||
143 | } | ||
144 | module_exit(overo_soc_exit); | ||
145 | |||
146 | MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>"); | ||
147 | MODULE_DESCRIPTION("ALSA SoC overo"); | ||
148 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c new file mode 100644 index 000000000000..ad97836818b1 --- /dev/null +++ b/sound/soc/omap/sdp3430.c | |||
@@ -0,0 +1,152 @@ | |||
1 | /* | ||
2 | * sdp3430.c -- SoC audio for TI OMAP3430 SDP | ||
3 | * | ||
4 | * Author: Misael Lopez Cruz <x0052729@ti.com> | ||
5 | * | ||
6 | * Based on: | ||
7 | * Author: Steve Sakoman <steve@sakoman.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * version 2 as published by the Free Software Foundation. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
21 | * 02110-1301 USA | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include <linux/clk.h> | ||
26 | #include <linux/platform_device.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/soc.h> | ||
30 | #include <sound/soc-dapm.h> | ||
31 | |||
32 | #include <asm/mach-types.h> | ||
33 | #include <mach/hardware.h> | ||
34 | #include <mach/gpio.h> | ||
35 | #include <mach/mcbsp.h> | ||
36 | |||
37 | #include "omap-mcbsp.h" | ||
38 | #include "omap-pcm.h" | ||
39 | #include "../codecs/twl4030.h" | ||
40 | |||
41 | static int sdp3430_hw_params(struct snd_pcm_substream *substream, | ||
42 | struct snd_pcm_hw_params *params) | ||
43 | { | ||
44 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
45 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
46 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
47 | int ret; | ||
48 | |||
49 | /* Set codec DAI configuration */ | ||
50 | ret = snd_soc_dai_set_fmt(codec_dai, | ||
51 | SND_SOC_DAIFMT_I2S | | ||
52 | SND_SOC_DAIFMT_NB_NF | | ||
53 | SND_SOC_DAIFMT_CBM_CFM); | ||
54 | if (ret < 0) { | ||
55 | printk(KERN_ERR "can't set codec DAI configuration\n"); | ||
56 | return ret; | ||
57 | } | ||
58 | |||
59 | /* Set cpu DAI configuration */ | ||
60 | ret = snd_soc_dai_set_fmt(cpu_dai, | ||
61 | SND_SOC_DAIFMT_I2S | | ||
62 | SND_SOC_DAIFMT_NB_NF | | ||
63 | SND_SOC_DAIFMT_CBM_CFM); | ||
64 | if (ret < 0) { | ||
65 | printk(KERN_ERR "can't set cpu DAI configuration\n"); | ||
66 | return ret; | ||
67 | } | ||
68 | |||
69 | /* Set the codec system clock for DAC and ADC */ | ||
70 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000, | ||
71 | SND_SOC_CLOCK_IN); | ||
72 | if (ret < 0) { | ||
73 | printk(KERN_ERR "can't set codec system clock\n"); | ||
74 | return ret; | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static struct snd_soc_ops sdp3430_ops = { | ||
81 | .hw_params = sdp3430_hw_params, | ||
82 | }; | ||
83 | |||
84 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
85 | static struct snd_soc_dai_link sdp3430_dai = { | ||
86 | .name = "TWL4030", | ||
87 | .stream_name = "TWL4030", | ||
88 | .cpu_dai = &omap_mcbsp_dai[0], | ||
89 | .codec_dai = &twl4030_dai, | ||
90 | .ops = &sdp3430_ops, | ||
91 | }; | ||
92 | |||
93 | /* Audio machine driver */ | ||
94 | static struct snd_soc_machine snd_soc_machine_sdp3430 = { | ||
95 | .name = "SDP3430", | ||
96 | .platform = &omap_soc_platform, | ||
97 | .dai_link = &sdp3430_dai, | ||
98 | .num_links = 1, | ||
99 | }; | ||
100 | |||
101 | /* Audio subsystem */ | ||
102 | static struct snd_soc_device sdp3430_snd_devdata = { | ||
103 | .machine = &snd_soc_machine_sdp3430, | ||
104 | .codec_dev = &soc_codec_dev_twl4030, | ||
105 | }; | ||
106 | |||
107 | static struct platform_device *sdp3430_snd_device; | ||
108 | |||
109 | static int __init sdp3430_soc_init(void) | ||
110 | { | ||
111 | int ret; | ||
112 | |||
113 | if (!machine_is_omap_3430sdp()) { | ||
114 | pr_debug("Not SDP3430!\n"); | ||
115 | return -ENODEV; | ||
116 | } | ||
117 | printk(KERN_INFO "SDP3430 SoC init\n"); | ||
118 | |||
119 | sdp3430_snd_device = platform_device_alloc("soc-audio", -1); | ||
120 | if (!sdp3430_snd_device) { | ||
121 | printk(KERN_ERR "Platform device allocation failed\n"); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata); | ||
126 | sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev; | ||
127 | *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */ | ||
128 | |||
129 | ret = platform_device_add(sdp3430_snd_device); | ||
130 | if (ret) | ||
131 | goto err1; | ||
132 | |||
133 | return 0; | ||
134 | |||
135 | err1: | ||
136 | printk(KERN_ERR "Unable to add platform device\n"); | ||
137 | platform_device_put(sdp3430_snd_device); | ||
138 | |||
139 | return ret; | ||
140 | } | ||
141 | module_init(sdp3430_soc_init); | ||
142 | |||
143 | static void __exit sdp3430_soc_exit(void) | ||
144 | { | ||
145 | platform_device_unregister(sdp3430_snd_device); | ||
146 | } | ||
147 | module_exit(sdp3430_soc_exit); | ||
148 | |||
149 | MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>"); | ||
150 | MODULE_DESCRIPTION("ALSA SoC SDP3430"); | ||
151 | MODULE_LICENSE("GPL"); | ||
152 | |||
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig index f8c1cdd940ac..f82e10699471 100644 --- a/sound/soc/pxa/Kconfig +++ b/sound/soc/pxa/Kconfig | |||
@@ -21,6 +21,9 @@ config SND_PXA2XX_SOC_AC97 | |||
21 | config SND_PXA2XX_SOC_I2S | 21 | config SND_PXA2XX_SOC_I2S |
22 | tristate | 22 | tristate |
23 | 23 | ||
24 | config SND_PXA_SOC_SSP | ||
25 | tristate | ||
26 | |||
24 | config SND_PXA2XX_SOC_CORGI | 27 | config SND_PXA2XX_SOC_CORGI |
25 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" | 28 | tristate "SoC Audio support for Sharp Zaurus SL-C7x0" |
26 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx | 29 | depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx |
@@ -75,3 +78,22 @@ config SND_PXA2XX_SOC_EM_X270 | |||
75 | help | 78 | help |
76 | Say Y if you want to add support for SoC audio on | 79 | Say Y if you want to add support for SoC audio on |
77 | CompuLab EM-x270. | 80 | CompuLab EM-x270. |
81 | |||
82 | config SND_PXA2XX_SOC_PALM27X | ||
83 | bool "SoC Audio support for Palm T|X, T5 and LifeDrive" | ||
84 | depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5) | ||
85 | select SND_PXA2XX_SOC_AC97 | ||
86 | select SND_SOC_WM9712 | ||
87 | help | ||
88 | Say Y if you want to add support for SoC audio on | ||
89 | Palm T|X, T5 or LifeDrive handheld computer. | ||
90 | |||
91 | config SND_SOC_ZYLONITE | ||
92 | tristate "SoC Audio support for Marvell Zylonite" | ||
93 | depends on SND_PXA2XX_SOC && MACH_ZYLONITE | ||
94 | select SND_PXA2XX_SOC_AC97 | ||
95 | select SND_PXA_SOC_SSP | ||
96 | select SND_SOC_WM9713 | ||
97 | help | ||
98 | Say Y if you want to add support for SoC audio on the | ||
99 | Marvell Zylonite reference platform. | ||
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile index 5bc8edf9dca9..08a9f2797729 100644 --- a/sound/soc/pxa/Makefile +++ b/sound/soc/pxa/Makefile | |||
@@ -2,10 +2,12 @@ | |||
2 | snd-soc-pxa2xx-objs := pxa2xx-pcm.o | 2 | snd-soc-pxa2xx-objs := pxa2xx-pcm.o |
3 | snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o | 3 | snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o |
4 | snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o | 4 | snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o |
5 | snd-soc-pxa-ssp-objs := pxa-ssp.o | ||
5 | 6 | ||
6 | obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o | 7 | obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o |
7 | obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o | 8 | obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o |
8 | obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o | 9 | obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o |
10 | obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o | ||
9 | 11 | ||
10 | # PXA Machine Support | 12 | # PXA Machine Support |
11 | snd-soc-corgi-objs := corgi.o | 13 | snd-soc-corgi-objs := corgi.o |
@@ -14,6 +16,8 @@ snd-soc-tosa-objs := tosa.o | |||
14 | snd-soc-e800-objs := e800_wm9712.o | 16 | snd-soc-e800-objs := e800_wm9712.o |
15 | snd-soc-spitz-objs := spitz.o | 17 | snd-soc-spitz-objs := spitz.o |
16 | snd-soc-em-x270-objs := em-x270.o | 18 | snd-soc-em-x270-objs := em-x270.o |
19 | snd-soc-palm27x-objs := palm27x.o | ||
20 | snd-soc-zylonite-objs := zylonite.o | ||
17 | 21 | ||
18 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o | 22 | obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o |
19 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o | 23 | obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o |
@@ -21,3 +25,5 @@ obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o | |||
21 | obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o | 25 | obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o |
22 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o | 26 | obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o |
23 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o | 27 | obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o |
28 | obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o | ||
29 | obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o | ||
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c index 2718eaf7895f..1ba25a559524 100644 --- a/sound/soc/pxa/corgi.c +++ b/sound/soc/pxa/corgi.c | |||
@@ -108,15 +108,11 @@ static int corgi_startup(struct snd_pcm_substream *substream) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | /* we need to unmute the HP at shutdown as the mute burns power on corgi */ | 110 | /* we need to unmute the HP at shutdown as the mute burns power on corgi */ |
111 | static int corgi_shutdown(struct snd_pcm_substream *substream) | 111 | static void corgi_shutdown(struct snd_pcm_substream *substream) |
112 | { | 112 | { |
113 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
114 | struct snd_soc_codec *codec = rtd->socdev->codec; | ||
115 | |||
116 | /* set = unmute headphone */ | 113 | /* set = unmute headphone */ |
117 | gpio_set_value(CORGI_GPIO_MUTE_L, 1); | 114 | gpio_set_value(CORGI_GPIO_MUTE_L, 1); |
118 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); | 115 | gpio_set_value(CORGI_GPIO_MUTE_R, 1); |
119 | return 0; | ||
120 | } | 116 | } |
121 | 117 | ||
122 | static int corgi_hw_params(struct snd_pcm_substream *substream, | 118 | static int corgi_hw_params(struct snd_pcm_substream *substream, |
@@ -314,8 +310,9 @@ static struct snd_soc_dai_link corgi_dai = { | |||
314 | }; | 310 | }; |
315 | 311 | ||
316 | /* corgi audio machine driver */ | 312 | /* corgi audio machine driver */ |
317 | static struct snd_soc_machine snd_soc_machine_corgi = { | 313 | static struct snd_soc_card snd_soc_corgi = { |
318 | .name = "Corgi", | 314 | .name = "Corgi", |
315 | .platform = &pxa2xx_soc_platform, | ||
319 | .dai_link = &corgi_dai, | 316 | .dai_link = &corgi_dai, |
320 | .num_links = 1, | 317 | .num_links = 1, |
321 | }; | 318 | }; |
@@ -328,8 +325,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = { | |||
328 | 325 | ||
329 | /* corgi audio subsystem */ | 326 | /* corgi audio subsystem */ |
330 | static struct snd_soc_device corgi_snd_devdata = { | 327 | static struct snd_soc_device corgi_snd_devdata = { |
331 | .machine = &snd_soc_machine_corgi, | 328 | .card = &snd_soc_corgi, |
332 | .platform = &pxa2xx_soc_platform, | ||
333 | .codec_dev = &soc_codec_dev_wm8731, | 329 | .codec_dev = &soc_codec_dev_wm8731, |
334 | .codec_data = &corgi_wm8731_setup, | 330 | .codec_data = &corgi_wm8731_setup, |
335 | }; | 331 | }; |
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c index 6781c5be242f..2e3386dfa0f0 100644 --- a/sound/soc/pxa/e800_wm9712.c +++ b/sound/soc/pxa/e800_wm9712.c | |||
@@ -29,7 +29,7 @@ | |||
29 | #include "pxa2xx-pcm.h" | 29 | #include "pxa2xx-pcm.h" |
30 | #include "pxa2xx-ac97.h" | 30 | #include "pxa2xx-ac97.h" |
31 | 31 | ||
32 | static struct snd_soc_machine e800; | 32 | static struct snd_soc_card e800; |
33 | 33 | ||
34 | static struct snd_soc_dai_link e800_dai[] = { | 34 | static struct snd_soc_dai_link e800_dai[] = { |
35 | { | 35 | { |
@@ -40,15 +40,15 @@ static struct snd_soc_dai_link e800_dai[] = { | |||
40 | }, | 40 | }, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static struct snd_soc_machine e800 = { | 43 | static struct snd_soc_card e800 = { |
44 | .name = "Toshiba e800", | 44 | .name = "Toshiba e800", |
45 | .platform = &pxa2xx_soc_platform, | ||
45 | .dai_link = e800_dai, | 46 | .dai_link = e800_dai, |
46 | .num_links = ARRAY_SIZE(e800_dai), | 47 | .num_links = ARRAY_SIZE(e800_dai), |
47 | }; | 48 | }; |
48 | 49 | ||
49 | static struct snd_soc_device e800_snd_devdata = { | 50 | static struct snd_soc_device e800_snd_devdata = { |
50 | .machine = &e800, | 51 | .card = &e800, |
51 | .platform = &pxa2xx_soc_platform, | ||
52 | .codec_dev = &soc_codec_dev_wm9712, | 52 | .codec_dev = &soc_codec_dev_wm9712, |
53 | }; | 53 | }; |
54 | 54 | ||
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c index e6ff6929ab4b..fe4a729ea648 100644 --- a/sound/soc/pxa/em-x270.c +++ b/sound/soc/pxa/em-x270.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/moduleparam.h> | 23 | #include <linux/moduleparam.h> |
24 | #include <linux/device.h> | 24 | #include <linux/device.h> |
25 | 25 | ||
26 | #include <sound/driver.h> | ||
27 | #include <sound/core.h> | 26 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
29 | #include <sound/soc.h> | 28 | #include <sound/soc.h> |
@@ -53,15 +52,15 @@ static struct snd_soc_dai_link em_x270_dai[] = { | |||
53 | }, | 52 | }, |
54 | }; | 53 | }; |
55 | 54 | ||
56 | static struct snd_soc_machine em_x270 = { | 55 | static struct snd_soc_card em_x270 = { |
57 | .name = "EM-X270", | 56 | .name = "EM-X270", |
57 | .platform = &pxa2xx_soc_platform, | ||
58 | .dai_link = em_x270_dai, | 58 | .dai_link = em_x270_dai, |
59 | .num_links = ARRAY_SIZE(em_x270_dai), | 59 | .num_links = ARRAY_SIZE(em_x270_dai), |
60 | }; | 60 | }; |
61 | 61 | ||
62 | static struct snd_soc_device em_x270_snd_devdata = { | 62 | static struct snd_soc_device em_x270_snd_devdata = { |
63 | .machine = &em_x270, | 63 | .card = &em_x270, |
64 | .platform = &pxa2xx_soc_platform, | ||
65 | .codec_dev = &soc_codec_dev_wm9712, | 64 | .codec_dev = &soc_codec_dev_wm9712, |
66 | }; | 65 | }; |
67 | 66 | ||
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c new file mode 100644 index 000000000000..4a9cf3083af0 --- /dev/null +++ b/sound/soc/pxa/palm27x.c | |||
@@ -0,0 +1,269 @@ | |||
1 | /* | ||
2 | * linux/sound/soc/pxa/palm27x.c | ||
3 | * | ||
4 | * SoC Audio driver for Palm T|X, T5 and LifeDrive | ||
5 | * | ||
6 | * based on tosa.c | ||
7 | * | ||
8 | * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/module.h> | ||
17 | #include <linux/moduleparam.h> | ||
18 | #include <linux/device.h> | ||
19 | #include <linux/gpio.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
22 | |||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/soc-dapm.h> | ||
27 | |||
28 | #include <asm/mach-types.h> | ||
29 | #include <mach/audio.h> | ||
30 | #include <mach/palmasoc.h> | ||
31 | |||
32 | #include "../codecs/wm9712.h" | ||
33 | #include "pxa2xx-pcm.h" | ||
34 | #include "pxa2xx-ac97.h" | ||
35 | |||
36 | static int palm27x_jack_func = 1; | ||
37 | static int palm27x_spk_func = 1; | ||
38 | static int palm27x_ep_gpio = -1; | ||
39 | |||
40 | static void palm27x_ext_control(struct snd_soc_codec *codec) | ||
41 | { | ||
42 | if (!palm27x_spk_func) | ||
43 | snd_soc_dapm_enable_pin(codec, "Speaker"); | ||
44 | else | ||
45 | snd_soc_dapm_disable_pin(codec, "Speaker"); | ||
46 | |||
47 | if (!palm27x_jack_func) | ||
48 | snd_soc_dapm_enable_pin(codec, "Headphone Jack"); | ||
49 | else | ||
50 | snd_soc_dapm_disable_pin(codec, "Headphone Jack"); | ||
51 | |||
52 | snd_soc_dapm_sync(codec); | ||
53 | } | ||
54 | |||
55 | static int palm27x_startup(struct snd_pcm_substream *substream) | ||
56 | { | ||
57 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
58 | struct snd_soc_codec *codec = rtd->socdev->codec; | ||
59 | |||
60 | /* check the jack status at stream startup */ | ||
61 | palm27x_ext_control(codec); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static struct snd_soc_ops palm27x_ops = { | ||
66 | .startup = palm27x_startup, | ||
67 | }; | ||
68 | |||
69 | static irqreturn_t palm27x_interrupt(int irq, void *v) | ||
70 | { | ||
71 | palm27x_spk_func = gpio_get_value(palm27x_ep_gpio); | ||
72 | palm27x_jack_func = !palm27x_spk_func; | ||
73 | return IRQ_HANDLED; | ||
74 | } | ||
75 | |||
76 | static int palm27x_get_jack(struct snd_kcontrol *kcontrol, | ||
77 | struct snd_ctl_elem_value *ucontrol) | ||
78 | { | ||
79 | ucontrol->value.integer.value[0] = palm27x_jack_func; | ||
80 | return 0; | ||
81 | } | ||
82 | |||
83 | static int palm27x_set_jack(struct snd_kcontrol *kcontrol, | ||
84 | struct snd_ctl_elem_value *ucontrol) | ||
85 | { | ||
86 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
87 | |||
88 | if (palm27x_jack_func == ucontrol->value.integer.value[0]) | ||
89 | return 0; | ||
90 | |||
91 | palm27x_jack_func = ucontrol->value.integer.value[0]; | ||
92 | palm27x_ext_control(codec); | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | static int palm27x_get_spk(struct snd_kcontrol *kcontrol, | ||
97 | struct snd_ctl_elem_value *ucontrol) | ||
98 | { | ||
99 | ucontrol->value.integer.value[0] = palm27x_spk_func; | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int palm27x_set_spk(struct snd_kcontrol *kcontrol, | ||
104 | struct snd_ctl_elem_value *ucontrol) | ||
105 | { | ||
106 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
107 | |||
108 | if (palm27x_spk_func == ucontrol->value.integer.value[0]) | ||
109 | return 0; | ||
110 | |||
111 | palm27x_spk_func = ucontrol->value.integer.value[0]; | ||
112 | palm27x_ext_control(codec); | ||
113 | return 1; | ||
114 | } | ||
115 | |||
116 | /* PalmTX machine dapm widgets */ | ||
117 | static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = { | ||
118 | SND_SOC_DAPM_HP("Headphone Jack", NULL), | ||
119 | SND_SOC_DAPM_SPK("Speaker", NULL), | ||
120 | }; | ||
121 | |||
122 | /* PalmTX audio map */ | ||
123 | static const struct snd_soc_dapm_route audio_map[] = { | ||
124 | /* headphone connected to HPOUTL, HPOUTR */ | ||
125 | {"Headphone Jack", NULL, "HPOUTL"}, | ||
126 | {"Headphone Jack", NULL, "HPOUTR"}, | ||
127 | |||
128 | /* ext speaker connected to ROUT2, LOUT2 */ | ||
129 | {"Speaker", NULL, "LOUT2"}, | ||
130 | {"Speaker", NULL, "ROUT2"}, | ||
131 | }; | ||
132 | |||
133 | static const char *jack_function[] = {"Headphone", "Off"}; | ||
134 | static const char *spk_function[] = {"On", "Off"}; | ||
135 | static const struct soc_enum palm27x_enum[] = { | ||
136 | SOC_ENUM_SINGLE_EXT(2, jack_function), | ||
137 | SOC_ENUM_SINGLE_EXT(2, spk_function), | ||
138 | }; | ||
139 | |||
140 | static const struct snd_kcontrol_new palm27x_controls[] = { | ||
141 | SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack, | ||
142 | palm27x_set_jack), | ||
143 | SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk, | ||
144 | palm27x_set_spk), | ||
145 | }; | ||
146 | |||
147 | static int palm27x_ac97_init(struct snd_soc_codec *codec) | ||
148 | { | ||
149 | int i, err; | ||
150 | |||
151 | snd_soc_dapm_nc_pin(codec, "OUT3"); | ||
152 | snd_soc_dapm_nc_pin(codec, "MONOOUT"); | ||
153 | |||
154 | /* add palm27x specific controls */ | ||
155 | for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) { | ||
156 | err = snd_ctl_add(codec->card, | ||
157 | snd_soc_cnew(&palm27x_controls[i], | ||
158 | codec, NULL)); | ||
159 | if (err < 0) | ||
160 | return err; | ||
161 | } | ||
162 | |||
163 | /* add palm27x specific widgets */ | ||
164 | snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets, | ||
165 | ARRAY_SIZE(palm27x_dapm_widgets)); | ||
166 | |||
167 | /* set up palm27x specific audio path audio_map */ | ||
168 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
169 | |||
170 | snd_soc_dapm_sync(codec); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static struct snd_soc_dai_link palm27x_dai[] = { | ||
175 | { | ||
176 | .name = "AC97 HiFi", | ||
177 | .stream_name = "AC97 HiFi", | ||
178 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
179 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI], | ||
180 | .init = palm27x_ac97_init, | ||
181 | .ops = &palm27x_ops, | ||
182 | }, | ||
183 | { | ||
184 | .name = "AC97 Aux", | ||
185 | .stream_name = "AC97 Aux", | ||
186 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
187 | .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX], | ||
188 | .ops = &palm27x_ops, | ||
189 | }, | ||
190 | }; | ||
191 | |||
192 | static struct snd_soc_card palm27x_asoc = { | ||
193 | .name = "Palm/PXA27x", | ||
194 | .platform = &pxa2xx_soc_platform, | ||
195 | .dai_link = palm27x_dai, | ||
196 | .num_links = ARRAY_SIZE(palm27x_dai), | ||
197 | }; | ||
198 | |||
199 | static struct snd_soc_device palm27x_snd_devdata = { | ||
200 | .card = &palm27x_asoc, | ||
201 | .codec_dev = &soc_codec_dev_wm9712, | ||
202 | }; | ||
203 | |||
204 | static struct platform_device *palm27x_snd_device; | ||
205 | |||
206 | static int __init palm27x_asoc_init(void) | ||
207 | { | ||
208 | int ret; | ||
209 | |||
210 | if (!(machine_is_palmtx() || machine_is_palmt5() || | ||
211 | machine_is_palmld())) | ||
212 | return -ENODEV; | ||
213 | |||
214 | ret = gpio_request(palm27x_ep_gpio, "Headphone Jack"); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | ret = gpio_direction_input(palm27x_ep_gpio); | ||
218 | if (ret) | ||
219 | goto err_alloc; | ||
220 | |||
221 | if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt, | ||
222 | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
223 | "Headphone jack", NULL)) | ||
224 | goto err_alloc; | ||
225 | |||
226 | palm27x_snd_device = platform_device_alloc("soc-audio", -1); | ||
227 | if (!palm27x_snd_device) { | ||
228 | ret = -ENOMEM; | ||
229 | goto err_dev; | ||
230 | } | ||
231 | |||
232 | platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata); | ||
233 | palm27x_snd_devdata.dev = &palm27x_snd_device->dev; | ||
234 | ret = platform_device_add(palm27x_snd_device); | ||
235 | |||
236 | if (ret != 0) | ||
237 | goto put_device; | ||
238 | |||
239 | return 0; | ||
240 | |||
241 | put_device: | ||
242 | platform_device_put(palm27x_snd_device); | ||
243 | err_dev: | ||
244 | free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); | ||
245 | err_alloc: | ||
246 | gpio_free(palm27x_ep_gpio); | ||
247 | |||
248 | return ret; | ||
249 | } | ||
250 | |||
251 | static void __exit palm27x_asoc_exit(void) | ||
252 | { | ||
253 | free_irq(gpio_to_irq(palm27x_ep_gpio), NULL); | ||
254 | gpio_free(palm27x_ep_gpio); | ||
255 | platform_device_unregister(palm27x_snd_device); | ||
256 | } | ||
257 | |||
258 | void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) | ||
259 | { | ||
260 | palm27x_ep_gpio = data->jack_gpio; | ||
261 | } | ||
262 | |||
263 | module_init(palm27x_asoc_init); | ||
264 | module_exit(palm27x_asoc_exit); | ||
265 | |||
266 | /* Module information */ | ||
267 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
268 | MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive"); | ||
269 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c index 4d9930c52789..6e9827189fff 100644 --- a/sound/soc/pxa/poodle.c +++ b/sound/soc/pxa/poodle.c | |||
@@ -276,8 +276,9 @@ static struct snd_soc_dai_link poodle_dai = { | |||
276 | }; | 276 | }; |
277 | 277 | ||
278 | /* poodle audio machine driver */ | 278 | /* poodle audio machine driver */ |
279 | static struct snd_soc_machine snd_soc_machine_poodle = { | 279 | static struct snd_soc_card snd_soc_poodle = { |
280 | .name = "Poodle", | 280 | .name = "Poodle", |
281 | .platform = &pxa2xx_soc_platform, | ||
281 | .dai_link = &poodle_dai, | 282 | .dai_link = &poodle_dai, |
282 | .num_links = 1, | 283 | .num_links = 1, |
283 | }; | 284 | }; |
@@ -290,8 +291,7 @@ static struct wm8731_setup_data poodle_wm8731_setup = { | |||
290 | 291 | ||
291 | /* poodle audio subsystem */ | 292 | /* poodle audio subsystem */ |
292 | static struct snd_soc_device poodle_snd_devdata = { | 293 | static struct snd_soc_device poodle_snd_devdata = { |
293 | .machine = &snd_soc_machine_poodle, | 294 | .card = &snd_soc_poodle, |
294 | .platform = &pxa2xx_soc_platform, | ||
295 | .codec_dev = &soc_codec_dev_wm8731, | 295 | .codec_dev = &soc_codec_dev_wm8731, |
296 | .codec_data = &poodle_wm8731_setup, | 296 | .codec_data = &poodle_wm8731_setup, |
297 | }; | 297 | }; |
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c new file mode 100644 index 000000000000..73cb6b4c2f2d --- /dev/null +++ b/sound/soc/pxa/pxa-ssp.c | |||
@@ -0,0 +1,931 @@ | |||
1 | #define DEBUG | ||
2 | /* | ||
3 | * pxa-ssp.c -- ALSA Soc Audio Layer | ||
4 | * | ||
5 | * Copyright 2005,2008 Wolfson Microelectronics PLC. | ||
6 | * Author: Liam Girdwood | ||
7 | * Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the | ||
11 | * Free Software Foundation; either version 2 of the License, or (at your | ||
12 | * option) any later version. | ||
13 | * | ||
14 | * TODO: | ||
15 | * o Test network mode for > 16bit sample size | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/clk.h> | ||
22 | #include <linux/io.h> | ||
23 | |||
24 | #include <sound/core.h> | ||
25 | #include <sound/pcm.h> | ||
26 | #include <sound/initval.h> | ||
27 | #include <sound/pcm_params.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/pxa2xx-lib.h> | ||
30 | |||
31 | #include <mach/hardware.h> | ||
32 | #include <mach/pxa-regs.h> | ||
33 | #include <mach/regs-ssp.h> | ||
34 | #include <mach/audio.h> | ||
35 | #include <mach/ssp.h> | ||
36 | |||
37 | #include "pxa2xx-pcm.h" | ||
38 | #include "pxa-ssp.h" | ||
39 | |||
40 | /* | ||
41 | * SSP audio private data | ||
42 | */ | ||
43 | struct ssp_priv { | ||
44 | struct ssp_dev dev; | ||
45 | unsigned int sysclk; | ||
46 | int dai_fmt; | ||
47 | #ifdef CONFIG_PM | ||
48 | struct ssp_state state; | ||
49 | #endif | ||
50 | }; | ||
51 | |||
52 | #define PXA2xx_SSP1_BASE 0x41000000 | ||
53 | #define PXA27x_SSP2_BASE 0x41700000 | ||
54 | #define PXA27x_SSP3_BASE 0x41900000 | ||
55 | #define PXA3xx_SSP4_BASE 0x41a00000 | ||
56 | |||
57 | static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = { | ||
58 | .name = "SSP1 PCM Mono out", | ||
59 | .dev_addr = PXA2xx_SSP1_BASE + SSDR, | ||
60 | .drcmr = &DRCMR(14), | ||
61 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
62 | DCMD_BURST16 | DCMD_WIDTH2, | ||
63 | }; | ||
64 | |||
65 | static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = { | ||
66 | .name = "SSP1 PCM Mono in", | ||
67 | .dev_addr = PXA2xx_SSP1_BASE + SSDR, | ||
68 | .drcmr = &DRCMR(13), | ||
69 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
70 | DCMD_BURST16 | DCMD_WIDTH2, | ||
71 | }; | ||
72 | |||
73 | static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = { | ||
74 | .name = "SSP1 PCM Stereo out", | ||
75 | .dev_addr = PXA2xx_SSP1_BASE + SSDR, | ||
76 | .drcmr = &DRCMR(14), | ||
77 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
78 | DCMD_BURST16 | DCMD_WIDTH4, | ||
79 | }; | ||
80 | |||
81 | static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = { | ||
82 | .name = "SSP1 PCM Stereo in", | ||
83 | .dev_addr = PXA2xx_SSP1_BASE + SSDR, | ||
84 | .drcmr = &DRCMR(13), | ||
85 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
86 | DCMD_BURST16 | DCMD_WIDTH4, | ||
87 | }; | ||
88 | |||
89 | static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = { | ||
90 | .name = "SSP2 PCM Mono out", | ||
91 | .dev_addr = PXA27x_SSP2_BASE + SSDR, | ||
92 | .drcmr = &DRCMR(16), | ||
93 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
94 | DCMD_BURST16 | DCMD_WIDTH2, | ||
95 | }; | ||
96 | |||
97 | static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = { | ||
98 | .name = "SSP2 PCM Mono in", | ||
99 | .dev_addr = PXA27x_SSP2_BASE + SSDR, | ||
100 | .drcmr = &DRCMR(15), | ||
101 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
102 | DCMD_BURST16 | DCMD_WIDTH2, | ||
103 | }; | ||
104 | |||
105 | static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = { | ||
106 | .name = "SSP2 PCM Stereo out", | ||
107 | .dev_addr = PXA27x_SSP2_BASE + SSDR, | ||
108 | .drcmr = &DRCMR(16), | ||
109 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
110 | DCMD_BURST16 | DCMD_WIDTH4, | ||
111 | }; | ||
112 | |||
113 | static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = { | ||
114 | .name = "SSP2 PCM Stereo in", | ||
115 | .dev_addr = PXA27x_SSP2_BASE + SSDR, | ||
116 | .drcmr = &DRCMR(15), | ||
117 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
118 | DCMD_BURST16 | DCMD_WIDTH4, | ||
119 | }; | ||
120 | |||
121 | static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = { | ||
122 | .name = "SSP3 PCM Mono out", | ||
123 | .dev_addr = PXA27x_SSP3_BASE + SSDR, | ||
124 | .drcmr = &DRCMR(67), | ||
125 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
126 | DCMD_BURST16 | DCMD_WIDTH2, | ||
127 | }; | ||
128 | |||
129 | static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = { | ||
130 | .name = "SSP3 PCM Mono in", | ||
131 | .dev_addr = PXA27x_SSP3_BASE + SSDR, | ||
132 | .drcmr = &DRCMR(66), | ||
133 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
134 | DCMD_BURST16 | DCMD_WIDTH2, | ||
135 | }; | ||
136 | |||
137 | static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = { | ||
138 | .name = "SSP3 PCM Stereo out", | ||
139 | .dev_addr = PXA27x_SSP3_BASE + SSDR, | ||
140 | .drcmr = &DRCMR(67), | ||
141 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
142 | DCMD_BURST16 | DCMD_WIDTH4, | ||
143 | }; | ||
144 | |||
145 | static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = { | ||
146 | .name = "SSP3 PCM Stereo in", | ||
147 | .dev_addr = PXA27x_SSP3_BASE + SSDR, | ||
148 | .drcmr = &DRCMR(66), | ||
149 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
150 | DCMD_BURST16 | DCMD_WIDTH4, | ||
151 | }; | ||
152 | |||
153 | static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = { | ||
154 | .name = "SSP4 PCM Mono out", | ||
155 | .dev_addr = PXA3xx_SSP4_BASE + SSDR, | ||
156 | .drcmr = &DRCMR(67), | ||
157 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
158 | DCMD_BURST16 | DCMD_WIDTH2, | ||
159 | }; | ||
160 | |||
161 | static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = { | ||
162 | .name = "SSP4 PCM Mono in", | ||
163 | .dev_addr = PXA3xx_SSP4_BASE + SSDR, | ||
164 | .drcmr = &DRCMR(66), | ||
165 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
166 | DCMD_BURST16 | DCMD_WIDTH2, | ||
167 | }; | ||
168 | |||
169 | static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = { | ||
170 | .name = "SSP4 PCM Stereo out", | ||
171 | .dev_addr = PXA3xx_SSP4_BASE + SSDR, | ||
172 | .drcmr = &DRCMR(67), | ||
173 | .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | | ||
174 | DCMD_BURST16 | DCMD_WIDTH4, | ||
175 | }; | ||
176 | |||
177 | static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = { | ||
178 | .name = "SSP4 PCM Stereo in", | ||
179 | .dev_addr = PXA3xx_SSP4_BASE + SSDR, | ||
180 | .drcmr = &DRCMR(66), | ||
181 | .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | | ||
182 | DCMD_BURST16 | DCMD_WIDTH4, | ||
183 | }; | ||
184 | |||
185 | static void dump_registers(struct ssp_device *ssp) | ||
186 | { | ||
187 | dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n", | ||
188 | ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1), | ||
189 | ssp_read_reg(ssp, SSTO)); | ||
190 | |||
191 | dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n", | ||
192 | ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR), | ||
193 | ssp_read_reg(ssp, SSACD)); | ||
194 | } | ||
195 | |||
196 | static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = { | ||
197 | { | ||
198 | &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in, | ||
199 | &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in, | ||
200 | }, | ||
201 | { | ||
202 | &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in, | ||
203 | &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in, | ||
204 | }, | ||
205 | { | ||
206 | &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in, | ||
207 | &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in, | ||
208 | }, | ||
209 | { | ||
210 | &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in, | ||
211 | &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in, | ||
212 | }, | ||
213 | }; | ||
214 | |||
215 | static int pxa_ssp_startup(struct snd_pcm_substream *substream, | ||
216 | struct snd_soc_dai *dai) | ||
217 | { | ||
218 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
219 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
220 | struct ssp_priv *priv = cpu_dai->private_data; | ||
221 | int ret = 0; | ||
222 | |||
223 | if (!cpu_dai->active) { | ||
224 | ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ); | ||
225 | if (ret < 0) | ||
226 | return ret; | ||
227 | ssp_disable(&priv->dev); | ||
228 | } | ||
229 | return ret; | ||
230 | } | ||
231 | |||
232 | static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, | ||
233 | struct snd_soc_dai *dai) | ||
234 | { | ||
235 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
236 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
237 | struct ssp_priv *priv = cpu_dai->private_data; | ||
238 | |||
239 | if (!cpu_dai->active) { | ||
240 | ssp_disable(&priv->dev); | ||
241 | ssp_exit(&priv->dev); | ||
242 | } | ||
243 | } | ||
244 | |||
245 | #ifdef CONFIG_PM | ||
246 | |||
247 | static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) | ||
248 | { | ||
249 | struct ssp_priv *priv = cpu_dai->private_data; | ||
250 | |||
251 | if (!cpu_dai->active) | ||
252 | return 0; | ||
253 | |||
254 | ssp_save_state(&priv->dev, &priv->state); | ||
255 | clk_disable(priv->dev.ssp->clk); | ||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) | ||
260 | { | ||
261 | struct ssp_priv *priv = cpu_dai->private_data; | ||
262 | |||
263 | if (!cpu_dai->active) | ||
264 | return 0; | ||
265 | |||
266 | clk_enable(priv->dev.ssp->clk); | ||
267 | ssp_restore_state(&priv->dev, &priv->state); | ||
268 | ssp_enable(&priv->dev); | ||
269 | |||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | #else | ||
274 | #define pxa_ssp_suspend NULL | ||
275 | #define pxa_ssp_resume NULL | ||
276 | #endif | ||
277 | |||
278 | /** | ||
279 | * ssp_set_clkdiv - set SSP clock divider | ||
280 | * @div: serial clock rate divider | ||
281 | */ | ||
282 | static void ssp_set_scr(struct ssp_dev *dev, u32 div) | ||
283 | { | ||
284 | struct ssp_device *ssp = dev->ssp; | ||
285 | u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR; | ||
286 | |||
287 | ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div))); | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Set the SSP ports SYSCLK. | ||
292 | */ | ||
293 | static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | ||
294 | int clk_id, unsigned int freq, int dir) | ||
295 | { | ||
296 | struct ssp_priv *priv = cpu_dai->private_data; | ||
297 | struct ssp_device *ssp = priv->dev.ssp; | ||
298 | int val; | ||
299 | |||
300 | u32 sscr0 = ssp_read_reg(ssp, SSCR0) & | ||
301 | ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); | ||
302 | |||
303 | dev_dbg(&ssp->pdev->dev, | ||
304 | "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n", | ||
305 | cpu_dai->id, clk_id, freq); | ||
306 | |||
307 | switch (clk_id) { | ||
308 | case PXA_SSP_CLK_NET_PLL: | ||
309 | sscr0 |= SSCR0_MOD; | ||
310 | break; | ||
311 | case PXA_SSP_CLK_PLL: | ||
312 | /* Internal PLL is fixed */ | ||
313 | if (cpu_is_pxa25x()) | ||
314 | priv->sysclk = 1843200; | ||
315 | else | ||
316 | priv->sysclk = 13000000; | ||
317 | break; | ||
318 | case PXA_SSP_CLK_EXT: | ||
319 | priv->sysclk = freq; | ||
320 | sscr0 |= SSCR0_ECS; | ||
321 | break; | ||
322 | case PXA_SSP_CLK_NET: | ||
323 | priv->sysclk = freq; | ||
324 | sscr0 |= SSCR0_NCS | SSCR0_MOD; | ||
325 | break; | ||
326 | case PXA_SSP_CLK_AUDIO: | ||
327 | priv->sysclk = 0; | ||
328 | ssp_set_scr(&priv->dev, 1); | ||
329 | sscr0 |= SSCR0_ADC; | ||
330 | break; | ||
331 | default: | ||
332 | return -ENODEV; | ||
333 | } | ||
334 | |||
335 | /* The SSP clock must be disabled when changing SSP clock mode | ||
336 | * on PXA2xx. On PXA3xx it must be enabled when doing so. */ | ||
337 | if (!cpu_is_pxa3xx()) | ||
338 | clk_disable(priv->dev.ssp->clk); | ||
339 | val = ssp_read_reg(ssp, SSCR0) | sscr0; | ||
340 | ssp_write_reg(ssp, SSCR0, val); | ||
341 | if (!cpu_is_pxa3xx()) | ||
342 | clk_enable(priv->dev.ssp->clk); | ||
343 | |||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | /* | ||
348 | * Set the SSP clock dividers. | ||
349 | */ | ||
350 | static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, | ||
351 | int div_id, int div) | ||
352 | { | ||
353 | struct ssp_priv *priv = cpu_dai->private_data; | ||
354 | struct ssp_device *ssp = priv->dev.ssp; | ||
355 | int val; | ||
356 | |||
357 | switch (div_id) { | ||
358 | case PXA_SSP_AUDIO_DIV_ACDS: | ||
359 | val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div); | ||
360 | ssp_write_reg(ssp, SSACD, val); | ||
361 | break; | ||
362 | case PXA_SSP_AUDIO_DIV_SCDB: | ||
363 | val = ssp_read_reg(ssp, SSACD); | ||
364 | val &= ~SSACD_SCDB; | ||
365 | #if defined(CONFIG_PXA3xx) | ||
366 | if (cpu_is_pxa3xx()) | ||
367 | val &= ~SSACD_SCDX8; | ||
368 | #endif | ||
369 | switch (div) { | ||
370 | case PXA_SSP_CLK_SCDB_1: | ||
371 | val |= SSACD_SCDB; | ||
372 | break; | ||
373 | case PXA_SSP_CLK_SCDB_4: | ||
374 | break; | ||
375 | #if defined(CONFIG_PXA3xx) | ||
376 | case PXA_SSP_CLK_SCDB_8: | ||
377 | if (cpu_is_pxa3xx()) | ||
378 | val |= SSACD_SCDX8; | ||
379 | else | ||
380 | return -EINVAL; | ||
381 | break; | ||
382 | #endif | ||
383 | default: | ||
384 | return -EINVAL; | ||
385 | } | ||
386 | ssp_write_reg(ssp, SSACD, val); | ||
387 | break; | ||
388 | case PXA_SSP_DIV_SCR: | ||
389 | ssp_set_scr(&priv->dev, div); | ||
390 | break; | ||
391 | default: | ||
392 | return -ENODEV; | ||
393 | } | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | /* | ||
399 | * Configure the PLL frequency pxa27x and (afaik - pxa320 only) | ||
400 | */ | ||
401 | static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, | ||
402 | int pll_id, unsigned int freq_in, unsigned int freq_out) | ||
403 | { | ||
404 | struct ssp_priv *priv = cpu_dai->private_data; | ||
405 | struct ssp_device *ssp = priv->dev.ssp; | ||
406 | u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70; | ||
407 | |||
408 | #if defined(CONFIG_PXA3xx) | ||
409 | if (cpu_is_pxa3xx()) | ||
410 | ssp_write_reg(ssp, SSACDD, 0); | ||
411 | #endif | ||
412 | |||
413 | switch (freq_out) { | ||
414 | case 5622000: | ||
415 | break; | ||
416 | case 11345000: | ||
417 | ssacd |= (0x1 << 4); | ||
418 | break; | ||
419 | case 12235000: | ||
420 | ssacd |= (0x2 << 4); | ||
421 | break; | ||
422 | case 14857000: | ||
423 | ssacd |= (0x3 << 4); | ||
424 | break; | ||
425 | case 32842000: | ||
426 | ssacd |= (0x4 << 4); | ||
427 | break; | ||
428 | case 48000000: | ||
429 | ssacd |= (0x5 << 4); | ||
430 | break; | ||
431 | case 0: | ||
432 | /* Disable */ | ||
433 | break; | ||
434 | |||
435 | default: | ||
436 | #ifdef CONFIG_PXA3xx | ||
437 | /* PXA3xx has a clock ditherer which can be used to generate | ||
438 | * a wider range of frequencies - calculate a value for it. | ||
439 | */ | ||
440 | if (cpu_is_pxa3xx()) { | ||
441 | u32 val; | ||
442 | u64 tmp = 19968; | ||
443 | tmp *= 1000000; | ||
444 | do_div(tmp, freq_out); | ||
445 | val = tmp; | ||
446 | |||
447 | val = (val << 16) | 64;; | ||
448 | ssp_write_reg(ssp, SSACDD, val); | ||
449 | |||
450 | ssacd |= (0x6 << 4); | ||
451 | |||
452 | dev_dbg(&ssp->pdev->dev, | ||
453 | "Using SSACDD %x to supply %dHz\n", | ||
454 | val, freq_out); | ||
455 | break; | ||
456 | } | ||
457 | #endif | ||
458 | |||
459 | return -EINVAL; | ||
460 | } | ||
461 | |||
462 | ssp_write_reg(ssp, SSACD, ssacd); | ||
463 | |||
464 | return 0; | ||
465 | } | ||
466 | |||
467 | /* | ||
468 | * Set the active slots in TDM/Network mode | ||
469 | */ | ||
470 | static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, | ||
471 | unsigned int mask, int slots) | ||
472 | { | ||
473 | struct ssp_priv *priv = cpu_dai->private_data; | ||
474 | struct ssp_device *ssp = priv->dev.ssp; | ||
475 | u32 sscr0; | ||
476 | |||
477 | sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7); | ||
478 | |||
479 | /* set number of active slots */ | ||
480 | sscr0 |= SSCR0_SlotsPerFrm(slots); | ||
481 | ssp_write_reg(ssp, SSCR0, sscr0); | ||
482 | |||
483 | /* set active slot mask */ | ||
484 | ssp_write_reg(ssp, SSTSA, mask); | ||
485 | ssp_write_reg(ssp, SSRSA, mask); | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /* | ||
490 | * Tristate the SSP DAI lines | ||
491 | */ | ||
492 | static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, | ||
493 | int tristate) | ||
494 | { | ||
495 | struct ssp_priv *priv = cpu_dai->private_data; | ||
496 | struct ssp_device *ssp = priv->dev.ssp; | ||
497 | u32 sscr1; | ||
498 | |||
499 | sscr1 = ssp_read_reg(ssp, SSCR1); | ||
500 | if (tristate) | ||
501 | sscr1 &= ~SSCR1_TTE; | ||
502 | else | ||
503 | sscr1 |= SSCR1_TTE; | ||
504 | ssp_write_reg(ssp, SSCR1, sscr1); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | |||
509 | /* | ||
510 | * Set up the SSP DAI format. | ||
511 | * The SSP Port must be inactive before calling this function as the | ||
512 | * physical interface format is changed. | ||
513 | */ | ||
514 | static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, | ||
515 | unsigned int fmt) | ||
516 | { | ||
517 | struct ssp_priv *priv = cpu_dai->private_data; | ||
518 | struct ssp_device *ssp = priv->dev.ssp; | ||
519 | u32 sscr0; | ||
520 | u32 sscr1; | ||
521 | u32 sspsp; | ||
522 | |||
523 | /* reset port settings */ | ||
524 | sscr0 = ssp_read_reg(ssp, SSCR0) & | ||
525 | (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC); | ||
526 | sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); | ||
527 | sspsp = 0; | ||
528 | |||
529 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
530 | case SND_SOC_DAIFMT_CBM_CFM: | ||
531 | sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; | ||
532 | break; | ||
533 | case SND_SOC_DAIFMT_CBM_CFS: | ||
534 | sscr1 |= SSCR1_SCLKDIR; | ||
535 | break; | ||
536 | case SND_SOC_DAIFMT_CBS_CFS: | ||
537 | break; | ||
538 | default: | ||
539 | return -EINVAL; | ||
540 | } | ||
541 | |||
542 | ssp_write_reg(ssp, SSCR0, sscr0); | ||
543 | ssp_write_reg(ssp, SSCR1, sscr1); | ||
544 | ssp_write_reg(ssp, SSPSP, sspsp); | ||
545 | |||
546 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
547 | case SND_SOC_DAIFMT_I2S: | ||
548 | sscr0 |= SSCR0_MOD | SSCR0_PSP; | ||
549 | sscr1 |= SSCR1_RWOT | SSCR1_TRAIL; | ||
550 | |||
551 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
552 | case SND_SOC_DAIFMT_NB_NF: | ||
553 | sspsp |= SSPSP_FSRT; | ||
554 | break; | ||
555 | case SND_SOC_DAIFMT_NB_IF: | ||
556 | sspsp |= SSPSP_SFRMP | SSPSP_FSRT; | ||
557 | break; | ||
558 | case SND_SOC_DAIFMT_IB_IF: | ||
559 | sspsp |= SSPSP_SFRMP; | ||
560 | break; | ||
561 | default: | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | break; | ||
565 | |||
566 | case SND_SOC_DAIFMT_DSP_A: | ||
567 | sspsp |= SSPSP_FSRT; | ||
568 | case SND_SOC_DAIFMT_DSP_B: | ||
569 | sscr0 |= SSCR0_MOD | SSCR0_PSP; | ||
570 | sscr1 |= SSCR1_TRAIL | SSCR1_RWOT; | ||
571 | |||
572 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
573 | case SND_SOC_DAIFMT_NB_NF: | ||
574 | sspsp |= SSPSP_SFRMP; | ||
575 | break; | ||
576 | case SND_SOC_DAIFMT_IB_IF: | ||
577 | break; | ||
578 | default: | ||
579 | return -EINVAL; | ||
580 | } | ||
581 | break; | ||
582 | |||
583 | default: | ||
584 | return -EINVAL; | ||
585 | } | ||
586 | |||
587 | ssp_write_reg(ssp, SSCR0, sscr0); | ||
588 | ssp_write_reg(ssp, SSCR1, sscr1); | ||
589 | ssp_write_reg(ssp, SSPSP, sspsp); | ||
590 | |||
591 | dump_registers(ssp); | ||
592 | |||
593 | /* Since we are configuring the timings for the format by hand | ||
594 | * we have to defer some things until hw_params() where we | ||
595 | * know parameters like the sample size. | ||
596 | */ | ||
597 | priv->dai_fmt = fmt; | ||
598 | |||
599 | return 0; | ||
600 | } | ||
601 | |||
602 | /* | ||
603 | * Set the SSP audio DMA parameters and sample size. | ||
604 | * Can be called multiple times by oss emulation. | ||
605 | */ | ||
606 | static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, | ||
607 | struct snd_pcm_hw_params *params, | ||
608 | struct snd_soc_dai *dai) | ||
609 | { | ||
610 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
611 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
612 | struct ssp_priv *priv = cpu_dai->private_data; | ||
613 | struct ssp_device *ssp = priv->dev.ssp; | ||
614 | int dma = 0, chn = params_channels(params); | ||
615 | u32 sscr0; | ||
616 | u32 sspsp; | ||
617 | int width = snd_pcm_format_physical_width(params_format(params)); | ||
618 | |||
619 | /* select correct DMA params */ | ||
620 | if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) | ||
621 | dma = 1; /* capture DMA offset is 1,3 */ | ||
622 | if (chn == 2) | ||
623 | dma += 2; /* stereo DMA offset is 2, mono is 0 */ | ||
624 | cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma]; | ||
625 | |||
626 | dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma); | ||
627 | |||
628 | /* we can only change the settings if the port is not in use */ | ||
629 | if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) | ||
630 | return 0; | ||
631 | |||
632 | /* clear selected SSP bits */ | ||
633 | sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); | ||
634 | ssp_write_reg(ssp, SSCR0, sscr0); | ||
635 | |||
636 | /* bit size */ | ||
637 | sscr0 = ssp_read_reg(ssp, SSCR0); | ||
638 | switch (params_format(params)) { | ||
639 | case SNDRV_PCM_FORMAT_S16_LE: | ||
640 | #ifdef CONFIG_PXA3xx | ||
641 | if (cpu_is_pxa3xx()) | ||
642 | sscr0 |= SSCR0_FPCKE; | ||
643 | #endif | ||
644 | sscr0 |= SSCR0_DataSize(16); | ||
645 | if (params_channels(params) > 1) | ||
646 | sscr0 |= SSCR0_EDSS; | ||
647 | break; | ||
648 | case SNDRV_PCM_FORMAT_S24_LE: | ||
649 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8)); | ||
650 | /* we must be in network mode (2 slots) for 24 bit stereo */ | ||
651 | break; | ||
652 | case SNDRV_PCM_FORMAT_S32_LE: | ||
653 | sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16)); | ||
654 | /* we must be in network mode (2 slots) for 32 bit stereo */ | ||
655 | break; | ||
656 | } | ||
657 | ssp_write_reg(ssp, SSCR0, sscr0); | ||
658 | |||
659 | switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
660 | case SND_SOC_DAIFMT_I2S: | ||
661 | /* Cleared when the DAI format is set */ | ||
662 | sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width); | ||
663 | ssp_write_reg(ssp, SSPSP, sspsp); | ||
664 | break; | ||
665 | default: | ||
666 | break; | ||
667 | } | ||
668 | |||
669 | /* We always use a network mode so we always require TDM slots | ||
670 | * - complain loudly and fail if they've not been set up yet. | ||
671 | */ | ||
672 | if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) { | ||
673 | dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n"); | ||
674 | return -EINVAL; | ||
675 | } | ||
676 | |||
677 | dump_registers(ssp); | ||
678 | |||
679 | return 0; | ||
680 | } | ||
681 | |||
682 | static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, | ||
683 | struct snd_soc_dai *dai) | ||
684 | { | ||
685 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
686 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
687 | int ret = 0; | ||
688 | struct ssp_priv *priv = cpu_dai->private_data; | ||
689 | struct ssp_device *ssp = priv->dev.ssp; | ||
690 | int val; | ||
691 | |||
692 | switch (cmd) { | ||
693 | case SNDRV_PCM_TRIGGER_RESUME: | ||
694 | ssp_enable(&priv->dev); | ||
695 | break; | ||
696 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
697 | val = ssp_read_reg(ssp, SSCR1); | ||
698 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
699 | val |= SSCR1_TSRE; | ||
700 | else | ||
701 | val |= SSCR1_RSRE; | ||
702 | ssp_write_reg(ssp, SSCR1, val); | ||
703 | val = ssp_read_reg(ssp, SSSR); | ||
704 | ssp_write_reg(ssp, SSSR, val); | ||
705 | break; | ||
706 | case SNDRV_PCM_TRIGGER_START: | ||
707 | val = ssp_read_reg(ssp, SSCR1); | ||
708 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
709 | val |= SSCR1_TSRE; | ||
710 | else | ||
711 | val |= SSCR1_RSRE; | ||
712 | ssp_write_reg(ssp, SSCR1, val); | ||
713 | ssp_enable(&priv->dev); | ||
714 | break; | ||
715 | case SNDRV_PCM_TRIGGER_STOP: | ||
716 | val = ssp_read_reg(ssp, SSCR1); | ||
717 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
718 | val &= ~SSCR1_TSRE; | ||
719 | else | ||
720 | val &= ~SSCR1_RSRE; | ||
721 | ssp_write_reg(ssp, SSCR1, val); | ||
722 | break; | ||
723 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
724 | ssp_disable(&priv->dev); | ||
725 | break; | ||
726 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
727 | val = ssp_read_reg(ssp, SSCR1); | ||
728 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
729 | val &= ~SSCR1_TSRE; | ||
730 | else | ||
731 | val &= ~SSCR1_RSRE; | ||
732 | ssp_write_reg(ssp, SSCR1, val); | ||
733 | break; | ||
734 | |||
735 | default: | ||
736 | ret = -EINVAL; | ||
737 | } | ||
738 | |||
739 | dump_registers(ssp); | ||
740 | |||
741 | return ret; | ||
742 | } | ||
743 | |||
744 | static int pxa_ssp_probe(struct platform_device *pdev, | ||
745 | struct snd_soc_dai *dai) | ||
746 | { | ||
747 | struct ssp_priv *priv; | ||
748 | int ret; | ||
749 | |||
750 | priv = kzalloc(sizeof(struct ssp_priv), GFP_KERNEL); | ||
751 | if (!priv) | ||
752 | return -ENOMEM; | ||
753 | |||
754 | priv->dev.ssp = ssp_request(dai->id, "SoC audio"); | ||
755 | if (priv->dev.ssp == NULL) { | ||
756 | ret = -ENODEV; | ||
757 | goto err_priv; | ||
758 | } | ||
759 | |||
760 | dai->private_data = priv; | ||
761 | |||
762 | return 0; | ||
763 | |||
764 | err_priv: | ||
765 | kfree(priv); | ||
766 | return ret; | ||
767 | } | ||
768 | |||
769 | static void pxa_ssp_remove(struct platform_device *pdev, | ||
770 | struct snd_soc_dai *dai) | ||
771 | { | ||
772 | struct ssp_priv *priv = dai->private_data; | ||
773 | ssp_free(priv->dev.ssp); | ||
774 | } | ||
775 | |||
776 | #define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
777 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | ||
778 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ | ||
779 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | ||
780 | |||
781 | #define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ | ||
782 | SNDRV_PCM_FMTBIT_S24_LE | \ | ||
783 | SNDRV_PCM_FMTBIT_S32_LE) | ||
784 | |||
785 | struct snd_soc_dai pxa_ssp_dai[] = { | ||
786 | { | ||
787 | .name = "pxa2xx-ssp1", | ||
788 | .id = 0, | ||
789 | .probe = pxa_ssp_probe, | ||
790 | .remove = pxa_ssp_remove, | ||
791 | .suspend = pxa_ssp_suspend, | ||
792 | .resume = pxa_ssp_resume, | ||
793 | .playback = { | ||
794 | .channels_min = 1, | ||
795 | .channels_max = 2, | ||
796 | .rates = PXA_SSP_RATES, | ||
797 | .formats = PXA_SSP_FORMATS, | ||
798 | }, | ||
799 | .capture = { | ||
800 | .channels_min = 1, | ||
801 | .channels_max = 2, | ||
802 | .rates = PXA_SSP_RATES, | ||
803 | .formats = PXA_SSP_FORMATS, | ||
804 | }, | ||
805 | .ops = { | ||
806 | .startup = pxa_ssp_startup, | ||
807 | .shutdown = pxa_ssp_shutdown, | ||
808 | .trigger = pxa_ssp_trigger, | ||
809 | .hw_params = pxa_ssp_hw_params, | ||
810 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
811 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
812 | .set_pll = pxa_ssp_set_dai_pll, | ||
813 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
814 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
815 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
816 | }, | ||
817 | }, | ||
818 | { .name = "pxa2xx-ssp2", | ||
819 | .id = 1, | ||
820 | .probe = pxa_ssp_probe, | ||
821 | .remove = pxa_ssp_remove, | ||
822 | .suspend = pxa_ssp_suspend, | ||
823 | .resume = pxa_ssp_resume, | ||
824 | .playback = { | ||
825 | .channels_min = 1, | ||
826 | .channels_max = 2, | ||
827 | .rates = PXA_SSP_RATES, | ||
828 | .formats = PXA_SSP_FORMATS, | ||
829 | }, | ||
830 | .capture = { | ||
831 | .channels_min = 1, | ||
832 | .channels_max = 2, | ||
833 | .rates = PXA_SSP_RATES, | ||
834 | .formats = PXA_SSP_FORMATS, | ||
835 | }, | ||
836 | .ops = { | ||
837 | .startup = pxa_ssp_startup, | ||
838 | .shutdown = pxa_ssp_shutdown, | ||
839 | .trigger = pxa_ssp_trigger, | ||
840 | .hw_params = pxa_ssp_hw_params, | ||
841 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
842 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
843 | .set_pll = pxa_ssp_set_dai_pll, | ||
844 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
845 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
846 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
847 | }, | ||
848 | }, | ||
849 | { | ||
850 | .name = "pxa2xx-ssp3", | ||
851 | .id = 2, | ||
852 | .probe = pxa_ssp_probe, | ||
853 | .remove = pxa_ssp_remove, | ||
854 | .suspend = pxa_ssp_suspend, | ||
855 | .resume = pxa_ssp_resume, | ||
856 | .playback = { | ||
857 | .channels_min = 1, | ||
858 | .channels_max = 2, | ||
859 | .rates = PXA_SSP_RATES, | ||
860 | .formats = PXA_SSP_FORMATS, | ||
861 | }, | ||
862 | .capture = { | ||
863 | .channels_min = 1, | ||
864 | .channels_max = 2, | ||
865 | .rates = PXA_SSP_RATES, | ||
866 | .formats = PXA_SSP_FORMATS, | ||
867 | }, | ||
868 | .ops = { | ||
869 | .startup = pxa_ssp_startup, | ||
870 | .shutdown = pxa_ssp_shutdown, | ||
871 | .trigger = pxa_ssp_trigger, | ||
872 | .hw_params = pxa_ssp_hw_params, | ||
873 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
874 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
875 | .set_pll = pxa_ssp_set_dai_pll, | ||
876 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
877 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
878 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
879 | }, | ||
880 | }, | ||
881 | { | ||
882 | .name = "pxa2xx-ssp4", | ||
883 | .id = 3, | ||
884 | .probe = pxa_ssp_probe, | ||
885 | .remove = pxa_ssp_remove, | ||
886 | .suspend = pxa_ssp_suspend, | ||
887 | .resume = pxa_ssp_resume, | ||
888 | .playback = { | ||
889 | .channels_min = 1, | ||
890 | .channels_max = 2, | ||
891 | .rates = PXA_SSP_RATES, | ||
892 | .formats = PXA_SSP_FORMATS, | ||
893 | }, | ||
894 | .capture = { | ||
895 | .channels_min = 1, | ||
896 | .channels_max = 2, | ||
897 | .rates = PXA_SSP_RATES, | ||
898 | .formats = PXA_SSP_FORMATS, | ||
899 | }, | ||
900 | .ops = { | ||
901 | .startup = pxa_ssp_startup, | ||
902 | .shutdown = pxa_ssp_shutdown, | ||
903 | .trigger = pxa_ssp_trigger, | ||
904 | .hw_params = pxa_ssp_hw_params, | ||
905 | .set_sysclk = pxa_ssp_set_dai_sysclk, | ||
906 | .set_clkdiv = pxa_ssp_set_dai_clkdiv, | ||
907 | .set_pll = pxa_ssp_set_dai_pll, | ||
908 | .set_fmt = pxa_ssp_set_dai_fmt, | ||
909 | .set_tdm_slot = pxa_ssp_set_dai_tdm_slot, | ||
910 | .set_tristate = pxa_ssp_set_dai_tristate, | ||
911 | }, | ||
912 | }, | ||
913 | }; | ||
914 | EXPORT_SYMBOL_GPL(pxa_ssp_dai); | ||
915 | |||
916 | static int __init pxa_ssp_init(void) | ||
917 | { | ||
918 | return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); | ||
919 | } | ||
920 | module_init(pxa_ssp_init); | ||
921 | |||
922 | static void __exit pxa_ssp_exit(void) | ||
923 | { | ||
924 | snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); | ||
925 | } | ||
926 | module_exit(pxa_ssp_exit); | ||
927 | |||
928 | /* Module information */ | ||
929 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
930 | MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface"); | ||
931 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h new file mode 100644 index 000000000000..91deadd55675 --- /dev/null +++ b/sound/soc/pxa/pxa-ssp.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* | ||
2 | * ASoC PXA SSP port support | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #ifndef _PXA_SSP_H | ||
10 | #define _PXA_SSP_H | ||
11 | |||
12 | /* pxa DAI SSP IDs */ | ||
13 | #define PXA_DAI_SSP1 0 | ||
14 | #define PXA_DAI_SSP2 1 | ||
15 | #define PXA_DAI_SSP3 2 | ||
16 | #define PXA_DAI_SSP4 3 | ||
17 | |||
18 | /* SSP clock sources */ | ||
19 | #define PXA_SSP_CLK_PLL 0 | ||
20 | #define PXA_SSP_CLK_EXT 1 | ||
21 | #define PXA_SSP_CLK_NET 2 | ||
22 | #define PXA_SSP_CLK_AUDIO 3 | ||
23 | #define PXA_SSP_CLK_NET_PLL 4 | ||
24 | |||
25 | /* SSP audio dividers */ | ||
26 | #define PXA_SSP_AUDIO_DIV_ACDS 0 | ||
27 | #define PXA_SSP_AUDIO_DIV_SCDB 1 | ||
28 | #define PXA_SSP_DIV_SCR 2 | ||
29 | |||
30 | /* SSP ACDS audio dividers values */ | ||
31 | #define PXA_SSP_CLK_AUDIO_DIV_1 0 | ||
32 | #define PXA_SSP_CLK_AUDIO_DIV_2 1 | ||
33 | #define PXA_SSP_CLK_AUDIO_DIV_4 2 | ||
34 | #define PXA_SSP_CLK_AUDIO_DIV_8 3 | ||
35 | #define PXA_SSP_CLK_AUDIO_DIV_16 4 | ||
36 | #define PXA_SSP_CLK_AUDIO_DIV_32 5 | ||
37 | |||
38 | /* SSP divider bypass */ | ||
39 | #define PXA_SSP_CLK_SCDB_4 0 | ||
40 | #define PXA_SSP_CLK_SCDB_1 1 | ||
41 | #define PXA_SSP_CLK_SCDB_8 2 | ||
42 | |||
43 | #define PXA_SSP_PLL_OUT 0 | ||
44 | |||
45 | extern struct snd_soc_dai pxa_ssp_dai[4]; | ||
46 | |||
47 | #endif | ||
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index a7a3a9c5c6ff..780db6757ad2 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -87,14 +87,12 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = { | |||
87 | }; | 87 | }; |
88 | 88 | ||
89 | #ifdef CONFIG_PM | 89 | #ifdef CONFIG_PM |
90 | static int pxa2xx_ac97_suspend(struct platform_device *pdev, | 90 | static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai) |
91 | struct snd_soc_dai *dai) | ||
92 | { | 91 | { |
93 | return pxa2xx_ac97_hw_suspend(); | 92 | return pxa2xx_ac97_hw_suspend(); |
94 | } | 93 | } |
95 | 94 | ||
96 | static int pxa2xx_ac97_resume(struct platform_device *pdev, | 95 | static int pxa2xx_ac97_resume(struct snd_soc_dai *dai) |
97 | struct snd_soc_dai *dai) | ||
98 | { | 96 | { |
99 | return pxa2xx_ac97_hw_resume(); | 97 | return pxa2xx_ac97_hw_resume(); |
100 | } | 98 | } |
@@ -117,7 +115,8 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev, | |||
117 | } | 115 | } |
118 | 116 | ||
119 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | 117 | static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, |
120 | struct snd_pcm_hw_params *params) | 118 | struct snd_pcm_hw_params *params, |
119 | struct snd_soc_dai *dai) | ||
121 | { | 120 | { |
122 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 121 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
123 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 122 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -131,7 +130,8 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream, | |||
131 | } | 130 | } |
132 | 131 | ||
133 | static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | 132 | static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, |
134 | struct snd_pcm_hw_params *params) | 133 | struct snd_pcm_hw_params *params, |
134 | struct snd_soc_dai *dai) | ||
135 | { | 135 | { |
136 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 136 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -145,7 +145,8 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream, | |||
145 | } | 145 | } |
146 | 146 | ||
147 | static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, | 147 | static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream, |
148 | struct snd_pcm_hw_params *params) | 148 | struct snd_pcm_hw_params *params, |
149 | struct snd_soc_dai *dai) | ||
149 | { | 150 | { |
150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 151 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
151 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 152 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -170,7 +171,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
170 | { | 171 | { |
171 | .name = "pxa2xx-ac97", | 172 | .name = "pxa2xx-ac97", |
172 | .id = 0, | 173 | .id = 0, |
173 | .type = SND_SOC_DAI_AC97, | 174 | .ac97_control = 1, |
174 | .probe = pxa2xx_ac97_probe, | 175 | .probe = pxa2xx_ac97_probe, |
175 | .remove = pxa2xx_ac97_remove, | 176 | .remove = pxa2xx_ac97_remove, |
176 | .suspend = pxa2xx_ac97_suspend, | 177 | .suspend = pxa2xx_ac97_suspend, |
@@ -193,7 +194,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
193 | { | 194 | { |
194 | .name = "pxa2xx-ac97-aux", | 195 | .name = "pxa2xx-ac97-aux", |
195 | .id = 1, | 196 | .id = 1, |
196 | .type = SND_SOC_DAI_AC97, | 197 | .ac97_control = 1, |
197 | .playback = { | 198 | .playback = { |
198 | .stream_name = "AC97 Aux Playback", | 199 | .stream_name = "AC97 Aux Playback", |
199 | .channels_min = 1, | 200 | .channels_min = 1, |
@@ -212,7 +213,7 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
212 | { | 213 | { |
213 | .name = "pxa2xx-ac97-mic", | 214 | .name = "pxa2xx-ac97-mic", |
214 | .id = 2, | 215 | .id = 2, |
215 | .type = SND_SOC_DAI_AC97, | 216 | .ac97_control = 1, |
216 | .capture = { | 217 | .capture = { |
217 | .stream_name = "AC97 Mic Capture", | 218 | .stream_name = "AC97 Mic Capture", |
218 | .channels_min = 1, | 219 | .channels_min = 1, |
@@ -227,6 +228,18 @@ struct snd_soc_dai pxa_ac97_dai[] = { | |||
227 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); | 228 | EXPORT_SYMBOL_GPL(pxa_ac97_dai); |
228 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 229 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
229 | 230 | ||
231 | static int __init pxa_ac97_init(void) | ||
232 | { | ||
233 | return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | ||
234 | } | ||
235 | module_init(pxa_ac97_init); | ||
236 | |||
237 | static void __exit pxa_ac97_exit(void) | ||
238 | { | ||
239 | snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai)); | ||
240 | } | ||
241 | module_exit(pxa_ac97_exit); | ||
242 | |||
230 | MODULE_AUTHOR("Nicolas Pitre"); | 243 | MODULE_AUTHOR("Nicolas Pitre"); |
231 | MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); | 244 | MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip"); |
232 | MODULE_LICENSE("GPL"); | 245 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c index e758034db5c3..517991fb1099 100644 --- a/sound/soc/pxa/pxa2xx-i2s.c +++ b/sound/soc/pxa/pxa2xx-i2s.c | |||
@@ -121,7 +121,8 @@ static struct pxa2xx_gpio gpio_bus[] = { | |||
121 | }, | 121 | }, |
122 | }; | 122 | }; |
123 | 123 | ||
124 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream) | 124 | static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream, |
125 | struct snd_soc_dai *dai) | ||
125 | { | 126 | { |
126 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 127 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
127 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 128 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -187,7 +188,8 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai, | |||
187 | } | 188 | } |
188 | 189 | ||
189 | static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | 190 | static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, |
190 | struct snd_pcm_hw_params *params) | 191 | struct snd_pcm_hw_params *params, |
192 | struct snd_soc_dai *dai) | ||
191 | { | 193 | { |
192 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 194 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
193 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 195 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -248,7 +250,8 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
248 | return 0; | 250 | return 0; |
249 | } | 251 | } |
250 | 252 | ||
251 | static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 253 | static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
254 | struct snd_soc_dai *dai) | ||
252 | { | 255 | { |
253 | int ret = 0; | 256 | int ret = 0; |
254 | 257 | ||
@@ -269,7 +272,8 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | |||
269 | return ret; | 272 | return ret; |
270 | } | 273 | } |
271 | 274 | ||
272 | static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream) | 275 | static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream, |
276 | struct snd_soc_dai *dai) | ||
273 | { | 277 | { |
274 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 278 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
275 | SACR1 |= SACR1_DRPL; | 279 | SACR1 |= SACR1_DRPL; |
@@ -289,8 +293,7 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream) | |||
289 | } | 293 | } |
290 | 294 | ||
291 | #ifdef CONFIG_PM | 295 | #ifdef CONFIG_PM |
292 | static int pxa2xx_i2s_suspend(struct platform_device *dev, | 296 | static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai) |
293 | struct snd_soc_dai *dai) | ||
294 | { | 297 | { |
295 | if (!dai->active) | 298 | if (!dai->active) |
296 | return 0; | 299 | return 0; |
@@ -307,8 +310,7 @@ static int pxa2xx_i2s_suspend(struct platform_device *dev, | |||
307 | return 0; | 310 | return 0; |
308 | } | 311 | } |
309 | 312 | ||
310 | static int pxa2xx_i2s_resume(struct platform_device *pdev, | 313 | static int pxa2xx_i2s_resume(struct snd_soc_dai *dai) |
311 | struct snd_soc_dai *dai) | ||
312 | { | 314 | { |
313 | if (!dai->active) | 315 | if (!dai->active) |
314 | return 0; | 316 | return 0; |
@@ -336,7 +338,6 @@ static int pxa2xx_i2s_resume(struct platform_device *pdev, | |||
336 | struct snd_soc_dai pxa_i2s_dai = { | 338 | struct snd_soc_dai pxa_i2s_dai = { |
337 | .name = "pxa2xx-i2s", | 339 | .name = "pxa2xx-i2s", |
338 | .id = 0, | 340 | .id = 0, |
339 | .type = SND_SOC_DAI_I2S, | ||
340 | .suspend = pxa2xx_i2s_suspend, | 341 | .suspend = pxa2xx_i2s_suspend, |
341 | .resume = pxa2xx_i2s_resume, | 342 | .resume = pxa2xx_i2s_resume, |
342 | .playback = { | 343 | .playback = { |
@@ -353,8 +354,7 @@ struct snd_soc_dai pxa_i2s_dai = { | |||
353 | .startup = pxa2xx_i2s_startup, | 354 | .startup = pxa2xx_i2s_startup, |
354 | .shutdown = pxa2xx_i2s_shutdown, | 355 | .shutdown = pxa2xx_i2s_shutdown, |
355 | .trigger = pxa2xx_i2s_trigger, | 356 | .trigger = pxa2xx_i2s_trigger, |
356 | .hw_params = pxa2xx_i2s_hw_params,}, | 357 | .hw_params = pxa2xx_i2s_hw_params, |
357 | .dai_ops = { | ||
358 | .set_fmt = pxa2xx_i2s_set_dai_fmt, | 358 | .set_fmt = pxa2xx_i2s_set_dai_fmt, |
359 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, | 359 | .set_sysclk = pxa2xx_i2s_set_dai_sysclk, |
360 | }, | 360 | }, |
@@ -364,12 +364,23 @@ EXPORT_SYMBOL_GPL(pxa_i2s_dai); | |||
364 | 364 | ||
365 | static int pxa2xx_i2s_probe(struct platform_device *dev) | 365 | static int pxa2xx_i2s_probe(struct platform_device *dev) |
366 | { | 366 | { |
367 | int ret; | ||
368 | |||
367 | clk_i2s = clk_get(&dev->dev, "I2SCLK"); | 369 | clk_i2s = clk_get(&dev->dev, "I2SCLK"); |
368 | return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0; | 370 | if (IS_ERR(clk_i2s)) |
371 | return PTR_ERR(clk_i2s); | ||
372 | |||
373 | pxa_i2s_dai.dev = &dev->dev; | ||
374 | ret = snd_soc_register_dai(&pxa_i2s_dai); | ||
375 | if (ret != 0) | ||
376 | clk_put(clk_i2s); | ||
377 | |||
378 | return ret; | ||
369 | } | 379 | } |
370 | 380 | ||
371 | static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) | 381 | static int __devexit pxa2xx_i2s_remove(struct platform_device *dev) |
372 | { | 382 | { |
383 | snd_soc_unregister_dai(&pxa_i2s_dai); | ||
373 | clk_put(clk_i2s); | 384 | clk_put(clk_i2s); |
374 | clk_i2s = ERR_PTR(-ENOENT); | 385 | clk_i2s = ERR_PTR(-ENOENT); |
375 | return 0; | 386 | return 0; |
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c index afcd892cd2fa..c670d08e7c9e 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) | |||
69 | return 0; | 69 | return 0; |
70 | } | 70 | } |
71 | 71 | ||
72 | struct snd_pcm_ops pxa2xx_pcm_ops = { | 72 | static struct snd_pcm_ops pxa2xx_pcm_ops = { |
73 | .open = __pxa2xx_pcm_open, | 73 | .open = __pxa2xx_pcm_open, |
74 | .close = __pxa2xx_pcm_close, | 74 | .close = __pxa2xx_pcm_close, |
75 | .ioctl = snd_pcm_lib_ioctl, | 75 | .ioctl = snd_pcm_lib_ioctl, |
@@ -118,6 +118,18 @@ struct snd_soc_platform pxa2xx_soc_platform = { | |||
118 | }; | 118 | }; |
119 | EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); | 119 | EXPORT_SYMBOL_GPL(pxa2xx_soc_platform); |
120 | 120 | ||
121 | static int __init pxa2xx_soc_platform_init(void) | ||
122 | { | ||
123 | return snd_soc_register_platform(&pxa2xx_soc_platform); | ||
124 | } | ||
125 | module_init(pxa2xx_soc_platform_init); | ||
126 | |||
127 | static void __exit pxa2xx_soc_platform_exit(void) | ||
128 | { | ||
129 | snd_soc_unregister_platform(&pxa2xx_soc_platform); | ||
130 | } | ||
131 | module_exit(pxa2xx_soc_platform_exit); | ||
132 | |||
121 | MODULE_AUTHOR("Nicolas Pitre"); | 133 | MODULE_AUTHOR("Nicolas Pitre"); |
122 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); | 134 | MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module"); |
123 | MODULE_LICENSE("GPL"); | 135 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c index d307b6757e95..a3b9e6bdf979 100644 --- a/sound/soc/pxa/spitz.c +++ b/sound/soc/pxa/spitz.c | |||
@@ -319,8 +319,9 @@ static struct snd_soc_dai_link spitz_dai = { | |||
319 | }; | 319 | }; |
320 | 320 | ||
321 | /* spitz audio machine driver */ | 321 | /* spitz audio machine driver */ |
322 | static struct snd_soc_machine snd_soc_machine_spitz = { | 322 | static struct snd_soc_card snd_soc_spitz = { |
323 | .name = "Spitz", | 323 | .name = "Spitz", |
324 | .platform = &pxa2xx_soc_platform, | ||
324 | .dai_link = &spitz_dai, | 325 | .dai_link = &spitz_dai, |
325 | .num_links = 1, | 326 | .num_links = 1, |
326 | }; | 327 | }; |
@@ -333,8 +334,7 @@ static struct wm8750_setup_data spitz_wm8750_setup = { | |||
333 | 334 | ||
334 | /* spitz audio subsystem */ | 335 | /* spitz audio subsystem */ |
335 | static struct snd_soc_device spitz_snd_devdata = { | 336 | static struct snd_soc_device spitz_snd_devdata = { |
336 | .machine = &snd_soc_machine_spitz, | 337 | .card = &snd_soc_spitz, |
337 | .platform = &pxa2xx_soc_platform, | ||
338 | .codec_dev = &soc_codec_dev_wm8750, | 338 | .codec_dev = &soc_codec_dev_wm8750, |
339 | .codec_data = &spitz_wm8750_setup, | 339 | .codec_data = &spitz_wm8750_setup, |
340 | }; | 340 | }; |
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c index afefe41b8c46..c77194f74c9b 100644 --- a/sound/soc/pxa/tosa.c +++ b/sound/soc/pxa/tosa.c | |||
@@ -38,7 +38,7 @@ | |||
38 | #include "pxa2xx-pcm.h" | 38 | #include "pxa2xx-pcm.h" |
39 | #include "pxa2xx-ac97.h" | 39 | #include "pxa2xx-ac97.h" |
40 | 40 | ||
41 | static struct snd_soc_machine tosa; | 41 | static struct snd_soc_card tosa; |
42 | 42 | ||
43 | #define TOSA_HP 0 | 43 | #define TOSA_HP 0 |
44 | #define TOSA_MIC_INT 1 | 44 | #define TOSA_MIC_INT 1 |
@@ -230,15 +230,37 @@ static struct snd_soc_dai_link tosa_dai[] = { | |||
230 | }, | 230 | }, |
231 | }; | 231 | }; |
232 | 232 | ||
233 | static struct snd_soc_machine tosa = { | 233 | static int tosa_probe(struct platform_device *dev) |
234 | { | ||
235 | int ret; | ||
236 | |||
237 | ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack"); | ||
238 | if (ret) | ||
239 | return ret; | ||
240 | ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0); | ||
241 | if (ret) | ||
242 | gpio_free(TOSA_GPIO_L_MUTE); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static int tosa_remove(struct platform_device *dev) | ||
248 | { | ||
249 | gpio_free(TOSA_GPIO_L_MUTE); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | static struct snd_soc_card tosa = { | ||
234 | .name = "Tosa", | 254 | .name = "Tosa", |
255 | .platform = &pxa2xx_soc_platform, | ||
235 | .dai_link = tosa_dai, | 256 | .dai_link = tosa_dai, |
236 | .num_links = ARRAY_SIZE(tosa_dai), | 257 | .num_links = ARRAY_SIZE(tosa_dai), |
258 | .probe = tosa_probe, | ||
259 | .remove = tosa_remove, | ||
237 | }; | 260 | }; |
238 | 261 | ||
239 | static struct snd_soc_device tosa_snd_devdata = { | 262 | static struct snd_soc_device tosa_snd_devdata = { |
240 | .machine = &tosa, | 263 | .card = &tosa, |
241 | .platform = &pxa2xx_soc_platform, | ||
242 | .codec_dev = &soc_codec_dev_wm9712, | 264 | .codec_dev = &soc_codec_dev_wm9712, |
243 | }; | 265 | }; |
244 | 266 | ||
@@ -251,11 +273,6 @@ static int __init tosa_init(void) | |||
251 | if (!machine_is_tosa()) | 273 | if (!machine_is_tosa()) |
252 | return -ENODEV; | 274 | return -ENODEV; |
253 | 275 | ||
254 | ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack"); | ||
255 | if (ret) | ||
256 | return ret; | ||
257 | gpio_direction_output(TOSA_GPIO_L_MUTE, 0); | ||
258 | |||
259 | tosa_snd_device = platform_device_alloc("soc-audio", -1); | 276 | tosa_snd_device = platform_device_alloc("soc-audio", -1); |
260 | if (!tosa_snd_device) { | 277 | if (!tosa_snd_device) { |
261 | ret = -ENOMEM; | 278 | ret = -ENOMEM; |
@@ -272,15 +289,12 @@ static int __init tosa_init(void) | |||
272 | platform_device_put(tosa_snd_device); | 289 | platform_device_put(tosa_snd_device); |
273 | 290 | ||
274 | err_alloc: | 291 | err_alloc: |
275 | gpio_free(TOSA_GPIO_L_MUTE); | ||
276 | |||
277 | return ret; | 292 | return ret; |
278 | } | 293 | } |
279 | 294 | ||
280 | static void __exit tosa_exit(void) | 295 | static void __exit tosa_exit(void) |
281 | { | 296 | { |
282 | platform_device_unregister(tosa_snd_device); | 297 | platform_device_unregister(tosa_snd_device); |
283 | gpio_free(TOSA_GPIO_L_MUTE); | ||
284 | } | 298 | } |
285 | 299 | ||
286 | module_init(tosa_init); | 300 | module_init(tosa_init); |
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c new file mode 100644 index 000000000000..f8e9ecd589d3 --- /dev/null +++ b/sound/soc/pxa/zylonite.c | |||
@@ -0,0 +1,219 @@ | |||
1 | /* | ||
2 | * zylonite.c -- SoC audio for Zylonite | ||
3 | * | ||
4 | * Copyright 2008 Wolfson Microelectronics PLC. | ||
5 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of the | ||
10 | * License, or (at your option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/moduleparam.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/i2c.h> | ||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/soc.h> | ||
22 | #include <sound/soc-dapm.h> | ||
23 | |||
24 | #include "../codecs/wm9713.h" | ||
25 | #include "pxa2xx-pcm.h" | ||
26 | #include "pxa2xx-ac97.h" | ||
27 | #include "pxa-ssp.h" | ||
28 | |||
29 | static struct snd_soc_card zylonite; | ||
30 | |||
31 | static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = { | ||
32 | SND_SOC_DAPM_HP("Headphone", NULL), | ||
33 | SND_SOC_DAPM_MIC("Headset Microphone", NULL), | ||
34 | SND_SOC_DAPM_MIC("Handset Microphone", NULL), | ||
35 | SND_SOC_DAPM_SPK("Multiactor", NULL), | ||
36 | SND_SOC_DAPM_SPK("Headset Earpiece", NULL), | ||
37 | }; | ||
38 | |||
39 | /* Currently supported audio map */ | ||
40 | static const struct snd_soc_dapm_route audio_map[] = { | ||
41 | |||
42 | /* Headphone output connected to HPL/HPR */ | ||
43 | { "Headphone", NULL, "HPL" }, | ||
44 | { "Headphone", NULL, "HPR" }, | ||
45 | |||
46 | /* On-board earpiece */ | ||
47 | { "Headset Earpiece", NULL, "OUT3" }, | ||
48 | |||
49 | /* Headphone mic */ | ||
50 | { "MIC2A", NULL, "Mic Bias" }, | ||
51 | { "Mic Bias", NULL, "Headset Microphone" }, | ||
52 | |||
53 | /* On-board mic */ | ||
54 | { "MIC1", NULL, "Mic Bias" }, | ||
55 | { "Mic Bias", NULL, "Handset Microphone" }, | ||
56 | |||
57 | /* Multiactor differentially connected over SPKL/SPKR */ | ||
58 | { "Multiactor", NULL, "SPKL" }, | ||
59 | { "Multiactor", NULL, "SPKR" }, | ||
60 | }; | ||
61 | |||
62 | static int zylonite_wm9713_init(struct snd_soc_codec *codec) | ||
63 | { | ||
64 | /* Currently we only support use of the AC97 clock here. If | ||
65 | * CLK_POUT is selected by SW15 then the clock API will need | ||
66 | * to be used to request and enable it here. | ||
67 | */ | ||
68 | |||
69 | snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, | ||
70 | ARRAY_SIZE(zylonite_dapm_widgets)); | ||
71 | |||
72 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
73 | |||
74 | /* Static setup for now */ | ||
75 | snd_soc_dapm_enable_pin(codec, "Headphone"); | ||
76 | snd_soc_dapm_enable_pin(codec, "Headset Earpiece"); | ||
77 | |||
78 | snd_soc_dapm_sync(codec); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | static int zylonite_voice_hw_params(struct snd_pcm_substream *substream, | ||
83 | struct snd_pcm_hw_params *params) | ||
84 | { | ||
85 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
86 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
87 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
88 | unsigned int pll_out = 0; | ||
89 | unsigned int acds = 0; | ||
90 | unsigned int wm9713_div = 0; | ||
91 | int ret = 0; | ||
92 | |||
93 | switch (params_rate(params)) { | ||
94 | case 8000: | ||
95 | wm9713_div = 12; | ||
96 | pll_out = 2048000; | ||
97 | break; | ||
98 | case 16000: | ||
99 | wm9713_div = 6; | ||
100 | pll_out = 4096000; | ||
101 | break; | ||
102 | case 48000: | ||
103 | default: | ||
104 | wm9713_div = 2; | ||
105 | pll_out = 12288000; | ||
106 | acds = 1; | ||
107 | break; | ||
108 | } | ||
109 | |||
110 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
111 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
112 | if (ret < 0) | ||
113 | return ret; | ||
114 | |||
115 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
116 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
117 | if (ret < 0) | ||
118 | return ret; | ||
119 | |||
120 | ret = snd_soc_dai_set_tdm_slot(cpu_dai, | ||
121 | params_channels(params), | ||
122 | params_channels(params)); | ||
123 | if (ret < 0) | ||
124 | return ret; | ||
125 | |||
126 | ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); | ||
127 | if (ret < 0) | ||
128 | return ret; | ||
129 | |||
130 | ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | |||
134 | ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
138 | /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs | ||
139 | * to be set instead. | ||
140 | */ | ||
141 | ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV, | ||
142 | WM9713_PCMDIV(wm9713_div)); | ||
143 | if (ret < 0) | ||
144 | return ret; | ||
145 | |||
146 | return 0; | ||
147 | } | ||
148 | |||
149 | static struct snd_soc_ops zylonite_voice_ops = { | ||
150 | .hw_params = zylonite_voice_hw_params, | ||
151 | }; | ||
152 | |||
153 | static struct snd_soc_dai_link zylonite_dai[] = { | ||
154 | { | ||
155 | .name = "AC97", | ||
156 | .stream_name = "AC97 HiFi", | ||
157 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI], | ||
158 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI], | ||
159 | .init = zylonite_wm9713_init, | ||
160 | }, | ||
161 | { | ||
162 | .name = "AC97 Aux", | ||
163 | .stream_name = "AC97 Aux", | ||
164 | .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX], | ||
165 | .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX], | ||
166 | }, | ||
167 | { | ||
168 | .name = "WM9713 Voice", | ||
169 | .stream_name = "WM9713 Voice", | ||
170 | .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3], | ||
171 | .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE], | ||
172 | .ops = &zylonite_voice_ops, | ||
173 | }, | ||
174 | }; | ||
175 | |||
176 | static struct snd_soc_card zylonite = { | ||
177 | .name = "Zylonite", | ||
178 | .platform = &pxa2xx_soc_platform, | ||
179 | .dai_link = zylonite_dai, | ||
180 | .num_links = ARRAY_SIZE(zylonite_dai), | ||
181 | }; | ||
182 | |||
183 | static struct snd_soc_device zylonite_snd_ac97_devdata = { | ||
184 | .card = &zylonite, | ||
185 | .codec_dev = &soc_codec_dev_wm9713, | ||
186 | }; | ||
187 | |||
188 | static struct platform_device *zylonite_snd_ac97_device; | ||
189 | |||
190 | static int __init zylonite_init(void) | ||
191 | { | ||
192 | int ret; | ||
193 | |||
194 | zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
195 | if (!zylonite_snd_ac97_device) | ||
196 | return -ENOMEM; | ||
197 | |||
198 | platform_set_drvdata(zylonite_snd_ac97_device, | ||
199 | &zylonite_snd_ac97_devdata); | ||
200 | zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev; | ||
201 | |||
202 | ret = platform_device_add(zylonite_snd_ac97_device); | ||
203 | if (ret != 0) | ||
204 | platform_device_put(zylonite_snd_ac97_device); | ||
205 | |||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | static void __exit zylonite_exit(void) | ||
210 | { | ||
211 | platform_device_unregister(zylonite_snd_ac97_device); | ||
212 | } | ||
213 | |||
214 | module_init(zylonite_init); | ||
215 | module_exit(zylonite_exit); | ||
216 | |||
217 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
218 | MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite"); | ||
219 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index b9f2353effeb..fcd03acf10f6 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -44,3 +44,8 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650 | |||
44 | Say Y if you want to add support for SoC audio on ln2440sbc | 44 | Say Y if you want to add support for SoC audio on ln2440sbc |
45 | with the ALC650. | 45 | with the ALC650. |
46 | 46 | ||
47 | config SND_S3C24XX_SOC_S3C24XX_UDA134X | ||
48 | tristate "SoC I2S Audio support UDA134X wired to a S3C24XX" | ||
49 | depends on SND_S3C24XX_SOC | ||
50 | select SND_S3C24XX_SOC_I2S | ||
51 | select SND_SOC_UDA134X | ||
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 0aa5fb0b9700..96b3f3f617d4 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -13,7 +13,9 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o | |||
13 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o | 13 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o |
14 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o | 14 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o |
15 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o | 15 | snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o |
16 | snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o | ||
16 | 17 | ||
17 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 18 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
18 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | 19 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o |
19 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o | 20 | obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o |
21 | 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 4eab2c19c454..12c71482d258 100644 --- a/sound/soc/s3c24xx/ln2440sbc_alc650.c +++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #include "s3c24xx-pcm.h" | 27 | #include "s3c24xx-pcm.h" |
28 | #include "s3c24xx-ac97.h" | 28 | #include "s3c24xx-ac97.h" |
29 | 29 | ||
30 | static struct snd_soc_machine ln2440sbc; | 30 | static struct snd_soc_card ln2440sbc; |
31 | 31 | ||
32 | static struct snd_soc_dai_link ln2440sbc_dai[] = { | 32 | static struct snd_soc_dai_link ln2440sbc_dai[] = { |
33 | { | 33 | { |
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = { | |||
38 | }, | 38 | }, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static struct snd_soc_machine ln2440sbc = { | 41 | static struct snd_soc_card ln2440sbc = { |
42 | .name = "LN2440SBC", | 42 | .name = "LN2440SBC", |
43 | .platform = &s3c24xx_soc_platform, | ||
43 | .dai_link = ln2440sbc_dai, | 44 | .dai_link = ln2440sbc_dai, |
44 | .num_links = ARRAY_SIZE(ln2440sbc_dai), | 45 | .num_links = ARRAY_SIZE(ln2440sbc_dai), |
45 | }; | 46 | }; |
46 | 47 | ||
47 | static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { | 48 | static struct snd_soc_device ln2440sbc_snd_ac97_devdata = { |
48 | .machine = &ln2440sbc, | 49 | .card = &ln2440sbc, |
49 | .platform = &s3c24xx_soc_platform, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | 50 | .codec_dev = &soc_codec_dev_ac97, |
51 | }; | 51 | }; |
52 | 52 | ||
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c index 87ddfefcc2fb..45bb12e8ea44 100644 --- a/sound/soc/s3c24xx/neo1973_wm8753.c +++ b/sound/soc/s3c24xx/neo1973_wm8753.c | |||
@@ -59,7 +59,7 @@ | |||
59 | #define NEO_CAPTURE_HEADSET 7 | 59 | #define NEO_CAPTURE_HEADSET 7 |
60 | #define NEO_CAPTURE_BLUETOOTH 8 | 60 | #define NEO_CAPTURE_BLUETOOTH 8 |
61 | 61 | ||
62 | static struct snd_soc_machine neo1973; | 62 | static struct snd_soc_card neo1973; |
63 | static struct i2c_client *i2c; | 63 | static struct i2c_client *i2c; |
64 | 64 | ||
65 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | 65 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, |
@@ -548,7 +548,6 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec) | |||
548 | static struct snd_soc_dai bt_dai = { | 548 | static struct snd_soc_dai bt_dai = { |
549 | .name = "Bluetooth", | 549 | .name = "Bluetooth", |
550 | .id = 0, | 550 | .id = 0, |
551 | .type = SND_SOC_DAI_PCM, | ||
552 | .playback = { | 551 | .playback = { |
553 | .channels_min = 1, | 552 | .channels_min = 1, |
554 | .channels_max = 1, | 553 | .channels_max = 1, |
@@ -579,8 +578,9 @@ static struct snd_soc_dai_link neo1973_dai[] = { | |||
579 | }, | 578 | }, |
580 | }; | 579 | }; |
581 | 580 | ||
582 | static struct snd_soc_machine neo1973 = { | 581 | static struct snd_soc_card neo1973 = { |
583 | .name = "neo1973", | 582 | .name = "neo1973", |
583 | .platform = &s3c24xx_soc_platform, | ||
584 | .dai_link = neo1973_dai, | 584 | .dai_link = neo1973_dai, |
585 | .num_links = ARRAY_SIZE(neo1973_dai), | 585 | .num_links = ARRAY_SIZE(neo1973_dai), |
586 | }; | 586 | }; |
@@ -591,8 +591,7 @@ static struct wm8753_setup_data neo1973_wm8753_setup = { | |||
591 | }; | 591 | }; |
592 | 592 | ||
593 | static struct snd_soc_device neo1973_snd_devdata = { | 593 | static struct snd_soc_device neo1973_snd_devdata = { |
594 | .machine = &neo1973, | 594 | .card = &neo1973, |
595 | .platform = &s3c24xx_soc_platform, | ||
596 | .codec_dev = &soc_codec_dev_wm8753, | 595 | .codec_dev = &soc_codec_dev_wm8753, |
597 | .codec_data = &neo1973_wm8753_setup, | 596 | .codec_data = &neo1973_wm8753_setup, |
598 | }; | 597 | }; |
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c index ded7d995a922..f3fc0aba0aaf 100644 --- a/sound/soc/s3c24xx/s3c2412-i2s.c +++ b/sound/soc/s3c24xx/s3c2412-i2s.c | |||
@@ -343,7 +343,8 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
343 | } | 343 | } |
344 | 344 | ||
345 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | 345 | static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, |
346 | struct snd_pcm_hw_params *params) | 346 | struct snd_pcm_hw_params *params, |
347 | struct snd_soc_dai *dai) | ||
347 | { | 348 | { |
348 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 349 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
349 | u32 iismod; | 350 | u32 iismod; |
@@ -373,7 +374,8 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream, | |||
373 | return 0; | 374 | return 0; |
374 | } | 375 | } |
375 | 376 | ||
376 | static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 377 | static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
378 | struct snd_soc_dai *dai) | ||
377 | { | 379 | { |
378 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); | 380 | int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); |
379 | unsigned long irqs; | 381 | unsigned long irqs; |
@@ -647,8 +649,7 @@ static int s3c2412_i2s_probe(struct platform_device *pdev, | |||
647 | } | 649 | } |
648 | 650 | ||
649 | #ifdef CONFIG_PM | 651 | #ifdef CONFIG_PM |
650 | static int s3c2412_i2s_suspend(struct platform_device *dev, | 652 | static int s3c2412_i2s_suspend(struct snd_soc_dai *dai) |
651 | struct snd_soc_dai *dai) | ||
652 | { | 653 | { |
653 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | 654 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; |
654 | u32 iismod; | 655 | u32 iismod; |
@@ -663,25 +664,24 @@ static int s3c2412_i2s_suspend(struct platform_device *dev, | |||
663 | iismod = readl(i2s->regs + S3C2412_IISMOD); | 664 | iismod = readl(i2s->regs + S3C2412_IISMOD); |
664 | 665 | ||
665 | if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) | 666 | if (iismod & S3C2412_IISCON_RXDMA_ACTIVE) |
666 | dev_warn(&dev->dev, "%s: RXDMA active?\n", __func__); | 667 | pr_warning("%s: RXDMA active?\n", __func__); |
667 | 668 | ||
668 | if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) | 669 | if (iismod & S3C2412_IISCON_TXDMA_ACTIVE) |
669 | dev_warn(&dev->dev, "%s: TXDMA active?\n", __func__); | 670 | pr_warning("%s: TXDMA active?\n", __func__); |
670 | 671 | ||
671 | if (iismod & S3C2412_IISCON_IIS_ACTIVE) | 672 | if (iismod & S3C2412_IISCON_IIS_ACTIVE) |
672 | dev_warn(&dev->dev, "%s: IIS active\n", __func__); | 673 | pr_warning("%s: IIS active\n", __func__); |
673 | } | 674 | } |
674 | 675 | ||
675 | return 0; | 676 | return 0; |
676 | } | 677 | } |
677 | 678 | ||
678 | static int s3c2412_i2s_resume(struct platform_device *pdev, | 679 | static int s3c2412_i2s_resume(struct snd_soc_dai *dai) |
679 | struct snd_soc_dai *dai) | ||
680 | { | 680 | { |
681 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; | 681 | struct s3c2412_i2s_info *i2s = &s3c2412_i2s; |
682 | 682 | ||
683 | dev_info(&pdev->dev, "dai_active %d, IISMOD %08x, IISCON %08x\n", | 683 | pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n", |
684 | dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); | 684 | dai->active, i2s->suspend_iismod, i2s->suspend_iiscon); |
685 | 685 | ||
686 | if (dai->active) { | 686 | if (dai->active) { |
687 | writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); | 687 | writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON); |
@@ -711,7 +711,6 @@ static int s3c2412_i2s_resume(struct platform_device *pdev, | |||
711 | struct snd_soc_dai s3c2412_i2s_dai = { | 711 | struct snd_soc_dai s3c2412_i2s_dai = { |
712 | .name = "s3c2412-i2s", | 712 | .name = "s3c2412-i2s", |
713 | .id = 0, | 713 | .id = 0, |
714 | .type = SND_SOC_DAI_I2S, | ||
715 | .probe = s3c2412_i2s_probe, | 714 | .probe = s3c2412_i2s_probe, |
716 | .suspend = s3c2412_i2s_suspend, | 715 | .suspend = s3c2412_i2s_suspend, |
717 | .resume = s3c2412_i2s_resume, | 716 | .resume = s3c2412_i2s_resume, |
@@ -730,8 +729,6 @@ struct snd_soc_dai s3c2412_i2s_dai = { | |||
730 | .ops = { | 729 | .ops = { |
731 | .trigger = s3c2412_i2s_trigger, | 730 | .trigger = s3c2412_i2s_trigger, |
732 | .hw_params = s3c2412_i2s_hw_params, | 731 | .hw_params = s3c2412_i2s_hw_params, |
733 | }, | ||
734 | .dai_ops = { | ||
735 | .set_fmt = s3c2412_i2s_set_fmt, | 732 | .set_fmt = s3c2412_i2s_set_fmt, |
736 | .set_clkdiv = s3c2412_i2s_set_clkdiv, | 733 | .set_clkdiv = s3c2412_i2s_set_clkdiv, |
737 | .set_sysclk = s3c2412_i2s_set_sysclk, | 734 | .set_sysclk = s3c2412_i2s_set_sysclk, |
@@ -739,6 +736,19 @@ struct snd_soc_dai s3c2412_i2s_dai = { | |||
739 | }; | 736 | }; |
740 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); | 737 | EXPORT_SYMBOL_GPL(s3c2412_i2s_dai); |
741 | 738 | ||
739 | static int __init s3c2412_i2s_init(void) | ||
740 | { | ||
741 | return snd_soc_register_dai(&s3c2412_i2s_dai); | ||
742 | } | ||
743 | module_init(s3c2412_i2s_init); | ||
744 | |||
745 | static void __exit s3c2412_i2s_exit(void) | ||
746 | { | ||
747 | snd_soc_unregister_dai(&s3c2412_i2s_dai); | ||
748 | } | ||
749 | module_exit(s3c2412_i2s_exit); | ||
750 | |||
751 | |||
742 | /* Module information */ | 752 | /* Module information */ |
743 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 753 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
744 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); | 754 | MODULE_DESCRIPTION("S3C2412 I2S SoC Interface"); |
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c index 19c5c3cf5d8c..1bfce40bb2e4 100644 --- a/sound/soc/s3c24xx/s3c2443-ac97.c +++ b/sound/soc/s3c24xx/s3c2443-ac97.c | |||
@@ -271,7 +271,8 @@ static void s3c2443_ac97_remove(struct platform_device *pdev, | |||
271 | } | 271 | } |
272 | 272 | ||
273 | static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream, | 273 | static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream, |
274 | struct snd_pcm_hw_params *params) | 274 | struct snd_pcm_hw_params *params, |
275 | struct snd_soc_dai *dai) | ||
275 | { | 276 | { |
276 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
277 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 278 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -284,7 +285,8 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream, | |||
284 | return 0; | 285 | return 0; |
285 | } | 286 | } |
286 | 287 | ||
287 | static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) | 288 | static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd, |
289 | struct snd_soc_dai *dai) | ||
288 | { | 290 | { |
289 | u32 ac_glbctrl; | 291 | u32 ac_glbctrl; |
290 | 292 | ||
@@ -313,7 +315,8 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) | |||
313 | } | 315 | } |
314 | 316 | ||
315 | static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, | 317 | static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, |
316 | struct snd_pcm_hw_params *params) | 318 | struct snd_pcm_hw_params *params, |
319 | struct snd_soc_dai *dai) | ||
317 | { | 320 | { |
318 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 321 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
319 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | 322 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; |
@@ -327,7 +330,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, | |||
327 | } | 330 | } |
328 | 331 | ||
329 | static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, | 332 | static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, |
330 | int cmd) | 333 | int cmd, struct snd_soc_dai *dai) |
331 | { | 334 | { |
332 | u32 ac_glbctrl; | 335 | u32 ac_glbctrl; |
333 | 336 | ||
@@ -356,7 +359,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { | |||
356 | { | 359 | { |
357 | .name = "s3c2443-ac97", | 360 | .name = "s3c2443-ac97", |
358 | .id = 0, | 361 | .id = 0, |
359 | .type = SND_SOC_DAI_AC97, | 362 | .ac97_control = 1, |
360 | .probe = s3c2443_ac97_probe, | 363 | .probe = s3c2443_ac97_probe, |
361 | .remove = s3c2443_ac97_remove, | 364 | .remove = s3c2443_ac97_remove, |
362 | .playback = { | 365 | .playback = { |
@@ -378,7 +381,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { | |||
378 | { | 381 | { |
379 | .name = "pxa2xx-ac97-mic", | 382 | .name = "pxa2xx-ac97-mic", |
380 | .id = 1, | 383 | .id = 1, |
381 | .type = SND_SOC_DAI_AC97, | 384 | .ac97_control = 1, |
382 | .capture = { | 385 | .capture = { |
383 | .stream_name = "AC97 Mic Capture", | 386 | .stream_name = "AC97 Mic Capture", |
384 | .channels_min = 1, | 387 | .channels_min = 1, |
@@ -393,6 +396,21 @@ struct snd_soc_dai s3c2443_ac97_dai[] = { | |||
393 | EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); | 396 | EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); |
394 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 397 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
395 | 398 | ||
399 | static int __init s3c2443_ac97_init(void) | ||
400 | { | ||
401 | return snd_soc_register_dais(s3c2443_ac97_dai, | ||
402 | ARRAY_SIZE(s3c2443_ac97_dai)); | ||
403 | } | ||
404 | module_init(s3c2443_ac97_init); | ||
405 | |||
406 | static void __exit s3c2443_ac97_exit(void) | ||
407 | { | ||
408 | snd_soc_unregister_dais(s3c2443_ac97_dai, | ||
409 | ARRAY_SIZE(s3c2443_ac97_dai)); | ||
410 | } | ||
411 | module_exit(s3c2443_ac97_exit); | ||
412 | |||
413 | |||
396 | MODULE_AUTHOR("Graeme Gregory"); | 414 | MODULE_AUTHOR("Graeme Gregory"); |
397 | MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip"); | 415 | MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip"); |
398 | MODULE_LICENSE("GPL"); | 416 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index ba4476b55fbc..6f4d439b57aa 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -243,7 +243,8 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai, | |||
243 | } | 243 | } |
244 | 244 | ||
245 | static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | 245 | static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, |
246 | struct snd_pcm_hw_params *params) | 246 | struct snd_pcm_hw_params *params, |
247 | struct snd_soc_dai *dai) | ||
247 | { | 248 | { |
248 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 249 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
249 | u32 iismod; | 250 | u32 iismod; |
@@ -261,10 +262,17 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
261 | 262 | ||
262 | switch (params_format(params)) { | 263 | switch (params_format(params)) { |
263 | case SNDRV_PCM_FORMAT_S8: | 264 | case SNDRV_PCM_FORMAT_S8: |
265 | iismod &= ~S3C2410_IISMOD_16BIT; | ||
266 | ((struct s3c24xx_pcm_dma_params *) | ||
267 | rtd->dai->cpu_dai->dma_data)->dma_size = 1; | ||
264 | break; | 268 | break; |
265 | case SNDRV_PCM_FORMAT_S16_LE: | 269 | case SNDRV_PCM_FORMAT_S16_LE: |
266 | iismod |= S3C2410_IISMOD_16BIT; | 270 | iismod |= S3C2410_IISMOD_16BIT; |
271 | ((struct s3c24xx_pcm_dma_params *) | ||
272 | rtd->dai->cpu_dai->dma_data)->dma_size = 2; | ||
267 | break; | 273 | break; |
274 | default: | ||
275 | return -EINVAL; | ||
268 | } | 276 | } |
269 | 277 | ||
270 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); | 278 | writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD); |
@@ -272,7 +280,8 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream, | |||
272 | return 0; | 280 | return 0; |
273 | } | 281 | } |
274 | 282 | ||
275 | static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd) | 283 | static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd, |
284 | struct snd_soc_dai *dai) | ||
276 | { | 285 | { |
277 | int ret = 0; | 286 | int ret = 0; |
278 | 287 | ||
@@ -410,8 +419,7 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev, | |||
410 | } | 419 | } |
411 | 420 | ||
412 | #ifdef CONFIG_PM | 421 | #ifdef CONFIG_PM |
413 | static int s3c24xx_i2s_suspend(struct platform_device *pdev, | 422 | static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai) |
414 | struct snd_soc_dai *cpu_dai) | ||
415 | { | 423 | { |
416 | DBG("Entered %s\n", __func__); | 424 | DBG("Entered %s\n", __func__); |
417 | 425 | ||
@@ -425,8 +433,7 @@ static int s3c24xx_i2s_suspend(struct platform_device *pdev, | |||
425 | return 0; | 433 | return 0; |
426 | } | 434 | } |
427 | 435 | ||
428 | static int s3c24xx_i2s_resume(struct platform_device *pdev, | 436 | static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai) |
429 | struct snd_soc_dai *cpu_dai) | ||
430 | { | 437 | { |
431 | DBG("Entered %s\n", __func__); | 438 | DBG("Entered %s\n", __func__); |
432 | clk_enable(s3c24xx_i2s.iis_clk); | 439 | clk_enable(s3c24xx_i2s.iis_clk); |
@@ -452,7 +459,6 @@ static int s3c24xx_i2s_resume(struct platform_device *pdev, | |||
452 | struct snd_soc_dai s3c24xx_i2s_dai = { | 459 | struct snd_soc_dai s3c24xx_i2s_dai = { |
453 | .name = "s3c24xx-i2s", | 460 | .name = "s3c24xx-i2s", |
454 | .id = 0, | 461 | .id = 0, |
455 | .type = SND_SOC_DAI_I2S, | ||
456 | .probe = s3c24xx_i2s_probe, | 462 | .probe = s3c24xx_i2s_probe, |
457 | .suspend = s3c24xx_i2s_suspend, | 463 | .suspend = s3c24xx_i2s_suspend, |
458 | .resume = s3c24xx_i2s_resume, | 464 | .resume = s3c24xx_i2s_resume, |
@@ -468,8 +474,7 @@ struct snd_soc_dai s3c24xx_i2s_dai = { | |||
468 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, | 474 | .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,}, |
469 | .ops = { | 475 | .ops = { |
470 | .trigger = s3c24xx_i2s_trigger, | 476 | .trigger = s3c24xx_i2s_trigger, |
471 | .hw_params = s3c24xx_i2s_hw_params,}, | 477 | .hw_params = s3c24xx_i2s_hw_params, |
472 | .dai_ops = { | ||
473 | .set_fmt = s3c24xx_i2s_set_fmt, | 478 | .set_fmt = s3c24xx_i2s_set_fmt, |
474 | .set_clkdiv = s3c24xx_i2s_set_clkdiv, | 479 | .set_clkdiv = s3c24xx_i2s_set_clkdiv, |
475 | .set_sysclk = s3c24xx_i2s_set_sysclk, | 480 | .set_sysclk = s3c24xx_i2s_set_sysclk, |
@@ -477,6 +482,18 @@ struct snd_soc_dai s3c24xx_i2s_dai = { | |||
477 | }; | 482 | }; |
478 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); | 483 | EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai); |
479 | 484 | ||
485 | static int __init s3c24xx_i2s_init(void) | ||
486 | { | ||
487 | return snd_soc_register_dai(&s3c24xx_i2s_dai); | ||
488 | } | ||
489 | module_init(s3c24xx_i2s_init); | ||
490 | |||
491 | static void __exit s3c24xx_i2s_exit(void) | ||
492 | { | ||
493 | snd_soc_unregister_dai(&s3c24xx_i2s_dai); | ||
494 | } | ||
495 | module_exit(s3c24xx_i2s_exit); | ||
496 | |||
480 | /* Module information */ | 497 | /* Module information */ |
481 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 498 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
482 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); | 499 | MODULE_DESCRIPTION("s3c24xx I2S SoC Interface"); |
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c index e13e614bada9..7c64d31d067e 100644 --- a/sound/soc/s3c24xx/s3c24xx-pcm.c +++ b/sound/soc/s3c24xx/s3c24xx-pcm.c | |||
@@ -465,6 +465,18 @@ struct snd_soc_platform s3c24xx_soc_platform = { | |||
465 | }; | 465 | }; |
466 | EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); | 466 | EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); |
467 | 467 | ||
468 | static int __init s3c24xx_soc_platform_init(void) | ||
469 | { | ||
470 | return snd_soc_register_platform(&s3c24xx_soc_platform); | ||
471 | } | ||
472 | module_init(s3c24xx_soc_platform_init); | ||
473 | |||
474 | static void __exit s3c24xx_soc_platform_exit(void) | ||
475 | { | ||
476 | snd_soc_unregister_platform(&s3c24xx_soc_platform); | ||
477 | } | ||
478 | module_exit(s3c24xx_soc_platform_exit); | ||
479 | |||
468 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 480 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
469 | MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); | 481 | MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); |
470 | MODULE_LICENSE("GPL"); | 482 | MODULE_LICENSE("GPL"); |
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c new file mode 100644 index 000000000000..a0a4d1832a14 --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c | |||
@@ -0,0 +1,373 @@ | |||
1 | /* | ||
2 | * Modifications by Christian Pellegrin <chripell@evolware.org> | ||
3 | * | ||
4 | * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver | ||
5 | * | ||
6 | * Copyright 2007 Dension Audio Systems Ltd. | ||
7 | * Author: Zoltan Devai | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/clk.h> | ||
16 | #include <linux/mutex.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <sound/pcm.h> | ||
19 | #include <sound/pcm_params.h> | ||
20 | #include <sound/soc.h> | ||
21 | #include <sound/soc-dapm.h> | ||
22 | #include <sound/s3c24xx_uda134x.h> | ||
23 | #include <sound/uda134x.h> | ||
24 | |||
25 | #include <asm/plat-s3c24xx/regs-iis.h> | ||
26 | |||
27 | #include "s3c24xx-pcm.h" | ||
28 | #include "s3c24xx-i2s.h" | ||
29 | #include "../codecs/uda134x.h" | ||
30 | |||
31 | |||
32 | /* #define ENFORCE_RATES 1 */ | ||
33 | /* | ||
34 | Unfortunately the S3C24XX in master mode has a limited capacity of | ||
35 | generating the clock for the codec. If you define this only rates | ||
36 | that are really available will be enforced. But be careful, most | ||
37 | user level application just want the usual sampling frequencies (8, | ||
38 | 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly | ||
39 | operation for embedded systems. So if you aren't very lucky or your | ||
40 | hardware engineer wasn't very forward-looking it's better to leave | ||
41 | this undefined. If you do so an approximate value for the requested | ||
42 | sampling rate in the range -/+ 5% will be chosen. If this in not | ||
43 | possible an error will be returned. | ||
44 | */ | ||
45 | |||
46 | static struct clk *xtal; | ||
47 | static struct clk *pclk; | ||
48 | /* this is need because we don't have a place where to keep the | ||
49 | * pointers to the clocks in each substream. We get the clocks only | ||
50 | * when we are actually using them so we don't block stuff like | ||
51 | * frequency change or oscillator power-off */ | ||
52 | static int clk_users; | ||
53 | static DEFINE_MUTEX(clk_lock); | ||
54 | |||
55 | static unsigned int rates[33 * 2]; | ||
56 | #ifdef ENFORCE_RATES | ||
57 | static struct snd_pcm_hw_constraint_list hw_constraints_rates = { | ||
58 | .count = ARRAY_SIZE(rates), | ||
59 | .list = rates, | ||
60 | .mask = 0, | ||
61 | }; | ||
62 | #endif | ||
63 | |||
64 | static struct platform_device *s3c24xx_uda134x_snd_device; | ||
65 | |||
66 | static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream) | ||
67 | { | ||
68 | int ret = 0; | ||
69 | #ifdef ENFORCE_RATES | ||
70 | struct snd_pcm_runtime *runtime = substream->runtime;; | ||
71 | #endif | ||
72 | |||
73 | mutex_lock(&clk_lock); | ||
74 | pr_debug("%s %d\n", __func__, clk_users); | ||
75 | if (clk_users == 0) { | ||
76 | xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal"); | ||
77 | if (!xtal) { | ||
78 | printk(KERN_ERR "%s cannot get xtal\n", __func__); | ||
79 | ret = -EBUSY; | ||
80 | } else { | ||
81 | pclk = clk_get(&s3c24xx_uda134x_snd_device->dev, | ||
82 | "pclk"); | ||
83 | if (!pclk) { | ||
84 | printk(KERN_ERR "%s cannot get pclk\n", | ||
85 | __func__); | ||
86 | clk_put(xtal); | ||
87 | ret = -EBUSY; | ||
88 | } | ||
89 | } | ||
90 | if (!ret) { | ||
91 | int i, j; | ||
92 | |||
93 | for (i = 0; i < 2; i++) { | ||
94 | int fs = i ? 256 : 384; | ||
95 | |||
96 | rates[i*33] = clk_get_rate(xtal) / fs; | ||
97 | for (j = 1; j < 33; j++) | ||
98 | rates[i*33 + j] = clk_get_rate(pclk) / | ||
99 | (j * fs); | ||
100 | } | ||
101 | } | ||
102 | } | ||
103 | clk_users += 1; | ||
104 | mutex_unlock(&clk_lock); | ||
105 | if (!ret) { | ||
106 | #ifdef ENFORCE_RATES | ||
107 | ret = snd_pcm_hw_constraint_list(runtime, 0, | ||
108 | SNDRV_PCM_HW_PARAM_RATE, | ||
109 | &hw_constraints_rates); | ||
110 | if (ret < 0) | ||
111 | printk(KERN_ERR "%s cannot set constraints\n", | ||
112 | __func__); | ||
113 | #endif | ||
114 | } | ||
115 | return ret; | ||
116 | } | ||
117 | |||
118 | static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream) | ||
119 | { | ||
120 | mutex_lock(&clk_lock); | ||
121 | pr_debug("%s %d\n", __func__, clk_users); | ||
122 | clk_users -= 1; | ||
123 | if (clk_users == 0) { | ||
124 | clk_put(xtal); | ||
125 | xtal = NULL; | ||
126 | clk_put(pclk); | ||
127 | pclk = NULL; | ||
128 | } | ||
129 | mutex_unlock(&clk_lock); | ||
130 | } | ||
131 | |||
132 | static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream, | ||
133 | struct snd_pcm_hw_params *params) | ||
134 | { | ||
135 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
136 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
137 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
138 | unsigned int clk = 0; | ||
139 | int ret = 0; | ||
140 | int clk_source, fs_mode; | ||
141 | unsigned long rate = params_rate(params); | ||
142 | long err, cerr; | ||
143 | unsigned int div; | ||
144 | int i, bi; | ||
145 | |||
146 | err = 999999; | ||
147 | bi = 0; | ||
148 | for (i = 0; i < 2*33; i++) { | ||
149 | cerr = rates[i] - rate; | ||
150 | if (cerr < 0) | ||
151 | cerr = -cerr; | ||
152 | if (cerr < err) { | ||
153 | err = cerr; | ||
154 | bi = i; | ||
155 | } | ||
156 | } | ||
157 | if (bi / 33 == 1) | ||
158 | fs_mode = S3C2410_IISMOD_256FS; | ||
159 | else | ||
160 | fs_mode = S3C2410_IISMOD_384FS; | ||
161 | if (bi % 33 == 0) { | ||
162 | clk_source = S3C24XX_CLKSRC_MPLL; | ||
163 | div = 1; | ||
164 | } else { | ||
165 | clk_source = S3C24XX_CLKSRC_PCLK; | ||
166 | div = bi % 33; | ||
167 | } | ||
168 | pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi); | ||
169 | |||
170 | clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate; | ||
171 | pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__, | ||
172 | fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS", | ||
173 | clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK", | ||
174 | div, clk, err); | ||
175 | |||
176 | if ((err * 100 / rate) > 5) { | ||
177 | printk(KERN_ERR "S3C24XX_UDA134X: effective frequency " | ||
178 | "too different from desired (%ld%%)\n", | ||
179 | err * 100 / rate); | ||
180 | return -EINVAL; | ||
181 | } | ||
182 | |||
183 | ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S | | ||
184 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
185 | if (ret < 0) | ||
186 | return ret; | ||
187 | |||
188 | ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S | | ||
189 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
190 | if (ret < 0) | ||
191 | return ret; | ||
192 | |||
193 | ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk, | ||
194 | SND_SOC_CLOCK_IN); | ||
195 | if (ret < 0) | ||
196 | return ret; | ||
197 | |||
198 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode); | ||
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | |||
202 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK, | ||
203 | S3C2410_IISMOD_32FS); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, | ||
208 | S3C24XX_PRESCALE(div, div)); | ||
209 | if (ret < 0) | ||
210 | return ret; | ||
211 | |||
212 | /* set the codec system clock for DAC and ADC */ | ||
213 | ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, | ||
214 | SND_SOC_CLOCK_OUT); | ||
215 | if (ret < 0) | ||
216 | return ret; | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static struct snd_soc_ops s3c24xx_uda134x_ops = { | ||
222 | .startup = s3c24xx_uda134x_startup, | ||
223 | .shutdown = s3c24xx_uda134x_shutdown, | ||
224 | .hw_params = s3c24xx_uda134x_hw_params, | ||
225 | }; | ||
226 | |||
227 | static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = { | ||
228 | .name = "UDA134X", | ||
229 | .stream_name = "UDA134X", | ||
230 | .codec_dai = &uda134x_dai, | ||
231 | .cpu_dai = &s3c24xx_i2s_dai, | ||
232 | .ops = &s3c24xx_uda134x_ops, | ||
233 | }; | ||
234 | |||
235 | static struct snd_soc_card snd_soc_s3c24xx_uda134x = { | ||
236 | .name = "S3C24XX_UDA134X", | ||
237 | .platform = &s3c24xx_soc_platform, | ||
238 | .dai_link = &s3c24xx_uda134x_dai_link, | ||
239 | .num_links = 1, | ||
240 | }; | ||
241 | |||
242 | static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins; | ||
243 | |||
244 | static void setdat(int v) | ||
245 | { | ||
246 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0); | ||
247 | } | ||
248 | |||
249 | static void setclk(int v) | ||
250 | { | ||
251 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0); | ||
252 | } | ||
253 | |||
254 | static void setmode(int v) | ||
255 | { | ||
256 | gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0); | ||
257 | } | ||
258 | |||
259 | static struct uda134x_platform_data s3c24xx_uda134x = { | ||
260 | .l3 = { | ||
261 | .setdat = setdat, | ||
262 | .setclk = setclk, | ||
263 | .setmode = setmode, | ||
264 | .data_hold = 1, | ||
265 | .data_setup = 1, | ||
266 | .clock_high = 1, | ||
267 | .mode_hold = 1, | ||
268 | .mode = 1, | ||
269 | .mode_setup = 1, | ||
270 | }, | ||
271 | }; | ||
272 | |||
273 | static struct snd_soc_device s3c24xx_uda134x_snd_devdata = { | ||
274 | .card = &snd_soc_s3c24xx_uda134x, | ||
275 | .codec_dev = &soc_codec_dev_uda134x, | ||
276 | .codec_data = &s3c24xx_uda134x, | ||
277 | }; | ||
278 | |||
279 | static int s3c24xx_uda134x_setup_pin(int pin, char *fun) | ||
280 | { | ||
281 | if (gpio_request(pin, "s3c24xx_uda134x") < 0) { | ||
282 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " | ||
283 | "l3 %s pin already in use", fun); | ||
284 | return -EBUSY; | ||
285 | } | ||
286 | gpio_direction_output(pin, 0); | ||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int s3c24xx_uda134x_probe(struct platform_device *pdev) | ||
291 | { | ||
292 | int ret; | ||
293 | |||
294 | printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n"); | ||
295 | |||
296 | s3c24xx_uda134x_l3_pins = pdev->dev.platform_data; | ||
297 | if (s3c24xx_uda134x_l3_pins == NULL) { | ||
298 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " | ||
299 | "unable to find platform data\n"); | ||
300 | return -ENODEV; | ||
301 | } | ||
302 | s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power; | ||
303 | s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model; | ||
304 | |||
305 | if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data, | ||
306 | "data") < 0) | ||
307 | return -EBUSY; | ||
308 | if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk, | ||
309 | "clk") < 0) { | ||
310 | gpio_free(s3c24xx_uda134x_l3_pins->l3_data); | ||
311 | return -EBUSY; | ||
312 | } | ||
313 | if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode, | ||
314 | "mode") < 0) { | ||
315 | gpio_free(s3c24xx_uda134x_l3_pins->l3_data); | ||
316 | gpio_free(s3c24xx_uda134x_l3_pins->l3_clk); | ||
317 | return -EBUSY; | ||
318 | } | ||
319 | |||
320 | s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1); | ||
321 | if (!s3c24xx_uda134x_snd_device) { | ||
322 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: " | ||
323 | "Unable to register\n"); | ||
324 | return -ENOMEM; | ||
325 | } | ||
326 | |||
327 | platform_set_drvdata(s3c24xx_uda134x_snd_device, | ||
328 | &s3c24xx_uda134x_snd_devdata); | ||
329 | s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev; | ||
330 | ret = platform_device_add(s3c24xx_uda134x_snd_device); | ||
331 | if (ret) { | ||
332 | printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n"); | ||
333 | platform_device_put(s3c24xx_uda134x_snd_device); | ||
334 | } | ||
335 | |||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | static int s3c24xx_uda134x_remove(struct platform_device *pdev) | ||
340 | { | ||
341 | platform_device_unregister(s3c24xx_uda134x_snd_device); | ||
342 | gpio_free(s3c24xx_uda134x_l3_pins->l3_data); | ||
343 | gpio_free(s3c24xx_uda134x_l3_pins->l3_clk); | ||
344 | gpio_free(s3c24xx_uda134x_l3_pins->l3_mode); | ||
345 | return 0; | ||
346 | } | ||
347 | |||
348 | static struct platform_driver s3c24xx_uda134x_driver = { | ||
349 | .probe = s3c24xx_uda134x_probe, | ||
350 | .remove = s3c24xx_uda134x_remove, | ||
351 | .driver = { | ||
352 | .name = "s3c24xx_uda134x", | ||
353 | .owner = THIS_MODULE, | ||
354 | }, | ||
355 | }; | ||
356 | |||
357 | static int __init s3c24xx_uda134x_init(void) | ||
358 | { | ||
359 | return platform_driver_register(&s3c24xx_uda134x_driver); | ||
360 | } | ||
361 | |||
362 | static void __exit s3c24xx_uda134x_exit(void) | ||
363 | { | ||
364 | platform_driver_unregister(&s3c24xx_uda134x_driver); | ||
365 | } | ||
366 | |||
367 | |||
368 | module_init(s3c24xx_uda134x_init); | ||
369 | module_exit(s3c24xx_uda134x_exit); | ||
370 | |||
371 | MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); | ||
372 | MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver"); | ||
373 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c index 8515d6ff03f2..a2a4f5323c17 100644 --- a/sound/soc/s3c24xx/smdk2443_wm9710.c +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include "s3c24xx-pcm.h" | 23 | #include "s3c24xx-pcm.h" |
24 | #include "s3c24xx-ac97.h" | 24 | #include "s3c24xx-ac97.h" |
25 | 25 | ||
26 | static struct snd_soc_machine smdk2443; | 26 | static struct snd_soc_card smdk2443; |
27 | 27 | ||
28 | static struct snd_soc_dai_link smdk2443_dai[] = { | 28 | static struct snd_soc_dai_link smdk2443_dai[] = { |
29 | { | 29 | { |
@@ -34,15 +34,15 @@ static struct snd_soc_dai_link smdk2443_dai[] = { | |||
34 | }, | 34 | }, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static struct snd_soc_machine smdk2443 = { | 37 | static struct snd_soc_card smdk2443 = { |
38 | .name = "SMDK2443", | 38 | .name = "SMDK2443", |
39 | .platform = &s3c24xx_soc_platform, | ||
39 | .dai_link = smdk2443_dai, | 40 | .dai_link = smdk2443_dai, |
40 | .num_links = ARRAY_SIZE(smdk2443_dai), | 41 | .num_links = ARRAY_SIZE(smdk2443_dai), |
41 | }; | 42 | }; |
42 | 43 | ||
43 | static struct snd_soc_device smdk2443_snd_ac97_devdata = { | 44 | static struct snd_soc_device smdk2443_snd_ac97_devdata = { |
44 | .machine = &smdk2443, | 45 | .card = &smdk2443, |
45 | .platform = &s3c24xx_soc_platform, | ||
46 | .codec_dev = &soc_codec_dev_ac97, | 46 | .codec_dev = &soc_codec_dev_ac97, |
47 | }; | 47 | }; |
48 | 48 | ||
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index 9faa12622d09..0dad3a0bb920 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -348,6 +348,18 @@ struct snd_soc_platform sh7760_soc_platform = { | |||
348 | }; | 348 | }; |
349 | EXPORT_SYMBOL_GPL(sh7760_soc_platform); | 349 | EXPORT_SYMBOL_GPL(sh7760_soc_platform); |
350 | 350 | ||
351 | static int __init sh7760_soc_platform_init(void) | ||
352 | { | ||
353 | return snd_soc_register_platform(&sh7760_soc_platform); | ||
354 | } | ||
355 | module_init(sh7760_soc_platform_init); | ||
356 | |||
357 | static void __exit sh7760_soc_platform_exit(void) | ||
358 | { | ||
359 | snd_soc_unregister_platform(&sh7760_soc_platform); | ||
360 | } | ||
361 | module_exit(sh7760_soc_platform_exit); | ||
362 | |||
351 | MODULE_LICENSE("GPL"); | 363 | MODULE_LICENSE("GPL"); |
352 | MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); | 364 | MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); |
353 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | 365 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index df7bc345c320..eab31838badf 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -236,7 +236,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = { | |||
236 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 236 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
237 | 237 | ||
238 | static int hac_hw_params(struct snd_pcm_substream *substream, | 238 | static int hac_hw_params(struct snd_pcm_substream *substream, |
239 | struct snd_pcm_hw_params *params) | 239 | struct snd_pcm_hw_params *params, |
240 | struct snd_soc_dai *dai) | ||
240 | { | 241 | { |
241 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 242 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
242 | struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; | 243 | struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; |
@@ -270,7 +271,7 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
270 | { | 271 | { |
271 | .name = "HAC0", | 272 | .name = "HAC0", |
272 | .id = 0, | 273 | .id = 0, |
273 | .type = SND_SOC_DAI_AC97, | 274 | .ac97_control = 1, |
274 | .playback = { | 275 | .playback = { |
275 | .rates = AC97_RATES, | 276 | .rates = AC97_RATES, |
276 | .formats = AC97_FMTS, | 277 | .formats = AC97_FMTS, |
@@ -290,8 +291,8 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
290 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | 291 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 |
291 | { | 292 | { |
292 | .name = "HAC1", | 293 | .name = "HAC1", |
294 | .ac97_control = 1, | ||
293 | .id = 1, | 295 | .id = 1, |
294 | .type = SND_SOC_DAI_AC97, | ||
295 | .playback = { | 296 | .playback = { |
296 | .rates = AC97_RATES, | 297 | .rates = AC97_RATES, |
297 | .formats = AC97_FMTS, | 298 | .formats = AC97_FMTS, |
@@ -313,6 +314,18 @@ struct snd_soc_dai sh4_hac_dai[] = { | |||
313 | }; | 314 | }; |
314 | EXPORT_SYMBOL_GPL(sh4_hac_dai); | 315 | EXPORT_SYMBOL_GPL(sh4_hac_dai); |
315 | 316 | ||
317 | static int __init sh4_hac_init(void) | ||
318 | { | ||
319 | return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | ||
320 | } | ||
321 | module_init(sh4_hac_init); | ||
322 | |||
323 | static void __exit sh4_hac_exit(void) | ||
324 | { | ||
325 | snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | ||
326 | } | ||
327 | module_exit(sh4_hac_exit); | ||
328 | |||
316 | MODULE_LICENSE("GPL"); | 329 | MODULE_LICENSE("GPL"); |
317 | MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); | 330 | MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); |
318 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | 331 | 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 92bfaf4774a7..ce7f95b59de3 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 = { | |||
38 | .ops = NULL, | 38 | .ops = NULL, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | static struct snd_soc_machine sh7760_ac97_soc_machine = { | 41 | static struct snd_soc_card sh7760_ac97_soc_machine = { |
42 | .name = "SH7760 AC97", | 42 | .name = "SH7760 AC97", |
43 | .platform = &sh7760_soc_platform, | ||
43 | .dai_link = &sh7760_ac97_dai, | 44 | .dai_link = &sh7760_ac97_dai, |
44 | .num_links = 1, | 45 | .num_links = 1, |
45 | }; | 46 | }; |
46 | 47 | ||
47 | static struct snd_soc_device sh7760_ac97_snd_devdata = { | 48 | static struct snd_soc_device sh7760_ac97_snd_devdata = { |
48 | .machine = &sh7760_ac97_soc_machine, | 49 | .card = &sh7760_ac97_soc_machine, |
49 | .platform = &sh7760_soc_platform, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | 50 | .codec_dev = &soc_codec_dev_ac97, |
51 | }; | 51 | }; |
52 | 52 | ||
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c index 55c3464163ab..d1e5390fddeb 100644 --- a/sound/soc/sh/ssi.c +++ b/sound/soc/sh/ssi.c | |||
@@ -89,7 +89,8 @@ struct ssi_priv { | |||
89 | * track usage of the SSI; it is simplex-only so prevent attempts of | 89 | * track usage of the SSI; it is simplex-only so prevent attempts of |
90 | * concurrent playback + capture. FIXME: any locking required? | 90 | * concurrent playback + capture. FIXME: any locking required? |
91 | */ | 91 | */ |
92 | static int ssi_startup(struct snd_pcm_substream *substream) | 92 | static int ssi_startup(struct snd_pcm_substream *substream, |
93 | struct snd_soc_dai *dai) | ||
93 | { | 94 | { |
94 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
95 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | 96 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; |
@@ -101,7 +102,8 @@ static int ssi_startup(struct snd_pcm_substream *substream) | |||
101 | return 0; | 102 | return 0; |
102 | } | 103 | } |
103 | 104 | ||
104 | static void ssi_shutdown(struct snd_pcm_substream *substream) | 105 | static void ssi_shutdown(struct snd_pcm_substream *substream, |
106 | struct snd_soc_dai *dai) | ||
105 | { | 107 | { |
106 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 108 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
107 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | 109 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; |
@@ -109,7 +111,8 @@ static void ssi_shutdown(struct snd_pcm_substream *substream) | |||
109 | ssi->inuse = 0; | 111 | ssi->inuse = 0; |
110 | } | 112 | } |
111 | 113 | ||
112 | static int ssi_trigger(struct snd_pcm_substream *substream, int cmd) | 114 | static int ssi_trigger(struct snd_pcm_substream *substream, int cmd, |
115 | struct snd_soc_dai *dai) | ||
113 | { | 116 | { |
114 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 117 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
115 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | 118 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; |
@@ -129,7 +132,8 @@ static int ssi_trigger(struct snd_pcm_substream *substream, int cmd) | |||
129 | } | 132 | } |
130 | 133 | ||
131 | static int ssi_hw_params(struct snd_pcm_substream *substream, | 134 | static int ssi_hw_params(struct snd_pcm_substream *substream, |
132 | struct snd_pcm_hw_params *params) | 135 | struct snd_pcm_hw_params *params, |
136 | struct snd_soc_dai *dai) | ||
133 | { | 137 | { |
134 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 138 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
135 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | 139 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; |
@@ -336,7 +340,6 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
336 | { | 340 | { |
337 | .name = "SSI0", | 341 | .name = "SSI0", |
338 | .id = 0, | 342 | .id = 0, |
339 | .type = SND_SOC_DAI_I2S, | ||
340 | .playback = { | 343 | .playback = { |
341 | .rates = SSI_RATES, | 344 | .rates = SSI_RATES, |
342 | .formats = SSI_FMTS, | 345 | .formats = SSI_FMTS, |
@@ -354,8 +357,6 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
354 | .shutdown = ssi_shutdown, | 357 | .shutdown = ssi_shutdown, |
355 | .trigger = ssi_trigger, | 358 | .trigger = ssi_trigger, |
356 | .hw_params = ssi_hw_params, | 359 | .hw_params = ssi_hw_params, |
357 | }, | ||
358 | .dai_ops = { | ||
359 | .set_sysclk = ssi_set_sysclk, | 360 | .set_sysclk = ssi_set_sysclk, |
360 | .set_clkdiv = ssi_set_clkdiv, | 361 | .set_clkdiv = ssi_set_clkdiv, |
361 | .set_fmt = ssi_set_fmt, | 362 | .set_fmt = ssi_set_fmt, |
@@ -365,7 +366,6 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
365 | { | 366 | { |
366 | .name = "SSI1", | 367 | .name = "SSI1", |
367 | .id = 1, | 368 | .id = 1, |
368 | .type = SND_SOC_DAI_I2S, | ||
369 | .playback = { | 369 | .playback = { |
370 | .rates = SSI_RATES, | 370 | .rates = SSI_RATES, |
371 | .formats = SSI_FMTS, | 371 | .formats = SSI_FMTS, |
@@ -383,8 +383,6 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
383 | .shutdown = ssi_shutdown, | 383 | .shutdown = ssi_shutdown, |
384 | .trigger = ssi_trigger, | 384 | .trigger = ssi_trigger, |
385 | .hw_params = ssi_hw_params, | 385 | .hw_params = ssi_hw_params, |
386 | }, | ||
387 | .dai_ops = { | ||
388 | .set_sysclk = ssi_set_sysclk, | 386 | .set_sysclk = ssi_set_sysclk, |
389 | .set_clkdiv = ssi_set_clkdiv, | 387 | .set_clkdiv = ssi_set_clkdiv, |
390 | .set_fmt = ssi_set_fmt, | 388 | .set_fmt = ssi_set_fmt, |
@@ -394,6 +392,18 @@ struct snd_soc_dai sh4_ssi_dai[] = { | |||
394 | }; | 392 | }; |
395 | EXPORT_SYMBOL_GPL(sh4_ssi_dai); | 393 | EXPORT_SYMBOL_GPL(sh4_ssi_dai); |
396 | 394 | ||
395 | static int __init sh4_ssi_init(void) | ||
396 | { | ||
397 | return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); | ||
398 | } | ||
399 | module_init(sh4_ssi_init); | ||
400 | |||
401 | static void __exit sh4_ssi_exit(void) | ||
402 | { | ||
403 | snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai)); | ||
404 | } | ||
405 | module_exit(sh4_ssi_exit); | ||
406 | |||
397 | MODULE_LICENSE("GPL"); | 407 | MODULE_LICENSE("GPL"); |
398 | MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); | 408 | MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); |
399 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | 409 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16c7453f4946..b098c0b4c584 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/debugfs.h> | ||
29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -34,18 +35,23 @@ | |||
34 | #include <sound/soc-dapm.h> | 35 | #include <sound/soc-dapm.h> |
35 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
36 | 37 | ||
37 | /* debug */ | ||
38 | #define SOC_DEBUG 0 | ||
39 | #if SOC_DEBUG | ||
40 | #define dbg(format, arg...) printk(format, ## arg) | ||
41 | #else | ||
42 | #define dbg(format, arg...) | ||
43 | #endif | ||
44 | |||
45 | static DEFINE_MUTEX(pcm_mutex); | 38 | static DEFINE_MUTEX(pcm_mutex); |
46 | static DEFINE_MUTEX(io_mutex); | 39 | static DEFINE_MUTEX(io_mutex); |
47 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 40 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
48 | 41 | ||
42 | #ifdef CONFIG_DEBUG_FS | ||
43 | static struct dentry *debugfs_root; | ||
44 | #endif | ||
45 | |||
46 | static DEFINE_MUTEX(client_mutex); | ||
47 | static LIST_HEAD(card_list); | ||
48 | static LIST_HEAD(dai_list); | ||
49 | static LIST_HEAD(platform_list); | ||
50 | static LIST_HEAD(codec_list); | ||
51 | |||
52 | static int snd_soc_register_card(struct snd_soc_card *card); | ||
53 | static int snd_soc_unregister_card(struct snd_soc_card *card); | ||
54 | |||
49 | /* | 55 | /* |
50 | * This is a timeout to do a DAPM powerdown after a stream is closed(). | 56 | * This is a timeout to do a DAPM powerdown after a stream is closed(). |
51 | * It can be used to eliminate pops between different playback streams, e.g. | 57 | * It can be used to eliminate pops between different playback streams, e.g. |
@@ -107,20 +113,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
107 | } | 113 | } |
108 | #endif | 114 | #endif |
109 | 115 | ||
110 | static inline const char *get_dai_name(int type) | ||
111 | { | ||
112 | switch (type) { | ||
113 | case SND_SOC_DAI_AC97_BUS: | ||
114 | case SND_SOC_DAI_AC97: | ||
115 | return "AC97"; | ||
116 | case SND_SOC_DAI_I2S: | ||
117 | return "I2S"; | ||
118 | case SND_SOC_DAI_PCM: | ||
119 | return "PCM"; | ||
120 | } | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | /* | 116 | /* |
125 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is | 117 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is |
126 | * then initialized and any private data can be allocated. This also calls | 118 | * then initialized and any private data can be allocated. This also calls |
@@ -130,9 +122,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
130 | { | 122 | { |
131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 123 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
132 | struct snd_soc_device *socdev = rtd->socdev; | 124 | struct snd_soc_device *socdev = rtd->socdev; |
125 | struct snd_soc_card *card = socdev->card; | ||
133 | struct snd_pcm_runtime *runtime = substream->runtime; | 126 | struct snd_pcm_runtime *runtime = substream->runtime; |
134 | struct snd_soc_dai_link *machine = rtd->dai; | 127 | struct snd_soc_dai_link *machine = rtd->dai; |
135 | struct snd_soc_platform *platform = socdev->platform; | 128 | struct snd_soc_platform *platform = card->platform; |
136 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 129 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
137 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 130 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
138 | int ret = 0; | 131 | int ret = 0; |
@@ -141,7 +134,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
141 | 134 | ||
142 | /* startup the audio subsystem */ | 135 | /* startup the audio subsystem */ |
143 | if (cpu_dai->ops.startup) { | 136 | if (cpu_dai->ops.startup) { |
144 | ret = cpu_dai->ops.startup(substream); | 137 | ret = cpu_dai->ops.startup(substream, cpu_dai); |
145 | if (ret < 0) { | 138 | if (ret < 0) { |
146 | printk(KERN_ERR "asoc: can't open interface %s\n", | 139 | printk(KERN_ERR "asoc: can't open interface %s\n", |
147 | cpu_dai->name); | 140 | cpu_dai->name); |
@@ -158,7 +151,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
158 | } | 151 | } |
159 | 152 | ||
160 | if (codec_dai->ops.startup) { | 153 | if (codec_dai->ops.startup) { |
161 | ret = codec_dai->ops.startup(substream); | 154 | ret = codec_dai->ops.startup(substream, codec_dai); |
162 | if (ret < 0) { | 155 | if (ret < 0) { |
163 | printk(KERN_ERR "asoc: can't open codec %s\n", | 156 | printk(KERN_ERR "asoc: can't open codec %s\n", |
164 | codec_dai->name); | 157 | codec_dai->name); |
@@ -228,12 +221,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
228 | goto machine_err; | 221 | goto machine_err; |
229 | } | 222 | } |
230 | 223 | ||
231 | dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); | 224 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); |
232 | dbg("asoc: rate mask 0x%x\n", runtime->hw.rates); | 225 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); |
233 | dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, | 226 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, |
234 | runtime->hw.channels_max); | 227 | runtime->hw.channels_max); |
235 | dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, | 228 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, |
236 | runtime->hw.rate_max); | 229 | runtime->hw.rate_max); |
237 | 230 | ||
238 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 231 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
239 | cpu_dai->playback.active = codec_dai->playback.active = 1; | 232 | cpu_dai->playback.active = codec_dai->playback.active = 1; |
@@ -255,7 +248,7 @@ codec_dai_err: | |||
255 | 248 | ||
256 | platform_err: | 249 | platform_err: |
257 | if (cpu_dai->ops.shutdown) | 250 | if (cpu_dai->ops.shutdown) |
258 | cpu_dai->ops.shutdown(substream); | 251 | cpu_dai->ops.shutdown(substream, cpu_dai); |
259 | out: | 252 | out: |
260 | mutex_unlock(&pcm_mutex); | 253 | mutex_unlock(&pcm_mutex); |
261 | return ret; | 254 | return ret; |
@@ -268,8 +261,9 @@ out: | |||
268 | */ | 261 | */ |
269 | static void close_delayed_work(struct work_struct *work) | 262 | static void close_delayed_work(struct work_struct *work) |
270 | { | 263 | { |
271 | struct snd_soc_device *socdev = | 264 | struct snd_soc_card *card = container_of(work, struct snd_soc_card, |
272 | container_of(work, struct snd_soc_device, delayed_work.work); | 265 | delayed_work.work); |
266 | struct snd_soc_device *socdev = card->socdev; | ||
273 | struct snd_soc_codec *codec = socdev->codec; | 267 | struct snd_soc_codec *codec = socdev->codec; |
274 | struct snd_soc_dai *codec_dai; | 268 | struct snd_soc_dai *codec_dai; |
275 | int i; | 269 | int i; |
@@ -278,18 +272,18 @@ static void close_delayed_work(struct work_struct *work) | |||
278 | for (i = 0; i < codec->num_dai; i++) { | 272 | for (i = 0; i < codec->num_dai; i++) { |
279 | codec_dai = &codec->dai[i]; | 273 | codec_dai = &codec->dai[i]; |
280 | 274 | ||
281 | dbg("pop wq checking: %s status: %s waiting: %s\n", | 275 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", |
282 | codec_dai->playback.stream_name, | 276 | codec_dai->playback.stream_name, |
283 | codec_dai->playback.active ? "active" : "inactive", | 277 | codec_dai->playback.active ? "active" : "inactive", |
284 | codec_dai->pop_wait ? "yes" : "no"); | 278 | codec_dai->pop_wait ? "yes" : "no"); |
285 | 279 | ||
286 | /* are we waiting on this codec DAI stream */ | 280 | /* are we waiting on this codec DAI stream */ |
287 | if (codec_dai->pop_wait == 1) { | 281 | if (codec_dai->pop_wait == 1) { |
288 | 282 | ||
289 | /* Reduce power if no longer active */ | 283 | /* Reduce power if no longer active */ |
290 | if (codec->active == 0) { | 284 | if (codec->active == 0) { |
291 | dbg("pop wq D1 %s %s\n", codec->name, | 285 | pr_debug("pop wq D1 %s %s\n", codec->name, |
292 | codec_dai->playback.stream_name); | 286 | codec_dai->playback.stream_name); |
293 | snd_soc_dapm_set_bias_level(socdev, | 287 | snd_soc_dapm_set_bias_level(socdev, |
294 | SND_SOC_BIAS_PREPARE); | 288 | SND_SOC_BIAS_PREPARE); |
295 | } | 289 | } |
@@ -301,8 +295,8 @@ static void close_delayed_work(struct work_struct *work) | |||
301 | 295 | ||
302 | /* Fall into standby if no longer active */ | 296 | /* Fall into standby if no longer active */ |
303 | if (codec->active == 0) { | 297 | if (codec->active == 0) { |
304 | dbg("pop wq D3 %s %s\n", codec->name, | 298 | pr_debug("pop wq D3 %s %s\n", codec->name, |
305 | codec_dai->playback.stream_name); | 299 | codec_dai->playback.stream_name); |
306 | snd_soc_dapm_set_bias_level(socdev, | 300 | snd_soc_dapm_set_bias_level(socdev, |
307 | SND_SOC_BIAS_STANDBY); | 301 | SND_SOC_BIAS_STANDBY); |
308 | } | 302 | } |
@@ -320,8 +314,9 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
320 | { | 314 | { |
321 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
322 | struct snd_soc_device *socdev = rtd->socdev; | 316 | struct snd_soc_device *socdev = rtd->socdev; |
317 | struct snd_soc_card *card = socdev->card; | ||
323 | struct snd_soc_dai_link *machine = rtd->dai; | 318 | struct snd_soc_dai_link *machine = rtd->dai; |
324 | struct snd_soc_platform *platform = socdev->platform; | 319 | struct snd_soc_platform *platform = card->platform; |
325 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 320 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
326 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 321 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
327 | struct snd_soc_codec *codec = socdev->codec; | 322 | struct snd_soc_codec *codec = socdev->codec; |
@@ -346,10 +341,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
346 | snd_soc_dai_digital_mute(codec_dai, 1); | 341 | snd_soc_dai_digital_mute(codec_dai, 1); |
347 | 342 | ||
348 | if (cpu_dai->ops.shutdown) | 343 | if (cpu_dai->ops.shutdown) |
349 | cpu_dai->ops.shutdown(substream); | 344 | cpu_dai->ops.shutdown(substream, cpu_dai); |
350 | 345 | ||
351 | if (codec_dai->ops.shutdown) | 346 | if (codec_dai->ops.shutdown) |
352 | codec_dai->ops.shutdown(substream); | 347 | codec_dai->ops.shutdown(substream, codec_dai); |
353 | 348 | ||
354 | if (machine->ops && machine->ops->shutdown) | 349 | if (machine->ops && machine->ops->shutdown) |
355 | machine->ops->shutdown(substream); | 350 | machine->ops->shutdown(substream); |
@@ -361,7 +356,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
361 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 356 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
362 | /* start delayed pop wq here for playback streams */ | 357 | /* start delayed pop wq here for playback streams */ |
363 | codec_dai->pop_wait = 1; | 358 | codec_dai->pop_wait = 1; |
364 | schedule_delayed_work(&socdev->delayed_work, | 359 | schedule_delayed_work(&card->delayed_work, |
365 | msecs_to_jiffies(pmdown_time)); | 360 | msecs_to_jiffies(pmdown_time)); |
366 | } else { | 361 | } else { |
367 | /* capture streams can be powered down now */ | 362 | /* capture streams can be powered down now */ |
@@ -387,8 +382,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
387 | { | 382 | { |
388 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 383 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
389 | struct snd_soc_device *socdev = rtd->socdev; | 384 | struct snd_soc_device *socdev = rtd->socdev; |
385 | struct snd_soc_card *card = socdev->card; | ||
390 | struct snd_soc_dai_link *machine = rtd->dai; | 386 | struct snd_soc_dai_link *machine = rtd->dai; |
391 | struct snd_soc_platform *platform = socdev->platform; | 387 | struct snd_soc_platform *platform = card->platform; |
392 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 388 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
393 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 389 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
394 | struct snd_soc_codec *codec = socdev->codec; | 390 | struct snd_soc_codec *codec = socdev->codec; |
@@ -413,7 +409,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
413 | } | 409 | } |
414 | 410 | ||
415 | if (codec_dai->ops.prepare) { | 411 | if (codec_dai->ops.prepare) { |
416 | ret = codec_dai->ops.prepare(substream); | 412 | ret = codec_dai->ops.prepare(substream, codec_dai); |
417 | if (ret < 0) { | 413 | if (ret < 0) { |
418 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | 414 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); |
419 | goto out; | 415 | goto out; |
@@ -421,58 +417,49 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
421 | } | 417 | } |
422 | 418 | ||
423 | if (cpu_dai->ops.prepare) { | 419 | if (cpu_dai->ops.prepare) { |
424 | ret = cpu_dai->ops.prepare(substream); | 420 | ret = cpu_dai->ops.prepare(substream, cpu_dai); |
425 | if (ret < 0) { | 421 | if (ret < 0) { |
426 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | 422 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); |
427 | goto out; | 423 | goto out; |
428 | } | 424 | } |
429 | } | 425 | } |
430 | 426 | ||
431 | /* we only want to start a DAPM playback stream if we are not waiting | 427 | /* cancel any delayed stream shutdown that is pending */ |
432 | * on an existing one stopping */ | 428 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
433 | if (codec_dai->pop_wait) { | 429 | codec_dai->pop_wait) { |
434 | /* we are waiting for the delayed work to start */ | 430 | codec_dai->pop_wait = 0; |
435 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 431 | cancel_delayed_work(&card->delayed_work); |
436 | snd_soc_dapm_stream_event(socdev->codec, | 432 | } |
437 | codec_dai->capture.stream_name, | ||
438 | SND_SOC_DAPM_STREAM_START); | ||
439 | else { | ||
440 | codec_dai->pop_wait = 0; | ||
441 | cancel_delayed_work(&socdev->delayed_work); | ||
442 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
443 | } | ||
444 | } else { | ||
445 | /* no delayed work - do we need to power up codec */ | ||
446 | if (codec->bias_level != SND_SOC_BIAS_ON) { | ||
447 | 433 | ||
448 | snd_soc_dapm_set_bias_level(socdev, | 434 | /* do we need to power up codec */ |
449 | SND_SOC_BIAS_PREPARE); | 435 | if (codec->bias_level != SND_SOC_BIAS_ON) { |
436 | snd_soc_dapm_set_bias_level(socdev, | ||
437 | SND_SOC_BIAS_PREPARE); | ||
450 | 438 | ||
451 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 439 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
452 | snd_soc_dapm_stream_event(codec, | 440 | snd_soc_dapm_stream_event(codec, |
453 | codec_dai->playback.stream_name, | 441 | codec_dai->playback.stream_name, |
454 | SND_SOC_DAPM_STREAM_START); | 442 | SND_SOC_DAPM_STREAM_START); |
455 | else | 443 | else |
456 | snd_soc_dapm_stream_event(codec, | 444 | snd_soc_dapm_stream_event(codec, |
457 | codec_dai->capture.stream_name, | 445 | codec_dai->capture.stream_name, |
458 | SND_SOC_DAPM_STREAM_START); | 446 | SND_SOC_DAPM_STREAM_START); |
459 | 447 | ||
460 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON); | 448 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON); |
461 | snd_soc_dai_digital_mute(codec_dai, 0); | 449 | snd_soc_dai_digital_mute(codec_dai, 0); |
462 | 450 | ||
463 | } else { | 451 | } else { |
464 | /* codec already powered - power on widgets */ | 452 | /* codec already powered - power on widgets */ |
465 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 453 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
466 | snd_soc_dapm_stream_event(codec, | 454 | snd_soc_dapm_stream_event(codec, |
467 | codec_dai->playback.stream_name, | 455 | codec_dai->playback.stream_name, |
468 | SND_SOC_DAPM_STREAM_START); | 456 | SND_SOC_DAPM_STREAM_START); |
469 | else | 457 | else |
470 | snd_soc_dapm_stream_event(codec, | 458 | snd_soc_dapm_stream_event(codec, |
471 | codec_dai->capture.stream_name, | 459 | codec_dai->capture.stream_name, |
472 | SND_SOC_DAPM_STREAM_START); | 460 | SND_SOC_DAPM_STREAM_START); |
473 | 461 | ||
474 | snd_soc_dai_digital_mute(codec_dai, 0); | 462 | snd_soc_dai_digital_mute(codec_dai, 0); |
475 | } | ||
476 | } | 463 | } |
477 | 464 | ||
478 | out: | 465 | out: |
@@ -491,7 +478,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
491 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 478 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
492 | struct snd_soc_device *socdev = rtd->socdev; | 479 | struct snd_soc_device *socdev = rtd->socdev; |
493 | struct snd_soc_dai_link *machine = rtd->dai; | 480 | struct snd_soc_dai_link *machine = rtd->dai; |
494 | struct snd_soc_platform *platform = socdev->platform; | 481 | struct snd_soc_card *card = socdev->card; |
482 | struct snd_soc_platform *platform = card->platform; | ||
495 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 483 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
496 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 484 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
497 | int ret = 0; | 485 | int ret = 0; |
@@ -507,7 +495,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
507 | } | 495 | } |
508 | 496 | ||
509 | if (codec_dai->ops.hw_params) { | 497 | if (codec_dai->ops.hw_params) { |
510 | ret = codec_dai->ops.hw_params(substream, params); | 498 | ret = codec_dai->ops.hw_params(substream, params, codec_dai); |
511 | if (ret < 0) { | 499 | if (ret < 0) { |
512 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | 500 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", |
513 | codec_dai->name); | 501 | codec_dai->name); |
@@ -516,7 +504,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
516 | } | 504 | } |
517 | 505 | ||
518 | if (cpu_dai->ops.hw_params) { | 506 | if (cpu_dai->ops.hw_params) { |
519 | ret = cpu_dai->ops.hw_params(substream, params); | 507 | ret = cpu_dai->ops.hw_params(substream, params, cpu_dai); |
520 | if (ret < 0) { | 508 | if (ret < 0) { |
521 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | 509 | printk(KERN_ERR "asoc: interface %s hw params failed\n", |
522 | cpu_dai->name); | 510 | cpu_dai->name); |
@@ -539,11 +527,11 @@ out: | |||
539 | 527 | ||
540 | platform_err: | 528 | platform_err: |
541 | if (cpu_dai->ops.hw_free) | 529 | if (cpu_dai->ops.hw_free) |
542 | cpu_dai->ops.hw_free(substream); | 530 | cpu_dai->ops.hw_free(substream, cpu_dai); |
543 | 531 | ||
544 | interface_err: | 532 | interface_err: |
545 | if (codec_dai->ops.hw_free) | 533 | if (codec_dai->ops.hw_free) |
546 | codec_dai->ops.hw_free(substream); | 534 | codec_dai->ops.hw_free(substream, codec_dai); |
547 | 535 | ||
548 | codec_err: | 536 | codec_err: |
549 | if (machine->ops && machine->ops->hw_free) | 537 | if (machine->ops && machine->ops->hw_free) |
@@ -561,7 +549,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
561 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 549 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
562 | struct snd_soc_device *socdev = rtd->socdev; | 550 | struct snd_soc_device *socdev = rtd->socdev; |
563 | struct snd_soc_dai_link *machine = rtd->dai; | 551 | struct snd_soc_dai_link *machine = rtd->dai; |
564 | struct snd_soc_platform *platform = socdev->platform; | 552 | struct snd_soc_card *card = socdev->card; |
553 | struct snd_soc_platform *platform = card->platform; | ||
565 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 554 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
566 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 555 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
567 | struct snd_soc_codec *codec = socdev->codec; | 556 | struct snd_soc_codec *codec = socdev->codec; |
@@ -582,10 +571,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
582 | 571 | ||
583 | /* now free hw params for the DAI's */ | 572 | /* now free hw params for the DAI's */ |
584 | if (codec_dai->ops.hw_free) | 573 | if (codec_dai->ops.hw_free) |
585 | codec_dai->ops.hw_free(substream); | 574 | codec_dai->ops.hw_free(substream, codec_dai); |
586 | 575 | ||
587 | if (cpu_dai->ops.hw_free) | 576 | if (cpu_dai->ops.hw_free) |
588 | cpu_dai->ops.hw_free(substream); | 577 | cpu_dai->ops.hw_free(substream, cpu_dai); |
589 | 578 | ||
590 | mutex_unlock(&pcm_mutex); | 579 | mutex_unlock(&pcm_mutex); |
591 | return 0; | 580 | return 0; |
@@ -595,14 +584,15 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
595 | { | 584 | { |
596 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 585 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
597 | struct snd_soc_device *socdev = rtd->socdev; | 586 | struct snd_soc_device *socdev = rtd->socdev; |
587 | struct snd_soc_card *card= socdev->card; | ||
598 | struct snd_soc_dai_link *machine = rtd->dai; | 588 | struct snd_soc_dai_link *machine = rtd->dai; |
599 | struct snd_soc_platform *platform = socdev->platform; | 589 | struct snd_soc_platform *platform = card->platform; |
600 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 590 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
601 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 591 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
602 | int ret; | 592 | int ret; |
603 | 593 | ||
604 | if (codec_dai->ops.trigger) { | 594 | if (codec_dai->ops.trigger) { |
605 | ret = codec_dai->ops.trigger(substream, cmd); | 595 | ret = codec_dai->ops.trigger(substream, cmd, codec_dai); |
606 | if (ret < 0) | 596 | if (ret < 0) |
607 | return ret; | 597 | return ret; |
608 | } | 598 | } |
@@ -614,7 +604,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
614 | } | 604 | } |
615 | 605 | ||
616 | if (cpu_dai->ops.trigger) { | 606 | if (cpu_dai->ops.trigger) { |
617 | ret = cpu_dai->ops.trigger(substream, cmd); | 607 | ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai); |
618 | if (ret < 0) | 608 | if (ret < 0) |
619 | return ret; | 609 | return ret; |
620 | } | 610 | } |
@@ -636,8 +626,8 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
636 | static int soc_suspend(struct platform_device *pdev, pm_message_t state) | 626 | static int soc_suspend(struct platform_device *pdev, pm_message_t state) |
637 | { | 627 | { |
638 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
639 | struct snd_soc_machine *machine = socdev->machine; | 629 | struct snd_soc_card *card = socdev->card; |
640 | struct snd_soc_platform *platform = socdev->platform; | 630 | struct snd_soc_platform *platform = card->platform; |
641 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 631 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
642 | struct snd_soc_codec *codec = socdev->codec; | 632 | struct snd_soc_codec *codec = socdev->codec; |
643 | int i; | 633 | int i; |
@@ -653,29 +643,29 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
653 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); | 643 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); |
654 | 644 | ||
655 | /* mute any active DAC's */ | 645 | /* mute any active DAC's */ |
656 | for (i = 0; i < machine->num_links; i++) { | 646 | for (i = 0; i < card->num_links; i++) { |
657 | struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; | 647 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
658 | if (dai->dai_ops.digital_mute && dai->playback.active) | 648 | if (dai->ops.digital_mute && dai->playback.active) |
659 | dai->dai_ops.digital_mute(dai, 1); | 649 | dai->ops.digital_mute(dai, 1); |
660 | } | 650 | } |
661 | 651 | ||
662 | /* suspend all pcms */ | 652 | /* suspend all pcms */ |
663 | for (i = 0; i < machine->num_links; i++) | 653 | for (i = 0; i < card->num_links; i++) |
664 | snd_pcm_suspend_all(machine->dai_link[i].pcm); | 654 | snd_pcm_suspend_all(card->dai_link[i].pcm); |
665 | 655 | ||
666 | if (machine->suspend_pre) | 656 | if (card->suspend_pre) |
667 | machine->suspend_pre(pdev, state); | 657 | card->suspend_pre(pdev, state); |
668 | 658 | ||
669 | for (i = 0; i < machine->num_links; i++) { | 659 | for (i = 0; i < card->num_links; i++) { |
670 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 660 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
671 | if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97) | 661 | if (cpu_dai->suspend && !cpu_dai->ac97_control) |
672 | cpu_dai->suspend(pdev, cpu_dai); | 662 | cpu_dai->suspend(cpu_dai); |
673 | if (platform->suspend) | 663 | if (platform->suspend) |
674 | platform->suspend(pdev, cpu_dai); | 664 | platform->suspend(cpu_dai); |
675 | } | 665 | } |
676 | 666 | ||
677 | /* close any waiting streams and save state */ | 667 | /* close any waiting streams and save state */ |
678 | run_delayed_work(&socdev->delayed_work); | 668 | run_delayed_work(&card->delayed_work); |
679 | codec->suspend_bias_level = codec->bias_level; | 669 | codec->suspend_bias_level = codec->bias_level; |
680 | 670 | ||
681 | for (i = 0; i < codec->num_dai; i++) { | 671 | for (i = 0; i < codec->num_dai; i++) { |
@@ -692,14 +682,14 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
692 | if (codec_dev->suspend) | 682 | if (codec_dev->suspend) |
693 | codec_dev->suspend(pdev, state); | 683 | codec_dev->suspend(pdev, state); |
694 | 684 | ||
695 | for (i = 0; i < machine->num_links; i++) { | 685 | for (i = 0; i < card->num_links; i++) { |
696 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 686 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
697 | if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97) | 687 | if (cpu_dai->suspend && cpu_dai->ac97_control) |
698 | cpu_dai->suspend(pdev, cpu_dai); | 688 | cpu_dai->suspend(cpu_dai); |
699 | } | 689 | } |
700 | 690 | ||
701 | if (machine->suspend_post) | 691 | if (card->suspend_post) |
702 | machine->suspend_post(pdev, state); | 692 | card->suspend_post(pdev, state); |
703 | 693 | ||
704 | return 0; | 694 | return 0; |
705 | } | 695 | } |
@@ -709,11 +699,11 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
709 | */ | 699 | */ |
710 | static void soc_resume_deferred(struct work_struct *work) | 700 | static void soc_resume_deferred(struct work_struct *work) |
711 | { | 701 | { |
712 | struct snd_soc_device *socdev = container_of(work, | 702 | struct snd_soc_card *card = container_of(work, |
713 | struct snd_soc_device, | 703 | struct snd_soc_card, |
714 | deferred_resume_work); | 704 | deferred_resume_work); |
715 | struct snd_soc_machine *machine = socdev->machine; | 705 | struct snd_soc_device *socdev = card->socdev; |
716 | struct snd_soc_platform *platform = socdev->platform; | 706 | struct snd_soc_platform *platform = card->platform; |
717 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 707 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
718 | struct snd_soc_codec *codec = socdev->codec; | 708 | struct snd_soc_codec *codec = socdev->codec; |
719 | struct platform_device *pdev = to_platform_device(socdev->dev); | 709 | struct platform_device *pdev = to_platform_device(socdev->dev); |
@@ -723,15 +713,15 @@ static void soc_resume_deferred(struct work_struct *work) | |||
723 | * so userspace apps are blocked from touching us | 713 | * so userspace apps are blocked from touching us |
724 | */ | 714 | */ |
725 | 715 | ||
726 | dev_info(socdev->dev, "starting resume work\n"); | 716 | dev_dbg(socdev->dev, "starting resume work\n"); |
727 | 717 | ||
728 | if (machine->resume_pre) | 718 | if (card->resume_pre) |
729 | machine->resume_pre(pdev); | 719 | card->resume_pre(pdev); |
730 | 720 | ||
731 | for (i = 0; i < machine->num_links; i++) { | 721 | for (i = 0; i < card->num_links; i++) { |
732 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 722 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
733 | if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97) | 723 | if (cpu_dai->resume && cpu_dai->ac97_control) |
734 | cpu_dai->resume(pdev, cpu_dai); | 724 | cpu_dai->resume(cpu_dai); |
735 | } | 725 | } |
736 | 726 | ||
737 | if (codec_dev->resume) | 727 | if (codec_dev->resume) |
@@ -749,24 +739,24 @@ static void soc_resume_deferred(struct work_struct *work) | |||
749 | } | 739 | } |
750 | 740 | ||
751 | /* unmute any active DACs */ | 741 | /* unmute any active DACs */ |
752 | for (i = 0; i < machine->num_links; i++) { | 742 | for (i = 0; i < card->num_links; i++) { |
753 | struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; | 743 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
754 | if (dai->dai_ops.digital_mute && dai->playback.active) | 744 | if (dai->ops.digital_mute && dai->playback.active) |
755 | dai->dai_ops.digital_mute(dai, 0); | 745 | dai->ops.digital_mute(dai, 0); |
756 | } | 746 | } |
757 | 747 | ||
758 | for (i = 0; i < machine->num_links; i++) { | 748 | for (i = 0; i < card->num_links; i++) { |
759 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 749 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
760 | if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97) | 750 | if (cpu_dai->resume && !cpu_dai->ac97_control) |
761 | cpu_dai->resume(pdev, cpu_dai); | 751 | cpu_dai->resume(cpu_dai); |
762 | if (platform->resume) | 752 | if (platform->resume) |
763 | platform->resume(pdev, cpu_dai); | 753 | platform->resume(cpu_dai); |
764 | } | 754 | } |
765 | 755 | ||
766 | if (machine->resume_post) | 756 | if (card->resume_post) |
767 | machine->resume_post(pdev); | 757 | card->resume_post(pdev); |
768 | 758 | ||
769 | dev_info(socdev->dev, "resume work completed\n"); | 759 | dev_dbg(socdev->dev, "resume work completed\n"); |
770 | 760 | ||
771 | /* userspace can access us now we are back as we were before */ | 761 | /* userspace can access us now we are back as we were before */ |
772 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); | 762 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); |
@@ -776,11 +766,12 @@ static void soc_resume_deferred(struct work_struct *work) | |||
776 | static int soc_resume(struct platform_device *pdev) | 766 | static int soc_resume(struct platform_device *pdev) |
777 | { | 767 | { |
778 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 768 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
769 | struct snd_soc_card *card = socdev->card; | ||
779 | 770 | ||
780 | dev_info(socdev->dev, "scheduling resume work\n"); | 771 | dev_dbg(socdev->dev, "scheduling resume work\n"); |
781 | 772 | ||
782 | if (!schedule_work(&socdev->deferred_resume_work)) | 773 | if (!schedule_work(&card->deferred_resume_work)) |
783 | dev_err(socdev->dev, "work item may be lost\n"); | 774 | dev_err(socdev->dev, "resume work item may be lost\n"); |
784 | 775 | ||
785 | return 0; | 776 | return 0; |
786 | } | 777 | } |
@@ -790,23 +781,83 @@ static int soc_resume(struct platform_device *pdev) | |||
790 | #define soc_resume NULL | 781 | #define soc_resume NULL |
791 | #endif | 782 | #endif |
792 | 783 | ||
793 | /* probes a new socdev */ | 784 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
794 | static int soc_probe(struct platform_device *pdev) | ||
795 | { | 785 | { |
796 | int ret = 0, i; | 786 | struct platform_device *pdev = container_of(card->dev, |
797 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 787 | struct platform_device, |
798 | struct snd_soc_machine *machine = socdev->machine; | 788 | dev); |
799 | struct snd_soc_platform *platform = socdev->platform; | 789 | struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; |
800 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 790 | struct snd_soc_platform *platform; |
791 | struct snd_soc_dai *dai; | ||
792 | int i, found, ret, ac97; | ||
793 | |||
794 | if (card->instantiated) | ||
795 | return; | ||
796 | |||
797 | found = 0; | ||
798 | list_for_each_entry(platform, &platform_list, list) | ||
799 | if (card->platform == platform) { | ||
800 | found = 1; | ||
801 | break; | ||
802 | } | ||
803 | if (!found) { | ||
804 | dev_dbg(card->dev, "Platform %s not registered\n", | ||
805 | card->platform->name); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | ac97 = 0; | ||
810 | for (i = 0; i < card->num_links; i++) { | ||
811 | found = 0; | ||
812 | list_for_each_entry(dai, &dai_list, list) | ||
813 | if (card->dai_link[i].cpu_dai == dai) { | ||
814 | found = 1; | ||
815 | break; | ||
816 | } | ||
817 | if (!found) { | ||
818 | dev_dbg(card->dev, "DAI %s not registered\n", | ||
819 | card->dai_link[i].cpu_dai->name); | ||
820 | return; | ||
821 | } | ||
801 | 822 | ||
802 | if (machine->probe) { | 823 | if (card->dai_link[i].cpu_dai->ac97_control) |
803 | ret = machine->probe(pdev); | 824 | ac97 = 1; |
825 | } | ||
826 | |||
827 | /* If we have AC97 in the system then don't wait for the | ||
828 | * codec. This will need revisiting if we have to handle | ||
829 | * systems with mixed AC97 and non-AC97 parts. Only check for | ||
830 | * DAIs currently; we can't do this per link since some AC97 | ||
831 | * codecs have non-AC97 DAIs. | ||
832 | */ | ||
833 | if (!ac97) | ||
834 | for (i = 0; i < card->num_links; i++) { | ||
835 | found = 0; | ||
836 | list_for_each_entry(dai, &dai_list, list) | ||
837 | if (card->dai_link[i].codec_dai == dai) { | ||
838 | found = 1; | ||
839 | break; | ||
840 | } | ||
841 | if (!found) { | ||
842 | dev_dbg(card->dev, "DAI %s not registered\n", | ||
843 | card->dai_link[i].codec_dai->name); | ||
844 | return; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* Note that we do not current check for codec components */ | ||
849 | |||
850 | dev_dbg(card->dev, "All components present, instantiating\n"); | ||
851 | |||
852 | /* Found everything, bring it up */ | ||
853 | if (card->probe) { | ||
854 | ret = card->probe(pdev); | ||
804 | if (ret < 0) | 855 | if (ret < 0) |
805 | return ret; | 856 | return; |
806 | } | 857 | } |
807 | 858 | ||
808 | for (i = 0; i < machine->num_links; i++) { | 859 | for (i = 0; i < card->num_links; i++) { |
809 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 860 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
810 | if (cpu_dai->probe) { | 861 | if (cpu_dai->probe) { |
811 | ret = cpu_dai->probe(pdev, cpu_dai); | 862 | ret = cpu_dai->probe(pdev, cpu_dai); |
812 | if (ret < 0) | 863 | if (ret < 0) |
@@ -827,13 +878,15 @@ static int soc_probe(struct platform_device *pdev) | |||
827 | } | 878 | } |
828 | 879 | ||
829 | /* DAPM stream work */ | 880 | /* DAPM stream work */ |
830 | INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work); | 881 | INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); |
831 | #ifdef CONFIG_PM | 882 | #ifdef CONFIG_PM |
832 | /* deferred resume work */ | 883 | /* deferred resume work */ |
833 | INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred); | 884 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); |
834 | #endif | 885 | #endif |
835 | 886 | ||
836 | return 0; | 887 | card->instantiated = 1; |
888 | |||
889 | return; | ||
837 | 890 | ||
838 | platform_err: | 891 | platform_err: |
839 | if (codec_dev->remove) | 892 | if (codec_dev->remove) |
@@ -841,15 +894,45 @@ platform_err: | |||
841 | 894 | ||
842 | cpu_dai_err: | 895 | cpu_dai_err: |
843 | for (i--; i >= 0; i--) { | 896 | for (i--; i >= 0; i--) { |
844 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 897 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
845 | if (cpu_dai->remove) | 898 | if (cpu_dai->remove) |
846 | cpu_dai->remove(pdev, cpu_dai); | 899 | cpu_dai->remove(pdev, cpu_dai); |
847 | } | 900 | } |
848 | 901 | ||
849 | if (machine->remove) | 902 | if (card->remove) |
850 | machine->remove(pdev); | 903 | card->remove(pdev); |
904 | } | ||
851 | 905 | ||
852 | return ret; | 906 | /* |
907 | * Attempt to initialise any uninitalised cards. Must be called with | ||
908 | * client_mutex. | ||
909 | */ | ||
910 | static void snd_soc_instantiate_cards(void) | ||
911 | { | ||
912 | struct snd_soc_card *card; | ||
913 | list_for_each_entry(card, &card_list, list) | ||
914 | snd_soc_instantiate_card(card); | ||
915 | } | ||
916 | |||
917 | /* probes a new socdev */ | ||
918 | static int soc_probe(struct platform_device *pdev) | ||
919 | { | ||
920 | int ret = 0; | ||
921 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
922 | struct snd_soc_card *card = socdev->card; | ||
923 | |||
924 | /* Bodge while we push things out of socdev */ | ||
925 | card->socdev = socdev; | ||
926 | |||
927 | /* Bodge while we unpick instantiation */ | ||
928 | card->dev = &pdev->dev; | ||
929 | ret = snd_soc_register_card(card); | ||
930 | if (ret != 0) { | ||
931 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
932 | return ret; | ||
933 | } | ||
934 | |||
935 | return 0; | ||
853 | } | 936 | } |
854 | 937 | ||
855 | /* removes a socdev */ | 938 | /* removes a socdev */ |
@@ -857,11 +940,11 @@ static int soc_remove(struct platform_device *pdev) | |||
857 | { | 940 | { |
858 | int i; | 941 | int i; |
859 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 942 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
860 | struct snd_soc_machine *machine = socdev->machine; | 943 | struct snd_soc_card *card = socdev->card; |
861 | struct snd_soc_platform *platform = socdev->platform; | 944 | struct snd_soc_platform *platform = card->platform; |
862 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 945 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
863 | 946 | ||
864 | run_delayed_work(&socdev->delayed_work); | 947 | run_delayed_work(&card->delayed_work); |
865 | 948 | ||
866 | if (platform->remove) | 949 | if (platform->remove) |
867 | platform->remove(pdev); | 950 | platform->remove(pdev); |
@@ -869,14 +952,16 @@ static int soc_remove(struct platform_device *pdev) | |||
869 | if (codec_dev->remove) | 952 | if (codec_dev->remove) |
870 | codec_dev->remove(pdev); | 953 | codec_dev->remove(pdev); |
871 | 954 | ||
872 | for (i = 0; i < machine->num_links; i++) { | 955 | for (i = 0; i < card->num_links; i++) { |
873 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 956 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
874 | if (cpu_dai->remove) | 957 | if (cpu_dai->remove) |
875 | cpu_dai->remove(pdev, cpu_dai); | 958 | cpu_dai->remove(pdev, cpu_dai); |
876 | } | 959 | } |
877 | 960 | ||
878 | if (machine->remove) | 961 | if (card->remove) |
879 | machine->remove(pdev); | 962 | card->remove(pdev); |
963 | |||
964 | snd_soc_unregister_card(card); | ||
880 | 965 | ||
881 | return 0; | 966 | return 0; |
882 | } | 967 | } |
@@ -898,6 +983,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
898 | struct snd_soc_dai_link *dai_link, int num) | 983 | struct snd_soc_dai_link *dai_link, int num) |
899 | { | 984 | { |
900 | struct snd_soc_codec *codec = socdev->codec; | 985 | struct snd_soc_codec *codec = socdev->codec; |
986 | struct snd_soc_card *card = socdev->card; | ||
987 | struct snd_soc_platform *platform = card->platform; | ||
901 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; | 988 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; |
902 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; | 989 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; |
903 | struct snd_soc_pcm_runtime *rtd; | 990 | struct snd_soc_pcm_runtime *rtd; |
@@ -914,8 +1001,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
914 | codec_dai->codec = socdev->codec; | 1001 | codec_dai->codec = socdev->codec; |
915 | 1002 | ||
916 | /* check client and interface hw capabilities */ | 1003 | /* check client and interface hw capabilities */ |
917 | sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name, | 1004 | sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, |
918 | get_dai_name(cpu_dai->type), num); | 1005 | num); |
919 | 1006 | ||
920 | if (codec_dai->playback.channels_min) | 1007 | if (codec_dai->playback.channels_min) |
921 | playback = 1; | 1008 | playback = 1; |
@@ -933,13 +1020,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
933 | 1020 | ||
934 | dai_link->pcm = pcm; | 1021 | dai_link->pcm = pcm; |
935 | pcm->private_data = rtd; | 1022 | pcm->private_data = rtd; |
936 | soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap; | 1023 | soc_pcm_ops.mmap = platform->pcm_ops->mmap; |
937 | soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer; | 1024 | soc_pcm_ops.pointer = platform->pcm_ops->pointer; |
938 | soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl; | 1025 | soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; |
939 | soc_pcm_ops.copy = socdev->platform->pcm_ops->copy; | 1026 | soc_pcm_ops.copy = platform->pcm_ops->copy; |
940 | soc_pcm_ops.silence = socdev->platform->pcm_ops->silence; | 1027 | soc_pcm_ops.silence = platform->pcm_ops->silence; |
941 | soc_pcm_ops.ack = socdev->platform->pcm_ops->ack; | 1028 | soc_pcm_ops.ack = platform->pcm_ops->ack; |
942 | soc_pcm_ops.page = socdev->platform->pcm_ops->page; | 1029 | soc_pcm_ops.page = platform->pcm_ops->page; |
943 | 1030 | ||
944 | if (playback) | 1031 | if (playback) |
945 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | 1032 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); |
@@ -947,24 +1034,22 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
947 | if (capture) | 1034 | if (capture) |
948 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | 1035 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); |
949 | 1036 | ||
950 | ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm); | 1037 | ret = platform->pcm_new(codec->card, codec_dai, pcm); |
951 | if (ret < 0) { | 1038 | if (ret < 0) { |
952 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); | 1039 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); |
953 | kfree(rtd); | 1040 | kfree(rtd); |
954 | return ret; | 1041 | return ret; |
955 | } | 1042 | } |
956 | 1043 | ||
957 | pcm->private_free = socdev->platform->pcm_free; | 1044 | pcm->private_free = platform->pcm_free; |
958 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | 1045 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, |
959 | cpu_dai->name); | 1046 | cpu_dai->name); |
960 | return ret; | 1047 | return ret; |
961 | } | 1048 | } |
962 | 1049 | ||
963 | /* codec register dump */ | 1050 | /* codec register dump */ |
964 | static ssize_t codec_reg_show(struct device *dev, | 1051 | static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) |
965 | struct device_attribute *attr, char *buf) | ||
966 | { | 1052 | { |
967 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
968 | struct snd_soc_codec *codec = devdata->codec; | 1053 | struct snd_soc_codec *codec = devdata->codec; |
969 | int i, step = 1, count = 0; | 1054 | int i, step = 1, count = 0; |
970 | 1055 | ||
@@ -1001,8 +1086,110 @@ static ssize_t codec_reg_show(struct device *dev, | |||
1001 | 1086 | ||
1002 | return count; | 1087 | return count; |
1003 | } | 1088 | } |
1089 | static ssize_t codec_reg_show(struct device *dev, | ||
1090 | struct device_attribute *attr, char *buf) | ||
1091 | { | ||
1092 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
1093 | return soc_codec_reg_show(devdata, buf); | ||
1094 | } | ||
1095 | |||
1004 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 1096 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
1005 | 1097 | ||
1098 | #ifdef CONFIG_DEBUG_FS | ||
1099 | static int codec_reg_open_file(struct inode *inode, struct file *file) | ||
1100 | { | ||
1101 | file->private_data = inode->i_private; | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | ||
1106 | size_t count, loff_t *ppos) | ||
1107 | { | ||
1108 | ssize_t ret; | ||
1109 | struct snd_soc_codec *codec = file->private_data; | ||
1110 | struct device *card_dev = codec->card->dev; | ||
1111 | struct snd_soc_device *devdata = card_dev->driver_data; | ||
1112 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1113 | if (!buf) | ||
1114 | return -ENOMEM; | ||
1115 | ret = soc_codec_reg_show(devdata, buf); | ||
1116 | if (ret >= 0) | ||
1117 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
1118 | kfree(buf); | ||
1119 | return ret; | ||
1120 | } | ||
1121 | |||
1122 | static ssize_t codec_reg_write_file(struct file *file, | ||
1123 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
1124 | { | ||
1125 | char buf[32]; | ||
1126 | int buf_size; | ||
1127 | char *start = buf; | ||
1128 | unsigned long reg, value; | ||
1129 | int step = 1; | ||
1130 | struct snd_soc_codec *codec = file->private_data; | ||
1131 | |||
1132 | buf_size = min(count, (sizeof(buf)-1)); | ||
1133 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1134 | return -EFAULT; | ||
1135 | buf[buf_size] = 0; | ||
1136 | |||
1137 | if (codec->reg_cache_step) | ||
1138 | step = codec->reg_cache_step; | ||
1139 | |||
1140 | while (*start == ' ') | ||
1141 | start++; | ||
1142 | reg = simple_strtoul(start, &start, 16); | ||
1143 | if ((reg >= codec->reg_cache_size) || (reg % step)) | ||
1144 | return -EINVAL; | ||
1145 | while (*start == ' ') | ||
1146 | start++; | ||
1147 | if (strict_strtoul(start, 16, &value)) | ||
1148 | return -EINVAL; | ||
1149 | codec->write(codec, reg, value); | ||
1150 | return buf_size; | ||
1151 | } | ||
1152 | |||
1153 | static const struct file_operations codec_reg_fops = { | ||
1154 | .open = codec_reg_open_file, | ||
1155 | .read = codec_reg_read_file, | ||
1156 | .write = codec_reg_write_file, | ||
1157 | }; | ||
1158 | |||
1159 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | ||
1160 | { | ||
1161 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | ||
1162 | debugfs_root, codec, | ||
1163 | &codec_reg_fops); | ||
1164 | if (!codec->debugfs_reg) | ||
1165 | printk(KERN_WARNING | ||
1166 | "ASoC: Failed to create codec register debugfs file\n"); | ||
1167 | |||
1168 | codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744, | ||
1169 | debugfs_root, | ||
1170 | &codec->pop_time); | ||
1171 | if (!codec->debugfs_pop_time) | ||
1172 | printk(KERN_WARNING | ||
1173 | "Failed to create pop time debugfs file\n"); | ||
1174 | } | ||
1175 | |||
1176 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | ||
1177 | { | ||
1178 | debugfs_remove(codec->debugfs_pop_time); | ||
1179 | debugfs_remove(codec->debugfs_reg); | ||
1180 | } | ||
1181 | |||
1182 | #else | ||
1183 | |||
1184 | static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | ||
1185 | { | ||
1186 | } | ||
1187 | |||
1188 | static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | ||
1189 | { | ||
1190 | } | ||
1191 | #endif | ||
1192 | |||
1006 | /** | 1193 | /** |
1007 | * snd_soc_new_ac97_codec - initailise AC97 device | 1194 | * snd_soc_new_ac97_codec - initailise AC97 device |
1008 | * @codec: audio codec | 1195 | * @codec: audio codec |
@@ -1121,7 +1308,7 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits); | |||
1121 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | 1308 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) |
1122 | { | 1309 | { |
1123 | struct snd_soc_codec *codec = socdev->codec; | 1310 | struct snd_soc_codec *codec = socdev->codec; |
1124 | struct snd_soc_machine *machine = socdev->machine; | 1311 | struct snd_soc_card *card = socdev->card; |
1125 | int ret = 0, i; | 1312 | int ret = 0, i; |
1126 | 1313 | ||
1127 | mutex_lock(&codec->mutex); | 1314 | mutex_lock(&codec->mutex); |
@@ -1140,11 +1327,11 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | |||
1140 | strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); | 1327 | strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); |
1141 | 1328 | ||
1142 | /* create the pcms */ | 1329 | /* create the pcms */ |
1143 | for (i = 0; i < machine->num_links; i++) { | 1330 | for (i = 0; i < card->num_links; i++) { |
1144 | ret = soc_new_pcm(socdev, &machine->dai_link[i], i); | 1331 | ret = soc_new_pcm(socdev, &card->dai_link[i], i); |
1145 | if (ret < 0) { | 1332 | if (ret < 0) { |
1146 | printk(KERN_ERR "asoc: can't create pcm %s\n", | 1333 | printk(KERN_ERR "asoc: can't create pcm %s\n", |
1147 | machine->dai_link[i].stream_name); | 1334 | card->dai_link[i].stream_name); |
1148 | mutex_unlock(&codec->mutex); | 1335 | mutex_unlock(&codec->mutex); |
1149 | return ret; | 1336 | return ret; |
1150 | } | 1337 | } |
@@ -1156,7 +1343,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | |||
1156 | EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | 1343 | EXPORT_SYMBOL_GPL(snd_soc_new_pcms); |
1157 | 1344 | ||
1158 | /** | 1345 | /** |
1159 | * snd_soc_register_card - register sound card | 1346 | * snd_soc_init_card - register sound card |
1160 | * @socdev: the SoC audio device | 1347 | * @socdev: the SoC audio device |
1161 | * | 1348 | * |
1162 | * Register a SoC sound card. Also registers an AC97 device if the | 1349 | * Register a SoC sound card. Also registers an AC97 device if the |
@@ -1164,29 +1351,28 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | |||
1164 | * | 1351 | * |
1165 | * Returns 0 for success, else error. | 1352 | * Returns 0 for success, else error. |
1166 | */ | 1353 | */ |
1167 | int snd_soc_register_card(struct snd_soc_device *socdev) | 1354 | int snd_soc_init_card(struct snd_soc_device *socdev) |
1168 | { | 1355 | { |
1169 | struct snd_soc_codec *codec = socdev->codec; | 1356 | struct snd_soc_codec *codec = socdev->codec; |
1170 | struct snd_soc_machine *machine = socdev->machine; | 1357 | struct snd_soc_card *card = socdev->card; |
1171 | int ret = 0, i, ac97 = 0, err = 0; | 1358 | int ret = 0, i, ac97 = 0, err = 0; |
1172 | 1359 | ||
1173 | for (i = 0; i < machine->num_links; i++) { | 1360 | for (i = 0; i < card->num_links; i++) { |
1174 | if (socdev->machine->dai_link[i].init) { | 1361 | if (card->dai_link[i].init) { |
1175 | err = socdev->machine->dai_link[i].init(codec); | 1362 | err = card->dai_link[i].init(codec); |
1176 | if (err < 0) { | 1363 | if (err < 0) { |
1177 | printk(KERN_ERR "asoc: failed to init %s\n", | 1364 | printk(KERN_ERR "asoc: failed to init %s\n", |
1178 | socdev->machine->dai_link[i].stream_name); | 1365 | card->dai_link[i].stream_name); |
1179 | continue; | 1366 | continue; |
1180 | } | 1367 | } |
1181 | } | 1368 | } |
1182 | if (socdev->machine->dai_link[i].codec_dai->type == | 1369 | if (card->dai_link[i].codec_dai->ac97_control) |
1183 | SND_SOC_DAI_AC97_BUS) | ||
1184 | ac97 = 1; | 1370 | ac97 = 1; |
1185 | } | 1371 | } |
1186 | snprintf(codec->card->shortname, sizeof(codec->card->shortname), | 1372 | snprintf(codec->card->shortname, sizeof(codec->card->shortname), |
1187 | "%s", machine->name); | 1373 | "%s", card->name); |
1188 | snprintf(codec->card->longname, sizeof(codec->card->longname), | 1374 | snprintf(codec->card->longname, sizeof(codec->card->longname), |
1189 | "%s (%s)", machine->name, codec->name); | 1375 | "%s (%s)", card->name, codec->name); |
1190 | 1376 | ||
1191 | ret = snd_card_register(codec->card); | 1377 | ret = snd_card_register(codec->card); |
1192 | if (ret < 0) { | 1378 | if (ret < 0) { |
@@ -1216,12 +1402,13 @@ int snd_soc_register_card(struct snd_soc_device *socdev) | |||
1216 | if (err < 0) | 1402 | if (err < 0) |
1217 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1403 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); |
1218 | 1404 | ||
1405 | soc_init_codec_debugfs(socdev->codec); | ||
1219 | mutex_unlock(&codec->mutex); | 1406 | mutex_unlock(&codec->mutex); |
1220 | 1407 | ||
1221 | out: | 1408 | out: |
1222 | return ret; | 1409 | return ret; |
1223 | } | 1410 | } |
1224 | EXPORT_SYMBOL_GPL(snd_soc_register_card); | 1411 | EXPORT_SYMBOL_GPL(snd_soc_init_card); |
1225 | 1412 | ||
1226 | /** | 1413 | /** |
1227 | * snd_soc_free_pcms - free sound card and pcms | 1414 | * snd_soc_free_pcms - free sound card and pcms |
@@ -1239,10 +1426,11 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev) | |||
1239 | #endif | 1426 | #endif |
1240 | 1427 | ||
1241 | mutex_lock(&codec->mutex); | 1428 | mutex_lock(&codec->mutex); |
1429 | soc_cleanup_codec_debugfs(socdev->codec); | ||
1242 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1430 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1243 | for (i = 0; i < codec->num_dai; i++) { | 1431 | for (i = 0; i < codec->num_dai; i++) { |
1244 | codec_dai = &codec->dai[i]; | 1432 | codec_dai = &codec->dai[i]; |
1245 | if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) { | 1433 | if (codec_dai->ac97_control && codec->ac97) { |
1246 | soc_ac97_dev_unregister(codec); | 1434 | soc_ac97_dev_unregister(codec); |
1247 | goto free_card; | 1435 | goto free_card; |
1248 | } | 1436 | } |
@@ -1756,8 +1944,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | |||
1756 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 1944 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
1757 | unsigned int freq, int dir) | 1945 | unsigned int freq, int dir) |
1758 | { | 1946 | { |
1759 | if (dai->dai_ops.set_sysclk) | 1947 | if (dai->ops.set_sysclk) |
1760 | return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir); | 1948 | return dai->ops.set_sysclk(dai, clk_id, freq, dir); |
1761 | else | 1949 | else |
1762 | return -EINVAL; | 1950 | return -EINVAL; |
1763 | } | 1951 | } |
@@ -1776,8 +1964,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
1776 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | 1964 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, |
1777 | int div_id, int div) | 1965 | int div_id, int div) |
1778 | { | 1966 | { |
1779 | if (dai->dai_ops.set_clkdiv) | 1967 | if (dai->ops.set_clkdiv) |
1780 | return dai->dai_ops.set_clkdiv(dai, div_id, div); | 1968 | return dai->ops.set_clkdiv(dai, div_id, div); |
1781 | else | 1969 | else |
1782 | return -EINVAL; | 1970 | return -EINVAL; |
1783 | } | 1971 | } |
@@ -1795,8 +1983,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | |||
1795 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, | 1983 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, |
1796 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 1984 | int pll_id, unsigned int freq_in, unsigned int freq_out) |
1797 | { | 1985 | { |
1798 | if (dai->dai_ops.set_pll) | 1986 | if (dai->ops.set_pll) |
1799 | return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out); | 1987 | return dai->ops.set_pll(dai, pll_id, freq_in, freq_out); |
1800 | else | 1988 | else |
1801 | return -EINVAL; | 1989 | return -EINVAL; |
1802 | } | 1990 | } |
@@ -1805,15 +1993,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | |||
1805 | /** | 1993 | /** |
1806 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. | 1994 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. |
1807 | * @dai: DAI | 1995 | * @dai: DAI |
1808 | * @clk_id: DAI specific clock ID | ||
1809 | * @fmt: SND_SOC_DAIFMT_ format value. | 1996 | * @fmt: SND_SOC_DAIFMT_ format value. |
1810 | * | 1997 | * |
1811 | * Configures the DAI hardware format and clocking. | 1998 | * Configures the DAI hardware format and clocking. |
1812 | */ | 1999 | */ |
1813 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 2000 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
1814 | { | 2001 | { |
1815 | if (dai->dai_ops.set_fmt) | 2002 | if (dai->ops.set_fmt) |
1816 | return dai->dai_ops.set_fmt(dai, fmt); | 2003 | return dai->ops.set_fmt(dai, fmt); |
1817 | else | 2004 | else |
1818 | return -EINVAL; | 2005 | return -EINVAL; |
1819 | } | 2006 | } |
@@ -1831,8 +2018,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
1831 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 2018 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
1832 | unsigned int mask, int slots) | 2019 | unsigned int mask, int slots) |
1833 | { | 2020 | { |
1834 | if (dai->dai_ops.set_sysclk) | 2021 | if (dai->ops.set_sysclk) |
1835 | return dai->dai_ops.set_tdm_slot(dai, mask, slots); | 2022 | return dai->ops.set_tdm_slot(dai, mask, slots); |
1836 | else | 2023 | else |
1837 | return -EINVAL; | 2024 | return -EINVAL; |
1838 | } | 2025 | } |
@@ -1847,8 +2034,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | |||
1847 | */ | 2034 | */ |
1848 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | 2035 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) |
1849 | { | 2036 | { |
1850 | if (dai->dai_ops.set_sysclk) | 2037 | if (dai->ops.set_sysclk) |
1851 | return dai->dai_ops.set_tristate(dai, tristate); | 2038 | return dai->ops.set_tristate(dai, tristate); |
1852 | else | 2039 | else |
1853 | return -EINVAL; | 2040 | return -EINVAL; |
1854 | } | 2041 | } |
@@ -1863,21 +2050,242 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | |||
1863 | */ | 2050 | */ |
1864 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) | 2051 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) |
1865 | { | 2052 | { |
1866 | if (dai->dai_ops.digital_mute) | 2053 | if (dai->ops.digital_mute) |
1867 | return dai->dai_ops.digital_mute(dai, mute); | 2054 | return dai->ops.digital_mute(dai, mute); |
1868 | else | 2055 | else |
1869 | return -EINVAL; | 2056 | return -EINVAL; |
1870 | } | 2057 | } |
1871 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 2058 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
1872 | 2059 | ||
1873 | static int __devinit snd_soc_init(void) | 2060 | /** |
2061 | * snd_soc_register_card - Register a card with the ASoC core | ||
2062 | * | ||
2063 | * @param card Card to register | ||
2064 | * | ||
2065 | * Note that currently this is an internal only function: it will be | ||
2066 | * exposed to machine drivers after further backporting of ASoC v2 | ||
2067 | * registration APIs. | ||
2068 | */ | ||
2069 | static int snd_soc_register_card(struct snd_soc_card *card) | ||
2070 | { | ||
2071 | if (!card->name || !card->dev) | ||
2072 | return -EINVAL; | ||
2073 | |||
2074 | INIT_LIST_HEAD(&card->list); | ||
2075 | card->instantiated = 0; | ||
2076 | |||
2077 | mutex_lock(&client_mutex); | ||
2078 | list_add(&card->list, &card_list); | ||
2079 | snd_soc_instantiate_cards(); | ||
2080 | mutex_unlock(&client_mutex); | ||
2081 | |||
2082 | dev_dbg(card->dev, "Registered card '%s'\n", card->name); | ||
2083 | |||
2084 | return 0; | ||
2085 | } | ||
2086 | |||
2087 | /** | ||
2088 | * snd_soc_unregister_card - Unregister a card with the ASoC core | ||
2089 | * | ||
2090 | * @param card Card to unregister | ||
2091 | * | ||
2092 | * Note that currently this is an internal only function: it will be | ||
2093 | * exposed to machine drivers after further backporting of ASoC v2 | ||
2094 | * registration APIs. | ||
2095 | */ | ||
2096 | static int snd_soc_unregister_card(struct snd_soc_card *card) | ||
2097 | { | ||
2098 | mutex_lock(&client_mutex); | ||
2099 | list_del(&card->list); | ||
2100 | mutex_unlock(&client_mutex); | ||
2101 | |||
2102 | dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); | ||
2103 | |||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | /** | ||
2108 | * snd_soc_register_dai - Register a DAI with the ASoC core | ||
2109 | * | ||
2110 | * @param dai DAI to register | ||
2111 | */ | ||
2112 | int snd_soc_register_dai(struct snd_soc_dai *dai) | ||
2113 | { | ||
2114 | if (!dai->name) | ||
2115 | return -EINVAL; | ||
2116 | |||
2117 | /* The device should become mandatory over time */ | ||
2118 | if (!dai->dev) | ||
2119 | printk(KERN_WARNING "No device for DAI %s\n", dai->name); | ||
2120 | |||
2121 | INIT_LIST_HEAD(&dai->list); | ||
2122 | |||
2123 | mutex_lock(&client_mutex); | ||
2124 | list_add(&dai->list, &dai_list); | ||
2125 | snd_soc_instantiate_cards(); | ||
2126 | mutex_unlock(&client_mutex); | ||
2127 | |||
2128 | pr_debug("Registered DAI '%s'\n", dai->name); | ||
2129 | |||
2130 | return 0; | ||
2131 | } | ||
2132 | EXPORT_SYMBOL_GPL(snd_soc_register_dai); | ||
2133 | |||
2134 | /** | ||
2135 | * snd_soc_unregister_dai - Unregister a DAI from the ASoC core | ||
2136 | * | ||
2137 | * @param dai DAI to unregister | ||
2138 | */ | ||
2139 | void snd_soc_unregister_dai(struct snd_soc_dai *dai) | ||
2140 | { | ||
2141 | mutex_lock(&client_mutex); | ||
2142 | list_del(&dai->list); | ||
2143 | mutex_unlock(&client_mutex); | ||
2144 | |||
2145 | pr_debug("Unregistered DAI '%s'\n", dai->name); | ||
2146 | } | ||
2147 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); | ||
2148 | |||
2149 | /** | ||
2150 | * snd_soc_register_dais - Register multiple DAIs with the ASoC core | ||
2151 | * | ||
2152 | * @param dai Array of DAIs to register | ||
2153 | * @param count Number of DAIs | ||
2154 | */ | ||
2155 | int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) | ||
2156 | { | ||
2157 | int i, ret; | ||
2158 | |||
2159 | for (i = 0; i < count; i++) { | ||
2160 | ret = snd_soc_register_dai(&dai[i]); | ||
2161 | if (ret != 0) | ||
2162 | goto err; | ||
2163 | } | ||
2164 | |||
2165 | return 0; | ||
2166 | |||
2167 | err: | ||
2168 | for (i--; i >= 0; i--) | ||
2169 | snd_soc_unregister_dai(&dai[i]); | ||
2170 | |||
2171 | return ret; | ||
2172 | } | ||
2173 | EXPORT_SYMBOL_GPL(snd_soc_register_dais); | ||
2174 | |||
2175 | /** | ||
2176 | * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core | ||
2177 | * | ||
2178 | * @param dai Array of DAIs to unregister | ||
2179 | * @param count Number of DAIs | ||
2180 | */ | ||
2181 | void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) | ||
2182 | { | ||
2183 | int i; | ||
2184 | |||
2185 | for (i = 0; i < count; i++) | ||
2186 | snd_soc_unregister_dai(&dai[i]); | ||
2187 | } | ||
2188 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); | ||
2189 | |||
2190 | /** | ||
2191 | * snd_soc_register_platform - Register a platform with the ASoC core | ||
2192 | * | ||
2193 | * @param platform platform to register | ||
2194 | */ | ||
2195 | int snd_soc_register_platform(struct snd_soc_platform *platform) | ||
2196 | { | ||
2197 | if (!platform->name) | ||
2198 | return -EINVAL; | ||
2199 | |||
2200 | INIT_LIST_HEAD(&platform->list); | ||
2201 | |||
2202 | mutex_lock(&client_mutex); | ||
2203 | list_add(&platform->list, &platform_list); | ||
2204 | snd_soc_instantiate_cards(); | ||
2205 | mutex_unlock(&client_mutex); | ||
2206 | |||
2207 | pr_debug("Registered platform '%s'\n", platform->name); | ||
2208 | |||
2209 | return 0; | ||
2210 | } | ||
2211 | EXPORT_SYMBOL_GPL(snd_soc_register_platform); | ||
2212 | |||
2213 | /** | ||
2214 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core | ||
2215 | * | ||
2216 | * @param platform platform to unregister | ||
2217 | */ | ||
2218 | void snd_soc_unregister_platform(struct snd_soc_platform *platform) | ||
1874 | { | 2219 | { |
1875 | printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION); | 2220 | mutex_lock(&client_mutex); |
2221 | list_del(&platform->list); | ||
2222 | mutex_unlock(&client_mutex); | ||
2223 | |||
2224 | pr_debug("Unregistered platform '%s'\n", platform->name); | ||
2225 | } | ||
2226 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); | ||
2227 | |||
2228 | /** | ||
2229 | * snd_soc_register_codec - Register a codec with the ASoC core | ||
2230 | * | ||
2231 | * @param codec codec to register | ||
2232 | */ | ||
2233 | int snd_soc_register_codec(struct snd_soc_codec *codec) | ||
2234 | { | ||
2235 | if (!codec->name) | ||
2236 | return -EINVAL; | ||
2237 | |||
2238 | /* The device should become mandatory over time */ | ||
2239 | if (!codec->dev) | ||
2240 | printk(KERN_WARNING "No device for codec %s\n", codec->name); | ||
2241 | |||
2242 | INIT_LIST_HEAD(&codec->list); | ||
2243 | |||
2244 | mutex_lock(&client_mutex); | ||
2245 | list_add(&codec->list, &codec_list); | ||
2246 | snd_soc_instantiate_cards(); | ||
2247 | mutex_unlock(&client_mutex); | ||
2248 | |||
2249 | pr_debug("Registered codec '%s'\n", codec->name); | ||
2250 | |||
2251 | return 0; | ||
2252 | } | ||
2253 | EXPORT_SYMBOL_GPL(snd_soc_register_codec); | ||
2254 | |||
2255 | /** | ||
2256 | * snd_soc_unregister_codec - Unregister a codec from the ASoC core | ||
2257 | * | ||
2258 | * @param codec codec to unregister | ||
2259 | */ | ||
2260 | void snd_soc_unregister_codec(struct snd_soc_codec *codec) | ||
2261 | { | ||
2262 | mutex_lock(&client_mutex); | ||
2263 | list_del(&codec->list); | ||
2264 | mutex_unlock(&client_mutex); | ||
2265 | |||
2266 | pr_debug("Unregistered codec '%s'\n", codec->name); | ||
2267 | } | ||
2268 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | ||
2269 | |||
2270 | static int __init snd_soc_init(void) | ||
2271 | { | ||
2272 | #ifdef CONFIG_DEBUG_FS | ||
2273 | debugfs_root = debugfs_create_dir("asoc", NULL); | ||
2274 | if (IS_ERR(debugfs_root) || !debugfs_root) { | ||
2275 | printk(KERN_WARNING | ||
2276 | "ASoC: Failed to create debugfs directory\n"); | ||
2277 | debugfs_root = NULL; | ||
2278 | } | ||
2279 | #endif | ||
2280 | |||
1876 | return platform_driver_register(&soc_driver); | 2281 | return platform_driver_register(&soc_driver); |
1877 | } | 2282 | } |
1878 | 2283 | ||
1879 | static void snd_soc_exit(void) | 2284 | static void __exit snd_soc_exit(void) |
1880 | { | 2285 | { |
2286 | #ifdef CONFIG_DEBUG_FS | ||
2287 | debugfs_remove_recursive(debugfs_root); | ||
2288 | #endif | ||
1881 | platform_driver_unregister(&soc_driver); | 2289 | platform_driver_unregister(&soc_driver); |
1882 | } | 2290 | } |
1883 | 2291 | ||
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 7351db9606e4..8863eddbac02 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <linux/bitops.h> | 37 | #include <linux/bitops.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/jiffies.h> | 39 | #include <linux/jiffies.h> |
40 | #include <linux/debugfs.h> | ||
41 | #include <sound/core.h> | 40 | #include <sound/core.h> |
42 | #include <sound/pcm.h> | 41 | #include <sound/pcm.h> |
43 | #include <sound/pcm_params.h> | 42 | #include <sound/pcm_params.h> |
@@ -67,17 +66,13 @@ static int dapm_status = 1; | |||
67 | module_param(dapm_status, int, 0); | 66 | module_param(dapm_status, int, 0); |
68 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); | 67 | MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); |
69 | 68 | ||
70 | static struct dentry *asoc_debugfs; | 69 | static void pop_wait(u32 pop_time) |
71 | |||
72 | static u32 pop_time; | ||
73 | |||
74 | static void pop_wait(void) | ||
75 | { | 70 | { |
76 | if (pop_time) | 71 | if (pop_time) |
77 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); | 72 | schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); |
78 | } | 73 | } |
79 | 74 | ||
80 | static void pop_dbg(const char *fmt, ...) | 75 | static void pop_dbg(u32 pop_time, const char *fmt, ...) |
81 | { | 76 | { |
82 | va_list args; | 77 | va_list args; |
83 | 78 | ||
@@ -85,7 +80,7 @@ static void pop_dbg(const char *fmt, ...) | |||
85 | 80 | ||
86 | if (pop_time) { | 81 | if (pop_time) { |
87 | vprintk(fmt, args); | 82 | vprintk(fmt, args); |
88 | pop_wait(); | 83 | pop_wait(pop_time); |
89 | } | 84 | } |
90 | 85 | ||
91 | va_end(args); | 86 | va_end(args); |
@@ -230,10 +225,11 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget) | |||
230 | 225 | ||
231 | change = old != new; | 226 | change = old != new; |
232 | if (change) { | 227 | if (change) { |
233 | pop_dbg("pop test %s : %s in %d ms\n", widget->name, | 228 | pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", |
234 | widget->power ? "on" : "off", pop_time); | 229 | widget->name, widget->power ? "on" : "off", |
230 | codec->pop_time); | ||
235 | snd_soc_write(codec, widget->reg, new); | 231 | snd_soc_write(codec, widget->reg, new); |
236 | pop_wait(); | 232 | pop_wait(codec->pop_time); |
237 | } | 233 | } |
238 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, | 234 | pr_debug("reg %x old %x new %x change %d\n", widget->reg, |
239 | old, new, change); | 235 | old, new, change); |
@@ -293,7 +289,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
293 | struct snd_soc_dapm_widget *w) | 289 | struct snd_soc_dapm_widget *w) |
294 | { | 290 | { |
295 | int i, ret = 0; | 291 | int i, ret = 0; |
296 | char name[32]; | 292 | size_t name_len; |
297 | struct snd_soc_dapm_path *path; | 293 | struct snd_soc_dapm_path *path; |
298 | 294 | ||
299 | /* add kcontrol */ | 295 | /* add kcontrol */ |
@@ -307,11 +303,16 @@ static int dapm_new_mixer(struct snd_soc_codec *codec, | |||
307 | continue; | 303 | continue; |
308 | 304 | ||
309 | /* add dapm control with long name */ | 305 | /* add dapm control with long name */ |
310 | snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name); | 306 | name_len = 2 + strlen(w->name) |
311 | path->long_name = kstrdup (name, GFP_KERNEL); | 307 | + strlen(w->kcontrols[i].name); |
308 | path->long_name = kmalloc(name_len, GFP_KERNEL); | ||
312 | if (path->long_name == NULL) | 309 | if (path->long_name == NULL) |
313 | return -ENOMEM; | 310 | return -ENOMEM; |
314 | 311 | ||
312 | snprintf(path->long_name, name_len, "%s %s", | ||
313 | w->name, w->kcontrols[i].name); | ||
314 | path->long_name[name_len - 1] = '\0'; | ||
315 | |||
315 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, | 316 | path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, |
316 | path->long_name); | 317 | path->long_name); |
317 | ret = snd_ctl_add(codec->card, path->kcontrol); | 318 | ret = snd_ctl_add(codec->card, path->kcontrol); |
@@ -821,23 +822,9 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); | |||
821 | 822 | ||
822 | int snd_soc_dapm_sys_add(struct device *dev) | 823 | int snd_soc_dapm_sys_add(struct device *dev) |
823 | { | 824 | { |
824 | int ret = 0; | ||
825 | |||
826 | if (!dapm_status) | 825 | if (!dapm_status) |
827 | return 0; | 826 | return 0; |
828 | 827 | return device_create_file(dev, &dev_attr_dapm_widget); | |
829 | ret = device_create_file(dev, &dev_attr_dapm_widget); | ||
830 | if (ret != 0) | ||
831 | return ret; | ||
832 | |||
833 | asoc_debugfs = debugfs_create_dir("asoc", NULL); | ||
834 | if (!IS_ERR(asoc_debugfs) && asoc_debugfs) | ||
835 | debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs, | ||
836 | &pop_time); | ||
837 | else | ||
838 | asoc_debugfs = NULL; | ||
839 | |||
840 | return 0; | ||
841 | } | 828 | } |
842 | 829 | ||
843 | static void snd_soc_dapm_sys_remove(struct device *dev) | 830 | static void snd_soc_dapm_sys_remove(struct device *dev) |
@@ -845,9 +832,6 @@ static void snd_soc_dapm_sys_remove(struct device *dev) | |||
845 | if (dapm_status) { | 832 | if (dapm_status) { |
846 | device_remove_file(dev, &dev_attr_dapm_widget); | 833 | device_remove_file(dev, &dev_attr_dapm_widget); |
847 | } | 834 | } |
848 | |||
849 | if (asoc_debugfs) | ||
850 | debugfs_remove_recursive(asoc_debugfs); | ||
851 | } | 835 | } |
852 | 836 | ||
853 | /* free all dapm widgets and resources */ | 837 | /* free all dapm widgets and resources */ |
@@ -1007,28 +991,6 @@ err: | |||
1007 | } | 991 | } |
1008 | 992 | ||
1009 | /** | 993 | /** |
1010 | * snd_soc_dapm_connect_input - connect dapm widgets | ||
1011 | * @codec: audio codec | ||
1012 | * @sink: name of target widget | ||
1013 | * @control: mixer control name | ||
1014 | * @source: name of source name | ||
1015 | * | ||
1016 | * Connects 2 dapm widgets together via a named audio path. The sink is | ||
1017 | * the widget receiving the audio signal, whilst the source is the sender | ||
1018 | * of the audio signal. | ||
1019 | * | ||
1020 | * This function has been deprecated in favour of snd_soc_dapm_add_routes(). | ||
1021 | * | ||
1022 | * Returns 0 for success else error. | ||
1023 | */ | ||
1024 | int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink, | ||
1025 | const char *control, const char *source) | ||
1026 | { | ||
1027 | return snd_soc_dapm_add_route(codec, sink, control, source); | ||
1028 | } | ||
1029 | EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input); | ||
1030 | |||
1031 | /** | ||
1032 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets | 994 | * snd_soc_dapm_add_routes - Add routes between DAPM widgets |
1033 | * @codec: codec | 995 | * @codec: codec |
1034 | * @route: audio routes | 996 | * @route: audio routes |
@@ -1358,8 +1320,12 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, | |||
1358 | 1320 | ||
1359 | for (i = 0; i < num; i++) { | 1321 | for (i = 0; i < num; i++) { |
1360 | ret = snd_soc_dapm_new_control(codec, widget); | 1322 | ret = snd_soc_dapm_new_control(codec, widget); |
1361 | if (ret < 0) | 1323 | if (ret < 0) { |
1324 | printk(KERN_ERR | ||
1325 | "ASoC: Failed to create DAPM control %s: %d\n", | ||
1326 | widget->name, ret); | ||
1362 | return ret; | 1327 | return ret; |
1328 | } | ||
1363 | widget++; | 1329 | widget++; |
1364 | } | 1330 | } |
1365 | return 0; | 1331 | return 0; |
@@ -1440,11 +1406,11 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, | |||
1440 | enum snd_soc_bias_level level) | 1406 | enum snd_soc_bias_level level) |
1441 | { | 1407 | { |
1442 | struct snd_soc_codec *codec = socdev->codec; | 1408 | struct snd_soc_codec *codec = socdev->codec; |
1443 | struct snd_soc_machine *machine = socdev->machine; | 1409 | struct snd_soc_card *card = socdev->card; |
1444 | int ret = 0; | 1410 | int ret = 0; |
1445 | 1411 | ||
1446 | if (machine->set_bias_level) | 1412 | if (card->set_bias_level) |
1447 | ret = machine->set_bias_level(machine, level); | 1413 | ret = card->set_bias_level(card, level); |
1448 | if (ret == 0 && codec->set_bias_level) | 1414 | if (ret == 0 && codec->set_bias_level) |
1449 | ret = codec->set_bias_level(codec, level); | 1415 | ret = codec->set_bias_level(codec, level); |
1450 | 1416 | ||
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c index 798ca124da58..ccd763dd7167 100644 --- a/sound/usb/caiaq/caiaq-control.c +++ b/sound/usb/caiaq/caiaq-control.c | |||
@@ -247,69 +247,56 @@ static struct caiaq_controller a8dj_controller[] = { | |||
247 | { "Software lock", 40 } | 247 | { "Software lock", 40 } |
248 | }; | 248 | }; |
249 | 249 | ||
250 | int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) | 250 | static int __devinit add_controls(struct caiaq_controller *c, int num, |
251 | struct snd_usb_caiaqdev *dev) | ||
251 | { | 252 | { |
252 | int i; | 253 | int i, ret; |
253 | struct snd_kcontrol *kc; | 254 | struct snd_kcontrol *kc; |
254 | 255 | ||
256 | for (i = 0; i < num; i++, c++) { | ||
257 | kcontrol_template.name = c->name; | ||
258 | kcontrol_template.private_value = c->index; | ||
259 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
260 | ret = snd_ctl_add(dev->chip.card, kc); | ||
261 | if (ret < 0) | ||
262 | return ret; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev) | ||
269 | { | ||
270 | int ret = 0; | ||
271 | |||
255 | switch (dev->chip.usb_id) { | 272 | switch (dev->chip.usb_id) { |
256 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): | 273 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1): |
257 | for (i = 0; i < ARRAY_SIZE(ak1_controller); i++) { | 274 | ret = add_controls(ak1_controller, |
258 | struct caiaq_controller *c = ak1_controller + i; | 275 | ARRAY_SIZE(ak1_controller), dev); |
259 | kcontrol_template.name = c->name; | ||
260 | kcontrol_template.private_value = c->index; | ||
261 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
262 | snd_ctl_add(dev->chip.card, kc); | ||
263 | } | ||
264 | |||
265 | break; | 276 | break; |
266 | 277 | ||
267 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): | 278 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2): |
268 | for (i = 0; i < ARRAY_SIZE(rk2_controller); i++) { | 279 | ret = add_controls(rk2_controller, |
269 | struct caiaq_controller *c = rk2_controller + i; | 280 | ARRAY_SIZE(rk2_controller), dev); |
270 | kcontrol_template.name = c->name; | ||
271 | kcontrol_template.private_value = c->index; | ||
272 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
273 | snd_ctl_add(dev->chip.card, kc); | ||
274 | } | ||
275 | |||
276 | break; | 281 | break; |
277 | 282 | ||
278 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): | 283 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3): |
279 | for (i = 0; i < ARRAY_SIZE(rk3_controller); i++) { | 284 | ret = add_controls(rk3_controller, |
280 | struct caiaq_controller *c = rk3_controller + i; | 285 | ARRAY_SIZE(rk3_controller), dev); |
281 | kcontrol_template.name = c->name; | ||
282 | kcontrol_template.private_value = c->index; | ||
283 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
284 | snd_ctl_add(dev->chip.card, kc); | ||
285 | } | ||
286 | |||
287 | break; | 286 | break; |
288 | 287 | ||
289 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): | 288 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): |
290 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): | 289 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): |
291 | for (i = 0; i < ARRAY_SIZE(kore_controller); i++) { | 290 | ret = add_controls(kore_controller, |
292 | struct caiaq_controller *c = kore_controller + i; | 291 | ARRAY_SIZE(kore_controller), dev); |
293 | kcontrol_template.name = c->name; | ||
294 | kcontrol_template.private_value = c->index; | ||
295 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
296 | snd_ctl_add(dev->chip.card, kc); | ||
297 | } | ||
298 | |||
299 | break; | 292 | break; |
300 | 293 | ||
301 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): | 294 | case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ): |
302 | for (i = 0; i < ARRAY_SIZE(a8dj_controller); i++) { | 295 | ret = add_controls(a8dj_controller, |
303 | struct caiaq_controller *c = a8dj_controller + i; | 296 | ARRAY_SIZE(a8dj_controller), dev); |
304 | kcontrol_template.name = c->name; | ||
305 | kcontrol_template.private_value = c->index; | ||
306 | kc = snd_ctl_new1(&kcontrol_template, dev); | ||
307 | snd_ctl_add(dev->chip.card, kc); | ||
308 | } | ||
309 | |||
310 | break; | 297 | break; |
311 | } | 298 | } |
312 | 299 | ||
313 | return 0; | 300 | return ret; |
314 | } | 301 | } |
315 | 302 | ||
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c index 83175083e50f..b143ef7152f7 100644 --- a/sound/usb/caiaq/caiaq-device.c +++ b/sound/usb/caiaq/caiaq-device.c | |||
@@ -42,7 +42,7 @@ | |||
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); | 44 | MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>"); |
45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.8"); | 45 | MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9"); |
46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," | 47 | MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2}," |
48 | "{Native Instruments, RigKontrol3}," | 48 | "{Native Instruments, RigKontrol3}," |
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index ff23cc1ce3b9..70b96355ca4c 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c | |||
@@ -276,7 +276,8 @@ static void subs_set_complete(struct urb **urbs, void (*complete)(struct urb *)) | |||
276 | } | 276 | } |
277 | } | 277 | } |
278 | 278 | ||
279 | int usb_stream_prepare_playback(struct usb_stream_kernel *sk, struct urb *inurb) | 279 | static int usb_stream_prepare_playback(struct usb_stream_kernel *sk, |
280 | struct urb *inurb) | ||
280 | { | 281 | { |
281 | struct usb_stream *s = sk->s; | 282 | struct usb_stream *s = sk->s; |
282 | struct urb *io; | 283 | struct urb *io; |