ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / pci / ice1712 / hoontech.c
1 /*
2  *   ALSA driver for ICEnsemble ICE1712 (Envy24)
3  *
4  *   Lowlevel functions for Hoontech STDSP24
5  *
6  *      Copyright (c) 2000 Jaroslav Kysela <perex@suse.cz>
7  *
8  *   This program is free software; you can redistribute it and/or modify
9  *   it under the terms of the GNU General Public License as published by
10  *   the Free Software Foundation; either version 2 of the License, or
11  *   (at your option) any later version.
12  *
13  *   This program is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with this program; if not, write to the Free Software
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
21  *
22  */      
23
24 #include <sound/driver.h>
25 #include <asm/io.h>
26 #include <linux/delay.h>
27 #include <linux/interrupt.h>
28 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <sound/core.h>
31
32 #include "ice1712.h"
33 #include "hoontech.h"
34
35
36 static void __devinit snd_ice1712_stdsp24_gpio_write(ice1712_t *ice, unsigned char byte)
37 {
38         byte |= ICE1712_STDSP24_CLOCK_BIT;
39         udelay(100);
40         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
41         byte &= ~ICE1712_STDSP24_CLOCK_BIT;
42         udelay(100);
43         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
44         byte |= ICE1712_STDSP24_CLOCK_BIT;
45         udelay(100);
46         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
47 }
48
49 static void __devinit snd_ice1712_stdsp24_darear(ice1712_t *ice, int activate)
50 {
51         down(&ice->gpio_mutex);
52         ICE1712_STDSP24_0_DAREAR(ice->hoontech_boxbits, activate);
53         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
54         up(&ice->gpio_mutex);
55 }
56
57 static void __devinit snd_ice1712_stdsp24_mute(ice1712_t *ice, int activate)
58 {
59         down(&ice->gpio_mutex);
60         ICE1712_STDSP24_3_MUTE(ice->hoontech_boxbits, activate);
61         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
62         up(&ice->gpio_mutex);
63 }
64
65 static void __devinit snd_ice1712_stdsp24_insel(ice1712_t *ice, int activate)
66 {
67         down(&ice->gpio_mutex);
68         ICE1712_STDSP24_3_INSEL(ice->hoontech_boxbits, activate);
69         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
70         up(&ice->gpio_mutex);
71 }
72
73 static void __devinit snd_ice1712_stdsp24_box_channel(ice1712_t *ice, int box, int chn, int activate)
74 {
75         down(&ice->gpio_mutex);
76
77         /* select box */
78         ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, box);
79         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
80
81         /* prepare for write */
82         if (chn == 3)
83                 ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 0);
84         ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, activate);
85         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
86
87         ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
88         ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
89         ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
90         ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
91         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
92         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
93         udelay(100);
94         if (chn == 3) {
95                 ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 0);
96                 snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
97         } else {
98                 switch (chn) {
99                 case 0: ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 0); break;
100                 case 1: ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 0); break;
101                 case 2: ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 0); break;
102                 }
103                 snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
104         }
105         udelay(100);
106         ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
107         ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
108         ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
109         ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
110         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[1]);
111         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
112         udelay(100);
113
114         ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, 0);
115         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
116
117         up(&ice->gpio_mutex);
118 }
119
120 static void __devinit snd_ice1712_stdsp24_box_midi(ice1712_t *ice, int box, int master, int slave)
121 {
122         down(&ice->gpio_mutex);
123
124         /* select box */
125         ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, box);
126         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[0]);
127
128         ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
129         ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, master);
130         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
131
132         udelay(100);
133         
134         ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 0);
135         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
136         
137         udelay(100);
138         
139         ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
140         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[2]);
141
142         udelay(100);
143
144         /* MIDI2 is direct */
145         ICE1712_STDSP24_3_MIDI2(ice->hoontech_boxbits, slave);
146         snd_ice1712_stdsp24_gpio_write(ice, ice->hoontech_boxbits[3]);
147
148         up(&ice->gpio_mutex);
149 }
150
151 static int __devinit snd_ice1712_hoontech_init(ice1712_t *ice)
152 {
153         int box, chn;
154
155         ice->num_total_dacs = 8;
156         ice->num_total_adcs = 8;
157
158         ice->hoontech_boxbits[0] = 
159         ice->hoontech_boxbits[1] = 
160         ice->hoontech_boxbits[2] = 
161         ice->hoontech_boxbits[3] = 0;   /* should be already */
162
163         ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 0);
164         ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 0, 1);
165         ICE1712_STDSP24_0_BOX(ice->hoontech_boxbits, 0);
166         ICE1712_STDSP24_0_DAREAR(ice->hoontech_boxbits, 0);
167
168         ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 1);
169         ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 1, 1);
170         ICE1712_STDSP24_1_CHN1(ice->hoontech_boxbits, 1);
171         ICE1712_STDSP24_1_CHN2(ice->hoontech_boxbits, 1);
172         ICE1712_STDSP24_1_CHN3(ice->hoontech_boxbits, 1);
173         
174         ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 2);
175         ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 2, 1);
176         ICE1712_STDSP24_2_CHN4(ice->hoontech_boxbits, 1);
177         ICE1712_STDSP24_2_MIDIIN(ice->hoontech_boxbits, 1);
178         ICE1712_STDSP24_2_MIDI1(ice->hoontech_boxbits, 0);
179
180         ICE1712_STDSP24_SET_ADDR(ice->hoontech_boxbits, 3);
181         ICE1712_STDSP24_CLOCK(ice->hoontech_boxbits, 3, 1);
182         ICE1712_STDSP24_3_MIDI2(ice->hoontech_boxbits, 0);
183         ICE1712_STDSP24_3_MUTE(ice->hoontech_boxbits, 1);
184         ICE1712_STDSP24_3_INSEL(ice->hoontech_boxbits, 0);
185
186         /* let's go - activate only functions in first box */
187         ice->hoontech_config = 0;
188                             /* ICE1712_STDSP24_MUTE |
189                                ICE1712_STDSP24_INSEL |
190                                ICE1712_STDSP24_DAREAR; */
191         ice->hoontech_boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
192                                      ICE1712_STDSP24_BOX_CHN2 |
193                                      ICE1712_STDSP24_BOX_CHN3 |
194                                      ICE1712_STDSP24_BOX_CHN4 |
195                                      ICE1712_STDSP24_BOX_MIDI1 |
196                                      ICE1712_STDSP24_BOX_MIDI2;
197         ice->hoontech_boxconfig[1] = 
198         ice->hoontech_boxconfig[2] = 
199         ice->hoontech_boxconfig[3] = 0;
200         snd_ice1712_stdsp24_darear(ice, (ice->hoontech_config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
201         snd_ice1712_stdsp24_mute(ice, (ice->hoontech_config & ICE1712_STDSP24_MUTE) ? 1 : 0);
202         snd_ice1712_stdsp24_insel(ice, (ice->hoontech_config & ICE1712_STDSP24_INSEL) ? 1 : 0);
203         for (box = 0; box < 4; box++) {
204                 for (chn = 0; chn < 4; chn++)
205                         snd_ice1712_stdsp24_box_channel(ice, box, chn, (ice->hoontech_boxconfig[box] & (1 << chn)) ? 1 : 0);
206                 snd_ice1712_stdsp24_box_midi(ice, box,
207                                 (ice->hoontech_boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1) ? 1 : 0,
208                                 (ice->hoontech_boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2) ? 1 : 0);
209         }
210
211         return 0;
212 }
213
214
215 /* entry point */
216 struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
217         {
218                 ICE1712_SUBDEVICE_STDSP24,
219                 "Hoontech SoundTrack Audio DSP24",
220                 snd_ice1712_hoontech_init,
221         },
222         {
223                 ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
224                 "Hoontech STA DSP24 Media 7.1",
225                 snd_ice1712_hoontech_init,
226         },
227         { } /* terminator */
228 };
229