diff options
89 files changed, 8426 insertions, 399 deletions
@@ -2212,13 +2212,13 @@ S: 2300 Copenhagen S | |||
2212 | S: Denmark | 2212 | S: Denmark |
2213 | 2213 | ||
2214 | N: Claudio S. Matsuoka | 2214 | N: Claudio S. Matsuoka |
2215 | E: claudio@conectiva.com | 2215 | E: cmatsuoka@gmail.com |
2216 | E: claudio@helllabs.org | 2216 | E: claudio@mandriva.com |
2217 | W: http://helllabs.org/~claudio | 2217 | W: http://helllabs.org/~claudio |
2218 | D: V4L, OV511 driver hacks | 2218 | D: V4L, OV511 and HDA-codec hacks |
2219 | S: Conectiva S.A. | 2219 | S: Conectiva S.A. |
2220 | S: R. Tocantins 89 | 2220 | S: Souza Naves 1250 |
2221 | S: 80050-430 Curitiba PR | 2221 | S: 80050-040 Curitiba PR |
2222 | S: Brazil | 2222 | S: Brazil |
2223 | 2223 | ||
2224 | N: Heinz Mauelshagen | 2224 | N: Heinz Mauelshagen |
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 355ff0a2bb7c..241e26c4ff92 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt | |||
@@ -467,7 +467,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
467 | above explicitly. | 467 | above explicitly. |
468 | 468 | ||
469 | The power-management is supported. | 469 | The power-management is supported. |
470 | 470 | ||
471 | Module snd-cs5530 | ||
472 | _________________ | ||
473 | |||
474 | Module for Cyrix/NatSemi Geode 5530 chip. | ||
475 | |||
471 | Module snd-cs5535audio | 476 | Module snd-cs5535audio |
472 | ---------------------- | 477 | ---------------------- |
473 | 478 | ||
@@ -759,6 +764,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
759 | 764 | ||
760 | model - force the model name | 765 | model - force the model name |
761 | position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) | 766 | position_fix - Fix DMA pointer (0 = auto, 1 = none, 2 = POSBUF, 3 = FIFO size) |
767 | probe_mask - Bitmask to probe codecs (default = -1, meaning all slots) | ||
762 | single_cmd - Use single immediate commands to communicate with | 768 | single_cmd - Use single immediate commands to communicate with |
763 | codecs (for debugging only) | 769 | codecs (for debugging only) |
764 | enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) | 770 | enable_msi - Enable Message Signaled Interrupt (MSI) (default = off) |
@@ -803,6 +809,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
803 | hp-3013 HP machines (3013-variant) | 809 | hp-3013 HP machines (3013-variant) |
804 | fujitsu Fujitsu S7020 | 810 | fujitsu Fujitsu S7020 |
805 | acer Acer TravelMate | 811 | acer Acer TravelMate |
812 | will Will laptops (PB V7900) | ||
813 | replacer Replacer 672V | ||
806 | basic fixed pin assignment (old default model) | 814 | basic fixed pin assignment (old default model) |
807 | auto auto-config reading BIOS (default) | 815 | auto auto-config reading BIOS (default) |
808 | 816 | ||
@@ -811,16 +819,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
811 | hp-bpc HP xw4400/6400/8400/9400 laptops | 819 | hp-bpc HP xw4400/6400/8400/9400 laptops |
812 | hp-bpc-d7000 HP BPC D7000 | 820 | hp-bpc-d7000 HP BPC D7000 |
813 | benq Benq ED8 | 821 | benq Benq ED8 |
822 | benq-t31 Benq T31 | ||
814 | hippo Hippo (ATI) with jack detection, Sony UX-90s | 823 | hippo Hippo (ATI) with jack detection, Sony UX-90s |
815 | hippo_1 Hippo (Benq) with jack detection | 824 | hippo_1 Hippo (Benq) with jack detection |
825 | sony-assamd Sony ASSAMD | ||
816 | basic fixed pin assignment w/o SPDIF | 826 | basic fixed pin assignment w/o SPDIF |
817 | auto auto-config reading BIOS (default) | 827 | auto auto-config reading BIOS (default) |
818 | 828 | ||
829 | ALC268 | ||
830 | 3stack 3-stack model | ||
831 | auto auto-config reading BIOS (default) | ||
832 | |||
833 | ALC662 | ||
834 | 3stack-dig 3-stack (2-channel) with SPDIF | ||
835 | 3stack-6ch 3-stack (6-channel) | ||
836 | 3stack-6ch-dig 3-stack (6-channel) with SPDIF | ||
837 | 6stack-dig 6-stack with SPDIF | ||
838 | lenovo-101e Lenovo laptop | ||
839 | auto auto-config reading BIOS (default) | ||
840 | |||
819 | ALC882/885 | 841 | ALC882/885 |
820 | 3stack-dig 3-jack with SPDIF I/O | 842 | 3stack-dig 3-jack with SPDIF I/O |
821 | 6stack-dig 6-jack digital with SPDIF I/O | 843 | 6stack-dig 6-jack digital with SPDIF I/O |
822 | arima Arima W820Di1 | 844 | arima Arima W820Di1 |
823 | macpro MacPro support | 845 | macpro MacPro support |
846 | imac24 iMac 24'' with jack detection | ||
824 | w2jc ASUS W2JC | 847 | w2jc ASUS W2JC |
825 | auto auto-config reading BIOS (default) | 848 | auto auto-config reading BIOS (default) |
826 | 849 | ||
@@ -832,9 +855,15 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
832 | 6stack-dig-demo 6-jack digital for Intel demo board | 855 | 6stack-dig-demo 6-jack digital for Intel demo board |
833 | acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) | 856 | acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) |
834 | medion Medion Laptops | 857 | medion Medion Laptops |
858 | medion-md2 Medion MD2 | ||
835 | targa-dig Targa/MSI | 859 | targa-dig Targa/MSI |
836 | targa-2ch-dig Targs/MSI with 2-channel | 860 | targa-2ch-dig Targs/MSI with 2-channel |
837 | laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE) | 861 | laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE) |
862 | lenovo-101e Lenovo 101E | ||
863 | lenovo-nb0763 Lenovo NB0763 | ||
864 | lenovo-ms7195-dig Lenovo MS7195 | ||
865 | 6stack-hp HP machines with 6stack (Nettle boards) | ||
866 | 3stack-hp HP machines with 3stack (Lucknow, Samba boards) | ||
838 | auto auto-config reading BIOS (default) | 867 | auto auto-config reading BIOS (default) |
839 | 868 | ||
840 | ALC861/660 | 869 | ALC861/660 |
@@ -853,7 +882,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
853 | 3stack-dig 3-jack with SPDIF OUT | 882 | 3stack-dig 3-jack with SPDIF OUT |
854 | 6stack-dig 6-jack with SPDIF OUT | 883 | 6stack-dig 6-jack with SPDIF OUT |
855 | 3stack-660 3-jack (for ALC660VD) | 884 | 3stack-660 3-jack (for ALC660VD) |
885 | 3stack-660-digout 3-jack with SPDIF OUT (for ALC660VD) | ||
856 | lenovo Lenovo 3000 C200 | 886 | lenovo Lenovo 3000 C200 |
887 | dallas Dallas laptops | ||
857 | auto auto-config reading BIOS (default) | 888 | auto auto-config reading BIOS (default) |
858 | 889 | ||
859 | CMI9880 | 890 | CMI9880 |
@@ -864,12 +895,26 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
864 | allout 5-jack in back, 2-jack in front, SPDIF out | 895 | allout 5-jack in back, 2-jack in front, SPDIF out |
865 | auto auto-config reading BIOS (default) | 896 | auto auto-config reading BIOS (default) |
866 | 897 | ||
898 | AD1882 | ||
899 | 3stack 3-stack mode (default) | ||
900 | 6stack 6-stack mode | ||
901 | |||
902 | AD1884 | ||
903 | N/A | ||
904 | |||
867 | AD1981 | 905 | AD1981 |
868 | basic 3-jack (default) | 906 | basic 3-jack (default) |
869 | hp HP nx6320 | 907 | hp HP nx6320 |
870 | thinkpad Lenovo Thinkpad T60/X60/Z60 | 908 | thinkpad Lenovo Thinkpad T60/X60/Z60 |
871 | toshiba Toshiba U205 | 909 | toshiba Toshiba U205 |
872 | 910 | ||
911 | AD1983 | ||
912 | N/A | ||
913 | |||
914 | AD1984 | ||
915 | basic default configuration | ||
916 | thinkpad Lenovo Thinkpad T61/X61 | ||
917 | |||
873 | AD1986A | 918 | AD1986A |
874 | 6stack 6-jack, separate surrounds (default) | 919 | 6stack 6-jack, separate surrounds (default) |
875 | 3stack 3-stack, shared surrounds | 920 | 3stack 3-stack, shared surrounds |
@@ -907,11 +952,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
907 | ref Reference board | 952 | ref Reference board |
908 | 3stack D945 3stack | 953 | 3stack D945 3stack |
909 | 5stack D945 5stack + SPDIF | 954 | 5stack D945 5stack + SPDIF |
910 | macmini Intel Mac Mini | 955 | dell Dell XPS M1210 |
911 | macbook Intel Mac Book | 956 | intel-mac-v1 Intel Mac Type 1 |
912 | macbook-pro-v1 Intel Mac Book Pro 1st generation | 957 | intel-mac-v2 Intel Mac Type 2 |
913 | macbook-pro Intel Mac Book Pro 2nd generation | 958 | intel-mac-v3 Intel Mac Type 3 |
914 | imac-intel Intel iMac | 959 | intel-mac-v4 Intel Mac Type 4 |
960 | intel-mac-v5 Intel Mac Type 5 | ||
961 | macmini Intel Mac Mini (equivalent with type 3) | ||
962 | macbook Intel Mac Book (eq. type 5) | ||
963 | macbook-pro-v1 Intel Mac Book Pro 1st generation (eq. type 3) | ||
964 | macbook-pro Intel Mac Book Pro 2nd generation (eq. type 3) | ||
965 | imac-intel Intel iMac (eq. type 2) | ||
966 | imac-intel-20 Intel iMac (newer version) (eq. type 3) | ||
915 | 967 | ||
916 | STAC9202/9250/9251 | 968 | STAC9202/9250/9251 |
917 | ref Reference board, base config | 969 | ref Reference board, base config |
@@ -956,6 +1008,17 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. | |||
956 | from the irq. Remember this is a last resort, and should be | 1008 | from the irq. Remember this is a last resort, and should be |
957 | avoided as much as possible... | 1009 | avoided as much as possible... |
958 | 1010 | ||
1011 | MORE NOTES ON "azx_get_response timeout" PROBLEMS: | ||
1012 | On some hardwares, you may need to add a proper probe_mask option | ||
1013 | to avoid the "azx_get_response timeout" problem above, instead. | ||
1014 | This occurs when the access to non-existing or non-working codec slot | ||
1015 | (likely a modem one) causes a stall of the communication via HD-audio | ||
1016 | bus. You can see which codec slots are probed by enabling | ||
1017 | CONFIG_SND_DEBUG_DETECT, or simply from the file name of the codec | ||
1018 | proc files. Then limit the slots to probe by probe_mask option. | ||
1019 | For example, probe_mask=1 means to probe only the first slot, and | ||
1020 | probe_mask=4 means only the third slot. | ||
1021 | |||
959 | The power-management is supported. | 1022 | The power-management is supported. |
960 | 1023 | ||
961 | Module snd-hdsp | 1024 | Module snd-hdsp |
diff --git a/Documentation/sound/alsa/Audiophile-Usb.txt b/Documentation/sound/alsa/Audiophile-Usb.txt index e40cce83327c..2ad5e6306c44 100644 --- a/Documentation/sound/alsa/Audiophile-Usb.txt +++ b/Documentation/sound/alsa/Audiophile-Usb.txt | |||
@@ -1,4 +1,4 @@ | |||
1 | Guide to using M-Audio Audiophile USB with ALSA and Jack v1.3 | 1 | Guide to using M-Audio Audiophile USB with ALSA and Jack v1.5 |
2 | ======================================================== | 2 | ======================================================== |
3 | 3 | ||
4 | Thibault Le Meur <Thibault.LeMeur@supelec.fr> | 4 | Thibault Le Meur <Thibault.LeMeur@supelec.fr> |
@@ -6,8 +6,19 @@ | |||
6 | This document is a guide to using the M-Audio Audiophile USB (tm) device with | 6 | This document is a guide to using the M-Audio Audiophile USB (tm) device with |
7 | ALSA and JACK. | 7 | ALSA and JACK. |
8 | 8 | ||
9 | History | ||
10 | ======= | ||
11 | * v1.4 - Thibault Le Meur (2007-07-11) | ||
12 | - Added Low Endianness nature of 16bits-modes | ||
13 | found by Hakan Lennestal <Hakan.Lennestal@brfsodrahamn.se> | ||
14 | - Modifying document structure | ||
15 | * v1.5 - Thibault Le Meur (2007-07-12) | ||
16 | - Added AC3/DTS passthru info | ||
17 | |||
18 | |||
9 | 1 - Audiophile USB Specs and correct usage | 19 | 1 - Audiophile USB Specs and correct usage |
10 | ========================================== | 20 | ========================================== |
21 | |||
11 | This part is a reminder of important facts about the functions and limitations | 22 | This part is a reminder of important facts about the functions and limitations |
12 | of the device. | 23 | of the device. |
13 | 24 | ||
@@ -25,18 +36,18 @@ The device has 4 audio interfaces, and 2 MIDI ports: | |||
25 | The internal DAC/ADC has the following characteristics: | 36 | The internal DAC/ADC has the following characteristics: |
26 | * sample depth of 16 or 24 bits | 37 | * sample depth of 16 or 24 bits |
27 | * sample rate from 8kHz to 96kHz | 38 | * sample rate from 8kHz to 96kHz |
28 | * Two ports can't use different sample depths at the same time. Moreover, the | 39 | * Two interfaces can't use different sample depths at the same time. |
29 | Audiophile USB documentation gives the following Warning: "Please exit any | 40 | Moreover, the Audiophile USB documentation gives the following Warning: |
30 | audio application running before switching between bit depths" | 41 | "Please exit any audio application running before switching between bit depths" |
31 | 42 | ||
32 | Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be | 43 | Due to the USB 1.1 bandwidth limitation, a limited number of interfaces can be |
33 | activated at the same time depending on the audio mode selected: | 44 | activated at the same time depending on the audio mode selected: |
34 | * 16-bit/48kHz ==> 4 channels in/4 channels out | 45 | * 16-bit/48kHz ==> 4 channels in + 4 channels out |
35 | - Ai+Ao+Di+Do | 46 | - Ai+Ao+Di+Do |
36 | * 24-bit/48kHz ==> 4 channels in/2 channels out, | 47 | * 24-bit/48kHz ==> 4 channels in + 2 channels out, |
37 | or 2 channels in/4 channels out | 48 | or 2 channels in + 4 channels out |
38 | - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do | 49 | - Ai+Ao+Do or Ai+Di+Ao or Ai+Di+Do or Di+Ao+Do |
39 | * 24-bit/96kHz ==> 2 channels in, or 2 channels out (half duplex only) | 50 | * 24-bit/96kHz ==> 2 channels in _or_ 2 channels out (half duplex only) |
40 | - Ai or Ao or Di or Do | 51 | - Ai or Ao or Di or Do |
41 | 52 | ||
42 | Important facts about the Digital interface: | 53 | Important facts about the Digital interface: |
@@ -52,44 +63,56 @@ source is connected | |||
52 | synchronization error (for instance sound played at an odd sample rate) | 63 | synchronization error (for instance sound played at an odd sample rate) |
53 | 64 | ||
54 | 65 | ||
55 | 2 - Audiophile USB support in ALSA | 66 | 2 - Audiophile USB MIDI support in ALSA |
56 | ================================== | 67 | ======================================= |
57 | 68 | ||
58 | 2.1 - MIDI ports | 69 | The Audiophile USB MIDI ports will be automatically supported once the |
59 | ---------------- | ||
60 | The Audiophile USB MIDI ports will be automatically supported once the | ||
61 | following modules have been loaded: | 70 | following modules have been loaded: |
62 | * snd-usb-audio | 71 | * snd-usb-audio |
63 | * snd-seq-midi | 72 | * snd-seq-midi |
64 | 73 | ||
65 | No additional setting is required. | 74 | No additional setting is required. |
66 | 75 | ||
67 | 2.2 - Audio ports | 76 | |
68 | ----------------- | 77 | 3 - Audiophile USB Audio support in ALSA |
78 | ======================================== | ||
69 | 79 | ||
70 | Audio functions of the Audiophile USB device are handled by the snd-usb-audio | 80 | Audio functions of the Audiophile USB device are handled by the snd-usb-audio |
71 | module. This module can work in a default mode (without any device-specific | 81 | module. This module can work in a default mode (without any device-specific |
72 | parameter), or in an "advanced" mode with the device-specific parameter called | 82 | parameter), or in an "advanced" mode with the device-specific parameter called |
73 | "device_setup". | 83 | "device_setup". |
74 | 84 | ||
75 | 2.2.1 - Default Alsa driver mode | 85 | 3.1 - Default Alsa driver mode |
76 | 86 | ------------------------------ | |
77 | The default behavior of the snd-usb-audio driver is to parse the device | 87 | |
78 | capabilities at startup and enable all functions inside the device (including | 88 | The default behavior of the snd-usb-audio driver is to list the device |
79 | all ports at any supported sample rates and sample depths). This approach | 89 | capabilities at startup and activate the required mode when required |
80 | has the advantage to let the driver easily switch from sample rates/depths | 90 | by the applications: for instance if the user is recording in a |
81 | automatically according to the need of the application claiming the device. | 91 | 24bit-depth-mode and immediately after wants to switch to a 16bit-depth mode, |
82 | 92 | the snd-usb-audio module will reconfigure the device on the fly. | |
83 | In this case the Audiophile ports are mapped to alsa pcm devices in the | 93 | |
84 | following way (I suppose the device's index is 1): | 94 | This approach has the advantage to let the driver automatically switch from sample |
95 | rates/depths automatically according to the user's needs. However, those who | ||
96 | are using the device under windows know that this is not how the device is meant to | ||
97 | work: under windows applications must be closed before using the m-audio control | ||
98 | panel to switch the device working mode. Thus as we'll see in next section, this | ||
99 | Default Alsa driver mode can lead to device misconfigurations. | ||
100 | |||
101 | Let's get back to the Default Alsa driver mode for now. In this case the | ||
102 | Audiophile interfaces are mapped to alsa pcm devices in the following | ||
103 | way (I suppose the device's index is 1): | ||
85 | * hw:1,0 is Ao in playback and Di in capture | 104 | * hw:1,0 is Ao in playback and Di in capture |
86 | * hw:1,1 is Do in playback and Ai in capture | 105 | * hw:1,1 is Do in playback and Ai in capture |
87 | * hw:1,2 is Do in AC3/DTS passthrough mode | 106 | * hw:1,2 is Do in AC3/DTS passthrough mode |
88 | 107 | ||
89 | You must note as well that the device uses Big Endian byte encoding so that | 108 | In this mode, the device uses Big Endian byte-encoding so that |
90 | supported audio format are S16_BE for 16-bit depth modes and S24_3BE for | 109 | supported audio format are S16_BE for 16-bit depth modes and S24_3BE for |
91 | 24-bits depth mode. One exception is the hw:1,2 port which is Little Endian | 110 | 24-bits depth mode. |
92 | compliant and thus uses S16_LE. | 111 | |
112 | One exception is the hw:1,2 port which was reported to be Little Endian | ||
113 | compliant (supposedly supporting S16_LE) but processes in fact only S16_BE streams. | ||
114 | This has been fixed in kernel 2.6.23 and above and now the hw:1,2 interface | ||
115 | is reported to be big endian in this default driver mode. | ||
93 | 116 | ||
94 | Examples: | 117 | Examples: |
95 | * playing a S24_3BE encoded raw file to the Ao port | 118 | * playing a S24_3BE encoded raw file to the Ao port |
@@ -98,22 +121,26 @@ Examples: | |||
98 | % arecord -D hw:1,1 -c2 -t raw -r48000 -fS24_3BE test.raw | 121 | % arecord -D hw:1,1 -c2 -t raw -r48000 -fS24_3BE test.raw |
99 | * playing a S16_BE encoded raw file to the Do port | 122 | * playing a S16_BE encoded raw file to the Do port |
100 | % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw | 123 | % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test.raw |
124 | * playing an ac3 sample file to the Do port | ||
125 | % aplay -D hw:1,2 --channels=6 ac3_S16_BE_encoded_file.raw | ||
101 | 126 | ||
102 | If you're happy with the default Alsa driver setup and don't experience any | 127 | If you're happy with the default Alsa driver mode and don't experience any |
103 | issue with this mode, then you can skip the following chapter. | 128 | issue with this mode, then you can skip the following chapter. |
104 | 129 | ||
105 | 2.2.2 - Advanced module setup | 130 | 3.2 - Advanced module setup |
131 | --------------------------- | ||
106 | 132 | ||
107 | Due to the hardware constraints described above, the device initialization made | 133 | Due to the hardware constraints described above, the device initialization made |
108 | by the Alsa driver in default mode may result in a corrupted state of the | 134 | by the Alsa driver in default mode may result in a corrupted state of the |
109 | device. For instance, a particularly annoying issue is that the sound captured | 135 | device. For instance, a particularly annoying issue is that the sound captured |
110 | from the Ai port sounds distorted (as if boosted with an excessive high volume | 136 | from the Ai interface sounds distorted (as if boosted with an excessive high |
111 | gain). | 137 | volume gain). |
112 | 138 | ||
113 | For people having this problem, the snd-usb-audio module has a new module | 139 | For people having this problem, the snd-usb-audio module has a new module |
114 | parameter called "device_setup". | 140 | parameter called "device_setup" (this parameter was introduced in kernel |
141 | release 2.6.17) | ||
115 | 142 | ||
116 | 2.2.2.1 - Initializing the working mode of the Audiophile USB | 143 | 3.2.1 - Initializing the working mode of the Audiophile USB |
117 | 144 | ||
118 | As far as the Audiophile USB device is concerned, this value let the user | 145 | As far as the Audiophile USB device is concerned, this value let the user |
119 | specify: | 146 | specify: |
@@ -121,33 +148,57 @@ specify: | |||
121 | * the sample rate | 148 | * the sample rate |
122 | * whether the Di port is used or not | 149 | * whether the Di port is used or not |
123 | 150 | ||
124 | Here is a list of supported device_setup values for this device: | 151 | When initialized with "device_setup=0x00", the snd-usb-audio module has |
125 | * device_setup=0x00 (or omitted) | 152 | the same behaviour as when the parameter is omitted (see paragraph "Default |
126 | - Alsa driver default mode | 153 | Alsa driver mode" above) |
127 | - maintains backward compatibility with setups that do not use this | 154 | |
128 | parameter by not introducing any change | 155 | Others modes are described in the following subsections. |
129 | - results sometimes in corrupted sound as described earlier | 156 | |
157 | 3.2.1.1 - 16-bit modes | ||
158 | |||
159 | The two supported modes are: | ||
160 | |||
130 | * device_setup=0x01 | 161 | * device_setup=0x01 |
131 | - 16bits 48kHz mode with Di disabled | 162 | - 16bits 48kHz mode with Di disabled |
132 | - Ai,Ao,Do can be used at the same time | 163 | - Ai,Ao,Do can be used at the same time |
133 | - hw:1,0 is not available in capture mode | 164 | - hw:1,0 is not available in capture mode |
134 | - hw:1,2 is not available | 165 | - hw:1,2 is not available |
166 | |||
135 | * device_setup=0x11 | 167 | * device_setup=0x11 |
136 | - 16bits 48kHz mode with Di enabled | 168 | - 16bits 48kHz mode with Di enabled |
137 | - Ai,Ao,Di,Do can be used at the same time | 169 | - Ai,Ao,Di,Do can be used at the same time |
138 | - hw:1,0 is available in capture mode | 170 | - hw:1,0 is available in capture mode |
139 | - hw:1,2 is not available | 171 | - hw:1,2 is not available |
172 | |||
173 | In this modes the device operates only at 16bits-modes. Before kernel 2.6.23, | ||
174 | the devices where reported to be Big-Endian when in fact they were Little-Endian | ||
175 | so that playing a file was a matter of using: | ||
176 | % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_BE test_S16_LE.raw | ||
177 | where "test_S16_LE.raw" was in fact a little-endian sample file. | ||
178 | |||
179 | Thanks to Hakan Lennestal (who discovered the Little-Endiannes of the device in | ||
180 | these modes) a fix has been committed (expected in kernel 2.6.23) and | ||
181 | Alsa now reports Little-Endian interfaces. Thus playing a file now is as simple as | ||
182 | using: | ||
183 | % aplay -D hw:1,1 -c2 -t raw -r48000 -fS16_LE test_S16_LE.raw | ||
184 | |||
185 | 3.2.1.2 - 24-bit modes | ||
186 | |||
187 | The three supported modes are: | ||
188 | |||
140 | * device_setup=0x09 | 189 | * device_setup=0x09 |
141 | - 24bits 48kHz mode with Di disabled | 190 | - 24bits 48kHz mode with Di disabled |
142 | - Ai,Ao,Do can be used at the same time | 191 | - Ai,Ao,Do can be used at the same time |
143 | - hw:1,0 is not available in capture mode | 192 | - hw:1,0 is not available in capture mode |
144 | - hw:1,2 is not available | 193 | - hw:1,2 is not available |
194 | |||
145 | * device_setup=0x19 | 195 | * device_setup=0x19 |
146 | - 24bits 48kHz mode with Di enabled | 196 | - 24bits 48kHz mode with Di enabled |
147 | - 3 ports from {Ai,Ao,Di,Do} can be used at the same time | 197 | - 3 ports from {Ai,Ao,Di,Do} can be used at the same time |
148 | - hw:1,0 is available in capture mode and an active digital source must be | 198 | - hw:1,0 is available in capture mode and an active digital source must be |
149 | connected to Di | 199 | connected to Di |
150 | - hw:1,2 is not available | 200 | - hw:1,2 is not available |
201 | |||
151 | * device_setup=0x0D or 0x10 | 202 | * device_setup=0x0D or 0x10 |
152 | - 24bits 96kHz mode | 203 | - 24bits 96kHz mode |
153 | - Di is enabled by default for this mode but does not need to be connected | 204 | - Di is enabled by default for this mode but does not need to be connected |
@@ -155,34 +206,64 @@ Here is a list of supported device_setup values for this device: | |||
155 | - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time | 206 | - Only 1 port from {Ai,Ao,Di,Do} can be used at the same time |
156 | - hw:1,0 is available in captured mode | 207 | - hw:1,0 is available in captured mode |
157 | - hw:1,2 is not available | 208 | - hw:1,2 is not available |
209 | |||
210 | In these modes the device is only Big-Endian compliant (see "Default Alsa driver | ||
211 | mode" above for an aplay command example) | ||
212 | |||
213 | 3.2.1.3 - AC3 w/ DTS passthru mode | ||
214 | |||
215 | Thanks to Hakan Lennestal, I now have a report saying that this mode works. | ||
216 | |||
158 | * device_setup=0x03 | 217 | * device_setup=0x03 |
159 | - 16bits 48kHz mode with only the Do port enabled | 218 | - 16bits 48kHz mode with only the Do port enabled |
160 | - AC3 with DTS passthru (not tested) | 219 | - AC3 with DTS passthru |
161 | - Caution with this setup the Do port is mapped to the pcm device hw:1,0 | 220 | - Caution with this setup the Do port is mapped to the pcm device hw:1,0 |
162 | 221 | ||
163 | 2.2.2.2 - Setting and switching configurations with the device_setup parameter | 222 | The command line used to playback the AC3/DTS encoded .wav-files in this mode: |
223 | % aplay -D hw:1,0 --channels=6 ac3_S16_LE_encoded_file.raw | ||
224 | |||
225 | 3.2.2 - How to use the device_setup parameter | ||
226 | ---------------------------------------------- | ||
164 | 227 | ||
165 | The parameter can be given: | 228 | The parameter can be given: |
229 | |||
166 | * By manually probing the device (as root): | 230 | * By manually probing the device (as root): |
167 | # modprobe -r snd-usb-audio | 231 | # modprobe -r snd-usb-audio |
168 | # modprobe snd-usb-audio index=1 device_setup=0x09 | 232 | # modprobe snd-usb-audio index=1 device_setup=0x09 |
233 | |||
169 | * Or while configuring the modules options in your modules configuration file | 234 | * Or while configuring the modules options in your modules configuration file |
170 | - For Fedora distributions, edit the /etc/modprobe.conf file: | 235 | - For Fedora distributions, edit the /etc/modprobe.conf file: |
171 | alias snd-card-1 snd-usb-audio | 236 | alias snd-card-1 snd-usb-audio |
172 | options snd-usb-audio index=1 device_setup=0x09 | 237 | options snd-usb-audio index=1 device_setup=0x09 |
173 | 238 | ||
174 | IMPORTANT NOTE WHEN SWITCHING CONFIGURATION: | 239 | CAUTION when initializaing the device |
175 | ------------------------------------------- | 240 | ------------------------------------- |
176 | * You may need to _first_ initialize the module with the correct device_setup | 241 | |
177 | parameter and _only_after_ turn on the Audiophile USB device | 242 | * Correct initialization on the device requires that device_setup is given to |
178 | * This is especially true when switching the sample depth: | 243 | the module BEFORE the device is turned on. So, if you use the "manual probing" |
244 | method described above, take care to power-on the device AFTER this initialization. | ||
245 | |||
246 | * Failing to respect this will lead in a misconfiguration of the device. In this case | ||
247 | turn off the device, unproble the snd-usb-audio module, then probe it again with | ||
248 | correct device_setup parameter and then (and only then) turn on the device again. | ||
249 | |||
250 | * If you've correctly initialized the device in a valid mode and then want to switch | ||
251 | to another mode (possibly with another sample-depth), please use also the following | ||
252 | procedure: | ||
179 | - first turn off the device | 253 | - first turn off the device |
180 | - de-register the snd-usb-audio module (modprobe -r) | 254 | - de-register the snd-usb-audio module (modprobe -r) |
181 | - change the device_setup parameter by changing the device_setup | 255 | - change the device_setup parameter by changing the device_setup |
182 | option in /etc/modprobe.conf | 256 | option in /etc/modprobe.conf |
183 | - turn on the device | 257 | - turn on the device |
258 | * A workaround for this last issue has been applied to kernel 2.6.23, but it may not | ||
259 | be enough to ensure the 'stability' of the device initialization. | ||
184 | 260 | ||
185 | 2.2.2.3 - Audiophile USB's device_setup structure | 261 | 3.2.3 - Technical details for hackers |
262 | ------------------------------------- | ||
263 | This section is for hackers, wanting to understand details about the device | ||
264 | internals and how Alsa supports it. | ||
265 | |||
266 | 3.2.3.1 - Audiophile USB's device_setup structure | ||
186 | 267 | ||
187 | If you want to understand the device_setup magic numbers for the Audiophile | 268 | If you want to understand the device_setup magic numbers for the Audiophile |
188 | USB, you need some very basic understanding of binary computation. However, | 269 | USB, you need some very basic understanding of binary computation. However, |
@@ -228,12 +309,12 @@ Caution: | |||
228 | - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll | 309 | - choosing b2 will prepare all interfaces for 24bits/96kHz but you'll |
229 | only be able to use one at the same time | 310 | only be able to use one at the same time |
230 | 311 | ||
231 | 2.2.3 - USB implementation details for this device | 312 | 3.2.3.2 - USB implementation details for this device |
232 | 313 | ||
233 | You may safely skip this section if you're not interested in driver | 314 | You may safely skip this section if you're not interested in driver |
234 | development. | 315 | hacking. |
235 | 316 | ||
236 | This section describes some internal aspects of the device and summarize the | 317 | This section describes some internal aspects of the device and summarizes the |
237 | data I got by usb-snooping the windows and Linux drivers. | 318 | data I got by usb-snooping the windows and Linux drivers. |
238 | 319 | ||
239 | The M-Audio Audiophile USB has 7 USB Interfaces: | 320 | The M-Audio Audiophile USB has 7 USB Interfaces: |
@@ -293,43 +374,45 @@ parse_audio_endpoints function uses a quirk called | |||
293 | "audiophile_skip_setting_quirk" in order to prevent AltSettings not | 374 | "audiophile_skip_setting_quirk" in order to prevent AltSettings not |
294 | corresponding to device_setup from being registered in the driver. | 375 | corresponding to device_setup from being registered in the driver. |
295 | 376 | ||
296 | 3 - Audiophile USB and Jack support | 377 | 4 - Audiophile USB and Jack support |
297 | =================================== | 378 | =================================== |
298 | 379 | ||
299 | This section deals with support of the Audiophile USB device in Jack. | 380 | This section deals with support of the Audiophile USB device in Jack. |
300 | The main issue regarding this support is that the device is Big Endian | ||
301 | compliant. | ||
302 | 381 | ||
303 | 3.1 - Using the plug alsa plugin | 382 | There are 2 main potential issues when using Jackd with the device: |
304 | -------------------------------- | 383 | * support for Big-Endian devices in 24-bit modes |
384 | * support for 4-in / 4-out channels | ||
385 | |||
386 | 4.1 - Direct support in Jackd | ||
387 | ----------------------------- | ||
305 | 388 | ||
306 | Jack doesn't directly support big endian devices. Thus, one way to have support | 389 | Jack supports big endian devices only in recent versions (thanks to |
307 | for this device with Alsa is to use the Alsa "plug" converter. | 390 | Andreas Steinmetz for his first big-endian patch). I can't remember |
391 | extacly when this support was released into jackd, let's just say that | ||
392 | with jackd version 0.103.0 it's almost ok (just a small bug is affecting | ||
393 | 16bits Big-Endian devices, but since you've read carefully the above | ||
394 | paragraphs, you're now using kernel >= 2.6.23 and your 16bits devices | ||
395 | are now Little Endians ;-) ). | ||
396 | |||
397 | You can run jackd with the following command for playback with Ao and | ||
398 | record with Ai: | ||
399 | % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1 | ||
400 | |||
401 | 4.2 - Using Alsa plughw | ||
402 | ----------------------- | ||
403 | If you don't have a recent Jackd installed, you can downgrade to using | ||
404 | the Alsa "plug" converter. | ||
308 | 405 | ||
309 | For instance here is one way to run Jack with 2 playback channels on Ao and 2 | 406 | For instance here is one way to run Jack with 2 playback channels on Ao and 2 |
310 | capture channels from Ai: | 407 | capture channels from Ai: |
311 | % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1 | 408 | % jackd -R -dalsa -dplughw:1 -r48000 -p256 -n2 -D -Cplughw:1,1 |
312 | 409 | ||
313 | |||
314 | However you may see the following warning message: | 410 | However you may see the following warning message: |
315 | "You appear to be using the ALSA software "plug" layer, probably a result of | 411 | "You appear to be using the ALSA software "plug" layer, probably a result of |
316 | using the "default" ALSA device. This is less efficient than it could be. | 412 | using the "default" ALSA device. This is less efficient than it could be. |
317 | Consider using a hardware device instead rather than using the plug layer." | 413 | Consider using a hardware device instead rather than using the plug layer." |
318 | 414 | ||
319 | 3.2 - Patching alsa to use direct pcm device | 415 | 4.3 - Getting 2 input and/or output interfaces in Jack |
320 | -------------------------------------------- | ||
321 | A patch for Jack by Andreas Steinmetz adds support for Big Endian devices. | ||
322 | However it has not been included in the CVS tree. | ||
323 | |||
324 | You can find it at the following URL: | ||
325 | http://sourceforge.net/tracker/index.php?func=detail&aid=1289682&group_id=39687& | ||
326 | atid=425939 | ||
327 | |||
328 | After having applied the patch you can run jackd with the following command | ||
329 | line: | ||
330 | % jackd -R -dalsa -Phw:1,0 -r48000 -p128 -n2 -D -Chw:1,1 | ||
331 | |||
332 | 3.2 - Getting 2 input and/or output interfaces in Jack | ||
333 | ------------------------------------------------------ | 416 | ------------------------------------------------------ |
334 | 417 | ||
335 | As you can see, starting the Jack server this way will only enable 1 stereo | 418 | As you can see, starting the Jack server this way will only enable 1 stereo |
@@ -339,6 +422,7 @@ This is due to the following restrictions: | |||
339 | * Jack can only open one capture device and one playback device at a time | 422 | * Jack can only open one capture device and one playback device at a time |
340 | * The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1 | 423 | * The Audiophile USB is seen as 2 (or three) Alsa devices: hw:1,0, hw:1,1 |
341 | (and optionally hw:1,2) | 424 | (and optionally hw:1,2) |
425 | |||
342 | If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to | 426 | If you want to get Ai+Di and/or Ao+Do support with Jack, you would need to |
343 | combine the Alsa devices into one logical "complex" device. | 427 | combine the Alsa devices into one logical "complex" device. |
344 | 428 | ||
@@ -348,13 +432,11 @@ It is related to another device (ice1712) but can be adapted to suit | |||
348 | the Audiophile USB. | 432 | the Audiophile USB. |
349 | 433 | ||
350 | Enabling multiple Audiophile USB interfaces for Jackd will certainly require: | 434 | Enabling multiple Audiophile USB interfaces for Jackd will certainly require: |
351 | * patching Jack with the previously mentioned "Big Endian" patch | 435 | * Making sure your Jackd version has the MMAP_COMPLEX patch (see the ice1712 page) |
352 | * patching Jackd with the MMAP_COMPLEX patch (see the ice1712 page) | 436 | * (maybe) patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page) |
353 | * patching the alsa-lib/src/pcm/pcm_multi.c file (see the ice1712 page) | ||
354 | * define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc | 437 | * define a multi device (combination of hw:1,0 and hw:1,1) in your .asoundrc |
355 | file | 438 | file |
356 | * start jackd with this device | 439 | * start jackd with this device |
357 | 440 | ||
358 | I had no success in testing this for now, but this may be due to my OS | 441 | I had no success in testing this for now, if you have any success with this kind |
359 | configuration. If you have any success with this kind of setup, please | 442 | of setup, please drop me an email. |
360 | drop me an email. | ||
diff --git a/Documentation/sound/alsa/OSS-Emulation.txt b/Documentation/sound/alsa/OSS-Emulation.txt index ec2a02541d5b..bfa0c9aacb4b 100644 --- a/Documentation/sound/alsa/OSS-Emulation.txt +++ b/Documentation/sound/alsa/OSS-Emulation.txt | |||
@@ -278,6 +278,21 @@ current mixer configuration by reading and writing the whole file | |||
278 | image. | 278 | image. |
279 | 279 | ||
280 | 280 | ||
281 | Duplex Streams | ||
282 | ============== | ||
283 | |||
284 | Note that when attempting to use a single device file for playback and | ||
285 | capture, the OSS API provides no way to set the format, sample rate or | ||
286 | number of channels different in each direction. Thus | ||
287 | io_handle = open("device", O_RDWR) | ||
288 | will only function correctly if the values are the same in each direction. | ||
289 | |||
290 | To use different values in the two directions, use both | ||
291 | input_handle = open("device", O_RDONLY) | ||
292 | output_handle = open("device", O_WRONLY) | ||
293 | and set the values for the corresponding handle. | ||
294 | |||
295 | |||
281 | Unsupported Features | 296 | Unsupported Features |
282 | ==================== | 297 | ==================== |
283 | 298 | ||
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index aa83d4163096..b69014865714 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h | |||
@@ -115,9 +115,10 @@ | |||
115 | #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ | 115 | #define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ |
116 | #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ | 116 | #define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ |
117 | #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ | 117 | #define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ |
118 | #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ | 118 | #define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */ |
119 | #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ | 119 | #define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */ |
120 | #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ | 120 | #define I2C_DRIVERID_WM8753 91 /* Wolfson WM8753 audio codec */ |
121 | #define I2C_DRIVERID_LM4857 92 /* LM4857 Audio Amplifier */ | ||
121 | 122 | ||
122 | #define I2C_DRIVERID_I2CDEV 900 | 123 | #define I2C_DRIVERID_I2CDEV 900 |
123 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ | 124 | #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ |
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h index aa49dda4f410..fd0a6c46f497 100644 --- a/include/sound/ak4xxx-adda.h +++ b/include/sound/ak4xxx-adda.h | |||
@@ -43,6 +43,7 @@ struct snd_ak4xxx_ops { | |||
43 | struct snd_akm4xxx_dac_channel { | 43 | struct snd_akm4xxx_dac_channel { |
44 | char *name; /* mixer volume name */ | 44 | char *name; /* mixer volume name */ |
45 | unsigned int num_channels; | 45 | unsigned int num_channels; |
46 | char *switch_name; /* mixer switch*/ | ||
46 | }; | 47 | }; |
47 | 48 | ||
48 | /* ADC labels and channels */ | 49 | /* ADC labels and channels */ |
diff --git a/include/sound/cs46xx.h b/include/sound/cs46xx.h index 685928e6f65a..353910ce9755 100644 --- a/include/sound/cs46xx.h +++ b/include/sound/cs46xx.h | |||
@@ -1723,6 +1723,10 @@ struct snd_cs46xx { | |||
1723 | struct snd_cs46xx_pcm *playback_pcm; | 1723 | struct snd_cs46xx_pcm *playback_pcm; |
1724 | unsigned int play_ctl; | 1724 | unsigned int play_ctl; |
1725 | #endif | 1725 | #endif |
1726 | |||
1727 | #ifdef CONFIG_PM | ||
1728 | u32 *saved_regs; | ||
1729 | #endif | ||
1726 | }; | 1730 | }; |
1727 | 1731 | ||
1728 | int snd_cs46xx_create(struct snd_card *card, | 1732 | int snd_cs46xx_create(struct snd_card *card, |
diff --git a/include/sound/cs46xx_dsp_spos.h b/include/sound/cs46xx_dsp_spos.h index da934def31e9..d9da9e59cf37 100644 --- a/include/sound/cs46xx_dsp_spos.h +++ b/include/sound/cs46xx_dsp_spos.h | |||
@@ -107,6 +107,7 @@ struct dsp_scb_descriptor { | |||
107 | char scb_name[DSP_MAX_SCB_NAME]; | 107 | char scb_name[DSP_MAX_SCB_NAME]; |
108 | u32 address; | 108 | u32 address; |
109 | int index; | 109 | int index; |
110 | u32 *data; | ||
110 | 111 | ||
111 | struct dsp_scb_descriptor * sub_list_ptr; | 112 | struct dsp_scb_descriptor * sub_list_ptr; |
112 | struct dsp_scb_descriptor * next_scb_ptr; | 113 | struct dsp_scb_descriptor * next_scb_ptr; |
@@ -127,6 +128,7 @@ struct dsp_task_descriptor { | |||
127 | int size; | 128 | int size; |
128 | u32 address; | 129 | u32 address; |
129 | int index; | 130 | int index; |
131 | u32 *data; | ||
130 | }; | 132 | }; |
131 | 133 | ||
132 | struct dsp_pcm_channel_descriptor { | 134 | struct dsp_pcm_channel_descriptor { |
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 23e45a4cf0e4..529d0a564367 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h | |||
@@ -1120,6 +1120,16 @@ | |||
1120 | /************************************************************************************************/ | 1120 | /************************************************************************************************/ |
1121 | /* EMU1010m HANA Destinations */ | 1121 | /* EMU1010m HANA Destinations */ |
1122 | /************************************************************************************************/ | 1122 | /************************************************************************************************/ |
1123 | /* 32-bit destinations of signal in the Hana FPGA. Destinations are either | ||
1124 | * physical outputs of Hana, or outputs going to Alice2 (audigy) for capture | ||
1125 | * - 16 x EMU_DST_ALICE2_EMU32_X. | ||
1126 | */ | ||
1127 | /* EMU32 = 32-bit serial channel between Alice2 (audigy) and Hana (FPGA) */ | ||
1128 | /* EMU_DST_ALICE2_EMU32_X - data channels from Hana to Alice2 used for capture. | ||
1129 | * Which data is fed into a EMU_DST_ALICE2_EMU32_X channel in Hana depends on | ||
1130 | * setup of mixer control for each destination - see emumixer.c - | ||
1131 | * snd_emu1010_output_enum_ctls[], snd_emu1010_input_enum_ctls[] | ||
1132 | */ | ||
1123 | #define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */ | 1133 | #define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */ |
1124 | #define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */ | 1134 | #define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */ |
1125 | #define EMU_DST_ALICE2_EMU32_2 0x0001 /* 16 EMU32 channels to Alice2 +0 to +0xf */ | 1135 | #define EMU_DST_ALICE2_EMU32_2 0x0001 /* 16 EMU32 channels to Alice2 +0 to +0xf */ |
@@ -1199,6 +1209,12 @@ | |||
1199 | /************************************************************************************************/ | 1209 | /************************************************************************************************/ |
1200 | /* EMU1010m HANA Sources */ | 1210 | /* EMU1010m HANA Sources */ |
1201 | /************************************************************************************************/ | 1211 | /************************************************************************************************/ |
1212 | /* 32-bit sources of signal in the Hana FPGA. The sources are routed to | ||
1213 | * destinations using mixer control for each destination - see emumixer.c | ||
1214 | * Sources are either physical inputs of FPGA, | ||
1215 | * or outputs from Alice (audigy) - 16 x EMU_SRC_ALICE_EMU32A + | ||
1216 | * 16 x EMU_SRC_ALICE_EMU32B | ||
1217 | */ | ||
1202 | #define EMU_SRC_SILENCE 0x0000 /* Silence */ | 1218 | #define EMU_SRC_SILENCE 0x0000 /* Silence */ |
1203 | #define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */ | 1219 | #define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */ |
1204 | #define EMU_SRC_DOCK_MIC_A2 0x0101 /* Audio Dock Mic A, 2nd or 96kHz */ | 1220 | #define EMU_SRC_DOCK_MIC_A2 0x0101 /* Audio Dock Mic A, 2nd or 96kHz */ |
diff --git a/include/sound/sb.h b/include/sound/sb.h index 2dd5c8e5b4fe..3ad854b397d2 100644 --- a/include/sound/sb.h +++ b/include/sound/sb.h | |||
@@ -38,6 +38,7 @@ enum sb_hw_type { | |||
38 | SB_HW_ALS100, /* Avance Logic ALS100 chip */ | 38 | SB_HW_ALS100, /* Avance Logic ALS100 chip */ |
39 | SB_HW_ALS4000, /* Avance Logic ALS4000 chip */ | 39 | SB_HW_ALS4000, /* Avance Logic ALS4000 chip */ |
40 | SB_HW_DT019X, /* Diamond Tech. DT-019X / Avance Logic ALS-007 */ | 40 | SB_HW_DT019X, /* Diamond Tech. DT-019X / Avance Logic ALS-007 */ |
41 | SB_HW_CS5530, /* Cyrix/NatSemi 5530 VSA1 */ | ||
41 | }; | 42 | }; |
42 | 43 | ||
43 | #define SB_OPEN_PCM 0x01 | 44 | #define SB_OPEN_PCM 0x01 |
diff --git a/include/sound/version.h b/include/sound/version.h index 8e5b2f0f5946..6bbcfefd2c38 100644 --- a/include/sound/version.h +++ b/include/sound/version.h | |||
@@ -1,3 +1,3 @@ | |||
1 | /* include/version.h. Generated by alsa/ksync script. */ | 1 | /* include/version.h. Generated by alsa/ksync script. */ |
2 | #define CONFIG_SND_VERSION "1.0.14" | 2 | #define CONFIG_SND_VERSION "1.0.14" |
3 | #define CONFIG_SND_DATE " (Thu May 31 09:03:25 2007 UTC)" | 3 | #define CONFIG_SND_DATE " (Fri Jul 20 09:12:58 2007 UTC)" |
diff --git a/include/sound/wavefront_fx.h b/include/sound/wavefront_fx.h deleted file mode 100644 index cec92b141796..000000000000 --- a/include/sound/wavefront_fx.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef __SOUND_WAVEFRONT_FX_H | ||
2 | #define __SOUND_WAVEFRONT_FX_H | ||
3 | |||
4 | extern int snd_wavefront_fx_detect (snd_wavefront_t *); | ||
5 | extern void snd_wavefront_fx_ioctl (snd_synth_t *sdev, | ||
6 | unsigned int cmd, | ||
7 | unsigned long arg); | ||
8 | |||
9 | #endif __SOUND_WAVEFRONT_FX_H | ||
diff --git a/sound/Kconfig b/sound/Kconfig index 9ea473823418..e48b9b37d228 100644 --- a/sound/Kconfig +++ b/sound/Kconfig | |||
@@ -65,6 +65,8 @@ source "sound/arm/Kconfig" | |||
65 | 65 | ||
66 | source "sound/mips/Kconfig" | 66 | source "sound/mips/Kconfig" |
67 | 67 | ||
68 | source "sound/sh/Kconfig" | ||
69 | |||
68 | # the following will depend on the order of config. | 70 | # the following will depend on the order of config. |
69 | # here assuming USB is defined before ALSA | 71 | # here assuming USB is defined before ALSA |
70 | source "sound/usb/Kconfig" | 72 | source "sound/usb/Kconfig" |
diff --git a/sound/Makefile b/sound/Makefile index b7c7fb7c24c8..3ead922bd9c6 100644 --- a/sound/Makefile +++ b/sound/Makefile | |||
@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o | |||
5 | obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o | 5 | obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o |
6 | obj-$(CONFIG_SOUND_PRIME) += oss/ | 6 | obj-$(CONFIG_SOUND_PRIME) += oss/ |
7 | obj-$(CONFIG_DMASOUND) += oss/ | 7 | obj-$(CONFIG_DMASOUND) += oss/ |
8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/ | 8 | obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/ |
9 | obj-$(CONFIG_SND_AOA) += aoa/ | 9 | obj-$(CONFIG_SND_AOA) += aoa/ |
10 | 10 | ||
11 | # This one must be compilable even if sound is configured out | 11 | # This one must be compilable even if sound is configured out |
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c index ded516717940..028852374f21 100644 --- a/sound/aoa/codecs/snd-aoa-codec-onyx.c +++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c | |||
@@ -661,7 +661,7 @@ static struct transfer_info onyx_transfers[] = { | |||
661 | .tag = 2, | 661 | .tag = 2, |
662 | }, | 662 | }, |
663 | #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE | 663 | #ifdef SNDRV_PCM_FMTBIT_COMPRESSED_16BE |
664 | Once alsa gets supports for this kind of thing we can add it... | 664 | /* Once alsa gets supports for this kind of thing we can add it... */ |
665 | { | 665 | { |
666 | /* digital compressed output */ | 666 | /* digital compressed output */ |
667 | .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, | 667 | .formats = SNDRV_PCM_FMTBIT_COMPRESSED_16BE, |
@@ -713,7 +713,7 @@ static int onyx_prepare(struct codec_info_item *cii, | |||
713 | if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { | 713 | if (substream->runtime->format == SNDRV_PCM_FMTBIT_COMPRESSED_16BE) { |
714 | /* mute and lock analog output */ | 714 | /* mute and lock analog output */ |
715 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); | 715 | onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v); |
716 | if (onyx_write_register(onyx | 716 | if (onyx_write_register(onyx, |
717 | ONYX_REG_DAC_CONTROL, | 717 | ONYX_REG_DAC_CONTROL, |
718 | v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) | 718 | v | ONYX_MUTE_RIGHT | ONYX_MUTE_LEFT)) |
719 | goto out_unlock; | 719 | goto out_unlock; |
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index a96733a5beb8..59b29cd482ae 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c | |||
@@ -1487,7 +1487,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream) | |||
1487 | 1487 | ||
1488 | snd_pcm_stream_lock_irq(substream); | 1488 | snd_pcm_stream_lock_irq(substream); |
1489 | /* resume pause */ | 1489 | /* resume pause */ |
1490 | if (runtime->status->state == SNDRV_PCM_STATE_PAUSED) | 1490 | if (substream->runtime->status->state == SNDRV_PCM_STATE_PAUSED) |
1491 | snd_pcm_pause(substream, 0); | 1491 | snd_pcm_pause(substream, 0); |
1492 | 1492 | ||
1493 | /* pre-start/stop - all running streams are changed to DRAINING state */ | 1493 | /* pre-start/stop - all running streams are changed to DRAINING state */ |
diff --git a/sound/core/seq/seq_instr.c b/sound/core/seq/seq_instr.c index f30d171b6d96..5efe6523a589 100644 --- a/sound/core/seq/seq_instr.c +++ b/sound/core/seq/seq_instr.c | |||
@@ -109,7 +109,7 @@ void snd_seq_instr_list_free(struct snd_seq_kinstr_list **list_ptr) | |||
109 | spin_lock_irqsave(&list->lock, flags); | 109 | spin_lock_irqsave(&list->lock, flags); |
110 | while (instr->use) { | 110 | while (instr->use) { |
111 | spin_unlock_irqrestore(&list->lock, flags); | 111 | spin_unlock_irqrestore(&list->lock, flags); |
112 | schedule_timeout_interruptible(1); | 112 | schedule_timeout(1); |
113 | spin_lock_irqsave(&list->lock, flags); | 113 | spin_lock_irqsave(&list->lock, flags); |
114 | } | 114 | } |
115 | spin_unlock_irqrestore(&list->lock, flags); | 115 | spin_unlock_irqrestore(&list->lock, flags); |
@@ -199,7 +199,7 @@ int snd_seq_instr_list_free_cond(struct snd_seq_kinstr_list *list, | |||
199 | instr = flist; | 199 | instr = flist; |
200 | flist = instr->next; | 200 | flist = instr->next; |
201 | while (instr->use) | 201 | while (instr->use) |
202 | schedule_timeout_interruptible(1); | 202 | schedule_timeout(1); |
203 | if (snd_seq_instr_free(instr, atomic)<0) | 203 | if (snd_seq_instr_free(instr, atomic)<0) |
204 | snd_printk(KERN_WARNING "instrument free problem\n"); | 204 | snd_printk(KERN_WARNING "instrument free problem\n"); |
205 | instr = next; | 205 | instr = next; |
@@ -555,7 +555,7 @@ static int instr_free(struct snd_seq_kinstr_ops *ops, | |||
555 | SNDRV_SEQ_INSTR_NOTIFY_REMOVE); | 555 | SNDRV_SEQ_INSTR_NOTIFY_REMOVE); |
556 | while (instr->use) { | 556 | while (instr->use) { |
557 | spin_unlock_irqrestore(&list->lock, flags); | 557 | spin_unlock_irqrestore(&list->lock, flags); |
558 | schedule_timeout_interruptible(1); | 558 | schedule_timeout(1); |
559 | spin_lock_irqsave(&list->lock, flags); | 559 | spin_lock_irqsave(&list->lock, flags); |
560 | } | 560 | } |
561 | spin_unlock_irqrestore(&list->lock, flags); | 561 | spin_unlock_irqrestore(&list->lock, flags); |
diff --git a/sound/core/timer.c b/sound/core/timer.c index 67520b3c0042..f2bbacedd567 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c | |||
@@ -1549,9 +1549,11 @@ static int snd_timer_user_info(struct file *file, | |||
1549 | int err = 0; | 1549 | int err = 0; |
1550 | 1550 | ||
1551 | tu = file->private_data; | 1551 | tu = file->private_data; |
1552 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1552 | if (!tu->timeri) |
1553 | return -EBADFD; | ||
1553 | t = tu->timeri->timer; | 1554 | t = tu->timeri->timer; |
1554 | snd_assert(t != NULL, return -ENXIO); | 1555 | if (!t) |
1556 | return -EBADFD; | ||
1555 | 1557 | ||
1556 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 1558 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
1557 | if (! info) | 1559 | if (! info) |
@@ -1579,9 +1581,11 @@ static int snd_timer_user_params(struct file *file, | |||
1579 | int err; | 1581 | int err; |
1580 | 1582 | ||
1581 | tu = file->private_data; | 1583 | tu = file->private_data; |
1582 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1584 | if (!tu->timeri) |
1585 | return -EBADFD; | ||
1583 | t = tu->timeri->timer; | 1586 | t = tu->timeri->timer; |
1584 | snd_assert(t != NULL, return -ENXIO); | 1587 | if (!t) |
1588 | return -EBADFD; | ||
1585 | if (copy_from_user(¶ms, _params, sizeof(params))) | 1589 | if (copy_from_user(¶ms, _params, sizeof(params))) |
1586 | return -EFAULT; | 1590 | return -EFAULT; |
1587 | if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { | 1591 | if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { |
@@ -1675,7 +1679,8 @@ static int snd_timer_user_status(struct file *file, | |||
1675 | struct snd_timer_status status; | 1679 | struct snd_timer_status status; |
1676 | 1680 | ||
1677 | tu = file->private_data; | 1681 | tu = file->private_data; |
1678 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1682 | if (!tu->timeri) |
1683 | return -EBADFD; | ||
1679 | memset(&status, 0, sizeof(status)); | 1684 | memset(&status, 0, sizeof(status)); |
1680 | status.tstamp = tu->tstamp; | 1685 | status.tstamp = tu->tstamp; |
1681 | status.resolution = snd_timer_resolution(tu->timeri); | 1686 | status.resolution = snd_timer_resolution(tu->timeri); |
@@ -1695,7 +1700,8 @@ static int snd_timer_user_start(struct file *file) | |||
1695 | struct snd_timer_user *tu; | 1700 | struct snd_timer_user *tu; |
1696 | 1701 | ||
1697 | tu = file->private_data; | 1702 | tu = file->private_data; |
1698 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1703 | if (!tu->timeri) |
1704 | return -EBADFD; | ||
1699 | snd_timer_stop(tu->timeri); | 1705 | snd_timer_stop(tu->timeri); |
1700 | tu->timeri->lost = 0; | 1706 | tu->timeri->lost = 0; |
1701 | tu->last_resolution = 0; | 1707 | tu->last_resolution = 0; |
@@ -1708,7 +1714,8 @@ static int snd_timer_user_stop(struct file *file) | |||
1708 | struct snd_timer_user *tu; | 1714 | struct snd_timer_user *tu; |
1709 | 1715 | ||
1710 | tu = file->private_data; | 1716 | tu = file->private_data; |
1711 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1717 | if (!tu->timeri) |
1718 | return -EBADFD; | ||
1712 | return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; | 1719 | return (err = snd_timer_stop(tu->timeri)) < 0 ? err : 0; |
1713 | } | 1720 | } |
1714 | 1721 | ||
@@ -1718,7 +1725,8 @@ static int snd_timer_user_continue(struct file *file) | |||
1718 | struct snd_timer_user *tu; | 1725 | struct snd_timer_user *tu; |
1719 | 1726 | ||
1720 | tu = file->private_data; | 1727 | tu = file->private_data; |
1721 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1728 | if (!tu->timeri) |
1729 | return -EBADFD; | ||
1722 | tu->timeri->lost = 0; | 1730 | tu->timeri->lost = 0; |
1723 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; | 1731 | return (err = snd_timer_continue(tu->timeri)) < 0 ? err : 0; |
1724 | } | 1732 | } |
@@ -1729,7 +1737,8 @@ static int snd_timer_user_pause(struct file *file) | |||
1729 | struct snd_timer_user *tu; | 1737 | struct snd_timer_user *tu; |
1730 | 1738 | ||
1731 | tu = file->private_data; | 1739 | tu = file->private_data; |
1732 | snd_assert(tu->timeri != NULL, return -ENXIO); | 1740 | if (!tu->timeri) |
1741 | return -EBADFD; | ||
1733 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; | 1742 | return (err = snd_timer_pause(tu->timeri)) < 0 ? err : 0; |
1734 | } | 1743 | } |
1735 | 1744 | ||
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c index a0f28f51fc7e..4360ae9de19c 100644 --- a/sound/drivers/dummy.c +++ b/sound/drivers/dummy.c | |||
@@ -659,7 +659,7 @@ static struct platform_driver snd_dummy_driver = { | |||
659 | }, | 659 | }, |
660 | }; | 660 | }; |
661 | 661 | ||
662 | static void __init_or_module snd_dummy_unregister_all(void) | 662 | static void snd_dummy_unregister_all(void) |
663 | { | 663 | { |
664 | int i; | 664 | int i; |
665 | 665 | ||
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index 1d563e515c17..67c6e9745418 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c | |||
@@ -228,7 +228,7 @@ static struct pnp_driver snd_mpu401_pnp_driver = { | |||
228 | static struct pnp_driver snd_mpu401_pnp_driver; | 228 | static struct pnp_driver snd_mpu401_pnp_driver; |
229 | #endif | 229 | #endif |
230 | 230 | ||
231 | static void __init_or_module snd_mpu401_unregister_all(void) | 231 | static void snd_mpu401_unregister_all(void) |
232 | { | 232 | { |
233 | int i; | 233 | int i; |
234 | 234 | ||
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c index 497cafb57d9b..0eb9b5cebfcd 100644 --- a/sound/drivers/portman2x4.c +++ b/sound/drivers/portman2x4.c | |||
@@ -833,7 +833,7 @@ static struct platform_driver snd_portman_driver = { | |||
833 | /********************************************************************* | 833 | /********************************************************************* |
834 | * module init stuff | 834 | * module init stuff |
835 | *********************************************************************/ | 835 | *********************************************************************/ |
836 | static void __init_or_module snd_portman_unregister_all(void) | 836 | static void snd_portman_unregister_all(void) |
837 | { | 837 | { |
838 | int i; | 838 | int i; |
839 | 839 | ||
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c index 838a4277929d..d3e6a20edd38 100644 --- a/sound/drivers/serial-u16550.c +++ b/sound/drivers/serial-u16550.c | |||
@@ -998,7 +998,7 @@ static struct platform_driver snd_serial_driver = { | |||
998 | }, | 998 | }, |
999 | }; | 999 | }; |
1000 | 1000 | ||
1001 | static void __init_or_module snd_serial_unregister_all(void) | 1001 | static void snd_serial_unregister_all(void) |
1002 | { | 1002 | { |
1003 | int i; | 1003 | int i; |
1004 | 1004 | ||
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c index 46f3d3486067..915c86773c21 100644 --- a/sound/drivers/virmidi.c +++ b/sound/drivers/virmidi.c | |||
@@ -145,7 +145,7 @@ static struct platform_driver snd_virmidi_driver = { | |||
145 | }, | 145 | }, |
146 | }; | 146 | }; |
147 | 147 | ||
148 | static void __init_or_module snd_virmidi_unregister_all(void) | 148 | static void snd_virmidi_unregister_all(void) |
149 | { | 149 | { |
150 | int i; | 150 | int i; |
151 | 151 | ||
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c index 8805110017a7..fd335159f849 100644 --- a/sound/i2c/other/ak4xxx-adda.c +++ b/sound/i2c/other/ak4xxx-adda.c | |||
@@ -481,8 +481,8 @@ static int ak4xxx_switch_get(struct snd_kcontrol *kcontrol, | |||
481 | int addr = AK_GET_ADDR(kcontrol->private_value); | 481 | int addr = AK_GET_ADDR(kcontrol->private_value); |
482 | int shift = AK_GET_SHIFT(kcontrol->private_value); | 482 | int shift = AK_GET_SHIFT(kcontrol->private_value); |
483 | int invert = AK_GET_INVERT(kcontrol->private_value); | 483 | int invert = AK_GET_INVERT(kcontrol->private_value); |
484 | unsigned char val = snd_akm4xxx_get(ak, chip, addr); | 484 | /* we observe the (1<<shift) bit only */ |
485 | 485 | unsigned char val = snd_akm4xxx_get(ak, chip, addr) & (1<<shift); | |
486 | if (invert) | 486 | if (invert) |
487 | val = ! val; | 487 | val = ! val; |
488 | ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0; | 488 | ucontrol->value.integer.value[0] = (val & (1<<shift)) != 0; |
@@ -585,6 +585,26 @@ static int build_dac_controls(struct snd_akm4xxx *ak) | |||
585 | 585 | ||
586 | mixer_ch = 0; | 586 | mixer_ch = 0; |
587 | for (idx = 0; idx < ak->num_dacs; ) { | 587 | for (idx = 0; idx < ak->num_dacs; ) { |
588 | /* mute control for Revolution 7.1 - AK4381 */ | ||
589 | if (ak->type == SND_AK4381 | ||
590 | && ak->dac_info[mixer_ch].switch_name) { | ||
591 | memset(&knew, 0, sizeof(knew)); | ||
592 | knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
593 | knew.count = 1; | ||
594 | knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
595 | knew.name = ak->dac_info[mixer_ch].switch_name; | ||
596 | knew.info = ak4xxx_switch_info; | ||
597 | knew.get = ak4xxx_switch_get; | ||
598 | knew.put = ak4xxx_switch_put; | ||
599 | knew.access = 0; | ||
600 | /* register 1, bit 0 (SMUTE): 0 = normal operation, | ||
601 | 1 = mute */ | ||
602 | knew.private_value = | ||
603 | AK_COMPOSE(idx/2, 1, 0, 0) | AK_INVERT; | ||
604 | err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); | ||
605 | if (err < 0) | ||
606 | return err; | ||
607 | } | ||
588 | memset(&knew, 0, sizeof(knew)); | 608 | memset(&knew, 0, sizeof(knew)); |
589 | if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { | 609 | if (! ak->dac_info || ! ak->dac_info[mixer_ch].name) { |
590 | knew.name = "DAC Volume"; | 610 | knew.name = "DAC Volume"; |
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index cf3803cd579c..ea5084abe60f 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig | |||
@@ -1,8 +1,5 @@ | |||
1 | # ALSA ISA drivers | 1 | # ALSA ISA drivers |
2 | 2 | ||
3 | menu "ISA devices" | ||
4 | depends on SND!=n && ISA && ISA_DMA_API | ||
5 | |||
6 | config SND_AD1848_LIB | 3 | config SND_AD1848_LIB |
7 | tristate | 4 | tristate |
8 | select SND_PCM | 5 | select SND_PCM |
@@ -11,6 +8,22 @@ config SND_CS4231_LIB | |||
11 | tristate | 8 | tristate |
12 | select SND_PCM | 9 | select SND_PCM |
13 | 10 | ||
11 | config SND_SB_COMMON | ||
12 | tristate | ||
13 | |||
14 | config SND_SB8_DSP | ||
15 | tristate | ||
16 | select SND_PCM | ||
17 | select SND_SB_COMMON | ||
18 | |||
19 | config SND_SB16_DSP | ||
20 | tristate | ||
21 | select SND_PCM | ||
22 | select SND_SB_COMMON | ||
23 | |||
24 | menu "ISA devices" | ||
25 | depends on SND!=n && ISA && ISA_DMA_API | ||
26 | |||
14 | config SND_ADLIB | 27 | config SND_ADLIB |
15 | tristate "AdLib FM card" | 28 | tristate "AdLib FM card" |
16 | depends on SND | 29 | depends on SND |
@@ -55,7 +68,7 @@ config SND_ALS100 | |||
55 | select ISAPNP | 68 | select ISAPNP |
56 | select SND_OPL3_LIB | 69 | select SND_OPL3_LIB |
57 | select SND_MPU401_UART | 70 | select SND_MPU401_UART |
58 | select SND_PCM | 71 | select SND_SB16_DSP |
59 | help | 72 | help |
60 | Say Y here to include support for soundcards based on Avance | 73 | Say Y here to include support for soundcards based on Avance |
61 | Logic ALS100, ALS110, ALS120 and ALS200 chips. | 74 | Logic ALS100, ALS110, ALS120 and ALS200 chips. |
@@ -81,6 +94,7 @@ config SND_CMI8330 | |||
81 | tristate "C-Media CMI8330" | 94 | tristate "C-Media CMI8330" |
82 | depends on SND | 95 | depends on SND |
83 | select SND_AD1848_LIB | 96 | select SND_AD1848_LIB |
97 | select SND_SB16_DSP | ||
84 | help | 98 | help |
85 | Say Y here to include support for soundcards based on the | 99 | Say Y here to include support for soundcards based on the |
86 | C-Media CMI8330 chip. | 100 | C-Media CMI8330 chip. |
@@ -132,7 +146,7 @@ config SND_DT019X | |||
132 | select ISAPNP | 146 | select ISAPNP |
133 | select SND_OPL3_LIB | 147 | select SND_OPL3_LIB |
134 | select SND_MPU401_UART | 148 | select SND_MPU401_UART |
135 | select SND_PCM | 149 | select SND_SB16_DSP |
136 | help | 150 | help |
137 | Say Y here to include support for soundcards based on the | 151 | Say Y here to include support for soundcards based on the |
138 | Diamond Technologies DT-019X or Avance Logic ALS-007 chips. | 152 | Diamond Technologies DT-019X or Avance Logic ALS-007 chips. |
@@ -145,7 +159,7 @@ config SND_ES968 | |||
145 | depends on SND && PNP && ISA | 159 | depends on SND && PNP && ISA |
146 | select ISAPNP | 160 | select ISAPNP |
147 | select SND_MPU401_UART | 161 | select SND_MPU401_UART |
148 | select SND_PCM | 162 | select SND_SB8_DSP |
149 | help | 163 | help |
150 | Say Y here to include support for ESS AudioDrive ES968 chips. | 164 | Say Y here to include support for ESS AudioDrive ES968 chips. |
151 | 165 | ||
@@ -321,7 +335,7 @@ config SND_SB8 | |||
321 | depends on SND | 335 | depends on SND |
322 | select SND_OPL3_LIB | 336 | select SND_OPL3_LIB |
323 | select SND_RAWMIDI | 337 | select SND_RAWMIDI |
324 | select SND_PCM | 338 | select SND_SB8_DSP |
325 | help | 339 | help |
326 | Say Y here to include support for Creative Sound Blaster 1.0/ | 340 | Say Y here to include support for Creative Sound Blaster 1.0/ |
327 | 2.0/Pro (8-bit) or 100% compatible soundcards. | 341 | 2.0/Pro (8-bit) or 100% compatible soundcards. |
@@ -334,7 +348,7 @@ config SND_SB16 | |||
334 | depends on SND | 348 | depends on SND |
335 | select SND_OPL3_LIB | 349 | select SND_OPL3_LIB |
336 | select SND_MPU401_UART | 350 | select SND_MPU401_UART |
337 | select SND_PCM | 351 | select SND_SB16_DSP |
338 | help | 352 | help |
339 | Say Y here to include support for Sound Blaster 16 soundcards | 353 | Say Y here to include support for Sound Blaster 16 soundcards |
340 | (including the Plug and Play version). | 354 | (including the Plug and Play version). |
@@ -347,7 +361,7 @@ config SND_SBAWE | |||
347 | depends on SND | 361 | depends on SND |
348 | select SND_OPL3_LIB | 362 | select SND_OPL3_LIB |
349 | select SND_MPU401_UART | 363 | select SND_MPU401_UART |
350 | select SND_PCM | 364 | select SND_SB16_DSP |
351 | help | 365 | help |
352 | Say Y here to include support for Sound Blaster AWE soundcards | 366 | Say Y here to include support for Sound Blaster AWE soundcards |
353 | (including the Plug and Play version). | 367 | (including the Plug and Play version). |
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c index 8094282c2ae1..1bc2e3fd5721 100644 --- a/sound/isa/ad1848/ad1848_lib.c +++ b/sound/isa/ad1848/ad1848_lib.c | |||
@@ -245,7 +245,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | |||
245 | snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); | 245 | snd_printk(KERN_ERR "mce_down - auto calibration time out (2)\n"); |
246 | return; | 246 | return; |
247 | } | 247 | } |
248 | time = schedule_timeout_interruptible(time); | 248 | time = schedule_timeout(time); |
249 | spin_lock_irqsave(&chip->reg_lock, flags); | 249 | spin_lock_irqsave(&chip->reg_lock, flags); |
250 | } | 250 | } |
251 | #if 0 | 251 | #if 0 |
@@ -258,7 +258,7 @@ static void snd_ad1848_mce_down(struct snd_ad1848 *chip) | |||
258 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); | 258 | snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n"); |
259 | return; | 259 | return; |
260 | } | 260 | } |
261 | time = schedule_timeout_interruptible(time); | 261 | time = schedule_timeout(time); |
262 | spin_lock_irqsave(&chip->reg_lock, flags); | 262 | spin_lock_irqsave(&chip->reg_lock, flags); |
263 | } | 263 | } |
264 | spin_unlock_irqrestore(&chip->reg_lock, flags); | 264 | spin_unlock_irqrestore(&chip->reg_lock, flags); |
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c index 4f6800b43b0e..e70db32991d9 100644 --- a/sound/isa/opl3sa2.c +++ b/sound/isa/opl3sa2.c | |||
@@ -164,6 +164,8 @@ static struct pnp_card_device_id snd_opl3sa2_pnpids[] = { | |||
164 | { .id = "YMH0801", .devs = { { "YMH0021" } } }, | 164 | { .id = "YMH0801", .devs = { { "YMH0021" } } }, |
165 | /* NeoMagic MagicWave 3DX */ | 165 | /* NeoMagic MagicWave 3DX */ |
166 | { .id = "NMX2200", .devs = { { "YMH2210" } } }, | 166 | { .id = "NMX2200", .devs = { { "YMH2210" } } }, |
167 | /* NeoMagic MagicWave 3D */ | ||
168 | { .id = "NMX2200", .devs = { { "NMX2210" } } }, | ||
167 | /* --- */ | 169 | /* --- */ |
168 | { .id = "" } /* end */ | 170 | { .id = "" } /* end */ |
169 | }; | 171 | }; |
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c index 60c120ffb9de..049d479ce2b3 100644 --- a/sound/isa/opti9xx/opti92x-ad1848.c +++ b/sound/isa/opti9xx/opti92x-ad1848.c | |||
@@ -1927,10 +1927,12 @@ static struct snd_card *snd_opti9xx_card_new(void) | |||
1927 | static int __devinit snd_opti9xx_isa_match(struct device *devptr, | 1927 | static int __devinit snd_opti9xx_isa_match(struct device *devptr, |
1928 | unsigned int dev) | 1928 | unsigned int dev) |
1929 | { | 1929 | { |
1930 | #ifdef CONFIG_PNP | ||
1930 | if (snd_opti9xx_pnp_is_probed) | 1931 | if (snd_opti9xx_pnp_is_probed) |
1931 | return 0; | 1932 | return 0; |
1932 | if (isapnp) | 1933 | if (isapnp) |
1933 | return 0; | 1934 | return 0; |
1935 | #endif | ||
1934 | return 1; | 1936 | return 1; |
1935 | } | 1937 | } |
1936 | 1938 | ||
@@ -2096,6 +2098,7 @@ static int __init alsa_card_opti9xx_init(void) | |||
2096 | pnp_register_card_driver(&opti9xx_pnpc_driver); | 2098 | pnp_register_card_driver(&opti9xx_pnpc_driver); |
2097 | if (snd_opti9xx_pnp_is_probed) | 2099 | if (snd_opti9xx_pnp_is_probed) |
2098 | return 0; | 2100 | return 0; |
2101 | pnp_unregister_card_driver(&opti9xx_pnpc_driver); | ||
2099 | #endif | 2102 | #endif |
2100 | return isa_register_driver(&snd_opti9xx_driver, 1); | 2103 | return isa_register_driver(&snd_opti9xx_driver, 1); |
2101 | } | 2104 | } |
diff --git a/sound/isa/sb/Makefile b/sound/isa/sb/Makefile index fd9d9c5726fc..556e66928029 100644 --- a/sound/isa/sb/Makefile +++ b/sound/isa/sb/Makefile | |||
@@ -22,14 +22,13 @@ snd-es968-objs := es968.o | |||
22 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) | 22 | sequencer = $(if $(subst y,,$(CONFIG_SND_SEQUENCER)),$(if $(1),m),$(if $(CONFIG_SND_SEQUENCER),$(1))) |
23 | 23 | ||
24 | # Toplevel Module Dependency | 24 | # Toplevel Module Dependency |
25 | obj-$(CONFIG_SND_ALS100) += snd-sb16-dsp.o snd-sb-common.o | 25 | obj-$(CONFIG_SND_SB_COMMON) += snd-sb-common.o |
26 | obj-$(CONFIG_SND_CMI8330) += snd-sb16-dsp.o snd-sb-common.o | 26 | obj-$(CONFIG_SND_SB16_DSP) += snd-sb16-dsp.o |
27 | obj-$(CONFIG_SND_DT019X) += snd-sb16-dsp.o snd-sb-common.o | 27 | obj-$(CONFIG_SND_SB8_DSP) += snd-sb8-dsp.o |
28 | obj-$(CONFIG_SND_SB8) += snd-sb8.o snd-sb8-dsp.o snd-sb-common.o | 28 | obj-$(CONFIG_SND_SB8) += snd-sb8.o |
29 | obj-$(CONFIG_SND_SB16) += snd-sb16.o snd-sb16-dsp.o snd-sb-common.o | 29 | obj-$(CONFIG_SND_SB16) += snd-sb16.o |
30 | obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o snd-sb16-dsp.o snd-sb-common.o | 30 | obj-$(CONFIG_SND_SBAWE) += snd-sbawe.o |
31 | obj-$(CONFIG_SND_ES968) += snd-es968.o snd-sb8-dsp.o snd-sb-common.o | 31 | obj-$(CONFIG_SND_ES968) += snd-es968.o |
32 | obj-$(CONFIG_SND_ALS4000) += snd-sb-common.o | ||
33 | ifeq ($(CONFIG_SND_SB16_CSP),y) | 32 | ifeq ($(CONFIG_SND_SB16_CSP),y) |
34 | obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o | 33 | obj-$(CONFIG_SND_SB16) += snd-sb16-csp.o |
35 | obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o | 34 | obj-$(CONFIG_SND_SBAWE) += snd-sb16-csp.o |
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c index 383911b9e74d..5d4d3aafe2d5 100644 --- a/sound/isa/sb/sb16_main.c +++ b/sound/isa/sb/sb16_main.c | |||
@@ -563,6 +563,11 @@ static int snd_sb16_playback_open(struct snd_pcm_substream *substream) | |||
563 | __open_ok: | 563 | __open_ok: |
564 | if (chip->hardware == SB_HW_ALS100) | 564 | if (chip->hardware == SB_HW_ALS100) |
565 | runtime->hw.rate_max = 48000; | 565 | runtime->hw.rate_max = 48000; |
566 | if (chip->hardware == SB_HW_CS5530) { | ||
567 | runtime->hw.buffer_bytes_max = 32 * 1024; | ||
568 | runtime->hw.periods_min = 2; | ||
569 | runtime->hw.rate_min = 44100; | ||
570 | } | ||
566 | if (chip->mode & SB_RATE_LOCK) | 571 | if (chip->mode & SB_RATE_LOCK) |
567 | runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; | 572 | runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; |
568 | chip->playback_substream = substream; | 573 | chip->playback_substream = substream; |
@@ -633,6 +638,11 @@ static int snd_sb16_capture_open(struct snd_pcm_substream *substream) | |||
633 | __open_ok: | 638 | __open_ok: |
634 | if (chip->hardware == SB_HW_ALS100) | 639 | if (chip->hardware == SB_HW_ALS100) |
635 | runtime->hw.rate_max = 48000; | 640 | runtime->hw.rate_max = 48000; |
641 | if (chip->hardware == SB_HW_CS5530) { | ||
642 | runtime->hw.buffer_bytes_max = 32 * 1024; | ||
643 | runtime->hw.periods_min = 2; | ||
644 | runtime->hw.rate_min = 44100; | ||
645 | } | ||
636 | if (chip->mode & SB_RATE_LOCK) | 646 | if (chip->mode & SB_RATE_LOCK) |
637 | runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; | 647 | runtime->hw.rate_min = runtime->hw.rate_max = chip->locked_rate; |
638 | chip->capture_substream = substream; | 648 | chip->capture_substream = substream; |
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c index 3094f3852167..efa9d5c2558a 100644 --- a/sound/isa/sb/sb_common.c +++ b/sound/isa/sb/sb_common.c | |||
@@ -128,7 +128,7 @@ static int snd_sbdsp_probe(struct snd_sb * chip) | |||
128 | minor = version & 0xff; | 128 | minor = version & 0xff; |
129 | snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", | 129 | snd_printdd("SB [0x%lx]: DSP chip found, version = %i.%i\n", |
130 | chip->port, major, minor); | 130 | chip->port, major, minor); |
131 | 131 | ||
132 | switch (chip->hardware) { | 132 | switch (chip->hardware) { |
133 | case SB_HW_AUTO: | 133 | case SB_HW_AUTO: |
134 | switch (major) { | 134 | switch (major) { |
@@ -168,6 +168,9 @@ static int snd_sbdsp_probe(struct snd_sb * chip) | |||
168 | case SB_HW_DT019X: | 168 | case SB_HW_DT019X: |
169 | str = "(DT019X/ALS007)"; | 169 | str = "(DT019X/ALS007)"; |
170 | break; | 170 | break; |
171 | case SB_HW_CS5530: | ||
172 | str = "16 (CS5530)"; | ||
173 | break; | ||
171 | default: | 174 | default: |
172 | return -ENODEV; | 175 | return -ENODEV; |
173 | } | 176 | } |
diff --git a/sound/isa/sb/sb_mixer.c b/sound/isa/sb/sb_mixer.c index 490b1ca5cf58..3d4befcff28e 100644 --- a/sound/isa/sb/sb_mixer.c +++ b/sound/isa/sb/sb_mixer.c | |||
@@ -821,6 +821,7 @@ int snd_sbmixer_new(struct snd_sb *chip) | |||
821 | break; | 821 | break; |
822 | case SB_HW_16: | 822 | case SB_HW_16: |
823 | case SB_HW_ALS100: | 823 | case SB_HW_ALS100: |
824 | case SB_HW_CS5530: | ||
824 | if ((err = snd_sbmixer_init(chip, | 825 | if ((err = snd_sbmixer_init(chip, |
825 | snd_sb16_controls, | 826 | snd_sb16_controls, |
826 | ARRAY_SIZE(snd_sb16_controls), | 827 | ARRAY_SIZE(snd_sb16_controls), |
@@ -950,6 +951,7 @@ void snd_sbmixer_suspend(struct snd_sb *chip) | |||
950 | break; | 951 | break; |
951 | case SB_HW_16: | 952 | case SB_HW_16: |
952 | case SB_HW_ALS100: | 953 | case SB_HW_ALS100: |
954 | case SB_HW_CS5530: | ||
953 | save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); | 955 | save_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); |
954 | break; | 956 | break; |
955 | case SB_HW_ALS4000: | 957 | case SB_HW_ALS4000: |
@@ -975,6 +977,7 @@ void snd_sbmixer_resume(struct snd_sb *chip) | |||
975 | break; | 977 | break; |
976 | case SB_HW_16: | 978 | case SB_HW_16: |
977 | case SB_HW_ALS100: | 979 | case SB_HW_ALS100: |
980 | case SB_HW_CS5530: | ||
978 | restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); | 981 | restore_mixer(chip, sb16_saved_regs, ARRAY_SIZE(sb16_saved_regs)); |
979 | break; | 982 | break; |
980 | case SB_HW_ALS4000: | 983 | case SB_HW_ALS4000: |
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c index 9ea417bcf3e5..cbad2a51cbaa 100644 --- a/sound/isa/sscape.c +++ b/sound/isa/sscape.c | |||
@@ -382,7 +382,7 @@ static int obp_startup_ack(struct soundscape *s, unsigned timeout) | |||
382 | unsigned long flags; | 382 | unsigned long flags; |
383 | unsigned char x; | 383 | unsigned char x; |
384 | 384 | ||
385 | schedule_timeout_interruptible(1); | 385 | schedule_timeout(1); |
386 | 386 | ||
387 | spin_lock_irqsave(&s->lock, flags); | 387 | spin_lock_irqsave(&s->lock, flags); |
388 | x = inb(HOST_DATA_IO(s->io_base)); | 388 | x = inb(HOST_DATA_IO(s->io_base)); |
@@ -409,7 +409,7 @@ static int host_startup_ack(struct soundscape *s, unsigned timeout) | |||
409 | unsigned long flags; | 409 | unsigned long flags; |
410 | unsigned char x; | 410 | unsigned char x; |
411 | 411 | ||
412 | schedule_timeout_interruptible(1); | 412 | schedule_timeout(1); |
413 | 413 | ||
414 | spin_lock_irqsave(&s->lock, flags); | 414 | spin_lock_irqsave(&s->lock, flags); |
415 | x = inb(HOST_DATA_IO(s->io_base)); | 415 | x = inb(HOST_DATA_IO(s->io_base)); |
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c index 78020d832e04..bacc51c86587 100644 --- a/sound/isa/wavefront/wavefront_synth.c +++ b/sound/isa/wavefront/wavefront_synth.c | |||
@@ -1780,7 +1780,7 @@ wavefront_should_cause_interrupt (snd_wavefront_t *dev, | |||
1780 | outb (val,port); | 1780 | outb (val,port); |
1781 | spin_unlock_irq(&dev->irq_lock); | 1781 | spin_unlock_irq(&dev->irq_lock); |
1782 | while (1) { | 1782 | while (1) { |
1783 | if ((timeout = schedule_timeout_interruptible(timeout)) == 0) | 1783 | if ((timeout = schedule_timeout(timeout)) == 0) |
1784 | return; | 1784 | return; |
1785 | if (dev->irq_ok) | 1785 | if (dev->irq_ok) |
1786 | return; | 1786 | return; |
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 61e35ecc57b8..c6b44102aa5b 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig | |||
@@ -33,6 +33,7 @@ config SND_ALS4000 | |||
33 | select SND_OPL3_LIB | 33 | select SND_OPL3_LIB |
34 | select SND_MPU401_UART | 34 | select SND_MPU401_UART |
35 | select SND_PCM | 35 | select SND_PCM |
36 | select SND_SB_COMMON | ||
36 | help | 37 | help |
37 | Say Y here to include support for soundcards based on Avance Logic | 38 | Say Y here to include support for soundcards based on Avance Logic |
38 | ALS4000 chips. | 39 | ALS4000 chips. |
@@ -215,6 +216,16 @@ config SND_CS46XX_NEW_DSP | |||
215 | 216 | ||
216 | This works better than the old code, so say Y. | 217 | This works better than the old code, so say Y. |
217 | 218 | ||
219 | config SND_CS5530 | ||
220 | tristate "CS5530 Audio" | ||
221 | depends on SND && ISA_DMA_API | ||
222 | select SND_SB16_DSP | ||
223 | help | ||
224 | Say Y here to include support for audio on Cyrix/NatSemi CS5530 chips. | ||
225 | |||
226 | To compile this driver as a module, choose M here: the module | ||
227 | will be called snd-cs5530. | ||
228 | |||
218 | config SND_CS5535AUDIO | 229 | config SND_CS5535AUDIO |
219 | tristate "CS5535/CS5536 Audio" | 230 | tristate "CS5535/CS5536 Audio" |
220 | depends on SND && X86 && !X86_64 | 231 | depends on SND && X86 && !X86_64 |
diff --git a/sound/pci/Makefile b/sound/pci/Makefile index e06736da9ef1..cd76e0293d06 100644 --- a/sound/pci/Makefile +++ b/sound/pci/Makefile | |||
@@ -12,6 +12,7 @@ snd-azt3328-objs := azt3328.o | |||
12 | snd-bt87x-objs := bt87x.o | 12 | snd-bt87x-objs := bt87x.o |
13 | snd-cmipci-objs := cmipci.o | 13 | snd-cmipci-objs := cmipci.o |
14 | snd-cs4281-objs := cs4281.o | 14 | snd-cs4281-objs := cs4281.o |
15 | snd-cs5530-objs := cs5530.o | ||
15 | snd-ens1370-objs := ens1370.o | 16 | snd-ens1370-objs := ens1370.o |
16 | snd-ens1371-objs := ens1371.o | 17 | snd-ens1371-objs := ens1371.o |
17 | snd-es1938-objs := es1938.o | 18 | snd-es1938-objs := es1938.o |
@@ -36,6 +37,7 @@ obj-$(CONFIG_SND_AZT3328) += snd-azt3328.o | |||
36 | obj-$(CONFIG_SND_BT87X) += snd-bt87x.o | 37 | obj-$(CONFIG_SND_BT87X) += snd-bt87x.o |
37 | obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o | 38 | obj-$(CONFIG_SND_CMIPCI) += snd-cmipci.o |
38 | obj-$(CONFIG_SND_CS4281) += snd-cs4281.o | 39 | obj-$(CONFIG_SND_CS4281) += snd-cs4281.o |
40 | obj-$(CONFIG_SND_CS5530) += snd-cs5530.o | ||
39 | obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o | 41 | obj-$(CONFIG_SND_ENS1370) += snd-ens1370.o |
40 | obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o | 42 | obj-$(CONFIG_SND_ENS1371) += snd-ens1371.o |
41 | obj-$(CONFIG_SND_ES1938) += snd-es1938.o | 43 | obj-$(CONFIG_SND_ES1938) += snd-es1938.o |
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c index 41543a4933e7..05b4c8696941 100644 --- a/sound/pci/ali5451/ali5451.c +++ b/sound/pci/ali5451/ali5451.c | |||
@@ -239,7 +239,7 @@ struct snd_ali_image { | |||
239 | 239 | ||
240 | 240 | ||
241 | struct snd_ali { | 241 | struct snd_ali { |
242 | unsigned long irq; | 242 | int irq; |
243 | unsigned long port; | 243 | unsigned long port; |
244 | unsigned char revision; | 244 | unsigned char revision; |
245 | 245 | ||
@@ -731,8 +731,7 @@ static void snd_ali_detect_spdif_rate(struct snd_ali *codec) | |||
731 | return; | 731 | return; |
732 | } | 732 | } |
733 | 733 | ||
734 | count = 0; | 734 | for (count = 0; count <= 50000; count++) { |
735 | while (count++ <= 50000) { | ||
736 | snd_ali_delay(codec, 6); | 735 | snd_ali_delay(codec, 6); |
737 | bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); | 736 | bval = inb(ALI_REG(codec,ALI_SPDIF_CTRL + 1)); |
738 | R2 = bval & 0x1F; | 737 | R2 = bval & 0x1F; |
@@ -2343,7 +2342,7 @@ static int __devinit snd_ali_probe(struct pci_dev *pci, | |||
2343 | strcpy(card->driver, "ALI5451"); | 2342 | strcpy(card->driver, "ALI5451"); |
2344 | strcpy(card->shortname, "ALI 5451"); | 2343 | strcpy(card->shortname, "ALI 5451"); |
2345 | 2344 | ||
2346 | sprintf(card->longname, "%s at 0x%lx, irq %li", | 2345 | sprintf(card->longname, "%s at 0x%lx, irq %i", |
2347 | card->shortname, codec->port, codec->irq); | 2346 | card->shortname, codec->port, codec->irq); |
2348 | 2347 | ||
2349 | snd_ali_printk("register card.\n"); | 2348 | snd_ali_printk("register card.\n"); |
diff --git a/sound/pci/als300.c b/sound/pci/als300.c index 8afcb98ca7bb..48cc39b771d9 100644 --- a/sound/pci/als300.c +++ b/sound/pci/als300.c | |||
@@ -88,8 +88,8 @@ | |||
88 | #define PLAYBACK_BLOCK_COUNTER 0x9A | 88 | #define PLAYBACK_BLOCK_COUNTER 0x9A |
89 | #define RECORD_BLOCK_COUNTER 0x9B | 89 | #define RECORD_BLOCK_COUNTER 0x9B |
90 | 90 | ||
91 | #define DEBUG_CALLS 1 | 91 | #define DEBUG_CALLS 0 |
92 | #define DEBUG_PLAY_REC 1 | 92 | #define DEBUG_PLAY_REC 0 |
93 | 93 | ||
94 | #if DEBUG_CALLS | 94 | #if DEBUG_CALLS |
95 | #define snd_als300_dbgcalls(format, args...) printk(format, ##args) | 95 | #define snd_als300_dbgcalls(format, args...) printk(format, ##args) |
@@ -733,7 +733,8 @@ static int __devinit snd_als300_create(struct snd_card *card, | |||
733 | 733 | ||
734 | snd_als300_init(chip); | 734 | snd_als300_init(chip); |
735 | 735 | ||
736 | if (snd_als300_ac97(chip) < 0) { | 736 | err = snd_als300_ac97(chip); |
737 | if (err < 0) { | ||
737 | snd_printk(KERN_WARNING "Could not create ac97\n"); | 738 | snd_printk(KERN_WARNING "Could not create ac97\n"); |
738 | snd_als300_free(chip); | 739 | snd_als300_free(chip); |
739 | return err; | 740 | return err; |
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 9fd7b8a5b75e..fcab8fb97e38 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c | |||
@@ -168,6 +168,25 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model."); | |||
168 | #include "ca0106.h" | 168 | #include "ca0106.h" |
169 | 169 | ||
170 | static struct snd_ca0106_details ca0106_chip_details[] = { | 170 | static struct snd_ca0106_details ca0106_chip_details[] = { |
171 | /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */ | ||
172 | /* It is really just a normal SB Live 24bit. */ | ||
173 | /* | ||
174 | * CTRL:CA0111-WTLF | ||
175 | * ADC: WM8775SEDS | ||
176 | * DAC: CS4382-KQZ | ||
177 | */ | ||
178 | /* Tested: | ||
179 | * Playback on front, rear, center/lfe speakers | ||
180 | * Capture from Mic in. | ||
181 | * Not-Tested: | ||
182 | * Capture from Line in. | ||
183 | * Playback to digital out. | ||
184 | */ | ||
185 | { .serial = 0x10121102, | ||
186 | .name = "X-Fi Extreme Audio [SB0790]", | ||
187 | .gpio_type = 1, | ||
188 | .i2c_adc = 1 } , | ||
189 | /* New Dell Sound Blaster Live! 7.1 24bit. This does not have an AC97. */ | ||
171 | /* AudigyLS[SB0310] */ | 190 | /* AudigyLS[SB0310] */ |
172 | { .serial = 0x10021102, | 191 | { .serial = 0x10021102, |
173 | .name = "AudigyLS [SB0310]", | 192 | .name = "AudigyLS [SB0310]", |
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c index bef1f6d1859c..71d7aab9d869 100644 --- a/sound/pci/cs46xx/cs46xx_lib.c +++ b/sound/pci/cs46xx/cs46xx_lib.c | |||
@@ -2897,6 +2897,10 @@ static int snd_cs46xx_free(struct snd_cs46xx *chip) | |||
2897 | } | 2897 | } |
2898 | #endif | 2898 | #endif |
2899 | 2899 | ||
2900 | #ifdef CONFIG_PM | ||
2901 | kfree(chip->saved_regs); | ||
2902 | #endif | ||
2903 | |||
2900 | pci_disable_device(chip->pci); | 2904 | pci_disable_device(chip->pci); |
2901 | kfree(chip); | 2905 | kfree(chip); |
2902 | return 0; | 2906 | return 0; |
@@ -3140,6 +3144,23 @@ static int snd_cs46xx_chip_init(struct snd_cs46xx *chip) | |||
3140 | /* | 3144 | /* |
3141 | * start and load DSP | 3145 | * start and load DSP |
3142 | */ | 3146 | */ |
3147 | |||
3148 | static void cs46xx_enable_stream_irqs(struct snd_cs46xx *chip) | ||
3149 | { | ||
3150 | unsigned int tmp; | ||
3151 | |||
3152 | snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); | ||
3153 | |||
3154 | tmp = snd_cs46xx_peek(chip, BA1_PFIE); | ||
3155 | tmp &= ~0x0000f03f; | ||
3156 | snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ | ||
3157 | |||
3158 | tmp = snd_cs46xx_peek(chip, BA1_CIE); | ||
3159 | tmp &= ~0x0000003f; | ||
3160 | tmp |= 0x00000001; | ||
3161 | snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ | ||
3162 | } | ||
3163 | |||
3143 | int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) | 3164 | int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) |
3144 | { | 3165 | { |
3145 | unsigned int tmp; | 3166 | unsigned int tmp; |
@@ -3214,19 +3235,7 @@ int __devinit snd_cs46xx_start_dsp(struct snd_cs46xx *chip) | |||
3214 | 3235 | ||
3215 | snd_cs46xx_proc_start(chip); | 3236 | snd_cs46xx_proc_start(chip); |
3216 | 3237 | ||
3217 | /* | 3238 | cs46xx_enable_stream_irqs(chip); |
3218 | * Enable interrupts on the part. | ||
3219 | */ | ||
3220 | snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM); | ||
3221 | |||
3222 | tmp = snd_cs46xx_peek(chip, BA1_PFIE); | ||
3223 | tmp &= ~0x0000f03f; | ||
3224 | snd_cs46xx_poke(chip, BA1_PFIE, tmp); /* playback interrupt enable */ | ||
3225 | |||
3226 | tmp = snd_cs46xx_peek(chip, BA1_CIE); | ||
3227 | tmp &= ~0x0000003f; | ||
3228 | tmp |= 0x00000001; | ||
3229 | snd_cs46xx_poke(chip, BA1_CIE, tmp); /* capture interrupt enable */ | ||
3230 | 3239 | ||
3231 | #ifndef CONFIG_SND_CS46XX_NEW_DSP | 3240 | #ifndef CONFIG_SND_CS46XX_NEW_DSP |
3232 | /* set the attenuation to 0dB */ | 3241 | /* set the attenuation to 0dB */ |
@@ -3665,11 +3674,19 @@ static struct cs_card_type __devinitdata cards[] = { | |||
3665 | * APM support | 3674 | * APM support |
3666 | */ | 3675 | */ |
3667 | #ifdef CONFIG_PM | 3676 | #ifdef CONFIG_PM |
3677 | static unsigned int saved_regs[] = { | ||
3678 | BA0_ACOSV, | ||
3679 | BA0_ASER_FADDR, | ||
3680 | BA0_ASER_MASTER, | ||
3681 | BA1_PVOL, | ||
3682 | BA1_CVOL, | ||
3683 | }; | ||
3684 | |||
3668 | int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | 3685 | int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) |
3669 | { | 3686 | { |
3670 | struct snd_card *card = pci_get_drvdata(pci); | 3687 | struct snd_card *card = pci_get_drvdata(pci); |
3671 | struct snd_cs46xx *chip = card->private_data; | 3688 | struct snd_cs46xx *chip = card->private_data; |
3672 | int amp_saved; | 3689 | int i, amp_saved; |
3673 | 3690 | ||
3674 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); | 3691 | snd_power_change_state(card, SNDRV_CTL_POWER_D3hot); |
3675 | chip->in_suspend = 1; | 3692 | chip->in_suspend = 1; |
@@ -3680,6 +3697,10 @@ int snd_cs46xx_suspend(struct pci_dev *pci, pm_message_t state) | |||
3680 | snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); | 3697 | snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); |
3681 | snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); | 3698 | snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); |
3682 | 3699 | ||
3700 | /* save some registers */ | ||
3701 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) | ||
3702 | chip->saved_regs[i] = snd_cs46xx_peekBA0(chip, saved_regs[i]); | ||
3703 | |||
3683 | amp_saved = chip->amplifier; | 3704 | amp_saved = chip->amplifier; |
3684 | /* turn off amp */ | 3705 | /* turn off amp */ |
3685 | chip->amplifier_ctrl(chip, -chip->amplifier); | 3706 | chip->amplifier_ctrl(chip, -chip->amplifier); |
@@ -3698,7 +3719,7 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3698 | { | 3719 | { |
3699 | struct snd_card *card = pci_get_drvdata(pci); | 3720 | struct snd_card *card = pci_get_drvdata(pci); |
3700 | struct snd_cs46xx *chip = card->private_data; | 3721 | struct snd_cs46xx *chip = card->private_data; |
3701 | int amp_saved; | 3722 | int i, amp_saved; |
3702 | 3723 | ||
3703 | pci_set_power_state(pci, PCI_D0); | 3724 | pci_set_power_state(pci, PCI_D0); |
3704 | pci_restore_state(pci); | 3725 | pci_restore_state(pci); |
@@ -3716,6 +3737,16 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3716 | 3737 | ||
3717 | snd_cs46xx_chip_init(chip); | 3738 | snd_cs46xx_chip_init(chip); |
3718 | 3739 | ||
3740 | snd_cs46xx_reset(chip); | ||
3741 | #ifdef CONFIG_SND_CS46XX_NEW_DSP | ||
3742 | cs46xx_dsp_resume(chip); | ||
3743 | /* restore some registers */ | ||
3744 | for (i = 0; i < ARRAY_SIZE(saved_regs); i++) | ||
3745 | snd_cs46xx_pokeBA0(chip, saved_regs[i], chip->saved_regs[i]); | ||
3746 | #else | ||
3747 | snd_cs46xx_download_image(chip); | ||
3748 | #endif | ||
3749 | |||
3719 | #if 0 | 3750 | #if 0 |
3720 | snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, | 3751 | snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, |
3721 | chip->ac97_general_purpose); | 3752 | chip->ac97_general_purpose); |
@@ -3730,6 +3761,13 @@ int snd_cs46xx_resume(struct pci_dev *pci) | |||
3730 | snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); | 3761 | snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]); |
3731 | snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); | 3762 | snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]); |
3732 | 3763 | ||
3764 | /* reset playback/capture */ | ||
3765 | snd_cs46xx_set_play_sample_rate(chip, 8000); | ||
3766 | snd_cs46xx_set_capture_sample_rate(chip, 8000); | ||
3767 | snd_cs46xx_proc_start(chip); | ||
3768 | |||
3769 | cs46xx_enable_stream_irqs(chip); | ||
3770 | |||
3733 | if (amp_saved) | 3771 | if (amp_saved) |
3734 | chip->amplifier_ctrl(chip, 1); /* turn amp on */ | 3772 | chip->amplifier_ctrl(chip, 1); /* turn amp on */ |
3735 | else | 3773 | else |
@@ -3896,6 +3934,15 @@ int __devinit snd_cs46xx_create(struct snd_card *card, | |||
3896 | 3934 | ||
3897 | snd_cs46xx_proc_init(card, chip); | 3935 | snd_cs46xx_proc_init(card, chip); |
3898 | 3936 | ||
3937 | #ifdef CONFIG_PM | ||
3938 | chip->saved_regs = kmalloc(sizeof(*chip->saved_regs) * | ||
3939 | ARRAY_SIZE(saved_regs), GFP_KERNEL); | ||
3940 | if (!chip->saved_regs) { | ||
3941 | snd_cs46xx_free(chip); | ||
3942 | return -ENOMEM; | ||
3943 | } | ||
3944 | #endif | ||
3945 | |||
3899 | chip->active_ctrl(chip, -1); /* disable CLKRUN */ | 3946 | chip->active_ctrl(chip, -1); /* disable CLKRUN */ |
3900 | 3947 | ||
3901 | snd_card_set_dev(card, &pci->dev); | 3948 | snd_card_set_dev(card, &pci->dev); |
diff --git a/sound/pci/cs46xx/cs46xx_lib.h b/sound/pci/cs46xx/cs46xx_lib.h index f75750c2bd24..20dcd72f06c1 100644 --- a/sound/pci/cs46xx/cs46xx_lib.h +++ b/sound/pci/cs46xx/cs46xx_lib.h | |||
@@ -86,6 +86,9 @@ static inline unsigned int snd_cs46xx_peekBA0(struct snd_cs46xx *chip, unsigned | |||
86 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); | 86 | struct dsp_spos_instance *cs46xx_dsp_spos_create (struct snd_cs46xx * chip); |
87 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); | 87 | void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip); |
88 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); | 88 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module); |
89 | #ifdef CONFIG_PM | ||
90 | int cs46xx_dsp_resume(struct snd_cs46xx * chip); | ||
91 | #endif | ||
89 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, | 92 | struct dsp_symbol_entry *cs46xx_dsp_lookup_symbol (struct snd_cs46xx * chip, char * symbol_name, |
90 | int symbol_type); | 93 | int symbol_type); |
91 | #ifdef CONFIG_PROC_FS | 94 | #ifdef CONFIG_PROC_FS |
diff --git a/sound/pci/cs46xx/dsp_spos.c b/sound/pci/cs46xx/dsp_spos.c index 336e77e2600c..590b35d91df2 100644 --- a/sound/pci/cs46xx/dsp_spos.c +++ b/sound/pci/cs46xx/dsp_spos.c | |||
@@ -306,13 +306,59 @@ void cs46xx_dsp_spos_destroy (struct snd_cs46xx * chip) | |||
306 | mutex_unlock(&chip->spos_mutex); | 306 | mutex_unlock(&chip->spos_mutex); |
307 | } | 307 | } |
308 | 308 | ||
309 | static int dsp_load_parameter(struct snd_cs46xx *chip, | ||
310 | struct dsp_segment_desc *parameter) | ||
311 | { | ||
312 | u32 doffset, dsize; | ||
313 | |||
314 | if (!parameter) { | ||
315 | snd_printdd("dsp_spos: module got no parameter segment\n"); | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); | ||
320 | dsize = parameter->size * 4; | ||
321 | |||
322 | snd_printdd("dsp_spos: " | ||
323 | "downloading parameter data to chip (%08x-%08x)\n", | ||
324 | doffset,doffset + dsize); | ||
325 | if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { | ||
326 | snd_printk(KERN_ERR "dsp_spos: " | ||
327 | "failed to download parameter data to DSP\n"); | ||
328 | return -EINVAL; | ||
329 | } | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | static int dsp_load_sample(struct snd_cs46xx *chip, | ||
334 | struct dsp_segment_desc *sample) | ||
335 | { | ||
336 | u32 doffset, dsize; | ||
337 | |||
338 | if (!sample) { | ||
339 | snd_printdd("dsp_spos: module got no sample segment\n"); | ||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); | ||
344 | dsize = sample->size * 4; | ||
345 | |||
346 | snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", | ||
347 | doffset,doffset + dsize); | ||
348 | |||
349 | if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { | ||
350 | snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); | ||
351 | return -EINVAL; | ||
352 | } | ||
353 | return 0; | ||
354 | } | ||
355 | |||
309 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) | 356 | int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * module) |
310 | { | 357 | { |
311 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 358 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
312 | struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); | 359 | struct dsp_segment_desc * code = get_segment_desc (module,SEGTYPE_SP_PROGRAM); |
313 | struct dsp_segment_desc * parameter = get_segment_desc (module,SEGTYPE_SP_PARAMETER); | ||
314 | struct dsp_segment_desc * sample = get_segment_desc (module,SEGTYPE_SP_SAMPLE); | ||
315 | u32 doffset, dsize; | 360 | u32 doffset, dsize; |
361 | int err; | ||
316 | 362 | ||
317 | if (ins->nmodules == DSP_MAX_MODULES - 1) { | 363 | if (ins->nmodules == DSP_MAX_MODULES - 1) { |
318 | snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); | 364 | snd_printk(KERN_ERR "dsp_spos: to many modules loaded into DSP\n"); |
@@ -326,49 +372,20 @@ int cs46xx_dsp_load_module (struct snd_cs46xx * chip, struct dsp_module_desc * m | |||
326 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); | 372 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, DSP_PARAMETER_BYTE_SIZE); |
327 | } | 373 | } |
328 | 374 | ||
329 | if (parameter == NULL) { | 375 | err = dsp_load_parameter(chip, get_segment_desc(module, |
330 | snd_printdd("dsp_spos: module got no parameter segment\n"); | 376 | SEGTYPE_SP_PARAMETER)); |
331 | } else { | 377 | if (err < 0) |
332 | if (ins->nmodules > 0) { | 378 | return err; |
333 | snd_printk(KERN_WARNING "dsp_spos: WARNING current parameter data may be overwriten!\n"); | ||
334 | } | ||
335 | |||
336 | doffset = (parameter->offset * 4 + DSP_PARAMETER_BYTE_OFFSET); | ||
337 | dsize = parameter->size * 4; | ||
338 | |||
339 | snd_printdd("dsp_spos: downloading parameter data to chip (%08x-%08x)\n", | ||
340 | doffset,doffset + dsize); | ||
341 | |||
342 | if (snd_cs46xx_download (chip, parameter->data, doffset, dsize)) { | ||
343 | snd_printk(KERN_ERR "dsp_spos: failed to download parameter data to DSP\n"); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | } | ||
347 | 379 | ||
348 | if (ins->nmodules == 0) { | 380 | if (ins->nmodules == 0) { |
349 | snd_printdd("dsp_spos: clearing sample area\n"); | 381 | snd_printdd("dsp_spos: clearing sample area\n"); |
350 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); | 382 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, DSP_SAMPLE_BYTE_SIZE); |
351 | } | 383 | } |
352 | 384 | ||
353 | if (sample == NULL) { | 385 | err = dsp_load_sample(chip, get_segment_desc(module, |
354 | snd_printdd("dsp_spos: module got no sample segment\n"); | 386 | SEGTYPE_SP_SAMPLE)); |
355 | } else { | 387 | if (err < 0) |
356 | if (ins->nmodules > 0) { | 388 | return err; |
357 | snd_printk(KERN_WARNING "dsp_spos: WARNING current sample data may be overwriten\n"); | ||
358 | } | ||
359 | |||
360 | doffset = (sample->offset * 4 + DSP_SAMPLE_BYTE_OFFSET); | ||
361 | dsize = sample->size * 4; | ||
362 | |||
363 | snd_printdd("dsp_spos: downloading sample data to chip (%08x-%08x)\n", | ||
364 | doffset,doffset + dsize); | ||
365 | |||
366 | if (snd_cs46xx_download (chip,sample->data,doffset,dsize)) { | ||
367 | snd_printk(KERN_ERR "dsp_spos: failed to sample data to DSP\n"); | ||
368 | return -EINVAL; | ||
369 | } | ||
370 | } | ||
371 | |||
372 | 389 | ||
373 | if (ins->nmodules == 0) { | 390 | if (ins->nmodules == 0) { |
374 | snd_printdd("dsp_spos: clearing code area\n"); | 391 | snd_printdd("dsp_spos: clearing code area\n"); |
@@ -986,7 +1003,10 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) | |||
986 | return NULL; | 1003 | return NULL; |
987 | } | 1004 | } |
988 | 1005 | ||
989 | strcpy(ins->tasks[ins->ntask].task_name,name); | 1006 | if (name) |
1007 | strcpy(ins->tasks[ins->ntask].task_name, name); | ||
1008 | else | ||
1009 | strcpy(ins->tasks[ins->ntask].task_name, "(NULL)"); | ||
990 | ins->tasks[ins->ntask].address = dest; | 1010 | ins->tasks[ins->ntask].address = dest; |
991 | ins->tasks[ins->ntask].size = size; | 1011 | ins->tasks[ins->ntask].size = size; |
992 | 1012 | ||
@@ -995,7 +1015,8 @@ _map_task_tree (struct snd_cs46xx *chip, char * name, u32 dest, u32 size) | |||
995 | desc = (ins->tasks + ins->ntask); | 1015 | desc = (ins->tasks + ins->ntask); |
996 | ins->ntask++; | 1016 | ins->ntask++; |
997 | 1017 | ||
998 | add_symbol (chip,name,dest,SYMBOL_PARAMETER); | 1018 | if (name) |
1019 | add_symbol (chip,name,dest,SYMBOL_PARAMETER); | ||
999 | return desc; | 1020 | return desc; |
1000 | } | 1021 | } |
1001 | 1022 | ||
@@ -1006,6 +1027,7 @@ cs46xx_dsp_create_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 | |||
1006 | 1027 | ||
1007 | desc = _map_scb (chip,name,dest); | 1028 | desc = _map_scb (chip,name,dest); |
1008 | if (desc) { | 1029 | if (desc) { |
1030 | desc->data = scb_data; | ||
1009 | _dsp_create_scb(chip,scb_data,dest); | 1031 | _dsp_create_scb(chip,scb_data,dest); |
1010 | } else { | 1032 | } else { |
1011 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); | 1033 | snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); |
@@ -1023,6 +1045,7 @@ cs46xx_dsp_create_task_tree (struct snd_cs46xx *chip, char * name, u32 * task_da | |||
1023 | 1045 | ||
1024 | desc = _map_task_tree (chip,name,dest,size); | 1046 | desc = _map_task_tree (chip,name,dest,size); |
1025 | if (desc) { | 1047 | if (desc) { |
1048 | desc->data = task_data; | ||
1026 | _dsp_create_task_tree(chip,task_data,dest,size); | 1049 | _dsp_create_task_tree(chip,task_data,dest,size); |
1027 | } else { | 1050 | } else { |
1028 | snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); | 1051 | snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); |
@@ -1320,8 +1343,10 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip) | |||
1320 | 0x0000ffff | 1343 | 0x0000ffff |
1321 | }; | 1344 | }; |
1322 | 1345 | ||
1323 | /* dirty hack ... */ | 1346 | if (!cs46xx_dsp_create_task_tree(chip, NULL, |
1324 | _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); | 1347 | (u32 *)&mix2_ostream_spb, |
1348 | WRITE_BACK_SPB, 2)) | ||
1349 | goto _fail_end; | ||
1325 | } | 1350 | } |
1326 | 1351 | ||
1327 | /* input sample converter */ | 1352 | /* input sample converter */ |
@@ -1622,7 +1647,6 @@ static int cs46xx_dsp_async_init (struct snd_cs46xx *chip, | |||
1622 | return 0; | 1647 | return 0; |
1623 | } | 1648 | } |
1624 | 1649 | ||
1625 | |||
1626 | static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) | 1650 | static void cs46xx_dsp_disable_spdif_hw (struct snd_cs46xx *chip) |
1627 | { | 1651 | { |
1628 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | 1652 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; |
@@ -1894,3 +1918,61 @@ int cs46xx_dsp_set_iec958_volume (struct snd_cs46xx * chip, u16 left, u16 right) | |||
1894 | 1918 | ||
1895 | return 0; | 1919 | return 0; |
1896 | } | 1920 | } |
1921 | |||
1922 | #ifdef CONFIG_PM | ||
1923 | int cs46xx_dsp_resume(struct snd_cs46xx * chip) | ||
1924 | { | ||
1925 | struct dsp_spos_instance * ins = chip->dsp_spos_instance; | ||
1926 | int i, err; | ||
1927 | |||
1928 | /* clear parameter, sample and code areas */ | ||
1929 | snd_cs46xx_clear_BA1(chip, DSP_PARAMETER_BYTE_OFFSET, | ||
1930 | DSP_PARAMETER_BYTE_SIZE); | ||
1931 | snd_cs46xx_clear_BA1(chip, DSP_SAMPLE_BYTE_OFFSET, | ||
1932 | DSP_SAMPLE_BYTE_SIZE); | ||
1933 | snd_cs46xx_clear_BA1(chip, DSP_CODE_BYTE_OFFSET, DSP_CODE_BYTE_SIZE); | ||
1934 | |||
1935 | for (i = 0; i < ins->nmodules; i++) { | ||
1936 | struct dsp_module_desc *module = &ins->modules[i]; | ||
1937 | struct dsp_segment_desc *seg; | ||
1938 | u32 doffset, dsize; | ||
1939 | |||
1940 | seg = get_segment_desc(module, SEGTYPE_SP_PARAMETER); | ||
1941 | err = dsp_load_parameter(chip, seg); | ||
1942 | if (err < 0) | ||
1943 | return err; | ||
1944 | |||
1945 | seg = get_segment_desc(module, SEGTYPE_SP_SAMPLE); | ||
1946 | err = dsp_load_sample(chip, seg); | ||
1947 | if (err < 0) | ||
1948 | return err; | ||
1949 | |||
1950 | seg = get_segment_desc(module, SEGTYPE_SP_PROGRAM); | ||
1951 | if (!seg) | ||
1952 | continue; | ||
1953 | |||
1954 | doffset = seg->offset * 4 + module->load_address * 4 | ||
1955 | + DSP_CODE_BYTE_OFFSET; | ||
1956 | dsize = seg->size * 4; | ||
1957 | err = snd_cs46xx_download(chip, | ||
1958 | ins->code.data + module->load_address, | ||
1959 | doffset, dsize); | ||
1960 | if (err < 0) | ||
1961 | return err; | ||
1962 | } | ||
1963 | |||
1964 | for (i = 0; i < ins->ntask; i++) { | ||
1965 | struct dsp_task_descriptor *t = &ins->tasks[i]; | ||
1966 | _dsp_create_task_tree(chip, t->data, t->address, t->size); | ||
1967 | } | ||
1968 | |||
1969 | for (i = 0; i < ins->nscb; i++) { | ||
1970 | struct dsp_scb_descriptor *s = &ins->scbs[i]; | ||
1971 | if (s->deleted) | ||
1972 | continue; | ||
1973 | _dsp_create_scb(chip, s->data, s->address); | ||
1974 | } | ||
1975 | |||
1976 | return 0; | ||
1977 | } | ||
1978 | #endif | ||
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c new file mode 100644 index 000000000000..240a0a462209 --- /dev/null +++ b/sound/pci/cs5530.c | |||
@@ -0,0 +1,306 @@ | |||
1 | /* | ||
2 | * cs5530.c - Initialisation code for Cyrix/NatSemi VSA1 softaudio | ||
3 | * | ||
4 | * (C) Copyright 2007 Ash Willis <ashwillis@programmer.net> | ||
5 | * (C) Copyright 2003 Red Hat Inc <alan@redhat.com> | ||
6 | * | ||
7 | * This driver was ported (shamelessly ripped ;) from oss/kahlua.c but I did | ||
8 | * mess with it a bit. The chip seems to have to have trouble with full duplex | ||
9 | * mode. If we're recording in 8bit 8000kHz, say, and we then attempt to | ||
10 | * simultaneously play back audio at 16bit 44100kHz, the device actually plays | ||
11 | * back in the same format in which it is capturing. By forcing the chip to | ||
12 | * always play/capture in 16/44100, we can let alsa-lib convert the samples and | ||
13 | * that way we can hack up some full duplex audio. | ||
14 | * | ||
15 | * XpressAudio(tm) is used on the Cyrix MediaGX (now NatSemi Geode) systems. | ||
16 | * The older version (VSA1) provides fairly good soundblaster emulation | ||
17 | * although there are a couple of bugs: large DMA buffers break record, | ||
18 | * and the MPU event handling seems suspect. VSA2 allows the native driver | ||
19 | * to control the AC97 audio engine directly and requires a different driver. | ||
20 | * | ||
21 | * Thanks to National Semiconductor for providing the needed information | ||
22 | * on the XpressAudio(tm) internals. | ||
23 | * | ||
24 | * This program is free software; you can redistribute it and/or modify it | ||
25 | * under the terms of the GNU General Public License as published by the | ||
26 | * Free Software Foundation; either version 2, or (at your option) any | ||
27 | * later version. | ||
28 | * | ||
29 | * This program is distributed in the hope that it will be useful, but | ||
30 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
31 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
32 | * General Public License for more details. | ||
33 | * | ||
34 | * TO DO: | ||
35 | * Investigate whether we can portably support Cognac (5520) in the | ||
36 | * same manner. | ||
37 | */ | ||
38 | |||
39 | #include <sound/driver.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/moduleparam.h> | ||
42 | #include <linux/pci.h> | ||
43 | #include <sound/core.h> | ||
44 | #include <sound/sb.h> | ||
45 | #include <sound/initval.h> | ||
46 | |||
47 | MODULE_AUTHOR("Ash Willis"); | ||
48 | MODULE_DESCRIPTION("CS5530 Audio"); | ||
49 | MODULE_LICENSE("GPL"); | ||
50 | |||
51 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; | ||
52 | static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; | ||
53 | static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; | ||
54 | |||
55 | struct snd_cs5530 { | ||
56 | struct snd_card *card; | ||
57 | struct pci_dev *pci; | ||
58 | struct snd_sb *sb; | ||
59 | unsigned long pci_base; | ||
60 | }; | ||
61 | |||
62 | static struct pci_device_id snd_cs5530_ids[] = { | ||
63 | {PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_5530_AUDIO, PCI_ANY_ID, | ||
64 | PCI_ANY_ID, 0, 0}, | ||
65 | {0,} | ||
66 | }; | ||
67 | |||
68 | MODULE_DEVICE_TABLE(pci, snd_cs5530_ids); | ||
69 | |||
70 | static int snd_cs5530_free(struct snd_cs5530 *chip) | ||
71 | { | ||
72 | pci_release_regions(chip->pci); | ||
73 | pci_disable_device(chip->pci); | ||
74 | kfree(chip); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | static int snd_cs5530_dev_free(struct snd_device *device) | ||
79 | { | ||
80 | struct snd_cs5530 *chip = device->device_data; | ||
81 | return snd_cs5530_free(chip); | ||
82 | } | ||
83 | |||
84 | static void __devexit snd_cs5530_remove(struct pci_dev *pci) | ||
85 | { | ||
86 | snd_card_free(pci_get_drvdata(pci)); | ||
87 | pci_set_drvdata(pci, NULL); | ||
88 | } | ||
89 | |||
90 | static u8 __devinit snd_cs5530_mixer_read(unsigned long io, u8 reg) | ||
91 | { | ||
92 | outb(reg, io + 4); | ||
93 | udelay(20); | ||
94 | reg = inb(io + 5); | ||
95 | udelay(20); | ||
96 | return reg; | ||
97 | } | ||
98 | |||
99 | static int __devinit snd_cs5530_create(struct snd_card *card, | ||
100 | struct pci_dev *pci, | ||
101 | struct snd_cs5530 **rchip) | ||
102 | { | ||
103 | struct snd_cs5530 *chip; | ||
104 | unsigned long sb_base; | ||
105 | u8 irq, dma8, dma16 = 0; | ||
106 | u16 map; | ||
107 | void __iomem *mem; | ||
108 | int err; | ||
109 | |||
110 | static struct snd_device_ops ops = { | ||
111 | .dev_free = snd_cs5530_dev_free, | ||
112 | }; | ||
113 | *rchip = NULL; | ||
114 | |||
115 | err = pci_enable_device(pci); | ||
116 | if (err < 0) | ||
117 | return err; | ||
118 | |||
119 | chip = kzalloc(sizeof(*chip), GFP_KERNEL); | ||
120 | if (chip == NULL) { | ||
121 | pci_disable_device(pci); | ||
122 | return -ENOMEM; | ||
123 | } | ||
124 | |||
125 | chip->card = card; | ||
126 | chip->pci = pci; | ||
127 | |||
128 | err = pci_request_regions(pci, "CS5530"); | ||
129 | if (err < 0) { | ||
130 | kfree(chip); | ||
131 | pci_disable_device(pci); | ||
132 | return err; | ||
133 | } | ||
134 | chip->pci_base = pci_resource_start(pci, 0); | ||
135 | |||
136 | mem = ioremap_nocache(chip->pci_base, pci_resource_len(pci, 0)); | ||
137 | if (mem == NULL) { | ||
138 | kfree(chip); | ||
139 | pci_disable_device(pci); | ||
140 | return -EBUSY; | ||
141 | } | ||
142 | |||
143 | map = readw(mem + 0x18); | ||
144 | iounmap(mem); | ||
145 | |||
146 | /* Map bits | ||
147 | 0:1 * 0x20 + 0x200 = sb base | ||
148 | 2 sb enable | ||
149 | 3 adlib enable | ||
150 | 5 MPU enable 0x330 | ||
151 | 6 MPU enable 0x300 | ||
152 | |||
153 | The other bits may be used internally so must be masked */ | ||
154 | |||
155 | sb_base = 0x220 + 0x20 * (map & 3); | ||
156 | |||
157 | if (map & (1<<2)) | ||
158 | printk(KERN_INFO "CS5530: XpressAudio at 0x%lx\n", sb_base); | ||
159 | else { | ||
160 | printk(KERN_ERR "Could not find XpressAudio!\n"); | ||
161 | snd_cs5530_free(chip); | ||
162 | return -ENODEV; | ||
163 | } | ||
164 | |||
165 | if (map & (1<<5)) | ||
166 | printk(KERN_INFO "CS5530: MPU at 0x300\n"); | ||
167 | else if (map & (1<<6)) | ||
168 | printk(KERN_INFO "CS5530: MPU at 0x330\n"); | ||
169 | |||
170 | irq = snd_cs5530_mixer_read(sb_base, 0x80) & 0x0F; | ||
171 | dma8 = snd_cs5530_mixer_read(sb_base, 0x81); | ||
172 | |||
173 | if (dma8 & 0x20) | ||
174 | dma16 = 5; | ||
175 | else if (dma8 & 0x40) | ||
176 | dma16 = 6; | ||
177 | else if (dma8 & 0x80) | ||
178 | dma16 = 7; | ||
179 | else { | ||
180 | printk(KERN_ERR "CS5530: No 16bit DMA enabled\n"); | ||
181 | snd_cs5530_free(chip); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
185 | if (dma8 & 0x01) | ||
186 | dma8 = 0; | ||
187 | else if (dma8 & 02) | ||
188 | dma8 = 1; | ||
189 | else if (dma8 & 0x08) | ||
190 | dma8 = 3; | ||
191 | else { | ||
192 | printk(KERN_ERR "CS5530: No 8bit DMA enabled\n"); | ||
193 | snd_cs5530_free(chip); | ||
194 | return -ENODEV; | ||
195 | } | ||
196 | |||
197 | if (irq & 1) | ||
198 | irq = 9; | ||
199 | else if (irq & 2) | ||
200 | irq = 5; | ||
201 | else if (irq & 4) | ||
202 | irq = 7; | ||
203 | else if (irq & 8) | ||
204 | irq = 10; | ||
205 | else { | ||
206 | printk(KERN_ERR "CS5530: SoundBlaster IRQ not set\n"); | ||
207 | snd_cs5530_free(chip); | ||
208 | return -ENODEV; | ||
209 | } | ||
210 | |||
211 | printk(KERN_INFO "CS5530: IRQ: %d DMA8: %d DMA16: %d\n", irq, dma8, | ||
212 | dma16); | ||
213 | |||
214 | err = snd_sbdsp_create(card, sb_base, irq, snd_sb16dsp_interrupt, dma8, | ||
215 | dma16, SB_HW_CS5530, &chip->sb); | ||
216 | if (err < 0) { | ||
217 | printk(KERN_ERR "CS5530: Could not create SoundBlaster\n"); | ||
218 | snd_cs5530_free(chip); | ||
219 | return err; | ||
220 | } | ||
221 | |||
222 | err = snd_sb16dsp_pcm(chip->sb, 0, &chip->sb->pcm); | ||
223 | if (err < 0) { | ||
224 | printk(KERN_ERR "CS5530: Could not create PCM\n"); | ||
225 | snd_cs5530_free(chip); | ||
226 | return err; | ||
227 | } | ||
228 | |||
229 | err = snd_sbmixer_new(chip->sb); | ||
230 | if (err < 0) { | ||
231 | printk(KERN_ERR "CS5530: Could not create Mixer\n"); | ||
232 | snd_cs5530_free(chip); | ||
233 | return err; | ||
234 | } | ||
235 | |||
236 | err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); | ||
237 | if (err < 0) { | ||
238 | snd_cs5530_free(chip); | ||
239 | return err; | ||
240 | } | ||
241 | |||
242 | snd_card_set_dev(card, &pci->dev); | ||
243 | *rchip = chip; | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int __devinit snd_cs5530_probe(struct pci_dev *pci, | ||
248 | const struct pci_device_id *pci_id) | ||
249 | { | ||
250 | static int dev; | ||
251 | struct snd_card *card; | ||
252 | struct snd_cs5530 *chip = NULL; | ||
253 | int err; | ||
254 | |||
255 | if (dev >= SNDRV_CARDS) | ||
256 | return -ENODEV; | ||
257 | if (!enable[dev]) { | ||
258 | dev++; | ||
259 | return -ENOENT; | ||
260 | } | ||
261 | |||
262 | card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); | ||
263 | |||
264 | if (card == NULL) | ||
265 | return -ENOMEM; | ||
266 | |||
267 | err = snd_cs5530_create(card, pci, &chip); | ||
268 | if (err < 0) { | ||
269 | snd_card_free(card); | ||
270 | return err; | ||
271 | } | ||
272 | |||
273 | strcpy(card->driver, "CS5530"); | ||
274 | strcpy(card->shortname, "CS5530 Audio"); | ||
275 | sprintf(card->longname, "%s at 0x%lx", card->shortname, chip->pci_base); | ||
276 | |||
277 | err = snd_card_register(card); | ||
278 | if (err < 0) { | ||
279 | snd_card_free(card); | ||
280 | return err; | ||
281 | } | ||
282 | pci_set_drvdata(pci, card); | ||
283 | dev++; | ||
284 | return 0; | ||
285 | } | ||
286 | |||
287 | static struct pci_driver driver = { | ||
288 | .name = "CS5530_Audio", | ||
289 | .id_table = snd_cs5530_ids, | ||
290 | .probe = snd_cs5530_probe, | ||
291 | .remove = __devexit_p(snd_cs5530_remove), | ||
292 | }; | ||
293 | |||
294 | static int __init alsa_card_cs5530_init(void) | ||
295 | { | ||
296 | return pci_register_driver(&driver); | ||
297 | } | ||
298 | |||
299 | static void __exit alsa_card_cs5530_exit(void) | ||
300 | { | ||
301 | pci_unregister_driver(&driver); | ||
302 | } | ||
303 | |||
304 | module_init(alsa_card_cs5530_init) | ||
305 | module_exit(alsa_card_cs5530_exit) | ||
306 | |||
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c index 4a9b59ad8ab1..404ae1be0a4b 100644 --- a/sound/pci/emu10k1/emu10k1_main.c +++ b/sound/pci/emu10k1/emu10k1_main.c | |||
@@ -51,9 +51,15 @@ | |||
51 | 51 | ||
52 | #define HANA_FILENAME "emu/hana.fw" | 52 | #define HANA_FILENAME "emu/hana.fw" |
53 | #define DOCK_FILENAME "emu/audio_dock.fw" | 53 | #define DOCK_FILENAME "emu/audio_dock.fw" |
54 | #define EMU1010B_FILENAME "emu/emu1010b.fw" | ||
55 | #define MICRO_DOCK_FILENAME "emu/micro_dock.fw" | ||
56 | #define EMU1010_NOTEBOOK_FILENAME "emu/emu1010_notebook.fw" | ||
54 | 57 | ||
55 | MODULE_FIRMWARE(HANA_FILENAME); | 58 | MODULE_FIRMWARE(HANA_FILENAME); |
56 | MODULE_FIRMWARE(DOCK_FILENAME); | 59 | MODULE_FIRMWARE(DOCK_FILENAME); |
60 | MODULE_FIRMWARE(EMU1010B_FILENAME); | ||
61 | MODULE_FIRMWARE(MICRO_DOCK_FILENAME); | ||
62 | MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME); | ||
57 | 63 | ||
58 | 64 | ||
59 | /************************************************************************* | 65 | /************************************************************************* |
@@ -660,10 +666,12 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
660 | return err; | 666 | return err; |
661 | } | 667 | } |
662 | snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); | 668 | snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size); |
669 | #if 0 | ||
663 | if (fw_entry->size != 0x133a4) { | 670 | if (fw_entry->size != 0x133a4) { |
664 | snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename); | 671 | snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename); |
665 | return -EINVAL; | 672 | return -EINVAL; |
666 | } | 673 | } |
674 | #endif | ||
667 | 675 | ||
668 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ | 676 | /* The FPGA is a Xilinx Spartan IIE XC2S50E */ |
669 | /* GPIO7 -> FPGA PGMN | 677 | /* GPIO7 -> FPGA PGMN |
@@ -694,6 +702,37 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * file | |||
694 | return 0; | 702 | return 0; |
695 | } | 703 | } |
696 | 704 | ||
705 | /* | ||
706 | * EMU-1010 - details found out from this driver, official MS Win drivers, | ||
707 | * testing the card: | ||
708 | * | ||
709 | * Audigy2 (aka Alice2): | ||
710 | * --------------------- | ||
711 | * * communication over PCI | ||
712 | * * conversion of 32-bit data coming over EMU32 links from HANA FPGA | ||
713 | * to 2 x 16-bit, using internal DSP instructions | ||
714 | * * slave mode, clock supplied by HANA | ||
715 | * * linked to HANA using: | ||
716 | * 32 x 32-bit serial EMU32 output channels | ||
717 | * 16 x EMU32 input channels | ||
718 | * (?) x I2S I/O channels (?) | ||
719 | * | ||
720 | * FPGA (aka HANA): | ||
721 | * --------------- | ||
722 | * * provides all (?) physical inputs and outputs of the card | ||
723 | * (ADC, DAC, SPDIF I/O, ADAT I/O, etc.) | ||
724 | * * provides clock signal for the card and Alice2 | ||
725 | * * two crystals - for 44.1kHz and 48kHz multiples | ||
726 | * * provides internal routing of signal sources to signal destinations | ||
727 | * * inputs/outputs to Alice2 - see above | ||
728 | * | ||
729 | * Current status of the driver: | ||
730 | * ---------------------------- | ||
731 | * * only 44.1/48kHz supported (the MS Win driver supports up to 192 kHz) | ||
732 | * * PCM device nb. 2: | ||
733 | * 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops | ||
734 | * 16 x 32-bit capture - snd_emu10k1_capture_efx_ops | ||
735 | */ | ||
697 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | 736 | static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) |
698 | { | 737 | { |
699 | unsigned int i; | 738 | unsigned int i; |
@@ -727,7 +766,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
727 | /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ | 766 | /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */ |
728 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 767 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); |
729 | snd_printdd("reg1=0x%x\n",reg); | 768 | snd_printdd("reg1=0x%x\n",reg); |
730 | if (reg == 0x55) { | 769 | if ((reg & 0x3f) == 0x15) { |
731 | /* FPGA netlist already present so clear it */ | 770 | /* FPGA netlist already present so clear it */ |
732 | /* Return to programming mode */ | 771 | /* Return to programming mode */ |
733 | 772 | ||
@@ -735,19 +774,32 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
735 | } | 774 | } |
736 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 775 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); |
737 | snd_printdd("reg2=0x%x\n",reg); | 776 | snd_printdd("reg2=0x%x\n",reg); |
738 | if (reg == 0x55) { | 777 | if ((reg & 0x3f) == 0x15) { |
739 | /* FPGA failed to return to programming mode */ | 778 | /* FPGA failed to return to programming mode */ |
779 | snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n"); | ||
740 | return -ENODEV; | 780 | return -ENODEV; |
741 | } | 781 | } |
742 | snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); | 782 | snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg); |
743 | if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) { | 783 | if (emu->card_capabilities->emu1010 == 1) { |
744 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME); | 784 | if ((err = snd_emu1010_load_firmware(emu, HANA_FILENAME)) != 0) { |
745 | return err; | 785 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", HANA_FILENAME); |
786 | return err; | ||
787 | } | ||
788 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
789 | if ((err = snd_emu1010_load_firmware(emu, EMU1010B_FILENAME)) != 0) { | ||
790 | snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010B_FILENAME); | ||
791 | return err; | ||
792 | } | ||
793 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
794 | if ((err = snd_emu1010_load_firmware(emu, EMU1010_NOTEBOOK_FILENAME)) != 0) { | ||
795 | snd_printk(KERN_INFO "emu1010: Loading Firmware file %s failed\n", EMU1010_NOTEBOOK_FILENAME); | ||
796 | return err; | ||
797 | } | ||
746 | } | 798 | } |
747 | 799 | ||
748 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | 800 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ |
749 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 801 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); |
750 | if (reg != 0x55) { | 802 | if ((reg & 0x3f) != 0x15) { |
751 | /* FPGA failed to be programmed */ | 803 | /* FPGA failed to be programmed */ |
752 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg); | 804 | snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg); |
753 | return -ENODEV; | 805 | return -ENODEV; |
@@ -850,6 +902,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
850 | EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1); | 902 | EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1); |
851 | snd_emu1010_fpga_link_dst_src_write(emu, | 903 | snd_emu1010_fpga_link_dst_src_write(emu, |
852 | EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1); | 904 | EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1); |
905 | /* Pavel Hofman - setting defaults for 8 more capture channels | ||
906 | * Defaults only, users will set their own values anyways, let's | ||
907 | * just copy/paste. | ||
908 | */ | ||
909 | |||
910 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
911 | EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1); | ||
912 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
913 | EMU_DST_ALICE2_EMU32_9, EMU_SRC_DOCK_MIC_B1); | ||
914 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
915 | EMU_DST_ALICE2_EMU32_A, EMU_SRC_HAMOA_ADC_LEFT2); | ||
916 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
917 | EMU_DST_ALICE2_EMU32_B, EMU_SRC_HAMOA_ADC_LEFT2); | ||
918 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
919 | EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_ADC1_LEFT1); | ||
920 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
921 | EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_ADC1_RIGHT1); | ||
922 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
923 | EMU_DST_ALICE2_EMU32_E, EMU_SRC_DOCK_ADC2_LEFT1); | ||
924 | snd_emu1010_fpga_link_dst_src_write(emu, | ||
925 | EMU_DST_ALICE2_EMU32_F, EMU_SRC_DOCK_ADC2_RIGHT1); | ||
853 | #endif | 926 | #endif |
854 | #if 0 | 927 | #if 0 |
855 | /* Original */ | 928 | /* Original */ |
@@ -943,16 +1016,27 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu) | |||
943 | /* Return to Audio Dock programming mode */ | 1016 | /* Return to Audio Dock programming mode */ |
944 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); | 1017 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n"); |
945 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); | 1018 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK ); |
946 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { | 1019 | if (emu->card_capabilities->emu1010 == 1) { |
947 | return err; | 1020 | if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) { |
1021 | return err; | ||
1022 | } | ||
1023 | } else if (emu->card_capabilities->emu1010 == 2) { | ||
1024 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1025 | return err; | ||
1026 | } | ||
1027 | } else if (emu->card_capabilities->emu1010 == 3) { | ||
1028 | if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) { | ||
1029 | return err; | ||
1030 | } | ||
948 | } | 1031 | } |
1032 | |||
949 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); | 1033 | snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 ); |
950 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); | 1034 | snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, ® ); |
951 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); | 1035 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg); |
952 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ | 1036 | /* ID, should read & 0x7f = 0x55 when FPGA programmed. */ |
953 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); | 1037 | snd_emu1010_fpga_read(emu, EMU_HANA_ID, ® ); |
954 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); | 1038 | snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg); |
955 | if (reg != 0x55) { | 1039 | if ((reg & 0x3f) != 0x15) { |
956 | /* FPGA failed to be programmed */ | 1040 | /* FPGA failed to be programmed */ |
957 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); | 1041 | snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg); |
958 | return 0; | 1042 | return 0; |
@@ -1227,9 +1311,15 @@ static struct snd_emu_chip_details emu_chip_details[] = { | |||
1227 | .emu10k2_chip = 1, | 1311 | .emu10k2_chip = 1, |
1228 | .ca0108_chip = 1, | 1312 | .ca0108_chip = 1, |
1229 | .ca_cardbus_chip = 1, | 1313 | .ca_cardbus_chip = 1, |
1230 | .spi_dac = 1, | 1314 | .spk71 = 1 , |
1231 | .i2c_adc = 1, | 1315 | .emu1010 = 3} , |
1232 | .spk71 = 1} , | 1316 | {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102, |
1317 | .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]", | ||
1318 | .id = "EMU1010", | ||
1319 | .emu10k2_chip = 1, | ||
1320 | .ca0108_chip = 1, | ||
1321 | .spk71 = 1 , | ||
1322 | .emu1010 = 2} , | ||
1233 | {.vendor = 0x1102, .device = 0x0008, | 1323 | {.vendor = 0x1102, .device = 0x0008, |
1234 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", | 1324 | .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", |
1235 | .id = "Audigy2", | 1325 | .id = "Audigy2", |
@@ -1663,12 +1753,13 @@ int __devinit snd_emu10k1_create(struct snd_card *card, | |||
1663 | emu->fx8010.extout_mask = extout_mask; | 1753 | emu->fx8010.extout_mask = extout_mask; |
1664 | emu->enable_ir = enable_ir; | 1754 | emu->enable_ir = enable_ir; |
1665 | 1755 | ||
1756 | if (emu->card_capabilities->ca_cardbus_chip) { | ||
1757 | if ((err = snd_emu10k1_cardbus_init(emu)) < 0) | ||
1758 | goto error; | ||
1759 | } | ||
1666 | if (emu->card_capabilities->ecard) { | 1760 | if (emu->card_capabilities->ecard) { |
1667 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) | 1761 | if ((err = snd_emu10k1_ecard_init(emu)) < 0) |
1668 | goto error; | 1762 | goto error; |
1669 | } else if (emu->card_capabilities->ca_cardbus_chip) { | ||
1670 | if ((err = snd_emu10k1_cardbus_init(emu)) < 0) | ||
1671 | goto error; | ||
1672 | } else if (emu->card_capabilities->emu1010) { | 1763 | } else if (emu->card_capabilities->emu1010) { |
1673 | if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { | 1764 | if ((err = snd_emu10k1_emu1010_init(emu)) < 0) { |
1674 | snd_emu10k1_free(emu); | 1765 | snd_emu10k1_free(emu); |
@@ -1814,10 +1905,10 @@ void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu) | |||
1814 | 1905 | ||
1815 | void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) | 1906 | void snd_emu10k1_resume_init(struct snd_emu10k1 *emu) |
1816 | { | 1907 | { |
1908 | if (emu->card_capabilities->ca_cardbus_chip) | ||
1909 | snd_emu10k1_cardbus_init(emu); | ||
1817 | if (emu->card_capabilities->ecard) | 1910 | if (emu->card_capabilities->ecard) |
1818 | snd_emu10k1_ecard_init(emu); | 1911 | snd_emu10k1_ecard_init(emu); |
1819 | else if (emu->card_capabilities->ca_cardbus_chip) | ||
1820 | snd_emu10k1_cardbus_init(emu); | ||
1821 | else if (emu->card_capabilities->emu1010) | 1912 | else if (emu->card_capabilities->emu1010) |
1822 | snd_emu10k1_emu1010_init(emu); | 1913 | snd_emu10k1_emu1010_init(emu); |
1823 | else | 1914 | else |
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c index c02012cccd8e..7206c0fa06f2 100644 --- a/sound/pci/emu10k1/emufx.c +++ b/sound/pci/emu10k1/emufx.c | |||
@@ -1123,6 +1123,11 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl | |||
1123 | ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; | 1123 | ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; |
1124 | } | 1124 | } |
1125 | 1125 | ||
1126 | /* | ||
1127 | * Used for emu1010 - conversion from 32-bit capture inputs from HANA | ||
1128 | * to 2 x 16-bit registers in audigy - their values are read via DMA. | ||
1129 | * Conversion is performed by Audigy DSP instructions of FX8010. | ||
1130 | */ | ||
1126 | static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( | 1131 | static int snd_emu10k1_audigy_dsp_convert_32_to_2x16( |
1127 | struct snd_emu10k1_fx8010_code *icode, | 1132 | struct snd_emu10k1_fx8010_code *icode, |
1128 | u32 *ptr, int tmp, int bit_shifter16, | 1133 | u32 *ptr, int tmp, int bit_shifter16, |
@@ -1193,7 +1198,11 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) | |||
1193 | snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); | 1198 | snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); |
1194 | 1199 | ||
1195 | #if 1 | 1200 | #if 1 |
1196 | /* PCM front Playback Volume (independent from stereo mix) */ | 1201 | /* PCM front Playback Volume (independent from stereo mix) |
1202 | * playback = 0 + ( gpr * FXBUS_PCM_LEFT_FRONT >> 31) | ||
1203 | * where gpr contains attenuation from corresponding mixer control | ||
1204 | * (snd_emu10k1_init_stereo_control) | ||
1205 | */ | ||
1197 | A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); | 1206 | A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); |
1198 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); | 1207 | A_OP(icode, &ptr, iMAC0, A_GPR(playback+1), A_C_00000000, A_GPR(gpr+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT)); |
1199 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); | 1208 | snd_emu10k1_init_stereo_control(&controls[nctl++], "PCM Front Playback Volume", gpr, 100); |
@@ -1549,7 +1558,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1549 | 1558 | ||
1550 | if (emu->card_capabilities->emu1010) { | 1559 | if (emu->card_capabilities->emu1010) { |
1551 | snd_printk("EMU inputs on\n"); | 1560 | snd_printk("EMU inputs on\n"); |
1552 | /* Capture 8 channels of S32_LE sound */ | 1561 | /* Capture 16 (originally 8) channels of S32_LE sound */ |
1553 | 1562 | ||
1554 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ | 1563 | /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */ |
1555 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ | 1564 | /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */ |
@@ -1560,6 +1569,11 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1560 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); | 1569 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) ); |
1561 | /* Right ADC in 1 of 2 */ | 1570 | /* Right ADC in 1 of 2 */ |
1562 | gpr_map[gpr++] = 0x00000000; | 1571 | gpr_map[gpr++] = 0x00000000; |
1572 | /* Delaying by one sample: instead of copying the input | ||
1573 | * value A_P16VIN to output A_FXBUS2 as in the first channel, | ||
1574 | * we use an auxiliary register, delaying the value by one | ||
1575 | * sample | ||
1576 | */ | ||
1563 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); | 1577 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) ); |
1564 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); | 1578 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000); |
1565 | gpr_map[gpr++] = 0x00000000; | 1579 | gpr_map[gpr++] = 0x00000000; |
@@ -1583,6 +1597,66 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) | |||
1583 | gpr_map[gpr++] = 0x00000000; | 1597 | gpr_map[gpr++] = 0x00000000; |
1584 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); | 1598 | snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) ); |
1585 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); | 1599 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000); |
1600 | /* Pavel Hofman - we still have voices, A_FXBUS2s, and | ||
1601 | * A_P16VINs available - | ||
1602 | * let's add 8 more capture channels - total of 16 | ||
1603 | */ | ||
1604 | gpr_map[gpr++] = 0x00000000; | ||
1605 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1606 | bit_shifter16, | ||
1607 | A_GPR(gpr - 1), | ||
1608 | A_FXBUS2(0x10)); | ||
1609 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x8), | ||
1610 | A_C_00000000, A_C_00000000); | ||
1611 | gpr_map[gpr++] = 0x00000000; | ||
1612 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1613 | bit_shifter16, | ||
1614 | A_GPR(gpr - 1), | ||
1615 | A_FXBUS2(0x12)); | ||
1616 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x9), | ||
1617 | A_C_00000000, A_C_00000000); | ||
1618 | gpr_map[gpr++] = 0x00000000; | ||
1619 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1620 | bit_shifter16, | ||
1621 | A_GPR(gpr - 1), | ||
1622 | A_FXBUS2(0x14)); | ||
1623 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xa), | ||
1624 | A_C_00000000, A_C_00000000); | ||
1625 | gpr_map[gpr++] = 0x00000000; | ||
1626 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1627 | bit_shifter16, | ||
1628 | A_GPR(gpr - 1), | ||
1629 | A_FXBUS2(0x16)); | ||
1630 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xb), | ||
1631 | A_C_00000000, A_C_00000000); | ||
1632 | gpr_map[gpr++] = 0x00000000; | ||
1633 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1634 | bit_shifter16, | ||
1635 | A_GPR(gpr - 1), | ||
1636 | A_FXBUS2(0x18)); | ||
1637 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xc), | ||
1638 | A_C_00000000, A_C_00000000); | ||
1639 | gpr_map[gpr++] = 0x00000000; | ||
1640 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1641 | bit_shifter16, | ||
1642 | A_GPR(gpr - 1), | ||
1643 | A_FXBUS2(0x1a)); | ||
1644 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xd), | ||
1645 | A_C_00000000, A_C_00000000); | ||
1646 | gpr_map[gpr++] = 0x00000000; | ||
1647 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1648 | bit_shifter16, | ||
1649 | A_GPR(gpr - 1), | ||
1650 | A_FXBUS2(0x1c)); | ||
1651 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xe), | ||
1652 | A_C_00000000, A_C_00000000); | ||
1653 | gpr_map[gpr++] = 0x00000000; | ||
1654 | snd_emu10k1_audigy_dsp_convert_32_to_2x16(icode, &ptr, tmp, | ||
1655 | bit_shifter16, | ||
1656 | A_GPR(gpr - 1), | ||
1657 | A_FXBUS2(0x1e)); | ||
1658 | A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0xf), | ||
1659 | A_C_00000000, A_C_00000000); | ||
1586 | 1660 | ||
1587 | #if 0 | 1661 | #if 0 |
1588 | for (z = 4; z < 8; z++) { | 1662 | for (z = 4; z < 8; z++) { |
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c index 4db6e1ca1665..7b2c1dcc5337 100644 --- a/sound/pci/emu10k1/emumixer.c +++ b/sound/pci/emu10k1/emumixer.c | |||
@@ -77,6 +77,10 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol, | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | /* | ||
81 | * Items labels in enum mixer controls assigning source data to | ||
82 | * each destination | ||
83 | */ | ||
80 | static char *emu1010_src_texts[] = { | 84 | static char *emu1010_src_texts[] = { |
81 | "Silence", | 85 | "Silence", |
82 | "Dock Mic A", | 86 | "Dock Mic A", |
@@ -133,6 +137,9 @@ static char *emu1010_src_texts[] = { | |||
133 | "DSP 31", | 137 | "DSP 31", |
134 | }; | 138 | }; |
135 | 139 | ||
140 | /* | ||
141 | * List of data sources available for each destination | ||
142 | */ | ||
136 | static unsigned int emu1010_src_regs[] = { | 143 | static unsigned int emu1010_src_regs[] = { |
137 | EMU_SRC_SILENCE,/* 0 */ | 144 | EMU_SRC_SILENCE,/* 0 */ |
138 | EMU_SRC_DOCK_MIC_A1, /* 1 */ | 145 | EMU_SRC_DOCK_MIC_A1, /* 1 */ |
@@ -189,6 +196,10 @@ static unsigned int emu1010_src_regs[] = { | |||
189 | EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ | 196 | EMU_SRC_ALICE_EMU32B+0xf, /* 52 */ |
190 | }; | 197 | }; |
191 | 198 | ||
199 | /* | ||
200 | * Data destinations - physical EMU outputs. | ||
201 | * Each destination has an enum mixer control to choose a data source | ||
202 | */ | ||
192 | static unsigned int emu1010_output_dst[] = { | 203 | static unsigned int emu1010_output_dst[] = { |
193 | EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ | 204 | EMU_DST_DOCK_DAC1_LEFT1, /* 0 */ |
194 | EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ | 205 | EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */ |
@@ -216,6 +227,11 @@ static unsigned int emu1010_output_dst[] = { | |||
216 | EMU_DST_HANA_ADAT+7, /* 23 */ | 227 | EMU_DST_HANA_ADAT+7, /* 23 */ |
217 | }; | 228 | }; |
218 | 229 | ||
230 | /* | ||
231 | * Data destinations - HANA outputs going to Alice2 (audigy) for | ||
232 | * capture (EMU32 + I2S links) | ||
233 | * Each destination has an enum mixer control to choose a data source | ||
234 | */ | ||
219 | static unsigned int emu1010_input_dst[] = { | 235 | static unsigned int emu1010_input_dst[] = { |
220 | EMU_DST_ALICE2_EMU32_0, | 236 | EMU_DST_ALICE2_EMU32_0, |
221 | EMU_DST_ALICE2_EMU32_1, | 237 | EMU_DST_ALICE2_EMU32_1, |
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index ab4f5df5241b..eda5cb373ded 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c | |||
@@ -1233,24 +1233,26 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) | |||
1233 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; | 1233 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; |
1234 | spin_lock_irq(&emu->reg_lock); | 1234 | spin_lock_irq(&emu->reg_lock); |
1235 | if (emu->card_capabilities->emu1010) { | 1235 | if (emu->card_capabilities->emu1010) { |
1236 | /* TODO | 1236 | /* Nb. of channels has been increased to 16 */ |
1237 | /* TODO | ||
1237 | * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE | 1238 | * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE |
1238 | * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | | 1239 | * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | |
1239 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | | 1240 | * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | |
1240 | * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 | 1241 | * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 |
1241 | * rate_min = 44100, | 1242 | * rate_min = 44100, |
1242 | * rate_max = 192000, | 1243 | * rate_max = 192000, |
1243 | * channels_min = 8, | 1244 | * channels_min = 16, |
1244 | * channels_max = 8, | 1245 | * channels_max = 16, |
1245 | * Need to add mixer control to fix sample rate | 1246 | * Need to add mixer control to fix sample rate |
1246 | * | 1247 | * |
1247 | * There are 16 mono channels of 16bits each. | 1248 | * There are 32 mono channels of 16bits each. |
1248 | * 24bit Audio uses 2x channels over 16bit | 1249 | * 24bit Audio uses 2x channels over 16bit |
1249 | * 96kHz uses 2x channels over 48kHz | 1250 | * 96kHz uses 2x channels over 48kHz |
1250 | * 192kHz uses 4x channels over 48kHz | 1251 | * 192kHz uses 4x channels over 48kHz |
1251 | * So, for 48kHz 24bit, one has 8 channels | 1252 | * So, for 48kHz 24bit, one has 16 channels |
1252 | * for 96kHz 24bit, one has 4 channels | 1253 | * for 96kHz 24bit, one has 8 channels |
1253 | * for 192kHz 24bit, one has 2 channels | 1254 | * for 192kHz 24bit, one has 4 channels |
1255 | * | ||
1254 | */ | 1256 | */ |
1255 | #if 1 | 1257 | #if 1 |
1256 | switch (emu->emu1010.internal_clock) { | 1258 | switch (emu->emu1010.internal_clock) { |
@@ -1258,13 +1260,15 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) | |||
1258 | /* For 44.1kHz */ | 1260 | /* For 44.1kHz */ |
1259 | runtime->hw.rates = SNDRV_PCM_RATE_44100; | 1261 | runtime->hw.rates = SNDRV_PCM_RATE_44100; |
1260 | runtime->hw.rate_min = runtime->hw.rate_max = 44100; | 1262 | runtime->hw.rate_min = runtime->hw.rate_max = 44100; |
1261 | runtime->hw.channels_min = runtime->hw.channels_max = 8; | 1263 | runtime->hw.channels_min = |
1264 | runtime->hw.channels_max = 16; | ||
1262 | break; | 1265 | break; |
1263 | case 1: | 1266 | case 1: |
1264 | /* For 48kHz */ | 1267 | /* For 48kHz */ |
1265 | runtime->hw.rates = SNDRV_PCM_RATE_48000; | 1268 | runtime->hw.rates = SNDRV_PCM_RATE_48000; |
1266 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; | 1269 | runtime->hw.rate_min = runtime->hw.rate_max = 48000; |
1267 | runtime->hw.channels_min = runtime->hw.channels_max = 8; | 1270 | runtime->hw.channels_min = |
1271 | runtime->hw.channels_max = 16; | ||
1268 | break; | 1272 | break; |
1269 | }; | 1273 | }; |
1270 | #endif | 1274 | #endif |
@@ -1282,7 +1286,7 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream) | |||
1282 | #endif | 1286 | #endif |
1283 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; | 1287 | runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE; |
1284 | /* efx_voices_mask[0] is expected to be zero | 1288 | /* efx_voices_mask[0] is expected to be zero |
1285 | * efx_voices_mask[1] is expected to have 16bits set | 1289 | * efx_voices_mask[1] is expected to have 32bits set |
1286 | */ | 1290 | */ |
1287 | } else { | 1291 | } else { |
1288 | runtime->hw.channels_min = runtime->hw.channels_max = 0; | 1292 | runtime->hw.channels_min = runtime->hw.channels_max = 0; |
@@ -1787,11 +1791,24 @@ int __devinit snd_emu10k1_pcm_efx(struct snd_emu10k1 * emu, int device, struct s | |||
1787 | /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ | 1791 | /* emu->efx_voices_mask[0] = FXWC_DEFAULTROUTE_C | FXWC_DEFAULTROUTE_A; */ |
1788 | if (emu->audigy) { | 1792 | if (emu->audigy) { |
1789 | emu->efx_voices_mask[0] = 0; | 1793 | emu->efx_voices_mask[0] = 0; |
1790 | emu->efx_voices_mask[1] = 0xffff; | 1794 | if (emu->card_capabilities->emu1010) |
1795 | /* Pavel Hofman - 32 voices will be used for | ||
1796 | * capture (write mode) - | ||
1797 | * each bit = corresponding voice | ||
1798 | */ | ||
1799 | emu->efx_voices_mask[1] = 0xffffffff; | ||
1800 | else | ||
1801 | emu->efx_voices_mask[1] = 0xffff; | ||
1791 | } else { | 1802 | } else { |
1792 | emu->efx_voices_mask[0] = 0xffff0000; | 1803 | emu->efx_voices_mask[0] = 0xffff0000; |
1793 | emu->efx_voices_mask[1] = 0; | 1804 | emu->efx_voices_mask[1] = 0; |
1794 | } | 1805 | } |
1806 | /* For emu1010, the control has to set 32 upper bits (voices) | ||
1807 | * out of the 64 bits (voices) to true for the 16-channels capture | ||
1808 | * to work correctly. Correct A_FXWC2 initial value (0xffffffff) | ||
1809 | * is already defined but the snd_emu10k1_pcm_efx_voices_mask | ||
1810 | * control can override this register's value. | ||
1811 | */ | ||
1795 | kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu); | 1812 | kctl = snd_ctl_new1(&snd_emu10k1_pcm_efx_voices_mask, emu); |
1796 | if (!kctl) | 1813 | if (!kctl) |
1797 | return -ENOMEM; | 1814 | return -ENOMEM; |
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c index 7c403965153b..21cb4268a59b 100644 --- a/sound/pci/ens1370.c +++ b/sound/pci/ens1370.c | |||
@@ -1607,8 +1607,8 @@ struct es1371_quirk { | |||
1607 | unsigned char rev; /* revision */ | 1607 | unsigned char rev; /* revision */ |
1608 | }; | 1608 | }; |
1609 | 1609 | ||
1610 | static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq, | 1610 | static int es1371_quirk_lookup(struct ensoniq *ensoniq, |
1611 | struct es1371_quirk *list) | 1611 | struct es1371_quirk *list) |
1612 | { | 1612 | { |
1613 | while (list->vid != (unsigned short)PCI_ANY_ID) { | 1613 | while (list->vid != (unsigned short)PCI_ANY_ID) { |
1614 | if (ensoniq->pci->vendor == list->vid && | 1614 | if (ensoniq->pci->vendor == list->vid && |
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 2fa281cbef91..92bc8b3fa2a0 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -341,6 +341,9 @@ struct azx { | |||
341 | unsigned int single_cmd :1; | 341 | unsigned int single_cmd :1; |
342 | unsigned int polling_mode :1; | 342 | unsigned int polling_mode :1; |
343 | unsigned int msi :1; | 343 | unsigned int msi :1; |
344 | |||
345 | /* for debugging */ | ||
346 | unsigned int last_cmd; /* last issued command (to sync) */ | ||
344 | }; | 347 | }; |
345 | 348 | ||
346 | /* driver types */ | 349 | /* driver types */ |
@@ -466,18 +469,10 @@ static void azx_free_cmd_io(struct azx *chip) | |||
466 | } | 469 | } |
467 | 470 | ||
468 | /* send a command */ | 471 | /* send a command */ |
469 | static int azx_corb_send_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, | 472 | static int azx_corb_send_cmd(struct hda_codec *codec, u32 val) |
470 | unsigned int verb, unsigned int para) | ||
471 | { | 473 | { |
472 | struct azx *chip = codec->bus->private_data; | 474 | struct azx *chip = codec->bus->private_data; |
473 | unsigned int wp; | 475 | unsigned int wp; |
474 | u32 val; | ||
475 | |||
476 | val = (u32)(codec->addr & 0x0f) << 28; | ||
477 | val |= (u32)direct << 27; | ||
478 | val |= (u32)nid << 20; | ||
479 | val |= verb << 8; | ||
480 | val |= para; | ||
481 | 476 | ||
482 | /* add command to corb */ | 477 | /* add command to corb */ |
483 | wp = azx_readb(chip, CORBWP); | 478 | wp = azx_readb(chip, CORBWP); |
@@ -538,12 +533,12 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
538 | } | 533 | } |
539 | if (! chip->rirb.cmds) | 534 | if (! chip->rirb.cmds) |
540 | return chip->rirb.res; /* the last value */ | 535 | return chip->rirb.res; /* the last value */ |
541 | schedule_timeout_interruptible(1); | 536 | schedule_timeout(1); |
542 | } while (time_after_eq(timeout, jiffies)); | 537 | } while (time_after_eq(timeout, jiffies)); |
543 | 538 | ||
544 | if (chip->msi) { | 539 | if (chip->msi) { |
545 | snd_printk(KERN_WARNING "hda_intel: No response from codec, " | 540 | snd_printk(KERN_WARNING "hda_intel: No response from codec, " |
546 | "disabling MSI...\n"); | 541 | "disabling MSI: last cmd=0x%08x\n", chip->last_cmd); |
547 | free_irq(chip->irq, chip); | 542 | free_irq(chip->irq, chip); |
548 | chip->irq = -1; | 543 | chip->irq = -1; |
549 | pci_disable_msi(chip->pci); | 544 | pci_disable_msi(chip->pci); |
@@ -555,13 +550,15 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
555 | 550 | ||
556 | if (!chip->polling_mode) { | 551 | if (!chip->polling_mode) { |
557 | snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " | 552 | snd_printk(KERN_WARNING "hda_intel: azx_get_response timeout, " |
558 | "switching to polling mode...\n"); | 553 | "switching to polling mode: last cmd=0x%08x\n", |
554 | chip->last_cmd); | ||
559 | chip->polling_mode = 1; | 555 | chip->polling_mode = 1; |
560 | goto again; | 556 | goto again; |
561 | } | 557 | } |
562 | 558 | ||
563 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " | 559 | snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, " |
564 | "switching to single_cmd mode...\n"); | 560 | "switching to single_cmd mode: last cmd=0x%08x\n", |
561 | chip->last_cmd); | ||
565 | chip->rirb.rp = azx_readb(chip, RIRBWP); | 562 | chip->rirb.rp = azx_readb(chip, RIRBWP); |
566 | chip->rirb.cmds = 0; | 563 | chip->rirb.cmds = 0; |
567 | /* switch to single_cmd mode */ | 564 | /* switch to single_cmd mode */ |
@@ -581,20 +578,11 @@ static unsigned int azx_rirb_get_response(struct hda_codec *codec) | |||
581 | */ | 578 | */ |
582 | 579 | ||
583 | /* send a command */ | 580 | /* send a command */ |
584 | static int azx_single_send_cmd(struct hda_codec *codec, hda_nid_t nid, | 581 | static int azx_single_send_cmd(struct hda_codec *codec, u32 val) |
585 | int direct, unsigned int verb, | ||
586 | unsigned int para) | ||
587 | { | 582 | { |
588 | struct azx *chip = codec->bus->private_data; | 583 | struct azx *chip = codec->bus->private_data; |
589 | u32 val; | ||
590 | int timeout = 50; | 584 | int timeout = 50; |
591 | 585 | ||
592 | val = (u32)(codec->addr & 0x0f) << 28; | ||
593 | val |= (u32)direct << 27; | ||
594 | val |= (u32)nid << 20; | ||
595 | val |= verb << 8; | ||
596 | val |= para; | ||
597 | |||
598 | while (timeout--) { | 586 | while (timeout--) { |
599 | /* check ICB busy bit */ | 587 | /* check ICB busy bit */ |
600 | if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { | 588 | if (! (azx_readw(chip, IRS) & ICH6_IRS_BUSY)) { |
@@ -639,10 +627,19 @@ static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid, | |||
639 | unsigned int para) | 627 | unsigned int para) |
640 | { | 628 | { |
641 | struct azx *chip = codec->bus->private_data; | 629 | struct azx *chip = codec->bus->private_data; |
630 | u32 val; | ||
631 | |||
632 | val = (u32)(codec->addr & 0x0f) << 28; | ||
633 | val |= (u32)direct << 27; | ||
634 | val |= (u32)nid << 20; | ||
635 | val |= verb << 8; | ||
636 | val |= para; | ||
637 | chip->last_cmd = val; | ||
638 | |||
642 | if (chip->single_cmd) | 639 | if (chip->single_cmd) |
643 | return azx_single_send_cmd(codec, nid, direct, verb, para); | 640 | return azx_single_send_cmd(codec, val); |
644 | else | 641 | else |
645 | return azx_corb_send_cmd(codec, nid, direct, verb, para); | 642 | return azx_corb_send_cmd(codec, val); |
646 | } | 643 | } |
647 | 644 | ||
648 | /* get a response */ | 645 | /* get a response */ |
@@ -1788,6 +1785,12 @@ static struct pci_device_id azx_ids[] = { | |||
1788 | { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */ | 1785 | { 0x10de, 0x044b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP65 */ |
1789 | { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ | 1786 | { 0x10de, 0x055c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ |
1790 | { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ | 1787 | { 0x10de, 0x055d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP67 */ |
1788 | { 0x10de, 0x07fc, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */ | ||
1789 | { 0x10de, 0x07fd, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP73 */ | ||
1790 | { 0x10de, 0x0774, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | ||
1791 | { 0x10de, 0x0775, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | ||
1792 | { 0x10de, 0x0776, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | ||
1793 | { 0x10de, 0x0777, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_NVIDIA }, /* NVIDIA MCP77 */ | ||
1791 | { 0, } | 1794 | { 0, } |
1792 | }; | 1795 | }; |
1793 | MODULE_DEVICE_TABLE(pci, azx_ids); | 1796 | MODULE_DEVICE_TABLE(pci, azx_ids); |
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c index e313e685f161..ac15066fd300 100644 --- a/sound/pci/hda/hda_proc.c +++ b/sound/pci/hda/hda_proc.c | |||
@@ -250,6 +250,12 @@ static void print_codec_info(struct snd_info_entry *entry, struct snd_info_buffe | |||
250 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); | 250 | snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id); |
251 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); | 251 | snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id); |
252 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); | 252 | snd_iprintf(buffer, "Revision Id: 0x%x\n", codec->revision_id); |
253 | |||
254 | if (codec->mfg) | ||
255 | snd_iprintf(buffer, "Modem Function Group: 0x%x\n", codec->mfg); | ||
256 | else | ||
257 | snd_iprintf(buffer, "No Modem Function Group found\n"); | ||
258 | |||
253 | if (! codec->afg) | 259 | if (! codec->afg) |
254 | return; | 260 | return; |
255 | snd_iprintf(buffer, "Default PCM:\n"); | 261 | snd_iprintf(buffer, "Default PCM:\n"); |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 0e1a879663fa..4d7f8d11ad75 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * HD audio interface patch for AD1981HD, AD1983, AD1986A, AD1988 | 2 | * HD audio interface patch for AD1882, AD1884, AD1981HD, AD1983, AD1984, |
3 | * AD1986A, AD1988 | ||
3 | * | 4 | * |
4 | * Copyright (c) 2005 Takashi Iwai <tiwai@suse.de> | 5 | * Copyright (c) 2005-2007 Takashi Iwai <tiwai@suse.de> |
5 | * | 6 | * |
6 | * This driver is free software; you can redistribute it and/or modify | 7 | * This driver is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -61,7 +62,7 @@ struct ad198x_spec { | |||
61 | int num_channel_mode; | 62 | int num_channel_mode; |
62 | 63 | ||
63 | /* PCM information */ | 64 | /* PCM information */ |
64 | struct hda_pcm pcm_rec[2]; /* used in alc_build_pcms() */ | 65 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
65 | 66 | ||
66 | struct mutex amp_mutex; /* PCM volume/mute control mutex */ | 67 | struct mutex amp_mutex; /* PCM volume/mute control mutex */ |
67 | unsigned int spdif_route; | 68 | unsigned int spdif_route; |
@@ -2775,11 +2776,634 @@ static int patch_ad1988(struct hda_codec *codec) | |||
2775 | 2776 | ||
2776 | 2777 | ||
2777 | /* | 2778 | /* |
2779 | * AD1884 / AD1984 | ||
2780 | * | ||
2781 | * port-B - front line/mic-in | ||
2782 | * port-E - aux in/out | ||
2783 | * port-F - aux in/out | ||
2784 | * port-C - rear line/mic-in | ||
2785 | * port-D - rear line/hp-out | ||
2786 | * port-A - front line/hp-out | ||
2787 | * | ||
2788 | * AD1984 = AD1884 + two digital mic-ins | ||
2789 | * | ||
2790 | * FIXME: | ||
2791 | * For simplicity, we share the single DAC for both HP and line-outs | ||
2792 | * right now. The inidividual playbacks could be easily implemented, | ||
2793 | * but no build-up framework is given, so far. | ||
2794 | */ | ||
2795 | |||
2796 | static hda_nid_t ad1884_dac_nids[1] = { | ||
2797 | 0x04, | ||
2798 | }; | ||
2799 | |||
2800 | static hda_nid_t ad1884_adc_nids[2] = { | ||
2801 | 0x08, 0x09, | ||
2802 | }; | ||
2803 | |||
2804 | static hda_nid_t ad1884_capsrc_nids[2] = { | ||
2805 | 0x0c, 0x0d, | ||
2806 | }; | ||
2807 | |||
2808 | #define AD1884_SPDIF_OUT 0x02 | ||
2809 | |||
2810 | static struct hda_input_mux ad1884_capture_source = { | ||
2811 | .num_items = 4, | ||
2812 | .items = { | ||
2813 | { "Front Mic", 0x0 }, | ||
2814 | { "Mic", 0x1 }, | ||
2815 | { "CD", 0x2 }, | ||
2816 | { "Mix", 0x3 }, | ||
2817 | }, | ||
2818 | }; | ||
2819 | |||
2820 | static struct snd_kcontrol_new ad1884_base_mixers[] = { | ||
2821 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), | ||
2822 | /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ | ||
2823 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
2824 | HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
2825 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), | ||
2826 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), | ||
2827 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | ||
2828 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | ||
2829 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), | ||
2830 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | ||
2831 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), | ||
2832 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), | ||
2833 | /* | ||
2834 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
2835 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
2836 | HDA_CODEC_VOLUME("Digital Beep Playback Volume", 0x10, 0x0, HDA_OUTPUT), | ||
2837 | HDA_CODEC_MUTE("Digital Beep Playback Switch", 0x10, 0x0, HDA_OUTPUT), | ||
2838 | */ | ||
2839 | HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), | ||
2840 | HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), | ||
2841 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
2842 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
2843 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
2844 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
2845 | { | ||
2846 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2847 | /* The multiple "Capture Source" controls confuse alsamixer | ||
2848 | * So call somewhat different.. | ||
2849 | * FIXME: the controls appear in the "playback" view! | ||
2850 | */ | ||
2851 | /* .name = "Capture Source", */ | ||
2852 | .name = "Input Source", | ||
2853 | .count = 2, | ||
2854 | .info = ad198x_mux_enum_info, | ||
2855 | .get = ad198x_mux_enum_get, | ||
2856 | .put = ad198x_mux_enum_put, | ||
2857 | }, | ||
2858 | /* SPDIF controls */ | ||
2859 | HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | ||
2860 | { | ||
2861 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2862 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", | ||
2863 | /* identical with ad1983 */ | ||
2864 | .info = ad1983_spdif_route_info, | ||
2865 | .get = ad1983_spdif_route_get, | ||
2866 | .put = ad1983_spdif_route_put, | ||
2867 | }, | ||
2868 | { } /* end */ | ||
2869 | }; | ||
2870 | |||
2871 | static struct snd_kcontrol_new ad1984_dmic_mixers[] = { | ||
2872 | HDA_CODEC_VOLUME("Digital Mic Capture Volume", 0x05, 0x0, HDA_INPUT), | ||
2873 | HDA_CODEC_MUTE("Digital Mic Capture Switch", 0x05, 0x0, HDA_INPUT), | ||
2874 | HDA_CODEC_VOLUME_IDX("Digital Mic Capture Volume", 1, 0x06, 0x0, | ||
2875 | HDA_INPUT), | ||
2876 | HDA_CODEC_MUTE_IDX("Digital Mic Capture Switch", 1, 0x06, 0x0, | ||
2877 | HDA_INPUT), | ||
2878 | { } /* end */ | ||
2879 | }; | ||
2880 | |||
2881 | /* | ||
2882 | * initialization verbs | ||
2883 | */ | ||
2884 | static struct hda_verb ad1884_init_verbs[] = { | ||
2885 | /* DACs; mute as default */ | ||
2886 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
2887 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
2888 | /* Port-A (HP) mixer */ | ||
2889 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
2890 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
2891 | /* Port-A pin */ | ||
2892 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2893 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2894 | /* HP selector - select DAC2 */ | ||
2895 | {0x22, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
2896 | /* Port-D (Line-out) mixer */ | ||
2897 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
2898 | {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
2899 | /* Port-D pin */ | ||
2900 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2901 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2902 | /* Mono-out mixer */ | ||
2903 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
2904 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
2905 | /* Mono-out pin */ | ||
2906 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
2907 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2908 | /* Mono selector */ | ||
2909 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
2910 | /* Port-B (front mic) pin */ | ||
2911 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2912 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2913 | /* Port-C (rear mic) pin */ | ||
2914 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
2915 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
2916 | /* Analog mixer; mute as default */ | ||
2917 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
2918 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
2919 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
2920 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
2921 | /* Analog Mix output amp */ | ||
2922 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | ||
2923 | /* SPDIF output selector */ | ||
2924 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ | ||
2925 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ | ||
2926 | { } /* end */ | ||
2927 | }; | ||
2928 | |||
2929 | static int patch_ad1884(struct hda_codec *codec) | ||
2930 | { | ||
2931 | struct ad198x_spec *spec; | ||
2932 | |||
2933 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
2934 | if (spec == NULL) | ||
2935 | return -ENOMEM; | ||
2936 | |||
2937 | mutex_init(&spec->amp_mutex); | ||
2938 | codec->spec = spec; | ||
2939 | |||
2940 | spec->multiout.max_channels = 2; | ||
2941 | spec->multiout.num_dacs = ARRAY_SIZE(ad1884_dac_nids); | ||
2942 | spec->multiout.dac_nids = ad1884_dac_nids; | ||
2943 | spec->multiout.dig_out_nid = AD1884_SPDIF_OUT; | ||
2944 | spec->num_adc_nids = ARRAY_SIZE(ad1884_adc_nids); | ||
2945 | spec->adc_nids = ad1884_adc_nids; | ||
2946 | spec->capsrc_nids = ad1884_capsrc_nids; | ||
2947 | spec->input_mux = &ad1884_capture_source; | ||
2948 | spec->num_mixers = 1; | ||
2949 | spec->mixers[0] = ad1884_base_mixers; | ||
2950 | spec->num_init_verbs = 1; | ||
2951 | spec->init_verbs[0] = ad1884_init_verbs; | ||
2952 | spec->spdif_route = 0; | ||
2953 | |||
2954 | codec->patch_ops = ad198x_patch_ops; | ||
2955 | |||
2956 | return 0; | ||
2957 | } | ||
2958 | |||
2959 | /* | ||
2960 | * Lenovo Thinkpad T61/X61 | ||
2961 | */ | ||
2962 | static struct hda_input_mux ad1984_thinkpad_capture_source = { | ||
2963 | .num_items = 3, | ||
2964 | .items = { | ||
2965 | { "Mic", 0x0 }, | ||
2966 | { "Internal Mic", 0x1 }, | ||
2967 | { "Mix", 0x3 }, | ||
2968 | }, | ||
2969 | }; | ||
2970 | |||
2971 | static struct snd_kcontrol_new ad1984_thinkpad_mixers[] = { | ||
2972 | HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT), | ||
2973 | /* HDA_CODEC_VOLUME_IDX("PCM Playback Volume", 1, 0x03, 0x0, HDA_OUTPUT), */ | ||
2974 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
2975 | HDA_CODEC_MUTE("Speaker Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
2976 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | ||
2977 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | ||
2978 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), | ||
2979 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | ||
2980 | HDA_CODEC_VOLUME("Docking Mic Playback Volume", 0x20, 0x04, HDA_INPUT), | ||
2981 | HDA_CODEC_MUTE("Docking Mic Playback Switch", 0x20, 0x04, HDA_INPUT), | ||
2982 | HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), | ||
2983 | HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), | ||
2984 | HDA_CODEC_VOLUME("Docking Mic Boost", 0x25, 0x0, HDA_OUTPUT), | ||
2985 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), | ||
2986 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), | ||
2987 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
2988 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
2989 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
2990 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
2991 | { | ||
2992 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2993 | /* The multiple "Capture Source" controls confuse alsamixer | ||
2994 | * So call somewhat different.. | ||
2995 | * FIXME: the controls appear in the "playback" view! | ||
2996 | */ | ||
2997 | /* .name = "Capture Source", */ | ||
2998 | .name = "Input Source", | ||
2999 | .count = 2, | ||
3000 | .info = ad198x_mux_enum_info, | ||
3001 | .get = ad198x_mux_enum_get, | ||
3002 | .put = ad198x_mux_enum_put, | ||
3003 | }, | ||
3004 | { } /* end */ | ||
3005 | }; | ||
3006 | |||
3007 | /* additional verbs */ | ||
3008 | static struct hda_verb ad1984_thinkpad_init_verbs[] = { | ||
3009 | /* Port-E (docking station mic) pin */ | ||
3010 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
3011 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3012 | /* docking mic boost */ | ||
3013 | {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3014 | /* Analog mixer - docking mic; mute as default */ | ||
3015 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
3016 | /* enable EAPD bit */ | ||
3017 | {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, | ||
3018 | { } /* end */ | ||
3019 | }; | ||
3020 | |||
3021 | /* Digial MIC ADC NID 0x05 + 0x06 */ | ||
3022 | static int ad1984_pcm_dmic_prepare(struct hda_pcm_stream *hinfo, | ||
3023 | struct hda_codec *codec, | ||
3024 | unsigned int stream_tag, | ||
3025 | unsigned int format, | ||
3026 | struct snd_pcm_substream *substream) | ||
3027 | { | ||
3028 | snd_hda_codec_setup_stream(codec, 0x05 + substream->number, | ||
3029 | stream_tag, 0, format); | ||
3030 | return 0; | ||
3031 | } | ||
3032 | |||
3033 | static int ad1984_pcm_dmic_cleanup(struct hda_pcm_stream *hinfo, | ||
3034 | struct hda_codec *codec, | ||
3035 | struct snd_pcm_substream *substream) | ||
3036 | { | ||
3037 | snd_hda_codec_setup_stream(codec, 0x05 + substream->number, | ||
3038 | 0, 0, 0); | ||
3039 | return 0; | ||
3040 | } | ||
3041 | |||
3042 | static struct hda_pcm_stream ad1984_pcm_dmic_capture = { | ||
3043 | .substreams = 2, | ||
3044 | .channels_min = 2, | ||
3045 | .channels_max = 2, | ||
3046 | .nid = 0x05, | ||
3047 | .ops = { | ||
3048 | .prepare = ad1984_pcm_dmic_prepare, | ||
3049 | .cleanup = ad1984_pcm_dmic_cleanup | ||
3050 | }, | ||
3051 | }; | ||
3052 | |||
3053 | static int ad1984_build_pcms(struct hda_codec *codec) | ||
3054 | { | ||
3055 | struct ad198x_spec *spec = codec->spec; | ||
3056 | struct hda_pcm *info; | ||
3057 | int err; | ||
3058 | |||
3059 | err = ad198x_build_pcms(codec); | ||
3060 | if (err < 0) | ||
3061 | return err; | ||
3062 | |||
3063 | info = spec->pcm_rec + codec->num_pcms; | ||
3064 | codec->num_pcms++; | ||
3065 | info->name = "AD1984 Digital Mic"; | ||
3066 | info->stream[SNDRV_PCM_STREAM_CAPTURE] = ad1984_pcm_dmic_capture; | ||
3067 | return 0; | ||
3068 | } | ||
3069 | |||
3070 | /* models */ | ||
3071 | enum { | ||
3072 | AD1984_BASIC, | ||
3073 | AD1984_THINKPAD, | ||
3074 | AD1984_MODELS | ||
3075 | }; | ||
3076 | |||
3077 | static const char *ad1984_models[AD1984_MODELS] = { | ||
3078 | [AD1984_BASIC] = "basic", | ||
3079 | [AD1984_THINKPAD] = "thinkpad", | ||
3080 | }; | ||
3081 | |||
3082 | static struct snd_pci_quirk ad1984_cfg_tbl[] = { | ||
3083 | /* Lenovo Thinkpad T61/X61 */ | ||
3084 | SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1984_THINKPAD), | ||
3085 | {} | ||
3086 | }; | ||
3087 | |||
3088 | static int patch_ad1984(struct hda_codec *codec) | ||
3089 | { | ||
3090 | struct ad198x_spec *spec; | ||
3091 | int board_config, err; | ||
3092 | |||
3093 | err = patch_ad1884(codec); | ||
3094 | if (err < 0) | ||
3095 | return err; | ||
3096 | spec = codec->spec; | ||
3097 | board_config = snd_hda_check_board_config(codec, AD1984_MODELS, | ||
3098 | ad1984_models, ad1984_cfg_tbl); | ||
3099 | switch (board_config) { | ||
3100 | case AD1984_BASIC: | ||
3101 | /* additional digital mics */ | ||
3102 | spec->mixers[spec->num_mixers++] = ad1984_dmic_mixers; | ||
3103 | codec->patch_ops.build_pcms = ad1984_build_pcms; | ||
3104 | break; | ||
3105 | case AD1984_THINKPAD: | ||
3106 | spec->multiout.dig_out_nid = 0; | ||
3107 | spec->input_mux = &ad1984_thinkpad_capture_source; | ||
3108 | spec->mixers[0] = ad1984_thinkpad_mixers; | ||
3109 | spec->init_verbs[spec->num_init_verbs++] = ad1984_thinkpad_init_verbs; | ||
3110 | break; | ||
3111 | } | ||
3112 | return 0; | ||
3113 | } | ||
3114 | |||
3115 | |||
3116 | /* | ||
3117 | * AD1882 | ||
3118 | * | ||
3119 | * port-A - front hp-out | ||
3120 | * port-B - front mic-in | ||
3121 | * port-C - rear line-in, shared surr-out (3stack) | ||
3122 | * port-D - rear line-out | ||
3123 | * port-E - rear mic-in, shared clfe-out (3stack) | ||
3124 | * port-F - rear surr-out (6stack) | ||
3125 | * port-G - rear clfe-out (6stack) | ||
3126 | */ | ||
3127 | |||
3128 | static hda_nid_t ad1882_dac_nids[3] = { | ||
3129 | 0x04, 0x03, 0x05 | ||
3130 | }; | ||
3131 | |||
3132 | static hda_nid_t ad1882_adc_nids[2] = { | ||
3133 | 0x08, 0x09, | ||
3134 | }; | ||
3135 | |||
3136 | static hda_nid_t ad1882_capsrc_nids[2] = { | ||
3137 | 0x0c, 0x0d, | ||
3138 | }; | ||
3139 | |||
3140 | #define AD1882_SPDIF_OUT 0x02 | ||
3141 | |||
3142 | /* list: 0x11, 0x39, 0x3a, 0x18, 0x3c, 0x3b, 0x12, 0x20 */ | ||
3143 | static struct hda_input_mux ad1882_capture_source = { | ||
3144 | .num_items = 5, | ||
3145 | .items = { | ||
3146 | { "Front Mic", 0x1 }, | ||
3147 | { "Mic", 0x4 }, | ||
3148 | { "Line", 0x2 }, | ||
3149 | { "CD", 0x3 }, | ||
3150 | { "Mix", 0x7 }, | ||
3151 | }, | ||
3152 | }; | ||
3153 | |||
3154 | static struct snd_kcontrol_new ad1882_base_mixers[] = { | ||
3155 | HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT), | ||
3156 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT), | ||
3157 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x05, 1, 0x0, HDA_OUTPUT), | ||
3158 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x05, 2, 0x0, HDA_OUTPUT), | ||
3159 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), | ||
3160 | HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), | ||
3161 | HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), | ||
3162 | HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), | ||
3163 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), | ||
3164 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), | ||
3165 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), | ||
3166 | HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), | ||
3167 | HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x04, HDA_INPUT), | ||
3168 | HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x04, HDA_INPUT), | ||
3169 | HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x06, HDA_INPUT), | ||
3170 | HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x06, HDA_INPUT), | ||
3171 | HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x07, HDA_INPUT), | ||
3172 | HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x07, HDA_INPUT), | ||
3173 | HDA_CODEC_VOLUME("Mic Boost", 0x3c, 0x0, HDA_OUTPUT), | ||
3174 | HDA_CODEC_VOLUME("Front Mic Boost", 0x39, 0x0, HDA_OUTPUT), | ||
3175 | HDA_CODEC_VOLUME("Line-In Boost", 0x3a, 0x0, HDA_OUTPUT), | ||
3176 | HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
3177 | HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), | ||
3178 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
3179 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), | ||
3180 | { | ||
3181 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3182 | /* The multiple "Capture Source" controls confuse alsamixer | ||
3183 | * So call somewhat different.. | ||
3184 | * FIXME: the controls appear in the "playback" view! | ||
3185 | */ | ||
3186 | /* .name = "Capture Source", */ | ||
3187 | .name = "Input Source", | ||
3188 | .count = 2, | ||
3189 | .info = ad198x_mux_enum_info, | ||
3190 | .get = ad198x_mux_enum_get, | ||
3191 | .put = ad198x_mux_enum_put, | ||
3192 | }, | ||
3193 | /* SPDIF controls */ | ||
3194 | HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), | ||
3195 | { | ||
3196 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3197 | .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", | ||
3198 | /* identical with ad1983 */ | ||
3199 | .info = ad1983_spdif_route_info, | ||
3200 | .get = ad1983_spdif_route_get, | ||
3201 | .put = ad1983_spdif_route_put, | ||
3202 | }, | ||
3203 | { } /* end */ | ||
3204 | }; | ||
3205 | |||
3206 | static struct snd_kcontrol_new ad1882_3stack_mixers[] = { | ||
3207 | HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
3208 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x17, 1, 0x0, HDA_OUTPUT), | ||
3209 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x17, 2, 0x0, HDA_OUTPUT), | ||
3210 | { | ||
3211 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
3212 | .name = "Channel Mode", | ||
3213 | .info = ad198x_ch_mode_info, | ||
3214 | .get = ad198x_ch_mode_get, | ||
3215 | .put = ad198x_ch_mode_put, | ||
3216 | }, | ||
3217 | { } /* end */ | ||
3218 | }; | ||
3219 | |||
3220 | static struct snd_kcontrol_new ad1882_6stack_mixers[] = { | ||
3221 | HDA_CODEC_MUTE("Surround Playback Switch", 0x16, 0x0, HDA_OUTPUT), | ||
3222 | HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x24, 1, 0x0, HDA_OUTPUT), | ||
3223 | HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x24, 2, 0x0, HDA_OUTPUT), | ||
3224 | { } /* end */ | ||
3225 | }; | ||
3226 | |||
3227 | static struct hda_verb ad1882_ch2_init[] = { | ||
3228 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
3229 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3230 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3231 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
3232 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3233 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3234 | { } /* end */ | ||
3235 | }; | ||
3236 | |||
3237 | static struct hda_verb ad1882_ch4_init[] = { | ||
3238 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3239 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3240 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3241 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
3242 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3243 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3244 | { } /* end */ | ||
3245 | }; | ||
3246 | |||
3247 | static struct hda_verb ad1882_ch6_init[] = { | ||
3248 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3249 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3250 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3251 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3252 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3253 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3254 | { } /* end */ | ||
3255 | }; | ||
3256 | |||
3257 | static struct hda_channel_mode ad1882_modes[3] = { | ||
3258 | { 2, ad1882_ch2_init }, | ||
3259 | { 4, ad1882_ch4_init }, | ||
3260 | { 6, ad1882_ch6_init }, | ||
3261 | }; | ||
3262 | |||
3263 | /* | ||
3264 | * initialization verbs | ||
3265 | */ | ||
3266 | static struct hda_verb ad1882_init_verbs[] = { | ||
3267 | /* DACs; mute as default */ | ||
3268 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3269 | {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3270 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
3271 | /* Port-A (HP) mixer */ | ||
3272 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3273 | {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3274 | /* Port-A pin */ | ||
3275 | {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
3276 | {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3277 | /* HP selector - select DAC2 */ | ||
3278 | {0x37, AC_VERB_SET_CONNECT_SEL, 0x1}, | ||
3279 | /* Port-D (Line-out) mixer */ | ||
3280 | {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3281 | {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3282 | /* Port-D pin */ | ||
3283 | {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
3284 | {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3285 | /* Mono-out mixer */ | ||
3286 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
3287 | {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
3288 | /* Mono-out pin */ | ||
3289 | {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
3290 | {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3291 | /* Port-B (front mic) pin */ | ||
3292 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
3293 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3294 | {0x39, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ | ||
3295 | /* Port-C (line-in) pin */ | ||
3296 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, | ||
3297 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3298 | {0x3a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ | ||
3299 | /* Port-C mixer - mute as input */ | ||
3300 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3301 | {0x2c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3302 | /* Port-E (mic-in) pin */ | ||
3303 | {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
3304 | {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3305 | {0x3c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* boost */ | ||
3306 | /* Port-E mixer - mute as input */ | ||
3307 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3308 | {0x26, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3309 | /* Port-F (surround) */ | ||
3310 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3311 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3312 | /* Port-G (CLFE) */ | ||
3313 | {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
3314 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
3315 | /* Analog mixer; mute as default */ | ||
3316 | /* list: 0x39, 0x3a, 0x11, 0x12, 0x3c, 0x3b, 0x18, 0x1a */ | ||
3317 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, | ||
3318 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, | ||
3319 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, | ||
3320 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, | ||
3321 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, | ||
3322 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, | ||
3323 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, | ||
3324 | {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, | ||
3325 | /* Analog Mix output amp */ | ||
3326 | {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x1f}, /* 0dB */ | ||
3327 | /* SPDIF output selector */ | ||
3328 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ | ||
3329 | {0x02, AC_VERB_SET_CONNECT_SEL, 0x0}, /* PCM */ | ||
3330 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ | ||
3331 | { } /* end */ | ||
3332 | }; | ||
3333 | |||
3334 | /* models */ | ||
3335 | enum { | ||
3336 | AD1882_3STACK, | ||
3337 | AD1882_6STACK, | ||
3338 | AD1882_MODELS | ||
3339 | }; | ||
3340 | |||
3341 | static const char *ad1882_models[AD1986A_MODELS] = { | ||
3342 | [AD1882_3STACK] = "3stack", | ||
3343 | [AD1882_6STACK] = "6stack", | ||
3344 | }; | ||
3345 | |||
3346 | |||
3347 | static int patch_ad1882(struct hda_codec *codec) | ||
3348 | { | ||
3349 | struct ad198x_spec *spec; | ||
3350 | int board_config; | ||
3351 | |||
3352 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
3353 | if (spec == NULL) | ||
3354 | return -ENOMEM; | ||
3355 | |||
3356 | mutex_init(&spec->amp_mutex); | ||
3357 | codec->spec = spec; | ||
3358 | |||
3359 | spec->multiout.max_channels = 6; | ||
3360 | spec->multiout.num_dacs = 3; | ||
3361 | spec->multiout.dac_nids = ad1882_dac_nids; | ||
3362 | spec->multiout.dig_out_nid = AD1882_SPDIF_OUT; | ||
3363 | spec->num_adc_nids = ARRAY_SIZE(ad1882_adc_nids); | ||
3364 | spec->adc_nids = ad1882_adc_nids; | ||
3365 | spec->capsrc_nids = ad1882_capsrc_nids; | ||
3366 | spec->input_mux = &ad1882_capture_source; | ||
3367 | spec->num_mixers = 1; | ||
3368 | spec->mixers[0] = ad1882_base_mixers; | ||
3369 | spec->num_init_verbs = 1; | ||
3370 | spec->init_verbs[0] = ad1882_init_verbs; | ||
3371 | spec->spdif_route = 0; | ||
3372 | |||
3373 | codec->patch_ops = ad198x_patch_ops; | ||
3374 | |||
3375 | /* override some parameters */ | ||
3376 | board_config = snd_hda_check_board_config(codec, AD1882_MODELS, | ||
3377 | ad1882_models, NULL); | ||
3378 | switch (board_config) { | ||
3379 | default: | ||
3380 | case AD1882_3STACK: | ||
3381 | spec->num_mixers = 2; | ||
3382 | spec->mixers[1] = ad1882_3stack_mixers; | ||
3383 | spec->channel_mode = ad1882_modes; | ||
3384 | spec->num_channel_mode = ARRAY_SIZE(ad1882_modes); | ||
3385 | spec->need_dac_fix = 1; | ||
3386 | spec->multiout.max_channels = 2; | ||
3387 | spec->multiout.num_dacs = 1; | ||
3388 | break; | ||
3389 | case AD1882_6STACK: | ||
3390 | spec->num_mixers = 2; | ||
3391 | spec->mixers[1] = ad1882_6stack_mixers; | ||
3392 | break; | ||
3393 | } | ||
3394 | return 0; | ||
3395 | } | ||
3396 | |||
3397 | |||
3398 | /* | ||
2778 | * patch entries | 3399 | * patch entries |
2779 | */ | 3400 | */ |
2780 | struct hda_codec_preset snd_hda_preset_analog[] = { | 3401 | struct hda_codec_preset snd_hda_preset_analog[] = { |
3402 | { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, | ||
3403 | { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, | ||
2781 | { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, | 3404 | { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, |
2782 | { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, | 3405 | { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, |
3406 | { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, | ||
2783 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, | 3407 | { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, |
2784 | { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, | 3408 | { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, |
2785 | { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, | 3409 | { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c index f8eb4c90f801..72d3ab9751ac 100644 --- a/sound/pci/hda/patch_atihdmi.c +++ b/sound/pci/hda/patch_atihdmi.c | |||
@@ -172,6 +172,7 @@ static int patch_atihdmi(struct hda_codec *codec) | |||
172 | */ | 172 | */ |
173 | struct hda_codec_preset snd_hda_preset_atihdmi[] = { | 173 | struct hda_codec_preset snd_hda_preset_atihdmi[] = { |
174 | { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, | 174 | { .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, |
175 | { .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi }, | ||
175 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, | 176 | { .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi }, |
176 | { .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi }, | 177 | { .id = 0x1002aa01, .name = "ATI R600 HDMI", .patch = patch_atihdmi }, |
177 | {} /* terminator */ | 178 | {} /* terminator */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index bef214bcdddf..4d8e8af5c819 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -801,7 +801,9 @@ static struct snd_pci_quirk cxt5045_cfg_tbl[] = { | |||
801 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), | 801 | SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV Series", CXT5045_LAPTOP), |
802 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), | 802 | SND_PCI_QUIRK(0x103c, 0x30b5, "HP DV2120", CXT5045_LAPTOP), |
803 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), | 803 | SND_PCI_QUIRK(0x103c, 0x30cd, "HP DV Series", CXT5045_LAPTOP), |
804 | SND_PCI_QUIRK(0x103c, 0x30d9, "HP Spartan", CXT5045_LAPTOP), | ||
804 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), | 805 | SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_FUJITSU), |
806 | SND_PCI_QUIRK(0x1734, 0x10cb, "Fujitsu Si3515", CXT5045_LAPTOP), | ||
805 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), | 807 | SND_PCI_QUIRK(0x8086, 0x2111, "Conexant Reference board", CXT5045_LAPTOP), |
806 | {} | 808 | {} |
807 | }; | 809 | }; |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 4776de93928b..9a47eec5a27b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -94,10 +94,18 @@ enum { | |||
94 | ALC262_HP_BPC_D7000_WF, | 94 | ALC262_HP_BPC_D7000_WF, |
95 | ALC262_BENQ_ED8, | 95 | ALC262_BENQ_ED8, |
96 | ALC262_SONY_ASSAMD, | 96 | ALC262_SONY_ASSAMD, |
97 | ALC262_BENQ_T31, | ||
97 | ALC262_AUTO, | 98 | ALC262_AUTO, |
98 | ALC262_MODEL_LAST /* last tag */ | 99 | ALC262_MODEL_LAST /* last tag */ |
99 | }; | 100 | }; |
100 | 101 | ||
102 | /* ALC268 models */ | ||
103 | enum { | ||
104 | ALC268_3ST, | ||
105 | ALC268_AUTO, | ||
106 | ALC268_MODEL_LAST /* last tag */ | ||
107 | }; | ||
108 | |||
101 | /* ALC861 models */ | 109 | /* ALC861 models */ |
102 | enum { | 110 | enum { |
103 | ALC861_3ST, | 111 | ALC861_3ST, |
@@ -115,6 +123,7 @@ enum { | |||
115 | /* ALC861-VD models */ | 123 | /* ALC861-VD models */ |
116 | enum { | 124 | enum { |
117 | ALC660VD_3ST, | 125 | ALC660VD_3ST, |
126 | ALC660VD_3ST_DIG, | ||
118 | ALC861VD_3ST, | 127 | ALC861VD_3ST, |
119 | ALC861VD_3ST_DIG, | 128 | ALC861VD_3ST_DIG, |
120 | ALC861VD_6ST_DIG, | 129 | ALC861VD_6ST_DIG, |
@@ -144,6 +153,7 @@ enum { | |||
144 | ALC882_TARGA, | 153 | ALC882_TARGA, |
145 | ALC882_ASUS_A7J, | 154 | ALC882_ASUS_A7J, |
146 | ALC885_MACPRO, | 155 | ALC885_MACPRO, |
156 | ALC885_IMAC24, | ||
147 | ALC882_AUTO, | 157 | ALC882_AUTO, |
148 | ALC882_MODEL_LAST, | 158 | ALC882_MODEL_LAST, |
149 | }; | 159 | }; |
@@ -163,6 +173,8 @@ enum { | |||
163 | ALC883_LENOVO_101E_2ch, | 173 | ALC883_LENOVO_101E_2ch, |
164 | ALC883_LENOVO_NB0763, | 174 | ALC883_LENOVO_NB0763, |
165 | ALC888_LENOVO_MS7195_DIG, | 175 | ALC888_LENOVO_MS7195_DIG, |
176 | ALC888_6ST_HP, | ||
177 | ALC888_3ST_HP, | ||
166 | ALC883_AUTO, | 178 | ALC883_AUTO, |
167 | ALC883_MODEL_LAST, | 179 | ALC883_MODEL_LAST, |
168 | }; | 180 | }; |
@@ -713,6 +725,38 @@ static void alc_subsystem_id(struct hda_codec *codec, | |||
713 | } | 725 | } |
714 | 726 | ||
715 | /* | 727 | /* |
728 | * Fix-up pin default configurations | ||
729 | */ | ||
730 | |||
731 | struct alc_pincfg { | ||
732 | hda_nid_t nid; | ||
733 | u32 val; | ||
734 | }; | ||
735 | |||
736 | static void alc_fix_pincfg(struct hda_codec *codec, | ||
737 | const struct snd_pci_quirk *quirk, | ||
738 | const struct alc_pincfg **pinfix) | ||
739 | { | ||
740 | const struct alc_pincfg *cfg; | ||
741 | |||
742 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | ||
743 | if (!quirk) | ||
744 | return; | ||
745 | |||
746 | cfg = pinfix[quirk->value]; | ||
747 | for (; cfg->nid; cfg++) { | ||
748 | int i; | ||
749 | u32 val = cfg->val; | ||
750 | for (i = 0; i < 4; i++) { | ||
751 | snd_hda_codec_write(codec, cfg->nid, 0, | ||
752 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0 + i, | ||
753 | val & 0xff); | ||
754 | val >>= 8; | ||
755 | } | ||
756 | } | ||
757 | } | ||
758 | |||
759 | /* | ||
716 | * ALC880 3-stack model | 760 | * ALC880 3-stack model |
717 | * | 761 | * |
718 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) | 762 | * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e) |
@@ -1878,31 +1922,53 @@ static void alc880_lg_unsol_event(struct hda_codec *codec, unsigned int res) | |||
1878 | * Pin assignment: | 1922 | * Pin assignment: |
1879 | * Speaker-out: 0x14 | 1923 | * Speaker-out: 0x14 |
1880 | * Mic-In: 0x18 | 1924 | * Mic-In: 0x18 |
1881 | * Built-in Mic-In: 0x19 (?) | 1925 | * Built-in Mic-In: 0x19 |
1882 | * HP-Out: 0x1b | 1926 | * Line-In: 0x1b |
1927 | * HP-Out: 0x1a | ||
1883 | * SPDIF-Out: 0x1e | 1928 | * SPDIF-Out: 0x1e |
1884 | */ | 1929 | */ |
1885 | 1930 | ||
1886 | /* seems analog CD is not working */ | ||
1887 | static struct hda_input_mux alc880_lg_lw_capture_source = { | 1931 | static struct hda_input_mux alc880_lg_lw_capture_source = { |
1888 | .num_items = 2, | 1932 | .num_items = 3, |
1889 | .items = { | 1933 | .items = { |
1890 | { "Mic", 0x0 }, | 1934 | { "Mic", 0x0 }, |
1891 | { "Internal Mic", 0x1 }, | 1935 | { "Internal Mic", 0x1 }, |
1936 | { "Line In", 0x2 }, | ||
1892 | }, | 1937 | }, |
1893 | }; | 1938 | }; |
1894 | 1939 | ||
1940 | #define alc880_lg_lw_modes alc880_threestack_modes | ||
1941 | |||
1895 | static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { | 1942 | static struct snd_kcontrol_new alc880_lg_lw_mixer[] = { |
1896 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 1943 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
1897 | HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT), | 1944 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), |
1945 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
1946 | HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT), | ||
1947 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), | ||
1948 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), | ||
1949 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), | ||
1950 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), | ||
1951 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
1952 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
1898 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 1953 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
1899 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 1954 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
1900 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 1955 | HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |
1901 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | 1956 | HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), |
1957 | { | ||
1958 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
1959 | .name = "Channel Mode", | ||
1960 | .info = alc_ch_mode_info, | ||
1961 | .get = alc_ch_mode_get, | ||
1962 | .put = alc_ch_mode_put, | ||
1963 | }, | ||
1902 | { } /* end */ | 1964 | { } /* end */ |
1903 | }; | 1965 | }; |
1904 | 1966 | ||
1905 | static struct hda_verb alc880_lg_lw_init_verbs[] = { | 1967 | static struct hda_verb alc880_lg_lw_init_verbs[] = { |
1968 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */ | ||
1969 | {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */ | ||
1970 | {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */ | ||
1971 | |||
1906 | /* set capture source to mic-in */ | 1972 | /* set capture source to mic-in */ |
1907 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1973 | {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
1908 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 1974 | {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
@@ -1912,7 +1978,6 @@ static struct hda_verb alc880_lg_lw_init_verbs[] = { | |||
1912 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 1978 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1913 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1979 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1914 | /* HP-out */ | 1980 | /* HP-out */ |
1915 | {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
1916 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | 1981 | {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, |
1917 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | 1982 | {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, |
1918 | /* mic-in to input */ | 1983 | /* mic-in to input */ |
@@ -2856,11 +2921,11 @@ static struct alc_config_preset alc880_presets[] = { | |||
2856 | .mixers = { alc880_lg_lw_mixer }, | 2921 | .mixers = { alc880_lg_lw_mixer }, |
2857 | .init_verbs = { alc880_volume_init_verbs, | 2922 | .init_verbs = { alc880_volume_init_verbs, |
2858 | alc880_lg_lw_init_verbs }, | 2923 | alc880_lg_lw_init_verbs }, |
2859 | .num_dacs = 1, | 2924 | .num_dacs = ARRAY_SIZE(alc880_dac_nids), |
2860 | .dac_nids = alc880_dac_nids, | 2925 | .dac_nids = alc880_dac_nids, |
2861 | .dig_out_nid = ALC880_DIGOUT_NID, | 2926 | .dig_out_nid = ALC880_DIGOUT_NID, |
2862 | .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes), | 2927 | .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes), |
2863 | .channel_mode = alc880_2_jack_modes, | 2928 | .channel_mode = alc880_lg_lw_modes, |
2864 | .input_mux = &alc880_lg_lw_capture_source, | 2929 | .input_mux = &alc880_lg_lw_capture_source, |
2865 | .unsol_event = alc880_lg_lw_unsol_event, | 2930 | .unsol_event = alc880_lg_lw_unsol_event, |
2866 | .init_hook = alc880_lg_lw_automute, | 2931 | .init_hook = alc880_lg_lw_automute, |
@@ -5054,6 +5119,60 @@ static struct hda_verb alc882_macpro_init_verbs[] = { | |||
5054 | { } | 5119 | { } |
5055 | }; | 5120 | }; |
5056 | 5121 | ||
5122 | /* iMac 24 mixer. */ | ||
5123 | static struct snd_kcontrol_new alc885_imac24_mixer[] = { | ||
5124 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT), | ||
5125 | HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT), | ||
5126 | { } /* end */ | ||
5127 | }; | ||
5128 | |||
5129 | /* iMac 24 init verbs. */ | ||
5130 | static struct hda_verb alc885_imac24_init_verbs[] = { | ||
5131 | /* Internal speakers: output 0 (0x0c) */ | ||
5132 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5133 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5134 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5135 | /* Internal speakers: output 0 (0x0c) */ | ||
5136 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | ||
5137 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5138 | {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5139 | /* Headphone: output 0 (0x0c) */ | ||
5140 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, | ||
5141 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, | ||
5142 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
5143 | {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | ||
5144 | /* Front Mic: input vref at 80% */ | ||
5145 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, | ||
5146 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
5147 | { } | ||
5148 | }; | ||
5149 | |||
5150 | /* Toggle speaker-output according to the hp-jack state */ | ||
5151 | static void alc885_imac24_automute(struct hda_codec *codec) | ||
5152 | { | ||
5153 | unsigned int present; | ||
5154 | |||
5155 | present = snd_hda_codec_read(codec, 0x14, 0, | ||
5156 | AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; | ||
5157 | snd_hda_codec_amp_update(codec, 0x18, 0, HDA_OUTPUT, 0, | ||
5158 | 0x80, present ? 0x80 : 0); | ||
5159 | snd_hda_codec_amp_update(codec, 0x18, 1, HDA_OUTPUT, 0, | ||
5160 | 0x80, present ? 0x80 : 0); | ||
5161 | snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, | ||
5162 | 0x80, present ? 0x80 : 0); | ||
5163 | snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, | ||
5164 | 0x80, present ? 0x80 : 0); | ||
5165 | } | ||
5166 | |||
5167 | /* Processes unsolicited events. */ | ||
5168 | static void alc885_imac24_unsol_event(struct hda_codec *codec, | ||
5169 | unsigned int res) | ||
5170 | { | ||
5171 | /* Headphone insertion or removal. */ | ||
5172 | if ((res >> 26) == ALC880_HP_EVENT) | ||
5173 | alc885_imac24_automute(codec); | ||
5174 | } | ||
5175 | |||
5057 | static struct hda_verb alc882_targa_verbs[] = { | 5176 | static struct hda_verb alc882_targa_verbs[] = { |
5058 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | 5177 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, |
5059 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | 5178 | {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, |
@@ -5274,6 +5393,7 @@ static const char *alc882_models[ALC882_MODEL_LAST] = { | |||
5274 | [ALC882_ARIMA] = "arima", | 5393 | [ALC882_ARIMA] = "arima", |
5275 | [ALC882_W2JC] = "w2jc", | 5394 | [ALC882_W2JC] = "w2jc", |
5276 | [ALC885_MACPRO] = "macpro", | 5395 | [ALC885_MACPRO] = "macpro", |
5396 | [ALC885_IMAC24] = "imac24", | ||
5277 | [ALC882_AUTO] = "auto", | 5397 | [ALC882_AUTO] = "auto", |
5278 | }; | 5398 | }; |
5279 | 5399 | ||
@@ -5284,6 +5404,7 @@ static struct snd_pci_quirk alc882_cfg_tbl[] = { | |||
5284 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ | 5404 | SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */ |
5285 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), | 5405 | SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), |
5286 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), | 5406 | SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J), |
5407 | SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG), | ||
5287 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), | 5408 | SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG), |
5288 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), | 5409 | SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC), |
5289 | {} | 5410 | {} |
@@ -5345,6 +5466,19 @@ static struct alc_config_preset alc882_presets[] = { | |||
5345 | .channel_mode = alc882_ch_modes, | 5466 | .channel_mode = alc882_ch_modes, |
5346 | .input_mux = &alc882_capture_source, | 5467 | .input_mux = &alc882_capture_source, |
5347 | }, | 5468 | }, |
5469 | [ALC885_IMAC24] = { | ||
5470 | .mixers = { alc885_imac24_mixer }, | ||
5471 | .init_verbs = { alc885_imac24_init_verbs }, | ||
5472 | .num_dacs = ARRAY_SIZE(alc882_dac_nids), | ||
5473 | .dac_nids = alc882_dac_nids, | ||
5474 | .dig_out_nid = ALC882_DIGOUT_NID, | ||
5475 | .dig_in_nid = ALC882_DIGIN_NID, | ||
5476 | .num_channel_mode = ARRAY_SIZE(alc882_ch_modes), | ||
5477 | .channel_mode = alc882_ch_modes, | ||
5478 | .input_mux = &alc882_capture_source, | ||
5479 | .unsol_event = alc885_imac24_unsol_event, | ||
5480 | .init_hook = alc885_imac24_automute, | ||
5481 | }, | ||
5348 | [ALC882_TARGA] = { | 5482 | [ALC882_TARGA] = { |
5349 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, | 5483 | .mixers = { alc882_targa_mixer, alc882_chmode_mixer, |
5350 | alc882_capture_mixer }, | 5484 | alc882_capture_mixer }, |
@@ -5379,6 +5513,29 @@ static struct alc_config_preset alc882_presets[] = { | |||
5379 | 5513 | ||
5380 | 5514 | ||
5381 | /* | 5515 | /* |
5516 | * Pin config fixes | ||
5517 | */ | ||
5518 | enum { | ||
5519 | PINFIX_ABIT_AW9D_MAX | ||
5520 | }; | ||
5521 | |||
5522 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | ||
5523 | { 0x15, 0x01080104 }, /* side */ | ||
5524 | { 0x16, 0x01011012 }, /* rear */ | ||
5525 | { 0x17, 0x01016011 }, /* clfe */ | ||
5526 | { } | ||
5527 | }; | ||
5528 | |||
5529 | static const struct alc_pincfg *alc882_pin_fixes[] = { | ||
5530 | [PINFIX_ABIT_AW9D_MAX] = alc882_abit_aw9d_pinfix, | ||
5531 | }; | ||
5532 | |||
5533 | static struct snd_pci_quirk alc882_pinfix_tbl[] = { | ||
5534 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | ||
5535 | {} | ||
5536 | }; | ||
5537 | |||
5538 | /* | ||
5382 | * BIOS auto configuration | 5539 | * BIOS auto configuration |
5383 | */ | 5540 | */ |
5384 | static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, | 5541 | static void alc882_auto_set_output_and_unmute(struct hda_codec *codec, |
@@ -5494,6 +5651,9 @@ static int patch_alc882(struct hda_codec *codec) | |||
5494 | case 0x106b0c00: /* Mac Pro */ | 5651 | case 0x106b0c00: /* Mac Pro */ |
5495 | board_config = ALC885_MACPRO; | 5652 | board_config = ALC885_MACPRO; |
5496 | break; | 5653 | break; |
5654 | case 0x106b1000: /* iMac 24 */ | ||
5655 | board_config = ALC885_IMAC24; | ||
5656 | break; | ||
5497 | default: | 5657 | default: |
5498 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " | 5658 | printk(KERN_INFO "hda_codec: Unknown model for ALC882, " |
5499 | "trying auto-probe from BIOS...\n"); | 5659 | "trying auto-probe from BIOS...\n"); |
@@ -5501,6 +5661,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
5501 | } | 5661 | } |
5502 | } | 5662 | } |
5503 | 5663 | ||
5664 | alc_fix_pincfg(codec, alc882_pinfix_tbl, alc882_pin_fixes); | ||
5665 | |||
5504 | if (board_config == ALC882_AUTO) { | 5666 | if (board_config == ALC882_AUTO) { |
5505 | /* automatic parse from the BIOS config */ | 5667 | /* automatic parse from the BIOS config */ |
5506 | err = alc882_parse_auto_config(codec); | 5668 | err = alc882_parse_auto_config(codec); |
@@ -5518,7 +5680,7 @@ static int patch_alc882(struct hda_codec *codec) | |||
5518 | if (board_config != ALC882_AUTO) | 5680 | if (board_config != ALC882_AUTO) |
5519 | setup_preset(spec, &alc882_presets[board_config]); | 5681 | setup_preset(spec, &alc882_presets[board_config]); |
5520 | 5682 | ||
5521 | if (board_config == ALC885_MACPRO) { | 5683 | if (board_config == ALC885_MACPRO || board_config == ALC885_IMAC24) { |
5522 | alc882_gpio_mute(codec, 0, 0); | 5684 | alc882_gpio_mute(codec, 0, 0); |
5523 | alc882_gpio_mute(codec, 1, 0); | 5685 | alc882_gpio_mute(codec, 1, 0); |
5524 | } | 5686 | } |
@@ -5995,6 +6157,84 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { | |||
5995 | { } /* end */ | 6157 | { } /* end */ |
5996 | }; | 6158 | }; |
5997 | 6159 | ||
6160 | static struct snd_kcontrol_new alc888_6st_hp_mixer[] = { | ||
6161 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
6162 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
6163 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
6164 | HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), | ||
6165 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
6166 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), | ||
6167 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), | ||
6168 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), | ||
6169 | HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), | ||
6170 | HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), | ||
6171 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
6172 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
6173 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
6174 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
6175 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
6176 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
6177 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
6178 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
6179 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
6180 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
6181 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
6182 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6183 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6184 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6185 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6186 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
6187 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
6188 | { | ||
6189 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6190 | /* .name = "Capture Source", */ | ||
6191 | .name = "Input Source", | ||
6192 | .count = 2, | ||
6193 | .info = alc883_mux_enum_info, | ||
6194 | .get = alc883_mux_enum_get, | ||
6195 | .put = alc883_mux_enum_put, | ||
6196 | }, | ||
6197 | { } /* end */ | ||
6198 | }; | ||
6199 | |||
6200 | static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { | ||
6201 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
6202 | HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), | ||
6203 | HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT), | ||
6204 | HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT), | ||
6205 | HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT), | ||
6206 | HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT), | ||
6207 | HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT), | ||
6208 | HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT), | ||
6209 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), | ||
6210 | HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), | ||
6211 | HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), | ||
6212 | HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), | ||
6213 | HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), | ||
6214 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
6215 | HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), | ||
6216 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
6217 | HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), | ||
6218 | HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), | ||
6219 | HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), | ||
6220 | HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), | ||
6221 | HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), | ||
6222 | HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), | ||
6223 | HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), | ||
6224 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), | ||
6225 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), | ||
6226 | { | ||
6227 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
6228 | /* .name = "Capture Source", */ | ||
6229 | .name = "Input Source", | ||
6230 | .count = 2, | ||
6231 | .info = alc883_mux_enum_info, | ||
6232 | .get = alc883_mux_enum_get, | ||
6233 | .put = alc883_mux_enum_put, | ||
6234 | }, | ||
6235 | { } /* end */ | ||
6236 | }; | ||
6237 | |||
5998 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { | 6238 | static struct snd_kcontrol_new alc883_chmode_mixer[] = { |
5999 | { | 6239 | { |
6000 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 6240 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
@@ -6126,6 +6366,42 @@ static struct hda_verb alc888_lenovo_ms7195_verbs[] = { | |||
6126 | { } /* end */ | 6366 | { } /* end */ |
6127 | }; | 6367 | }; |
6128 | 6368 | ||
6369 | static struct hda_verb alc888_6st_hp_verbs[] = { | ||
6370 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | ||
6371 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Rear : output 2 (0x0e) */ | ||
6372 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* CLFE : output 1 (0x0d) */ | ||
6373 | {0x17, AC_VERB_SET_CONNECT_SEL, 0x03}, /* Side : output 3 (0x0f) */ | ||
6374 | { } | ||
6375 | }; | ||
6376 | |||
6377 | static struct hda_verb alc888_3st_hp_verbs[] = { | ||
6378 | {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */ | ||
6379 | {0x18, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */ | ||
6380 | {0x16, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */ | ||
6381 | { } | ||
6382 | }; | ||
6383 | |||
6384 | static struct hda_verb alc888_3st_hp_2ch_init[] = { | ||
6385 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, | ||
6386 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
6387 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, | ||
6388 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE }, | ||
6389 | { } | ||
6390 | }; | ||
6391 | |||
6392 | static struct hda_verb alc888_3st_hp_6ch_init[] = { | ||
6393 | { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
6394 | { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
6395 | { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
6396 | { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, | ||
6397 | { } | ||
6398 | }; | ||
6399 | |||
6400 | static struct hda_channel_mode alc888_3st_hp_modes[2] = { | ||
6401 | { 2, alc888_3st_hp_2ch_init }, | ||
6402 | { 6, alc888_3st_hp_6ch_init }, | ||
6403 | }; | ||
6404 | |||
6129 | /* toggle front-jack and RCA according to the hp-jack state */ | 6405 | /* toggle front-jack and RCA according to the hp-jack state */ |
6130 | static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) | 6406 | static void alc888_lenovo_ms7195_front_automute(struct hda_codec *codec) |
6131 | { | 6407 | { |
@@ -6368,11 +6644,14 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { | |||
6368 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", | 6644 | [ALC883_LENOVO_101E_2ch] = "lenovo-101e", |
6369 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", | 6645 | [ALC883_LENOVO_NB0763] = "lenovo-nb0763", |
6370 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", | 6646 | [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", |
6647 | [ALC888_6ST_HP] = "6stack-hp", | ||
6648 | [ALC888_3ST_HP] = "3stack-hp", | ||
6371 | [ALC883_AUTO] = "auto", | 6649 | [ALC883_AUTO] = "auto", |
6372 | }; | 6650 | }; |
6373 | 6651 | ||
6374 | static struct snd_pci_quirk alc883_cfg_tbl[] = { | 6652 | static struct snd_pci_quirk alc883_cfg_tbl[] = { |
6375 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), | 6653 | SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG), |
6654 | SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), | ||
6376 | SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), | 6655 | SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch), |
6377 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), | 6656 | SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), |
6378 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), | 6657 | SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), |
@@ -6381,6 +6660,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6381 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), | 6660 | SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG), |
6382 | SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG), | 6661 | SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG), |
6383 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), | 6662 | SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG), |
6663 | SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), | ||
6664 | SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG), | ||
6384 | SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), | 6665 | SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG), |
6385 | SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), | 6666 | SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG), |
6386 | SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG), | 6667 | SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG), |
@@ -6400,6 +6681,9 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { | |||
6400 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), | 6681 | SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch), |
6401 | SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), | 6682 | SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763), |
6402 | SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), | 6683 | SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763), |
6684 | SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP), | ||
6685 | SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), | ||
6686 | SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), | ||
6403 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), | 6687 | SND_PCI_QUIRK(0x17c0, 0x4071, "MEDION MD2", ALC883_MEDION_MD2), |
6404 | {} | 6688 | {} |
6405 | }; | 6689 | }; |
@@ -6584,6 +6868,31 @@ static struct alc_config_preset alc883_presets[] = { | |||
6584 | .unsol_event = alc883_lenovo_ms7195_unsol_event, | 6868 | .unsol_event = alc883_lenovo_ms7195_unsol_event, |
6585 | .init_hook = alc888_lenovo_ms7195_front_automute, | 6869 | .init_hook = alc888_lenovo_ms7195_front_automute, |
6586 | }, | 6870 | }, |
6871 | [ALC888_6ST_HP] = { | ||
6872 | .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, | ||
6873 | .init_verbs = { alc883_init_verbs, alc888_6st_hp_verbs }, | ||
6874 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
6875 | .dac_nids = alc883_dac_nids, | ||
6876 | .dig_out_nid = ALC883_DIGOUT_NID, | ||
6877 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
6878 | .adc_nids = alc883_adc_nids, | ||
6879 | .dig_in_nid = ALC883_DIGIN_NID, | ||
6880 | .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), | ||
6881 | .channel_mode = alc883_sixstack_modes, | ||
6882 | .input_mux = &alc883_capture_source, | ||
6883 | }, | ||
6884 | [ALC888_3ST_HP] = { | ||
6885 | .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer }, | ||
6886 | .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs }, | ||
6887 | .num_dacs = ARRAY_SIZE(alc883_dac_nids), | ||
6888 | .dac_nids = alc883_dac_nids, | ||
6889 | .num_adc_nids = ARRAY_SIZE(alc883_adc_nids), | ||
6890 | .adc_nids = alc883_adc_nids, | ||
6891 | .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes), | ||
6892 | .channel_mode = alc888_3st_hp_modes, | ||
6893 | .need_dac_fix = 1, | ||
6894 | .input_mux = &alc883_capture_source, | ||
6895 | }, | ||
6587 | }; | 6896 | }; |
6588 | 6897 | ||
6589 | 6898 | ||
@@ -6857,7 +7166,16 @@ static struct snd_kcontrol_new alc262_sony_mixer[] = { | |||
6857 | { } /* end */ | 7166 | { } /* end */ |
6858 | }; | 7167 | }; |
6859 | 7168 | ||
6860 | 7169 | static struct snd_kcontrol_new alc262_benq_t31_mixer[] = { | |
7170 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | ||
7171 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
7172 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
7173 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | ||
7174 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | ||
7175 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | ||
7176 | HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT), | ||
7177 | { } /* end */ | ||
7178 | }; | ||
6861 | 7179 | ||
6862 | #define alc262_capture_mixer alc882_capture_mixer | 7180 | #define alc262_capture_mixer alc882_capture_mixer |
6863 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer | 7181 | #define alc262_capture_alt_mixer alc882_capture_alt_mixer |
@@ -7189,6 +7507,15 @@ static struct hda_verb alc262_EAPD_verbs[] = { | |||
7189 | {} | 7507 | {} |
7190 | }; | 7508 | }; |
7191 | 7509 | ||
7510 | static struct hda_verb alc262_benq_t31_EAPD_verbs[] = { | ||
7511 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
7512 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
7513 | |||
7514 | {0x20, AC_VERB_SET_COEF_INDEX, 0x07}, | ||
7515 | {0x20, AC_VERB_SET_PROC_COEF, 0x3050}, | ||
7516 | {} | ||
7517 | }; | ||
7518 | |||
7192 | /* add playback controls from the parsed DAC table */ | 7519 | /* add playback controls from the parsed DAC table */ |
7193 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | 7520 | static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, |
7194 | const struct auto_pin_cfg *cfg) | 7521 | const struct auto_pin_cfg *cfg) |
@@ -7584,7 +7911,8 @@ static const char *alc262_models[ALC262_MODEL_LAST] = { | |||
7584 | [ALC262_HP_BPC] = "hp-bpc", | 7911 | [ALC262_HP_BPC] = "hp-bpc", |
7585 | [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", | 7912 | [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000", |
7586 | [ALC262_BENQ_ED8] = "benq", | 7913 | [ALC262_BENQ_ED8] = "benq", |
7587 | [ALC262_BENQ_ED8] = "sony-assamd", | 7914 | [ALC262_BENQ_T31] = "benq-t31", |
7915 | [ALC262_SONY_ASSAMD] = "sony-assamd", | ||
7588 | [ALC262_AUTO] = "auto", | 7916 | [ALC262_AUTO] = "auto", |
7589 | }; | 7917 | }; |
7590 | 7918 | ||
@@ -7592,8 +7920,12 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
7592 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), | 7920 | SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO), |
7593 | SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), | 7921 | SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC), |
7594 | SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC), | 7922 | SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC), |
7923 | SND_PCI_QUIRK(0x103c, 0x12ff, "HP xw4550", ALC262_HP_BPC), | ||
7924 | SND_PCI_QUIRK(0x103c, 0x1308, "HP xw4600", ALC262_HP_BPC), | ||
7595 | SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC), | 7925 | SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC), |
7926 | SND_PCI_QUIRK(0x103c, 0x1307, "HP xw6600", ALC262_HP_BPC), | ||
7596 | SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), | 7927 | SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC), |
7928 | SND_PCI_QUIRK(0x103c, 0x1306, "HP xw8600", ALC262_HP_BPC), | ||
7597 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), | 7929 | SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL), |
7598 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), | 7930 | SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL), |
7599 | SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL), | 7931 | SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL), |
@@ -7606,6 +7938,7 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = { | |||
7606 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), | 7938 | SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU), |
7607 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), | 7939 | SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1), |
7608 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), | 7940 | SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8), |
7941 | SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31), | ||
7609 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), | 7942 | SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD), |
7610 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 7943 | SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
7611 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), | 7944 | SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD), |
@@ -7710,6 +8043,17 @@ static struct alc_config_preset alc262_presets[] = { | |||
7710 | .channel_mode = alc262_modes, | 8043 | .channel_mode = alc262_modes, |
7711 | .input_mux = &alc262_capture_source, | 8044 | .input_mux = &alc262_capture_source, |
7712 | .unsol_event = alc262_hippo_unsol_event, | 8045 | .unsol_event = alc262_hippo_unsol_event, |
8046 | }, | ||
8047 | [ALC262_BENQ_T31] = { | ||
8048 | .mixers = { alc262_benq_t31_mixer }, | ||
8049 | .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs, alc262_hippo_unsol_verbs }, | ||
8050 | .num_dacs = ARRAY_SIZE(alc262_dac_nids), | ||
8051 | .dac_nids = alc262_dac_nids, | ||
8052 | .hp_nid = 0x03, | ||
8053 | .num_channel_mode = ARRAY_SIZE(alc262_modes), | ||
8054 | .channel_mode = alc262_modes, | ||
8055 | .input_mux = &alc262_capture_source, | ||
8056 | .unsol_event = alc262_hippo_unsol_event, | ||
7713 | }, | 8057 | }, |
7714 | }; | 8058 | }; |
7715 | 8059 | ||
@@ -7800,6 +8144,515 @@ static int patch_alc262(struct hda_codec *codec) | |||
7800 | } | 8144 | } |
7801 | 8145 | ||
7802 | /* | 8146 | /* |
8147 | * ALC268 channel source setting (2 channel) | ||
8148 | */ | ||
8149 | #define ALC268_DIGOUT_NID ALC880_DIGOUT_NID | ||
8150 | #define alc268_modes alc260_modes | ||
8151 | |||
8152 | static hda_nid_t alc268_dac_nids[2] = { | ||
8153 | /* front, hp */ | ||
8154 | 0x02, 0x03 | ||
8155 | }; | ||
8156 | |||
8157 | static hda_nid_t alc268_adc_nids[2] = { | ||
8158 | /* ADC0-1 */ | ||
8159 | 0x08, 0x07 | ||
8160 | }; | ||
8161 | |||
8162 | static hda_nid_t alc268_adc_nids_alt[1] = { | ||
8163 | /* ADC0 */ | ||
8164 | 0x08 | ||
8165 | }; | ||
8166 | |||
8167 | static struct snd_kcontrol_new alc268_base_mixer[] = { | ||
8168 | /* output mixer control */ | ||
8169 | HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT), | ||
8170 | HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT), | ||
8171 | HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), | ||
8172 | HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), | ||
8173 | { } | ||
8174 | }; | ||
8175 | |||
8176 | /* | ||
8177 | * generic initialization of ADC, input mixers and output mixers | ||
8178 | */ | ||
8179 | static struct hda_verb alc268_base_init_verbs[] = { | ||
8180 | /* Unmute DAC0-1 and set vol = 0 */ | ||
8181 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
8182 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8183 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8184 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
8185 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8186 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8187 | |||
8188 | /* | ||
8189 | * Set up output mixers (0x0c - 0x0e) | ||
8190 | */ | ||
8191 | /* set vol=0 to output mixers */ | ||
8192 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8193 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8194 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
8195 | {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00}, | ||
8196 | |||
8197 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8198 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8199 | |||
8200 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
8201 | {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0}, | ||
8202 | {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40}, | ||
8203 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
8204 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
8205 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8206 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8207 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8208 | |||
8209 | {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8210 | {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8211 | {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8212 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8213 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8214 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8215 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8216 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
8217 | |||
8218 | /* FIXME: use matrix-type input source selection */ | ||
8219 | /* Mixer elements: 0x18, 19, 1a, 1c, 14, 15, 0b */ | ||
8220 | /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */ | ||
8221 | /* Input mixer2 */ | ||
8222 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
8223 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
8224 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
8225 | {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
8226 | |||
8227 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, | ||
8228 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, | ||
8229 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, | ||
8230 | {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, | ||
8231 | { } | ||
8232 | }; | ||
8233 | |||
8234 | /* | ||
8235 | * generic initialization of ADC, input mixers and output mixers | ||
8236 | */ | ||
8237 | static struct hda_verb alc268_volume_init_verbs[] = { | ||
8238 | /* set output DAC */ | ||
8239 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8240 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8241 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8242 | {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8243 | |||
8244 | {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
8245 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, | ||
8246 | {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8247 | {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8248 | {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20}, | ||
8249 | |||
8250 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, | ||
8251 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8252 | {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, | ||
8253 | {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8254 | {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)}, | ||
8255 | |||
8256 | {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8257 | {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8258 | {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8259 | {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, | ||
8260 | |||
8261 | /* set PCBEEP vol = 0 */ | ||
8262 | {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, (0xb000 | (0x00 << 8))}, | ||
8263 | |||
8264 | { } | ||
8265 | }; | ||
8266 | |||
8267 | #define alc268_mux_enum_info alc_mux_enum_info | ||
8268 | #define alc268_mux_enum_get alc_mux_enum_get | ||
8269 | |||
8270 | static int alc268_mux_enum_put(struct snd_kcontrol *kcontrol, | ||
8271 | struct snd_ctl_elem_value *ucontrol) | ||
8272 | { | ||
8273 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
8274 | struct alc_spec *spec = codec->spec; | ||
8275 | const struct hda_input_mux *imux = spec->input_mux; | ||
8276 | unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); | ||
8277 | static hda_nid_t capture_mixers[3] = { 0x23, 0x24 }; | ||
8278 | hda_nid_t nid = capture_mixers[adc_idx]; | ||
8279 | unsigned int *cur_val = &spec->cur_mux[adc_idx]; | ||
8280 | unsigned int i, idx; | ||
8281 | |||
8282 | idx = ucontrol->value.enumerated.item[0]; | ||
8283 | if (idx >= imux->num_items) | ||
8284 | idx = imux->num_items - 1; | ||
8285 | if (*cur_val == idx && !codec->in_resume) | ||
8286 | return 0; | ||
8287 | for (i = 0; i < imux->num_items; i++) { | ||
8288 | unsigned int v = (i == idx) ? 0x7000 : 0x7080; | ||
8289 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | ||
8290 | v | (imux->items[i].index << 8)); | ||
8291 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CONNECT_SEL, | ||
8292 | idx ); | ||
8293 | } | ||
8294 | *cur_val = idx; | ||
8295 | return 1; | ||
8296 | } | ||
8297 | |||
8298 | static struct snd_kcontrol_new alc268_capture_alt_mixer[] = { | ||
8299 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), | ||
8300 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), | ||
8301 | { | ||
8302 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8303 | /* The multiple "Capture Source" controls confuse alsamixer | ||
8304 | * So call somewhat different.. | ||
8305 | * FIXME: the controls appear in the "playback" view! | ||
8306 | */ | ||
8307 | /* .name = "Capture Source", */ | ||
8308 | .name = "Input Source", | ||
8309 | .count = 1, | ||
8310 | .info = alc268_mux_enum_info, | ||
8311 | .get = alc268_mux_enum_get, | ||
8312 | .put = alc268_mux_enum_put, | ||
8313 | }, | ||
8314 | { } /* end */ | ||
8315 | }; | ||
8316 | |||
8317 | static struct snd_kcontrol_new alc268_capture_mixer[] = { | ||
8318 | HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT), | ||
8319 | HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT), | ||
8320 | HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT), | ||
8321 | HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT), | ||
8322 | { | ||
8323 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
8324 | /* The multiple "Capture Source" controls confuse alsamixer | ||
8325 | * So call somewhat different.. | ||
8326 | * FIXME: the controls appear in the "playback" view! | ||
8327 | */ | ||
8328 | /* .name = "Capture Source", */ | ||
8329 | .name = "Input Source", | ||
8330 | .count = 2, | ||
8331 | .info = alc268_mux_enum_info, | ||
8332 | .get = alc268_mux_enum_get, | ||
8333 | .put = alc268_mux_enum_put, | ||
8334 | }, | ||
8335 | { } /* end */ | ||
8336 | }; | ||
8337 | |||
8338 | static struct hda_input_mux alc268_capture_source = { | ||
8339 | .num_items = 4, | ||
8340 | .items = { | ||
8341 | { "Mic", 0x0 }, | ||
8342 | { "Front Mic", 0x1 }, | ||
8343 | { "Line", 0x2 }, | ||
8344 | { "CD", 0x3 }, | ||
8345 | }, | ||
8346 | }; | ||
8347 | |||
8348 | /* create input playback/capture controls for the given pin */ | ||
8349 | static int alc268_new_analog_output(struct alc_spec *spec, hda_nid_t nid, | ||
8350 | const char *ctlname, int idx) | ||
8351 | { | ||
8352 | char name[32]; | ||
8353 | int err; | ||
8354 | |||
8355 | sprintf(name, "%s Playback Volume", ctlname); | ||
8356 | if (nid == 0x14) { | ||
8357 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
8358 | HDA_COMPOSE_AMP_VAL(0x02, 3, idx, | ||
8359 | HDA_OUTPUT)); | ||
8360 | if (err < 0) | ||
8361 | return err; | ||
8362 | } else if (nid == 0x15) { | ||
8363 | err = add_control(spec, ALC_CTL_WIDGET_VOL, name, | ||
8364 | HDA_COMPOSE_AMP_VAL(0x03, 3, idx, | ||
8365 | HDA_OUTPUT)); | ||
8366 | if (err < 0) | ||
8367 | return err; | ||
8368 | } else | ||
8369 | return -1; | ||
8370 | sprintf(name, "%s Playback Switch", ctlname); | ||
8371 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, name, | ||
8372 | HDA_COMPOSE_AMP_VAL(nid, 3, idx, HDA_OUTPUT)); | ||
8373 | if (err < 0) | ||
8374 | return err; | ||
8375 | return 0; | ||
8376 | } | ||
8377 | |||
8378 | /* add playback controls from the parsed DAC table */ | ||
8379 | static int alc268_auto_create_multi_out_ctls(struct alc_spec *spec, | ||
8380 | const struct auto_pin_cfg *cfg) | ||
8381 | { | ||
8382 | hda_nid_t nid; | ||
8383 | int err; | ||
8384 | |||
8385 | spec->multiout.num_dacs = 2; /* only use one dac */ | ||
8386 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
8387 | spec->multiout.dac_nids[0] = 2; | ||
8388 | spec->multiout.dac_nids[1] = 3; | ||
8389 | |||
8390 | nid = cfg->line_out_pins[0]; | ||
8391 | if (nid) | ||
8392 | alc268_new_analog_output(spec, nid, "Front", 0); | ||
8393 | |||
8394 | nid = cfg->speaker_pins[0]; | ||
8395 | if (nid == 0x1d) { | ||
8396 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
8397 | "Speaker Playback Volume", | ||
8398 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | ||
8399 | if (err < 0) | ||
8400 | return err; | ||
8401 | } | ||
8402 | nid = cfg->hp_pins[0]; | ||
8403 | if (nid) | ||
8404 | alc268_new_analog_output(spec, nid, "Headphone", 0); | ||
8405 | |||
8406 | nid = cfg->line_out_pins[1] | cfg->line_out_pins[2]; | ||
8407 | if (nid == 0x16) { | ||
8408 | err = add_control(spec, ALC_CTL_WIDGET_MUTE, | ||
8409 | "Mono Playback Switch", | ||
8410 | HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_INPUT)); | ||
8411 | if (err < 0) | ||
8412 | return err; | ||
8413 | } | ||
8414 | return 0; | ||
8415 | } | ||
8416 | |||
8417 | /* create playback/capture controls for input pins */ | ||
8418 | static int alc268_auto_create_analog_input_ctls(struct alc_spec *spec, | ||
8419 | const struct auto_pin_cfg *cfg) | ||
8420 | { | ||
8421 | struct hda_input_mux *imux = &spec->private_imux; | ||
8422 | int i, idx1; | ||
8423 | |||
8424 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
8425 | switch(cfg->input_pins[i]) { | ||
8426 | case 0x18: | ||
8427 | idx1 = 0; /* Mic 1 */ | ||
8428 | break; | ||
8429 | case 0x19: | ||
8430 | idx1 = 1; /* Mic 2 */ | ||
8431 | break; | ||
8432 | case 0x1a: | ||
8433 | idx1 = 2; /* Line In */ | ||
8434 | break; | ||
8435 | case 0x1c: | ||
8436 | idx1 = 3; /* CD */ | ||
8437 | break; | ||
8438 | default: | ||
8439 | continue; | ||
8440 | } | ||
8441 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
8442 | imux->items[imux->num_items].index = idx1; | ||
8443 | imux->num_items++; | ||
8444 | } | ||
8445 | return 0; | ||
8446 | } | ||
8447 | |||
8448 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) | ||
8449 | { | ||
8450 | struct alc_spec *spec = codec->spec; | ||
8451 | hda_nid_t speaker_nid = spec->autocfg.speaker_pins[0]; | ||
8452 | hda_nid_t hp_nid = spec->autocfg.hp_pins[0]; | ||
8453 | hda_nid_t line_nid = spec->autocfg.line_out_pins[0]; | ||
8454 | unsigned int dac_vol1, dac_vol2; | ||
8455 | |||
8456 | if (speaker_nid) { | ||
8457 | snd_hda_codec_write(codec, speaker_nid, 0, | ||
8458 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
8459 | snd_hda_codec_write(codec, 0x0f, 0, | ||
8460 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
8461 | AMP_IN_UNMUTE(1)); | ||
8462 | snd_hda_codec_write(codec, 0x10, 0, | ||
8463 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
8464 | AMP_IN_UNMUTE(1)); | ||
8465 | } else { | ||
8466 | snd_hda_codec_write(codec, 0x0f, 0, | ||
8467 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); | ||
8468 | snd_hda_codec_write(codec, 0x10, 0, | ||
8469 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)); | ||
8470 | } | ||
8471 | |||
8472 | dac_vol1 = dac_vol2 = 0xb000 | 0x40; /* set max volume */ | ||
8473 | if (line_nid == 0x14) | ||
8474 | dac_vol2 = AMP_OUT_ZERO; | ||
8475 | else if (line_nid == 0x15) | ||
8476 | dac_vol1 = AMP_OUT_ZERO; | ||
8477 | if (hp_nid == 0x14) | ||
8478 | dac_vol2 = AMP_OUT_ZERO; | ||
8479 | else if (hp_nid == 0x15) | ||
8480 | dac_vol1 = AMP_OUT_ZERO; | ||
8481 | if (line_nid != 0x16 || hp_nid != 0x16 || | ||
8482 | spec->autocfg.line_out_pins[1] != 0x16 || | ||
8483 | spec->autocfg.line_out_pins[2] != 0x16) | ||
8484 | dac_vol1 = dac_vol2 = AMP_OUT_ZERO; | ||
8485 | |||
8486 | snd_hda_codec_write(codec, 0x02, 0, | ||
8487 | AC_VERB_SET_AMP_GAIN_MUTE, dac_vol1); | ||
8488 | snd_hda_codec_write(codec, 0x03, 0, | ||
8489 | AC_VERB_SET_AMP_GAIN_MUTE, dac_vol2); | ||
8490 | } | ||
8491 | |||
8492 | /* pcm configuration: identiacal with ALC880 */ | ||
8493 | #define alc268_pcm_analog_playback alc880_pcm_analog_playback | ||
8494 | #define alc268_pcm_analog_capture alc880_pcm_analog_capture | ||
8495 | #define alc268_pcm_digital_playback alc880_pcm_digital_playback | ||
8496 | |||
8497 | /* | ||
8498 | * BIOS auto configuration | ||
8499 | */ | ||
8500 | static int alc268_parse_auto_config(struct hda_codec *codec) | ||
8501 | { | ||
8502 | struct alc_spec *spec = codec->spec; | ||
8503 | int err; | ||
8504 | static hda_nid_t alc268_ignore[] = { 0 }; | ||
8505 | |||
8506 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, | ||
8507 | alc268_ignore); | ||
8508 | if (err < 0) | ||
8509 | return err; | ||
8510 | if (!spec->autocfg.line_outs) | ||
8511 | return 0; /* can't find valid BIOS pin config */ | ||
8512 | |||
8513 | err = alc268_auto_create_multi_out_ctls(spec, &spec->autocfg); | ||
8514 | if (err < 0) | ||
8515 | return err; | ||
8516 | err = alc268_auto_create_analog_input_ctls(spec, &spec->autocfg); | ||
8517 | if (err < 0) | ||
8518 | return err; | ||
8519 | |||
8520 | spec->multiout.max_channels = 2; | ||
8521 | |||
8522 | /* digital only support output */ | ||
8523 | if (spec->autocfg.dig_out_pin) | ||
8524 | spec->multiout.dig_out_nid = ALC268_DIGOUT_NID; | ||
8525 | |||
8526 | if (spec->kctl_alloc) | ||
8527 | spec->mixers[spec->num_mixers++] = spec->kctl_alloc; | ||
8528 | |||
8529 | spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs; | ||
8530 | spec->num_mux_defs = 1; | ||
8531 | spec->input_mux = &spec->private_imux; | ||
8532 | |||
8533 | return 1; | ||
8534 | } | ||
8535 | |||
8536 | #define alc268_auto_init_multi_out alc882_auto_init_multi_out | ||
8537 | #define alc268_auto_init_hp_out alc882_auto_init_hp_out | ||
8538 | #define alc268_auto_init_analog_input alc882_auto_init_analog_input | ||
8539 | |||
8540 | /* init callback for auto-configuration model -- overriding the default init */ | ||
8541 | static void alc268_auto_init(struct hda_codec *codec) | ||
8542 | { | ||
8543 | alc268_auto_init_multi_out(codec); | ||
8544 | alc268_auto_init_hp_out(codec); | ||
8545 | alc268_auto_init_mono_speaker_out(codec); | ||
8546 | alc268_auto_init_analog_input(codec); | ||
8547 | } | ||
8548 | |||
8549 | /* | ||
8550 | * configuration and preset | ||
8551 | */ | ||
8552 | static const char *alc268_models[ALC268_MODEL_LAST] = { | ||
8553 | [ALC268_3ST] = "3stack", | ||
8554 | [ALC268_AUTO] = "auto", | ||
8555 | }; | ||
8556 | |||
8557 | static struct snd_pci_quirk alc268_cfg_tbl[] = { | ||
8558 | SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST), | ||
8559 | {} | ||
8560 | }; | ||
8561 | |||
8562 | static struct alc_config_preset alc268_presets[] = { | ||
8563 | [ALC268_3ST] = { | ||
8564 | .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, | ||
8565 | .init_verbs = { alc268_base_init_verbs }, | ||
8566 | .num_dacs = ARRAY_SIZE(alc268_dac_nids), | ||
8567 | .dac_nids = alc268_dac_nids, | ||
8568 | .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), | ||
8569 | .adc_nids = alc268_adc_nids_alt, | ||
8570 | .hp_nid = 0x03, | ||
8571 | .dig_out_nid = ALC268_DIGOUT_NID, | ||
8572 | .num_channel_mode = ARRAY_SIZE(alc268_modes), | ||
8573 | .channel_mode = alc268_modes, | ||
8574 | .input_mux = &alc268_capture_source, | ||
8575 | }, | ||
8576 | }; | ||
8577 | |||
8578 | static int patch_alc268(struct hda_codec *codec) | ||
8579 | { | ||
8580 | struct alc_spec *spec; | ||
8581 | int board_config; | ||
8582 | int err; | ||
8583 | |||
8584 | spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); | ||
8585 | if (spec == NULL) | ||
8586 | return -ENOMEM; | ||
8587 | |||
8588 | codec->spec = spec; | ||
8589 | |||
8590 | board_config = snd_hda_check_board_config(codec, ALC268_MODEL_LAST, | ||
8591 | alc268_models, | ||
8592 | alc268_cfg_tbl); | ||
8593 | |||
8594 | if (board_config < 0 || board_config >= ALC268_MODEL_LAST) { | ||
8595 | printk(KERN_INFO "hda_codec: Unknown model for ALC268, " | ||
8596 | "trying auto-probe from BIOS...\n"); | ||
8597 | board_config = ALC268_AUTO; | ||
8598 | } | ||
8599 | |||
8600 | if (board_config == ALC268_AUTO) { | ||
8601 | /* automatic parse from the BIOS config */ | ||
8602 | err = alc268_parse_auto_config(codec); | ||
8603 | if (err < 0) { | ||
8604 | alc_free(codec); | ||
8605 | return err; | ||
8606 | } else if (!err) { | ||
8607 | printk(KERN_INFO | ||
8608 | "hda_codec: Cannot set up configuration " | ||
8609 | "from BIOS. Using base mode...\n"); | ||
8610 | board_config = ALC268_3ST; | ||
8611 | } | ||
8612 | } | ||
8613 | |||
8614 | if (board_config != ALC268_AUTO) | ||
8615 | setup_preset(spec, &alc268_presets[board_config]); | ||
8616 | |||
8617 | spec->stream_name_analog = "ALC268 Analog"; | ||
8618 | spec->stream_analog_playback = &alc268_pcm_analog_playback; | ||
8619 | spec->stream_analog_capture = &alc268_pcm_analog_capture; | ||
8620 | |||
8621 | spec->stream_name_digital = "ALC268 Digital"; | ||
8622 | spec->stream_digital_playback = &alc268_pcm_digital_playback; | ||
8623 | |||
8624 | if (board_config == ALC268_AUTO) { | ||
8625 | if (!spec->adc_nids && spec->input_mux) { | ||
8626 | /* check whether NID 0x07 is valid */ | ||
8627 | unsigned int wcap = get_wcaps(codec, 0x07); | ||
8628 | |||
8629 | /* get type */ | ||
8630 | wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; | ||
8631 | if (wcap != AC_WID_AUD_IN) { | ||
8632 | spec->adc_nids = alc268_adc_nids_alt; | ||
8633 | spec->num_adc_nids = | ||
8634 | ARRAY_SIZE(alc268_adc_nids_alt); | ||
8635 | spec->mixers[spec->num_mixers] = | ||
8636 | alc268_capture_alt_mixer; | ||
8637 | spec->num_mixers++; | ||
8638 | } else { | ||
8639 | spec->adc_nids = alc268_adc_nids; | ||
8640 | spec->num_adc_nids = | ||
8641 | ARRAY_SIZE(alc268_adc_nids); | ||
8642 | spec->mixers[spec->num_mixers] = | ||
8643 | alc268_capture_mixer; | ||
8644 | spec->num_mixers++; | ||
8645 | } | ||
8646 | } | ||
8647 | } | ||
8648 | codec->patch_ops = alc_patch_ops; | ||
8649 | if (board_config == ALC268_AUTO) | ||
8650 | spec->init_hook = alc268_auto_init; | ||
8651 | |||
8652 | return 0; | ||
8653 | } | ||
8654 | |||
8655 | /* | ||
7803 | * ALC861 channel source setting (2/6 channel selection for 3-stack) | 8656 | * ALC861 channel source setting (2/6 channel selection for 3-stack) |
7804 | */ | 8657 | */ |
7805 | 8658 | ||
@@ -8767,13 +9620,21 @@ static struct snd_pci_quirk alc861_cfg_tbl[] = { | |||
8767 | SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), | 9620 | SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP), |
8768 | SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), | 9621 | SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP), |
8769 | SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), | 9622 | SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP), |
9623 | SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP), | ||
8770 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), | 9624 | SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS), |
9625 | SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG), | ||
8771 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), | 9626 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA), |
8772 | SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), | 9627 | /* FIXME: the entry below breaks Toshiba A100 (model=auto works!) |
9628 | * Any other models that need this preset? | ||
9629 | */ | ||
9630 | /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */ | ||
8773 | SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), | 9631 | SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31), |
9632 | SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), | ||
8774 | SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), | 9633 | SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31), |
8775 | SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), | 9634 | SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST), |
8776 | SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), | 9635 | SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST), |
9636 | SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST), | ||
9637 | SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST), | ||
8777 | {} | 9638 | {} |
8778 | }; | 9639 | }; |
8779 | 9640 | ||
@@ -9464,6 +10325,7 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re | |||
9464 | */ | 10325 | */ |
9465 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | 10326 | static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { |
9466 | [ALC660VD_3ST] = "3stack-660", | 10327 | [ALC660VD_3ST] = "3stack-660", |
10328 | [ALC660VD_3ST_DIG]= "3stack-660-digout", | ||
9467 | [ALC861VD_3ST] = "3stack", | 10329 | [ALC861VD_3ST] = "3stack", |
9468 | [ALC861VD_3ST_DIG] = "3stack-digout", | 10330 | [ALC861VD_3ST_DIG] = "3stack-digout", |
9469 | [ALC861VD_6ST_DIG] = "6stack-digout", | 10331 | [ALC861VD_6ST_DIG] = "6stack-digout", |
@@ -9475,7 +10337,7 @@ static const char *alc861vd_models[ALC861VD_MODEL_LAST] = { | |||
9475 | static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | 10337 | static struct snd_pci_quirk alc861vd_cfg_tbl[] = { |
9476 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), | 10338 | SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST), |
9477 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), | 10339 | SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST), |
9478 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST), | 10340 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG), |
9479 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), | 10341 | SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST), |
9480 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), | 10342 | SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST), |
9481 | 10343 | ||
@@ -9483,6 +10345,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = { | |||
9483 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), | 10345 | SND_PCI_QUIRK(0x1179, 0xff01, "DALLAS", ALC861VD_DALLAS), |
9484 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), | 10346 | SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_LENOVO), |
9485 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), | 10347 | SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo", ALC861VD_LENOVO), |
10348 | SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO), | ||
9486 | {} | 10349 | {} |
9487 | }; | 10350 | }; |
9488 | 10351 | ||
@@ -9499,6 +10362,19 @@ static struct alc_config_preset alc861vd_presets[] = { | |||
9499 | .channel_mode = alc861vd_3stack_2ch_modes, | 10362 | .channel_mode = alc861vd_3stack_2ch_modes, |
9500 | .input_mux = &alc861vd_capture_source, | 10363 | .input_mux = &alc861vd_capture_source, |
9501 | }, | 10364 | }, |
10365 | [ALC660VD_3ST_DIG] = { | ||
10366 | .mixers = { alc861vd_3st_mixer }, | ||
10367 | .init_verbs = { alc861vd_volume_init_verbs, | ||
10368 | alc861vd_3stack_init_verbs }, | ||
10369 | .num_dacs = ARRAY_SIZE(alc660vd_dac_nids), | ||
10370 | .dac_nids = alc660vd_dac_nids, | ||
10371 | .dig_out_nid = ALC861VD_DIGOUT_NID, | ||
10372 | .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids), | ||
10373 | .adc_nids = alc861vd_adc_nids, | ||
10374 | .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes), | ||
10375 | .channel_mode = alc861vd_3stack_2ch_modes, | ||
10376 | .input_mux = &alc861vd_capture_source, | ||
10377 | }, | ||
9502 | [ALC861VD_3ST] = { | 10378 | [ALC861VD_3ST] = { |
9503 | .mixers = { alc861vd_3st_mixer }, | 10379 | .mixers = { alc861vd_3st_mixer }, |
9504 | .init_verbs = { alc861vd_volume_init_verbs, | 10380 | .init_verbs = { alc861vd_volume_init_verbs, |
@@ -10420,7 +11296,7 @@ static int alc662_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
10420 | for (i = 0; i < cfg->line_outs; i++) { | 11296 | for (i = 0; i < cfg->line_outs; i++) { |
10421 | if (!spec->multiout.dac_nids[i]) | 11297 | if (!spec->multiout.dac_nids[i]) |
10422 | continue; | 11298 | continue; |
10423 | nid = alc880_idx_to_dac(i); | 11299 | nid = alc880_idx_to_mixer(i); |
10424 | if (i == 2) { | 11300 | if (i == 2) { |
10425 | /* Center/LFE */ | 11301 | /* Center/LFE */ |
10426 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 11302 | err = add_control(spec, ALC_CTL_WIDGET_VOL, |
@@ -10643,14 +11519,10 @@ static int alc662_parse_auto_config(struct hda_codec *codec) | |||
10643 | spec->num_mux_defs = 1; | 11519 | spec->num_mux_defs = 1; |
10644 | spec->input_mux = &spec->private_imux; | 11520 | spec->input_mux = &spec->private_imux; |
10645 | 11521 | ||
10646 | if (err < 0) | 11522 | spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs; |
10647 | return err; | ||
10648 | else if (err > 0) | ||
10649 | /* hack - override the init verbs */ | ||
10650 | spec->init_verbs[0] = alc662_auto_init_verbs; | ||
10651 | spec->mixers[spec->num_mixers] = alc662_capture_mixer; | 11523 | spec->mixers[spec->num_mixers] = alc662_capture_mixer; |
10652 | spec->num_mixers++; | 11524 | spec->num_mixers++; |
10653 | return err; | 11525 | return 1; |
10654 | } | 11526 | } |
10655 | 11527 | ||
10656 | /* additional initialization for auto-configuration model */ | 11528 | /* additional initialization for auto-configuration model */ |
@@ -10687,7 +11559,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
10687 | if (err < 0) { | 11559 | if (err < 0) { |
10688 | alc_free(codec); | 11560 | alc_free(codec); |
10689 | return err; | 11561 | return err; |
10690 | } else if (err) { | 11562 | } else if (!err) { |
10691 | printk(KERN_INFO | 11563 | printk(KERN_INFO |
10692 | "hda_codec: Cannot set up configuration " | 11564 | "hda_codec: Cannot set up configuration " |
10693 | "from BIOS. Using base mode...\n"); | 11565 | "from BIOS. Using base mode...\n"); |
@@ -10724,6 +11596,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
10724 | struct hda_codec_preset snd_hda_preset_realtek[] = { | 11596 | struct hda_codec_preset snd_hda_preset_realtek[] = { |
10725 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, | 11597 | { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, |
10726 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, | 11598 | { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, |
11599 | { .id = 0x10ec0268, .name = "ALC268", .patch = patch_alc268 }, | ||
10727 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", | 11600 | { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660", |
10728 | .patch = patch_alc861 }, | 11601 | .patch = patch_alc861 }, |
10729 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, | 11602 | { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd }, |
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c index 43f537ef40bf..6d2ecc38905c 100644 --- a/sound/pci/hda/patch_si3054.c +++ b/sound/pci/hda/patch_si3054.c | |||
@@ -304,8 +304,12 @@ struct hda_codec_preset snd_hda_preset_si3054[] = { | |||
304 | { .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 }, | 304 | { .id = 0x10573055, .name = "Si3054", .patch = patch_si3054 }, |
305 | { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, | 305 | { .id = 0x10573057, .name = "Si3054", .patch = patch_si3054 }, |
306 | { .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 }, | 306 | { .id = 0x10573155, .name = "Si3054", .patch = patch_si3054 }, |
307 | /* VIA HDA on Clevo m540 */ | ||
308 | { .id = 0x11063288, .name = "Si3054", .patch = patch_si3054 }, | ||
307 | /* Asus A8J Modem (SM56) */ | 309 | /* Asus A8J Modem (SM56) */ |
308 | { .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 }, | 310 | { .id = 0x15433155, .name = "Si3054", .patch = patch_si3054 }, |
311 | /* LG LW20 modem */ | ||
312 | { .id = 0x18540018, .name = "Si3054", .patch = patch_si3054 }, | ||
309 | {} | 313 | {} |
310 | }; | 314 | }; |
311 | 315 | ||
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index e3964fc4c405..3f25de72966b 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -44,6 +44,7 @@ enum { | |||
44 | 44 | ||
45 | enum { | 45 | enum { |
46 | STAC_9205_REF, | 46 | STAC_9205_REF, |
47 | STAC_M43xx, | ||
47 | STAC_9205_MODELS | 48 | STAC_9205_MODELS |
48 | }; | 49 | }; |
49 | 50 | ||
@@ -59,11 +60,19 @@ enum { | |||
59 | STAC_D945_REF, | 60 | STAC_D945_REF, |
60 | STAC_D945GTP3, | 61 | STAC_D945GTP3, |
61 | STAC_D945GTP5, | 62 | STAC_D945GTP5, |
63 | STAC_922X_DELL, | ||
64 | STAC_INTEL_MAC_V1, | ||
65 | STAC_INTEL_MAC_V2, | ||
66 | STAC_INTEL_MAC_V3, | ||
67 | STAC_INTEL_MAC_V4, | ||
68 | STAC_INTEL_MAC_V5, | ||
69 | /* for backward compitability */ | ||
62 | STAC_MACMINI, | 70 | STAC_MACMINI, |
63 | STAC_MACBOOK, | 71 | STAC_MACBOOK, |
64 | STAC_MACBOOK_PRO_V1, | 72 | STAC_MACBOOK_PRO_V1, |
65 | STAC_MACBOOK_PRO_V2, | 73 | STAC_MACBOOK_PRO_V2, |
66 | STAC_IMAC_INTEL, | 74 | STAC_IMAC_INTEL, |
75 | STAC_IMAC_INTEL_20, | ||
67 | STAC_922X_MODELS | 76 | STAC_922X_MODELS |
68 | }; | 77 | }; |
69 | 78 | ||
@@ -210,7 +219,6 @@ static hda_nid_t stac9205_pin_nids[12] = { | |||
210 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | 219 | 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, |
211 | 0x0f, 0x14, 0x16, 0x17, 0x18, | 220 | 0x0f, 0x14, 0x16, 0x17, 0x18, |
212 | 0x21, 0x22, | 221 | 0x21, 0x22, |
213 | |||
214 | }; | 222 | }; |
215 | 223 | ||
216 | static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, | 224 | static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol, |
@@ -326,8 +334,6 @@ static struct snd_kcontrol_new stac9200_mixer[] = { | |||
326 | }; | 334 | }; |
327 | 335 | ||
328 | static struct snd_kcontrol_new stac925x_mixer[] = { | 336 | static struct snd_kcontrol_new stac925x_mixer[] = { |
329 | HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT), | ||
330 | HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT), | ||
331 | { | 337 | { |
332 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 338 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
333 | .name = "Input Source", | 339 | .name = "Input Source", |
@@ -549,44 +555,78 @@ static unsigned int d945gtp5_pin_configs[10] = { | |||
549 | 0x02a19320, 0x40000100, | 555 | 0x02a19320, 0x40000100, |
550 | }; | 556 | }; |
551 | 557 | ||
552 | static unsigned int macbook_pro_v1_pin_configs[10] = { | 558 | static unsigned int intel_mac_v1_pin_configs[10] = { |
553 | 0x0321e230, 0x03a1e020, 0x9017e110, 0x01014010, | 559 | 0x0121e21f, 0x400000ff, 0x9017e110, 0x400000fd, |
554 | 0x01a19021, 0x0381e021, 0x1345e240, 0x13c5e22e, | 560 | 0x400000fe, 0x0181e020, 0x1145e030, 0x11c5e240, |
555 | 0x02a19320, 0x400000fb | 561 | 0x400000fc, 0x400000fb, |
562 | }; | ||
563 | |||
564 | static unsigned int intel_mac_v2_pin_configs[10] = { | ||
565 | 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, | ||
566 | 0x400000fe, 0x0181e020, 0x1145e230, 0x500000fa, | ||
567 | 0x400000fc, 0x400000fb, | ||
568 | }; | ||
569 | |||
570 | static unsigned int intel_mac_v3_pin_configs[10] = { | ||
571 | 0x0121e21f, 0x90a7012e, 0x9017e110, 0x400000fd, | ||
572 | 0x400000fe, 0x0181e020, 0x1145e230, 0x11c5e240, | ||
573 | 0x400000fc, 0x400000fb, | ||
556 | }; | 574 | }; |
557 | 575 | ||
558 | static unsigned int macbook_pro_v2_pin_configs[10] = { | 576 | static unsigned int intel_mac_v4_pin_configs[10] = { |
559 | 0x0221401f, 0x90a70120, 0x01813024, 0x01014010, | 577 | 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, |
560 | 0x400000fd, 0x01016011, 0x1345e240, 0x13c5e22e, | 578 | 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, |
561 | 0x400000fc, 0x400000fb, | 579 | 0x400000fc, 0x400000fb, |
562 | }; | 580 | }; |
563 | 581 | ||
564 | static unsigned int imac_intel_pin_configs[10] = { | 582 | static unsigned int intel_mac_v5_pin_configs[10] = { |
565 | 0x0121e230, 0x90a70120, 0x9017e110, 0x400000fe, | 583 | 0x0321e21f, 0x03a1e02e, 0x9017e110, 0x9017e11f, |
566 | 0x400000fd, 0x0181e021, 0x1145e040, 0x400000fa, | 584 | 0x400000fe, 0x0381e020, 0x1345e230, 0x13c5e240, |
567 | 0x400000fc, 0x400000fb, | 585 | 0x400000fc, 0x400000fb, |
568 | }; | 586 | }; |
569 | 587 | ||
588 | static unsigned int stac922x_dell_pin_configs[10] = { | ||
589 | 0x0221121e, 0x408103ff, 0x02a1123e, 0x90100310, | ||
590 | 0x408003f1, 0x0221122f, 0x03451340, 0x40c003f2, | ||
591 | 0x50a003f3, 0x405003f4 | ||
592 | }; | ||
593 | |||
570 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { | 594 | static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { |
571 | [STAC_D945_REF] = ref922x_pin_configs, | 595 | [STAC_D945_REF] = ref922x_pin_configs, |
572 | [STAC_D945GTP3] = d945gtp3_pin_configs, | 596 | [STAC_D945GTP3] = d945gtp3_pin_configs, |
573 | [STAC_D945GTP5] = d945gtp5_pin_configs, | 597 | [STAC_D945GTP5] = d945gtp5_pin_configs, |
574 | [STAC_MACMINI] = macbook_pro_v1_pin_configs, | 598 | [STAC_922X_DELL] = stac922x_dell_pin_configs, |
575 | [STAC_MACBOOK] = macbook_pro_v1_pin_configs, | 599 | [STAC_INTEL_MAC_V1] = intel_mac_v1_pin_configs, |
576 | [STAC_MACBOOK_PRO_V1] = macbook_pro_v1_pin_configs, | 600 | [STAC_INTEL_MAC_V2] = intel_mac_v2_pin_configs, |
577 | [STAC_MACBOOK_PRO_V2] = macbook_pro_v2_pin_configs, | 601 | [STAC_INTEL_MAC_V3] = intel_mac_v3_pin_configs, |
578 | [STAC_IMAC_INTEL] = imac_intel_pin_configs, | 602 | [STAC_INTEL_MAC_V4] = intel_mac_v4_pin_configs, |
603 | [STAC_INTEL_MAC_V5] = intel_mac_v5_pin_configs, | ||
604 | /* for backward compitability */ | ||
605 | [STAC_MACMINI] = intel_mac_v3_pin_configs, | ||
606 | [STAC_MACBOOK] = intel_mac_v5_pin_configs, | ||
607 | [STAC_MACBOOK_PRO_V1] = intel_mac_v3_pin_configs, | ||
608 | [STAC_MACBOOK_PRO_V2] = intel_mac_v3_pin_configs, | ||
609 | [STAC_IMAC_INTEL] = intel_mac_v2_pin_configs, | ||
610 | [STAC_IMAC_INTEL_20] = intel_mac_v3_pin_configs, | ||
579 | }; | 611 | }; |
580 | 612 | ||
581 | static const char *stac922x_models[STAC_922X_MODELS] = { | 613 | static const char *stac922x_models[STAC_922X_MODELS] = { |
582 | [STAC_D945_REF] = "ref", | 614 | [STAC_D945_REF] = "ref", |
583 | [STAC_D945GTP5] = "5stack", | 615 | [STAC_D945GTP5] = "5stack", |
584 | [STAC_D945GTP3] = "3stack", | 616 | [STAC_D945GTP3] = "3stack", |
617 | [STAC_922X_DELL] = "dell", | ||
618 | [STAC_INTEL_MAC_V1] = "intel-mac-v1", | ||
619 | [STAC_INTEL_MAC_V2] = "intel-mac-v2", | ||
620 | [STAC_INTEL_MAC_V3] = "intel-mac-v3", | ||
621 | [STAC_INTEL_MAC_V4] = "intel-mac-v4", | ||
622 | [STAC_INTEL_MAC_V5] = "intel-mac-v5", | ||
623 | /* for backward compitability */ | ||
585 | [STAC_MACMINI] = "macmini", | 624 | [STAC_MACMINI] = "macmini", |
586 | [STAC_MACBOOK] = "macbook", | 625 | [STAC_MACBOOK] = "macbook", |
587 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", | 626 | [STAC_MACBOOK_PRO_V1] = "macbook-pro-v1", |
588 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", | 627 | [STAC_MACBOOK_PRO_V2] = "macbook-pro", |
589 | [STAC_IMAC_INTEL] = "imac-intel", | 628 | [STAC_IMAC_INTEL] = "imac-intel", |
629 | [STAC_IMAC_INTEL_20] = "imac-intel-20", | ||
590 | }; | 630 | }; |
591 | 631 | ||
592 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { | 632 | static struct snd_pci_quirk stac922x_cfg_tbl[] = { |
@@ -649,7 +689,10 @@ static struct snd_pci_quirk stac922x_cfg_tbl[] = { | |||
649 | /* other systems */ | 689 | /* other systems */ |
650 | /* Apple Mac Mini (early 2006) */ | 690 | /* Apple Mac Mini (early 2006) */ |
651 | SND_PCI_QUIRK(0x8384, 0x7680, | 691 | SND_PCI_QUIRK(0x8384, 0x7680, |
652 | "Mac Mini", STAC_MACMINI), | 692 | "Mac Mini", STAC_INTEL_MAC_V3), |
693 | /* Dell */ | ||
694 | SND_PCI_QUIRK(0x1028, 0x01d7, "Dell XPS M1210", STAC_922X_DELL), | ||
695 | |||
653 | {} /* terminator */ | 696 | {} /* terminator */ |
654 | }; | 697 | }; |
655 | 698 | ||
@@ -730,7 +773,8 @@ static unsigned int ref9205_pin_configs[12] = { | |||
730 | }; | 773 | }; |
731 | 774 | ||
732 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { | 775 | static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = { |
733 | ref9205_pin_configs, | 776 | [STAC_REF] = ref9205_pin_configs, |
777 | [STAC_M43xx] = NULL, | ||
734 | }; | 778 | }; |
735 | 779 | ||
736 | static const char *stac9205_models[STAC_9205_MODELS] = { | 780 | static const char *stac9205_models[STAC_9205_MODELS] = { |
@@ -741,6 +785,10 @@ static struct snd_pci_quirk stac9205_cfg_tbl[] = { | |||
741 | /* SigmaTel reference board */ | 785 | /* SigmaTel reference board */ |
742 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, | 786 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, |
743 | "DFI LanParty", STAC_9205_REF), | 787 | "DFI LanParty", STAC_9205_REF), |
788 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01f8, | ||
789 | "Dell Precision", STAC_M43xx), | ||
790 | SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x01ff, | ||
791 | "Dell Precision", STAC_M43xx), | ||
744 | {} /* terminator */ | 792 | {} /* terminator */ |
745 | }; | 793 | }; |
746 | 794 | ||
@@ -770,33 +818,56 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec) | |||
770 | return 0; | 818 | return 0; |
771 | } | 819 | } |
772 | 820 | ||
821 | static void stac92xx_set_config_reg(struct hda_codec *codec, | ||
822 | hda_nid_t pin_nid, unsigned int pin_config) | ||
823 | { | ||
824 | int i; | ||
825 | snd_hda_codec_write(codec, pin_nid, 0, | ||
826 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | ||
827 | pin_config & 0x000000ff); | ||
828 | snd_hda_codec_write(codec, pin_nid, 0, | ||
829 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | ||
830 | (pin_config & 0x0000ff00) >> 8); | ||
831 | snd_hda_codec_write(codec, pin_nid, 0, | ||
832 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | ||
833 | (pin_config & 0x00ff0000) >> 16); | ||
834 | snd_hda_codec_write(codec, pin_nid, 0, | ||
835 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | ||
836 | pin_config >> 24); | ||
837 | i = snd_hda_codec_read(codec, pin_nid, 0, | ||
838 | AC_VERB_GET_CONFIG_DEFAULT, | ||
839 | 0x00); | ||
840 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", | ||
841 | pin_nid, i); | ||
842 | } | ||
843 | |||
773 | static void stac92xx_set_config_regs(struct hda_codec *codec) | 844 | static void stac92xx_set_config_regs(struct hda_codec *codec) |
774 | { | 845 | { |
775 | int i; | 846 | int i; |
776 | struct sigmatel_spec *spec = codec->spec; | 847 | struct sigmatel_spec *spec = codec->spec; |
777 | unsigned int pin_cfg; | ||
778 | 848 | ||
779 | if (! spec->pin_nids || ! spec->pin_configs) | 849 | if (!spec->pin_configs) |
780 | return; | 850 | return; |
781 | 851 | ||
782 | for (i = 0; i < spec->num_pins; i++) { | 852 | for (i = 0; i < spec->num_pins; i++) |
783 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 853 | stac92xx_set_config_reg(codec, spec->pin_nids[i], |
784 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_0, | 854 | spec->pin_configs[i]); |
785 | spec->pin_configs[i] & 0x000000ff); | 855 | } |
786 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 856 | |
787 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, | 857 | static void stac92xx_enable_gpio_mask(struct hda_codec *codec, |
788 | (spec->pin_configs[i] & 0x0000ff00) >> 8); | 858 | int gpio_mask, int gpio_data) |
789 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 859 | { |
790 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, | 860 | /* Configure GPIOx as output */ |
791 | (spec->pin_configs[i] & 0x00ff0000) >> 16); | 861 | snd_hda_codec_write(codec, codec->afg, 0, |
792 | snd_hda_codec_write(codec, spec->pin_nids[i], 0, | 862 | AC_VERB_SET_GPIO_DIRECTION, gpio_mask); |
793 | AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, | 863 | /* Configure GPIOx as CMOS */ |
794 | spec->pin_configs[i] >> 24); | 864 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000); |
795 | pin_cfg = snd_hda_codec_read(codec, spec->pin_nids[i], 0, | 865 | /* Assert GPIOx */ |
796 | AC_VERB_GET_CONFIG_DEFAULT, | 866 | snd_hda_codec_write(codec, codec->afg, 0, |
797 | 0x00); | 867 | AC_VERB_SET_GPIO_DATA, gpio_data); |
798 | snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x pin config %8.8x\n", spec->pin_nids[i], pin_cfg); | 868 | /* Enable GPIOx */ |
799 | } | 869 | snd_hda_codec_write(codec, codec->afg, 0, |
870 | AC_VERB_SET_GPIO_MASK, gpio_mask); | ||
800 | } | 871 | } |
801 | 872 | ||
802 | /* | 873 | /* |
@@ -1168,7 +1239,7 @@ static int is_in_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid) | |||
1168 | * and 9202/925x. For those, dac_nids[] must be hard-coded. | 1239 | * and 9202/925x. For those, dac_nids[] must be hard-coded. |
1169 | */ | 1240 | */ |
1170 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | 1241 | static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, |
1171 | const struct auto_pin_cfg *cfg) | 1242 | struct auto_pin_cfg *cfg) |
1172 | { | 1243 | { |
1173 | struct sigmatel_spec *spec = codec->spec; | 1244 | struct sigmatel_spec *spec = codec->spec; |
1174 | int i, j, conn_len = 0; | 1245 | int i, j, conn_len = 0; |
@@ -1193,6 +1264,13 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec, | |||
1193 | } | 1264 | } |
1194 | 1265 | ||
1195 | if (j == conn_len) { | 1266 | if (j == conn_len) { |
1267 | if (spec->multiout.num_dacs > 0) { | ||
1268 | /* we have already working output pins, | ||
1269 | * so let's drop the broken ones again | ||
1270 | */ | ||
1271 | cfg->line_outs = spec->multiout.num_dacs; | ||
1272 | break; | ||
1273 | } | ||
1196 | /* error out, no available DAC found */ | 1274 | /* error out, no available DAC found */ |
1197 | snd_printk(KERN_ERR | 1275 | snd_printk(KERN_ERR |
1198 | "%s: No available DAC for pin 0x%x\n", | 1276 | "%s: No available DAC for pin 0x%x\n", |
@@ -1334,7 +1412,15 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
1334 | continue; | 1412 | continue; |
1335 | add_spec_dacs(spec, nid); | 1413 | add_spec_dacs(spec, nid); |
1336 | } | 1414 | } |
1337 | 1415 | for (i = 0; i < cfg->line_outs; i++) { | |
1416 | nid = snd_hda_codec_read(codec, cfg->line_out_pins[i], 0, | ||
1417 | AC_VERB_GET_CONNECT_LIST, 0) & 0xff; | ||
1418 | if (check_in_dac_nids(spec, nid)) | ||
1419 | nid = 0; | ||
1420 | if (! nid) | ||
1421 | continue; | ||
1422 | add_spec_dacs(spec, nid); | ||
1423 | } | ||
1338 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { | 1424 | for (i = old_num_dacs; i < spec->multiout.num_dacs; i++) { |
1339 | static const char *pfxs[] = { | 1425 | static const char *pfxs[] = { |
1340 | "Speaker", "External Speaker", "Speaker2", | 1426 | "Speaker", "External Speaker", "Speaker2", |
@@ -1891,7 +1977,7 @@ static int patch_stac9200(struct hda_codec *codec) | |||
1891 | return -ENOMEM; | 1977 | return -ENOMEM; |
1892 | 1978 | ||
1893 | codec->spec = spec; | 1979 | codec->spec = spec; |
1894 | spec->num_pins = 8; | 1980 | spec->num_pins = ARRAY_SIZE(stac9200_pin_nids); |
1895 | spec->pin_nids = stac9200_pin_nids; | 1981 | spec->pin_nids = stac9200_pin_nids; |
1896 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, | 1982 | spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS, |
1897 | stac9200_models, | 1983 | stac9200_models, |
@@ -1941,7 +2027,7 @@ static int patch_stac925x(struct hda_codec *codec) | |||
1941 | return -ENOMEM; | 2027 | return -ENOMEM; |
1942 | 2028 | ||
1943 | codec->spec = spec; | 2029 | codec->spec = spec; |
1944 | spec->num_pins = 8; | 2030 | spec->num_pins = ARRAY_SIZE(stac925x_pin_nids); |
1945 | spec->pin_nids = stac925x_pin_nids; | 2031 | spec->pin_nids = stac925x_pin_nids; |
1946 | spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, | 2032 | spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS, |
1947 | stac925x_models, | 2033 | stac925x_models, |
@@ -2013,29 +2099,41 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2013 | return -ENOMEM; | 2099 | return -ENOMEM; |
2014 | 2100 | ||
2015 | codec->spec = spec; | 2101 | codec->spec = spec; |
2016 | spec->num_pins = 10; | 2102 | spec->num_pins = ARRAY_SIZE(stac922x_pin_nids); |
2017 | spec->pin_nids = stac922x_pin_nids; | 2103 | spec->pin_nids = stac922x_pin_nids; |
2018 | spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, | 2104 | spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS, |
2019 | stac922x_models, | 2105 | stac922x_models, |
2020 | stac922x_cfg_tbl); | 2106 | stac922x_cfg_tbl); |
2021 | if (spec->board_config == STAC_MACMINI) { | 2107 | if (spec->board_config == STAC_INTEL_MAC_V3) { |
2022 | spec->gpio_mute = 1; | 2108 | spec->gpio_mute = 1; |
2023 | /* Intel Macs have all same PCI SSID, so we need to check | 2109 | /* Intel Macs have all same PCI SSID, so we need to check |
2024 | * codec SSID to distinguish the exact models | 2110 | * codec SSID to distinguish the exact models |
2025 | */ | 2111 | */ |
2026 | printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); | 2112 | printk(KERN_INFO "hda_codec: STAC922x, Apple subsys_id=%x\n", codec->subsystem_id); |
2027 | switch (codec->subsystem_id) { | 2113 | switch (codec->subsystem_id) { |
2028 | case 0x106b0a00: /* MacBook First generatoin */ | 2114 | |
2029 | spec->board_config = STAC_MACBOOK; | 2115 | case 0x106b0800: |
2116 | spec->board_config = STAC_INTEL_MAC_V1; | ||
2117 | break; | ||
2118 | case 0x106b0600: | ||
2119 | case 0x106b0700: | ||
2120 | spec->board_config = STAC_INTEL_MAC_V2; | ||
2030 | break; | 2121 | break; |
2031 | case 0x106b0200: /* MacBook Pro first generation */ | 2122 | case 0x106b0e00: |
2032 | spec->board_config = STAC_MACBOOK_PRO_V1; | 2123 | case 0x106b0f00: |
2124 | case 0x106b1600: | ||
2125 | case 0x106b1700: | ||
2126 | case 0x106b0200: | ||
2127 | case 0x106b1e00: | ||
2128 | spec->board_config = STAC_INTEL_MAC_V3; | ||
2033 | break; | 2129 | break; |
2034 | case 0x106b1e00: /* MacBook Pro second generation */ | 2130 | case 0x106b1a00: |
2035 | spec->board_config = STAC_MACBOOK_PRO_V2; | 2131 | case 0x00000100: |
2132 | spec->board_config = STAC_INTEL_MAC_V4; | ||
2036 | break; | 2133 | break; |
2037 | case 0x106b0700: /* Intel-based iMac */ | 2134 | case 0x106b0a00: |
2038 | spec->board_config = STAC_IMAC_INTEL; | 2135 | case 0x106b2200: |
2136 | spec->board_config = STAC_INTEL_MAC_V5; | ||
2039 | break; | 2137 | break; |
2040 | } | 2138 | } |
2041 | } | 2139 | } |
@@ -2082,6 +2180,13 @@ static int patch_stac922x(struct hda_codec *codec) | |||
2082 | 2180 | ||
2083 | codec->patch_ops = stac92xx_patch_ops; | 2181 | codec->patch_ops = stac92xx_patch_ops; |
2084 | 2182 | ||
2183 | /* Fix Mux capture level; max to 2 */ | ||
2184 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, | ||
2185 | (0 << AC_AMPCAP_OFFSET_SHIFT) | | ||
2186 | (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
2187 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
2188 | (0 << AC_AMPCAP_MUTE_SHIFT)); | ||
2189 | |||
2085 | return 0; | 2190 | return 0; |
2086 | } | 2191 | } |
2087 | 2192 | ||
@@ -2095,7 +2200,7 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2095 | return -ENOMEM; | 2200 | return -ENOMEM; |
2096 | 2201 | ||
2097 | codec->spec = spec; | 2202 | codec->spec = spec; |
2098 | spec->num_pins = 14; | 2203 | spec->num_pins = ARRAY_SIZE(stac927x_pin_nids); |
2099 | spec->pin_nids = stac927x_pin_nids; | 2204 | spec->pin_nids = stac927x_pin_nids; |
2100 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, | 2205 | spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS, |
2101 | stac927x_models, | 2206 | stac927x_models, |
@@ -2141,7 +2246,9 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2141 | } | 2246 | } |
2142 | 2247 | ||
2143 | spec->multiout.dac_nids = spec->dac_nids; | 2248 | spec->multiout.dac_nids = spec->dac_nids; |
2144 | 2249 | /* GPIO0 High = Enable EAPD */ | |
2250 | stac92xx_enable_gpio_mask(codec, 0x00000001, 0x00000001); | ||
2251 | |||
2145 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); | 2252 | err = stac92xx_parse_auto_config(codec, 0x1e, 0x20); |
2146 | if (!err) { | 2253 | if (!err) { |
2147 | if (spec->board_config < 0) { | 2254 | if (spec->board_config < 0) { |
@@ -2159,27 +2266,20 @@ static int patch_stac927x(struct hda_codec *codec) | |||
2159 | 2266 | ||
2160 | codec->patch_ops = stac92xx_patch_ops; | 2267 | codec->patch_ops = stac92xx_patch_ops; |
2161 | 2268 | ||
2162 | /* Fix Mux capture level; max to 2 */ | ||
2163 | snd_hda_override_amp_caps(codec, 0x12, HDA_OUTPUT, | ||
2164 | (0 << AC_AMPCAP_OFFSET_SHIFT) | | ||
2165 | (2 << AC_AMPCAP_NUM_STEPS_SHIFT) | | ||
2166 | (0x27 << AC_AMPCAP_STEP_SIZE_SHIFT) | | ||
2167 | (0 << AC_AMPCAP_MUTE_SHIFT)); | ||
2168 | |||
2169 | return 0; | 2269 | return 0; |
2170 | } | 2270 | } |
2171 | 2271 | ||
2172 | static int patch_stac9205(struct hda_codec *codec) | 2272 | static int patch_stac9205(struct hda_codec *codec) |
2173 | { | 2273 | { |
2174 | struct sigmatel_spec *spec; | 2274 | struct sigmatel_spec *spec; |
2175 | int err; | 2275 | int err, gpio_mask, gpio_data; |
2176 | 2276 | ||
2177 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 2277 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
2178 | if (spec == NULL) | 2278 | if (spec == NULL) |
2179 | return -ENOMEM; | 2279 | return -ENOMEM; |
2180 | 2280 | ||
2181 | codec->spec = spec; | 2281 | codec->spec = spec; |
2182 | spec->num_pins = 14; | 2282 | spec->num_pins = ARRAY_SIZE(stac9205_pin_nids); |
2183 | spec->pin_nids = stac9205_pin_nids; | 2283 | spec->pin_nids = stac9205_pin_nids; |
2184 | spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, | 2284 | spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS, |
2185 | stac9205_models, | 2285 | stac9205_models, |
@@ -2209,19 +2309,21 @@ static int patch_stac9205(struct hda_codec *codec) | |||
2209 | spec->mixer = stac9205_mixer; | 2309 | spec->mixer = stac9205_mixer; |
2210 | 2310 | ||
2211 | spec->multiout.dac_nids = spec->dac_nids; | 2311 | spec->multiout.dac_nids = spec->dac_nids; |
2312 | |||
2313 | if (spec->board_config == STAC_M43xx) { | ||
2314 | /* Enable SPDIF in/out */ | ||
2315 | stac92xx_set_config_reg(codec, 0x1f, 0x01441030); | ||
2316 | stac92xx_set_config_reg(codec, 0x20, 0x1c410030); | ||
2317 | |||
2318 | gpio_mask = 0x00000007; /* GPIO0-2 */ | ||
2319 | /* GPIO0 High = EAPD, GPIO1 Low = DRM, | ||
2320 | * GPIO2 High = Headphone Mute | ||
2321 | */ | ||
2322 | gpio_data = 0x00000005; | ||
2323 | } else | ||
2324 | gpio_mask = gpio_data = 0x00000001; /* GPIO0 High = EAPD */ | ||
2212 | 2325 | ||
2213 | /* Configure GPIO0 as EAPD output */ | 2326 | stac92xx_enable_gpio_mask(codec, gpio_mask, gpio_data); |
2214 | snd_hda_codec_write(codec, codec->afg, 0, | ||
2215 | AC_VERB_SET_GPIO_DIRECTION, 0x00000001); | ||
2216 | /* Configure GPIO0 as CMOS */ | ||
2217 | snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000); | ||
2218 | /* Assert GPIO0 high */ | ||
2219 | snd_hda_codec_write(codec, codec->afg, 0, | ||
2220 | AC_VERB_SET_GPIO_DATA, 0x00000001); | ||
2221 | /* Enable GPIO0 */ | ||
2222 | snd_hda_codec_write(codec, codec->afg, 0, | ||
2223 | AC_VERB_SET_GPIO_MASK, 0x00000001); | ||
2224 | |||
2225 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); | 2327 | err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); |
2226 | if (!err) { | 2328 | if (!err) { |
2227 | if (spec->board_config < 0) { | 2329 | if (spec->board_config < 0) { |
@@ -2256,8 +2358,8 @@ static struct hda_input_mux vaio_mux = { | |||
2256 | .num_items = 2, | 2358 | .num_items = 2, |
2257 | .items = { | 2359 | .items = { |
2258 | /* { "HP", 0x0 }, */ | 2360 | /* { "HP", 0x0 }, */ |
2259 | { "Line", 0x1 }, | 2361 | { "Mic Jack", 0x1 }, |
2260 | { "Mic", 0x2 }, | 2362 | { "Internal Mic", 0x2 }, |
2261 | { "PCM", 0x3 }, | 2363 | { "PCM", 0x3 }, |
2262 | } | 2364 | } |
2263 | }; | 2365 | }; |
@@ -2268,7 +2370,7 @@ static struct hda_verb vaio_init[] = { | |||
2268 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ | 2370 | {0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? (<- 0x2) */ |
2269 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 2371 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ |
2270 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | 2372 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ |
2271 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ | 2373 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ |
2272 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | 2374 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ |
2273 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | 2375 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ |
2274 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ | 2376 | {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* capture sw/vol -> 0x8 */ |
@@ -2284,7 +2386,7 @@ static struct hda_verb vaio_ar_init[] = { | |||
2284 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ | 2386 | {0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD */ |
2285 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ | 2387 | /* {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },*/ /* Optical Out */ |
2286 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ | 2388 | {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Mic? */ |
2287 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x2}, /* mic-sel: 0a,0d,14,02 */ | 2389 | {0x15, AC_VERB_SET_CONNECT_SEL, 0x1}, /* mic-sel: 0a,0d,14,02 */ |
2288 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ | 2390 | {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* HP */ |
2289 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ | 2391 | {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Speaker */ |
2290 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ | 2392 | /* {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},*/ /* Optical Out */ |
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c index 690ceb340644..d18a31e188a9 100644 --- a/sound/pci/ice1712/revo.c +++ b/sound/pci/ice1712/revo.c | |||
@@ -186,7 +186,12 @@ static int revo51_i2c_init(struct snd_ice1712 *ice, | |||
186 | #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } | 186 | #define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } |
187 | 187 | ||
188 | static const struct snd_akm4xxx_dac_channel revo71_front[] = { | 188 | static const struct snd_akm4xxx_dac_channel revo71_front[] = { |
189 | AK_DAC("PCM Playback Volume", 2) | 189 | { |
190 | .name = "PCM Playback Volume", | ||
191 | .num_channels = 2, | ||
192 | /* front channels DAC supports muting */ | ||
193 | .switch_name = "PCM Playback Switch", | ||
194 | }, | ||
190 | }; | 195 | }; |
191 | 196 | ||
192 | static const struct snd_akm4xxx_dac_channel revo71_surround[] = { | 197 | static const struct snd_akm4xxx_dac_channel revo71_surround[] = { |
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c index 03b3a4792f73..c7621bd770a6 100644 --- a/sound/pci/nm256/nm256.c +++ b/sound/pci/nm256/nm256.c | |||
@@ -1533,7 +1533,8 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci, | |||
1533 | printk(KERN_ERR " force the driver to load by " | 1533 | printk(KERN_ERR " force the driver to load by " |
1534 | "passing in the module parameter\n"); | 1534 | "passing in the module parameter\n"); |
1535 | printk(KERN_ERR " force_ac97=1\n"); | 1535 | printk(KERN_ERR " force_ac97=1\n"); |
1536 | printk(KERN_ERR " or try sb16 or cs423x drivers instead.\n"); | 1536 | printk(KERN_ERR " or try sb16, opl3sa2, or " |
1537 | "cs423x drivers instead.\n"); | ||
1537 | err = -ENXIO; | 1538 | err = -ENXIO; |
1538 | goto __error; | 1539 | goto __error; |
1539 | } | 1540 | } |
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c index bd7dbd267ed1..2de27405a0bd 100644 --- a/sound/pci/rme9652/rme9652.c +++ b/sound/pci/rme9652/rme9652.c | |||
@@ -406,7 +406,7 @@ static snd_pcm_uframes_t rme9652_hw_pointer(struct snd_rme9652 *rme9652) | |||
406 | } else if (!frag) | 406 | } else if (!frag) |
407 | return 0; | 407 | return 0; |
408 | offset -= rme9652->max_jitter; | 408 | offset -= rme9652->max_jitter; |
409 | if (offset < 0) | 409 | if ((int)offset < 0) |
410 | offset += period_size * 2; | 410 | offset += period_size * 2; |
411 | } else { | 411 | } else { |
412 | if (offset > period_size + rme9652->max_jitter) { | 412 | if (offset > period_size + rme9652->max_jitter) { |
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c index 50c9f92cfd1b..6ea09df0c73a 100644 --- a/sound/pci/via82xx.c +++ b/sound/pci/via82xx.c | |||
@@ -2098,7 +2098,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2098 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 2098 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
2099 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 2099 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
2100 | break; | 2100 | break; |
2101 | schedule_timeout_uninterruptible(1); | 2101 | schedule_timeout(1); |
2102 | } while (time_before(jiffies, end_time)); | 2102 | } while (time_before(jiffies, end_time)); |
2103 | 2103 | ||
2104 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 2104 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -2117,7 +2117,7 @@ static int snd_via82xx_chip_init(struct via82xx *chip) | |||
2117 | chip->ac97_secondary = 1; | 2117 | chip->ac97_secondary = 1; |
2118 | goto __ac97_ok2; | 2118 | goto __ac97_ok2; |
2119 | } | 2119 | } |
2120 | schedule_timeout_interruptible(1); | 2120 | schedule_timeout(1); |
2121 | } while (time_before(jiffies, end_time)); | 2121 | } while (time_before(jiffies, end_time)); |
2122 | /* This is ok, the most of motherboards have only one codec */ | 2122 | /* This is ok, the most of motherboards have only one codec */ |
2123 | 2123 | ||
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c index 8cbf8eba4ae9..72425e73abae 100644 --- a/sound/pci/via82xx_modem.c +++ b/sound/pci/via82xx_modem.c | |||
@@ -983,7 +983,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); | 983 | pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval); |
984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ | 984 | if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */ |
985 | break; | 985 | break; |
986 | schedule_timeout_uninterruptible(1); | 986 | schedule_timeout(1); |
987 | } while (time_before(jiffies, end_time)); | 987 | } while (time_before(jiffies, end_time)); |
988 | 988 | ||
989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) | 989 | if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY) |
@@ -1001,7 +1001,7 @@ static int snd_via82xx_chip_init(struct via82xx_modem *chip) | |||
1001 | chip->ac97_secondary = 1; | 1001 | chip->ac97_secondary = 1; |
1002 | goto __ac97_ok2; | 1002 | goto __ac97_ok2; |
1003 | } | 1003 | } |
1004 | schedule_timeout_interruptible(1); | 1004 | schedule_timeout(1); |
1005 | } while (time_before(jiffies, end_time)); | 1005 | } while (time_before(jiffies, end_time)); |
1006 | /* This is ok, the most of motherboards have only one codec */ | 1006 | /* This is ok, the most of motherboards have only one codec */ |
1007 | 1007 | ||
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig index a3fb1496e4dc..cacb0b136883 100644 --- a/sound/ppc/Kconfig +++ b/sound/ppc/Kconfig | |||
@@ -33,3 +33,23 @@ config SND_POWERMAC_AUTO_DRC | |||
33 | option. | 33 | option. |
34 | 34 | ||
35 | endmenu | 35 | endmenu |
36 | |||
37 | menu "ALSA PowerPC devices" | ||
38 | depends on SND!=n && ( PPC64 || PPC32 ) | ||
39 | |||
40 | config SND_PS3 | ||
41 | tristate "PS3 Audio support" | ||
42 | depends on SND && PS3_PS3AV | ||
43 | select SND_PCM | ||
44 | default m | ||
45 | help | ||
46 | Say Y here to include support for audio on the PS3 | ||
47 | |||
48 | To compile this driver as a module, choose M here: the module | ||
49 | will be called snd_ps3. | ||
50 | |||
51 | config SND_PS3_DEFAULT_START_DELAY | ||
52 | int "Startup delay time in ms" | ||
53 | depends on SND_PS3 | ||
54 | default "2000" | ||
55 | endmenu | ||
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile index 4d95c652c8ca..eacee2d0675c 100644 --- a/sound/ppc/Makefile +++ b/sound/ppc/Makefile | |||
@@ -6,4 +6,5 @@ | |||
6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o | 6 | snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o |
7 | 7 | ||
8 | # Toplevel Module Dependency | 8 | # Toplevel Module Dependency |
9 | obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o | 9 | obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o |
10 | obj-$(CONFIG_SND_PS3) += snd_ps3.o | ||
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c new file mode 100644 index 000000000000..1aa0b467599f --- /dev/null +++ b/sound/ppc/snd_ps3.c | |||
@@ -0,0 +1,1125 @@ | |||
1 | /* | ||
2 | * Audio support for PS3 | ||
3 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
4 | * All rights reserved. | ||
5 | * Copyright 2006, 2007 Sony Corporation | ||
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 | ||
9 | * as published by the Free Software Foundation; version 2 of the Licence. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #include <linux/init.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/io.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <sound/driver.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/initval.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/asound.h> | ||
30 | #include <sound/memalloc.h> | ||
31 | #include <sound/pcm_params.h> | ||
32 | #include <sound/control.h> | ||
33 | #include <linux/dmapool.h> | ||
34 | #include <linux/dma-mapping.h> | ||
35 | #include <asm/firmware.h> | ||
36 | #include <linux/io.h> | ||
37 | #include <asm/dma.h> | ||
38 | #include <asm/lv1call.h> | ||
39 | #include <asm/ps3.h> | ||
40 | #include <asm/ps3av.h> | ||
41 | |||
42 | #include "snd_ps3_reg.h" | ||
43 | #include "snd_ps3.h" | ||
44 | |||
45 | MODULE_LICENSE("GPL v2"); | ||
46 | MODULE_DESCRIPTION("PS3 sound driver"); | ||
47 | MODULE_AUTHOR("Sony Computer Entertainment Inc."); | ||
48 | |||
49 | /* module entries */ | ||
50 | static int __init snd_ps3_init(void); | ||
51 | static void __exit snd_ps3_exit(void); | ||
52 | |||
53 | /* ALSA snd driver ops */ | ||
54 | static int snd_ps3_pcm_open(struct snd_pcm_substream *substream); | ||
55 | static int snd_ps3_pcm_close(struct snd_pcm_substream *substream); | ||
56 | static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream); | ||
57 | static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, | ||
58 | int cmd); | ||
59 | static snd_pcm_uframes_t snd_ps3_pcm_pointer(struct snd_pcm_substream | ||
60 | *substream); | ||
61 | static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, | ||
62 | struct snd_pcm_hw_params *hw_params); | ||
63 | static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream); | ||
64 | |||
65 | |||
66 | /* ps3_system_bus_driver entries */ | ||
67 | static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev); | ||
68 | static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev); | ||
69 | |||
70 | /* address setup */ | ||
71 | static int snd_ps3_map_mmio(void); | ||
72 | static void snd_ps3_unmap_mmio(void); | ||
73 | static int snd_ps3_allocate_irq(void); | ||
74 | static void snd_ps3_free_irq(void); | ||
75 | static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start); | ||
76 | |||
77 | /* interrupt handler */ | ||
78 | static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id); | ||
79 | |||
80 | |||
81 | /* set sampling rate/format */ | ||
82 | static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream); | ||
83 | /* take effect parameter change */ | ||
84 | static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card); | ||
85 | /* initialize avsetting and take it effect */ | ||
86 | static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card); | ||
87 | /* setup dma */ | ||
88 | static int snd_ps3_program_dma(struct snd_ps3_card_info *card, | ||
89 | enum snd_ps3_dma_filltype filltype); | ||
90 | static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card); | ||
91 | |||
92 | static dma_addr_t v_to_bus(struct snd_ps3_card_info *, void *vaddr, int ch); | ||
93 | |||
94 | |||
95 | module_init(snd_ps3_init); | ||
96 | module_exit(snd_ps3_exit); | ||
97 | |||
98 | /* | ||
99 | * global | ||
100 | */ | ||
101 | static struct snd_ps3_card_info the_card; | ||
102 | |||
103 | static int snd_ps3_start_delay = CONFIG_SND_PS3_DEFAULT_START_DELAY; | ||
104 | |||
105 | module_param_named(start_delay, snd_ps3_start_delay, uint, 0644); | ||
106 | MODULE_PARM_DESC(start_delay, "time to insert silent data in milisec"); | ||
107 | |||
108 | static int index = SNDRV_DEFAULT_IDX1; | ||
109 | static char *id = SNDRV_DEFAULT_STR1; | ||
110 | |||
111 | module_param(index, int, 0444); | ||
112 | MODULE_PARM_DESC(index, "Index value for PS3 soundchip."); | ||
113 | module_param(id, charp, 0444); | ||
114 | MODULE_PARM_DESC(id, "ID string for PS3 soundchip."); | ||
115 | |||
116 | |||
117 | /* | ||
118 | * PS3 audio register access | ||
119 | */ | ||
120 | static inline u32 read_reg(unsigned int reg) | ||
121 | { | ||
122 | return in_be32(the_card.mapped_mmio_vaddr + reg); | ||
123 | } | ||
124 | static inline void write_reg(unsigned int reg, u32 val) | ||
125 | { | ||
126 | out_be32(the_card.mapped_mmio_vaddr + reg, val); | ||
127 | } | ||
128 | static inline void update_reg(unsigned int reg, u32 or_val) | ||
129 | { | ||
130 | u32 newval = read_reg(reg) | or_val; | ||
131 | write_reg(reg, newval); | ||
132 | } | ||
133 | static inline void update_mask_reg(unsigned int reg, u32 mask, u32 or_val) | ||
134 | { | ||
135 | u32 newval = (read_reg(reg) & mask) | or_val; | ||
136 | write_reg(reg, newval); | ||
137 | } | ||
138 | |||
139 | /* | ||
140 | * ALSA defs | ||
141 | */ | ||
142 | const static struct snd_pcm_hardware snd_ps3_pcm_hw = { | ||
143 | .info = (SNDRV_PCM_INFO_MMAP | | ||
144 | SNDRV_PCM_INFO_NONINTERLEAVED | | ||
145 | SNDRV_PCM_INFO_MMAP_VALID), | ||
146 | .formats = (SNDRV_PCM_FMTBIT_S16_BE | | ||
147 | SNDRV_PCM_FMTBIT_S24_BE), | ||
148 | .rates = (SNDRV_PCM_RATE_44100 | | ||
149 | SNDRV_PCM_RATE_48000 | | ||
150 | SNDRV_PCM_RATE_88200 | | ||
151 | SNDRV_PCM_RATE_96000), | ||
152 | .rate_min = 44100, | ||
153 | .rate_max = 96000, | ||
154 | |||
155 | .channels_min = 2, /* stereo only */ | ||
156 | .channels_max = 2, | ||
157 | |||
158 | .buffer_bytes_max = PS3_AUDIO_FIFO_SIZE * 64, | ||
159 | |||
160 | /* interrupt by four stages */ | ||
161 | .period_bytes_min = PS3_AUDIO_FIFO_STAGE_SIZE * 4, | ||
162 | .period_bytes_max = PS3_AUDIO_FIFO_STAGE_SIZE * 4, | ||
163 | |||
164 | .periods_min = 16, | ||
165 | .periods_max = 32, /* buffer_size_max/ period_bytes_max */ | ||
166 | |||
167 | .fifo_size = PS3_AUDIO_FIFO_SIZE | ||
168 | }; | ||
169 | |||
170 | static struct snd_pcm_ops snd_ps3_pcm_spdif_ops = | ||
171 | { | ||
172 | .open = snd_ps3_pcm_open, | ||
173 | .close = snd_ps3_pcm_close, | ||
174 | .prepare = snd_ps3_pcm_prepare, | ||
175 | .ioctl = snd_pcm_lib_ioctl, | ||
176 | .trigger = snd_ps3_pcm_trigger, | ||
177 | .pointer = snd_ps3_pcm_pointer, | ||
178 | .hw_params = snd_ps3_pcm_hw_params, | ||
179 | .hw_free = snd_ps3_pcm_hw_free | ||
180 | }; | ||
181 | |||
182 | static int snd_ps3_verify_dma_stop(struct snd_ps3_card_info *card, | ||
183 | int count, int force_stop) | ||
184 | { | ||
185 | int dma_ch, done, retries, stop_forced = 0; | ||
186 | uint32_t status; | ||
187 | |||
188 | for (dma_ch = 0; dma_ch < 8; dma_ch ++) { | ||
189 | retries = count; | ||
190 | do { | ||
191 | status = read_reg(PS3_AUDIO_KICK(dma_ch)) & | ||
192 | PS3_AUDIO_KICK_STATUS_MASK; | ||
193 | switch (status) { | ||
194 | case PS3_AUDIO_KICK_STATUS_DONE: | ||
195 | case PS3_AUDIO_KICK_STATUS_NOTIFY: | ||
196 | case PS3_AUDIO_KICK_STATUS_CLEAR: | ||
197 | case PS3_AUDIO_KICK_STATUS_ERROR: | ||
198 | done = 1; | ||
199 | break; | ||
200 | default: | ||
201 | done = 0; | ||
202 | udelay(10); | ||
203 | } | ||
204 | } while (!done && --retries); | ||
205 | if (!retries && force_stop) { | ||
206 | pr_info("%s: DMA ch %d is not stopped.", | ||
207 | __func__, dma_ch); | ||
208 | /* last resort. force to stop dma. | ||
209 | * NOTE: this cause DMA done interrupts | ||
210 | */ | ||
211 | update_reg(PS3_AUDIO_CONFIG, PS3_AUDIO_CONFIG_CLEAR); | ||
212 | stop_forced = 1; | ||
213 | } | ||
214 | } | ||
215 | return stop_forced; | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | * wait for all dma is done. | ||
220 | * NOTE: caller should reset card->running before call. | ||
221 | * If not, the interrupt handler will re-start DMA, | ||
222 | * then DMA is never stopped. | ||
223 | */ | ||
224 | static void snd_ps3_wait_for_dma_stop(struct snd_ps3_card_info *card) | ||
225 | { | ||
226 | int stop_forced; | ||
227 | /* | ||
228 | * wait for the last dma is done | ||
229 | */ | ||
230 | |||
231 | /* | ||
232 | * expected maximum DMA done time is 5.7ms + something (DMA itself). | ||
233 | * 5.7ms is from 16bit/sample 2ch 44.1Khz; the time next | ||
234 | * DMA kick event would occur. | ||
235 | */ | ||
236 | stop_forced = snd_ps3_verify_dma_stop(card, 700, 1); | ||
237 | |||
238 | /* | ||
239 | * clear outstanding interrupts. | ||
240 | */ | ||
241 | update_reg(PS3_AUDIO_INTR_0, 0); | ||
242 | update_reg(PS3_AUDIO_AX_IS, 0); | ||
243 | |||
244 | /* | ||
245 | *revert CLEAR bit since it will not reset automatically after DMA stop | ||
246 | */ | ||
247 | if (stop_forced) | ||
248 | update_mask_reg(PS3_AUDIO_CONFIG, ~PS3_AUDIO_CONFIG_CLEAR, 0); | ||
249 | /* ensure the hardware sees changes */ | ||
250 | wmb(); | ||
251 | } | ||
252 | |||
253 | static void snd_ps3_kick_dma(struct snd_ps3_card_info *card) | ||
254 | { | ||
255 | |||
256 | update_reg(PS3_AUDIO_KICK(0), PS3_AUDIO_KICK_REQUEST); | ||
257 | /* ensure the hardware sees the change */ | ||
258 | wmb(); | ||
259 | } | ||
260 | |||
261 | /* | ||
262 | * convert virtual addr to ioif bus addr. | ||
263 | */ | ||
264 | static dma_addr_t v_to_bus(struct snd_ps3_card_info *card, | ||
265 | void * paddr, | ||
266 | int ch) | ||
267 | { | ||
268 | return card->dma_start_bus_addr[ch] + | ||
269 | (paddr - card->dma_start_vaddr[ch]); | ||
270 | }; | ||
271 | |||
272 | |||
273 | /* | ||
274 | * increment ring buffer pointer. | ||
275 | * NOTE: caller must hold write spinlock | ||
276 | */ | ||
277 | static void snd_ps3_bump_buffer(struct snd_ps3_card_info *card, | ||
278 | enum snd_ps3_ch ch, size_t byte_count, | ||
279 | int stage) | ||
280 | { | ||
281 | if (!stage) | ||
282 | card->dma_last_transfer_vaddr[ch] = | ||
283 | card->dma_next_transfer_vaddr[ch]; | ||
284 | card->dma_next_transfer_vaddr[ch] += byte_count; | ||
285 | if ((card->dma_start_vaddr[ch] + (card->dma_buffer_size / 2)) <= | ||
286 | card->dma_next_transfer_vaddr[ch]) { | ||
287 | card->dma_next_transfer_vaddr[ch] = card->dma_start_vaddr[ch]; | ||
288 | } | ||
289 | } | ||
290 | /* | ||
291 | * setup dmac to send data to audio and attenuate samples on the ring buffer | ||
292 | */ | ||
293 | static int snd_ps3_program_dma(struct snd_ps3_card_info *card, | ||
294 | enum snd_ps3_dma_filltype filltype) | ||
295 | { | ||
296 | /* this dmac does not support over 4G */ | ||
297 | uint32_t dma_addr; | ||
298 | int fill_stages, dma_ch, stage; | ||
299 | enum snd_ps3_ch ch; | ||
300 | uint32_t ch0_kick_event = 0; /* initialize to mute gcc */ | ||
301 | void *start_vaddr; | ||
302 | unsigned long irqsave; | ||
303 | int silent = 0; | ||
304 | |||
305 | switch (filltype) { | ||
306 | case SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL: | ||
307 | silent = 1; | ||
308 | /* intentionally fall thru */ | ||
309 | case SND_PS3_DMA_FILLTYPE_FIRSTFILL: | ||
310 | ch0_kick_event = PS3_AUDIO_KICK_EVENT_ALWAYS; | ||
311 | break; | ||
312 | |||
313 | case SND_PS3_DMA_FILLTYPE_SILENT_RUNNING: | ||
314 | silent = 1; | ||
315 | /* intentionally fall thru */ | ||
316 | case SND_PS3_DMA_FILLTYPE_RUNNING: | ||
317 | ch0_kick_event = PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY; | ||
318 | break; | ||
319 | } | ||
320 | |||
321 | snd_ps3_verify_dma_stop(card, 700, 0); | ||
322 | fill_stages = 4; | ||
323 | spin_lock_irqsave(&card->dma_lock, irqsave); | ||
324 | for (ch = 0; ch < 2; ch++) { | ||
325 | start_vaddr = card->dma_next_transfer_vaddr[0]; | ||
326 | for (stage = 0; stage < fill_stages; stage ++) { | ||
327 | dma_ch = stage * 2 + ch; | ||
328 | if (silent) | ||
329 | dma_addr = card->null_buffer_start_dma_addr; | ||
330 | else | ||
331 | dma_addr = | ||
332 | v_to_bus(card, | ||
333 | card->dma_next_transfer_vaddr[ch], | ||
334 | ch); | ||
335 | |||
336 | write_reg(PS3_AUDIO_SOURCE(dma_ch), | ||
337 | (PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY | | ||
338 | dma_addr)); | ||
339 | |||
340 | /* dst: fixed to 3wire#0 */ | ||
341 | if (ch == 0) | ||
342 | write_reg(PS3_AUDIO_DEST(dma_ch), | ||
343 | (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | | ||
344 | PS3_AUDIO_AO_3W_LDATA(0))); | ||
345 | else | ||
346 | write_reg(PS3_AUDIO_DEST(dma_ch), | ||
347 | (PS3_AUDIO_DEST_TARGET_AUDIOFIFO | | ||
348 | PS3_AUDIO_AO_3W_RDATA(0))); | ||
349 | |||
350 | /* count always 1 DMA block (1/2 stage = 128 bytes) */ | ||
351 | write_reg(PS3_AUDIO_DMASIZE(dma_ch), 0); | ||
352 | /* bump pointer if needed */ | ||
353 | if (!silent) | ||
354 | snd_ps3_bump_buffer(card, ch, | ||
355 | PS3_AUDIO_DMAC_BLOCK_SIZE, | ||
356 | stage); | ||
357 | |||
358 | /* kick event */ | ||
359 | if (dma_ch == 0) | ||
360 | write_reg(PS3_AUDIO_KICK(dma_ch), | ||
361 | ch0_kick_event); | ||
362 | else | ||
363 | write_reg(PS3_AUDIO_KICK(dma_ch), | ||
364 | PS3_AUDIO_KICK_EVENT_AUDIO_DMA(dma_ch | ||
365 | - 1) | | ||
366 | PS3_AUDIO_KICK_REQUEST); | ||
367 | } | ||
368 | } | ||
369 | /* ensure the hardware sees the change */ | ||
370 | wmb(); | ||
371 | spin_unlock_irqrestore(&card->dma_lock, irqsave); | ||
372 | |||
373 | return 0; | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * audio mute on/off | ||
378 | * mute_on : 0 output enabled | ||
379 | * 1 mute | ||
380 | */ | ||
381 | static int snd_ps3_mute(int mute_on) | ||
382 | { | ||
383 | return ps3av_audio_mute(mute_on); | ||
384 | } | ||
385 | |||
386 | /* | ||
387 | * PCM operators | ||
388 | */ | ||
389 | static int snd_ps3_pcm_open(struct snd_pcm_substream *substream) | ||
390 | { | ||
391 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
392 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | ||
393 | int pcm_index; | ||
394 | |||
395 | pcm_index = substream->pcm->device; | ||
396 | /* to retrieve substream/runtime in interrupt handler */ | ||
397 | card->substream = substream; | ||
398 | |||
399 | runtime->hw = snd_ps3_pcm_hw; | ||
400 | |||
401 | card->start_delay = snd_ps3_start_delay; | ||
402 | |||
403 | /* mute off */ | ||
404 | snd_ps3_mute(0); /* this function sleep */ | ||
405 | |||
406 | snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, | ||
407 | PS3_AUDIO_FIFO_STAGE_SIZE * 4 * 2); | ||
408 | return 0; | ||
409 | }; | ||
410 | |||
411 | static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream, | ||
412 | struct snd_pcm_hw_params *hw_params) | ||
413 | { | ||
414 | size_t size; | ||
415 | |||
416 | /* alloc transport buffer */ | ||
417 | size = params_buffer_bytes(hw_params); | ||
418 | snd_pcm_lib_malloc_pages(substream, size); | ||
419 | return 0; | ||
420 | }; | ||
421 | |||
422 | static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream, | ||
423 | unsigned int delay_ms) | ||
424 | { | ||
425 | int ret; | ||
426 | int rate ; | ||
427 | |||
428 | rate = substream->runtime->rate; | ||
429 | ret = snd_pcm_format_size(substream->runtime->format, | ||
430 | rate * delay_ms / 1000) | ||
431 | * substream->runtime->channels; | ||
432 | |||
433 | pr_debug(KERN_ERR "%s: time=%d rate=%d bytes=%ld, frames=%d, ret=%d\n", | ||
434 | __func__, | ||
435 | delay_ms, | ||
436 | rate, | ||
437 | snd_pcm_format_size(substream->runtime->format, rate), | ||
438 | rate * delay_ms / 1000, | ||
439 | ret); | ||
440 | |||
441 | return ret; | ||
442 | }; | ||
443 | |||
444 | static int snd_ps3_pcm_prepare(struct snd_pcm_substream *substream) | ||
445 | { | ||
446 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
447 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | ||
448 | unsigned long irqsave; | ||
449 | |||
450 | if (!snd_ps3_set_avsetting(substream)) { | ||
451 | /* some parameter changed */ | ||
452 | write_reg(PS3_AUDIO_AX_IE, | ||
453 | PS3_AUDIO_AX_IE_ASOBEIE(0) | | ||
454 | PS3_AUDIO_AX_IE_ASOBUIE(0)); | ||
455 | /* | ||
456 | * let SPDIF device re-lock with SPDIF signal, | ||
457 | * start with some silence | ||
458 | */ | ||
459 | card->silent = snd_ps3_delay_to_bytes(substream, | ||
460 | card->start_delay) / | ||
461 | (PS3_AUDIO_FIFO_STAGE_SIZE * 4); /* every 4 times */ | ||
462 | } | ||
463 | |||
464 | /* restart ring buffer pointer */ | ||
465 | spin_lock_irqsave(&card->dma_lock, irqsave); | ||
466 | { | ||
467 | card->dma_buffer_size = runtime->dma_bytes; | ||
468 | |||
469 | card->dma_last_transfer_vaddr[SND_PS3_CH_L] = | ||
470 | card->dma_next_transfer_vaddr[SND_PS3_CH_L] = | ||
471 | card->dma_start_vaddr[SND_PS3_CH_L] = | ||
472 | runtime->dma_area; | ||
473 | card->dma_start_bus_addr[SND_PS3_CH_L] = runtime->dma_addr; | ||
474 | |||
475 | card->dma_last_transfer_vaddr[SND_PS3_CH_R] = | ||
476 | card->dma_next_transfer_vaddr[SND_PS3_CH_R] = | ||
477 | card->dma_start_vaddr[SND_PS3_CH_R] = | ||
478 | runtime->dma_area + (runtime->dma_bytes / 2); | ||
479 | card->dma_start_bus_addr[SND_PS3_CH_R] = | ||
480 | runtime->dma_addr + (runtime->dma_bytes / 2); | ||
481 | |||
482 | pr_debug("%s: vaddr=%p bus=%#lx\n", __func__, | ||
483 | card->dma_start_vaddr[SND_PS3_CH_L], | ||
484 | card->dma_start_bus_addr[SND_PS3_CH_L]); | ||
485 | |||
486 | } | ||
487 | spin_unlock_irqrestore(&card->dma_lock, irqsave); | ||
488 | |||
489 | /* ensure the hardware sees the change */ | ||
490 | mb(); | ||
491 | |||
492 | return 0; | ||
493 | }; | ||
494 | |||
495 | static int snd_ps3_pcm_trigger(struct snd_pcm_substream *substream, | ||
496 | int cmd) | ||
497 | { | ||
498 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | ||
499 | int ret = 0; | ||
500 | |||
501 | switch (cmd) { | ||
502 | case SNDRV_PCM_TRIGGER_START: | ||
503 | /* clear outstanding interrupts */ | ||
504 | update_reg(PS3_AUDIO_AX_IS, 0); | ||
505 | |||
506 | spin_lock(&card->dma_lock); | ||
507 | { | ||
508 | card->running = 1; | ||
509 | } | ||
510 | spin_unlock(&card->dma_lock); | ||
511 | |||
512 | snd_ps3_program_dma(card, | ||
513 | SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); | ||
514 | snd_ps3_kick_dma(card); | ||
515 | while (read_reg(PS3_AUDIO_KICK(7)) & | ||
516 | PS3_AUDIO_KICK_STATUS_MASK) { | ||
517 | udelay(1); | ||
518 | } | ||
519 | snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); | ||
520 | snd_ps3_kick_dma(card); | ||
521 | break; | ||
522 | |||
523 | case SNDRV_PCM_TRIGGER_STOP: | ||
524 | spin_lock(&card->dma_lock); | ||
525 | { | ||
526 | card->running = 0; | ||
527 | } | ||
528 | spin_unlock(&card->dma_lock); | ||
529 | snd_ps3_wait_for_dma_stop(card); | ||
530 | break; | ||
531 | default: | ||
532 | break; | ||
533 | |||
534 | } | ||
535 | |||
536 | return ret; | ||
537 | }; | ||
538 | |||
539 | /* | ||
540 | * report current pointer | ||
541 | */ | ||
542 | static snd_pcm_uframes_t snd_ps3_pcm_pointer( | ||
543 | struct snd_pcm_substream *substream) | ||
544 | { | ||
545 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | ||
546 | size_t bytes; | ||
547 | snd_pcm_uframes_t ret; | ||
548 | |||
549 | spin_lock(&card->dma_lock); | ||
550 | { | ||
551 | bytes = (size_t)(card->dma_last_transfer_vaddr[SND_PS3_CH_L] - | ||
552 | card->dma_start_vaddr[SND_PS3_CH_L]); | ||
553 | } | ||
554 | spin_unlock(&card->dma_lock); | ||
555 | |||
556 | ret = bytes_to_frames(substream->runtime, bytes * 2); | ||
557 | |||
558 | return ret; | ||
559 | }; | ||
560 | |||
561 | static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream) | ||
562 | { | ||
563 | int ret; | ||
564 | ret = snd_pcm_lib_free_pages(substream); | ||
565 | return ret; | ||
566 | }; | ||
567 | |||
568 | static int snd_ps3_pcm_close(struct snd_pcm_substream *substream) | ||
569 | { | ||
570 | /* mute on */ | ||
571 | snd_ps3_mute(1); | ||
572 | return 0; | ||
573 | }; | ||
574 | |||
575 | static void snd_ps3_audio_fixup(struct snd_ps3_card_info *card) | ||
576 | { | ||
577 | /* | ||
578 | * avsetting driver seems to never change the followings | ||
579 | * so, init them here once | ||
580 | */ | ||
581 | |||
582 | /* no dma interrupt needed */ | ||
583 | write_reg(PS3_AUDIO_INTR_EN_0, 0); | ||
584 | |||
585 | /* use every 4 buffer empty interrupt */ | ||
586 | update_mask_reg(PS3_AUDIO_AX_IC, | ||
587 | PS3_AUDIO_AX_IC_AASOIMD_MASK, | ||
588 | PS3_AUDIO_AX_IC_AASOIMD_EVERY4); | ||
589 | |||
590 | /* enable 3wire clocks */ | ||
591 | update_mask_reg(PS3_AUDIO_AO_3WMCTRL, | ||
592 | ~(PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED | | ||
593 | PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED), | ||
594 | 0); | ||
595 | update_reg(PS3_AUDIO_AO_3WMCTRL, | ||
596 | PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT); | ||
597 | } | ||
598 | |||
599 | /* | ||
600 | * av setting | ||
601 | * NOTE: calling this function may generate audio interrupt. | ||
602 | */ | ||
603 | static int snd_ps3_change_avsetting(struct snd_ps3_card_info *card) | ||
604 | { | ||
605 | int ret, retries, i; | ||
606 | pr_debug("%s: start\n", __func__); | ||
607 | |||
608 | ret = ps3av_set_audio_mode(card->avs.avs_audio_ch, | ||
609 | card->avs.avs_audio_rate, | ||
610 | card->avs.avs_audio_width, | ||
611 | card->avs.avs_audio_format, | ||
612 | card->avs.avs_audio_source); | ||
613 | /* | ||
614 | * Reset the following unwanted settings: | ||
615 | */ | ||
616 | |||
617 | /* disable all 3wire buffers */ | ||
618 | update_mask_reg(PS3_AUDIO_AO_3WMCTRL, | ||
619 | ~(PS3_AUDIO_AO_3WMCTRL_ASOEN(0) | | ||
620 | PS3_AUDIO_AO_3WMCTRL_ASOEN(1) | | ||
621 | PS3_AUDIO_AO_3WMCTRL_ASOEN(2) | | ||
622 | PS3_AUDIO_AO_3WMCTRL_ASOEN(3)), | ||
623 | 0); | ||
624 | wmb(); /* ensure the hardware sees the change */ | ||
625 | /* wait for actually stopped */ | ||
626 | retries = 1000; | ||
627 | while ((read_reg(PS3_AUDIO_AO_3WMCTRL) & | ||
628 | (PS3_AUDIO_AO_3WMCTRL_ASORUN(0) | | ||
629 | PS3_AUDIO_AO_3WMCTRL_ASORUN(1) | | ||
630 | PS3_AUDIO_AO_3WMCTRL_ASORUN(2) | | ||
631 | PS3_AUDIO_AO_3WMCTRL_ASORUN(3))) && | ||
632 | --retries) { | ||
633 | udelay(1); | ||
634 | } | ||
635 | |||
636 | /* reset buffer pointer */ | ||
637 | for (i = 0; i < 4; i++) { | ||
638 | update_reg(PS3_AUDIO_AO_3WCTRL(i), | ||
639 | PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET); | ||
640 | udelay(10); | ||
641 | } | ||
642 | wmb(); /* ensure the hardware actually start resetting */ | ||
643 | |||
644 | /* enable 3wire#0 buffer */ | ||
645 | update_reg(PS3_AUDIO_AO_3WMCTRL, PS3_AUDIO_AO_3WMCTRL_ASOEN(0)); | ||
646 | |||
647 | |||
648 | /* In 24bit mode,ALSA inserts a zero byte at first byte of per sample */ | ||
649 | update_mask_reg(PS3_AUDIO_AO_3WCTRL(0), | ||
650 | ~PS3_AUDIO_AO_3WCTRL_ASODF, | ||
651 | PS3_AUDIO_AO_3WCTRL_ASODF_LSB); | ||
652 | update_mask_reg(PS3_AUDIO_AO_SPDCTRL(0), | ||
653 | ~PS3_AUDIO_AO_SPDCTRL_SPODF, | ||
654 | PS3_AUDIO_AO_SPDCTRL_SPODF_LSB); | ||
655 | /* ensure all the setting above is written back to register */ | ||
656 | wmb(); | ||
657 | /* avsetting driver altered AX_IE, caller must reset it if you want */ | ||
658 | pr_debug("%s: end\n", __func__); | ||
659 | return ret; | ||
660 | } | ||
661 | |||
662 | static int snd_ps3_init_avsetting(struct snd_ps3_card_info *card) | ||
663 | { | ||
664 | int ret; | ||
665 | pr_debug("%s: start\n", __func__); | ||
666 | card->avs.avs_audio_ch = PS3AV_CMD_AUDIO_NUM_OF_CH_2; | ||
667 | card->avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; | ||
668 | card->avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; | ||
669 | card->avs.avs_audio_format = PS3AV_CMD_AUDIO_FORMAT_PCM; | ||
670 | card->avs.avs_audio_source = PS3AV_CMD_AUDIO_SOURCE_SERIAL; | ||
671 | |||
672 | ret = snd_ps3_change_avsetting(card); | ||
673 | |||
674 | snd_ps3_audio_fixup(card); | ||
675 | |||
676 | /* to start to generate SPDIF signal, fill data */ | ||
677 | snd_ps3_program_dma(card, SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); | ||
678 | snd_ps3_kick_dma(card); | ||
679 | pr_debug("%s: end\n", __func__); | ||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | /* | ||
684 | * set sampling rate according to the substream | ||
685 | */ | ||
686 | static int snd_ps3_set_avsetting(struct snd_pcm_substream *substream) | ||
687 | { | ||
688 | struct snd_ps3_card_info *card = snd_pcm_substream_chip(substream); | ||
689 | struct snd_ps3_avsetting_info avs; | ||
690 | |||
691 | avs = card->avs; | ||
692 | |||
693 | pr_debug("%s: called freq=%d width=%d\n", __func__, | ||
694 | substream->runtime->rate, | ||
695 | snd_pcm_format_width(substream->runtime->format)); | ||
696 | |||
697 | pr_debug("%s: before freq=%d width=%d\n", __func__, | ||
698 | card->avs.avs_audio_rate, card->avs.avs_audio_width); | ||
699 | |||
700 | /* sample rate */ | ||
701 | switch (substream->runtime->rate) { | ||
702 | case 44100: | ||
703 | avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_44K; | ||
704 | break; | ||
705 | case 48000: | ||
706 | avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_48K; | ||
707 | break; | ||
708 | case 88200: | ||
709 | avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_88K; | ||
710 | break; | ||
711 | case 96000: | ||
712 | avs.avs_audio_rate = PS3AV_CMD_AUDIO_FS_96K; | ||
713 | break; | ||
714 | default: | ||
715 | pr_info("%s: invalid rate %d\n", __func__, | ||
716 | substream->runtime->rate); | ||
717 | return 1; | ||
718 | } | ||
719 | |||
720 | /* width */ | ||
721 | switch (snd_pcm_format_width(substream->runtime->format)) { | ||
722 | case 16: | ||
723 | avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_16; | ||
724 | break; | ||
725 | case 24: | ||
726 | avs.avs_audio_width = PS3AV_CMD_AUDIO_WORD_BITS_24; | ||
727 | break; | ||
728 | default: | ||
729 | pr_info("%s: invalid width %d\n", __func__, | ||
730 | snd_pcm_format_width(substream->runtime->format)); | ||
731 | return 1; | ||
732 | } | ||
733 | |||
734 | if ((card->avs.avs_audio_width != avs.avs_audio_width) || | ||
735 | (card->avs.avs_audio_rate != avs.avs_audio_rate)) { | ||
736 | card->avs = avs; | ||
737 | snd_ps3_change_avsetting(card); | ||
738 | |||
739 | pr_debug("%s: after freq=%d width=%d\n", __func__, | ||
740 | card->avs.avs_audio_rate, card->avs.avs_audio_width); | ||
741 | |||
742 | return 0; | ||
743 | } else | ||
744 | return 1; | ||
745 | } | ||
746 | |||
747 | |||
748 | |||
749 | static int snd_ps3_map_mmio(void) | ||
750 | { | ||
751 | the_card.mapped_mmio_vaddr = | ||
752 | ioremap(the_card.ps3_dev->m_region->bus_addr, | ||
753 | the_card.ps3_dev->m_region->len); | ||
754 | |||
755 | if (!the_card.mapped_mmio_vaddr) { | ||
756 | pr_info("%s: ioremap 0 failed p=%#lx l=%#lx \n", | ||
757 | __func__, the_card.ps3_dev->m_region->lpar_addr, | ||
758 | the_card.ps3_dev->m_region->len); | ||
759 | return -ENXIO; | ||
760 | } | ||
761 | |||
762 | return 0; | ||
763 | }; | ||
764 | |||
765 | static void snd_ps3_unmap_mmio(void) | ||
766 | { | ||
767 | iounmap(the_card.mapped_mmio_vaddr); | ||
768 | the_card.mapped_mmio_vaddr = NULL; | ||
769 | } | ||
770 | |||
771 | static int snd_ps3_allocate_irq(void) | ||
772 | { | ||
773 | int ret; | ||
774 | u64 lpar_addr, lpar_size; | ||
775 | u64 __iomem *mapped; | ||
776 | |||
777 | /* FIXME: move this to device_init (H/W probe) */ | ||
778 | |||
779 | /* get irq outlet */ | ||
780 | ret = lv1_gpu_device_map(1, &lpar_addr, &lpar_size); | ||
781 | if (ret) { | ||
782 | pr_info("%s: device map 1 failed %d\n", __func__, | ||
783 | ret); | ||
784 | return -ENXIO; | ||
785 | } | ||
786 | |||
787 | mapped = ioremap(lpar_addr, lpar_size); | ||
788 | if (!mapped) { | ||
789 | pr_info("%s: ioremap 1 failed \n", __func__); | ||
790 | return -ENXIO; | ||
791 | } | ||
792 | |||
793 | the_card.audio_irq_outlet = in_be64(mapped); | ||
794 | |||
795 | iounmap(mapped); | ||
796 | ret = lv1_gpu_device_unmap(1); | ||
797 | if (ret) | ||
798 | pr_info("%s: unmap 1 failed\n", __func__); | ||
799 | |||
800 | /* irq */ | ||
801 | ret = ps3_irq_plug_setup(PS3_BINDING_CPU_ANY, | ||
802 | the_card.audio_irq_outlet, | ||
803 | &the_card.irq_no); | ||
804 | if (ret) { | ||
805 | pr_info("%s:ps3_alloc_irq failed (%d)\n", __func__, ret); | ||
806 | return ret; | ||
807 | } | ||
808 | |||
809 | ret = request_irq(the_card.irq_no, snd_ps3_interrupt, IRQF_DISABLED, | ||
810 | SND_PS3_DRIVER_NAME, &the_card); | ||
811 | if (ret) { | ||
812 | pr_info("%s: request_irq failed (%d)\n", __func__, ret); | ||
813 | goto cleanup_irq; | ||
814 | } | ||
815 | |||
816 | return 0; | ||
817 | |||
818 | cleanup_irq: | ||
819 | ps3_irq_plug_destroy(the_card.irq_no); | ||
820 | return ret; | ||
821 | }; | ||
822 | |||
823 | static void snd_ps3_free_irq(void) | ||
824 | { | ||
825 | free_irq(the_card.irq_no, &the_card); | ||
826 | ps3_irq_plug_destroy(the_card.irq_no); | ||
827 | } | ||
828 | |||
829 | static void snd_ps3_audio_set_base_addr(uint64_t ioaddr_start) | ||
830 | { | ||
831 | uint64_t val; | ||
832 | int ret; | ||
833 | |||
834 | val = (ioaddr_start & (0x0fUL << 32)) >> (32 - 20) | | ||
835 | (0x03UL << 24) | | ||
836 | (0x0fUL << 12) | | ||
837 | (PS3_AUDIO_IOID); | ||
838 | |||
839 | ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0); | ||
840 | if (ret) | ||
841 | pr_info("%s: gpu_attribute failed %d\n", __func__, | ||
842 | ret); | ||
843 | } | ||
844 | |||
845 | static int __init snd_ps3_driver_probe(struct ps3_system_bus_device *dev) | ||
846 | { | ||
847 | int ret; | ||
848 | u64 lpar_addr, lpar_size; | ||
849 | |||
850 | BUG_ON(!firmware_has_feature(FW_FEATURE_PS3_LV1)); | ||
851 | BUG_ON(dev->match_id != PS3_MATCH_ID_SOUND); | ||
852 | |||
853 | the_card.ps3_dev = dev; | ||
854 | |||
855 | ret = ps3_open_hv_device(dev); | ||
856 | |||
857 | if (ret) | ||
858 | return -ENXIO; | ||
859 | |||
860 | /* setup MMIO */ | ||
861 | ret = lv1_gpu_device_map(2, &lpar_addr, &lpar_size); | ||
862 | if (ret) { | ||
863 | pr_info("%s: device map 2 failed %d\n", __func__, ret); | ||
864 | goto clean_open; | ||
865 | } | ||
866 | ps3_mmio_region_init(dev, dev->m_region, lpar_addr, lpar_size, | ||
867 | PAGE_SHIFT); | ||
868 | |||
869 | ret = snd_ps3_map_mmio(); | ||
870 | if (ret) | ||
871 | goto clean_dev_map; | ||
872 | |||
873 | /* setup DMA area */ | ||
874 | ps3_dma_region_init(dev, dev->d_region, | ||
875 | PAGE_SHIFT, /* use system page size */ | ||
876 | 0, /* dma type; not used */ | ||
877 | NULL, | ||
878 | _ALIGN_UP(SND_PS3_DMA_REGION_SIZE, PAGE_SIZE)); | ||
879 | dev->d_region->ioid = PS3_AUDIO_IOID; | ||
880 | |||
881 | ret = ps3_dma_region_create(dev->d_region); | ||
882 | if (ret) { | ||
883 | pr_info("%s: region_create\n", __func__); | ||
884 | goto clean_mmio; | ||
885 | } | ||
886 | |||
887 | snd_ps3_audio_set_base_addr(dev->d_region->bus_addr); | ||
888 | |||
889 | /* CONFIG_SND_PS3_DEFAULT_START_DELAY */ | ||
890 | the_card.start_delay = snd_ps3_start_delay; | ||
891 | |||
892 | /* irq */ | ||
893 | if (snd_ps3_allocate_irq()) { | ||
894 | ret = -ENXIO; | ||
895 | goto clean_dma_region; | ||
896 | } | ||
897 | |||
898 | /* create card instance */ | ||
899 | the_card.card = snd_card_new(index, id, THIS_MODULE, 0); | ||
900 | if (!the_card.card) { | ||
901 | ret = -ENXIO; | ||
902 | goto clean_irq; | ||
903 | } | ||
904 | |||
905 | strcpy(the_card.card->driver, "PS3"); | ||
906 | strcpy(the_card.card->shortname, "PS3"); | ||
907 | strcpy(the_card.card->longname, "PS3 sound"); | ||
908 | /* create PCM devices instance */ | ||
909 | /* NOTE:this driver works assuming pcm:substream = 1:1 */ | ||
910 | ret = snd_pcm_new(the_card.card, | ||
911 | "SPDIF", | ||
912 | 0, /* instance index, will be stored pcm.device*/ | ||
913 | 1, /* output substream */ | ||
914 | 0, /* input substream */ | ||
915 | &(the_card.pcm)); | ||
916 | if (ret) | ||
917 | goto clean_card; | ||
918 | |||
919 | the_card.pcm->private_data = &the_card; | ||
920 | strcpy(the_card.pcm->name, "SPDIF"); | ||
921 | |||
922 | /* set pcm ops */ | ||
923 | snd_pcm_set_ops(the_card.pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
924 | &snd_ps3_pcm_spdif_ops); | ||
925 | |||
926 | the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED; | ||
927 | /* pre-alloc PCM DMA buffer*/ | ||
928 | ret = snd_pcm_lib_preallocate_pages_for_all(the_card.pcm, | ||
929 | SNDRV_DMA_TYPE_DEV, | ||
930 | &dev->core, | ||
931 | SND_PS3_PCM_PREALLOC_SIZE, | ||
932 | SND_PS3_PCM_PREALLOC_SIZE); | ||
933 | if (ret < 0) { | ||
934 | pr_info("%s: prealloc failed\n", __func__); | ||
935 | goto clean_card; | ||
936 | } | ||
937 | |||
938 | /* | ||
939 | * allocate null buffer | ||
940 | * its size should be lager than PS3_AUDIO_FIFO_STAGE_SIZE * 2 | ||
941 | * PAGE_SIZE is enogh | ||
942 | */ | ||
943 | if (!(the_card.null_buffer_start_vaddr = | ||
944 | dma_alloc_coherent(&the_card.ps3_dev->core, | ||
945 | PAGE_SIZE, | ||
946 | &the_card.null_buffer_start_dma_addr, | ||
947 | GFP_KERNEL))) { | ||
948 | pr_info("%s: nullbuffer alloc failed\n", __func__); | ||
949 | goto clean_preallocate; | ||
950 | } | ||
951 | pr_debug("%s: null vaddr=%p dma=%#lx\n", __func__, | ||
952 | the_card.null_buffer_start_vaddr, | ||
953 | the_card.null_buffer_start_dma_addr); | ||
954 | /* set default sample rate/word width */ | ||
955 | snd_ps3_init_avsetting(&the_card); | ||
956 | |||
957 | /* register the card */ | ||
958 | ret = snd_card_register(the_card.card); | ||
959 | if (ret < 0) | ||
960 | goto clean_dma_map; | ||
961 | |||
962 | pr_info("%s started. start_delay=%dms\n", | ||
963 | the_card.card->longname, the_card.start_delay); | ||
964 | return 0; | ||
965 | |||
966 | clean_dma_map: | ||
967 | dma_free_coherent(&the_card.ps3_dev->core, | ||
968 | PAGE_SIZE, | ||
969 | the_card.null_buffer_start_vaddr, | ||
970 | the_card.null_buffer_start_dma_addr); | ||
971 | clean_preallocate: | ||
972 | snd_pcm_lib_preallocate_free_for_all(the_card.pcm); | ||
973 | clean_card: | ||
974 | snd_card_free(the_card.card); | ||
975 | clean_irq: | ||
976 | snd_ps3_free_irq(); | ||
977 | clean_dma_region: | ||
978 | ps3_dma_region_free(dev->d_region); | ||
979 | clean_mmio: | ||
980 | snd_ps3_unmap_mmio(); | ||
981 | clean_dev_map: | ||
982 | lv1_gpu_device_unmap(2); | ||
983 | clean_open: | ||
984 | ps3_close_hv_device(dev); | ||
985 | /* | ||
986 | * there is no destructor function to pcm. | ||
987 | * midlayer automatically releases if the card removed | ||
988 | */ | ||
989 | return ret; | ||
990 | }; /* snd_ps3_probe */ | ||
991 | |||
992 | /* called when module removal */ | ||
993 | static int snd_ps3_driver_remove(struct ps3_system_bus_device *dev) | ||
994 | { | ||
995 | int ret; | ||
996 | pr_info("%s:start id=%d\n", __func__, dev->match_id); | ||
997 | if (dev->match_id != PS3_MATCH_ID_SOUND) | ||
998 | return -ENXIO; | ||
999 | |||
1000 | /* | ||
1001 | * ctl and preallocate buffer will be freed in | ||
1002 | * snd_card_free | ||
1003 | */ | ||
1004 | ret = snd_card_free(the_card.card); | ||
1005 | if (ret) | ||
1006 | pr_info("%s: ctl freecard=%d\n", __func__, ret); | ||
1007 | |||
1008 | dma_free_coherent(&dev->core, | ||
1009 | PAGE_SIZE, | ||
1010 | the_card.null_buffer_start_vaddr, | ||
1011 | the_card.null_buffer_start_dma_addr); | ||
1012 | |||
1013 | ps3_dma_region_free(dev->d_region); | ||
1014 | |||
1015 | snd_ps3_free_irq(); | ||
1016 | snd_ps3_unmap_mmio(); | ||
1017 | |||
1018 | lv1_gpu_device_unmap(2); | ||
1019 | ps3_close_hv_device(dev); | ||
1020 | pr_info("%s:end id=%d\n", __func__, dev->match_id); | ||
1021 | return 0; | ||
1022 | } /* snd_ps3_remove */ | ||
1023 | |||
1024 | static struct ps3_system_bus_driver snd_ps3_bus_driver_info = { | ||
1025 | .match_id = PS3_MATCH_ID_SOUND, | ||
1026 | .probe = snd_ps3_driver_probe, | ||
1027 | .remove = snd_ps3_driver_remove, | ||
1028 | .shutdown = snd_ps3_driver_remove, | ||
1029 | .core = { | ||
1030 | .name = SND_PS3_DRIVER_NAME, | ||
1031 | .owner = THIS_MODULE, | ||
1032 | }, | ||
1033 | }; | ||
1034 | |||
1035 | |||
1036 | /* | ||
1037 | * Interrupt handler | ||
1038 | */ | ||
1039 | static irqreturn_t snd_ps3_interrupt(int irq, void *dev_id) | ||
1040 | { | ||
1041 | |||
1042 | uint32_t port_intr; | ||
1043 | int underflow_occured = 0; | ||
1044 | struct snd_ps3_card_info *card = dev_id; | ||
1045 | |||
1046 | if (!card->running) { | ||
1047 | update_reg(PS3_AUDIO_AX_IS, 0); | ||
1048 | update_reg(PS3_AUDIO_INTR_0, 0); | ||
1049 | return IRQ_HANDLED; | ||
1050 | } | ||
1051 | |||
1052 | port_intr = read_reg(PS3_AUDIO_AX_IS); | ||
1053 | /* | ||
1054 | *serial buffer empty detected (every 4 times), | ||
1055 | *program next dma and kick it | ||
1056 | */ | ||
1057 | if (port_intr & PS3_AUDIO_AX_IE_ASOBEIE(0)) { | ||
1058 | write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBEIE(0)); | ||
1059 | if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { | ||
1060 | write_reg(PS3_AUDIO_AX_IS, port_intr); | ||
1061 | underflow_occured = 1; | ||
1062 | } | ||
1063 | if (card->silent) { | ||
1064 | /* we are still in silent time */ | ||
1065 | snd_ps3_program_dma(card, | ||
1066 | (underflow_occured) ? | ||
1067 | SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL : | ||
1068 | SND_PS3_DMA_FILLTYPE_SILENT_RUNNING); | ||
1069 | snd_ps3_kick_dma(card); | ||
1070 | card->silent --; | ||
1071 | } else { | ||
1072 | snd_ps3_program_dma(card, | ||
1073 | (underflow_occured) ? | ||
1074 | SND_PS3_DMA_FILLTYPE_FIRSTFILL : | ||
1075 | SND_PS3_DMA_FILLTYPE_RUNNING); | ||
1076 | snd_ps3_kick_dma(card); | ||
1077 | snd_pcm_period_elapsed(card->substream); | ||
1078 | } | ||
1079 | } else if (port_intr & PS3_AUDIO_AX_IE_ASOBUIE(0)) { | ||
1080 | write_reg(PS3_AUDIO_AX_IS, PS3_AUDIO_AX_IE_ASOBUIE(0)); | ||
1081 | /* | ||
1082 | * serial out underflow, but buffer empty not detected. | ||
1083 | * in this case, fill fifo with 0 to recover. After | ||
1084 | * filling dummy data, serial automatically start to | ||
1085 | * consume them and then will generate normal buffer | ||
1086 | * empty interrupts. | ||
1087 | * If both buffer underflow and buffer empty are occured, | ||
1088 | * it is better to do nomal data transfer than empty one | ||
1089 | */ | ||
1090 | snd_ps3_program_dma(card, | ||
1091 | SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); | ||
1092 | snd_ps3_kick_dma(card); | ||
1093 | snd_ps3_program_dma(card, | ||
1094 | SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL); | ||
1095 | snd_ps3_kick_dma(card); | ||
1096 | } | ||
1097 | /* clear interrupt cause */ | ||
1098 | return IRQ_HANDLED; | ||
1099 | }; | ||
1100 | |||
1101 | /* | ||
1102 | * module/subsystem initialize/terminate | ||
1103 | */ | ||
1104 | static int __init snd_ps3_init(void) | ||
1105 | { | ||
1106 | int ret; | ||
1107 | |||
1108 | if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) | ||
1109 | return -ENXIO; | ||
1110 | |||
1111 | memset(&the_card, 0, sizeof(the_card)); | ||
1112 | spin_lock_init(&the_card.dma_lock); | ||
1113 | |||
1114 | /* register systembus DRIVER, this calls our probe() func */ | ||
1115 | ret = ps3_system_bus_driver_register(&snd_ps3_bus_driver_info); | ||
1116 | |||
1117 | return ret; | ||
1118 | } | ||
1119 | |||
1120 | static void __exit snd_ps3_exit(void) | ||
1121 | { | ||
1122 | ps3_system_bus_driver_unregister(&snd_ps3_bus_driver_info); | ||
1123 | } | ||
1124 | |||
1125 | MODULE_ALIAS(PS3_MODULE_ALIAS_SOUND); | ||
diff --git a/sound/ppc/snd_ps3.h b/sound/ppc/snd_ps3.h new file mode 100644 index 000000000000..4b7e6fbbe500 --- /dev/null +++ b/sound/ppc/snd_ps3.h | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Audio support for PS3 | ||
3 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
4 | * All rights reserved. | ||
5 | * Copyright 2006, 2007 Sony Corporation | ||
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 | ||
9 | * as published by the Free Software Foundation; version 2 of the Licence. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | #if !defined(_SND_PS3_H_) | ||
22 | #define _SND_PS3_H_ | ||
23 | |||
24 | #include <linux/irqreturn.h> | ||
25 | |||
26 | #define SND_PS3_DRIVER_NAME "snd_ps3" | ||
27 | |||
28 | enum snd_ps3_out_channel { | ||
29 | SND_PS3_OUT_SPDIF_0, | ||
30 | SND_PS3_OUT_SPDIF_1, | ||
31 | SND_PS3_OUT_SERIAL_0, | ||
32 | SND_PS3_OUT_DEVS | ||
33 | }; | ||
34 | |||
35 | enum snd_ps3_dma_filltype { | ||
36 | SND_PS3_DMA_FILLTYPE_FIRSTFILL, | ||
37 | SND_PS3_DMA_FILLTYPE_RUNNING, | ||
38 | SND_PS3_DMA_FILLTYPE_SILENT_FIRSTFILL, | ||
39 | SND_PS3_DMA_FILLTYPE_SILENT_RUNNING | ||
40 | }; | ||
41 | |||
42 | enum snd_ps3_ch { | ||
43 | SND_PS3_CH_L = 0, | ||
44 | SND_PS3_CH_R = 1, | ||
45 | SND_PS3_CH_MAX = 2 | ||
46 | }; | ||
47 | |||
48 | struct snd_ps3_avsetting_info { | ||
49 | uint32_t avs_audio_ch; /* fixed */ | ||
50 | uint32_t avs_audio_rate; | ||
51 | uint32_t avs_audio_width; | ||
52 | uint32_t avs_audio_format; /* fixed */ | ||
53 | uint32_t avs_audio_source; /* fixed */ | ||
54 | }; | ||
55 | /* | ||
56 | * PS3 audio 'card' instance | ||
57 | * there should be only ONE hardware. | ||
58 | */ | ||
59 | struct snd_ps3_card_info { | ||
60 | struct ps3_system_bus_device *ps3_dev; | ||
61 | struct snd_card *card; | ||
62 | |||
63 | struct snd_pcm *pcm; | ||
64 | struct snd_pcm_substream *substream; | ||
65 | |||
66 | /* hvc info */ | ||
67 | u64 audio_lpar_addr; | ||
68 | u64 audio_lpar_size; | ||
69 | |||
70 | /* registers */ | ||
71 | void __iomem *mapped_mmio_vaddr; | ||
72 | |||
73 | /* irq */ | ||
74 | u64 audio_irq_outlet; | ||
75 | unsigned int irq_no; | ||
76 | |||
77 | /* remember avsetting */ | ||
78 | struct snd_ps3_avsetting_info avs; | ||
79 | |||
80 | /* dma buffer management */ | ||
81 | spinlock_t dma_lock; | ||
82 | /* dma_lock start */ | ||
83 | void * dma_start_vaddr[2]; /* 0 for L, 1 for R */ | ||
84 | dma_addr_t dma_start_bus_addr[2]; | ||
85 | size_t dma_buffer_size; | ||
86 | void * dma_last_transfer_vaddr[2]; | ||
87 | void * dma_next_transfer_vaddr[2]; | ||
88 | int silent; | ||
89 | /* dma_lock end */ | ||
90 | |||
91 | int running; | ||
92 | |||
93 | /* null buffer */ | ||
94 | void *null_buffer_start_vaddr; | ||
95 | dma_addr_t null_buffer_start_dma_addr; | ||
96 | |||
97 | /* start delay */ | ||
98 | unsigned int start_delay; | ||
99 | |||
100 | }; | ||
101 | |||
102 | |||
103 | /* PS3 audio DMAC block size in bytes */ | ||
104 | #define PS3_AUDIO_DMAC_BLOCK_SIZE (128) | ||
105 | /* one stage (stereo) of audio FIFO in bytes */ | ||
106 | #define PS3_AUDIO_FIFO_STAGE_SIZE (256) | ||
107 | /* how many stages the fifo have */ | ||
108 | #define PS3_AUDIO_FIFO_STAGE_COUNT (8) | ||
109 | /* fifo size 128 bytes * 8 stages * stereo (2ch) */ | ||
110 | #define PS3_AUDIO_FIFO_SIZE \ | ||
111 | (PS3_AUDIO_FIFO_STAGE_SIZE * PS3_AUDIO_FIFO_STAGE_COUNT) | ||
112 | |||
113 | /* PS3 audio DMAC max block count in one dma shot = 128 (0x80) blocks*/ | ||
114 | #define PS3_AUDIO_DMAC_MAX_BLOCKS (PS3_AUDIO_DMASIZE_BLOCKS_MASK + 1) | ||
115 | |||
116 | #define PS3_AUDIO_NORMAL_DMA_START_CH (0) | ||
117 | #define PS3_AUDIO_NORMAL_DMA_COUNT (8) | ||
118 | #define PS3_AUDIO_NULL_DMA_START_CH \ | ||
119 | (PS3_AUDIO_NORMAL_DMA_START_CH + PS3_AUDIO_NORMAL_DMA_COUNT) | ||
120 | #define PS3_AUDIO_NULL_DMA_COUNT (2) | ||
121 | |||
122 | #define SND_PS3_MAX_VOL (0x0F) | ||
123 | #define SND_PS3_MIN_VOL (0x00) | ||
124 | #define SND_PS3_MIN_ATT SND_PS3_MIN_VOL | ||
125 | #define SND_PS3_MAX_ATT SND_PS3_MAX_VOL | ||
126 | |||
127 | #define SND_PS3_PCM_PREALLOC_SIZE \ | ||
128 | (PS3_AUDIO_DMAC_BLOCK_SIZE * PS3_AUDIO_DMAC_MAX_BLOCKS * 4) | ||
129 | |||
130 | #define SND_PS3_DMA_REGION_SIZE \ | ||
131 | (SND_PS3_PCM_PREALLOC_SIZE + PAGE_SIZE) | ||
132 | |||
133 | #define PS3_AUDIO_IOID (1UL) | ||
134 | |||
135 | #endif /* _SND_PS3_H_ */ | ||
diff --git a/sound/ppc/snd_ps3_reg.h b/sound/ppc/snd_ps3_reg.h new file mode 100644 index 000000000000..03fdee4aaaf2 --- /dev/null +++ b/sound/ppc/snd_ps3_reg.h | |||
@@ -0,0 +1,891 @@ | |||
1 | /* | ||
2 | * Audio support for PS3 | ||
3 | * Copyright (C) 2007 Sony Computer Entertainment Inc. | ||
4 | * Copyright 2006, 2007 Sony Corporation | ||
5 | * All rights reserved. | ||
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 | ||
9 | * as published by the Free Software Foundation; version 2 of the License. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
19 | */ | ||
20 | |||
21 | /* | ||
22 | * interrupt / configure registers | ||
23 | */ | ||
24 | |||
25 | #define PS3_AUDIO_INTR_0 (0x00000100) | ||
26 | #define PS3_AUDIO_INTR_EN_0 (0x00000140) | ||
27 | #define PS3_AUDIO_CONFIG (0x00000200) | ||
28 | |||
29 | /* | ||
30 | * DMAC registers | ||
31 | * n:0..9 | ||
32 | */ | ||
33 | #define PS3_AUDIO_DMAC_REGBASE(x) (0x0000210 + 0x20 * (x)) | ||
34 | |||
35 | #define PS3_AUDIO_KICK(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x00) | ||
36 | #define PS3_AUDIO_SOURCE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x04) | ||
37 | #define PS3_AUDIO_DEST(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x08) | ||
38 | #define PS3_AUDIO_DMASIZE(n) (PS3_AUDIO_DMAC_REGBASE(n) + 0x0C) | ||
39 | |||
40 | /* | ||
41 | * mute control | ||
42 | */ | ||
43 | #define PS3_AUDIO_AX_MCTRL (0x00004000) | ||
44 | #define PS3_AUDIO_AX_ISBP (0x00004004) | ||
45 | #define PS3_AUDIO_AX_AOBP (0x00004008) | ||
46 | #define PS3_AUDIO_AX_IC (0x00004010) | ||
47 | #define PS3_AUDIO_AX_IE (0x00004014) | ||
48 | #define PS3_AUDIO_AX_IS (0x00004018) | ||
49 | |||
50 | /* | ||
51 | * three wire serial | ||
52 | * n:0..3 | ||
53 | */ | ||
54 | #define PS3_AUDIO_AO_MCTRL (0x00006000) | ||
55 | #define PS3_AUDIO_AO_3WMCTRL (0x00006004) | ||
56 | |||
57 | #define PS3_AUDIO_AO_3WCTRL(n) (0x00006200 + 0x200 * (n)) | ||
58 | |||
59 | /* | ||
60 | * S/PDIF | ||
61 | * n:0..1 | ||
62 | * x:0..11 | ||
63 | * y:0..5 | ||
64 | */ | ||
65 | #define PS3_AUDIO_AO_SPD_REGBASE(n) (0x00007200 + 0x200 * (n)) | ||
66 | |||
67 | #define PS3_AUDIO_AO_SPDCTRL(n) \ | ||
68 | (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x00) | ||
69 | #define PS3_AUDIO_AO_SPDUB(n, x) \ | ||
70 | (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x04 + 0x04 * (x)) | ||
71 | #define PS3_AUDIO_AO_SPDCS(n, y) \ | ||
72 | (PS3_AUDIO_AO_SPD_REGBASE(n) + 0x34 + 0x04 * (y)) | ||
73 | |||
74 | |||
75 | /* | ||
76 | PS3_AUDIO_INTR_0 register tells an interrupt handler which audio | ||
77 | DMA channel triggered the interrupt. The interrupt status for a channel | ||
78 | can be cleared by writing a '1' to the corresponding bit. A new interrupt | ||
79 | cannot be generated until the previous interrupt has been cleared. | ||
80 | |||
81 | Note that the status reported by PS3_AUDIO_INTR_0 is independent of the | ||
82 | value of PS3_AUDIO_INTR_EN_0. | ||
83 | |||
84 | 31 24 23 16 15 8 7 0 | ||
85 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
86 | |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_0 | ||
87 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
88 | */ | ||
89 | #define PS3_AUDIO_INTR_0_CHAN(n) (1 << ((n) * 2)) | ||
90 | #define PS3_AUDIO_INTR_0_CHAN9 PS3_AUDIO_INTR_0_CHAN(9) | ||
91 | #define PS3_AUDIO_INTR_0_CHAN8 PS3_AUDIO_INTR_0_CHAN(8) | ||
92 | #define PS3_AUDIO_INTR_0_CHAN7 PS3_AUDIO_INTR_0_CHAN(7) | ||
93 | #define PS3_AUDIO_INTR_0_CHAN6 PS3_AUDIO_INTR_0_CHAN(6) | ||
94 | #define PS3_AUDIO_INTR_0_CHAN5 PS3_AUDIO_INTR_0_CHAN(5) | ||
95 | #define PS3_AUDIO_INTR_0_CHAN4 PS3_AUDIO_INTR_0_CHAN(4) | ||
96 | #define PS3_AUDIO_INTR_0_CHAN3 PS3_AUDIO_INTR_0_CHAN(3) | ||
97 | #define PS3_AUDIO_INTR_0_CHAN2 PS3_AUDIO_INTR_0_CHAN(2) | ||
98 | #define PS3_AUDIO_INTR_0_CHAN1 PS3_AUDIO_INTR_0_CHAN(1) | ||
99 | #define PS3_AUDIO_INTR_0_CHAN0 PS3_AUDIO_INTR_0_CHAN(0) | ||
100 | |||
101 | /* | ||
102 | The PS3_AUDIO_INTR_EN_0 register specifies which DMA channels can generate | ||
103 | an interrupt to the PU. Each bit of PS3_AUDIO_INTR_EN_0 is ANDed with the | ||
104 | corresponding bit in PS3_AUDIO_INTR_0. The resulting bits are OR'd together | ||
105 | to generate the Audio interrupt. | ||
106 | |||
107 | 31 24 23 16 15 8 7 0 | ||
108 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
109 | |0 0 0 0 0 0 0 0 0 0 0 0 0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C|0|C| INTR_EN_0 | ||
110 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
111 | |||
112 | Bit assignments are same as PS3_AUDIO_INTR_0 | ||
113 | */ | ||
114 | |||
115 | /* | ||
116 | PS3_AUDIO_CONFIG | ||
117 | 31 24 23 16 15 8 7 0 | ||
118 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
119 | |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 C|0 0 0 0 0 0 0 0| CONFIG | ||
120 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
121 | |||
122 | */ | ||
123 | |||
124 | /* The CLEAR field cancels all pending transfers, and stops any running DMA | ||
125 | transfers. Any interrupts associated with the canceled transfers | ||
126 | will occur as if the transfer had finished. | ||
127 | Since this bit is designed to recover from DMA related issues | ||
128 | which are caused by unpredictable situations, it is prefered to wait | ||
129 | for normal DMA transfer end without using this bit. | ||
130 | */ | ||
131 | #define PS3_AUDIO_CONFIG_CLEAR (1 << 8) /* RWIVF */ | ||
132 | |||
133 | /* | ||
134 | PS3_AUDIO_AX_MCTRL: Audio Port Mute Control Register | ||
135 | |||
136 | 31 24 23 16 15 8 7 0 | ||
137 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
138 | |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|A|A|0 0 0 0 0 0 0|S|S|A|A|A|A| AX_MCTRL | ||
139 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
140 | */ | ||
141 | |||
142 | /* 3 Wire Audio Serial Output Channel Mutes (0..3) */ | ||
143 | #define PS3_AUDIO_AX_MCTRL_ASOMT(n) (1 << (3 - (n))) /* RWIVF */ | ||
144 | #define PS3_AUDIO_AX_MCTRL_ASO3MT (1 << 0) /* RWIVF */ | ||
145 | #define PS3_AUDIO_AX_MCTRL_ASO2MT (1 << 1) /* RWIVF */ | ||
146 | #define PS3_AUDIO_AX_MCTRL_ASO1MT (1 << 2) /* RWIVF */ | ||
147 | #define PS3_AUDIO_AX_MCTRL_ASO0MT (1 << 3) /* RWIVF */ | ||
148 | |||
149 | /* S/PDIF mutes (0,1)*/ | ||
150 | #define PS3_AUDIO_AX_MCTRL_SPOMT(n) (1 << (5 - (n))) /* RWIVF */ | ||
151 | #define PS3_AUDIO_AX_MCTRL_SPO1MT (1 << 4) /* RWIVF */ | ||
152 | #define PS3_AUDIO_AX_MCTRL_SPO0MT (1 << 5) /* RWIVF */ | ||
153 | |||
154 | /* All 3 Wire Serial Outputs Mute */ | ||
155 | #define PS3_AUDIO_AX_MCTRL_AASOMT (1 << 13) /* RWIVF */ | ||
156 | |||
157 | /* All S/PDIF Mute */ | ||
158 | #define PS3_AUDIO_AX_MCTRL_ASPOMT (1 << 14) /* RWIVF */ | ||
159 | |||
160 | /* All Audio Outputs Mute */ | ||
161 | #define PS3_AUDIO_AX_MCTRL_AAOMT (1 << 15) /* RWIVF */ | ||
162 | |||
163 | /* | ||
164 | S/PDIF Outputs Buffer Read/Write Pointer Register | ||
165 | |||
166 | 31 24 23 16 15 8 7 0 | ||
167 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
168 | |0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B|0 0 0 0 0 0 0 0|0|SPO0B|0|SPO1B| AX_ISBP | ||
169 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
170 | |||
171 | */ | ||
172 | /* | ||
173 | S/PDIF Output Channel Read Buffer Numbers | ||
174 | Buffer number is value of field. | ||
175 | Indicates current read access buffer ID from Audio Data | ||
176 | Transfer controller of S/PDIF Output | ||
177 | */ | ||
178 | |||
179 | #define PS3_AUDIO_AX_ISBP_SPOBRN_MASK(n) (0x7 << 4 * (1 - (n))) /* R-IUF */ | ||
180 | #define PS3_AUDIO_AX_ISBP_SPO1BRN_MASK (0x7 << 0) /* R-IUF */ | ||
181 | #define PS3_AUDIO_AX_ISBP_SPO0BRN_MASK (0x7 << 4) /* R-IUF */ | ||
182 | |||
183 | /* | ||
184 | S/PDIF Output Channel Buffer Write Numbers | ||
185 | Indicates current write access buffer ID from bus master. | ||
186 | */ | ||
187 | #define PS3_AUDIO_AX_ISBP_SPOBWN_MASK(n) (0x7 << 4 * (5 - (n))) /* R-IUF */ | ||
188 | #define PS3_AUDIO_AX_ISBP_SPO1BWN_MASK (0x7 << 16) /* R-IUF */ | ||
189 | #define PS3_AUDIO_AX_ISBP_SPO0BWN_MASK (0x7 << 20) /* R-IUF */ | ||
190 | |||
191 | /* | ||
192 | 3 Wire Audio Serial Outputs Buffer Read/Write | ||
193 | Pointer Register | ||
194 | Buffer number is value of field | ||
195 | |||
196 | 31 24 23 16 15 8 7 0 | ||
197 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
198 | |0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B|0|ASO0B|0|ASO1B|0|ASO2B|0|ASO3B| AX_AOBP | ||
199 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
200 | */ | ||
201 | |||
202 | /* | ||
203 | 3 Wire Audio Serial Output Channel Buffer Read Numbers | ||
204 | Indicates current read access buffer Id from Audio Data Transfer | ||
205 | Controller of 3 Wire Audio Serial Output Channels | ||
206 | */ | ||
207 | #define PS3_AUDIO_AX_AOBP_ASOBRN_MASK(n) (0x7 << 4 * (3 - (n))) /* R-IUF */ | ||
208 | |||
209 | #define PS3_AUDIO_AX_AOBP_ASO3BRN_MASK (0x7 << 0) /* R-IUF */ | ||
210 | #define PS3_AUDIO_AX_AOBP_ASO2BRN_MASK (0x7 << 4) /* R-IUF */ | ||
211 | #define PS3_AUDIO_AX_AOBP_ASO1BRN_MASK (0x7 << 8) /* R-IUF */ | ||
212 | #define PS3_AUDIO_AX_AOBP_ASO0BRN_MASK (0x7 << 12) /* R-IUF */ | ||
213 | |||
214 | /* | ||
215 | 3 Wire Audio Serial Output Channel Buffer Write Numbers | ||
216 | Indicates current write access buffer ID from bus master. | ||
217 | */ | ||
218 | #define PS3_AUDIO_AX_AOBP_ASOBWN_MASK(n) (0x7 << 4 * (7 - (n))) /* R-IUF */ | ||
219 | |||
220 | #define PS3_AUDIO_AX_AOBP_ASO3BWN_MASK (0x7 << 16) /* R-IUF */ | ||
221 | #define PS3_AUDIO_AX_AOBP_ASO2BWN_MASK (0x7 << 20) /* R-IUF */ | ||
222 | #define PS3_AUDIO_AX_AOBP_ASO1BWN_MASK (0x7 << 24) /* R-IUF */ | ||
223 | #define PS3_AUDIO_AX_AOBP_ASO0BWN_MASK (0x7 << 28) /* R-IUF */ | ||
224 | |||
225 | |||
226 | |||
227 | /* | ||
228 | Audio Port Interrupt Condition Register | ||
229 | For the fields in this register, the following values apply: | ||
230 | 0 = Interrupt is generated every interrupt event. | ||
231 | 1 = Interrupt is generated every 2 interrupt events. | ||
232 | 2 = Interrupt is generated every 4 interrupt events. | ||
233 | 3 = Reserved | ||
234 | |||
235 | |||
236 | 31 24 23 16 15 8 7 0 | ||
237 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
238 | |0 0 0 0 0 0 0 0|0 0|SPO|0 0|SPO|0 0|AAS|0 0 0 0 0 0 0 0 0 0 0 0| AX_IC | ||
239 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
240 | */ | ||
241 | /* | ||
242 | All 3-Wire Audio Serial Outputs Interrupt Mode | ||
243 | Configures the Interrupt and Signal Notification | ||
244 | condition of all 3-wire Audio Serial Outputs. | ||
245 | */ | ||
246 | #define PS3_AUDIO_AX_IC_AASOIMD_MASK (0x3 << 12) /* RWIVF */ | ||
247 | #define PS3_AUDIO_AX_IC_AASOIMD_EVERY1 (0x0 << 12) /* RWI-V */ | ||
248 | #define PS3_AUDIO_AX_IC_AASOIMD_EVERY2 (0x1 << 12) /* RW--V */ | ||
249 | #define PS3_AUDIO_AX_IC_AASOIMD_EVERY4 (0x2 << 12) /* RW--V */ | ||
250 | |||
251 | /* | ||
252 | S/PDIF Output Channel Interrupt Modes | ||
253 | Configures the Interrupt and signal Notification | ||
254 | conditions of S/PDIF output channels. | ||
255 | */ | ||
256 | #define PS3_AUDIO_AX_IC_SPO1IMD_MASK (0x3 << 16) /* RWIVF */ | ||
257 | #define PS3_AUDIO_AX_IC_SPO1IMD_EVERY1 (0x0 << 16) /* RWI-V */ | ||
258 | #define PS3_AUDIO_AX_IC_SPO1IMD_EVERY2 (0x1 << 16) /* RW--V */ | ||
259 | #define PS3_AUDIO_AX_IC_SPO1IMD_EVERY4 (0x2 << 16) /* RW--V */ | ||
260 | |||
261 | #define PS3_AUDIO_AX_IC_SPO0IMD_MASK (0x3 << 20) /* RWIVF */ | ||
262 | #define PS3_AUDIO_AX_IC_SPO0IMD_EVERY1 (0x0 << 20) /* RWI-V */ | ||
263 | #define PS3_AUDIO_AX_IC_SPO0IMD_EVERY2 (0x1 << 20) /* RW--V */ | ||
264 | #define PS3_AUDIO_AX_IC_SPO0IMD_EVERY4 (0x2 << 20) /* RW--V */ | ||
265 | |||
266 | /* | ||
267 | Audio Port interrupt Enable Register | ||
268 | Configures whether to enable or disable each Interrupt Generation. | ||
269 | |||
270 | |||
271 | 31 24 23 16 15 8 7 0 | ||
272 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
273 | |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IE | ||
274 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
275 | |||
276 | */ | ||
277 | |||
278 | /* | ||
279 | 3 Wire Audio Serial Output Channel Buffer Underflow | ||
280 | Interrupt Enables | ||
281 | Select enable/disable of Buffer Underflow Interrupts for | ||
282 | 3-Wire Audio Serial Output Channels | ||
283 | DISABLED=Interrupt generation disabled. | ||
284 | */ | ||
285 | #define PS3_AUDIO_AX_IE_ASOBUIE(n) (1 << (3 - (n))) /* RWIVF */ | ||
286 | #define PS3_AUDIO_AX_IE_ASO3BUIE (1 << 0) /* RWIVF */ | ||
287 | #define PS3_AUDIO_AX_IE_ASO2BUIE (1 << 1) /* RWIVF */ | ||
288 | #define PS3_AUDIO_AX_IE_ASO1BUIE (1 << 2) /* RWIVF */ | ||
289 | #define PS3_AUDIO_AX_IE_ASO0BUIE (1 << 3) /* RWIVF */ | ||
290 | |||
291 | /* S/PDIF Output Channel Buffer Underflow Interrupt Enables */ | ||
292 | |||
293 | #define PS3_AUDIO_AX_IE_SPOBUIE(n) (1 << (7 - (n))) /* RWIVF */ | ||
294 | #define PS3_AUDIO_AX_IE_SPO1BUIE (1 << 6) /* RWIVF */ | ||
295 | #define PS3_AUDIO_AX_IE_SPO0BUIE (1 << 7) /* RWIVF */ | ||
296 | |||
297 | /* S/PDIF Output Channel One Block Transfer Completion Interrupt Enables */ | ||
298 | |||
299 | #define PS3_AUDIO_AX_IE_SPOBTCIE(n) (1 << (11 - (n))) /* RWIVF */ | ||
300 | #define PS3_AUDIO_AX_IE_SPO1BTCIE (1 << 10) /* RWIVF */ | ||
301 | #define PS3_AUDIO_AX_IE_SPO0BTCIE (1 << 11) /* RWIVF */ | ||
302 | |||
303 | /* 3-Wire Audio Serial Output Channel Buffer Empty Interrupt Enables */ | ||
304 | |||
305 | #define PS3_AUDIO_AX_IE_ASOBEIE(n) (1 << (19 - (n))) /* RWIVF */ | ||
306 | #define PS3_AUDIO_AX_IE_ASO3BEIE (1 << 16) /* RWIVF */ | ||
307 | #define PS3_AUDIO_AX_IE_ASO2BEIE (1 << 17) /* RWIVF */ | ||
308 | #define PS3_AUDIO_AX_IE_ASO1BEIE (1 << 18) /* RWIVF */ | ||
309 | #define PS3_AUDIO_AX_IE_ASO0BEIE (1 << 19) /* RWIVF */ | ||
310 | |||
311 | /* S/PDIF Output Channel Buffer Empty Interrupt Enables */ | ||
312 | |||
313 | #define PS3_AUDIO_AX_IE_SPOBEIE(n) (1 << (23 - (n))) /* RWIVF */ | ||
314 | #define PS3_AUDIO_AX_IE_SPO1BEIE (1 << 22) /* RWIVF */ | ||
315 | #define PS3_AUDIO_AX_IE_SPO0BEIE (1 << 23) /* RWIVF */ | ||
316 | |||
317 | /* | ||
318 | Audio Port Interrupt Status Register | ||
319 | Indicates Interrupt status, which interrupt has occured, and can clear | ||
320 | each interrupt in this register. | ||
321 | Writing 1b to a field containing 1b clears field and de-asserts interrupt. | ||
322 | Writing 0b to a field has no effect. | ||
323 | Field vaules are the following: | ||
324 | 0 - Interrupt hasn't occured. | ||
325 | 1 - Interrupt has occured. | ||
326 | |||
327 | |||
328 | 31 24 23 16 15 8 7 0 | ||
329 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
330 | |0 0 0 0 0 0 0 0|S|S|0 0|A|A|A|A|0 0 0 0|S|S|0 0|S|S|0 0|A|A|A|A| AX_IS | ||
331 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
332 | |||
333 | Bit assignment are same as AX_IE | ||
334 | */ | ||
335 | |||
336 | /* | ||
337 | Audio Output Master Control Register | ||
338 | Configures Master Clock and other master Audio Output Settings | ||
339 | |||
340 | |||
341 | 31 24 23 16 15 8 7 0 | ||
342 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
343 | |0|SCKSE|0|SCKSE| MR0 | MR1 |MCL|MCL|0 0 0 0|0 0 0 0 0 0 0 0| AO_MCTRL | ||
344 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
345 | */ | ||
346 | |||
347 | /* | ||
348 | MCLK Output Control | ||
349 | Controls mclko[1] output. | ||
350 | 0 - Disable output (fixed at High) | ||
351 | 1 - Output clock produced by clock selected | ||
352 | with scksel1 by mr1 | ||
353 | 2 - Reserved | ||
354 | 3 - Reserved | ||
355 | */ | ||
356 | |||
357 | #define PS3_AUDIO_AO_MCTRL_MCLKC1_MASK (0x3 << 12) /* RWIVF */ | ||
358 | #define PS3_AUDIO_AO_MCTRL_MCLKC1_DISABLED (0x0 << 12) /* RWI-V */ | ||
359 | #define PS3_AUDIO_AO_MCTRL_MCLKC1_ENABLED (0x1 << 12) /* RW--V */ | ||
360 | #define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD2 (0x2 << 12) /* RW--V */ | ||
361 | #define PS3_AUDIO_AO_MCTRL_MCLKC1_RESVD3 (0x3 << 12) /* RW--V */ | ||
362 | |||
363 | /* | ||
364 | MCLK Output Control | ||
365 | Controls mclko[0] output. | ||
366 | 0 - Disable output (fixed at High) | ||
367 | 1 - Output clock produced by clock selected | ||
368 | with SCKSEL0 by MR0 | ||
369 | 2 - Reserved | ||
370 | 3 - Reserved | ||
371 | */ | ||
372 | #define PS3_AUDIO_AO_MCTRL_MCLKC0_MASK (0x3 << 14) /* RWIVF */ | ||
373 | #define PS3_AUDIO_AO_MCTRL_MCLKC0_DISABLED (0x0 << 14) /* RWI-V */ | ||
374 | #define PS3_AUDIO_AO_MCTRL_MCLKC0_ENABLED (0x1 << 14) /* RW--V */ | ||
375 | #define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD2 (0x2 << 14) /* RW--V */ | ||
376 | #define PS3_AUDIO_AO_MCTRL_MCLKC0_RESVD3 (0x3 << 14) /* RW--V */ | ||
377 | /* | ||
378 | Master Clock Rate 1 | ||
379 | Sets the divide ration of Master Clock1 (clock output from | ||
380 | mclko[1] for the input clock selected by scksel1. | ||
381 | */ | ||
382 | #define PS3_AUDIO_AO_MCTRL_MR1_MASK (0xf << 16) | ||
383 | #define PS3_AUDIO_AO_MCTRL_MR1_DEFAULT (0x0 << 16) /* RWI-V */ | ||
384 | /* | ||
385 | Master Clock Rate 0 | ||
386 | Sets the divide ratio of Master Clock0 (clock output from | ||
387 | mclko[0] for the input clock selected by scksel0). | ||
388 | */ | ||
389 | #define PS3_AUDIO_AO_MCTRL_MR0_MASK (0xf << 20) /* RWIVF */ | ||
390 | #define PS3_AUDIO_AO_MCTRL_MR0_DEFAULT (0x0 << 20) /* RWI-V */ | ||
391 | /* | ||
392 | System Clock Select 0/1 | ||
393 | Selects the system clock to be used as Master Clock 0/1 | ||
394 | Input the system clock that is appropriate for the sampling | ||
395 | rate. | ||
396 | */ | ||
397 | #define PS3_AUDIO_AO_MCTRL_SCKSEL1_MASK (0x7 << 24) /* RWIVF */ | ||
398 | #define PS3_AUDIO_AO_MCTRL_SCKSEL1_DEFAULT (0x2 << 24) /* RWI-V */ | ||
399 | |||
400 | #define PS3_AUDIO_AO_MCTRL_SCKSEL0_MASK (0x7 << 28) /* RWIVF */ | ||
401 | #define PS3_AUDIO_AO_MCTRL_SCKSEL0_DEFAULT (0x2 << 28) /* RWI-V */ | ||
402 | |||
403 | |||
404 | /* | ||
405 | 3-Wire Audio Output Master Control Register | ||
406 | Configures clock, 3-Wire Audio Serial Output Enable, and | ||
407 | other 3-Wire Audio Serial Output Master Settings | ||
408 | |||
409 | |||
410 | 31 24 23 16 15 8 7 0 | ||
411 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
412 | |A|A|A|A|0 0 0|A| ASOSR |0 0 0 0|A|A|A|A|A|A|0|1|0 0 0 0 0 0 0 0| AO_3WMCTRL | ||
413 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
414 | */ | ||
415 | |||
416 | |||
417 | /* | ||
418 | LRCKO Polarity | ||
419 | 0 - Reserved | ||
420 | 1 - default | ||
421 | */ | ||
422 | #define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK (1 << 8) /* RWIVF */ | ||
423 | #define PS3_AUDIO_AO_3WMCTRL_ASOPLRCK_DEFAULT (1 << 8) /* RW--V */ | ||
424 | |||
425 | /* LRCK Output Disable */ | ||
426 | |||
427 | #define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD (1 << 10) /* RWIVF */ | ||
428 | #define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_ENABLED (0 << 10) /* RW--V */ | ||
429 | #define PS3_AUDIO_AO_3WMCTRL_ASOLRCKD_DISABLED (1 << 10) /* RWI-V */ | ||
430 | |||
431 | /* Bit Clock Output Disable */ | ||
432 | |||
433 | #define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD (1 << 11) /* RWIVF */ | ||
434 | #define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_ENABLED (0 << 11) /* RW--V */ | ||
435 | #define PS3_AUDIO_AO_3WMCTRL_ASOBCLKD_DISABLED (1 << 11) /* RWI-V */ | ||
436 | |||
437 | /* | ||
438 | 3-Wire Audio Serial Output Channel 0-3 Operational | ||
439 | Status. Each bit becomes 1 after each 3-Wire Audio | ||
440 | Serial Output Channel N is in action by setting 1 to | ||
441 | asoen. | ||
442 | Each bit becomes 0 after each 3-Wire Audio Serial Output | ||
443 | Channel N is out of action by setting 0 to asoen. | ||
444 | */ | ||
445 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN(n) (1 << (15 - (n))) /* R-IVF */ | ||
446 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(n) (0 << (15 - (n))) /* R-I-V */ | ||
447 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(n) (1 << (15 - (n))) /* R---V */ | ||
448 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN0 \ | ||
449 | PS3_AUDIO_AO_3WMCTRL_ASORUN(0) | ||
450 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN0_STOPPED \ | ||
451 | PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(0) | ||
452 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN0_RUNNING \ | ||
453 | PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(0) | ||
454 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN1 \ | ||
455 | PS3_AUDIO_AO_3WMCTRL_ASORUN(1) | ||
456 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN1_STOPPED \ | ||
457 | PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(1) | ||
458 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN1_RUNNING \ | ||
459 | PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(1) | ||
460 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN2 \ | ||
461 | PS3_AUDIO_AO_3WMCTRL_ASORUN(2) | ||
462 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN2_STOPPED \ | ||
463 | PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(2) | ||
464 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN2_RUNNING \ | ||
465 | PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(2) | ||
466 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN3 \ | ||
467 | PS3_AUDIO_AO_3WMCTRL_ASORUN(3) | ||
468 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN3_STOPPED \ | ||
469 | PS3_AUDIO_AO_3WMCTRL_ASORUN_STOPPED(3) | ||
470 | #define PS3_AUDIO_AO_3WMCTRL_ASORUN3_RUNNING \ | ||
471 | PS3_AUDIO_AO_3WMCTRL_ASORUN_RUNNING(3) | ||
472 | |||
473 | /* | ||
474 | Sampling Rate | ||
475 | Specifies the divide ratio of the bit clock (clock output | ||
476 | from bclko) used by the 3-wire Audio Output Clock, whcih | ||
477 | is applied to the master clock selected by mcksel. | ||
478 | Data output is synchronized with this clock. | ||
479 | */ | ||
480 | #define PS3_AUDIO_AO_3WMCTRL_ASOSR_MASK (0xf << 20) /* RWIVF */ | ||
481 | #define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV2 (0x1 << 20) /* RWI-V */ | ||
482 | #define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV4 (0x2 << 20) /* RW--V */ | ||
483 | #define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV8 (0x4 << 20) /* RW--V */ | ||
484 | #define PS3_AUDIO_AO_3WMCTRL_ASOSR_DIV12 (0x6 << 20) /* RW--V */ | ||
485 | |||
486 | /* | ||
487 | Master Clock Select | ||
488 | 0 - Master Clock 0 | ||
489 | 1 - Master Clock 1 | ||
490 | */ | ||
491 | #define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL (1 << 24) /* RWIVF */ | ||
492 | #define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK0 (0 << 24) /* RWI-V */ | ||
493 | #define PS3_AUDIO_AO_3WMCTRL_ASOMCKSEL_CLK1 (1 << 24) /* RW--V */ | ||
494 | |||
495 | /* | ||
496 | Enables and disables 4ch 3-Wire Audio Serial Output | ||
497 | operation. Each Bit from 0 to 3 corresponds to an | ||
498 | output channel, which means that each output channel | ||
499 | can be enabled or disabled individually. When | ||
500 | multiple channels are enabled at the same time, output | ||
501 | operations are performed in synchronization. | ||
502 | Bit 0 - Output Channel 0 (SDOUT[0]) | ||
503 | Bit 1 - Output Channel 1 (SDOUT[1]) | ||
504 | Bit 2 - Output Channel 2 (SDOUT[2]) | ||
505 | Bit 3 - Output Channel 3 (SDOUT[3]) | ||
506 | */ | ||
507 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN(n) (1 << (31 - (n))) /* RWIVF */ | ||
508 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(n) (0 << (31 - (n))) /* RWI-V */ | ||
509 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(n) (1 << (31 - (n))) /* RW--V */ | ||
510 | |||
511 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN0 \ | ||
512 | PS3_AUDIO_AO_3WMCTRL_ASOEN(0) /* RWIVF */ | ||
513 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN0_DISABLED \ | ||
514 | PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(0) /* RWI-V */ | ||
515 | #define PS3_AUDIO_AO_3WMCTRL_ASOEN0_ENABLED \ | ||
516 | PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(0) /* RW--V */ | ||
517 | #define PS3_AUDIO_A1_3WMCTRL_ASOEN0 \ | ||
518 | PS3_AUDIO_AO_3WMCTRL_ASOEN(1) /* RWIVF */ | ||
519 | #define PS3_AUDIO_A1_3WMCTRL_ASOEN0_DISABLED \ | ||
520 | PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(1) /* RWI-V */ | ||
521 | #define PS3_AUDIO_A1_3WMCTRL_ASOEN0_ENABLED \ | ||
522 | PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(1) /* RW--V */ | ||
523 | #define PS3_AUDIO_A2_3WMCTRL_ASOEN0 \ | ||
524 | PS3_AUDIO_AO_3WMCTRL_ASOEN(2) /* RWIVF */ | ||
525 | #define PS3_AUDIO_A2_3WMCTRL_ASOEN0_DISABLED \ | ||
526 | PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(2) /* RWI-V */ | ||
527 | #define PS3_AUDIO_A2_3WMCTRL_ASOEN0_ENABLED \ | ||
528 | PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(2) /* RW--V */ | ||
529 | #define PS3_AUDIO_A3_3WMCTRL_ASOEN0 \ | ||
530 | PS3_AUDIO_AO_3WMCTRL_ASOEN(3) /* RWIVF */ | ||
531 | #define PS3_AUDIO_A3_3WMCTRL_ASOEN0_DISABLED \ | ||
532 | PS3_AUDIO_AO_3WMCTRL_ASOEN_DISABLED(3) /* RWI-V */ | ||
533 | #define PS3_AUDIO_A3_3WMCTRL_ASOEN0_ENABLED \ | ||
534 | PS3_AUDIO_AO_3WMCTRL_ASOEN_ENABLED(3) /* RW--V */ | ||
535 | |||
536 | /* | ||
537 | 3-Wire Audio Serial output Channel 0-3 Control Register | ||
538 | Configures settings for 3-Wire Serial Audio Output Channel 0-3 | ||
539 | |||
540 | |||
541 | 31 24 23 16 15 8 7 0 | ||
542 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
543 | |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|A|0 0 0 0|A|0|ASO|0 0 0|0|0|0|0|0| AO_3WCTRL | ||
544 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
545 | |||
546 | */ | ||
547 | /* | ||
548 | Data Bit Mode | ||
549 | Specifies the number of data bits | ||
550 | 0 - 16 bits | ||
551 | 1 - reserved | ||
552 | 2 - 20 bits | ||
553 | 3 - 24 bits | ||
554 | */ | ||
555 | #define PS3_AUDIO_AO_3WCTRL_ASODB_MASK (0x3 << 8) /* RWIVF */ | ||
556 | #define PS3_AUDIO_AO_3WCTRL_ASODB_16BIT (0x0 << 8) /* RWI-V */ | ||
557 | #define PS3_AUDIO_AO_3WCTRL_ASODB_RESVD (0x1 << 8) /* RWI-V */ | ||
558 | #define PS3_AUDIO_AO_3WCTRL_ASODB_20BIT (0x2 << 8) /* RW--V */ | ||
559 | #define PS3_AUDIO_AO_3WCTRL_ASODB_24BIT (0x3 << 8) /* RW--V */ | ||
560 | /* | ||
561 | Data Format Mode | ||
562 | Specifies the data format where (LSB side or MSB) the data(in 20 bit | ||
563 | or 24 bit resolution mode) is put in a 32 bit field. | ||
564 | 0 - Data put on LSB side | ||
565 | 1 - Data put on MSB side | ||
566 | */ | ||
567 | #define PS3_AUDIO_AO_3WCTRL_ASODF (1 << 11) /* RWIVF */ | ||
568 | #define PS3_AUDIO_AO_3WCTRL_ASODF_LSB (0 << 11) /* RWI-V */ | ||
569 | #define PS3_AUDIO_AO_3WCTRL_ASODF_MSB (1 << 11) /* RW--V */ | ||
570 | /* | ||
571 | Buffer Reset | ||
572 | Performs buffer reset. Writing 1 to this bit initializes the | ||
573 | corresponding 3-Wire Audio Output buffers(both L and R). | ||
574 | */ | ||
575 | #define PS3_AUDIO_AO_3WCTRL_ASOBRST (1 << 16) /* CWIVF */ | ||
576 | #define PS3_AUDIO_AO_3WCTRL_ASOBRST_IDLE (0 << 16) /* -WI-V */ | ||
577 | #define PS3_AUDIO_AO_3WCTRL_ASOBRST_RESET (1 << 16) /* -W--T */ | ||
578 | |||
579 | /* | ||
580 | S/PDIF Audio Output Channel 0/1 Control Register | ||
581 | Configures settings for S/PDIF Audio Output Channel 0/1. | ||
582 | |||
583 | 31 24 23 16 15 8 7 0 | ||
584 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
585 | |S|0 0 0|S|0 0|S| SPOSR |0 0|SPO|0 0 0 0|S|0|SPO|0 0 0 0 0 0 0|S| AO_SPDCTRL | ||
586 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
587 | */ | ||
588 | /* | ||
589 | Buffer reset. Writing 1 to this bit initializes the | ||
590 | corresponding S/PDIF output buffer pointer. | ||
591 | */ | ||
592 | #define PS3_AUDIO_AO_SPDCTRL_SPOBRST (1 << 0) /* CWIVF */ | ||
593 | #define PS3_AUDIO_AO_SPDCTRL_SPOBRST_IDLE (0 << 0) /* -WI-V */ | ||
594 | #define PS3_AUDIO_AO_SPDCTRL_SPOBRST_RESET (1 << 0) /* -W--T */ | ||
595 | |||
596 | /* | ||
597 | Data Bit Mode | ||
598 | Specifies number of data bits | ||
599 | 0 - 16 bits | ||
600 | 1 - Reserved | ||
601 | 2 - 20 bits | ||
602 | 3 - 24 bits | ||
603 | */ | ||
604 | #define PS3_AUDIO_AO_SPDCTRL_SPODB_MASK (0x3 << 8) /* RWIVF */ | ||
605 | #define PS3_AUDIO_AO_SPDCTRL_SPODB_16BIT (0x0 << 8) /* RWI-V */ | ||
606 | #define PS3_AUDIO_AO_SPDCTRL_SPODB_RESVD (0x1 << 8) /* RW--V */ | ||
607 | #define PS3_AUDIO_AO_SPDCTRL_SPODB_20BIT (0x2 << 8) /* RW--V */ | ||
608 | #define PS3_AUDIO_AO_SPDCTRL_SPODB_24BIT (0x3 << 8) /* RW--V */ | ||
609 | /* | ||
610 | Data format Mode | ||
611 | Specifies the data format, where (LSB side or MSB) | ||
612 | the data(in 20 or 24 bit resolution) is put in the | ||
613 | 32 bit field. | ||
614 | 0 - LSB Side | ||
615 | 1 - MSB Side | ||
616 | */ | ||
617 | #define PS3_AUDIO_AO_SPDCTRL_SPODF (1 << 11) /* RWIVF */ | ||
618 | #define PS3_AUDIO_AO_SPDCTRL_SPODF_LSB (0 << 11) /* RWI-V */ | ||
619 | #define PS3_AUDIO_AO_SPDCTRL_SPODF_MSB (1 << 11) /* RW--V */ | ||
620 | /* | ||
621 | Source Select | ||
622 | Specifies the source of the S/PDIF output. When 0, output | ||
623 | operation is controlled by 3wen[0] of AO_3WMCTRL register. | ||
624 | The SR must have the same setting as the a0_3wmctrl reg. | ||
625 | 0 - 3-Wire Audio OUT Ch0 Buffer | ||
626 | 1 - S/PDIF buffer | ||
627 | */ | ||
628 | #define PS3_AUDIO_AO_SPDCTRL_SPOSS_MASK (0x3 << 16) /* RWIVF */ | ||
629 | #define PS3_AUDIO_AO_SPDCTRL_SPOSS_3WEN (0x0 << 16) /* RWI-V */ | ||
630 | #define PS3_AUDIO_AO_SPDCTRL_SPOSS_SPDIF (0x1 << 16) /* RW--V */ | ||
631 | /* | ||
632 | Sampling Rate | ||
633 | Specifies the divide ratio of the bit clock (clock output | ||
634 | from bclko) used by the S/PDIF Output Clock, which | ||
635 | is applied to the master clock selected by mcksel. | ||
636 | */ | ||
637 | #define PS3_AUDIO_AO_SPDCTRL_SPOSR (0xf << 20) /* RWIVF */ | ||
638 | #define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV2 (0x1 << 20) /* RWI-V */ | ||
639 | #define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV4 (0x2 << 20) /* RW--V */ | ||
640 | #define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV8 (0x4 << 20) /* RW--V */ | ||
641 | #define PS3_AUDIO_AO_SPDCTRL_SPOSR_DIV12 (0x6 << 20) /* RW--V */ | ||
642 | /* | ||
643 | Master Clock Select | ||
644 | 0 - Master Clock 0 | ||
645 | 1 - Master Clock 1 | ||
646 | */ | ||
647 | #define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL (1 << 24) /* RWIVF */ | ||
648 | #define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK0 (0 << 24) /* RWI-V */ | ||
649 | #define PS3_AUDIO_AO_SPDCTRL_SPOMCKSEL_CLK1 (1 << 24) /* RW--V */ | ||
650 | |||
651 | /* | ||
652 | S/PDIF Output Channel Operational Status | ||
653 | This bit becomes 1 after S/PDIF Output Channel is in | ||
654 | action by setting 1 to spoen. This bit becomes 0 | ||
655 | after S/PDIF Output Channel is out of action by setting | ||
656 | 0 to spoen. | ||
657 | */ | ||
658 | #define PS3_AUDIO_AO_SPDCTRL_SPORUN (1 << 27) /* R-IVF */ | ||
659 | #define PS3_AUDIO_AO_SPDCTRL_SPORUN_STOPPED (0 << 27) /* R-I-V */ | ||
660 | #define PS3_AUDIO_AO_SPDCTRL_SPORUN_RUNNING (1 << 27) /* R---V */ | ||
661 | |||
662 | /* | ||
663 | S/PDIF Audio Output Channel Output Enable | ||
664 | Enables and disables output operation. This bit is used | ||
665 | only when sposs = 1 | ||
666 | */ | ||
667 | #define PS3_AUDIO_AO_SPDCTRL_SPOEN (1 << 31) /* RWIVF */ | ||
668 | #define PS3_AUDIO_AO_SPDCTRL_SPOEN_DISABLED (0 << 31) /* RWI-V */ | ||
669 | #define PS3_AUDIO_AO_SPDCTRL_SPOEN_ENABLED (1 << 31) /* RW--V */ | ||
670 | |||
671 | /* | ||
672 | S/PDIF Audio Output Channel Channel Status | ||
673 | Setting Registers. | ||
674 | Configures channel status bit settings for each block | ||
675 | (192 bits). | ||
676 | Output is performed from the MSB(AO_SPDCS0 register bit 31). | ||
677 | The same value is added for subframes within the same frame. | ||
678 | 31 24 23 16 15 8 7 0 | ||
679 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
680 | | SPOCS | AO_SPDCS | ||
681 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
682 | |||
683 | S/PDIF Audio Output Channel User Bit Setting | ||
684 | Configures user bit settings for each block (384 bits). | ||
685 | Output is performed from the MSB(ao_spdub0 register bit 31). | ||
686 | |||
687 | |||
688 | 31 24 23 16 15 8 7 0 | ||
689 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
690 | | SPOUB | AO_SPDUB | ||
691 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
692 | */ | ||
693 | /***************************************************************************** | ||
694 | * | ||
695 | * DMAC register | ||
696 | * | ||
697 | *****************************************************************************/ | ||
698 | /* | ||
699 | The PS3_AUDIO_KICK register is used to initiate a DMA transfer and monitor | ||
700 | its status | ||
701 | |||
702 | 31 24 23 16 15 8 7 0 | ||
703 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
704 | |0 0 0 0 0|STATU|0 0 0| EVENT |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0|R| KICK | ||
705 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
706 | */ | ||
707 | /* | ||
708 | The REQUEST field is written to ACTIVE to initiate a DMA request when EVENT | ||
709 | occurs. | ||
710 | It will return to the DONE state when the request is completed. | ||
711 | The registers for a DMA channel should only be written if REQUEST is IDLE. | ||
712 | */ | ||
713 | |||
714 | #define PS3_AUDIO_KICK_REQUEST (1 << 0) /* RWIVF */ | ||
715 | #define PS3_AUDIO_KICK_REQUEST_IDLE (0 << 0) /* RWI-V */ | ||
716 | #define PS3_AUDIO_KICK_REQUEST_ACTIVE (1 << 0) /* -W--T */ | ||
717 | |||
718 | /* | ||
719 | *The EVENT field is used to set the event in which | ||
720 | *the DMA request becomes active. | ||
721 | */ | ||
722 | #define PS3_AUDIO_KICK_EVENT_MASK (0x1f << 16) /* RWIVF */ | ||
723 | #define PS3_AUDIO_KICK_EVENT_ALWAYS (0x00 << 16) /* RWI-V */ | ||
724 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT0_EMPTY (0x01 << 16) /* RW--V */ | ||
725 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT0_UNDERFLOW (0x02 << 16) /* RW--V */ | ||
726 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT1_EMPTY (0x03 << 16) /* RW--V */ | ||
727 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT1_UNDERFLOW (0x04 << 16) /* RW--V */ | ||
728 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT2_EMPTY (0x05 << 16) /* RW--V */ | ||
729 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT2_UNDERFLOW (0x06 << 16) /* RW--V */ | ||
730 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT3_EMPTY (0x07 << 16) /* RW--V */ | ||
731 | #define PS3_AUDIO_KICK_EVENT_SERIALOUT3_UNDERFLOW (0x08 << 16) /* RW--V */ | ||
732 | #define PS3_AUDIO_KICK_EVENT_SPDIF0_BLOCKTRANSFERCOMPLETE \ | ||
733 | (0x09 << 16) /* RW--V */ | ||
734 | #define PS3_AUDIO_KICK_EVENT_SPDIF0_UNDERFLOW (0x0A << 16) /* RW--V */ | ||
735 | #define PS3_AUDIO_KICK_EVENT_SPDIF0_EMPTY (0x0B << 16) /* RW--V */ | ||
736 | #define PS3_AUDIO_KICK_EVENT_SPDIF1_BLOCKTRANSFERCOMPLETE \ | ||
737 | (0x0C << 16) /* RW--V */ | ||
738 | #define PS3_AUDIO_KICK_EVENT_SPDIF1_UNDERFLOW (0x0D << 16) /* RW--V */ | ||
739 | #define PS3_AUDIO_KICK_EVENT_SPDIF1_EMPTY (0x0E << 16) /* RW--V */ | ||
740 | |||
741 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA(n) \ | ||
742 | ((0x13 + (n)) << 16) /* RW--V */ | ||
743 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA0 (0x13 << 16) /* RW--V */ | ||
744 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA1 (0x14 << 16) /* RW--V */ | ||
745 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA2 (0x15 << 16) /* RW--V */ | ||
746 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA3 (0x16 << 16) /* RW--V */ | ||
747 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA4 (0x17 << 16) /* RW--V */ | ||
748 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA5 (0x18 << 16) /* RW--V */ | ||
749 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA6 (0x19 << 16) /* RW--V */ | ||
750 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA7 (0x1A << 16) /* RW--V */ | ||
751 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA8 (0x1B << 16) /* RW--V */ | ||
752 | #define PS3_AUDIO_KICK_EVENT_AUDIO_DMA9 (0x1C << 16) /* RW--V */ | ||
753 | |||
754 | /* | ||
755 | The STATUS field can be used to monitor the progress of a DMA request. | ||
756 | DONE indicates the previous request has completed. | ||
757 | EVENT indicates that the DMA engine is waiting for the EVENT to occur. | ||
758 | PENDING indicates that the DMA engine has not started processing this | ||
759 | request, but the EVENT has occured. | ||
760 | DMA indicates that the data transfer is in progress. | ||
761 | NOTIFY indicates that the notifier signalling end of transfer is being written. | ||
762 | CLEAR indicated that the previous transfer was cleared. | ||
763 | ERROR indicates the previous transfer requested an unsupported | ||
764 | source/destination combination. | ||
765 | */ | ||
766 | |||
767 | #define PS3_AUDIO_KICK_STATUS_MASK (0x7 << 24) /* R-IVF */ | ||
768 | #define PS3_AUDIO_KICK_STATUS_DONE (0x0 << 24) /* R-I-V */ | ||
769 | #define PS3_AUDIO_KICK_STATUS_EVENT (0x1 << 24) /* R---V */ | ||
770 | #define PS3_AUDIO_KICK_STATUS_PENDING (0x2 << 24) /* R---V */ | ||
771 | #define PS3_AUDIO_KICK_STATUS_DMA (0x3 << 24) /* R---V */ | ||
772 | #define PS3_AUDIO_KICK_STATUS_NOTIFY (0x4 << 24) /* R---V */ | ||
773 | #define PS3_AUDIO_KICK_STATUS_CLEAR (0x5 << 24) /* R---V */ | ||
774 | #define PS3_AUDIO_KICK_STATUS_ERROR (0x6 << 24) /* R---V */ | ||
775 | |||
776 | /* | ||
777 | The PS3_AUDIO_SOURCE register specifies the source address for transfers. | ||
778 | |||
779 | |||
780 | 31 24 23 16 15 8 7 0 | ||
781 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
782 | | START |0 0 0 0 0|TAR| SOURCE | ||
783 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
784 | */ | ||
785 | |||
786 | /* | ||
787 | The Audio DMA engine uses 128-byte transfers, thus the address must be aligned | ||
788 | to a 128 byte boundary. The low seven bits are assumed to be 0. | ||
789 | */ | ||
790 | |||
791 | #define PS3_AUDIO_SOURCE_START_MASK (0x01FFFFFF << 7) /* RWIUF */ | ||
792 | |||
793 | /* | ||
794 | The TARGET field specifies the memory space containing the source address. | ||
795 | */ | ||
796 | |||
797 | #define PS3_AUDIO_SOURCE_TARGET_MASK (3 << 0) /* RWIVF */ | ||
798 | #define PS3_AUDIO_SOURCE_TARGET_SYSTEM_MEMORY (2 << 0) /* RW--V */ | ||
799 | |||
800 | /* | ||
801 | The PS3_AUDIO_DEST register specifies the destination address for transfers. | ||
802 | |||
803 | |||
804 | 31 24 23 16 15 8 7 0 | ||
805 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
806 | | START |0 0 0 0 0|TAR| DEST | ||
807 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
808 | */ | ||
809 | |||
810 | /* | ||
811 | The Audio DMA engine uses 128-byte transfers, thus the address must be aligned | ||
812 | to a 128 byte boundary. The low seven bits are assumed to be 0. | ||
813 | */ | ||
814 | |||
815 | #define PS3_AUDIO_DEST_START_MASK (0x01FFFFFF << 7) /* RWIUF */ | ||
816 | |||
817 | /* | ||
818 | The TARGET field specifies the memory space containing the destination address | ||
819 | AUDIOFIFO = Audio WriteData FIFO, | ||
820 | */ | ||
821 | |||
822 | #define PS3_AUDIO_DEST_TARGET_MASK (3 << 0) /* RWIVF */ | ||
823 | #define PS3_AUDIO_DEST_TARGET_AUDIOFIFO (1 << 0) /* RW--V */ | ||
824 | |||
825 | /* | ||
826 | PS3_AUDIO_DMASIZE specifies the number of 128-byte blocks + 1 to transfer. | ||
827 | So a value of 0 means 128-bytes will get transfered. | ||
828 | |||
829 | |||
830 | 31 24 23 16 15 8 7 0 | ||
831 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
832 | |0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0| BLOCKS | DMASIZE | ||
833 | +-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-|-+-+-+-+-+-+-+-+ | ||
834 | */ | ||
835 | |||
836 | |||
837 | #define PS3_AUDIO_DMASIZE_BLOCKS_MASK (0x7f << 0) /* RWIUF */ | ||
838 | |||
839 | /* | ||
840 | * source/destination address for internal fifos | ||
841 | */ | ||
842 | #define PS3_AUDIO_AO_3W_LDATA(n) (0x1000 + (0x100 * (n))) | ||
843 | #define PS3_AUDIO_AO_3W_RDATA(n) (0x1080 + (0x100 * (n))) | ||
844 | |||
845 | #define PS3_AUDIO_AO_SPD_DATA(n) (0x2000 + (0x400 * (n))) | ||
846 | |||
847 | |||
848 | /* | ||
849 | * field attiribute | ||
850 | * | ||
851 | * Read | ||
852 | * ' ' = Other Information | ||
853 | * '-' = Field is part of a write-only register | ||
854 | * 'C' = Value read is always the same, constant value line follows (C) | ||
855 | * 'R' = Value is read | ||
856 | * | ||
857 | * Write | ||
858 | * ' ' = Other Information | ||
859 | * '-' = Must not be written (D), value ignored when written (R,A,F) | ||
860 | * 'W' = Can be written | ||
861 | * | ||
862 | * Internal State | ||
863 | * ' ' = Other Information | ||
864 | * '-' = No internal state | ||
865 | * 'X' = Internal state, initial value is unknown | ||
866 | * 'I' = Internal state, initial value is known and follows (I) | ||
867 | * | ||
868 | * Declaration/Size | ||
869 | * ' ' = Other Information | ||
870 | * '-' = Does Not Apply | ||
871 | * 'V' = Type is void | ||
872 | * 'U' = Type is unsigned integer | ||
873 | * 'S' = Type is signed integer | ||
874 | * 'F' = Type is IEEE floating point | ||
875 | * '1' = Byte size (008) | ||
876 | * '2' = Short size (016) | ||
877 | * '3' = Three byte size (024) | ||
878 | * '4' = Word size (032) | ||
879 | * '8' = Double size (064) | ||
880 | * | ||
881 | * Define Indicator | ||
882 | * ' ' = Other Information | ||
883 | * 'D' = Device | ||
884 | * 'M' = Memory | ||
885 | * 'R' = Register | ||
886 | * 'A' = Array of Registers | ||
887 | * 'F' = Field | ||
888 | * 'V' = Value | ||
889 | * 'T' = Task | ||
890 | */ | ||
891 | |||
diff --git a/sound/sh/Kconfig b/sound/sh/Kconfig new file mode 100644 index 000000000000..b7e08ef22a94 --- /dev/null +++ b/sound/sh/Kconfig | |||
@@ -0,0 +1,14 @@ | |||
1 | # ALSA SH drivers | ||
2 | |||
3 | menu "SUPERH devices" | ||
4 | depends on SND!=n && SUPERH | ||
5 | |||
6 | config SND_AICA | ||
7 | tristate "Dreamcast Yamaha AICA sound" | ||
8 | depends on SH_DREAMCAST && SND | ||
9 | select SND_PCM | ||
10 | help | ||
11 | ALSA Sound driver for the SEGA Dreamcast console. | ||
12 | |||
13 | endmenu | ||
14 | |||
diff --git a/sound/sh/Makefile b/sound/sh/Makefile new file mode 100644 index 000000000000..8fdcb6e26f00 --- /dev/null +++ b/sound/sh/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # | ||
2 | # Makefile for ALSA | ||
3 | # | ||
4 | |||
5 | snd-aica-objs := aica.o | ||
6 | |||
7 | # Toplevel Module Dependency | ||
8 | obj-$(CONFIG_SND_AICA) += snd-aica.o | ||
diff --git a/sound/sh/aica.c b/sound/sh/aica.c new file mode 100644 index 000000000000..739786529ca5 --- /dev/null +++ b/sound/sh/aica.c | |||
@@ -0,0 +1,665 @@ | |||
1 | /* | ||
2 | * This code is licenced under | ||
3 | * the General Public Licence | ||
4 | * version 2 | ||
5 | * | ||
6 | * Copyright Adrian McMenamin 2005, 2006, 2007 | ||
7 | * <adrian@mcmen.demon.co.uk> | ||
8 | * Requires firmware (BSD licenced) available from: | ||
9 | * http://linuxdc.cvs.sourceforge.net/linuxdc/linux-sh-dc/sound/oss/aica/firmware/ | ||
10 | * or the maintainer | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of version 2 of the GNU General Public License as published by | ||
14 | * the Free Software Foundation. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
24 | * | ||
25 | */ | ||
26 | |||
27 | #include <linux/init.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/time.h> | ||
31 | #include <linux/wait.h> | ||
32 | #include <linux/moduleparam.h> | ||
33 | #include <linux/platform_device.h> | ||
34 | #include <linux/firmware.h> | ||
35 | #include <linux/timer.h> | ||
36 | #include <linux/delay.h> | ||
37 | #include <linux/workqueue.h> | ||
38 | #include <sound/driver.h> | ||
39 | #include <sound/core.h> | ||
40 | #include <sound/control.h> | ||
41 | #include <sound/pcm.h> | ||
42 | #include <sound/initval.h> | ||
43 | #include <sound/info.h> | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/dma.h> | ||
46 | #include <asm/dreamcast/sysasic.h> | ||
47 | #include "aica.h" | ||
48 | |||
49 | MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>"); | ||
50 | MODULE_DESCRIPTION("Dreamcast AICA sound (pcm) driver"); | ||
51 | MODULE_LICENSE("GPL"); | ||
52 | MODULE_SUPPORTED_DEVICE("{{Yamaha/SEGA, AICA}}"); | ||
53 | |||
54 | /* module parameters */ | ||
55 | #define CARD_NAME "AICA" | ||
56 | static int index = -1; | ||
57 | static char *id; | ||
58 | static int enable = 1; | ||
59 | module_param(index, int, 0444); | ||
60 | MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard."); | ||
61 | module_param(id, charp, 0444); | ||
62 | MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard."); | ||
63 | module_param(enable, bool, 0644); | ||
64 | MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard."); | ||
65 | |||
66 | /* Use workqueue */ | ||
67 | static struct workqueue_struct *aica_queue; | ||
68 | |||
69 | /* Simple platform device */ | ||
70 | static struct platform_device *pd; | ||
71 | static struct resource aica_memory_space[2] = { | ||
72 | { | ||
73 | .name = "AICA ARM CONTROL", | ||
74 | .start = ARM_RESET_REGISTER, | ||
75 | .flags = IORESOURCE_MEM, | ||
76 | .end = ARM_RESET_REGISTER + 3, | ||
77 | }, | ||
78 | { | ||
79 | .name = "AICA Sound RAM", | ||
80 | .start = SPU_MEMORY_BASE, | ||
81 | .flags = IORESOURCE_MEM, | ||
82 | .end = SPU_MEMORY_BASE + 0x200000 - 1, | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | /* SPU specific functions */ | ||
87 | /* spu_write_wait - wait for G2-SH FIFO to clear */ | ||
88 | static void spu_write_wait(void) | ||
89 | { | ||
90 | int time_count; | ||
91 | time_count = 0; | ||
92 | while (1) { | ||
93 | if (!(readl(G2_FIFO) & 0x11)) | ||
94 | break; | ||
95 | /* To ensure hardware failure doesn't wedge kernel */ | ||
96 | time_count++; | ||
97 | if (time_count > 0x10000) { | ||
98 | snd_printk | ||
99 | ("WARNING: G2 FIFO appears to be blocked.\n"); | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /* spu_memset - write to memory in SPU address space */ | ||
106 | static void spu_memset(u32 toi, u32 what, int length) | ||
107 | { | ||
108 | int i; | ||
109 | snd_assert(length % 4 == 0, return); | ||
110 | for (i = 0; i < length; i++) { | ||
111 | if (!(i % 8)) | ||
112 | spu_write_wait(); | ||
113 | writel(what, toi + SPU_MEMORY_BASE); | ||
114 | toi++; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | /* spu_memload - write to SPU address space */ | ||
119 | static void spu_memload(u32 toi, void *from, int length) | ||
120 | { | ||
121 | u32 *froml = from; | ||
122 | u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi); | ||
123 | int i; | ||
124 | u32 val; | ||
125 | length = DIV_ROUND_UP(length, 4); | ||
126 | spu_write_wait(); | ||
127 | for (i = 0; i < length; i++) { | ||
128 | if (!(i % 8)) | ||
129 | spu_write_wait(); | ||
130 | val = *froml; | ||
131 | writel(val, to); | ||
132 | froml++; | ||
133 | to++; | ||
134 | } | ||
135 | } | ||
136 | |||
137 | /* spu_disable - set spu registers to stop sound output */ | ||
138 | static void spu_disable(void) | ||
139 | { | ||
140 | int i; | ||
141 | u32 regval; | ||
142 | spu_write_wait(); | ||
143 | regval = readl(ARM_RESET_REGISTER); | ||
144 | regval |= 1; | ||
145 | spu_write_wait(); | ||
146 | writel(regval, ARM_RESET_REGISTER); | ||
147 | for (i = 0; i < 64; i++) { | ||
148 | spu_write_wait(); | ||
149 | regval = readl(SPU_REGISTER_BASE + (i * 0x80)); | ||
150 | regval = (regval & ~0x4000) | 0x8000; | ||
151 | spu_write_wait(); | ||
152 | writel(regval, SPU_REGISTER_BASE + (i * 0x80)); | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* spu_enable - set spu registers to enable sound output */ | ||
157 | static void spu_enable(void) | ||
158 | { | ||
159 | u32 regval = readl(ARM_RESET_REGISTER); | ||
160 | regval &= ~1; | ||
161 | spu_write_wait(); | ||
162 | writel(regval, ARM_RESET_REGISTER); | ||
163 | } | ||
164 | |||
165 | /* | ||
166 | * Halt the sound processor, clear the memory, | ||
167 | * load some default ARM7 code, and then restart ARM7 | ||
168 | */ | ||
169 | static void spu_reset(void) | ||
170 | { | ||
171 | spu_disable(); | ||
172 | spu_memset(0, 0, 0x200000 / 4); | ||
173 | /* Put ARM7 in endless loop */ | ||
174 | ctrl_outl(0xea000002, SPU_MEMORY_BASE); | ||
175 | spu_enable(); | ||
176 | } | ||
177 | |||
178 | /* aica_chn_start - write to spu to start playback */ | ||
179 | static void aica_chn_start(void) | ||
180 | { | ||
181 | spu_write_wait(); | ||
182 | writel(AICA_CMD_KICK | AICA_CMD_START, (u32 *) AICA_CONTROL_POINT); | ||
183 | } | ||
184 | |||
185 | /* aica_chn_halt - write to spu to halt playback */ | ||
186 | static void aica_chn_halt(void) | ||
187 | { | ||
188 | spu_write_wait(); | ||
189 | writel(AICA_CMD_KICK | AICA_CMD_STOP, (u32 *) AICA_CONTROL_POINT); | ||
190 | } | ||
191 | |||
192 | /* ALSA code below */ | ||
193 | static struct snd_pcm_hardware snd_pcm_aica_playback_hw = { | ||
194 | .info = (SNDRV_PCM_INFO_NONINTERLEAVED), | ||
195 | .formats = | ||
196 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | | ||
197 | SNDRV_PCM_FMTBIT_IMA_ADPCM), | ||
198 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
199 | .rate_min = 8000, | ||
200 | .rate_max = 48000, | ||
201 | .channels_min = 1, | ||
202 | .channels_max = 2, | ||
203 | .buffer_bytes_max = AICA_BUFFER_SIZE, | ||
204 | .period_bytes_min = AICA_PERIOD_SIZE, | ||
205 | .period_bytes_max = AICA_PERIOD_SIZE, | ||
206 | .periods_min = AICA_PERIOD_NUMBER, | ||
207 | .periods_max = AICA_PERIOD_NUMBER, | ||
208 | }; | ||
209 | |||
210 | static int aica_dma_transfer(int channels, int buffer_size, | ||
211 | struct snd_pcm_substream *substream) | ||
212 | { | ||
213 | int q, err, period_offset; | ||
214 | struct snd_card_aica *dreamcastcard; | ||
215 | struct snd_pcm_runtime *runtime; | ||
216 | err = 0; | ||
217 | dreamcastcard = substream->pcm->private_data; | ||
218 | period_offset = dreamcastcard->clicks; | ||
219 | period_offset %= (AICA_PERIOD_NUMBER / channels); | ||
220 | runtime = substream->runtime; | ||
221 | for (q = 0; q < channels; q++) { | ||
222 | err = dma_xfer(AICA_DMA_CHANNEL, | ||
223 | (unsigned long) (runtime->dma_area + | ||
224 | (AICA_BUFFER_SIZE * q) / | ||
225 | channels + | ||
226 | AICA_PERIOD_SIZE * | ||
227 | period_offset), | ||
228 | AICA_CHANNEL0_OFFSET + q * CHANNEL_OFFSET + | ||
229 | AICA_PERIOD_SIZE * period_offset, | ||
230 | buffer_size / channels, AICA_DMA_MODE); | ||
231 | if (unlikely(err < 0)) | ||
232 | break; | ||
233 | dma_wait_for_completion(AICA_DMA_CHANNEL); | ||
234 | } | ||
235 | return err; | ||
236 | } | ||
237 | |||
238 | static void startup_aica(struct snd_card_aica *dreamcastcard) | ||
239 | { | ||
240 | spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, | ||
241 | dreamcastcard->channel, sizeof(struct aica_channel)); | ||
242 | aica_chn_start(); | ||
243 | } | ||
244 | |||
245 | static void run_spu_dma(struct work_struct *work) | ||
246 | { | ||
247 | int buffer_size; | ||
248 | struct snd_pcm_runtime *runtime; | ||
249 | struct snd_card_aica *dreamcastcard; | ||
250 | dreamcastcard = | ||
251 | container_of(work, struct snd_card_aica, spu_dma_work); | ||
252 | runtime = dreamcastcard->substream->runtime; | ||
253 | if (unlikely(dreamcastcard->dma_check == 0)) { | ||
254 | buffer_size = | ||
255 | frames_to_bytes(runtime, runtime->buffer_size); | ||
256 | if (runtime->channels > 1) | ||
257 | dreamcastcard->channel->flags |= 0x01; | ||
258 | aica_dma_transfer(runtime->channels, buffer_size, | ||
259 | dreamcastcard->substream); | ||
260 | startup_aica(dreamcastcard); | ||
261 | dreamcastcard->clicks = | ||
262 | buffer_size / (AICA_PERIOD_SIZE * runtime->channels); | ||
263 | return; | ||
264 | } else { | ||
265 | aica_dma_transfer(runtime->channels, | ||
266 | AICA_PERIOD_SIZE * runtime->channels, | ||
267 | dreamcastcard->substream); | ||
268 | snd_pcm_period_elapsed(dreamcastcard->substream); | ||
269 | dreamcastcard->clicks++; | ||
270 | if (unlikely(dreamcastcard->clicks >= AICA_PERIOD_NUMBER)) | ||
271 | dreamcastcard->clicks %= AICA_PERIOD_NUMBER; | ||
272 | mod_timer(&dreamcastcard->timer, jiffies + 1); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static void aica_period_elapsed(unsigned long timer_var) | ||
277 | { | ||
278 | /*timer function - so cannot sleep */ | ||
279 | int play_period; | ||
280 | struct snd_pcm_runtime *runtime; | ||
281 | struct snd_pcm_substream *substream; | ||
282 | struct snd_card_aica *dreamcastcard; | ||
283 | substream = (struct snd_pcm_substream *) timer_var; | ||
284 | runtime = substream->runtime; | ||
285 | dreamcastcard = substream->pcm->private_data; | ||
286 | /* Have we played out an additional period? */ | ||
287 | play_period = | ||
288 | frames_to_bytes(runtime, | ||
289 | readl | ||
290 | (AICA_CONTROL_CHANNEL_SAMPLE_NUMBER)) / | ||
291 | AICA_PERIOD_SIZE; | ||
292 | if (play_period == dreamcastcard->current_period) { | ||
293 | /* reschedule the timer */ | ||
294 | mod_timer(&(dreamcastcard->timer), jiffies + 1); | ||
295 | return; | ||
296 | } | ||
297 | if (runtime->channels > 1) | ||
298 | dreamcastcard->current_period = play_period; | ||
299 | if (unlikely(dreamcastcard->dma_check == 0)) | ||
300 | dreamcastcard->dma_check = 1; | ||
301 | queue_work(aica_queue, &(dreamcastcard->spu_dma_work)); | ||
302 | } | ||
303 | |||
304 | static void spu_begin_dma(struct snd_pcm_substream *substream) | ||
305 | { | ||
306 | struct snd_card_aica *dreamcastcard; | ||
307 | struct snd_pcm_runtime *runtime; | ||
308 | runtime = substream->runtime; | ||
309 | dreamcastcard = substream->pcm->private_data; | ||
310 | /*get the queue to do the work */ | ||
311 | queue_work(aica_queue, &(dreamcastcard->spu_dma_work)); | ||
312 | /* Timer may already be running */ | ||
313 | if (unlikely(dreamcastcard->timer.data)) { | ||
314 | mod_timer(&dreamcastcard->timer, jiffies + 4); | ||
315 | return; | ||
316 | } | ||
317 | init_timer(&(dreamcastcard->timer)); | ||
318 | dreamcastcard->timer.data = (unsigned long) substream; | ||
319 | dreamcastcard->timer.function = aica_period_elapsed; | ||
320 | dreamcastcard->timer.expires = jiffies + 4; | ||
321 | add_timer(&(dreamcastcard->timer)); | ||
322 | } | ||
323 | |||
324 | static int snd_aicapcm_pcm_open(struct snd_pcm_substream | ||
325 | *substream) | ||
326 | { | ||
327 | struct snd_pcm_runtime *runtime; | ||
328 | struct aica_channel *channel; | ||
329 | struct snd_card_aica *dreamcastcard; | ||
330 | if (!enable) | ||
331 | return -ENOENT; | ||
332 | dreamcastcard = substream->pcm->private_data; | ||
333 | channel = kmalloc(sizeof(struct aica_channel), GFP_KERNEL); | ||
334 | if (!channel) | ||
335 | return -ENOMEM; | ||
336 | /* set defaults for channel */ | ||
337 | channel->sfmt = SM_8BIT; | ||
338 | channel->cmd = AICA_CMD_START; | ||
339 | channel->vol = dreamcastcard->master_volume; | ||
340 | channel->pan = 0x80; | ||
341 | channel->pos = 0; | ||
342 | channel->flags = 0; /* default to mono */ | ||
343 | dreamcastcard->channel = channel; | ||
344 | runtime = substream->runtime; | ||
345 | runtime->hw = snd_pcm_aica_playback_hw; | ||
346 | spu_enable(); | ||
347 | dreamcastcard->clicks = 0; | ||
348 | dreamcastcard->current_period = 0; | ||
349 | dreamcastcard->dma_check = 0; | ||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | static int snd_aicapcm_pcm_close(struct snd_pcm_substream | ||
354 | *substream) | ||
355 | { | ||
356 | struct snd_card_aica *dreamcastcard = substream->pcm->private_data; | ||
357 | flush_workqueue(aica_queue); | ||
358 | if (dreamcastcard->timer.data) | ||
359 | del_timer(&dreamcastcard->timer); | ||
360 | kfree(dreamcastcard->channel); | ||
361 | spu_disable(); | ||
362 | return 0; | ||
363 | } | ||
364 | |||
365 | static int snd_aicapcm_pcm_hw_free(struct snd_pcm_substream | ||
366 | *substream) | ||
367 | { | ||
368 | /* Free the DMA buffer */ | ||
369 | return snd_pcm_lib_free_pages(substream); | ||
370 | } | ||
371 | |||
372 | static int snd_aicapcm_pcm_hw_params(struct snd_pcm_substream | ||
373 | *substream, struct snd_pcm_hw_params | ||
374 | *hw_params) | ||
375 | { | ||
376 | /* Allocate a DMA buffer using ALSA built-ins */ | ||
377 | return | ||
378 | snd_pcm_lib_malloc_pages(substream, | ||
379 | params_buffer_bytes(hw_params)); | ||
380 | } | ||
381 | |||
382 | static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream | ||
383 | *substream) | ||
384 | { | ||
385 | struct snd_card_aica *dreamcastcard = substream->pcm->private_data; | ||
386 | if ((substream->runtime)->format == SNDRV_PCM_FORMAT_S16_LE) | ||
387 | dreamcastcard->channel->sfmt = SM_16BIT; | ||
388 | dreamcastcard->channel->freq = substream->runtime->rate; | ||
389 | dreamcastcard->substream = substream; | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static int snd_aicapcm_pcm_trigger(struct snd_pcm_substream | ||
394 | *substream, int cmd) | ||
395 | { | ||
396 | switch (cmd) { | ||
397 | case SNDRV_PCM_TRIGGER_START: | ||
398 | spu_begin_dma(substream); | ||
399 | break; | ||
400 | case SNDRV_PCM_TRIGGER_STOP: | ||
401 | aica_chn_halt(); | ||
402 | break; | ||
403 | default: | ||
404 | return -EINVAL; | ||
405 | } | ||
406 | return 0; | ||
407 | } | ||
408 | |||
409 | static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream | ||
410 | *substream) | ||
411 | { | ||
412 | return readl(AICA_CONTROL_CHANNEL_SAMPLE_NUMBER); | ||
413 | } | ||
414 | |||
415 | static struct snd_pcm_ops snd_aicapcm_playback_ops = { | ||
416 | .open = snd_aicapcm_pcm_open, | ||
417 | .close = snd_aicapcm_pcm_close, | ||
418 | .ioctl = snd_pcm_lib_ioctl, | ||
419 | .hw_params = snd_aicapcm_pcm_hw_params, | ||
420 | .hw_free = snd_aicapcm_pcm_hw_free, | ||
421 | .prepare = snd_aicapcm_pcm_prepare, | ||
422 | .trigger = snd_aicapcm_pcm_trigger, | ||
423 | .pointer = snd_aicapcm_pcm_pointer, | ||
424 | }; | ||
425 | |||
426 | /* TO DO: set up to handle more than one pcm instance */ | ||
427 | static int __init snd_aicapcmchip(struct snd_card_aica | ||
428 | *dreamcastcard, int pcm_index) | ||
429 | { | ||
430 | struct snd_pcm *pcm; | ||
431 | int err; | ||
432 | /* AICA has no capture ability */ | ||
433 | err = | ||
434 | snd_pcm_new(dreamcastcard->card, "AICA PCM", pcm_index, 1, 0, | ||
435 | &pcm); | ||
436 | if (unlikely(err < 0)) | ||
437 | return err; | ||
438 | pcm->private_data = dreamcastcard; | ||
439 | strcpy(pcm->name, "AICA PCM"); | ||
440 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, | ||
441 | &snd_aicapcm_playback_ops); | ||
442 | /* Allocate the DMA buffers */ | ||
443 | err = | ||
444 | snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
445 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
446 | snd_dma_continuous_data | ||
447 | (GFP_KERNEL), | ||
448 | AICA_BUFFER_SIZE, | ||
449 | AICA_BUFFER_SIZE); | ||
450 | return err; | ||
451 | } | ||
452 | |||
453 | /* Mixer controls */ | ||
454 | static int aica_pcmswitch_info(struct snd_kcontrol *kcontrol, | ||
455 | struct snd_ctl_elem_info *uinfo) | ||
456 | { | ||
457 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
458 | uinfo->count = 1; | ||
459 | uinfo->value.integer.min = 0; | ||
460 | uinfo->value.integer.max = 1; | ||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static int aica_pcmswitch_get(struct snd_kcontrol *kcontrol, | ||
465 | struct snd_ctl_elem_value *ucontrol) | ||
466 | { | ||
467 | ucontrol->value.integer.value[0] = 1; /* TO DO: Fix me */ | ||
468 | return 0; | ||
469 | } | ||
470 | |||
471 | static int aica_pcmswitch_put(struct snd_kcontrol *kcontrol, | ||
472 | struct snd_ctl_elem_value *ucontrol) | ||
473 | { | ||
474 | if (ucontrol->value.integer.value[0] == 1) | ||
475 | return 0; /* TO DO: Fix me */ | ||
476 | else | ||
477 | aica_chn_halt(); | ||
478 | return 0; | ||
479 | } | ||
480 | |||
481 | static int aica_pcmvolume_info(struct snd_kcontrol *kcontrol, | ||
482 | struct snd_ctl_elem_info *uinfo) | ||
483 | { | ||
484 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
485 | uinfo->count = 1; | ||
486 | uinfo->value.integer.min = 0; | ||
487 | uinfo->value.integer.max = 0xFF; | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | static int aica_pcmvolume_get(struct snd_kcontrol *kcontrol, | ||
492 | struct snd_ctl_elem_value *ucontrol) | ||
493 | { | ||
494 | struct snd_card_aica *dreamcastcard; | ||
495 | dreamcastcard = kcontrol->private_data; | ||
496 | if (unlikely(!dreamcastcard->channel)) | ||
497 | return -ETXTBSY; /* we've not yet been set up */ | ||
498 | ucontrol->value.integer.value[0] = dreamcastcard->channel->vol; | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static int aica_pcmvolume_put(struct snd_kcontrol *kcontrol, | ||
503 | struct snd_ctl_elem_value *ucontrol) | ||
504 | { | ||
505 | struct snd_card_aica *dreamcastcard; | ||
506 | dreamcastcard = kcontrol->private_data; | ||
507 | if (unlikely(!dreamcastcard->channel)) | ||
508 | return -ETXTBSY; | ||
509 | if (unlikely(dreamcastcard->channel->vol == | ||
510 | ucontrol->value.integer.value[0])) | ||
511 | return 0; | ||
512 | dreamcastcard->channel->vol = ucontrol->value.integer.value[0]; | ||
513 | dreamcastcard->master_volume = ucontrol->value.integer.value[0]; | ||
514 | spu_memload(AICA_CHANNEL0_CONTROL_OFFSET, | ||
515 | dreamcastcard->channel, sizeof(struct aica_channel)); | ||
516 | return 1; | ||
517 | } | ||
518 | |||
519 | static struct snd_kcontrol_new snd_aica_pcmswitch_control __devinitdata = { | ||
520 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
521 | .name = "PCM Playback Switch", | ||
522 | .index = 0, | ||
523 | .info = aica_pcmswitch_info, | ||
524 | .get = aica_pcmswitch_get, | ||
525 | .put = aica_pcmswitch_put | ||
526 | }; | ||
527 | |||
528 | static struct snd_kcontrol_new snd_aica_pcmvolume_control __devinitdata = { | ||
529 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
530 | .name = "PCM Playback Volume", | ||
531 | .index = 0, | ||
532 | .info = aica_pcmvolume_info, | ||
533 | .get = aica_pcmvolume_get, | ||
534 | .put = aica_pcmvolume_put | ||
535 | }; | ||
536 | |||
537 | static int load_aica_firmware(void) | ||
538 | { | ||
539 | int err; | ||
540 | const struct firmware *fw_entry; | ||
541 | spu_reset(); | ||
542 | err = request_firmware(&fw_entry, "aica_firmware.bin", &pd->dev); | ||
543 | if (unlikely(err)) | ||
544 | return err; | ||
545 | /* write firware into memory */ | ||
546 | spu_disable(); | ||
547 | spu_memload(0, fw_entry->data, fw_entry->size); | ||
548 | spu_enable(); | ||
549 | release_firmware(fw_entry); | ||
550 | return err; | ||
551 | } | ||
552 | |||
553 | static int __devinit add_aicamixer_controls(struct snd_card_aica | ||
554 | *dreamcastcard) | ||
555 | { | ||
556 | int err; | ||
557 | err = snd_ctl_add | ||
558 | (dreamcastcard->card, | ||
559 | snd_ctl_new1(&snd_aica_pcmvolume_control, dreamcastcard)); | ||
560 | if (unlikely(err < 0)) | ||
561 | return err; | ||
562 | err = snd_ctl_add | ||
563 | (dreamcastcard->card, | ||
564 | snd_ctl_new1(&snd_aica_pcmswitch_control, dreamcastcard)); | ||
565 | if (unlikely(err < 0)) | ||
566 | return err; | ||
567 | return 0; | ||
568 | } | ||
569 | |||
570 | static int snd_aica_remove(struct platform_device *devptr) | ||
571 | { | ||
572 | struct snd_card_aica *dreamcastcard; | ||
573 | dreamcastcard = platform_get_drvdata(devptr); | ||
574 | if (unlikely(!dreamcastcard)) | ||
575 | return -ENODEV; | ||
576 | snd_card_free(dreamcastcard->card); | ||
577 | kfree(dreamcastcard); | ||
578 | platform_set_drvdata(devptr, NULL); | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | static int __init snd_aica_probe(struct platform_device *devptr) | ||
583 | { | ||
584 | int err; | ||
585 | struct snd_card_aica *dreamcastcard; | ||
586 | dreamcastcard = kmalloc(sizeof(struct snd_card_aica), GFP_KERNEL); | ||
587 | if (unlikely(!dreamcastcard)) | ||
588 | return -ENOMEM; | ||
589 | dreamcastcard->card = | ||
590 | snd_card_new(index, SND_AICA_DRIVER, THIS_MODULE, 0); | ||
591 | if (unlikely(!dreamcastcard->card)) { | ||
592 | kfree(dreamcastcard); | ||
593 | return -ENODEV; | ||
594 | } | ||
595 | strcpy(dreamcastcard->card->driver, "snd_aica"); | ||
596 | strcpy(dreamcastcard->card->shortname, SND_AICA_DRIVER); | ||
597 | strcpy(dreamcastcard->card->longname, | ||
598 | "Yamaha AICA Super Intelligent Sound Processor for SEGA Dreamcast"); | ||
599 | /* Prepare to use the queue */ | ||
600 | INIT_WORK(&(dreamcastcard->spu_dma_work), run_spu_dma); | ||
601 | /* Load the PCM 'chip' */ | ||
602 | err = snd_aicapcmchip(dreamcastcard, 0); | ||
603 | if (unlikely(err < 0)) | ||
604 | goto freedreamcast; | ||
605 | snd_card_set_dev(dreamcastcard->card, &devptr->dev); | ||
606 | dreamcastcard->timer.data = 0; | ||
607 | dreamcastcard->channel = NULL; | ||
608 | /* Add basic controls */ | ||
609 | err = add_aicamixer_controls(dreamcastcard); | ||
610 | if (unlikely(err < 0)) | ||
611 | goto freedreamcast; | ||
612 | /* Register the card with ALSA subsystem */ | ||
613 | err = snd_card_register(dreamcastcard->card); | ||
614 | if (unlikely(err < 0)) | ||
615 | goto freedreamcast; | ||
616 | platform_set_drvdata(devptr, dreamcastcard); | ||
617 | aica_queue = create_workqueue(CARD_NAME); | ||
618 | if (unlikely(!aica_queue)) | ||
619 | goto freedreamcast; | ||
620 | snd_printk | ||
621 | ("ALSA Driver for Yamaha AICA Super Intelligent Sound Processor\n"); | ||
622 | return 0; | ||
623 | freedreamcast: | ||
624 | snd_card_free(dreamcastcard->card); | ||
625 | kfree(dreamcastcard); | ||
626 | return err; | ||
627 | } | ||
628 | |||
629 | static struct platform_driver snd_aica_driver = { | ||
630 | .probe = snd_aica_probe, | ||
631 | .remove = snd_aica_remove, | ||
632 | .driver = { | ||
633 | .name = SND_AICA_DRIVER}, | ||
634 | }; | ||
635 | |||
636 | static int __init aica_init(void) | ||
637 | { | ||
638 | int err; | ||
639 | err = platform_driver_register(&snd_aica_driver); | ||
640 | if (unlikely(err < 0)) | ||
641 | return err; | ||
642 | pd = platform_device_register_simple(SND_AICA_DRIVER, -1, | ||
643 | aica_memory_space, 2); | ||
644 | if (unlikely(IS_ERR(pd))) { | ||
645 | platform_driver_unregister(&snd_aica_driver); | ||
646 | return PTR_ERR(pd); | ||
647 | } | ||
648 | /* Load the firmware */ | ||
649 | return load_aica_firmware(); | ||
650 | } | ||
651 | |||
652 | static void __exit aica_exit(void) | ||
653 | { | ||
654 | /* Destroy the aica kernel thread * | ||
655 | * being extra cautious to check if it exists*/ | ||
656 | if (likely(aica_queue)) | ||
657 | destroy_workqueue(aica_queue); | ||
658 | platform_device_unregister(pd); | ||
659 | platform_driver_unregister(&snd_aica_driver); | ||
660 | /* Kill any sound still playing and reset ARM7 to safe state */ | ||
661 | spu_reset(); | ||
662 | } | ||
663 | |||
664 | module_init(aica_init); | ||
665 | module_exit(aica_exit); | ||
diff --git a/sound/sh/aica.h b/sound/sh/aica.h new file mode 100644 index 000000000000..8c11e3d10a50 --- /dev/null +++ b/sound/sh/aica.h | |||
@@ -0,0 +1,81 @@ | |||
1 | /* aica.h | ||
2 | * Header file for ALSA driver for | ||
3 | * Sega Dreamcast Yamaha AICA sound | ||
4 | * Copyright Adrian McMenamin | ||
5 | * <adrian@mcmen.demon.co.uk> | ||
6 | * 2006 | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of version 2 of the GNU General Public License as published by | ||
10 | * the Free Software Foundation. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | /* SPU memory and register constants etc */ | ||
24 | #define G2_FIFO 0xa05f688c | ||
25 | #define SPU_MEMORY_BASE 0xA0800000 | ||
26 | #define ARM_RESET_REGISTER 0xA0702C00 | ||
27 | #define SPU_REGISTER_BASE 0xA0700000 | ||
28 | |||
29 | /* AICA channels stuff */ | ||
30 | #define AICA_CONTROL_POINT 0xA0810000 | ||
31 | #define AICA_CONTROL_CHANNEL_SAMPLE_NUMBER 0xA0810008 | ||
32 | #define AICA_CHANNEL0_CONTROL_OFFSET 0x10004 | ||
33 | |||
34 | /* Command values */ | ||
35 | #define AICA_CMD_KICK 0x80000000 | ||
36 | #define AICA_CMD_NONE 0 | ||
37 | #define AICA_CMD_START 1 | ||
38 | #define AICA_CMD_STOP 2 | ||
39 | #define AICA_CMD_VOL 3 | ||
40 | |||
41 | /* Sound modes */ | ||
42 | #define SM_8BIT 1 | ||
43 | #define SM_16BIT 0 | ||
44 | #define SM_ADPCM 2 | ||
45 | |||
46 | /* Buffer and period size */ | ||
47 | #define AICA_BUFFER_SIZE 0x8000 | ||
48 | #define AICA_PERIOD_SIZE 0x800 | ||
49 | #define AICA_PERIOD_NUMBER 16 | ||
50 | |||
51 | #define AICA_CHANNEL0_OFFSET 0x11000 | ||
52 | #define AICA_CHANNEL1_OFFSET 0x21000 | ||
53 | #define CHANNEL_OFFSET 0x10000 | ||
54 | |||
55 | #define AICA_DMA_CHANNEL 0 | ||
56 | #define AICA_DMA_MODE 5 | ||
57 | |||
58 | #define SND_AICA_DRIVER "AICA" | ||
59 | |||
60 | struct aica_channel { | ||
61 | uint32_t cmd; /* Command ID */ | ||
62 | uint32_t pos; /* Sample position */ | ||
63 | uint32_t length; /* Sample length */ | ||
64 | uint32_t freq; /* Frequency */ | ||
65 | uint32_t vol; /* Volume 0-255 */ | ||
66 | uint32_t pan; /* Pan 0-255 */ | ||
67 | uint32_t sfmt; /* Sound format */ | ||
68 | uint32_t flags; /* Bit flags */ | ||
69 | }; | ||
70 | |||
71 | struct snd_card_aica { | ||
72 | struct work_struct spu_dma_work; | ||
73 | struct snd_card *card; | ||
74 | struct aica_channel *channel; | ||
75 | struct snd_pcm_substream *substream; | ||
76 | int clicks; | ||
77 | int current_period; | ||
78 | struct timer_list timer; | ||
79 | int master_volume; | ||
80 | int dma_check; | ||
81 | }; | ||
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 10cffc087181..97b255233175 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -27,6 +27,7 @@ config SND_SOC | |||
27 | source "sound/soc/at91/Kconfig" | 27 | source "sound/soc/at91/Kconfig" |
28 | source "sound/soc/pxa/Kconfig" | 28 | source "sound/soc/pxa/Kconfig" |
29 | source "sound/soc/s3c24xx/Kconfig" | 29 | source "sound/soc/s3c24xx/Kconfig" |
30 | source "sound/soc/sh/Kconfig" | ||
30 | 31 | ||
31 | # Supported codecs | 32 | # Supported codecs |
32 | source "sound/soc/codecs/Kconfig" | 33 | source "sound/soc/codecs/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 0ae2e49036f9..304140377632 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,4 +1,4 @@ | |||
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/ at91/ pxa/ s3c24xx/ | 4 | obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/ s3c24xx/ sh/ |
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig index 044a3712077a..e97c68306a9a 100644 --- a/sound/soc/s3c24xx/Kconfig +++ b/sound/soc/s3c24xx/Kconfig | |||
@@ -1,6 +1,7 @@ | |||
1 | config SND_S3C24XX_SOC | 1 | config SND_S3C24XX_SOC |
2 | tristate "SoC Audio for the Samsung S3C24XX chips" | 2 | tristate "SoC Audio for the Samsung S3C24XX chips" |
3 | depends on ARCH_S3C2410 && SND_SOC | 3 | depends on ARCH_S3C2410 && SND_SOC |
4 | select SND_PCM | ||
4 | help | 5 | help |
5 | Say Y or M if you want to add support for codecs attached to | 6 | Say Y or M if you want to add support for codecs attached to |
6 | the S3C24XX AC97, I2S or SSP interface. You will also need | 7 | the S3C24XX AC97, I2S or SSP interface. You will also need |
@@ -8,3 +9,29 @@ config SND_S3C24XX_SOC | |||
8 | 9 | ||
9 | config SND_S3C24XX_SOC_I2S | 10 | config SND_S3C24XX_SOC_I2S |
10 | tristate | 11 | tristate |
12 | |||
13 | config SND_S3C2443_SOC_AC97 | ||
14 | tristate | ||
15 | select AC97_BUS | ||
16 | select SND_AC97_CODEC | ||
17 | select SND_SOC_AC97_BUS | ||
18 | |||
19 | config SND_S3C24XX_SOC_NEO1973_WM8753 | ||
20 | tristate "SoC I2S Audio support for NEO1973 - WM8753" | ||
21 | depends on SND_S3C24XX_SOC && MACH_GTA01 | ||
22 | select SND_S3C24XX_SOC_I2S | ||
23 | select SND_SOC_WM8753 | ||
24 | help | ||
25 | Say Y if you want to add support for SoC audio on smdk2440 | ||
26 | with the WM8753. | ||
27 | |||
28 | config SND_S3C24XX_SOC_SMDK2443_WM9710 | ||
29 | tristate "SoC AC97 Audio support for SMDK2443 - WM9710" | ||
30 | depends on SND_S3C24XX_SOC && MACH_SMDK2443 | ||
31 | select SND_S3C2443_SOC_AC97 | ||
32 | select SND_SOC_AC97_CODEC | ||
33 | help | ||
34 | Say Y if you want to add support for SoC audio on smdk2443 | ||
35 | with the WM9710. | ||
36 | |||
37 | |||
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile index 6f0fffcb30f5..13c92f0fa1e4 100644 --- a/sound/soc/s3c24xx/Makefile +++ b/sound/soc/s3c24xx/Makefile | |||
@@ -1,6 +1,15 @@ | |||
1 | # S3c24XX Platform Support | 1 | # S3c24XX Platform Support |
2 | snd-soc-s3c24xx-objs := s3c24xx-pcm.o | 2 | snd-soc-s3c24xx-objs := s3c24xx-pcm.o |
3 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o | 3 | snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o |
4 | snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o | 6 | obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o |
6 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o | 7 | obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o |
8 | obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o | ||
9 | |||
10 | # S3C24XX Machine Support | ||
11 | snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o | ||
12 | snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o | ||
13 | |||
14 | obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | ||
15 | obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o | ||
diff --git a/sound/soc/s3c24xx/lm4857.h b/sound/soc/s3c24xx/lm4857.h new file mode 100644 index 000000000000..0cf5b7011d6f --- /dev/null +++ b/sound/soc/s3c24xx/lm4857.h | |||
@@ -0,0 +1,32 @@ | |||
1 | /* | ||
2 | * lm4857.h -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * Revision history | ||
14 | * 18th Jun 2007 Initial version. | ||
15 | */ | ||
16 | |||
17 | #ifndef LM4857_H_ | ||
18 | #define LM4857_H_ | ||
19 | |||
20 | /* The register offsets in the cache array */ | ||
21 | #define LM4857_MVOL 0 | ||
22 | #define LM4857_LVOL 1 | ||
23 | #define LM4857_RVOL 2 | ||
24 | #define LM4857_CTRL 3 | ||
25 | |||
26 | /* the shifts required to set these bits */ | ||
27 | #define LM4857_3D 5 | ||
28 | #define LM4857_WAKEUP 5 | ||
29 | #define LM4857_EPGAIN 4 | ||
30 | |||
31 | #endif /*LM4857_H_*/ | ||
32 | |||
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c new file mode 100644 index 000000000000..d5a8fc2cf8d6 --- /dev/null +++ b/sound/soc/s3c24xx/neo1973_wm8753.c | |||
@@ -0,0 +1,670 @@ | |||
1 | /* | ||
2 | * neo1973_wm8753.c -- SoC audio for Neo1973 | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * Revision history | ||
14 | * 20th Jan 2007 Initial version. | ||
15 | * 05th Feb 2007 Rename all to Neo1973 | ||
16 | * | ||
17 | */ | ||
18 | |||
19 | #include <linux/module.h> | ||
20 | #include <linux/moduleparam.h> | ||
21 | #include <linux/timer.h> | ||
22 | #include <linux/interrupt.h> | ||
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <sound/driver.h> | ||
26 | #include <sound/core.h> | ||
27 | #include <sound/pcm.h> | ||
28 | #include <sound/soc.h> | ||
29 | #include <sound/soc-dapm.h> | ||
30 | |||
31 | #include <asm/mach-types.h> | ||
32 | #include <asm/hardware/scoop.h> | ||
33 | #include <asm/arch/regs-iis.h> | ||
34 | #include <asm/arch/regs-clock.h> | ||
35 | #include <asm/arch/regs-gpio.h> | ||
36 | #include <asm/hardware.h> | ||
37 | #include <asm/arch/audio.h> | ||
38 | #include <asm/io.h> | ||
39 | #include <asm/arch/spi-gpio.h> | ||
40 | #include "../codecs/wm8753.h" | ||
41 | #include "lm4857.h" | ||
42 | #include "s3c24xx-pcm.h" | ||
43 | #include "s3c24xx-i2s.h" | ||
44 | |||
45 | /* define the scenarios */ | ||
46 | #define NEO_AUDIO_OFF 0 | ||
47 | #define NEO_GSM_CALL_AUDIO_HANDSET 1 | ||
48 | #define NEO_GSM_CALL_AUDIO_HEADSET 2 | ||
49 | #define NEO_GSM_CALL_AUDIO_BLUETOOTH 3 | ||
50 | #define NEO_STEREO_TO_SPEAKERS 4 | ||
51 | #define NEO_STEREO_TO_HEADPHONES 5 | ||
52 | #define NEO_CAPTURE_HANDSET 6 | ||
53 | #define NEO_CAPTURE_HEADSET 7 | ||
54 | #define NEO_CAPTURE_BLUETOOTH 8 | ||
55 | |||
56 | static struct snd_soc_machine neo1973; | ||
57 | static struct i2c_client *i2c; | ||
58 | |||
59 | static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream, | ||
60 | struct snd_pcm_hw_params *params) | ||
61 | { | ||
62 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
63 | struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; | ||
64 | struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; | ||
65 | unsigned int pll_out = 0, bclk = 0; | ||
66 | int ret = 0; | ||
67 | unsigned long iis_clkrate; | ||
68 | |||
69 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
70 | |||
71 | switch (params_rate(params)) { | ||
72 | case 8000: | ||
73 | case 16000: | ||
74 | pll_out = 12288000; | ||
75 | break; | ||
76 | case 48000: | ||
77 | bclk = WM8753_BCLK_DIV_4; | ||
78 | pll_out = 12288000; | ||
79 | break; | ||
80 | case 96000: | ||
81 | bclk = WM8753_BCLK_DIV_2; | ||
82 | pll_out = 12288000; | ||
83 | break; | ||
84 | case 11025: | ||
85 | bclk = WM8753_BCLK_DIV_16; | ||
86 | pll_out = 11289600; | ||
87 | break; | ||
88 | case 22050: | ||
89 | bclk = WM8753_BCLK_DIV_8; | ||
90 | pll_out = 11289600; | ||
91 | break; | ||
92 | case 44100: | ||
93 | bclk = WM8753_BCLK_DIV_4; | ||
94 | pll_out = 11289600; | ||
95 | break; | ||
96 | case 88200: | ||
97 | bclk = WM8753_BCLK_DIV_2; | ||
98 | pll_out = 11289600; | ||
99 | break; | ||
100 | } | ||
101 | |||
102 | /* set codec DAI configuration */ | ||
103 | ret = codec_dai->dai_ops.set_fmt(codec_dai, | ||
104 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
105 | SND_SOC_DAIFMT_CBM_CFM); | ||
106 | if (ret < 0) | ||
107 | return ret; | ||
108 | |||
109 | /* set cpu DAI configuration */ | ||
110 | ret = cpu_dai->dai_ops.set_fmt(cpu_dai, | ||
111 | SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | | ||
112 | SND_SOC_DAIFMT_CBM_CFM); | ||
113 | if (ret < 0) | ||
114 | return ret; | ||
115 | |||
116 | /* set the codec system clock for DAC and ADC */ | ||
117 | ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_MCLK, pll_out, | ||
118 | SND_SOC_CLOCK_IN); | ||
119 | if (ret < 0) | ||
120 | return ret; | ||
121 | |||
122 | /* set MCLK division for sample rate */ | ||
123 | ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, | ||
124 | S3C2410_IISMOD_32FS ); | ||
125 | if (ret < 0) | ||
126 | return ret; | ||
127 | |||
128 | /* set codec BCLK division for sample rate */ | ||
129 | ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk); | ||
130 | if (ret < 0) | ||
131 | return ret; | ||
132 | |||
133 | /* set prescaler division for sample rate */ | ||
134 | ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, | ||
135 | S3C24XX_PRESCALE(4,4)); | ||
136 | if (ret < 0) | ||
137 | return ret; | ||
138 | |||
139 | /* codec PLL input is PCLK/4 */ | ||
140 | ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, | ||
141 | iis_clkrate / 4, pll_out); | ||
142 | if (ret < 0) | ||
143 | return ret; | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream) | ||
149 | { | ||
150 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
151 | struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; | ||
152 | |||
153 | /* disable the PLL */ | ||
154 | return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL1, 0, 0); | ||
155 | } | ||
156 | |||
157 | /* | ||
158 | * Neo1973 WM8753 HiFi DAI opserations. | ||
159 | */ | ||
160 | static struct snd_soc_ops neo1973_hifi_ops = { | ||
161 | .hw_params = neo1973_hifi_hw_params, | ||
162 | .hw_free = neo1973_hifi_hw_free, | ||
163 | }; | ||
164 | |||
165 | static int neo1973_voice_hw_params(struct snd_pcm_substream *substream, | ||
166 | struct snd_pcm_hw_params *params) | ||
167 | { | ||
168 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
169 | struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; | ||
170 | unsigned int pcmdiv = 0; | ||
171 | int ret = 0; | ||
172 | unsigned long iis_clkrate; | ||
173 | |||
174 | iis_clkrate = s3c24xx_i2s_get_clockrate(); | ||
175 | |||
176 | if (params_rate(params) != 8000) | ||
177 | return -EINVAL; | ||
178 | if (params_channels(params) != 1) | ||
179 | return -EINVAL; | ||
180 | |||
181 | pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */ | ||
182 | |||
183 | /* todo: gg check mode (DSP_B) against CSR datasheet */ | ||
184 | /* set codec DAI configuration */ | ||
185 | ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B | | ||
186 | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); | ||
187 | if (ret < 0) | ||
188 | return ret; | ||
189 | |||
190 | /* set the codec system clock for DAC and ADC */ | ||
191 | ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8753_PCMCLK, 12288000, | ||
192 | SND_SOC_CLOCK_IN); | ||
193 | if (ret < 0) | ||
194 | return ret; | ||
195 | |||
196 | /* set codec PCM division for sample rate */ | ||
197 | ret = codec_dai->dai_ops.set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv); | ||
198 | if (ret < 0) | ||
199 | return ret; | ||
200 | |||
201 | /* configue and enable PLL for 12.288MHz output */ | ||
202 | ret = codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, | ||
203 | iis_clkrate / 4, 12288000); | ||
204 | if (ret < 0) | ||
205 | return ret; | ||
206 | |||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | static int neo1973_voice_hw_free(struct snd_pcm_substream *substream) | ||
211 | { | ||
212 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
213 | struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai; | ||
214 | |||
215 | /* disable the PLL */ | ||
216 | return codec_dai->dai_ops.set_pll(codec_dai, WM8753_PLL2, 0, 0); | ||
217 | } | ||
218 | |||
219 | static struct snd_soc_ops neo1973_voice_ops = { | ||
220 | .hw_params = neo1973_voice_hw_params, | ||
221 | .hw_free = neo1973_voice_hw_free, | ||
222 | }; | ||
223 | |||
224 | static int neo1973_scenario = 0; | ||
225 | |||
226 | static int neo1973_get_scenario(struct snd_kcontrol *kcontrol, | ||
227 | struct snd_ctl_elem_value *ucontrol) | ||
228 | { | ||
229 | ucontrol->value.integer.value[0] = neo1973_scenario; | ||
230 | return 0; | ||
231 | } | ||
232 | |||
233 | static int set_scenario_endpoints(struct snd_soc_codec *codec, int scenario) | ||
234 | { | ||
235 | switch(neo1973_scenario) { | ||
236 | case NEO_AUDIO_OFF: | ||
237 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
238 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
239 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
240 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
241 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
242 | break; | ||
243 | case NEO_GSM_CALL_AUDIO_HANDSET: | ||
244 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); | ||
245 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); | ||
246 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); | ||
247 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
248 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 1); | ||
249 | break; | ||
250 | case NEO_GSM_CALL_AUDIO_HEADSET: | ||
251 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); | ||
252 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); | ||
253 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); | ||
254 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 1); | ||
255 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
256 | break; | ||
257 | case NEO_GSM_CALL_AUDIO_BLUETOOTH: | ||
258 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
259 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 1); | ||
260 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 1); | ||
261 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
262 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
263 | break; | ||
264 | case NEO_STEREO_TO_SPEAKERS: | ||
265 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); | ||
266 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
267 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
268 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
269 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
270 | break; | ||
271 | case NEO_STEREO_TO_HEADPHONES: | ||
272 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 1); | ||
273 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
274 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
275 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
276 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
277 | break; | ||
278 | case NEO_CAPTURE_HANDSET: | ||
279 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
280 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
281 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
282 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
283 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 1); | ||
284 | break; | ||
285 | case NEO_CAPTURE_HEADSET: | ||
286 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
287 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
288 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
289 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 1); | ||
290 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
291 | break; | ||
292 | case NEO_CAPTURE_BLUETOOTH: | ||
293 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
294 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
295 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
296 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
297 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
298 | break; | ||
299 | default: | ||
300 | snd_soc_dapm_set_endpoint(codec, "Audio Out", 0); | ||
301 | snd_soc_dapm_set_endpoint(codec, "GSM Line Out", 0); | ||
302 | snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0); | ||
303 | snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0); | ||
304 | snd_soc_dapm_set_endpoint(codec, "Call Mic", 0); | ||
305 | } | ||
306 | |||
307 | snd_soc_dapm_sync_endpoints(codec); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static int neo1973_set_scenario(struct snd_kcontrol *kcontrol, | ||
313 | struct snd_ctl_elem_value *ucontrol) | ||
314 | { | ||
315 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
316 | |||
317 | if (neo1973_scenario == ucontrol->value.integer.value[0]) | ||
318 | return 0; | ||
319 | |||
320 | neo1973_scenario = ucontrol->value.integer.value[0]; | ||
321 | set_scenario_endpoints(codec, neo1973_scenario); | ||
322 | return 1; | ||
323 | } | ||
324 | |||
325 | static u8 lm4857_regs[4] = {0x00, 0x40, 0x80, 0xC0}; | ||
326 | |||
327 | static void lm4857_write_regs(void) | ||
328 | { | ||
329 | if (i2c_master_send(i2c, lm4857_regs, 4) != 4) | ||
330 | printk(KERN_ERR "lm4857: i2c write failed\n"); | ||
331 | } | ||
332 | |||
333 | static int lm4857_get_reg(struct snd_kcontrol *kcontrol, | ||
334 | struct snd_ctl_elem_value *ucontrol) | ||
335 | { | ||
336 | int reg=kcontrol->private_value & 0xFF; | ||
337 | int shift = (kcontrol->private_value >> 8) & 0x0F; | ||
338 | int mask = (kcontrol->private_value >> 16) & 0xFF; | ||
339 | |||
340 | ucontrol->value.integer.value[0] = (lm4857_regs[reg] >> shift) & mask; | ||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | static int lm4857_set_reg(struct snd_kcontrol *kcontrol, | ||
345 | struct snd_ctl_elem_value *ucontrol) | ||
346 | { | ||
347 | int reg = kcontrol->private_value & 0xFF; | ||
348 | int shift = (kcontrol->private_value >> 8) & 0x0F; | ||
349 | int mask = (kcontrol->private_value >> 16) & 0xFF; | ||
350 | |||
351 | if (((lm4857_regs[reg] >> shift ) & mask) == | ||
352 | ucontrol->value.integer.value[0]) | ||
353 | return 0; | ||
354 | |||
355 | lm4857_regs[reg] &= ~ (mask << shift); | ||
356 | lm4857_regs[reg] |= ucontrol->value.integer.value[0] << shift; | ||
357 | lm4857_write_regs(); | ||
358 | return 1; | ||
359 | } | ||
360 | |||
361 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | ||
362 | struct snd_ctl_elem_value *ucontrol) | ||
363 | { | ||
364 | u8 value = lm4857_regs[LM4857_CTRL] & 0x0F; | ||
365 | |||
366 | if (value) | ||
367 | value -= 5; | ||
368 | |||
369 | ucontrol->value.integer.value[0] = value; | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | ||
374 | struct snd_ctl_elem_value *ucontrol) | ||
375 | { | ||
376 | u8 value = ucontrol->value.integer.value[0]; | ||
377 | |||
378 | if (value) | ||
379 | value += 5; | ||
380 | |||
381 | if ((lm4857_regs[LM4857_CTRL] & 0x0F) == value) | ||
382 | return 0; | ||
383 | |||
384 | lm4857_regs[LM4857_CTRL] &= 0xF0; | ||
385 | lm4857_regs[LM4857_CTRL] |= value; | ||
386 | lm4857_write_regs(); | ||
387 | return 1; | ||
388 | } | ||
389 | |||
390 | static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = { | ||
391 | SND_SOC_DAPM_LINE("Audio Out", NULL), | ||
392 | SND_SOC_DAPM_LINE("GSM Line Out", NULL), | ||
393 | SND_SOC_DAPM_LINE("GSM Line In", NULL), | ||
394 | SND_SOC_DAPM_MIC("Headset Mic", NULL), | ||
395 | SND_SOC_DAPM_MIC("Call Mic", NULL), | ||
396 | }; | ||
397 | |||
398 | |||
399 | /* example machine audio_mapnections */ | ||
400 | static const char* audio_map[][3] = { | ||
401 | |||
402 | /* Connections to the lm4857 amp */ | ||
403 | {"Audio Out", NULL, "LOUT1"}, | ||
404 | {"Audio Out", NULL, "ROUT1"}, | ||
405 | |||
406 | /* Connections to the GSM Module */ | ||
407 | {"GSM Line Out", NULL, "MONO1"}, | ||
408 | {"GSM Line Out", NULL, "MONO2"}, | ||
409 | {"RXP", NULL, "GSM Line In"}, | ||
410 | {"RXN", NULL, "GSM Line In"}, | ||
411 | |||
412 | /* Connections to Headset */ | ||
413 | {"MIC1", NULL, "Mic Bias"}, | ||
414 | {"Mic Bias", NULL, "Headset Mic"}, | ||
415 | |||
416 | /* Call Mic */ | ||
417 | {"MIC2", NULL, "Mic Bias"}, | ||
418 | {"MIC2N", NULL, "Mic Bias"}, | ||
419 | {"Mic Bias", NULL, "Call Mic"}, | ||
420 | |||
421 | /* Connect the ALC pins */ | ||
422 | {"ACIN", NULL, "ACOP"}, | ||
423 | |||
424 | {NULL, NULL, NULL}, | ||
425 | }; | ||
426 | |||
427 | static const char *lm4857_mode[] = { | ||
428 | "Off", | ||
429 | "Call Speaker", | ||
430 | "Stereo Speakers", | ||
431 | "Stereo Speakers + Headphones", | ||
432 | "Headphones" | ||
433 | }; | ||
434 | |||
435 | static const struct soc_enum lm4857_mode_enum[] = { | ||
436 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(lm4857_mode), lm4857_mode), | ||
437 | }; | ||
438 | |||
439 | static const char *neo_scenarios[] = { | ||
440 | "Off", | ||
441 | "GSM Handset", | ||
442 | "GSM Headset", | ||
443 | "GSM Bluetooth", | ||
444 | "Speakers", | ||
445 | "Headphones", | ||
446 | "Capture Handset", | ||
447 | "Capture Headset", | ||
448 | "Capture Bluetooth" | ||
449 | }; | ||
450 | |||
451 | static const struct soc_enum neo_scenario_enum[] = { | ||
452 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(neo_scenarios),neo_scenarios), | ||
453 | }; | ||
454 | |||
455 | static const struct snd_kcontrol_new wm8753_neo1973_controls[] = { | ||
456 | SOC_SINGLE_EXT("Amp Left Playback Volume", LM4857_LVOL, 0, 31, 0, | ||
457 | lm4857_get_reg, lm4857_set_reg), | ||
458 | SOC_SINGLE_EXT("Amp Right Playback Volume", LM4857_RVOL, 0, 31, 0, | ||
459 | lm4857_get_reg, lm4857_set_reg), | ||
460 | SOC_SINGLE_EXT("Amp Mono Playback Volume", LM4857_MVOL, 0, 31, 0, | ||
461 | lm4857_get_reg, lm4857_set_reg), | ||
462 | SOC_ENUM_EXT("Amp Mode", lm4857_mode_enum[0], | ||
463 | lm4857_get_mode, lm4857_set_mode), | ||
464 | SOC_ENUM_EXT("Neo Mode", neo_scenario_enum[0], | ||
465 | neo1973_get_scenario, neo1973_set_scenario), | ||
466 | SOC_SINGLE_EXT("Amp Spk 3D Playback Switch", LM4857_LVOL, 5, 1, 0, | ||
467 | lm4857_get_reg, lm4857_set_reg), | ||
468 | SOC_SINGLE_EXT("Amp HP 3d Playback Switch", LM4857_RVOL, 5, 1, 0, | ||
469 | lm4857_get_reg, lm4857_set_reg), | ||
470 | SOC_SINGLE_EXT("Amp Fast Wakeup Playback Switch", LM4857_CTRL, 5, 1, 0, | ||
471 | lm4857_get_reg, lm4857_set_reg), | ||
472 | SOC_SINGLE_EXT("Amp Earpiece 6dB Playback Switch", LM4857_CTRL, 4, 1, 0, | ||
473 | lm4857_get_reg, lm4857_set_reg), | ||
474 | }; | ||
475 | |||
476 | /* | ||
477 | * This is an example machine initialisation for a wm8753 connected to a | ||
478 | * neo1973 II. It is missing logic to detect hp/mic insertions and logic | ||
479 | * to re-route the audio in such an event. | ||
480 | */ | ||
481 | static int neo1973_wm8753_init(struct snd_soc_codec *codec) | ||
482 | { | ||
483 | int i, err; | ||
484 | |||
485 | /* set up NC codec pins */ | ||
486 | snd_soc_dapm_set_endpoint(codec, "LOUT2", 0); | ||
487 | snd_soc_dapm_set_endpoint(codec, "ROUT2", 0); | ||
488 | snd_soc_dapm_set_endpoint(codec, "OUT3", 0); | ||
489 | snd_soc_dapm_set_endpoint(codec, "OUT4", 0); | ||
490 | snd_soc_dapm_set_endpoint(codec, "LINE1", 0); | ||
491 | snd_soc_dapm_set_endpoint(codec, "LINE2", 0); | ||
492 | |||
493 | |||
494 | /* set endpoints to default mode */ | ||
495 | set_scenario_endpoints(codec, NEO_AUDIO_OFF); | ||
496 | |||
497 | /* Add neo1973 specific widgets */ | ||
498 | for (i = 0; i < ARRAY_SIZE(wm8753_dapm_widgets); i++) | ||
499 | snd_soc_dapm_new_control(codec, &wm8753_dapm_widgets[i]); | ||
500 | |||
501 | /* add neo1973 specific controls */ | ||
502 | for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_controls); i++) { | ||
503 | err = snd_ctl_add(codec->card, | ||
504 | snd_soc_cnew(&wm8753_neo1973_controls[i], | ||
505 | codec, NULL)); | ||
506 | if (err < 0) | ||
507 | return err; | ||
508 | } | ||
509 | |||
510 | /* set up neo1973 specific audio path audio_mapnects */ | ||
511 | for (i = 0; audio_map[i][0] != NULL; i++) { | ||
512 | snd_soc_dapm_connect_input(codec, audio_map[i][0], | ||
513 | audio_map[i][1], audio_map[i][2]); | ||
514 | } | ||
515 | |||
516 | snd_soc_dapm_sync_endpoints(codec); | ||
517 | return 0; | ||
518 | } | ||
519 | |||
520 | /* | ||
521 | * BT Codec DAI | ||
522 | */ | ||
523 | static struct snd_soc_cpu_dai bt_dai = | ||
524 | { .name = "Bluetooth", | ||
525 | .id = 0, | ||
526 | .type = SND_SOC_DAI_PCM, | ||
527 | .playback = { | ||
528 | .channels_min = 1, | ||
529 | .channels_max = 1, | ||
530 | .rates = SNDRV_PCM_RATE_8000, | ||
531 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
532 | .capture = { | ||
533 | .channels_min = 1, | ||
534 | .channels_max = 1, | ||
535 | .rates = SNDRV_PCM_RATE_8000, | ||
536 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
537 | }; | ||
538 | |||
539 | static struct snd_soc_dai_link neo1973_dai[] = { | ||
540 | { /* Hifi Playback - for similatious use with voice below */ | ||
541 | .name = "WM8753", | ||
542 | .stream_name = "WM8753 HiFi", | ||
543 | .cpu_dai = &s3c24xx_i2s_dai, | ||
544 | .codec_dai = &wm8753_dai[WM8753_DAI_HIFI], | ||
545 | .init = neo1973_wm8753_init, | ||
546 | .ops = &neo1973_hifi_ops, | ||
547 | }, | ||
548 | { /* Voice via BT */ | ||
549 | .name = "Bluetooth", | ||
550 | .stream_name = "Voice", | ||
551 | .cpu_dai = &bt_dai, | ||
552 | .codec_dai = &wm8753_dai[WM8753_DAI_VOICE], | ||
553 | .ops = &neo1973_voice_ops, | ||
554 | }, | ||
555 | }; | ||
556 | |||
557 | static struct snd_soc_machine neo1973 = { | ||
558 | .name = "neo1973", | ||
559 | .dai_link = neo1973_dai, | ||
560 | .num_links = ARRAY_SIZE(neo1973_dai), | ||
561 | }; | ||
562 | |||
563 | static struct wm8753_setup_data neo1973_wm8753_setup = { | ||
564 | .i2c_address = 0x1a, | ||
565 | }; | ||
566 | |||
567 | static struct snd_soc_device neo1973_snd_devdata = { | ||
568 | .machine = &neo1973, | ||
569 | .platform = &s3c24xx_soc_platform, | ||
570 | .codec_dev = &soc_codec_dev_wm8753, | ||
571 | .codec_data = &neo1973_wm8753_setup, | ||
572 | }; | ||
573 | |||
574 | static struct i2c_client client_template; | ||
575 | |||
576 | static unsigned short normal_i2c[] = { 0x7C, I2C_CLIENT_END }; | ||
577 | |||
578 | /* Magic definition of all other variables and things */ | ||
579 | I2C_CLIENT_INSMOD; | ||
580 | |||
581 | static int lm4857_amp_probe(struct i2c_adapter *adap, int addr, int kind) | ||
582 | { | ||
583 | int ret; | ||
584 | |||
585 | client_template.adapter = adap; | ||
586 | client_template.addr = addr; | ||
587 | |||
588 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
589 | if (i2c == NULL) | ||
590 | return -ENOMEM; | ||
591 | |||
592 | ret = i2c_attach_client(i2c); | ||
593 | if (ret < 0) { | ||
594 | printk(KERN_ERR "LM4857 failed to attach at addr %x\n", addr); | ||
595 | goto exit_err; | ||
596 | } | ||
597 | |||
598 | lm4857_write_regs(); | ||
599 | return ret; | ||
600 | |||
601 | exit_err: | ||
602 | kfree(i2c); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
606 | static int lm4857_i2c_detach(struct i2c_client *client) | ||
607 | { | ||
608 | i2c_detach_client(client); | ||
609 | kfree(client); | ||
610 | return 0; | ||
611 | } | ||
612 | |||
613 | static int lm4857_i2c_attach(struct i2c_adapter *adap) | ||
614 | { | ||
615 | return i2c_probe(adap, &addr_data, lm4857_amp_probe); | ||
616 | } | ||
617 | |||
618 | /* corgi i2c codec control layer */ | ||
619 | static struct i2c_driver lm4857_i2c_driver = { | ||
620 | .driver = { | ||
621 | .name = "LM4857 I2C Amp", | ||
622 | .owner = THIS_MODULE, | ||
623 | }, | ||
624 | .id = I2C_DRIVERID_LM4857, | ||
625 | .attach_adapter = lm4857_i2c_attach, | ||
626 | .detach_client = lm4857_i2c_detach, | ||
627 | .command = NULL, | ||
628 | }; | ||
629 | |||
630 | static struct i2c_client client_template = { | ||
631 | .name = "LM4857", | ||
632 | .driver = &lm4857_i2c_driver, | ||
633 | }; | ||
634 | |||
635 | static struct platform_device *neo1973_snd_device; | ||
636 | |||
637 | static int __init neo1973_init(void) | ||
638 | { | ||
639 | int ret; | ||
640 | |||
641 | neo1973_snd_device = platform_device_alloc("soc-audio", -1); | ||
642 | if (!neo1973_snd_device) | ||
643 | return -ENOMEM; | ||
644 | |||
645 | platform_set_drvdata(neo1973_snd_device, &neo1973_snd_devdata); | ||
646 | neo1973_snd_devdata.dev = &neo1973_snd_device->dev; | ||
647 | ret = platform_device_add(neo1973_snd_device); | ||
648 | |||
649 | if (ret) | ||
650 | platform_device_put(neo1973_snd_device); | ||
651 | |||
652 | ret = i2c_add_driver(&lm4857_i2c_driver); | ||
653 | if (ret != 0) | ||
654 | printk(KERN_ERR "can't add i2c driver"); | ||
655 | |||
656 | return ret; | ||
657 | } | ||
658 | |||
659 | static void __exit neo1973_exit(void) | ||
660 | { | ||
661 | platform_device_unregister(neo1973_snd_device); | ||
662 | } | ||
663 | |||
664 | module_init(neo1973_init); | ||
665 | module_exit(neo1973_exit); | ||
666 | |||
667 | /* Module information */ | ||
668 | MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com"); | ||
669 | MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973"); | ||
670 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c new file mode 100644 index 000000000000..75acf7ef5528 --- /dev/null +++ b/sound/soc/s3c24xx/s3c2443-ac97.c | |||
@@ -0,0 +1,401 @@ | |||
1 | /* | ||
2 | * s3c2443-ac97.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2007 Wolfson Microelectronics PLC. | ||
5 | * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
6 | * | ||
7 | * Copyright (C) 2005, Sean Choi <sh428.choi@samsung.com> | ||
8 | * All rights reserved. | ||
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 | * Revision history | ||
15 | * 21st Mar 2007 Initial Version | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/clk.h> | ||
25 | |||
26 | #include <sound/driver.h> | ||
27 | #include <sound/core.h> | ||
28 | #include <sound/pcm.h> | ||
29 | #include <sound/ac97_codec.h> | ||
30 | #include <sound/initval.h> | ||
31 | #include <sound/soc.h> | ||
32 | |||
33 | #include <asm/hardware.h> | ||
34 | #include <asm/io.h> | ||
35 | #include <asm/arch/regs-ac97.h> | ||
36 | #include <asm/arch/regs-gpio.h> | ||
37 | #include <asm/arch/regs-clock.h> | ||
38 | #include <asm/arch/audio.h> | ||
39 | #include <asm/dma.h> | ||
40 | #include <asm/arch/dma.h> | ||
41 | |||
42 | #include "s3c24xx-pcm.h" | ||
43 | #include "s3c24xx-ac97.h" | ||
44 | |||
45 | struct s3c24xx_ac97_info { | ||
46 | void __iomem *regs; | ||
47 | struct clk *ac97_clk; | ||
48 | }; | ||
49 | static struct s3c24xx_ac97_info s3c24xx_ac97; | ||
50 | |||
51 | DECLARE_COMPLETION(ac97_completion); | ||
52 | static u32 codec_ready; | ||
53 | static DECLARE_MUTEX(ac97_mutex); | ||
54 | |||
55 | static unsigned short s3c2443_ac97_read(struct snd_ac97 *ac97, | ||
56 | unsigned short reg) | ||
57 | { | ||
58 | u32 ac_glbctrl; | ||
59 | u32 ac_codec_cmd; | ||
60 | u32 stat, addr, data; | ||
61 | |||
62 | down(&ac97_mutex); | ||
63 | |||
64 | codec_ready = S3C_AC97_GLBSTAT_CODECREADY; | ||
65 | ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
66 | ac_codec_cmd = S3C_AC97_CODEC_CMD_READ | AC_CMD_ADDR(reg); | ||
67 | writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
68 | |||
69 | udelay(50); | ||
70 | |||
71 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
72 | ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; | ||
73 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
74 | |||
75 | wait_for_completion(&ac97_completion); | ||
76 | |||
77 | stat = readl(s3c24xx_ac97.regs + S3C_AC97_STAT); | ||
78 | addr = (stat >> 16) & 0x7f; | ||
79 | data = (stat & 0xffff); | ||
80 | |||
81 | if (addr != reg) | ||
82 | printk(KERN_ERR "s3c24xx-ac97: req addr = %02x," | ||
83 | " rep addr = %02x\n", reg, addr); | ||
84 | |||
85 | up(&ac97_mutex); | ||
86 | |||
87 | return (unsigned short)data; | ||
88 | } | ||
89 | |||
90 | static void s3c2443_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
91 | unsigned short val) | ||
92 | { | ||
93 | u32 ac_glbctrl; | ||
94 | u32 ac_codec_cmd; | ||
95 | |||
96 | down(&ac97_mutex); | ||
97 | |||
98 | codec_ready = S3C_AC97_GLBSTAT_CODECREADY; | ||
99 | ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
100 | ac_codec_cmd = AC_CMD_ADDR(reg) | AC_CMD_DATA(val); | ||
101 | writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
102 | |||
103 | udelay(50); | ||
104 | |||
105 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
106 | ac_glbctrl |= S3C_AC97_GLBCTRL_CODECREADYIE; | ||
107 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
108 | |||
109 | wait_for_completion(&ac97_completion); | ||
110 | |||
111 | ac_codec_cmd = readl(s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
112 | ac_codec_cmd |= S3C_AC97_CODEC_CMD_READ; | ||
113 | writel(ac_codec_cmd, s3c24xx_ac97.regs + S3C_AC97_CODEC_CMD); | ||
114 | |||
115 | up(&ac97_mutex); | ||
116 | |||
117 | } | ||
118 | |||
119 | static void s3c2443_ac97_warm_reset(struct snd_ac97 *ac97) | ||
120 | { | ||
121 | u32 ac_glbctrl; | ||
122 | |||
123 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
124 | ac_glbctrl = S3C_AC97_GLBCTRL_WARMRESET; | ||
125 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
126 | msleep(1); | ||
127 | |||
128 | ac_glbctrl = 0; | ||
129 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
130 | msleep(1); | ||
131 | } | ||
132 | |||
133 | static void s3c2443_ac97_cold_reset(struct snd_ac97 *ac97) | ||
134 | { | ||
135 | u32 ac_glbctrl; | ||
136 | |||
137 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
138 | ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET; | ||
139 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
140 | msleep(1); | ||
141 | |||
142 | ac_glbctrl = 0; | ||
143 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
144 | msleep(1); | ||
145 | |||
146 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
147 | ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; | ||
148 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
149 | msleep(1); | ||
150 | |||
151 | ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; | ||
152 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
153 | msleep(1); | ||
154 | |||
155 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA | | ||
156 | S3C_AC97_GLBCTRL_PCMINTM_DMA | S3C_AC97_GLBCTRL_MICINTM_DMA; | ||
157 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
158 | } | ||
159 | |||
160 | static irqreturn_t s3c2443_ac97_irq(int irq, void *dev_id) | ||
161 | { | ||
162 | int status; | ||
163 | u32 ac_glbctrl; | ||
164 | |||
165 | status = readl(s3c24xx_ac97.regs + S3C_AC97_GLBSTAT) & codec_ready; | ||
166 | |||
167 | if (status) { | ||
168 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
169 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_CODECREADYIE; | ||
170 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
171 | complete(&ac97_completion); | ||
172 | } | ||
173 | return IRQ_HANDLED; | ||
174 | } | ||
175 | |||
176 | struct snd_ac97_bus_ops soc_ac97_ops = { | ||
177 | .read = s3c2443_ac97_read, | ||
178 | .write = s3c2443_ac97_write, | ||
179 | .warm_reset = s3c2443_ac97_warm_reset, | ||
180 | .reset = s3c2443_ac97_cold_reset, | ||
181 | }; | ||
182 | |||
183 | static struct s3c2410_dma_client s3c2443_dma_client_out = { | ||
184 | .name = "AC97 PCM Stereo out" | ||
185 | }; | ||
186 | |||
187 | static struct s3c2410_dma_client s3c2443_dma_client_in = { | ||
188 | .name = "AC97 PCM Stereo in" | ||
189 | }; | ||
190 | |||
191 | static struct s3c2410_dma_client s3c2443_dma_client_micin = { | ||
192 | .name = "AC97 Mic Mono in" | ||
193 | }; | ||
194 | |||
195 | static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_out = { | ||
196 | .client = &s3c2443_dma_client_out, | ||
197 | .channel = DMACH_PCM_OUT, | ||
198 | .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, | ||
199 | .dma_size = 4, | ||
200 | }; | ||
201 | |||
202 | static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_in = { | ||
203 | .client = &s3c2443_dma_client_in, | ||
204 | .channel = DMACH_PCM_IN, | ||
205 | .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, | ||
206 | .dma_size = 4, | ||
207 | }; | ||
208 | |||
209 | static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = { | ||
210 | .client = &s3c2443_dma_client_micin, | ||
211 | .channel = DMACH_MIC_IN, | ||
212 | .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA, | ||
213 | .dma_size = 4, | ||
214 | }; | ||
215 | |||
216 | static int s3c2443_ac97_probe(struct platform_device *pdev) | ||
217 | { | ||
218 | int ret; | ||
219 | u32 ac_glbctrl; | ||
220 | |||
221 | s3c24xx_ac97.regs = ioremap(S3C2440_PA_AC97, 0x100); | ||
222 | if (s3c24xx_ac97.regs == NULL) | ||
223 | return -ENXIO; | ||
224 | |||
225 | s3c24xx_ac97.ac97_clk = clk_get(&pdev->dev, "ac97"); | ||
226 | if (s3c24xx_ac97.ac97_clk == NULL) { | ||
227 | printk(KERN_ERR "s3c2443-ac97 failed to get ac97_clock\n"); | ||
228 | iounmap(s3c24xx_ac97.regs); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | clk_enable(s3c24xx_ac97.ac97_clk); | ||
232 | |||
233 | s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2443_GPE0_AC_nRESET); | ||
234 | s3c2410_gpio_cfgpin(S3C2410_GPE1, S3C2443_GPE1_AC_SYNC); | ||
235 | s3c2410_gpio_cfgpin(S3C2410_GPE2, S3C2443_GPE2_AC_BITCLK); | ||
236 | s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2443_GPE3_AC_SDI); | ||
237 | s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2443_GPE4_AC_SDO); | ||
238 | |||
239 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
240 | ac_glbctrl = S3C_AC97_GLBCTRL_COLDRESET; | ||
241 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
242 | msleep(1); | ||
243 | |||
244 | ac_glbctrl = 0; | ||
245 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
246 | msleep(1); | ||
247 | |||
248 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
249 | ac_glbctrl = S3C_AC97_GLBCTRL_ACLINKON; | ||
250 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
251 | msleep(1); | ||
252 | |||
253 | ac_glbctrl |= S3C_AC97_GLBCTRL_TRANSFERDATAENABLE; | ||
254 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
255 | |||
256 | ret = request_irq(IRQ_S3C2443_AC97, s3c2443_ac97_irq, | ||
257 | IRQF_DISABLED, "AC97", NULL); | ||
258 | if (ret < 0) { | ||
259 | printk(KERN_ERR "s3c24xx-ac97: interrupt request failed.\n"); | ||
260 | clk_disable(s3c24xx_ac97.ac97_clk); | ||
261 | clk_put(s3c24xx_ac97.ac97_clk); | ||
262 | iounmap(s3c24xx_ac97.regs); | ||
263 | } | ||
264 | return ret; | ||
265 | } | ||
266 | |||
267 | static void s3c2443_ac97_remove(struct platform_device *pdev) | ||
268 | { | ||
269 | free_irq(IRQ_S3C2443_AC97, NULL); | ||
270 | clk_disable(s3c24xx_ac97.ac97_clk); | ||
271 | clk_put(s3c24xx_ac97.ac97_clk); | ||
272 | iounmap(s3c24xx_ac97.regs); | ||
273 | } | ||
274 | |||
275 | static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream, | ||
276 | struct snd_pcm_hw_params *params) | ||
277 | { | ||
278 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
279 | struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; | ||
280 | |||
281 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
282 | cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_out; | ||
283 | else | ||
284 | cpu_dai->dma_data = &s3c2443_ac97_pcm_stereo_in; | ||
285 | |||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd) | ||
290 | { | ||
291 | u32 ac_glbctrl; | ||
292 | |||
293 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
294 | switch(cmd) { | ||
295 | case SNDRV_PCM_TRIGGER_START: | ||
296 | case SNDRV_PCM_TRIGGER_RESUME: | ||
297 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
298 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
299 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; | ||
300 | else | ||
301 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMOUTTM_DMA; | ||
302 | break; | ||
303 | case SNDRV_PCM_TRIGGER_STOP: | ||
304 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
305 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
306 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | ||
307 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; | ||
308 | else | ||
309 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMOUTTM_MASK; | ||
310 | break; | ||
311 | } | ||
312 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream, | ||
318 | struct snd_pcm_hw_params *params) | ||
319 | { | ||
320 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
321 | struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai; | ||
322 | |||
323 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | ||
324 | return -ENODEV; | ||
325 | else | ||
326 | cpu_dai->dma_data = &s3c2443_ac97_mic_mono_in; | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream, | ||
332 | int cmd) | ||
333 | { | ||
334 | u32 ac_glbctrl; | ||
335 | |||
336 | ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
337 | switch(cmd) { | ||
338 | case SNDRV_PCM_TRIGGER_START: | ||
339 | case SNDRV_PCM_TRIGGER_RESUME: | ||
340 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | ||
341 | ac_glbctrl |= S3C_AC97_GLBCTRL_PCMINTM_DMA; | ||
342 | break; | ||
343 | case SNDRV_PCM_TRIGGER_STOP: | ||
344 | case SNDRV_PCM_TRIGGER_SUSPEND: | ||
345 | case SNDRV_PCM_TRIGGER_PAUSE_PUSH: | ||
346 | ac_glbctrl &= ~S3C_AC97_GLBCTRL_PCMINTM_MASK; | ||
347 | } | ||
348 | writel(ac_glbctrl, s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | |||
353 | #define s3c2443_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | ||
354 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ | ||
355 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
356 | |||
357 | struct snd_soc_cpu_dai s3c2443_ac97_dai[] = { | ||
358 | { | ||
359 | .name = "s3c2443-ac97", | ||
360 | .id = 0, | ||
361 | .type = SND_SOC_DAI_AC97, | ||
362 | .probe = s3c2443_ac97_probe, | ||
363 | .remove = s3c2443_ac97_remove, | ||
364 | .playback = { | ||
365 | .stream_name = "AC97 Playback", | ||
366 | .channels_min = 2, | ||
367 | .channels_max = 2, | ||
368 | .rates = s3c2443_AC97_RATES, | ||
369 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
370 | .capture = { | ||
371 | .stream_name = "AC97 Capture", | ||
372 | .channels_min = 2, | ||
373 | .channels_max = 2, | ||
374 | .rates = s3c2443_AC97_RATES, | ||
375 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
376 | .ops = { | ||
377 | .hw_params = s3c2443_ac97_hw_params, | ||
378 | .trigger = s3c2443_ac97_trigger}, | ||
379 | }, | ||
380 | { | ||
381 | .name = "pxa2xx-ac97-mic", | ||
382 | .id = 1, | ||
383 | .type = SND_SOC_DAI_AC97, | ||
384 | .capture = { | ||
385 | .stream_name = "AC97 Mic Capture", | ||
386 | .channels_min = 1, | ||
387 | .channels_max = 1, | ||
388 | .rates = s3c2443_AC97_RATES, | ||
389 | .formats = SNDRV_PCM_FMTBIT_S16_LE,}, | ||
390 | .ops = { | ||
391 | .hw_params = s3c2443_ac97_hw_mic_params, | ||
392 | .trigger = s3c2443_ac97_mic_trigger,}, | ||
393 | }, | ||
394 | }; | ||
395 | |||
396 | EXPORT_SYMBOL_GPL(s3c2443_ac97_dai); | ||
397 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
398 | |||
399 | MODULE_AUTHOR("Graeme Gregory"); | ||
400 | MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip"); | ||
401 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/s3c24xx/s3c24xx-ac97.h b/sound/soc/s3c24xx/s3c24xx-ac97.h new file mode 100644 index 000000000000..2b835e8260fa --- /dev/null +++ b/sound/soc/s3c24xx/s3c24xx-ac97.h | |||
@@ -0,0 +1,25 @@ | |||
1 | /* | ||
2 | * s3c24xx-ac97.c -- ALSA Soc Audio Layer | ||
3 | * | ||
4 | * (c) 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * Revision history | ||
14 | * 10th Nov 2006 Initial version. | ||
15 | */ | ||
16 | |||
17 | #ifndef S3C24XXAC97_H_ | ||
18 | #define S3C24XXAC97_H_ | ||
19 | |||
20 | #define AC_CMD_ADDR(x) (x << 16) | ||
21 | #define AC_CMD_DATA(x) (x & 0xffff) | ||
22 | |||
23 | extern struct snd_soc_cpu_dai s3c2443_ac97_dai[]; | ||
24 | |||
25 | #endif /*S3C24XXAC97_H_*/ | ||
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c index 8ca314dc8891..39f02462e07d 100644 --- a/sound/soc/s3c24xx/s3c24xx-i2s.c +++ b/sound/soc/s3c24xx/s3c24xx-i2s.c | |||
@@ -344,11 +344,11 @@ static int s3c24xx_i2s_set_clkdiv(struct snd_soc_cpu_dai *cpu_dai, | |||
344 | DBG("Entered %s\n", __FUNCTION__); | 344 | DBG("Entered %s\n", __FUNCTION__); |
345 | 345 | ||
346 | switch (div_id) { | 346 | switch (div_id) { |
347 | case S3C24XX_DIV_MCLK: | 347 | case S3C24XX_DIV_BCLK: |
348 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; | 348 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~S3C2410_IISMOD_FS_MASK; |
349 | writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); | 349 | writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); |
350 | break; | 350 | break; |
351 | case S3C24XX_DIV_BCLK: | 351 | case S3C24XX_DIV_MCLK: |
352 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS); | 352 | reg = readl(s3c24xx_i2s.regs + S3C2410_IISMOD) & ~(S3C2410_IISMOD_384FS); |
353 | writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); | 353 | writel(reg | div, s3c24xx_i2s.regs + S3C2410_IISMOD); |
354 | break; | 354 | break; |
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c new file mode 100644 index 000000000000..d46cd811ceb3 --- /dev/null +++ b/sound/soc/s3c24xx/smdk2443_wm9710.c | |||
@@ -0,0 +1,85 @@ | |||
1 | /* | ||
2 | * smdk2443_wm9710.c -- SoC audio for smdk2443 | ||
3 | * | ||
4 | * Copyright 2007 Wolfson Microelectronics PLC. | ||
5 | * Author: Graeme Gregory | ||
6 | * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * Revision history | ||
14 | * 8th Mar 2007 Initial version. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/device.h> | ||
20 | #include <sound/driver.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 "../codecs/ac97.h" | ||
27 | #include "s3c24xx-pcm.h" | ||
28 | #include "s3c24xx-ac97.h" | ||
29 | |||
30 | static struct snd_soc_machine smdk2443; | ||
31 | |||
32 | static struct snd_soc_dai_link smdk2443_dai[] = { | ||
33 | { | ||
34 | .name = "AC97", | ||
35 | .stream_name = "AC97 HiFi", | ||
36 | .cpu_dai = &s3c2443_ac97_dai[0], | ||
37 | .codec_dai = &ac97_dai, | ||
38 | }, | ||
39 | }; | ||
40 | |||
41 | static struct snd_soc_machine smdk2443 = { | ||
42 | .name = "SMDK2443", | ||
43 | .dai_link = smdk2443_dai, | ||
44 | .num_links = ARRAY_SIZE(smdk2443_dai), | ||
45 | }; | ||
46 | |||
47 | static struct snd_soc_device smdk2443_snd_ac97_devdata = { | ||
48 | .machine = &smdk2443, | ||
49 | .platform = &s3c24xx_soc_platform, | ||
50 | .codec_dev = &soc_codec_dev_ac97, | ||
51 | }; | ||
52 | |||
53 | static struct platform_device *smdk2443_snd_ac97_device; | ||
54 | |||
55 | static int __init smdk2443_init(void) | ||
56 | { | ||
57 | int ret; | ||
58 | |||
59 | smdk2443_snd_ac97_device = platform_device_alloc("soc-audio", -1); | ||
60 | if (!smdk2443_snd_ac97_device) | ||
61 | return -ENOMEM; | ||
62 | |||
63 | platform_set_drvdata(smdk2443_snd_ac97_device, | ||
64 | &smdk2443_snd_ac97_devdata); | ||
65 | smdk2443_snd_ac97_devdata.dev = &smdk2443_snd_ac97_device->dev; | ||
66 | ret = platform_device_add(smdk2443_snd_ac97_device); | ||
67 | |||
68 | if (ret) | ||
69 | platform_device_put(smdk2443_snd_ac97_device); | ||
70 | |||
71 | return ret; | ||
72 | } | ||
73 | |||
74 | static void __exit smdk2443_exit(void) | ||
75 | { | ||
76 | platform_device_unregister(smdk2443_snd_ac97_device); | ||
77 | } | ||
78 | |||
79 | module_init(smdk2443_init); | ||
80 | module_exit(smdk2443_exit); | ||
81 | |||
82 | /* Module information */ | ||
83 | MODULE_AUTHOR("Graeme Gregory, graeme.gregory@wolfsonmicro.com, www.wolfsonmicro.com"); | ||
84 | MODULE_DESCRIPTION("ALSA SoC WM9710 SMDK2443"); | ||
85 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig new file mode 100644 index 000000000000..f03220d23e73 --- /dev/null +++ b/sound/soc/sh/Kconfig | |||
@@ -0,0 +1,38 @@ | |||
1 | menu "SoC Audio support for SuperH" | ||
2 | |||
3 | config SND_SOC_PCM_SH7760 | ||
4 | tristate "SoC Audio support for Renesas SH7760" | ||
5 | depends on CPU_SUBTYPE_SH7760 && SND_SOC && SH_DMABRG | ||
6 | help | ||
7 | Enable this option for SH7760 AC97/I2S audio support. | ||
8 | |||
9 | |||
10 | ## | ||
11 | ## Audio unit modules | ||
12 | ## | ||
13 | |||
14 | config SND_SOC_SH4_HAC | ||
15 | select AC97_BUS | ||
16 | select SND_SOC_AC97_BUS | ||
17 | select SND_AC97_CODEC | ||
18 | tristate | ||
19 | |||
20 | config SND_SOC_SH4_SSI | ||
21 | tristate | ||
22 | |||
23 | |||
24 | |||
25 | ## | ||
26 | ## Boards | ||
27 | ## | ||
28 | |||
29 | config SND_SH7760_AC97 | ||
30 | tristate "SH7760 AC97 sound support" | ||
31 | depends on CPU_SUBTYPE_SH7760 && SND_SOC_PCM_SH7760 | ||
32 | select SND_SOC_SH4_HAC | ||
33 | select SND_SOC_AC97_CODEC | ||
34 | help | ||
35 | This option enables generic sound support for the first | ||
36 | AC97 unit of the SH7760. | ||
37 | |||
38 | endmenu | ||
diff --git a/sound/soc/sh/Makefile b/sound/soc/sh/Makefile new file mode 100644 index 000000000000..a8e8ab81cc6a --- /dev/null +++ b/sound/soc/sh/Makefile | |||
@@ -0,0 +1,14 @@ | |||
1 | ## DMA engines | ||
2 | snd-soc-dma-sh7760-objs := dma-sh7760.o | ||
3 | obj-$(CONFIG_SND_SOC_PCM_SH7760) += snd-soc-dma-sh7760.o | ||
4 | |||
5 | ## audio units found on some SH-4 | ||
6 | snd-soc-hac-objs := hac.o | ||
7 | snd-soc-ssi-objs := ssi.o | ||
8 | obj-$(CONFIG_SND_SOC_SH4_HAC) += snd-soc-hac.o | ||
9 | obj-$(CONFIG_SND_SOC_SH4_SSI) += snd-soc-ssi.o | ||
10 | |||
11 | ## boards | ||
12 | snd-soc-sh7760-ac97-objs := sh7760-ac97.o | ||
13 | |||
14 | obj-$(CONFIG_SND_SH7760_AC97) += snd-soc-sh7760-ac97.o | ||
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c new file mode 100644 index 000000000000..cdee374b843e --- /dev/null +++ b/sound/soc/sh/dma-sh7760.c | |||
@@ -0,0 +1,354 @@ | |||
1 | /* | ||
2 | * SH7760 ("camelot") DMABRG audio DMA unit support | ||
3 | * | ||
4 | * Copyright (C) 2007 Manuel Lauss <mano@roarinelk.homelinux.net> | ||
5 | * licensed under the terms outlined in the file COPYING at the root | ||
6 | * of the linux kernel sources. | ||
7 | * | ||
8 | * The SH7760 DMABRG provides 4 dma channels (2x rec, 2x play), which | ||
9 | * trigger an interrupt when one half of the programmed transfer size | ||
10 | * has been xmitted. | ||
11 | * | ||
12 | * FIXME: little-endian only for now | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | #include <sound/driver.h> | ||
20 | #include <sound/core.h> | ||
21 | #include <sound/pcm.h> | ||
22 | #include <sound/pcm_params.h> | ||
23 | #include <sound/soc.h> | ||
24 | #include <asm/dmabrg.h> | ||
25 | |||
26 | |||
27 | /* registers and bits */ | ||
28 | #define BRGATXSAR 0x00 | ||
29 | #define BRGARXDAR 0x04 | ||
30 | #define BRGATXTCR 0x08 | ||
31 | #define BRGARXTCR 0x0C | ||
32 | #define BRGACR 0x10 | ||
33 | #define BRGATXTCNT 0x14 | ||
34 | #define BRGARXTCNT 0x18 | ||
35 | |||
36 | #define ACR_RAR (1 << 18) | ||
37 | #define ACR_RDS (1 << 17) | ||
38 | #define ACR_RDE (1 << 16) | ||
39 | #define ACR_TAR (1 << 2) | ||
40 | #define ACR_TDS (1 << 1) | ||
41 | #define ACR_TDE (1 << 0) | ||
42 | |||
43 | /* receiver/transmitter data alignment */ | ||
44 | #define ACR_RAM_NONE (0 << 24) | ||
45 | #define ACR_RAM_4BYTE (1 << 24) | ||
46 | #define ACR_RAM_2WORD (2 << 24) | ||
47 | #define ACR_TAM_NONE (0 << 8) | ||
48 | #define ACR_TAM_4BYTE (1 << 8) | ||
49 | #define ACR_TAM_2WORD (2 << 8) | ||
50 | |||
51 | |||
52 | struct camelot_pcm { | ||
53 | unsigned long mmio; /* DMABRG audio channel control reg MMIO */ | ||
54 | unsigned int txid; /* ID of first DMABRG IRQ for this unit */ | ||
55 | |||
56 | struct snd_pcm_substream *tx_ss; | ||
57 | unsigned long tx_period_size; | ||
58 | unsigned int tx_period; | ||
59 | |||
60 | struct snd_pcm_substream *rx_ss; | ||
61 | unsigned long rx_period_size; | ||
62 | unsigned int rx_period; | ||
63 | |||
64 | } cam_pcm_data[2] = { | ||
65 | { | ||
66 | .mmio = 0xFE3C0040, | ||
67 | .txid = DMABRGIRQ_A0TXF, | ||
68 | }, | ||
69 | { | ||
70 | .mmio = 0xFE3C0060, | ||
71 | .txid = DMABRGIRQ_A1TXF, | ||
72 | }, | ||
73 | }; | ||
74 | |||
75 | #define BRGREG(x) (*(unsigned long *)(cam->mmio + (x))) | ||
76 | |||
77 | /* | ||
78 | * set a minimum of 16kb per period, to avoid interrupt-"storm" and | ||
79 | * resulting skipping. In general, the bigger the minimum size, the | ||
80 | * better for overall system performance. (The SH7760 is a puny CPU | ||
81 | * with a slow SDRAM interface and poor internal bus bandwidth, | ||
82 | * *especially* when the LCDC is active). The minimum for the DMAC | ||
83 | * is 8 bytes; 16kbytes are enough to get skip-free playback of a | ||
84 | * 44kHz/16bit/stereo MP3 on a lightly loaded system, and maintain | ||
85 | * reasonable responsiveness in MPlayer. | ||
86 | */ | ||
87 | #define DMABRG_PERIOD_MIN 16 * 1024 | ||
88 | #define DMABRG_PERIOD_MAX 0x03fffffc | ||
89 | #define DMABRG_PREALLOC_BUFFER 32 * 1024 | ||
90 | #define DMABRG_PREALLOC_BUFFER_MAX 32 * 1024 | ||
91 | |||
92 | /* support everything the SSI supports */ | ||
93 | #define DMABRG_RATES \ | ||
94 | SNDRV_PCM_RATE_8000_192000 | ||
95 | |||
96 | #define DMABRG_FMTS \ | ||
97 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
98 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
99 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ | ||
100 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ | ||
101 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) | ||
102 | |||
103 | static struct snd_pcm_hardware camelot_pcm_hardware = { | ||
104 | .info = (SNDRV_PCM_INFO_MMAP | | ||
105 | SNDRV_PCM_INFO_INTERLEAVED | | ||
106 | SNDRV_PCM_INFO_BLOCK_TRANSFER | | ||
107 | SNDRV_PCM_INFO_MMAP_VALID), | ||
108 | .formats = DMABRG_FMTS, | ||
109 | .rates = DMABRG_RATES, | ||
110 | .rate_min = 8000, | ||
111 | .rate_max = 192000, | ||
112 | .channels_min = 2, | ||
113 | .channels_max = 8, /* max of the SSI */ | ||
114 | .buffer_bytes_max = DMABRG_PERIOD_MAX, | ||
115 | .period_bytes_min = DMABRG_PERIOD_MIN, | ||
116 | .period_bytes_max = DMABRG_PERIOD_MAX / 2, | ||
117 | .periods_min = 2, | ||
118 | .periods_max = 2, | ||
119 | .fifo_size = 128, | ||
120 | }; | ||
121 | |||
122 | static void camelot_txdma(void *data) | ||
123 | { | ||
124 | struct camelot_pcm *cam = data; | ||
125 | cam->tx_period ^= 1; | ||
126 | snd_pcm_period_elapsed(cam->tx_ss); | ||
127 | } | ||
128 | |||
129 | static void camelot_rxdma(void *data) | ||
130 | { | ||
131 | struct camelot_pcm *cam = data; | ||
132 | cam->rx_period ^= 1; | ||
133 | snd_pcm_period_elapsed(cam->rx_ss); | ||
134 | } | ||
135 | |||
136 | static int camelot_pcm_open(struct snd_pcm_substream *substream) | ||
137 | { | ||
138 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
139 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
140 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | ||
141 | int ret, dmairq; | ||
142 | |||
143 | snd_soc_set_runtime_hwparams(substream, &camelot_pcm_hardware); | ||
144 | |||
145 | /* DMABRG buffer half/full events */ | ||
146 | dmairq = (recv) ? cam->txid + 2 : cam->txid; | ||
147 | if (recv) { | ||
148 | cam->rx_ss = substream; | ||
149 | ret = dmabrg_request_irq(dmairq, camelot_rxdma, cam); | ||
150 | if (unlikely(ret)) { | ||
151 | pr_debug("audio unit %d irqs already taken!\n", | ||
152 | rtd->dai->cpu_dai->id); | ||
153 | return -EBUSY; | ||
154 | } | ||
155 | (void)dmabrg_request_irq(dmairq + 1,camelot_rxdma, cam); | ||
156 | } else { | ||
157 | cam->tx_ss = substream; | ||
158 | ret = dmabrg_request_irq(dmairq, camelot_txdma, cam); | ||
159 | if (unlikely(ret)) { | ||
160 | pr_debug("audio unit %d irqs already taken!\n", | ||
161 | rtd->dai->cpu_dai->id); | ||
162 | return -EBUSY; | ||
163 | } | ||
164 | (void)dmabrg_request_irq(dmairq + 1, camelot_txdma, cam); | ||
165 | } | ||
166 | return 0; | ||
167 | } | ||
168 | |||
169 | static int camelot_pcm_close(struct snd_pcm_substream *substream) | ||
170 | { | ||
171 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
172 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
173 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | ||
174 | int dmairq; | ||
175 | |||
176 | dmairq = (recv) ? cam->txid + 2 : cam->txid; | ||
177 | |||
178 | if (recv) | ||
179 | cam->rx_ss = NULL; | ||
180 | else | ||
181 | cam->tx_ss = NULL; | ||
182 | |||
183 | dmabrg_free_irq(dmairq + 1); | ||
184 | dmabrg_free_irq(dmairq); | ||
185 | |||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static int camelot_hw_params(struct snd_pcm_substream *substream, | ||
190 | struct snd_pcm_hw_params *hw_params) | ||
191 | { | ||
192 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
193 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
194 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | ||
195 | int ret; | ||
196 | |||
197 | ret = snd_pcm_lib_malloc_pages(substream, | ||
198 | params_buffer_bytes(hw_params)); | ||
199 | if (ret < 0) | ||
200 | return ret; | ||
201 | |||
202 | if (recv) { | ||
203 | cam->rx_period_size = params_period_bytes(hw_params); | ||
204 | cam->rx_period = 0; | ||
205 | } else { | ||
206 | cam->tx_period_size = params_period_bytes(hw_params); | ||
207 | cam->tx_period = 0; | ||
208 | } | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int camelot_hw_free(struct snd_pcm_substream *substream) | ||
213 | { | ||
214 | return snd_pcm_lib_free_pages(substream); | ||
215 | } | ||
216 | |||
217 | static int camelot_prepare(struct snd_pcm_substream *substream) | ||
218 | { | ||
219 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
220 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
221 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
222 | |||
223 | pr_debug("PCM data: addr 0x%08ulx len %d\n", | ||
224 | (u32)runtime->dma_addr, runtime->dma_bytes); | ||
225 | |||
226 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | ||
227 | BRGREG(BRGATXSAR) = (unsigned long)runtime->dma_area; | ||
228 | BRGREG(BRGATXTCR) = runtime->dma_bytes; | ||
229 | } else { | ||
230 | BRGREG(BRGARXDAR) = (unsigned long)runtime->dma_area; | ||
231 | BRGREG(BRGARXTCR) = runtime->dma_bytes; | ||
232 | } | ||
233 | |||
234 | return 0; | ||
235 | } | ||
236 | |||
237 | static inline void dmabrg_play_dma_start(struct camelot_pcm *cam) | ||
238 | { | ||
239 | unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS); | ||
240 | /* start DMABRG engine: XFER start, auto-addr-reload */ | ||
241 | BRGREG(BRGACR) = acr | ACR_TDE | ACR_TAR | ACR_TAM_2WORD; | ||
242 | } | ||
243 | |||
244 | static inline void dmabrg_play_dma_stop(struct camelot_pcm *cam) | ||
245 | { | ||
246 | unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS); | ||
247 | /* forcibly terminate data transmission */ | ||
248 | BRGREG(BRGACR) = acr | ACR_TDS; | ||
249 | } | ||
250 | |||
251 | static inline void dmabrg_rec_dma_start(struct camelot_pcm *cam) | ||
252 | { | ||
253 | unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS); | ||
254 | /* start DMABRG engine: recv start, auto-reload */ | ||
255 | BRGREG(BRGACR) = acr | ACR_RDE | ACR_RAR | ACR_RAM_2WORD; | ||
256 | } | ||
257 | |||
258 | static inline void dmabrg_rec_dma_stop(struct camelot_pcm *cam) | ||
259 | { | ||
260 | unsigned long acr = BRGREG(BRGACR) & ~(ACR_TDS | ACR_RDS); | ||
261 | /* forcibly terminate data receiver */ | ||
262 | BRGREG(BRGACR) = acr | ACR_RDS; | ||
263 | } | ||
264 | |||
265 | static int camelot_trigger(struct snd_pcm_substream *substream, int cmd) | ||
266 | { | ||
267 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
268 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
269 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | ||
270 | |||
271 | switch (cmd) { | ||
272 | case SNDRV_PCM_TRIGGER_START: | ||
273 | if (recv) | ||
274 | dmabrg_rec_dma_start(cam); | ||
275 | else | ||
276 | dmabrg_play_dma_start(cam); | ||
277 | break; | ||
278 | case SNDRV_PCM_TRIGGER_STOP: | ||
279 | if (recv) | ||
280 | dmabrg_rec_dma_stop(cam); | ||
281 | else | ||
282 | dmabrg_play_dma_stop(cam); | ||
283 | break; | ||
284 | default: | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
288 | return 0; | ||
289 | } | ||
290 | |||
291 | static snd_pcm_uframes_t camelot_pos(struct snd_pcm_substream *substream) | ||
292 | { | ||
293 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
295 | struct camelot_pcm *cam = &cam_pcm_data[rtd->dai->cpu_dai->id]; | ||
296 | int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; | ||
297 | unsigned long pos; | ||
298 | |||
299 | /* cannot use the DMABRG pointer register: under load, by the | ||
300 | * time ALSA comes around to read the register, it is already | ||
301 | * far ahead (or worse, already done with the fragment) of the | ||
302 | * position at the time the IRQ was triggered, which results in | ||
303 | * fast-playback sound in my test application (ScummVM) | ||
304 | */ | ||
305 | if (recv) | ||
306 | pos = cam->rx_period ? cam->rx_period_size : 0; | ||
307 | else | ||
308 | pos = cam->tx_period ? cam->tx_period_size : 0; | ||
309 | |||
310 | return bytes_to_frames(runtime, pos); | ||
311 | } | ||
312 | |||
313 | static struct snd_pcm_ops camelot_pcm_ops = { | ||
314 | .open = camelot_pcm_open, | ||
315 | .close = camelot_pcm_close, | ||
316 | .ioctl = snd_pcm_lib_ioctl, | ||
317 | .hw_params = camelot_hw_params, | ||
318 | .hw_free = camelot_hw_free, | ||
319 | .prepare = camelot_prepare, | ||
320 | .trigger = camelot_trigger, | ||
321 | .pointer = camelot_pos, | ||
322 | }; | ||
323 | |||
324 | static void camelot_pcm_free(struct snd_pcm *pcm) | ||
325 | { | ||
326 | snd_pcm_lib_preallocate_free_for_all(pcm); | ||
327 | } | ||
328 | |||
329 | static int camelot_pcm_new(struct snd_card *card, | ||
330 | struct snd_soc_codec_dai *dai, | ||
331 | struct snd_pcm *pcm) | ||
332 | { | ||
333 | /* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel | ||
334 | * in MMAP mode (i.e. aplay -M) | ||
335 | */ | ||
336 | snd_pcm_lib_preallocate_pages_for_all(pcm, | ||
337 | SNDRV_DMA_TYPE_CONTINUOUS, | ||
338 | snd_dma_continuous_data(GFP_KERNEL), | ||
339 | DMABRG_PREALLOC_BUFFER, DMABRG_PREALLOC_BUFFER_MAX); | ||
340 | |||
341 | return 0; | ||
342 | } | ||
343 | |||
344 | struct snd_soc_platform sh7760_soc_platform = { | ||
345 | .name = "sh7760-pcm", | ||
346 | .pcm_ops = &camelot_pcm_ops, | ||
347 | .pcm_new = camelot_pcm_new, | ||
348 | .pcm_free = camelot_pcm_free, | ||
349 | }; | ||
350 | EXPORT_SYMBOL_GPL(sh7760_soc_platform); | ||
351 | |||
352 | MODULE_LICENSE("GPL"); | ||
353 | MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver"); | ||
354 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | ||
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c new file mode 100644 index 000000000000..8e3f03908cdb --- /dev/null +++ b/sound/soc/sh/hac.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * Hitachi Audio Controller (AC97) support for SH7760/SH7780 | ||
3 | * | ||
4 | * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net> | ||
5 | * licensed under the terms outlined in the file COPYING at the root | ||
6 | * of the linux kernel sources. | ||
7 | * | ||
8 | * dont forget to set IPSEL/OMSEL register bits (in your board code) to | ||
9 | * enable HAC output pins! | ||
10 | */ | ||
11 | |||
12 | /* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only | ||
13 | * the FIRST can be used since ASoC does not pass any information to the | ||
14 | * ac97_read/write() functions regarding WHICH unit to use. You'll have | ||
15 | * to edit the code a bit to use the other AC97 unit. --mlau | ||
16 | */ | ||
17 | |||
18 | #include <linux/init.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <sound/driver.h> | ||
25 | #include <sound/core.h> | ||
26 | #include <sound/pcm.h> | ||
27 | #include <sound/ac97_codec.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | /* regs and bits */ | ||
32 | #define HACCR 0x08 | ||
33 | #define HACCSAR 0x20 | ||
34 | #define HACCSDR 0x24 | ||
35 | #define HACPCML 0x28 | ||
36 | #define HACPCMR 0x2C | ||
37 | #define HACTIER 0x50 | ||
38 | #define HACTSR 0x54 | ||
39 | #define HACRIER 0x58 | ||
40 | #define HACRSR 0x5C | ||
41 | #define HACACR 0x60 | ||
42 | |||
43 | #define CR_CR (1 << 15) /* "codec-ready" indicator */ | ||
44 | #define CR_CDRT (1 << 11) /* cold reset */ | ||
45 | #define CR_WMRT (1 << 10) /* warm reset */ | ||
46 | #define CR_B9 (1 << 9) /* the mysterious "bit 9" */ | ||
47 | #define CR_ST (1 << 5) /* AC97 link start bit */ | ||
48 | |||
49 | #define CSAR_RD (1 << 19) /* AC97 data read bit */ | ||
50 | #define CSAR_WR (0) | ||
51 | |||
52 | #define TSR_CMDAMT (1 << 31) | ||
53 | #define TSR_CMDDMT (1 << 30) | ||
54 | |||
55 | #define RSR_STARY (1 << 22) | ||
56 | #define RSR_STDRY (1 << 21) | ||
57 | |||
58 | #define ACR_DMARX16 (1 << 30) | ||
59 | #define ACR_DMATX16 (1 << 29) | ||
60 | #define ACR_TX12ATOM (1 << 26) | ||
61 | #define ACR_DMARX20 ((1 << 24) | (1 << 22)) | ||
62 | #define ACR_DMATX20 ((1 << 23) | (1 << 21)) | ||
63 | |||
64 | #define CSDR_SHIFT 4 | ||
65 | #define CSDR_MASK (0xffff << CSDR_SHIFT) | ||
66 | #define CSAR_SHIFT 12 | ||
67 | #define CSAR_MASK (0x7f << CSAR_SHIFT) | ||
68 | |||
69 | #define AC97_WRITE_RETRY 1 | ||
70 | #define AC97_READ_RETRY 5 | ||
71 | |||
72 | /* manual-suggested AC97 codec access timeouts (us) */ | ||
73 | #define TMO_E1 500 /* 21 < E1 < 1000 */ | ||
74 | #define TMO_E2 13 /* 13 < E2 */ | ||
75 | #define TMO_E3 21 /* 21 < E3 */ | ||
76 | #define TMO_E4 500 /* 21 < E4 < 1000 */ | ||
77 | |||
78 | struct hac_priv { | ||
79 | unsigned long mmio; /* HAC base address */ | ||
80 | } hac_cpu_data[] = { | ||
81 | #if defined(CONFIG_CPU_SUBTYPE_SH7760) | ||
82 | { | ||
83 | .mmio = 0xFE240000, | ||
84 | }, | ||
85 | { | ||
86 | .mmio = 0xFE250000, | ||
87 | }, | ||
88 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | ||
89 | { | ||
90 | .mmio = 0xFFE40000, | ||
91 | }, | ||
92 | #else | ||
93 | #error "Unsupported SuperH SoC" | ||
94 | #endif | ||
95 | }; | ||
96 | |||
97 | #define HACREG(reg) (*(unsigned long *)(hac->mmio + (reg))) | ||
98 | |||
99 | /* | ||
100 | * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906) | ||
101 | */ | ||
102 | static int hac_get_codec_data(struct hac_priv *hac, unsigned short r, | ||
103 | unsigned short *v) | ||
104 | { | ||
105 | unsigned int to1, to2, i; | ||
106 | unsigned short adr; | ||
107 | |||
108 | for (i = 0; i < AC97_READ_RETRY; ++i) { | ||
109 | *v = 0; | ||
110 | /* wait for HAC to receive something from the codec */ | ||
111 | for (to1 = TMO_E4; | ||
112 | to1 && !(HACREG(HACRSR) & RSR_STARY); | ||
113 | --to1) | ||
114 | udelay(1); | ||
115 | for (to2 = TMO_E4; | ||
116 | to2 && !(HACREG(HACRSR) & RSR_STDRY); | ||
117 | --to2) | ||
118 | udelay(1); | ||
119 | |||
120 | if (!to1 && !to2) | ||
121 | return 0; /* codec comm is down */ | ||
122 | |||
123 | adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT); | ||
124 | *v = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT); | ||
125 | |||
126 | HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY); | ||
127 | |||
128 | if (r == adr) | ||
129 | break; | ||
130 | |||
131 | /* manual says: wait at least 21 usec before retrying */ | ||
132 | udelay(21); | ||
133 | } | ||
134 | HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY); | ||
135 | return (i < AC97_READ_RETRY); | ||
136 | } | ||
137 | |||
138 | static unsigned short hac_read_codec_aux(struct hac_priv *hac, | ||
139 | unsigned short reg) | ||
140 | { | ||
141 | unsigned short val; | ||
142 | unsigned int i, to; | ||
143 | |||
144 | for (i = 0; i < AC97_READ_RETRY; i++) { | ||
145 | /* send_read_request */ | ||
146 | local_irq_disable(); | ||
147 | HACREG(HACTSR) &= ~(TSR_CMDAMT); | ||
148 | HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD; | ||
149 | local_irq_enable(); | ||
150 | |||
151 | for (to = TMO_E3; | ||
152 | to && !(HACREG(HACTSR) & TSR_CMDAMT); | ||
153 | --to) | ||
154 | udelay(1); | ||
155 | |||
156 | HACREG(HACTSR) &= ~TSR_CMDAMT; | ||
157 | val = 0; | ||
158 | if (hac_get_codec_data(hac, reg, &val) != 0) | ||
159 | break; | ||
160 | } | ||
161 | |||
162 | if (i == AC97_READ_RETRY) | ||
163 | return ~0; | ||
164 | |||
165 | return val; | ||
166 | } | ||
167 | |||
168 | static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg, | ||
169 | unsigned short val) | ||
170 | { | ||
171 | int unit_id = 0 /* ac97->private_data */; | ||
172 | struct hac_priv *hac = &hac_cpu_data[unit_id]; | ||
173 | unsigned int i, to; | ||
174 | /* write_codec_aux */ | ||
175 | for (i = 0; i < AC97_WRITE_RETRY; i++) { | ||
176 | /* send_write_request */ | ||
177 | local_irq_disable(); | ||
178 | HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT); | ||
179 | HACREG(HACCSDR) = (val << CSDR_SHIFT); | ||
180 | HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD); | ||
181 | local_irq_enable(); | ||
182 | |||
183 | /* poll-wait for CMDAMT and CMDDMT */ | ||
184 | for (to = TMO_E1; | ||
185 | to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT)); | ||
186 | --to) | ||
187 | udelay(1); | ||
188 | |||
189 | HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT); | ||
190 | if (to) | ||
191 | break; | ||
192 | /* timeout, try again */ | ||
193 | } | ||
194 | } | ||
195 | |||
196 | static unsigned short hac_ac97_read(struct snd_ac97 *ac97, | ||
197 | unsigned short reg) | ||
198 | { | ||
199 | int unit_id = 0 /* ac97->private_data */; | ||
200 | struct hac_priv *hac = &hac_cpu_data[unit_id]; | ||
201 | return hac_read_codec_aux(hac, reg); | ||
202 | } | ||
203 | |||
204 | static void hac_ac97_warmrst(struct snd_ac97 *ac97) | ||
205 | { | ||
206 | int unit_id = 0 /* ac97->private_data */; | ||
207 | struct hac_priv *hac = &hac_cpu_data[unit_id]; | ||
208 | unsigned int tmo; | ||
209 | |||
210 | HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9; | ||
211 | msleep(10); | ||
212 | HACREG(HACCR) = CR_ST | CR_B9; | ||
213 | for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--) | ||
214 | udelay(1); | ||
215 | |||
216 | if (!tmo) | ||
217 | printk(KERN_INFO "hac: reset: AC97 link down!\n"); | ||
218 | /* settings this bit lets us have a conversation with codec */ | ||
219 | HACREG(HACACR) |= ACR_TX12ATOM; | ||
220 | } | ||
221 | |||
222 | static void hac_ac97_coldrst(struct snd_ac97 *ac97) | ||
223 | { | ||
224 | int unit_id = 0 /* ac97->private_data */; | ||
225 | struct hac_priv *hac; | ||
226 | hac = &hac_cpu_data[unit_id]; | ||
227 | |||
228 | HACREG(HACCR) = 0; | ||
229 | HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9; | ||
230 | msleep(10); | ||
231 | hac_ac97_warmrst(ac97); | ||
232 | } | ||
233 | |||
234 | struct snd_ac97_bus_ops soc_ac97_ops = { | ||
235 | .read = hac_ac97_read, | ||
236 | .write = hac_ac97_write, | ||
237 | .reset = hac_ac97_coldrst, | ||
238 | .warm_reset = hac_ac97_warmrst, | ||
239 | }; | ||
240 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
241 | |||
242 | static int hac_hw_params(struct snd_pcm_substream *substream, | ||
243 | struct snd_pcm_hw_params *params) | ||
244 | { | ||
245 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
246 | struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id]; | ||
247 | int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; | ||
248 | |||
249 | switch (params->msbits) { | ||
250 | case 16: | ||
251 | HACREG(HACACR) |= d ? ACR_DMARX16 : ACR_DMATX16; | ||
252 | HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20; | ||
253 | break; | ||
254 | case 20: | ||
255 | HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16; | ||
256 | HACREG(HACACR) |= d ? ACR_DMARX20 : ACR_DMATX20; | ||
257 | break; | ||
258 | default: | ||
259 | pr_debug("hac: invalid depth %d bit\n", params->msbits); | ||
260 | return -EINVAL; | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | return 0; | ||
265 | } | ||
266 | |||
267 | #define AC97_RATES \ | ||
268 | SNDRV_PCM_RATE_8000_192000 | ||
269 | |||
270 | #define AC97_FMTS \ | ||
271 | SNDRV_PCM_FMTBIT_S16_LE | ||
272 | |||
273 | struct snd_soc_cpu_dai sh4_hac_dai[] = { | ||
274 | { | ||
275 | .name = "HAC0", | ||
276 | .id = 0, | ||
277 | .type = SND_SOC_DAI_AC97, | ||
278 | .playback = { | ||
279 | .rates = AC97_RATES, | ||
280 | .formats = AC97_FMTS, | ||
281 | .channels_min = 2, | ||
282 | .channels_max = 2, | ||
283 | }, | ||
284 | .capture = { | ||
285 | .rates = AC97_RATES, | ||
286 | .formats = AC97_FMTS, | ||
287 | .channels_min = 2, | ||
288 | .channels_max = 2, | ||
289 | }, | ||
290 | .ops = { | ||
291 | .hw_params = hac_hw_params, | ||
292 | }, | ||
293 | }, | ||
294 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | ||
295 | { | ||
296 | .name = "HAC1", | ||
297 | .id = 1, | ||
298 | .type = SND_SOC_DAI_AC97, | ||
299 | .playback = { | ||
300 | .rates = AC97_RATES, | ||
301 | .formats = AC97_FMTS, | ||
302 | .channels_min = 2, | ||
303 | .channels_max = 2, | ||
304 | }, | ||
305 | .capture = { | ||
306 | .rates = AC97_RATES, | ||
307 | .formats = AC97_FMTS, | ||
308 | .channels_min = 2, | ||
309 | .channels_max = 2, | ||
310 | }, | ||
311 | .ops = { | ||
312 | .hw_params = hac_hw_params, | ||
313 | }, | ||
314 | |||
315 | }, | ||
316 | #endif | ||
317 | }; | ||
318 | EXPORT_SYMBOL_GPL(sh4_hac_dai); | ||
319 | |||
320 | MODULE_LICENSE("GPL"); | ||
321 | MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver"); | ||
322 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | ||
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c new file mode 100644 index 000000000000..5563f14511fa --- /dev/null +++ b/sound/soc/sh/sh7760-ac97.c | |||
@@ -0,0 +1,92 @@ | |||
1 | /* | ||
2 | * Generic AC97 sound support for SH7760 | ||
3 | * | ||
4 | * (c) 2007 Manuel Lauss | ||
5 | * | ||
6 | * Licensed under the GPLv2. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/moduleparam.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | #include <sound/driver.h> | ||
13 | #include <sound/core.h> | ||
14 | #include <sound/pcm.h> | ||
15 | #include <sound/soc.h> | ||
16 | #include <sound/soc-dapm.h> | ||
17 | #include <asm/io.h> | ||
18 | |||
19 | #include "../codecs/ac97.h" | ||
20 | |||
21 | #define IPSEL 0xFE400034 | ||
22 | |||
23 | /* platform specific structs can be declared here */ | ||
24 | extern struct snd_soc_cpu_dai sh4_hac_dai[2]; | ||
25 | extern struct snd_soc_platform sh7760_soc_platform; | ||
26 | |||
27 | static int machine_init(struct snd_soc_codec *codec) | ||
28 | { | ||
29 | snd_soc_dapm_sync_endpoints(codec); | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static struct snd_soc_dai_link sh7760_ac97_dai = { | ||
34 | .name = "AC97", | ||
35 | .stream_name = "AC97 HiFi", | ||
36 | .cpu_dai = &sh4_hac_dai[0], /* HAC0 */ | ||
37 | .codec_dai = &ac97_dai, | ||
38 | .init = machine_init, | ||
39 | .ops = NULL, | ||
40 | }; | ||
41 | |||
42 | static struct snd_soc_machine sh7760_ac97_soc_machine = { | ||
43 | .name = "SH7760 AC97", | ||
44 | .dai_link = &sh7760_ac97_dai, | ||
45 | .num_links = 1, | ||
46 | }; | ||
47 | |||
48 | static struct snd_soc_device sh7760_ac97_snd_devdata = { | ||
49 | .machine = &sh7760_ac97_soc_machine, | ||
50 | .platform = &sh7760_soc_platform, | ||
51 | .codec_dev = &soc_codec_dev_ac97, | ||
52 | }; | ||
53 | |||
54 | static struct platform_device *sh7760_ac97_snd_device; | ||
55 | |||
56 | static int __init sh7760_ac97_init(void) | ||
57 | { | ||
58 | int ret; | ||
59 | unsigned short ipsel; | ||
60 | |||
61 | /* enable both AC97 controllers in pinmux reg */ | ||
62 | ipsel = ctrl_inw(IPSEL); | ||
63 | ctrl_outw(ipsel | (3 << 10), IPSEL); | ||
64 | |||
65 | ret = -ENOMEM; | ||
66 | sh7760_ac97_snd_device = platform_device_alloc("soc-audio", -1); | ||
67 | if (!sh7760_ac97_snd_device) | ||
68 | goto out; | ||
69 | |||
70 | platform_set_drvdata(sh7760_ac97_snd_device, | ||
71 | &sh7760_ac97_snd_devdata); | ||
72 | sh7760_ac97_snd_devdata.dev = &sh7760_ac97_snd_device->dev; | ||
73 | ret = platform_device_add(sh7760_ac97_snd_device); | ||
74 | |||
75 | if (ret) | ||
76 | platform_device_put(sh7760_ac97_snd_device); | ||
77 | |||
78 | out: | ||
79 | return ret; | ||
80 | } | ||
81 | |||
82 | static void __exit sh7760_ac97_exit(void) | ||
83 | { | ||
84 | platform_device_unregister(sh7760_ac97_snd_device); | ||
85 | } | ||
86 | |||
87 | module_init(sh7760_ac97_init); | ||
88 | module_exit(sh7760_ac97_exit); | ||
89 | |||
90 | MODULE_LICENSE("GPL"); | ||
91 | MODULE_DESCRIPTION("Generic SH7760 AC97 sound machine"); | ||
92 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | ||
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c new file mode 100644 index 000000000000..b72bc316cb8e --- /dev/null +++ b/sound/soc/sh/ssi.c | |||
@@ -0,0 +1,400 @@ | |||
1 | /* | ||
2 | * Serial Sound Interface (I2S) support for SH7760/SH7780 | ||
3 | * | ||
4 | * Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net> | ||
5 | * | ||
6 | * licensed under the terms outlined in the file COPYING at the root | ||
7 | * of the linux kernel sources. | ||
8 | * | ||
9 | * dont forget to set IPSEL/OMSEL register bits (in your board code) to | ||
10 | * enable SSI output pins! | ||
11 | */ | ||
12 | |||
13 | /* | ||
14 | * LIMITATIONS: | ||
15 | * The SSI unit has only one physical data line, so full duplex is | ||
16 | * impossible. This can be remedied on the SH7760 by using the | ||
17 | * other SSI unit for recording; however the SH7780 has only 1 SSI | ||
18 | * unit, and its pins are shared with the AC97 unit, among others. | ||
19 | * | ||
20 | * FEATURES: | ||
21 | * The SSI features "compressed mode": in this mode it continuously | ||
22 | * streams PCM data over the I2S lines and uses LRCK as a handshake | ||
23 | * signal. Can be used to send compressed data (AC3/DTS) to a DSP. | ||
24 | * The number of bits sent over the wire in a frame can be adjusted | ||
25 | * and can be independent from the actual sample bit depth. This is | ||
26 | * useful to support TDM mode codecs like the AD1939 which have a | ||
27 | * fixed TDM slot size, regardless of sample resolution. | ||
28 | */ | ||
29 | |||
30 | #include <linux/init.h> | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/platform_device.h> | ||
33 | #include <sound/driver.h> | ||
34 | #include <sound/core.h> | ||
35 | #include <sound/pcm.h> | ||
36 | #include <sound/initval.h> | ||
37 | #include <sound/soc.h> | ||
38 | #include <asm/io.h> | ||
39 | |||
40 | #define SSICR 0x00 | ||
41 | #define SSISR 0x04 | ||
42 | |||
43 | #define CR_DMAEN (1 << 28) | ||
44 | #define CR_CHNL_SHIFT 22 | ||
45 | #define CR_CHNL_MASK (3 << CR_CHNL_SHIFT) | ||
46 | #define CR_DWL_SHIFT 19 | ||
47 | #define CR_DWL_MASK (7 << CR_DWL_SHIFT) | ||
48 | #define CR_SWL_SHIFT 16 | ||
49 | #define CR_SWL_MASK (7 << CR_SWL_SHIFT) | ||
50 | #define CR_SCK_MASTER (1 << 15) /* bitclock master bit */ | ||
51 | #define CR_SWS_MASTER (1 << 14) /* wordselect master bit */ | ||
52 | #define CR_SCKP (1 << 13) /* I2Sclock polarity */ | ||
53 | #define CR_SWSP (1 << 12) /* LRCK polarity */ | ||
54 | #define CR_SPDP (1 << 11) | ||
55 | #define CR_SDTA (1 << 10) /* i2s alignment (msb/lsb) */ | ||
56 | #define CR_PDTA (1 << 9) /* fifo data alignment */ | ||
57 | #define CR_DEL (1 << 8) /* delay data by 1 i2sclk */ | ||
58 | #define CR_BREN (1 << 7) /* clock gating in burst mode */ | ||
59 | #define CR_CKDIV_SHIFT 4 | ||
60 | #define CR_CKDIV_MASK (7 << CR_CKDIV_SHIFT) /* bitclock divider */ | ||
61 | #define CR_MUTE (1 << 3) /* SSI mute */ | ||
62 | #define CR_CPEN (1 << 2) /* compressed mode */ | ||
63 | #define CR_TRMD (1 << 1) /* transmit/receive select */ | ||
64 | #define CR_EN (1 << 0) /* enable SSI */ | ||
65 | |||
66 | #define SSIREG(reg) (*(unsigned long *)(ssi->mmio + (reg))) | ||
67 | |||
68 | struct ssi_priv { | ||
69 | unsigned long mmio; | ||
70 | unsigned long sysclk; | ||
71 | int inuse; | ||
72 | } ssi_cpu_data[] = { | ||
73 | #if defined(CONFIG_CPU_SUBTYPE_SH7760) | ||
74 | { | ||
75 | .mmio = 0xFE680000, | ||
76 | }, | ||
77 | { | ||
78 | .mmio = 0xFE690000, | ||
79 | }, | ||
80 | #elif defined(CONFIG_CPU_SUBTYPE_SH7780) | ||
81 | { | ||
82 | .mmio = 0xFFE70000, | ||
83 | }, | ||
84 | #else | ||
85 | #error "Unsupported SuperH SoC" | ||
86 | #endif | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * track usage of the SSI; it is simplex-only so prevent attempts of | ||
91 | * concurrent playback + capture. FIXME: any locking required? | ||
92 | */ | ||
93 | static int ssi_startup(struct snd_pcm_substream *substream) | ||
94 | { | ||
95 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
96 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
97 | if (ssi->inuse) { | ||
98 | pr_debug("ssi: already in use!\n"); | ||
99 | return -EBUSY; | ||
100 | } else | ||
101 | ssi->inuse = 1; | ||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static void ssi_shutdown(struct snd_pcm_substream *substream) | ||
106 | { | ||
107 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
108 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
109 | |||
110 | ssi->inuse = 0; | ||
111 | } | ||
112 | |||
113 | static int ssi_trigger(struct snd_pcm_substream *substream, int cmd) | ||
114 | { | ||
115 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
116 | struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
117 | |||
118 | switch (cmd) { | ||
119 | case SNDRV_PCM_TRIGGER_START: | ||
120 | SSIREG(SSICR) |= CR_DMAEN | CR_EN; | ||
121 | break; | ||
122 | case SNDRV_PCM_TRIGGER_STOP: | ||
123 | SSIREG(SSICR) &= ~(CR_DMAEN | CR_EN); | ||
124 | break; | ||
125 | default: | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | |||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int ssi_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 ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id]; | ||
137 | unsigned long ssicr = SSIREG(SSICR); | ||
138 | unsigned int bits, channels, swl, recv, i; | ||
139 | |||
140 | channels = params_channels(params); | ||
141 | bits = params->msbits; | ||
142 | recv = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? 0 : 1; | ||
143 | |||
144 | pr_debug("ssi_hw_params() enter\nssicr was %08lx\n", ssicr); | ||
145 | pr_debug("bits: %d channels: %d\n", bits, channels); | ||
146 | |||
147 | ssicr &= ~(CR_TRMD | CR_CHNL_MASK | CR_DWL_MASK | CR_PDTA | | ||
148 | CR_SWL_MASK); | ||
149 | |||
150 | /* direction (send/receive) */ | ||
151 | if (!recv) | ||
152 | ssicr |= CR_TRMD; /* transmit */ | ||
153 | |||
154 | /* channels */ | ||
155 | if ((channels < 2) || (channels > 8) || (channels & 1)) { | ||
156 | pr_debug("ssi: invalid number of channels\n"); | ||
157 | return -EINVAL; | ||
158 | } | ||
159 | ssicr |= ((channels >> 1) - 1) << CR_CHNL_SHIFT; | ||
160 | |||
161 | /* DATA WORD LENGTH (DWL): databits in audio sample */ | ||
162 | i = 0; | ||
163 | switch (bits) { | ||
164 | case 32: ++i; | ||
165 | case 24: ++i; | ||
166 | case 22: ++i; | ||
167 | case 20: ++i; | ||
168 | case 18: ++i; | ||
169 | case 16: ++i; | ||
170 | ssicr |= i << CR_DWL_SHIFT; | ||
171 | case 8: break; | ||
172 | default: | ||
173 | pr_debug("ssi: invalid sample width\n"); | ||
174 | return -EINVAL; | ||
175 | } | ||
176 | |||
177 | /* | ||
178 | * SYSTEM WORD LENGTH: size in bits of half a frame over the I2S | ||
179 | * wires. This is usually bits_per_sample x channels/2; i.e. in | ||
180 | * Stereo mode the SWL equals DWL. SWL can be bigger than the | ||
181 | * product of (channels_per_slot x samplebits), e.g. for codecs | ||
182 | * like the AD1939 which only accept 32bit wide TDM slots. For | ||
183 | * "standard" I2S operation we set SWL = chans / 2 * DWL here. | ||
184 | * Waiting for ASoC to get TDM support ;-) | ||
185 | */ | ||
186 | if ((bits > 16) && (bits <= 24)) { | ||
187 | bits = 24; /* these are padded by the SSI */ | ||
188 | /*ssicr |= CR_PDTA;*/ /* cpu/data endianness ? */ | ||
189 | } | ||
190 | i = 0; | ||
191 | swl = (bits * channels) / 2; | ||
192 | switch (swl) { | ||
193 | case 256: ++i; | ||
194 | case 128: ++i; | ||
195 | case 64: ++i; | ||
196 | case 48: ++i; | ||
197 | case 32: ++i; | ||
198 | case 16: ++i; | ||
199 | ssicr |= i << CR_SWL_SHIFT; | ||
200 | case 8: break; | ||
201 | default: | ||
202 | pr_debug("ssi: invalid system word length computed\n"); | ||
203 | return -EINVAL; | ||
204 | } | ||
205 | |||
206 | SSIREG(SSICR) = ssicr; | ||
207 | |||
208 | pr_debug("ssi_hw_params() leave\nssicr is now %08lx\n", ssicr); | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | static int ssi_set_sysclk(struct snd_soc_cpu_dai *cpu_dai, int clk_id, | ||
213 | unsigned int freq, int dir) | ||
214 | { | ||
215 | struct ssi_priv *ssi = &ssi_cpu_data[cpu_dai->id]; | ||
216 | |||
217 | ssi->sysclk = freq; | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | /* | ||
223 | * This divider is used to generate the SSI_SCK (I2S bitclock) from the | ||
224 | * clock at the HAC_BIT_CLK ("oversampling clock") pin. | ||
225 | */ | ||
226 | static int ssi_set_clkdiv(struct snd_soc_cpu_dai *dai, int did, int div) | ||
227 | { | ||
228 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; | ||
229 | unsigned long ssicr; | ||
230 | int i; | ||
231 | |||
232 | i = 0; | ||
233 | ssicr = SSIREG(SSICR) & ~CR_CKDIV_MASK; | ||
234 | switch (div) { | ||
235 | case 16: ++i; | ||
236 | case 8: ++i; | ||
237 | case 4: ++i; | ||
238 | case 2: ++i; | ||
239 | SSIREG(SSICR) = ssicr | (i << CR_CKDIV_SHIFT); | ||
240 | case 1: break; | ||
241 | default: | ||
242 | pr_debug("ssi: invalid sck divider %d\n", div); | ||
243 | return -EINVAL; | ||
244 | } | ||
245 | |||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static int ssi_set_fmt(struct snd_soc_cpu_dai *dai, unsigned int fmt) | ||
250 | { | ||
251 | struct ssi_priv *ssi = &ssi_cpu_data[dai->id]; | ||
252 | unsigned long ssicr = SSIREG(SSICR); | ||
253 | |||
254 | pr_debug("ssi_set_fmt()\nssicr was 0x%08lx\n", ssicr); | ||
255 | |||
256 | ssicr &= ~(CR_DEL | CR_PDTA | CR_BREN | CR_SWSP | CR_SCKP | | ||
257 | CR_SWS_MASTER | CR_SCK_MASTER); | ||
258 | |||
259 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
260 | case SND_SOC_DAIFMT_I2S: | ||
261 | break; | ||
262 | case SND_SOC_DAIFMT_RIGHT_J: | ||
263 | ssicr |= CR_DEL | CR_PDTA; | ||
264 | break; | ||
265 | case SND_SOC_DAIFMT_LEFT_J: | ||
266 | ssicr |= CR_DEL; | ||
267 | break; | ||
268 | default: | ||
269 | pr_debug("ssi: unsupported format\n"); | ||
270 | return -EINVAL; | ||
271 | } | ||
272 | |||
273 | switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) { | ||
274 | case SND_SOC_DAIFMT_CONT: | ||
275 | break; | ||
276 | case SND_SOC_DAIFMT_GATED: | ||
277 | ssicr |= CR_BREN; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
282 | case SND_SOC_DAIFMT_NB_NF: | ||
283 | ssicr |= CR_SCKP; /* sample data at low clkedge */ | ||
284 | break; | ||
285 | case SND_SOC_DAIFMT_NB_IF: | ||
286 | ssicr |= CR_SCKP | CR_SWSP; | ||
287 | break; | ||
288 | case SND_SOC_DAIFMT_IB_NF: | ||
289 | break; | ||
290 | case SND_SOC_DAIFMT_IB_IF: | ||
291 | ssicr |= CR_SWSP; /* word select starts low */ | ||
292 | break; | ||
293 | default: | ||
294 | pr_debug("ssi: invalid inversion\n"); | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
299 | case SND_SOC_DAIFMT_CBM_CFM: | ||
300 | break; | ||
301 | case SND_SOC_DAIFMT_CBS_CFM: | ||
302 | ssicr |= CR_SCK_MASTER; | ||
303 | break; | ||
304 | case SND_SOC_DAIFMT_CBM_CFS: | ||
305 | ssicr |= CR_SWS_MASTER; | ||
306 | break; | ||
307 | case SND_SOC_DAIFMT_CBS_CFS: | ||
308 | ssicr |= CR_SWS_MASTER | CR_SCK_MASTER; | ||
309 | break; | ||
310 | default: | ||
311 | pr_debug("ssi: invalid master/slave configuration\n"); | ||
312 | return -EINVAL; | ||
313 | } | ||
314 | |||
315 | SSIREG(SSICR) = ssicr; | ||
316 | pr_debug("ssi_set_fmt() leave\nssicr is now 0x%08lx\n", ssicr); | ||
317 | |||
318 | return 0; | ||
319 | } | ||
320 | |||
321 | /* the SSI depends on an external clocksource (at HAC_BIT_CLK) even in | ||
322 | * Master mode, so really this is board specific; the SSI can do any | ||
323 | * rate with the right bitclk and divider settings. | ||
324 | */ | ||
325 | #define SSI_RATES \ | ||
326 | SNDRV_PCM_RATE_8000_192000 | ||
327 | |||
328 | /* the SSI can do 8-32 bit samples, with 8 possible channels */ | ||
329 | #define SSI_FMTS \ | ||
330 | (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \ | ||
331 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE | \ | ||
332 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \ | ||
333 | SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \ | ||
334 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE) | ||
335 | |||
336 | struct snd_soc_cpu_dai sh4_ssi_dai[] = { | ||
337 | { | ||
338 | .name = "SSI0", | ||
339 | .id = 0, | ||
340 | .type = SND_SOC_DAI_I2S, | ||
341 | .playback = { | ||
342 | .rates = SSI_RATES, | ||
343 | .formats = SSI_FMTS, | ||
344 | .channels_min = 2, | ||
345 | .channels_max = 8, | ||
346 | }, | ||
347 | .capture = { | ||
348 | .rates = SSI_RATES, | ||
349 | .formats = SSI_FMTS, | ||
350 | .channels_min = 2, | ||
351 | .channels_max = 8, | ||
352 | }, | ||
353 | .ops = { | ||
354 | .startup = ssi_startup, | ||
355 | .shutdown = ssi_shutdown, | ||
356 | .trigger = ssi_trigger, | ||
357 | .hw_params = ssi_hw_params, | ||
358 | }, | ||
359 | .dai_ops = { | ||
360 | .set_sysclk = ssi_set_sysclk, | ||
361 | .set_clkdiv = ssi_set_clkdiv, | ||
362 | .set_fmt = ssi_set_fmt, | ||
363 | }, | ||
364 | }, | ||
365 | #ifdef CONFIG_CPU_SUBTYPE_SH7760 | ||
366 | { | ||
367 | .name = "SSI1", | ||
368 | .id = 1, | ||
369 | .type = SND_SOC_DAI_I2S, | ||
370 | .playback = { | ||
371 | .rates = SSI_RATES, | ||
372 | .formats = SSI_FMTS, | ||
373 | .channels_min = 2, | ||
374 | .channels_max = 8, | ||
375 | }, | ||
376 | .capture = { | ||
377 | .rates = SSI_RATES, | ||
378 | .formats = SSI_FMTS, | ||
379 | .channels_min = 2, | ||
380 | .channels_max = 8, | ||
381 | }, | ||
382 | .ops = { | ||
383 | .startup = ssi_startup, | ||
384 | .shutdown = ssi_shutdown, | ||
385 | .trigger = ssi_trigger, | ||
386 | .hw_params = ssi_hw_params, | ||
387 | }, | ||
388 | .dai_ops = { | ||
389 | .set_sysclk = ssi_set_sysclk, | ||
390 | .set_clkdiv = ssi_set_clkdiv, | ||
391 | .set_fmt = ssi_set_fmt, | ||
392 | }, | ||
393 | }, | ||
394 | #endif | ||
395 | }; | ||
396 | EXPORT_SYMBOL_GPL(sh4_ssi_dai); | ||
397 | |||
398 | MODULE_LICENSE("GPL"); | ||
399 | MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver"); | ||
400 | MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); | ||
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c index 8ebc1adb5ed9..7bd5852fcc0d 100644 --- a/sound/usb/usbaudio.c +++ b/sound/usb/usbaudio.c | |||
@@ -2350,7 +2350,9 @@ static int is_big_endian_format(struct snd_usb_audio *chip, struct audioformat * | |||
2350 | return 1; | 2350 | return 1; |
2351 | break; | 2351 | break; |
2352 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ | 2352 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ |
2353 | return 1; | 2353 | if (device_setup[chip->index] == 0x00 || |
2354 | fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3) | ||
2355 | return 1; | ||
2354 | } | 2356 | } |
2355 | return 0; | 2357 | return 0; |
2356 | } | 2358 | } |
@@ -2530,7 +2532,18 @@ static int parse_audio_format_i(struct snd_usb_audio *chip, struct audioformat * | |||
2530 | * but we give normal PCM format to get the existing | 2532 | * but we give normal PCM format to get the existing |
2531 | * apps working... | 2533 | * apps working... |
2532 | */ | 2534 | */ |
2533 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | 2535 | switch (chip->usb_id) { |
2536 | |||
2537 | case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ | ||
2538 | if (device_setup[chip->index] == 0x00 && | ||
2539 | fp->altsetting == 6) | ||
2540 | pcm_format = SNDRV_PCM_FORMAT_S16_BE; | ||
2541 | else | ||
2542 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | ||
2543 | break; | ||
2544 | default: | ||
2545 | pcm_format = SNDRV_PCM_FORMAT_S16_LE; | ||
2546 | } | ||
2534 | } else { | 2547 | } else { |
2535 | pcm_format = parse_audio_format_i_type(chip, fp, format, fmt); | 2548 | pcm_format = parse_audio_format_i_type(chip, fp, format, fmt); |
2536 | if (pcm_format < 0) | 2549 | if (pcm_format < 0) |
@@ -3251,6 +3264,11 @@ static int snd_usb_cm106_boot_quirk(struct usb_device *dev) | |||
3251 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, | 3264 | static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, |
3252 | int iface, int altno) | 3265 | int iface, int altno) |
3253 | { | 3266 | { |
3267 | /* Reset ALL ifaces to 0 altsetting. | ||
3268 | * Call it for every possible altsetting of every interface. | ||
3269 | */ | ||
3270 | usb_set_interface(chip->dev, iface, 0); | ||
3271 | |||
3254 | if (device_setup[chip->index] & AUDIOPHILE_SET) { | 3272 | if (device_setup[chip->index] & AUDIOPHILE_SET) { |
3255 | if ((device_setup[chip->index] & AUDIOPHILE_SET_DTS) | 3273 | if ((device_setup[chip->index] & AUDIOPHILE_SET_DTS) |
3256 | && altno != 6) | 3274 | && altno != 6) |
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h index 374fbf657a2d..5a2f518c6629 100644 --- a/sound/usb/usbquirks.h +++ b/sound/usb/usbquirks.h | |||
@@ -57,6 +57,24 @@ | |||
57 | USB_DEVICE_ID_MATCH_INT_CLASS | | 57 | USB_DEVICE_ID_MATCH_INT_CLASS | |
58 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | 58 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, |
59 | .idVendor = 0x046d, | 59 | .idVendor = 0x046d, |
60 | .idProduct = 0x08ae, | ||
61 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
62 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL | ||
63 | }, | ||
64 | { | ||
65 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | | ||
66 | USB_DEVICE_ID_MATCH_INT_CLASS | | ||
67 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | ||
68 | .idVendor = 0x046d, | ||
69 | .idProduct = 0x08c6, | ||
70 | .bInterfaceClass = USB_CLASS_AUDIO, | ||
71 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL | ||
72 | }, | ||
73 | { | ||
74 | .match_flags = USB_DEVICE_ID_MATCH_DEVICE | | ||
75 | USB_DEVICE_ID_MATCH_INT_CLASS | | ||
76 | USB_DEVICE_ID_MATCH_INT_SUBCLASS, | ||
77 | .idVendor = 0x046d, | ||
60 | .idProduct = 0x08f0, | 78 | .idProduct = 0x08f0, |
61 | .bInterfaceClass = USB_CLASS_AUDIO, | 79 | .bInterfaceClass = USB_CLASS_AUDIO, |
62 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL | 80 | .bInterfaceSubClass = USB_SUBCLASS_AUDIO_CONTROL |
@@ -1051,7 +1069,15 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1051 | .type = QUIRK_MIDI_STANDARD_INTERFACE | 1069 | .type = QUIRK_MIDI_STANDARD_INTERFACE |
1052 | } | 1070 | } |
1053 | }, | 1071 | }, |
1054 | /* TODO: add Roland EXR support */ | 1072 | { |
1073 | USB_DEVICE(0x0582, 0x0060), | ||
1074 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1075 | .vendor_name = "Roland", | ||
1076 | .product_name = "EXR Series", | ||
1077 | .ifnum = 0, | ||
1078 | .type = QUIRK_MIDI_STANDARD_INTERFACE | ||
1079 | } | ||
1080 | }, | ||
1055 | { | 1081 | { |
1056 | /* has ID 0x0067 when not in "Advanced Driver" mode */ | 1082 | /* has ID 0x0067 when not in "Advanced Driver" mode */ |
1057 | USB_DEVICE(0x0582, 0x0065), | 1083 | USB_DEVICE(0x0582, 0x0065), |
@@ -1094,6 +1120,19 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1094 | } | 1120 | } |
1095 | } | 1121 | } |
1096 | }, | 1122 | }, |
1123 | { | ||
1124 | USB_DEVICE(0x582, 0x00a6), | ||
1125 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1126 | .vendor_name = "Roland", | ||
1127 | .product_name = "Juno-G", | ||
1128 | .ifnum = 0, | ||
1129 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1130 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1131 | .out_cables = 0x0001, | ||
1132 | .in_cables = 0x0001 | ||
1133 | } | ||
1134 | } | ||
1135 | }, | ||
1097 | { /* | 1136 | { /* |
1098 | * This quirk is for the "Advanced" modes of the Edirol UA-25. | 1137 | * This quirk is for the "Advanced" modes of the Edirol UA-25. |
1099 | * If the switch is not in an advanced setting, the UA-25 has | 1138 | * If the switch is not in an advanced setting, the UA-25 has |
@@ -1230,6 +1269,37 @@ YAMAHA_DEVICE(0x7010, "UB99"), | |||
1230 | } | 1269 | } |
1231 | }, | 1270 | }, |
1232 | /* TODO: add Edirol MD-P1 support */ | 1271 | /* TODO: add Edirol MD-P1 support */ |
1272 | { | ||
1273 | /* Roland SH-201 */ | ||
1274 | USB_DEVICE(0x0582, 0x00ad), | ||
1275 | .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) { | ||
1276 | .vendor_name = "Roland", | ||
1277 | .product_name = "SH-201", | ||
1278 | .ifnum = QUIRK_ANY_INTERFACE, | ||
1279 | .type = QUIRK_COMPOSITE, | ||
1280 | .data = (const struct snd_usb_audio_quirk[]) { | ||
1281 | { | ||
1282 | .ifnum = 0, | ||
1283 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1284 | }, | ||
1285 | { | ||
1286 | .ifnum = 1, | ||
1287 | .type = QUIRK_AUDIO_STANDARD_INTERFACE | ||
1288 | }, | ||
1289 | { | ||
1290 | .ifnum = 2, | ||
1291 | .type = QUIRK_MIDI_FIXED_ENDPOINT, | ||
1292 | .data = & (const struct snd_usb_midi_endpoint_info) { | ||
1293 | .out_cables = 0x0001, | ||
1294 | .in_cables = 0x0001 | ||
1295 | } | ||
1296 | }, | ||
1297 | { | ||
1298 | .ifnum = -1 | ||
1299 | } | ||
1300 | } | ||
1301 | } | ||
1302 | }, | ||
1233 | 1303 | ||
1234 | /* Guillemot devices */ | 1304 | /* Guillemot devices */ |
1235 | { | 1305 | { |
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index 0a352e46862f..48e9aa3f18c9 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c | |||
@@ -935,10 +935,9 @@ static struct snd_pcm_ops snd_usX2Y_pcm_ops = | |||
935 | */ | 935 | */ |
936 | static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) | 936 | static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) |
937 | { | 937 | { |
938 | if (NULL != usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]) { | 938 | kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]); |
939 | kfree(usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]); | 939 | usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL; |
940 | usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK] = NULL; | 940 | |
941 | } | ||
942 | kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]); | 941 | kfree(usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]); |
943 | usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL; | 942 | usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE] = NULL; |
944 | } | 943 | } |