3d84d21e484da1586b036105e964c419c48d32c0
[pandora-kernel.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@perex.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 <linux/delay.h>
25 #include <linux/interrupt.h>
26 #include <linux/init.h>
27 #include <linux/slab.h>
28 #include <linux/mutex.h>
29
30 #include <sound/core.h>
31
32 #include "ice1712.h"
33 #include "hoontech.h"
34
35 /* Hoontech-specific setting */
36 struct hoontech_spec {
37         unsigned char boxbits[4];
38         unsigned int config;
39         unsigned short boxconfig[4];
40 };
41
42 static void __devinit snd_ice1712_stdsp24_gpio_write(struct snd_ice1712 *ice, unsigned char byte)
43 {
44         byte |= ICE1712_STDSP24_CLOCK_BIT;
45         udelay(100);
46         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
47         byte &= ~ICE1712_STDSP24_CLOCK_BIT;
48         udelay(100);
49         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
50         byte |= ICE1712_STDSP24_CLOCK_BIT;
51         udelay(100);
52         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, byte);
53 }
54
55 static void __devinit snd_ice1712_stdsp24_darear(struct snd_ice1712 *ice, int activate)
56 {
57         struct hoontech_spec *spec = ice->spec;
58         mutex_lock(&ice->gpio_mutex);
59         ICE1712_STDSP24_0_DAREAR(spec->boxbits, activate);
60         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
61         mutex_unlock(&ice->gpio_mutex);
62 }
63
64 static void __devinit snd_ice1712_stdsp24_mute(struct snd_ice1712 *ice, int activate)
65 {
66         struct hoontech_spec *spec = ice->spec;
67         mutex_lock(&ice->gpio_mutex);
68         ICE1712_STDSP24_3_MUTE(spec->boxbits, activate);
69         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
70         mutex_unlock(&ice->gpio_mutex);
71 }
72
73 static void __devinit snd_ice1712_stdsp24_insel(struct snd_ice1712 *ice, int activate)
74 {
75         struct hoontech_spec *spec = ice->spec;
76         mutex_lock(&ice->gpio_mutex);
77         ICE1712_STDSP24_3_INSEL(spec->boxbits, activate);
78         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
79         mutex_unlock(&ice->gpio_mutex);
80 }
81
82 static void __devinit snd_ice1712_stdsp24_box_channel(struct snd_ice1712 *ice, int box, int chn, int activate)
83 {
84         struct hoontech_spec *spec = ice->spec;
85
86         mutex_lock(&ice->gpio_mutex);
87
88         /* select box */
89         ICE1712_STDSP24_0_BOX(spec->boxbits, box);
90         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
91
92         /* prepare for write */
93         if (chn == 3)
94                 ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
95         ICE1712_STDSP24_2_MIDI1(spec->boxbits, activate);
96         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
97         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
98
99         ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
100         ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
101         ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
102         ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
103         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
104         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
105         udelay(100);
106         if (chn == 3) {
107                 ICE1712_STDSP24_2_CHN4(spec->boxbits, 0);
108                 snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
109         } else {
110                 switch (chn) {
111                 case 0: ICE1712_STDSP24_1_CHN1(spec->boxbits, 0); break;
112                 case 1: ICE1712_STDSP24_1_CHN2(spec->boxbits, 0); break;
113                 case 2: ICE1712_STDSP24_1_CHN3(spec->boxbits, 0); break;
114                 }
115                 snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
116         }
117         udelay(100);
118         ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
119         ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
120         ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
121         ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
122         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[1]);
123         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
124         udelay(100);
125
126         ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
127         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
128
129         mutex_unlock(&ice->gpio_mutex);
130 }
131
132 static void __devinit snd_ice1712_stdsp24_box_midi(struct snd_ice1712 *ice, int box, int master)
133 {
134         struct hoontech_spec *spec = ice->spec;
135
136         mutex_lock(&ice->gpio_mutex);
137
138         /* select box */
139         ICE1712_STDSP24_0_BOX(spec->boxbits, box);
140         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[0]);
141
142         ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
143         ICE1712_STDSP24_2_MIDI1(spec->boxbits, master);
144         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
145         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
146
147         udelay(100);
148         
149         ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 0);
150         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
151         
152         mdelay(10);
153         
154         ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
155         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[2]);
156
157         mutex_unlock(&ice->gpio_mutex);
158 }
159
160 static void __devinit snd_ice1712_stdsp24_midi2(struct snd_ice1712 *ice, int activate)
161 {
162         struct hoontech_spec *spec = ice->spec;
163         mutex_lock(&ice->gpio_mutex);
164         ICE1712_STDSP24_3_MIDI2(spec->boxbits, activate);
165         snd_ice1712_stdsp24_gpio_write(ice, spec->boxbits[3]);
166         mutex_unlock(&ice->gpio_mutex);
167 }
168
169 static int __devinit snd_ice1712_hoontech_init(struct snd_ice1712 *ice)
170 {
171         struct hoontech_spec *spec;
172         int box, chn;
173
174         ice->num_total_dacs = 8;
175         ice->num_total_adcs = 8;
176
177         spec = kzalloc(sizeof(*spec), GFP_KERNEL);
178         if (!spec)
179                 return -ENOMEM;
180         ice->spec = spec;
181
182         ICE1712_STDSP24_SET_ADDR(spec->boxbits, 0);
183         ICE1712_STDSP24_CLOCK(spec->boxbits, 0, 1);
184         ICE1712_STDSP24_0_BOX(spec->boxbits, 0);
185         ICE1712_STDSP24_0_DAREAR(spec->boxbits, 0);
186
187         ICE1712_STDSP24_SET_ADDR(spec->boxbits, 1);
188         ICE1712_STDSP24_CLOCK(spec->boxbits, 1, 1);
189         ICE1712_STDSP24_1_CHN1(spec->boxbits, 1);
190         ICE1712_STDSP24_1_CHN2(spec->boxbits, 1);
191         ICE1712_STDSP24_1_CHN3(spec->boxbits, 1);
192         
193         ICE1712_STDSP24_SET_ADDR(spec->boxbits, 2);
194         ICE1712_STDSP24_CLOCK(spec->boxbits, 2, 1);
195         ICE1712_STDSP24_2_CHN4(spec->boxbits, 1);
196         ICE1712_STDSP24_2_MIDIIN(spec->boxbits, 1);
197         ICE1712_STDSP24_2_MIDI1(spec->boxbits, 0);
198
199         ICE1712_STDSP24_SET_ADDR(spec->boxbits, 3);
200         ICE1712_STDSP24_CLOCK(spec->boxbits, 3, 1);
201         ICE1712_STDSP24_3_MIDI2(spec->boxbits, 0);
202         ICE1712_STDSP24_3_MUTE(spec->boxbits, 1);
203         ICE1712_STDSP24_3_INSEL(spec->boxbits, 0);
204
205         /* let's go - activate only functions in first box */
206         spec->config = 0;
207                             /* ICE1712_STDSP24_MUTE |
208                                ICE1712_STDSP24_INSEL |
209                                ICE1712_STDSP24_DAREAR; */
210         /*  These boxconfigs have caused problems in the past.
211          *  The code is not optimal, but should now enable a working config to
212          *  be achieved.
213          *  ** MIDI IN can only be configured on one box **
214          *  ICE1712_STDSP24_BOX_MIDI1 needs to be set for that box.
215          *  Tests on a ADAC2000 box suggest the box config flags do not
216          *  work as would be expected, and the inputs are crossed.
217          *  Setting ICE1712_STDSP24_BOX_MIDI1 and ICE1712_STDSP24_BOX_MIDI2
218          *  on the same box connects MIDI-In to both 401 uarts; both outputs
219          *  are then active on all boxes.
220          *  The default config here sets up everything on the first box.
221          *  Alan Horstmann  5.2.2008
222          */
223         spec->boxconfig[0] = ICE1712_STDSP24_BOX_CHN1 |
224                                      ICE1712_STDSP24_BOX_CHN2 |
225                                      ICE1712_STDSP24_BOX_CHN3 |
226                                      ICE1712_STDSP24_BOX_CHN4 |
227                                      ICE1712_STDSP24_BOX_MIDI1 |
228                                      ICE1712_STDSP24_BOX_MIDI2;
229         spec->boxconfig[1] = 
230         spec->boxconfig[2] = 
231         spec->boxconfig[3] = 0;
232         snd_ice1712_stdsp24_darear(ice,
233                 (spec->config & ICE1712_STDSP24_DAREAR) ? 1 : 0);
234         snd_ice1712_stdsp24_mute(ice,
235                 (spec->config & ICE1712_STDSP24_MUTE) ? 1 : 0);
236         snd_ice1712_stdsp24_insel(ice,
237                 (spec->config & ICE1712_STDSP24_INSEL) ? 1 : 0);
238         for (box = 0; box < 4; box++) {
239                 if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI2)
240                         snd_ice1712_stdsp24_midi2(ice, 1);
241                 for (chn = 0; chn < 4; chn++)
242                         snd_ice1712_stdsp24_box_channel(ice, box, chn,
243                                 (spec->boxconfig[box] & (1 << chn)) ? 1 : 0);
244                 if (spec->boxconfig[box] & ICE1712_STDSP24_BOX_MIDI1)
245                         snd_ice1712_stdsp24_box_midi(ice, box, 1);
246         }
247
248         return 0;
249 }
250
251 /*
252  * AK4524 access
253  */
254
255 /* start callback for STDSP24 with modified hardware */
256 static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
257 {
258         struct snd_ice1712 *ice = ak->private_data[0];
259         unsigned char tmp;
260         snd_ice1712_save_gpio_status(ice);
261         tmp =   ICE1712_STDSP24_SERIAL_DATA |
262                 ICE1712_STDSP24_SERIAL_CLOCK |
263                 ICE1712_STDSP24_AK4524_CS;
264         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION,
265                           ice->gpio.direction | tmp);
266         snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ~tmp);
267 }
268
269 static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
270 {
271         /* Hoontech STDSP24 with modified hardware */
272         static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
273                 .num_adcs = 2,
274                 .num_dacs = 2,
275                 .type = SND_AK4524,
276                 .ops = {
277                         .lock = stdsp24_ak4524_lock
278                 }
279         };
280
281         static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
282                 .caddr = 2,
283                 .cif = 1, /* CIF high */
284                 .data_mask = ICE1712_STDSP24_SERIAL_DATA,
285                 .clk_mask = ICE1712_STDSP24_SERIAL_CLOCK,
286                 .cs_mask = ICE1712_STDSP24_AK4524_CS,
287                 .cs_addr = ICE1712_STDSP24_AK4524_CS,
288                 .cs_none = 0,
289                 .add_flags = 0,
290         };
291
292         int err;
293         struct snd_akm4xxx *ak;
294
295         /* set the analog DACs */
296         ice->num_total_dacs = 2;
297
298         /* set the analog ADCs */
299         ice->num_total_adcs = 2;
300         
301         /* analog section */
302         ak = ice->akm = kmalloc(sizeof(struct snd_akm4xxx), GFP_KERNEL);
303         if (! ak)
304                 return -ENOMEM;
305         ice->akm_codecs = 1;
306
307         err = snd_ice1712_akm4xxx_init(ak, &akm_stdsp24_mv, &akm_stdsp24_mv_priv, ice);
308         if (err < 0)
309                 return err;
310
311         /* ak4524 controls */
312         err = snd_ice1712_akm4xxx_build_controls(ice);
313         if (err < 0)
314                 return err;
315
316         return 0;
317 }
318
319 static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
320 {
321         ice->gpio.write_mask = ice->eeprom.gpiomask;
322         ice->gpio.direction = ice->eeprom.gpiodir;
323         snd_ice1712_write(ice, ICE1712_IREG_GPIO_WRITE_MASK, ice->eeprom.gpiomask);
324         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DIRECTION, ice->eeprom.gpiodir);
325         snd_ice1712_write(ice, ICE1712_IREG_GPIO_DATA, ice->eeprom.gpiostate);
326         return 0;
327 }
328
329
330 /* entry point */
331 struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
332         {
333                 .subvendor = ICE1712_SUBDEVICE_STDSP24,
334                 .name = "Hoontech SoundTrack Audio DSP24",
335                 .model = "dsp24",
336                 .chip_init = snd_ice1712_hoontech_init,
337                 .mpu401_1_name = "MIDI-1 Hoontech/STA DSP24",
338                 .mpu401_2_name = "MIDI-2 Hoontech/STA DSP24",
339         },
340         {
341                 .subvendor = ICE1712_SUBDEVICE_STDSP24_VALUE,   /* a dummy id */
342                 .name = "Hoontech SoundTrack Audio DSP24 Value",
343                 .model = "dsp24_value",
344                 .chip_init = snd_ice1712_value_init,
345         },
346         {
347                 .subvendor = ICE1712_SUBDEVICE_STDSP24_MEDIA7_1,
348                 .name = "Hoontech STA DSP24 Media 7.1",
349                 .model = "dsp24_71",
350                 .chip_init = snd_ice1712_hoontech_init,
351         },
352         {
353                 .subvendor = ICE1712_SUBDEVICE_EVENT_EZ8,       /* a dummy id */
354                 .name = "Event Electronics EZ8",
355                 .model = "ez8",
356                 .chip_init = snd_ice1712_ez8_init,
357         },
358         { } /* terminator */
359 };