vserver 1.9.3
[linux-2.6.git] / sound / pci / cs46xx / cs46xx_lib.c
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3  *                   Abramo Bagnara <abramo@alsa-project.org>
4  *                   Cirrus Logic, Inc.
5  *  Routines for control of Cirrus Logic CS461x chips
6  *
7  *  KNOWN BUGS:
8  *    - Sometimes the SPDIF input DSP tasks get's unsynchronized
9  *      and the SPDIF get somewhat "distorcionated", or/and left right channel
10  *      are swapped. To get around this problem when it happens, mute and unmute 
11  *      the SPDIF input mixer controll.
12  *    - On the Hercules Game Theater XP the amplifier are sometimes turned
13  *      off on inadecuate moments which causes distorcions on sound.
14  *
15  *  TODO:
16  *    - Secondary CODEC on some soundcards
17  *    - SPDIF input support for other sample rates then 48khz
18  *    - Posibility to mix the SPDIF output with analog sources.
19  *    - PCM channels for Center and LFE on secondary codec
20  *
21  *  NOTE: with CONFIG_SND_CS46XX_NEW_DSP unset uses old DSP image (which
22  *        is default configuration), no SPDIF, no secondary codec, no
23  *        multi channel PCM.  But known to work.
24  *
25  *  FINALLY: A credit to the developers Tom and Jordan 
26  *           at Cirrus for have helping me out with the DSP, however we
27  *           still don't have sufficient documentation and technical
28  *           references to be able to implement all fancy feutures
29  *           supported by the cs46xx DSP's. 
30  *           Benny <benny@hostmobility.com>
31  *                
32  *   This program is free software; you can redistribute it and/or modify
33  *   it under the terms of the GNU General Public License as published by
34  *   the Free Software Foundation; either version 2 of the License, or
35  *   (at your option) any later version.
36  *
37  *   This program is distributed in the hope that it will be useful,
38  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
39  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40  *   GNU General Public License for more details.
41  *
42  *   You should have received a copy of the GNU General Public License
43  *   along with this program; if not, write to the Free Software
44  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
45  *
46  */
47
48 #include <sound/driver.h>
49 #include <linux/delay.h>
50 #include <linux/pci.h>
51 #include <linux/pm.h>
52 #include <linux/init.h>
53 #include <linux/interrupt.h>
54 #include <linux/slab.h>
55 #include <linux/gameport.h>
56
57 #include <sound/core.h>
58 #include <sound/control.h>
59 #include <sound/info.h>
60 #include <sound/pcm.h>
61 #include <sound/pcm_params.h>
62 #include <sound/cs46xx.h>
63
64 #include <asm/io.h>
65
66 #include "cs46xx_lib.h"
67 #include "dsp_spos.h"
68
69 static void amp_voyetra(cs46xx_t *chip, int change);
70
71 static unsigned short snd_cs46xx_codec_read(cs46xx_t *chip,
72                                             unsigned short reg,
73                                             int codec_index)
74 {
75         int count;
76         unsigned short result,tmp;
77         u32 offset = 0;
78         snd_assert ( (codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
79                      (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
80                      return -EINVAL);
81
82         chip->active_ctrl(chip, 1);
83
84         if (codec_index == CS46XX_SECONDARY_CODEC_INDEX)
85                 offset = CS46XX_SECONDARY_CODEC_OFFSET;
86
87         /*
88          *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
89          *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97 
90          *  3. Write ACCTL = Control Register = 460h for initiating the write7---55
91          *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 17h
92          *  5. if DCV not cleared, break and return error
93          *  6. Read ACSTS = Status Register = 464h, check VSTS bit
94          */
95
96         snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
97
98         tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL);
99         if ((tmp & ACCTL_VFRM) == 0) {
100                 snd_printk(KERN_WARNING  "cs46xx: ACCTL_VFRM not set 0x%x\n",tmp);
101                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, (tmp & (~ACCTL_ESYN)) | ACCTL_VFRM );
102                 mdelay(50);
103                 tmp = snd_cs46xx_peekBA0(chip, BA0_ACCTL + offset);
104                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, tmp | ACCTL_ESYN | ACCTL_VFRM );
105
106         }
107
108         /*
109          *  Setup the AC97 control registers on the CS461x to send the
110          *  appropriate command to the AC97 to perform the read.
111          *  ACCAD = Command Address Register = 46Ch
112          *  ACCDA = Command Data Register = 470h
113          *  ACCTL = Control Register = 460h
114          *  set DCV - will clear when process completed
115          *  set CRW - Read command
116          *  set VFRM - valid frame enabled
117          *  set ESYN - ASYNC generation enabled
118          *  set RSTN - ARST# inactive, AC97 codec not reset
119          */
120
121         snd_cs46xx_pokeBA0(chip, BA0_ACCAD, reg);
122         snd_cs46xx_pokeBA0(chip, BA0_ACCDA, 0);
123         if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
124                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL,/* clear ACCTL_DCV */ ACCTL_CRW | 
125                                    ACCTL_VFRM | ACCTL_ESYN |
126                                    ACCTL_RSTN);
127                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_CRW |
128                                    ACCTL_VFRM | ACCTL_ESYN |
129                                    ACCTL_RSTN);
130         } else {
131                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
132                                    ACCTL_CRW | ACCTL_VFRM | ACCTL_ESYN |
133                                    ACCTL_RSTN);
134         }
135
136         /*
137          *  Wait for the read to occur.
138          */
139         for (count = 0; count < 1000; count++) {
140                 /*
141                  *  First, we want to wait for a short time.
142                  */
143                 udelay(10);
144                 /*
145                  *  Now, check to see if the read has completed.
146                  *  ACCTL = 460h, DCV should be reset by now and 460h = 17h
147                  */
148                 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV))
149                         goto ok1;
150         }
151
152         snd_printk("AC'97 read problem (ACCTL_DCV), reg = 0x%x\n", reg);
153         result = 0xffff;
154         goto end;
155         
156  ok1:
157         /*
158          *  Wait for the valid status bit to go active.
159          */
160         for (count = 0; count < 100; count++) {
161                 /*
162                  *  Read the AC97 status register.
163                  *  ACSTS = Status Register = 464h
164                  *  VSTS - Valid Status
165                  */
166                 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS + offset) & ACSTS_VSTS)
167                         goto ok2;
168                 udelay(10);
169         }
170         
171         snd_printk("AC'97 read problem (ACSTS_VSTS), codec_index %d, reg = 0x%x\n", codec_index, reg);
172         result = 0xffff;
173         goto end;
174
175  ok2:
176         /*
177          *  Read the data returned from the AC97 register.
178          *  ACSDA = Status Data Register = 474h
179          */
180 #if 0
181         printk("e) reg = 0x%x, val = 0x%x, BA0_ACCAD = 0x%x\n", reg,
182                         snd_cs46xx_peekBA0(chip, BA0_ACSDA),
183                         snd_cs46xx_peekBA0(chip, BA0_ACCAD));
184 #endif
185
186         //snd_cs46xx_peekBA0(chip, BA0_ACCAD);
187         result = snd_cs46xx_peekBA0(chip, BA0_ACSDA + offset);
188  end:
189         chip->active_ctrl(chip, -1);
190         return result;
191 }
192
193 static unsigned short snd_cs46xx_ac97_read(ac97_t * ac97,
194                                             unsigned short reg)
195 {
196         cs46xx_t *chip = ac97->private_data;
197         unsigned short val;
198         int codec_index = ac97->num;
199
200         snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
201                    codec_index == CS46XX_SECONDARY_CODEC_INDEX,
202                    return 0xffff);
203
204         val = snd_cs46xx_codec_read(chip, reg, codec_index);
205
206         /* HACK: voyetra uses EAPD bit in the reverse way.
207          * we flip the bit to show the mixer status correctly
208          */
209         if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
210                 val ^= 0x8000;
211
212         return val;
213 }
214
215
216 static void snd_cs46xx_codec_write(cs46xx_t *chip,
217                                    unsigned short reg,
218                                    unsigned short val,
219                                    int codec_index)
220 {
221         int count;
222
223         snd_assert ((codec_index == CS46XX_PRIMARY_CODEC_INDEX) ||
224                     (codec_index == CS46XX_SECONDARY_CODEC_INDEX),
225                     return);
226
227         chip->active_ctrl(chip, 1);
228
229         /*
230          *  1. Write ACCAD = Command Address Register = 46Ch for AC97 register address
231          *  2. Write ACCDA = Command Data Register = 470h    for data to write to AC97
232          *  3. Write ACCTL = Control Register = 460h for initiating the write
233          *  4. Read ACCTL = 460h, DCV should be reset by now and 460h = 07h
234          *  5. if DCV not cleared, break and return error
235          */
236
237         /*
238          *  Setup the AC97 control registers on the CS461x to send the
239          *  appropriate command to the AC97 to perform the read.
240          *  ACCAD = Command Address Register = 46Ch
241          *  ACCDA = Command Data Register = 470h
242          *  ACCTL = Control Register = 460h
243          *  set DCV - will clear when process completed
244          *  reset CRW - Write command
245          *  set VFRM - valid frame enabled
246          *  set ESYN - ASYNC generation enabled
247          *  set RSTN - ARST# inactive, AC97 codec not reset
248          */
249         snd_cs46xx_pokeBA0(chip, BA0_ACCAD , reg);
250         snd_cs46xx_pokeBA0(chip, BA0_ACCDA , val);
251         snd_cs46xx_peekBA0(chip, BA0_ACCTL);
252
253         if (codec_index == CS46XX_PRIMARY_CODEC_INDEX) {
254                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, /* clear ACCTL_DCV */ ACCTL_VFRM |
255                                    ACCTL_ESYN | ACCTL_RSTN);
256                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_VFRM |
257                                    ACCTL_ESYN | ACCTL_RSTN);
258         } else {
259                 snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_DCV | ACCTL_TC |
260                                    ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
261         }
262
263         for (count = 0; count < 4000; count++) {
264                 /*
265                  *  First, we want to wait for a short time.
266                  */
267                 udelay(10);
268                 /*
269                  *  Now, check to see if the write has completed.
270                  *  ACCTL = 460h, DCV should be reset by now and 460h = 07h
271                  */
272                 if (!(snd_cs46xx_peekBA0(chip, BA0_ACCTL) & ACCTL_DCV)) {
273                         goto end;
274                 }
275         }
276         snd_printk("AC'97 write problem, codec_index = %d, reg = 0x%x, val = 0x%x\n", codec_index, reg, val);
277  end:
278         chip->active_ctrl(chip, -1);
279 }
280
281 static void snd_cs46xx_ac97_write(ac97_t *ac97,
282                                    unsigned short reg,
283                                    unsigned short val)
284 {
285         cs46xx_t *chip = ac97->private_data;
286         int codec_index = ac97->num;
287
288         snd_assert(codec_index == CS46XX_PRIMARY_CODEC_INDEX ||
289                    codec_index == CS46XX_SECONDARY_CODEC_INDEX,
290                    return);
291
292         /* HACK: voyetra uses EAPD bit in the reverse way.
293          * we flip the bit to show the mixer status correctly
294          */
295         if (reg == AC97_POWERDOWN && chip->amplifier_ctrl == amp_voyetra)
296                 val ^= 0x8000;
297
298         snd_cs46xx_codec_write(chip, reg, val, codec_index);
299 }
300
301
302 /*
303  *  Chip initialization
304  */
305
306 int snd_cs46xx_download(cs46xx_t *chip,
307                         u32 *src,
308                         unsigned long offset,
309                         unsigned long len)
310 {
311         unsigned long dst;
312         unsigned int bank = offset >> 16;
313         offset = offset & 0xffff;
314
315         snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
316         dst = chip->region.idx[bank+1].remap_addr + offset;
317         len /= sizeof(u32);
318
319         /* writel already converts 32-bit value to right endianess */
320         while (len-- > 0) {
321                 writel(*src++, dst);
322                 dst += sizeof(u32);
323         }
324         return 0;
325 }
326
327 #ifdef CONFIG_SND_CS46XX_NEW_DSP
328
329 #include "imgs/cwc4630.h"
330 #include "imgs/cwcasync.h"
331 #include "imgs/cwcsnoop.h"
332 #include "imgs/cwcbinhack.h"
333 #include "imgs/cwcdma.h"
334
335 int snd_cs46xx_clear_BA1(cs46xx_t *chip,
336                          unsigned long offset,
337                          unsigned long len) 
338 {
339         unsigned long dst;
340         unsigned int bank = offset >> 16;
341         offset = offset & 0xffff;
342
343         snd_assert(!(offset & 3) && !(len & 3), return -EINVAL);
344         dst = chip->region.idx[bank+1].remap_addr + offset;
345         len /= sizeof(u32);
346
347         /* writel already converts 32-bit value to right endianess */
348         while (len-- > 0) {
349                 writel(0, dst);
350                 dst += sizeof(u32);
351         }
352         return 0;
353 }
354
355 #else /* old DSP image */
356
357 #include "cs46xx_image.h"
358
359 int snd_cs46xx_download_image(cs46xx_t *chip)
360 {
361         int idx, err;
362         unsigned long offset = 0;
363
364         for (idx = 0; idx < BA1_MEMORY_COUNT; idx++) {
365                 if ((err = snd_cs46xx_download(chip,
366                                                &BA1Struct.map[offset],
367                                                BA1Struct.memory[idx].offset,
368                                                BA1Struct.memory[idx].size)) < 0)
369                         return err;
370                 offset += BA1Struct.memory[idx].size >> 2;
371         }       
372         return 0;
373 }
374 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
375
376 /*
377  *  Chip reset
378  */
379
380 static void snd_cs46xx_reset(cs46xx_t *chip)
381 {
382         int idx;
383
384         /*
385          *  Write the reset bit of the SP control register.
386          */
387         snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RSTSP);
388
389         /*
390          *  Write the control register.
391          */
392         snd_cs46xx_poke(chip, BA1_SPCR, SPCR_DRQEN);
393
394         /*
395          *  Clear the trap registers.
396          */
397         for (idx = 0; idx < 8; idx++) {
398                 snd_cs46xx_poke(chip, BA1_DREG, DREG_REGID_TRAP_SELECT + idx);
399                 snd_cs46xx_poke(chip, BA1_TWPR, 0xFFFF);
400         }
401         snd_cs46xx_poke(chip, BA1_DREG, 0);
402
403         /*
404          *  Set the frame timer to reflect the number of cycles per frame.
405          */
406         snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
407 }
408
409 static int cs46xx_wait_for_fifo(cs46xx_t * chip,int retry_timeout) 
410 {
411         u32 i, status = 0;
412         /*
413          * Make sure the previous FIFO write operation has completed.
414          */
415         for(i = 0; i < 50; i++){
416                 status = snd_cs46xx_peekBA0(chip, BA0_SERBST);
417     
418                 if( !(status & SERBST_WBSY) )
419                         break;
420
421                 mdelay(retry_timeout);
422         }
423   
424         if(status & SERBST_WBSY) {
425                 snd_printk( KERN_ERR "cs46xx: failure waiting for FIFO command to complete\n");
426
427                 return -EINVAL;
428         }
429
430         return 0;
431 }
432
433 static void snd_cs46xx_clear_serial_FIFOs(cs46xx_t *chip)
434 {
435         int idx, powerdown = 0;
436         unsigned int tmp;
437
438         /*
439          *  See if the devices are powered down.  If so, we must power them up first
440          *  or they will not respond.
441          */
442         tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
443         if (!(tmp & CLKCR1_SWCE)) {
444                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
445                 powerdown = 1;
446         }
447
448         /*
449          *  We want to clear out the serial port FIFOs so we don't end up playing
450          *  whatever random garbage happens to be in them.  We fill the sample FIFOS
451          *  with zero (silence).
452          */
453         snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0);
454
455         /*
456          *  Fill all 256 sample FIFO locations.
457          */
458         for (idx = 0; idx < 0xFF; idx++) {
459                 /*
460                  *  Make sure the previous FIFO write operation has completed.
461                  */
462                 if (cs46xx_wait_for_fifo(chip,1)) {
463                         snd_printdd ("failed waiting for FIFO at addr (%02X)\n",idx);
464
465                         if (powerdown)
466                                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
467           
468                         break;
469                 }
470                 /*
471                  *  Write the serial port FIFO index.
472                  */
473                 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
474                 /*
475                  *  Tell the serial port to load the new value into the FIFO location.
476                  */
477                 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
478         }
479         /*
480          *  Now, if we powered up the devices, then power them back down again.
481          *  This is kinda ugly, but should never happen.
482          */
483         if (powerdown)
484                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
485 }
486
487 static void snd_cs46xx_proc_start(cs46xx_t *chip)
488 {
489         int cnt;
490
491         /*
492          *  Set the frame timer to reflect the number of cycles per frame.
493          */
494         snd_cs46xx_poke(chip, BA1_FRMT, 0xadf);
495         /*
496          *  Turn on the run, run at frame, and DMA enable bits in the local copy of
497          *  the SP control register.
498          */
499         snd_cs46xx_poke(chip, BA1_SPCR, SPCR_RUN | SPCR_RUNFR | SPCR_DRQEN);
500         /*
501          *  Wait until the run at frame bit resets itself in the SP control
502          *  register.
503          */
504         for (cnt = 0; cnt < 25; cnt++) {
505                 udelay(50);
506                 if (!(snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR))
507                         break;
508         }
509
510         if (snd_cs46xx_peek(chip, BA1_SPCR) & SPCR_RUNFR)
511                 snd_printk("SPCR_RUNFR never reset\n");
512 }
513
514 static void snd_cs46xx_proc_stop(cs46xx_t *chip)
515 {
516         /*
517          *  Turn off the run, run at frame, and DMA enable bits in the local copy of
518          *  the SP control register.
519          */
520         snd_cs46xx_poke(chip, BA1_SPCR, 0);
521 }
522
523 /*
524  *  Sample rate routines
525  */
526
527 #define GOF_PER_SEC 200
528
529 static void snd_cs46xx_set_play_sample_rate(cs46xx_t *chip, unsigned int rate)
530 {
531         unsigned long flags;
532         unsigned int tmp1, tmp2;
533         unsigned int phiIncr;
534         unsigned int correctionPerGOF, correctionPerSec;
535
536         /*
537          *  Compute the values used to drive the actual sample rate conversion.
538          *  The following formulas are being computed, using inline assembly
539          *  since we need to use 64 bit arithmetic to compute the values:
540          *
541          *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
542          *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
543          *                                   GOF_PER_SEC)
544          *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
545          *                       GOF_PER_SEC * correctionPerGOF
546          *
547          *  i.e.
548          *
549          *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
550          *  correctionPerGOF:correctionPerSec =
551          *      dividend:remainder(ulOther / GOF_PER_SEC)
552          */
553         tmp1 = rate << 16;
554         phiIncr = tmp1 / 48000;
555         tmp1 -= phiIncr * 48000;
556         tmp1 <<= 10;
557         phiIncr <<= 10;
558         tmp2 = tmp1 / 48000;
559         phiIncr += tmp2;
560         tmp1 -= tmp2 * 48000;
561         correctionPerGOF = tmp1 / GOF_PER_SEC;
562         tmp1 -= correctionPerGOF * GOF_PER_SEC;
563         correctionPerSec = tmp1;
564
565         /*
566          *  Fill in the SampleRateConverter control block.
567          */
568         spin_lock_irqsave(&chip->reg_lock, flags);
569         snd_cs46xx_poke(chip, BA1_PSRC,
570           ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
571         snd_cs46xx_poke(chip, BA1_PPI, phiIncr);
572         spin_unlock_irqrestore(&chip->reg_lock, flags);
573 }
574
575 static void snd_cs46xx_set_capture_sample_rate(cs46xx_t *chip, unsigned int rate)
576 {
577         unsigned long flags;
578         unsigned int phiIncr, coeffIncr, tmp1, tmp2;
579         unsigned int correctionPerGOF, correctionPerSec, initialDelay;
580         unsigned int frameGroupLength, cnt;
581
582         /*
583          *  We can only decimate by up to a factor of 1/9th the hardware rate.
584          *  Correct the value if an attempt is made to stray outside that limit.
585          */
586         if ((rate * 9) < 48000)
587                 rate = 48000 / 9;
588
589         /*
590          *  We can not capture at at rate greater than the Input Rate (48000).
591          *  Return an error if an attempt is made to stray outside that limit.
592          */
593         if (rate > 48000)
594                 rate = 48000;
595
596         /*
597          *  Compute the values used to drive the actual sample rate conversion.
598          *  The following formulas are being computed, using inline assembly
599          *  since we need to use 64 bit arithmetic to compute the values:
600          *
601          *     coeffIncr = -floor((Fs,out * 2^23) / Fs,in)
602          *     phiIncr = floor((Fs,in * 2^26) / Fs,out)
603          *     correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
604          *                                GOF_PER_SEC)
605          *     correctionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -
606          *                          GOF_PER_SEC * correctionPerGOF
607          *     initialDelay = ceil((24 * Fs,in) / Fs,out)
608          *
609          * i.e.
610          *
611          *     coeffIncr = neg(dividend((Fs,out * 2^23) / Fs,in))
612          *     phiIncr:ulOther = dividend:remainder((Fs,in * 2^26) / Fs,out)
613          *     correctionPerGOF:correctionPerSec =
614          *          dividend:remainder(ulOther / GOF_PER_SEC)
615          *     initialDelay = dividend(((24 * Fs,in) + Fs,out - 1) / Fs,out)
616          */
617
618         tmp1 = rate << 16;
619         coeffIncr = tmp1 / 48000;
620         tmp1 -= coeffIncr * 48000;
621         tmp1 <<= 7;
622         coeffIncr <<= 7;
623         coeffIncr += tmp1 / 48000;
624         coeffIncr ^= 0xFFFFFFFF;
625         coeffIncr++;
626         tmp1 = 48000 << 16;
627         phiIncr = tmp1 / rate;
628         tmp1 -= phiIncr * rate;
629         tmp1 <<= 10;
630         phiIncr <<= 10;
631         tmp2 = tmp1 / rate;
632         phiIncr += tmp2;
633         tmp1 -= tmp2 * rate;
634         correctionPerGOF = tmp1 / GOF_PER_SEC;
635         tmp1 -= correctionPerGOF * GOF_PER_SEC;
636         correctionPerSec = tmp1;
637         initialDelay = ((48000 * 24) + rate - 1) / rate;
638
639         /*
640          *  Fill in the VariDecimate control block.
641          */
642         spin_lock_irqsave(&chip->reg_lock, flags);
643         snd_cs46xx_poke(chip, BA1_CSRC,
644                 ((correctionPerSec << 16) & 0xFFFF0000) | (correctionPerGOF & 0xFFFF));
645         snd_cs46xx_poke(chip, BA1_CCI, coeffIncr);
646         snd_cs46xx_poke(chip, BA1_CD,
647                 (((BA1_VARIDEC_BUF_1 + (initialDelay << 2)) << 16) & 0xFFFF0000) | 0x80);
648         snd_cs46xx_poke(chip, BA1_CPI, phiIncr);
649         spin_unlock_irqrestore(&chip->reg_lock, flags);
650
651         /*
652          *  Figure out the frame group length for the write back task.  Basically,
653          *  this is just the factors of 24000 (2^6*3*5^3) that are not present in
654          *  the output sample rate.
655          */
656         frameGroupLength = 1;
657         for (cnt = 2; cnt <= 64; cnt *= 2) {
658                 if (((rate / cnt) * cnt) != rate)
659                         frameGroupLength *= 2;
660         }
661         if (((rate / 3) * 3) != rate) {
662                 frameGroupLength *= 3;
663         }
664         for (cnt = 5; cnt <= 125; cnt *= 5) {
665                 if (((rate / cnt) * cnt) != rate) 
666                         frameGroupLength *= 5;
667         }
668
669         /*
670          * Fill in the WriteBack control block.
671          */
672         spin_lock_irqsave(&chip->reg_lock, flags);
673         snd_cs46xx_poke(chip, BA1_CFG1, frameGroupLength);
674         snd_cs46xx_poke(chip, BA1_CFG2, (0x00800000 | frameGroupLength));
675         snd_cs46xx_poke(chip, BA1_CCST, 0x0000FFFF);
676         snd_cs46xx_poke(chip, BA1_CSPB, ((65536 * rate) / 24000));
677         snd_cs46xx_poke(chip, (BA1_CSPB + 4), 0x0000FFFF);
678         spin_unlock_irqrestore(&chip->reg_lock, flags);
679 }
680
681 /*
682  *  PCM part
683  */
684
685 static void snd_cs46xx_pb_trans_copy(snd_pcm_substream_t *substream,
686                                      snd_pcm_indirect_t *rec, size_t bytes)
687 {
688         snd_pcm_runtime_t *runtime = substream->runtime;
689         cs46xx_pcm_t * cpcm = runtime->private_data;
690         memcpy(cpcm->hw_buf.area + rec->hw_data, runtime->dma_area + rec->sw_data, bytes);
691 }
692
693 static int snd_cs46xx_playback_transfer(snd_pcm_substream_t *substream)
694 {
695         snd_pcm_runtime_t *runtime = substream->runtime;
696         cs46xx_pcm_t * cpcm = runtime->private_data;
697         snd_pcm_indirect_playback_transfer(substream, &cpcm->pcm_rec, snd_cs46xx_pb_trans_copy);
698         return 0;
699 }
700
701 static void snd_cs46xx_cp_trans_copy(snd_pcm_substream_t *substream,
702                                      snd_pcm_indirect_t *rec, size_t bytes)
703 {
704         cs46xx_t *chip = snd_pcm_substream_chip(substream);
705         snd_pcm_runtime_t *runtime = substream->runtime;
706         memcpy(runtime->dma_area + rec->sw_data,
707                chip->capt.hw_buf.area + rec->hw_data, bytes);
708 }
709
710 static int snd_cs46xx_capture_transfer(snd_pcm_substream_t *substream)
711 {
712         cs46xx_t *chip = snd_pcm_substream_chip(substream);
713         snd_pcm_indirect_capture_transfer(substream, &chip->capt.pcm_rec, snd_cs46xx_cp_trans_copy);
714         return 0;
715 }
716
717 static snd_pcm_uframes_t snd_cs46xx_playback_direct_pointer(snd_pcm_substream_t * substream)
718 {
719         cs46xx_t *chip = snd_pcm_substream_chip(substream);
720         size_t ptr;
721         cs46xx_pcm_t *cpcm = substream->runtime->private_data;
722         snd_assert (cpcm->pcm_channel,return -ENXIO);
723
724 #ifdef CONFIG_SND_CS46XX_NEW_DSP
725         ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
726 #else
727         ptr = snd_cs46xx_peek(chip, BA1_PBA);
728 #endif
729         ptr -= cpcm->hw_buf.addr;
730         return ptr >> cpcm->shift;
731 }
732
733 static snd_pcm_uframes_t snd_cs46xx_playback_indirect_pointer(snd_pcm_substream_t * substream)
734 {
735         cs46xx_t *chip = snd_pcm_substream_chip(substream);
736         size_t ptr;
737         cs46xx_pcm_t *cpcm = substream->runtime->private_data;
738
739 #ifdef CONFIG_SND_CS46XX_NEW_DSP
740         snd_assert (cpcm->pcm_channel,return -ENXIO);
741         ptr = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 2) << 2);
742 #else
743         ptr = snd_cs46xx_peek(chip, BA1_PBA);
744 #endif
745         ptr -= cpcm->hw_buf.addr;
746         return snd_pcm_indirect_playback_pointer(substream, &cpcm->pcm_rec, ptr);
747 }
748
749 static snd_pcm_uframes_t snd_cs46xx_capture_direct_pointer(snd_pcm_substream_t * substream)
750 {
751         cs46xx_t *chip = snd_pcm_substream_chip(substream);
752         size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
753         return ptr >> chip->capt.shift;
754 }
755
756 static snd_pcm_uframes_t snd_cs46xx_capture_indirect_pointer(snd_pcm_substream_t * substream)
757 {
758         cs46xx_t *chip = snd_pcm_substream_chip(substream);
759         size_t ptr = snd_cs46xx_peek(chip, BA1_CBA) - chip->capt.hw_buf.addr;
760         return snd_pcm_indirect_capture_pointer(substream, &chip->capt.pcm_rec, ptr);
761 }
762
763 static int snd_cs46xx_playback_trigger(snd_pcm_substream_t * substream,
764                                        int cmd)
765 {
766         cs46xx_t *chip = snd_pcm_substream_chip(substream);
767         /*snd_pcm_runtime_t *runtime = substream->runtime;*/
768         int result = 0;
769
770 #ifdef CONFIG_SND_CS46XX_NEW_DSP
771         cs46xx_pcm_t *cpcm = substream->runtime->private_data;
772         if (! cpcm->pcm_channel) {
773                 return -ENXIO;
774         }
775 #endif
776         switch (cmd) {
777         case SNDRV_PCM_TRIGGER_START:
778         case SNDRV_PCM_TRIGGER_RESUME:
779 #ifdef CONFIG_SND_CS46XX_NEW_DSP
780                 /* magic value to unmute PCM stream  playback volume */
781                 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 
782                                        SCBVolumeCtrl) << 2, 0x80008000);
783
784                 if (cpcm->pcm_channel->unlinked)
785                         cs46xx_dsp_pcm_link(chip,cpcm->pcm_channel);
786
787                 if (substream->runtime->periods != CS46XX_FRAGS)
788                         snd_cs46xx_playback_transfer(substream);
789 #else
790                 spin_lock(&chip->reg_lock);
791                 if (substream->runtime->periods != CS46XX_FRAGS)
792                         snd_cs46xx_playback_transfer(substream);
793                 { unsigned int tmp;
794                 tmp = snd_cs46xx_peek(chip, BA1_PCTL);
795                 tmp &= 0x0000ffff;
796                 snd_cs46xx_poke(chip, BA1_PCTL, chip->play_ctl | tmp);
797                 }
798                 spin_unlock(&chip->reg_lock);
799 #endif
800                 break;
801         case SNDRV_PCM_TRIGGER_STOP:
802         case SNDRV_PCM_TRIGGER_SUSPEND:
803 #ifdef CONFIG_SND_CS46XX_NEW_DSP
804                 /* magic mute channel */
805                 snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 
806                                        SCBVolumeCtrl) << 2, 0xffffffff);
807
808                 if (!cpcm->pcm_channel->unlinked)
809                         cs46xx_dsp_pcm_unlink(chip,cpcm->pcm_channel);
810 #else
811                 spin_lock(&chip->reg_lock);
812                 { unsigned int tmp;
813                 tmp = snd_cs46xx_peek(chip, BA1_PCTL);
814                 tmp &= 0x0000ffff;
815                 snd_cs46xx_poke(chip, BA1_PCTL, tmp);
816                 }
817                 spin_unlock(&chip->reg_lock);
818 #endif
819                 break;
820         default:
821                 result = -EINVAL;
822                 break;
823         }
824
825         return result;
826 }
827
828 static int snd_cs46xx_capture_trigger(snd_pcm_substream_t * substream,
829                                       int cmd)
830 {
831         cs46xx_t *chip = snd_pcm_substream_chip(substream);
832         unsigned int tmp;
833         int result = 0;
834
835         spin_lock(&chip->reg_lock);
836         switch (cmd) {
837         case SNDRV_PCM_TRIGGER_START:
838         case SNDRV_PCM_TRIGGER_RESUME:
839                 tmp = snd_cs46xx_peek(chip, BA1_CCTL);
840                 tmp &= 0xffff0000;
841                 snd_cs46xx_poke(chip, BA1_CCTL, chip->capt.ctl | tmp);
842                 break;
843         case SNDRV_PCM_TRIGGER_STOP:
844         case SNDRV_PCM_TRIGGER_SUSPEND:
845                 tmp = snd_cs46xx_peek(chip, BA1_CCTL);
846                 tmp &= 0xffff0000;
847                 snd_cs46xx_poke(chip, BA1_CCTL, tmp);
848                 break;
849         default:
850                 result = -EINVAL;
851                 break;
852         }
853         spin_unlock(&chip->reg_lock);
854
855         return result;
856 }
857
858 #ifdef CONFIG_SND_CS46XX_NEW_DSP
859 static int _cs46xx_adjust_sample_rate (cs46xx_t *chip, cs46xx_pcm_t *cpcm,
860                                        int sample_rate) 
861 {
862
863         /* If PCMReaderSCB and SrcTaskSCB not created yet ... */
864         if ( cpcm->pcm_channel == NULL) {
865                 cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, 
866                                                                    cpcm, cpcm->hw_buf.addr,cpcm->pcm_channel_id);
867                 if (cpcm->pcm_channel == NULL) {
868                         snd_printk(KERN_ERR "cs46xx: failed to create virtual PCM channel\n");
869                         return -ENOMEM;
870                 }
871                 cpcm->pcm_channel->sample_rate = sample_rate;
872         } else
873         /* if sample rate is changed */
874         if ((int)cpcm->pcm_channel->sample_rate != sample_rate) {
875                 int unlinked = cpcm->pcm_channel->unlinked;
876                 cs46xx_dsp_destroy_pcm_channel (chip,cpcm->pcm_channel);
877
878                 if ( (cpcm->pcm_channel = cs46xx_dsp_create_pcm_channel (chip, sample_rate, cpcm, 
879                                                                          cpcm->hw_buf.addr,
880                                                                          cpcm->pcm_channel_id)) == NULL) {
881                         snd_printk(KERN_ERR "cs46xx: failed to re-create virtual PCM channel\n");
882                         return -ENOMEM;
883                 }
884
885                 if (!unlinked) cs46xx_dsp_pcm_link (chip,cpcm->pcm_channel);
886                 cpcm->pcm_channel->sample_rate = sample_rate;
887         }
888
889         return 0;
890 }
891 #endif
892
893
894 static int snd_cs46xx_playback_hw_params(snd_pcm_substream_t * substream,
895                                          snd_pcm_hw_params_t * hw_params)
896 {
897         snd_pcm_runtime_t *runtime = substream->runtime;
898         cs46xx_pcm_t *cpcm;
899         int err;
900 #ifdef CONFIG_SND_CS46XX_NEW_DSP
901         cs46xx_t *chip = snd_pcm_substream_chip(substream);
902         int sample_rate = params_rate(hw_params);
903         int period_size = params_period_bytes(hw_params);
904 #endif
905         cpcm = runtime->private_data;
906
907 #ifdef CONFIG_SND_CS46XX_NEW_DSP
908         snd_assert (sample_rate != 0, return -ENXIO);
909
910         down (&chip->spos_mutex);
911
912         if (_cs46xx_adjust_sample_rate (chip,cpcm,sample_rate)) {
913                 up (&chip->spos_mutex);
914                 return -ENXIO;
915         }
916
917         snd_assert (cpcm->pcm_channel != NULL);
918         if (!cpcm->pcm_channel) {
919                 up (&chip->spos_mutex);
920                 return -ENXIO;
921         }
922
923
924         if (cs46xx_dsp_pcm_channel_set_period (chip,cpcm->pcm_channel,period_size)) {
925                  up (&chip->spos_mutex);
926                  return -EINVAL;
927          }
928
929         snd_printdd ("period_size (%d), periods (%d) buffer_size(%d)\n",
930                      period_size, params_periods(hw_params),
931                      params_buffer_bytes(hw_params));
932 #endif
933
934         if (params_periods(hw_params) == CS46XX_FRAGS) {
935                 if (runtime->dma_area != cpcm->hw_buf.area)
936                         snd_pcm_lib_free_pages(substream);
937                 runtime->dma_area = cpcm->hw_buf.area;
938                 runtime->dma_addr = cpcm->hw_buf.addr;
939                 runtime->dma_bytes = cpcm->hw_buf.bytes;
940
941
942 #ifdef CONFIG_SND_CS46XX_NEW_DSP
943                 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
944                         substream->ops = &snd_cs46xx_playback_ops;
945                 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
946                         substream->ops = &snd_cs46xx_playback_rear_ops;
947                 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
948                         substream->ops = &snd_cs46xx_playback_clfe_ops;
949                 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
950                         substream->ops = &snd_cs46xx_playback_iec958_ops;
951                 } else {
952                         snd_assert(0);
953                 }
954 #else
955                 substream->ops = &snd_cs46xx_playback_ops;
956 #endif
957
958         } else {
959                 if (runtime->dma_area == cpcm->hw_buf.area) {
960                         runtime->dma_area = NULL;
961                         runtime->dma_addr = 0;
962                         runtime->dma_bytes = 0;
963                 }
964                 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0) {
965 #ifdef CONFIG_SND_CS46XX_NEW_DSP
966                         up (&chip->spos_mutex);
967 #endif
968                         return err;
969                 }
970
971 #ifdef CONFIG_SND_CS46XX_NEW_DSP
972                 if (cpcm->pcm_channel_id == DSP_PCM_MAIN_CHANNEL) {
973                         substream->ops = &snd_cs46xx_playback_indirect_ops;
974                 } else if (cpcm->pcm_channel_id == DSP_PCM_REAR_CHANNEL) {
975                         substream->ops = &snd_cs46xx_playback_indirect_rear_ops;
976                 } else if (cpcm->pcm_channel_id == DSP_PCM_CENTER_LFE_CHANNEL) {
977                         substream->ops = &snd_cs46xx_playback_indirect_clfe_ops;
978                 } else if (cpcm->pcm_channel_id == DSP_IEC958_CHANNEL) {
979                         substream->ops = &snd_cs46xx_playback_indirect_iec958_ops;
980                 } else {
981                         snd_assert(0);
982                 }
983 #else
984                 substream->ops = &snd_cs46xx_playback_indirect_ops;
985 #endif
986
987         }
988
989 #ifdef CONFIG_SND_CS46XX_NEW_DSP
990         up (&chip->spos_mutex);
991 #endif
992
993         return 0;
994 }
995
996 static int snd_cs46xx_playback_hw_free(snd_pcm_substream_t * substream)
997 {
998         /*cs46xx_t *chip = snd_pcm_substream_chip(substream);*/
999         snd_pcm_runtime_t *runtime = substream->runtime;
1000         cs46xx_pcm_t *cpcm;
1001
1002         cpcm = runtime->private_data;
1003
1004         /* if play_back open fails, then this function
1005            is called and cpcm can actually be NULL here */
1006         if (!cpcm) return -ENXIO;
1007
1008         if (runtime->dma_area != cpcm->hw_buf.area)
1009                 snd_pcm_lib_free_pages(substream);
1010     
1011         runtime->dma_area = NULL;
1012         runtime->dma_addr = 0;
1013         runtime->dma_bytes = 0;
1014
1015         return 0;
1016 }
1017
1018 static int snd_cs46xx_playback_prepare(snd_pcm_substream_t * substream)
1019 {
1020         unsigned int tmp;
1021         unsigned int pfie;
1022         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1023         snd_pcm_runtime_t *runtime = substream->runtime;
1024         cs46xx_pcm_t *cpcm;
1025
1026         cpcm = runtime->private_data;
1027
1028 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1029     snd_assert (cpcm->pcm_channel != NULL, return -ENXIO);
1030
1031         pfie = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2 );
1032         pfie &= ~0x0000f03f;
1033 #else
1034         /* old dsp */
1035         pfie = snd_cs46xx_peek(chip, BA1_PFIE);
1036         pfie &= ~0x0000f03f;
1037 #endif
1038
1039         cpcm->shift = 2;
1040         /* if to convert from stereo to mono */
1041         if (runtime->channels == 1) {
1042                 cpcm->shift--;
1043                 pfie |= 0x00002000;
1044         }
1045         /* if to convert from 8 bit to 16 bit */
1046         if (snd_pcm_format_width(runtime->format) == 8) {
1047                 cpcm->shift--;
1048                 pfie |= 0x00001000;
1049         }
1050         /* if to convert to unsigned */
1051         if (snd_pcm_format_unsigned(runtime->format))
1052                 pfie |= 0x00008000;
1053
1054         /* Never convert byte order when sample stream is 8 bit */
1055         if (snd_pcm_format_width(runtime->format) != 8) {
1056                 /* convert from big endian to little endian */
1057                 if (snd_pcm_format_big_endian(runtime->format))
1058                         pfie |= 0x00004000;
1059         }
1060         
1061         memset(&cpcm->pcm_rec, 0, sizeof(cpcm->pcm_rec));
1062         cpcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
1063         cpcm->pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << cpcm->shift;
1064
1065 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1066
1067         tmp = snd_cs46xx_peek(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2);
1068         tmp &= ~0x000003ff;
1069         tmp |= (4 << cpcm->shift) - 1;
1070         /* playback transaction count register */
1071         snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address) << 2, tmp);
1072
1073         /* playback format && interrupt enable */
1074         snd_cs46xx_poke(chip, (cpcm->pcm_channel->pcm_reader_scb->address + 1) << 2, pfie | cpcm->pcm_channel->pcm_slot);
1075 #else
1076         snd_cs46xx_poke(chip, BA1_PBA, cpcm->hw_buf.addr);
1077         tmp = snd_cs46xx_peek(chip, BA1_PDTC);
1078         tmp &= ~0x000003ff;
1079         tmp |= (4 << cpcm->shift) - 1;
1080         snd_cs46xx_poke(chip, BA1_PDTC, tmp);
1081         snd_cs46xx_poke(chip, BA1_PFIE, pfie);
1082         snd_cs46xx_set_play_sample_rate(chip, runtime->rate);
1083 #endif
1084
1085         return 0;
1086 }
1087
1088 static int snd_cs46xx_capture_hw_params(snd_pcm_substream_t * substream,
1089                                         snd_pcm_hw_params_t * hw_params)
1090 {
1091         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1092         snd_pcm_runtime_t *runtime = substream->runtime;
1093         int err;
1094
1095 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1096         cs46xx_dsp_pcm_ostream_set_period (chip, params_period_bytes(hw_params));
1097 #endif
1098         if (runtime->periods == CS46XX_FRAGS) {
1099                 if (runtime->dma_area != chip->capt.hw_buf.area)
1100                         snd_pcm_lib_free_pages(substream);
1101                 runtime->dma_area = chip->capt.hw_buf.area;
1102                 runtime->dma_addr = chip->capt.hw_buf.addr;
1103                 runtime->dma_bytes = chip->capt.hw_buf.bytes;
1104                 substream->ops = &snd_cs46xx_capture_ops;
1105         } else {
1106                 if (runtime->dma_area == chip->capt.hw_buf.area) {
1107                         runtime->dma_area = NULL;
1108                         runtime->dma_addr = 0;
1109                         runtime->dma_bytes = 0;
1110                 }
1111                 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
1112                         return err;
1113                 substream->ops = &snd_cs46xx_capture_indirect_ops;
1114         }
1115
1116         return 0;
1117 }
1118
1119 static int snd_cs46xx_capture_hw_free(snd_pcm_substream_t * substream)
1120 {
1121         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1122         snd_pcm_runtime_t *runtime = substream->runtime;
1123
1124         if (runtime->dma_area != chip->capt.hw_buf.area)
1125                 snd_pcm_lib_free_pages(substream);
1126         runtime->dma_area = NULL;
1127         runtime->dma_addr = 0;
1128         runtime->dma_bytes = 0;
1129
1130         return 0;
1131 }
1132
1133 static int snd_cs46xx_capture_prepare(snd_pcm_substream_t * substream)
1134 {
1135         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1136         snd_pcm_runtime_t *runtime = substream->runtime;
1137
1138         snd_cs46xx_poke(chip, BA1_CBA, chip->capt.hw_buf.addr);
1139         chip->capt.shift = 2;
1140         memset(&chip->capt.pcm_rec, 0, sizeof(chip->capt.pcm_rec));
1141         chip->capt.pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
1142         chip->capt.pcm_rec.hw_buffer_size = runtime->period_size * CS46XX_FRAGS << 2;
1143         snd_cs46xx_set_capture_sample_rate(chip, runtime->rate);
1144
1145         return 0;
1146 }
1147
1148 static irqreturn_t snd_cs46xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1149 {
1150         cs46xx_t *chip = dev_id;
1151         u32 status1;
1152 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1153         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
1154         u32 status2;
1155         int i;
1156         cs46xx_pcm_t *cpcm = NULL;
1157 #endif
1158
1159         /*
1160          *  Read the Interrupt Status Register to clear the interrupt
1161          */
1162         status1 = snd_cs46xx_peekBA0(chip, BA0_HISR);
1163         if ((status1 & 0x7fffffff) == 0) {
1164                 snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
1165                 return IRQ_NONE;
1166         }
1167
1168 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1169         status2 = snd_cs46xx_peekBA0(chip, BA0_HSR0);
1170
1171         for (i = 0; i < DSP_MAX_PCM_CHANNELS; ++i) {
1172                 if (i <= 15) {
1173                         if ( status1 & (1 << i) ) {
1174                                 if (i == CS46XX_DSP_CAPTURE_CHANNEL) {
1175                                         if (chip->capt.substream)
1176                                                 snd_pcm_period_elapsed(chip->capt.substream);
1177                                 } else {
1178                                         if (ins->pcm_channels[i].active &&
1179                                             ins->pcm_channels[i].private_data &&
1180                                             !ins->pcm_channels[i].unlinked) {
1181                                                 cpcm = ins->pcm_channels[i].private_data;
1182                                                 snd_pcm_period_elapsed(cpcm->substream);
1183                                         }
1184                                 }
1185                         }
1186                 } else {
1187                         if ( status2 & (1 << (i - 16))) {
1188                                 if (ins->pcm_channels[i].active && 
1189                                     ins->pcm_channels[i].private_data &&
1190                                     !ins->pcm_channels[i].unlinked) {
1191                                         cpcm = ins->pcm_channels[i].private_data;
1192                                         snd_pcm_period_elapsed(cpcm->substream);
1193                                 }
1194                         }
1195                 }
1196         }
1197
1198 #else
1199         /* old dsp */
1200         if ((status1 & HISR_VC0) && chip->playback_pcm) {
1201                 if (chip->playback_pcm->substream)
1202                         snd_pcm_period_elapsed(chip->playback_pcm->substream);
1203         }
1204         if ((status1 & HISR_VC1) && chip->pcm) {
1205                 if (chip->capt.substream)
1206                         snd_pcm_period_elapsed(chip->capt.substream);
1207         }
1208 #endif
1209
1210         if ((status1 & HISR_MIDI) && chip->rmidi) {
1211                 unsigned char c;
1212                 
1213                 spin_lock(&chip->reg_lock);
1214                 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_RBE) == 0) {
1215                         c = snd_cs46xx_peekBA0(chip, BA0_MIDRP);
1216                         if ((chip->midcr & MIDCR_RIE) == 0)
1217                                 continue;
1218                         spin_unlock(&chip->reg_lock);
1219                         snd_rawmidi_receive(chip->midi_input, &c, 1);
1220                         spin_lock(&chip->reg_lock);
1221                 }
1222                 while ((snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
1223                         if ((chip->midcr & MIDCR_TIE) == 0)
1224                                 break;
1225                         if (snd_rawmidi_transmit(chip->midi_output, &c, 1) != 1) {
1226                                 chip->midcr &= ~MIDCR_TIE;
1227                                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
1228                                 break;
1229                         }
1230                         snd_cs46xx_pokeBA0(chip, BA0_MIDWP, c);
1231                 }
1232                 spin_unlock(&chip->reg_lock);
1233         }
1234         /*
1235          *  EOI to the PCI part....reenables interrupts
1236          */
1237         snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_CHGM | HICR_IEV);
1238
1239         return IRQ_HANDLED;
1240 }
1241
1242 static snd_pcm_hardware_t snd_cs46xx_playback =
1243 {
1244         .info =                 (SNDRV_PCM_INFO_MMAP |
1245                                  SNDRV_PCM_INFO_INTERLEAVED | 
1246                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1247                                  SNDRV_PCM_INFO_RESUME),
1248         .formats =              (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 |
1249                                  SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
1250                                  SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE),
1251         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1252         .rate_min =             5500,
1253         .rate_max =             48000,
1254         .channels_min =         1,
1255         .channels_max =         2,
1256         .buffer_bytes_max =     (256 * 1024),
1257         .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
1258         .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
1259         .periods_min =          CS46XX_FRAGS,
1260         .periods_max =          1024,
1261         .fifo_size =            0,
1262 };
1263
1264 static snd_pcm_hardware_t snd_cs46xx_capture =
1265 {
1266         .info =                 (SNDRV_PCM_INFO_MMAP |
1267                                  SNDRV_PCM_INFO_INTERLEAVED |
1268                                  SNDRV_PCM_INFO_BLOCK_TRANSFER |
1269                                  SNDRV_PCM_INFO_RESUME),
1270         .formats =              SNDRV_PCM_FMTBIT_S16_LE,
1271         .rates =                SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
1272         .rate_min =             5500,
1273         .rate_max =             48000,
1274         .channels_min =         2,
1275         .channels_max =         2,
1276         .buffer_bytes_max =     (256 * 1024),
1277         .period_bytes_min =     CS46XX_MIN_PERIOD_SIZE,
1278         .period_bytes_max =     CS46XX_MAX_PERIOD_SIZE,
1279         .periods_min =          CS46XX_FRAGS,
1280         .periods_max =          1024,
1281         .fifo_size =            0,
1282 };
1283
1284 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1285
1286 static unsigned int period_sizes[] = { 32, 64, 128, 256, 512, 1024, 2048 };
1287
1288 static snd_pcm_hw_constraint_list_t hw_constraints_period_sizes = {
1289         .count = ARRAY_SIZE(period_sizes),
1290         .list = period_sizes,
1291         .mask = 0
1292 };
1293
1294 #endif
1295
1296 static void snd_cs46xx_pcm_free_substream(snd_pcm_runtime_t *runtime)
1297 {
1298         cs46xx_pcm_t * cpcm = runtime->private_data;
1299         kfree(cpcm);
1300 }
1301
1302 static int _cs46xx_playback_open_channel (snd_pcm_substream_t * substream,int pcm_channel_id)
1303 {
1304         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1305         cs46xx_pcm_t * cpcm;
1306         snd_pcm_runtime_t *runtime = substream->runtime;
1307
1308         cpcm = kcalloc(1, sizeof(*cpcm), GFP_KERNEL);
1309         if (cpcm == NULL)
1310                 return -ENOMEM;
1311         if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
1312                                 PAGE_SIZE, &cpcm->hw_buf) < 0) {
1313                 kfree(cpcm);
1314                 return -ENOMEM;
1315         }
1316
1317         runtime->hw = snd_cs46xx_playback;
1318         runtime->private_data = cpcm;
1319         runtime->private_free = snd_cs46xx_pcm_free_substream;
1320
1321         cpcm->substream = substream;
1322 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1323         down (&chip->spos_mutex);
1324         cpcm->pcm_channel = NULL; 
1325         cpcm->pcm_channel_id = pcm_channel_id;
1326
1327
1328         snd_pcm_hw_constraint_list(runtime, 0,
1329                                    SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
1330                                    &hw_constraints_period_sizes);
1331
1332         up (&chip->spos_mutex);
1333 #else
1334         chip->playback_pcm = cpcm; /* HACK */
1335 #endif
1336
1337         if (chip->accept_valid)
1338                 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
1339         chip->active_ctrl(chip, 1);
1340
1341         return 0;
1342 }
1343
1344 static int snd_cs46xx_playback_open(snd_pcm_substream_t * substream)
1345 {
1346         snd_printdd("open front channel\n");
1347         return _cs46xx_playback_open_channel(substream,DSP_PCM_MAIN_CHANNEL);
1348 }
1349
1350 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1351 static int snd_cs46xx_playback_open_rear(snd_pcm_substream_t * substream)
1352 {
1353         snd_printdd("open rear channel\n");
1354
1355         return _cs46xx_playback_open_channel(substream,DSP_PCM_REAR_CHANNEL);
1356 }
1357
1358 static int snd_cs46xx_playback_open_clfe(snd_pcm_substream_t * substream)
1359 {
1360         snd_printdd("open center - LFE channel\n");
1361
1362         return _cs46xx_playback_open_channel(substream,DSP_PCM_CENTER_LFE_CHANNEL);
1363 }
1364
1365 static int snd_cs46xx_playback_open_iec958(snd_pcm_substream_t * substream)
1366 {
1367         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1368
1369         snd_printdd("open raw iec958 channel\n");
1370
1371         down (&chip->spos_mutex);
1372         cs46xx_iec958_pre_open (chip);
1373         up (&chip->spos_mutex);
1374
1375         return _cs46xx_playback_open_channel(substream,DSP_IEC958_CHANNEL);
1376 }
1377
1378 static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream);
1379
1380 static int snd_cs46xx_playback_close_iec958(snd_pcm_substream_t * substream)
1381 {
1382         int err;
1383         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1384   
1385         snd_printdd("close raw iec958 channel\n");
1386
1387         err = snd_cs46xx_playback_close(substream);
1388
1389         down (&chip->spos_mutex);
1390         cs46xx_iec958_post_close (chip);
1391         up (&chip->spos_mutex);
1392
1393         return err;
1394 }
1395 #endif
1396
1397 static int snd_cs46xx_capture_open(snd_pcm_substream_t * substream)
1398 {
1399         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1400
1401         if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
1402                                 PAGE_SIZE, &chip->capt.hw_buf) < 0)
1403                 return -ENOMEM;
1404         chip->capt.substream = substream;
1405         substream->runtime->hw = snd_cs46xx_capture;
1406
1407         if (chip->accept_valid)
1408                 substream->runtime->hw.info |= SNDRV_PCM_INFO_MMAP_VALID;
1409
1410         chip->active_ctrl(chip, 1);
1411
1412 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1413         snd_pcm_hw_constraint_list(substream->runtime, 0,
1414                                    SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 
1415                                    &hw_constraints_period_sizes);
1416 #endif
1417         return 0;
1418 }
1419
1420 static int snd_cs46xx_playback_close(snd_pcm_substream_t * substream)
1421 {
1422         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1423         snd_pcm_runtime_t *runtime = substream->runtime;
1424         cs46xx_pcm_t * cpcm;
1425
1426         cpcm = runtime->private_data;
1427
1428         /* when playback_open fails, then cpcm can be NULL */
1429         if (!cpcm) return -ENXIO;
1430
1431 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1432         down (&chip->spos_mutex);
1433         if (cpcm->pcm_channel) {
1434                 cs46xx_dsp_destroy_pcm_channel(chip,cpcm->pcm_channel);
1435                 cpcm->pcm_channel = NULL;
1436         }
1437         up (&chip->spos_mutex);
1438 #else
1439         chip->playback_pcm = NULL;
1440 #endif
1441
1442         cpcm->substream = NULL;
1443         snd_dma_free_pages(&cpcm->hw_buf);
1444         chip->active_ctrl(chip, -1);
1445
1446         return 0;
1447 }
1448
1449 static int snd_cs46xx_capture_close(snd_pcm_substream_t * substream)
1450 {
1451         cs46xx_t *chip = snd_pcm_substream_chip(substream);
1452
1453         chip->capt.substream = NULL;
1454         snd_dma_free_pages(&chip->capt.hw_buf);
1455         chip->active_ctrl(chip, -1);
1456
1457         return 0;
1458 }
1459
1460 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1461 snd_pcm_ops_t snd_cs46xx_playback_rear_ops = {
1462         .open =                 snd_cs46xx_playback_open_rear,
1463         .close =                snd_cs46xx_playback_close,
1464         .ioctl =                snd_pcm_lib_ioctl,
1465         .hw_params =            snd_cs46xx_playback_hw_params,
1466         .hw_free =              snd_cs46xx_playback_hw_free,
1467         .prepare =              snd_cs46xx_playback_prepare,
1468         .trigger =              snd_cs46xx_playback_trigger,
1469         .pointer =              snd_cs46xx_playback_direct_pointer,
1470 };
1471
1472 snd_pcm_ops_t snd_cs46xx_playback_indirect_rear_ops = {
1473         .open =                 snd_cs46xx_playback_open_rear,
1474         .close =                snd_cs46xx_playback_close,
1475         .ioctl =                snd_pcm_lib_ioctl,
1476         .hw_params =            snd_cs46xx_playback_hw_params,
1477         .hw_free =              snd_cs46xx_playback_hw_free,
1478         .prepare =              snd_cs46xx_playback_prepare,
1479         .trigger =              snd_cs46xx_playback_trigger,
1480         .pointer =              snd_cs46xx_playback_indirect_pointer,
1481         .ack =                  snd_cs46xx_playback_transfer,
1482 };
1483
1484 snd_pcm_ops_t snd_cs46xx_playback_clfe_ops = {
1485         .open =                 snd_cs46xx_playback_open_clfe,
1486         .close =                snd_cs46xx_playback_close,
1487         .ioctl =                snd_pcm_lib_ioctl,
1488         .hw_params =            snd_cs46xx_playback_hw_params,
1489         .hw_free =              snd_cs46xx_playback_hw_free,
1490         .prepare =              snd_cs46xx_playback_prepare,
1491         .trigger =              snd_cs46xx_playback_trigger,
1492         .pointer =              snd_cs46xx_playback_direct_pointer,
1493 };
1494
1495 snd_pcm_ops_t snd_cs46xx_playback_indirect_clfe_ops = {
1496         .open =                 snd_cs46xx_playback_open_clfe,
1497         .close =                snd_cs46xx_playback_close,
1498         .ioctl =                snd_pcm_lib_ioctl,
1499         .hw_params =            snd_cs46xx_playback_hw_params,
1500         .hw_free =              snd_cs46xx_playback_hw_free,
1501         .prepare =              snd_cs46xx_playback_prepare,
1502         .trigger =              snd_cs46xx_playback_trigger,
1503         .pointer =              snd_cs46xx_playback_indirect_pointer,
1504         .ack =                  snd_cs46xx_playback_transfer,
1505 };
1506
1507 snd_pcm_ops_t snd_cs46xx_playback_iec958_ops = {
1508         .open =                 snd_cs46xx_playback_open_iec958,
1509         .close =                snd_cs46xx_playback_close_iec958,
1510         .ioctl =                snd_pcm_lib_ioctl,
1511         .hw_params =            snd_cs46xx_playback_hw_params,
1512         .hw_free =              snd_cs46xx_playback_hw_free,
1513         .prepare =              snd_cs46xx_playback_prepare,
1514         .trigger =              snd_cs46xx_playback_trigger,
1515         .pointer =              snd_cs46xx_playback_direct_pointer,
1516 };
1517
1518 snd_pcm_ops_t snd_cs46xx_playback_indirect_iec958_ops = {
1519         .open =                 snd_cs46xx_playback_open_iec958,
1520         .close =                snd_cs46xx_playback_close_iec958,
1521         .ioctl =                snd_pcm_lib_ioctl,
1522         .hw_params =            snd_cs46xx_playback_hw_params,
1523         .hw_free =              snd_cs46xx_playback_hw_free,
1524         .prepare =              snd_cs46xx_playback_prepare,
1525         .trigger =              snd_cs46xx_playback_trigger,
1526         .pointer =              snd_cs46xx_playback_indirect_pointer,
1527         .ack =                  snd_cs46xx_playback_transfer,
1528 };
1529
1530 #endif
1531
1532 snd_pcm_ops_t snd_cs46xx_playback_ops = {
1533         .open =                 snd_cs46xx_playback_open,
1534         .close =                snd_cs46xx_playback_close,
1535         .ioctl =                snd_pcm_lib_ioctl,
1536         .hw_params =            snd_cs46xx_playback_hw_params,
1537         .hw_free =              snd_cs46xx_playback_hw_free,
1538         .prepare =              snd_cs46xx_playback_prepare,
1539         .trigger =              snd_cs46xx_playback_trigger,
1540         .pointer =              snd_cs46xx_playback_direct_pointer,
1541 };
1542
1543 snd_pcm_ops_t snd_cs46xx_playback_indirect_ops = {
1544         .open =                 snd_cs46xx_playback_open,
1545         .close =                snd_cs46xx_playback_close,
1546         .ioctl =                snd_pcm_lib_ioctl,
1547         .hw_params =            snd_cs46xx_playback_hw_params,
1548         .hw_free =              snd_cs46xx_playback_hw_free,
1549         .prepare =              snd_cs46xx_playback_prepare,
1550         .trigger =              snd_cs46xx_playback_trigger,
1551         .pointer =              snd_cs46xx_playback_indirect_pointer,
1552         .ack =                  snd_cs46xx_playback_transfer,
1553 };
1554
1555 snd_pcm_ops_t snd_cs46xx_capture_ops = {
1556         .open =                 snd_cs46xx_capture_open,
1557         .close =                snd_cs46xx_capture_close,
1558         .ioctl =                snd_pcm_lib_ioctl,
1559         .hw_params =            snd_cs46xx_capture_hw_params,
1560         .hw_free =              snd_cs46xx_capture_hw_free,
1561         .prepare =              snd_cs46xx_capture_prepare,
1562         .trigger =              snd_cs46xx_capture_trigger,
1563         .pointer =              snd_cs46xx_capture_direct_pointer,
1564 };
1565
1566 snd_pcm_ops_t snd_cs46xx_capture_indirect_ops = {
1567         .open =                 snd_cs46xx_capture_open,
1568         .close =                snd_cs46xx_capture_close,
1569         .ioctl =                snd_pcm_lib_ioctl,
1570         .hw_params =            snd_cs46xx_capture_hw_params,
1571         .hw_free =              snd_cs46xx_capture_hw_free,
1572         .prepare =              snd_cs46xx_capture_prepare,
1573         .trigger =              snd_cs46xx_capture_trigger,
1574         .pointer =              snd_cs46xx_capture_indirect_pointer,
1575         .ack =                  snd_cs46xx_capture_transfer,
1576 };
1577
1578 static void snd_cs46xx_pcm_free(snd_pcm_t *pcm)
1579 {
1580         cs46xx_t *chip = pcm->private_data;
1581         chip->pcm = NULL;
1582         snd_pcm_lib_preallocate_free_for_all(pcm);
1583 }
1584
1585 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1586 static void snd_cs46xx_pcm_rear_free(snd_pcm_t *pcm)
1587 {
1588         cs46xx_t *chip = pcm->private_data;
1589         chip->pcm_rear = NULL;
1590         snd_pcm_lib_preallocate_free_for_all(pcm);
1591 }
1592
1593 static void snd_cs46xx_pcm_center_lfe_free(snd_pcm_t *pcm)
1594 {
1595         cs46xx_t *chip = pcm->private_data;
1596         chip->pcm_center_lfe = NULL;
1597         snd_pcm_lib_preallocate_free_for_all(pcm);
1598 }
1599
1600 static void snd_cs46xx_pcm_iec958_free(snd_pcm_t *pcm)
1601 {
1602         cs46xx_t *chip = pcm->private_data;
1603         chip->pcm_iec958 = NULL;
1604         snd_pcm_lib_preallocate_free_for_all(pcm);
1605 }
1606
1607 #define MAX_PLAYBACK_CHANNELS   (DSP_MAX_PCM_CHANNELS - 1)
1608 #else
1609 #define MAX_PLAYBACK_CHANNELS   1
1610 #endif
1611
1612 int __devinit snd_cs46xx_pcm(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
1613 {
1614         snd_pcm_t *pcm;
1615         int err;
1616
1617         if (rpcm)
1618                 *rpcm = NULL;
1619         if ((err = snd_pcm_new(chip->card, "CS46xx", device, MAX_PLAYBACK_CHANNELS, 1, &pcm)) < 0)
1620                 return err;
1621
1622         pcm->private_data = chip;
1623         pcm->private_free = snd_cs46xx_pcm_free;
1624
1625         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_ops);
1626         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs46xx_capture_ops);
1627
1628         /* global setup */
1629         pcm->info_flags = 0;
1630         strcpy(pcm->name, "CS46xx");
1631         chip->pcm = pcm;
1632
1633         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1634                                               snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1635
1636         if (rpcm)
1637                 *rpcm = pcm;
1638
1639         return 0;
1640 }
1641
1642
1643 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1644 int __devinit snd_cs46xx_pcm_rear(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
1645 {
1646         snd_pcm_t *pcm;
1647         int err;
1648
1649         if (rpcm)
1650                 *rpcm = NULL;
1651
1652         if ((err = snd_pcm_new(chip->card, "CS46xx - Rear", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
1653                 return err;
1654
1655         pcm->private_data = chip;
1656         pcm->private_free = snd_cs46xx_pcm_rear_free;
1657
1658         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_rear_ops);
1659
1660         /* global setup */
1661         pcm->info_flags = 0;
1662         strcpy(pcm->name, "CS46xx - Rear");
1663         chip->pcm_rear = pcm;
1664
1665         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1666                                               snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1667
1668         if (rpcm)
1669                 *rpcm = pcm;
1670
1671         return 0;
1672 }
1673
1674 int __devinit snd_cs46xx_pcm_center_lfe(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
1675 {
1676         snd_pcm_t *pcm;
1677         int err;
1678
1679         if (rpcm)
1680                 *rpcm = NULL;
1681
1682         if ((err = snd_pcm_new(chip->card, "CS46xx - Center LFE", device, MAX_PLAYBACK_CHANNELS, 0, &pcm)) < 0)
1683                 return err;
1684
1685         pcm->private_data = chip;
1686         pcm->private_free = snd_cs46xx_pcm_center_lfe_free;
1687
1688         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_clfe_ops);
1689
1690         /* global setup */
1691         pcm->info_flags = 0;
1692         strcpy(pcm->name, "CS46xx - Center LFE");
1693         chip->pcm_center_lfe = pcm;
1694
1695         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1696                                               snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1697
1698         if (rpcm)
1699                 *rpcm = pcm;
1700
1701         return 0;
1702 }
1703
1704 int __devinit snd_cs46xx_pcm_iec958(cs46xx_t *chip, int device, snd_pcm_t ** rpcm)
1705 {
1706         snd_pcm_t *pcm;
1707         int err;
1708
1709         if (rpcm)
1710                 *rpcm = NULL;
1711
1712         if ((err = snd_pcm_new(chip->card, "CS46xx - IEC958", device, 1, 0, &pcm)) < 0)
1713                 return err;
1714
1715         pcm->private_data = chip;
1716         pcm->private_free = snd_cs46xx_pcm_iec958_free;
1717
1718         snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs46xx_playback_iec958_ops);
1719
1720         /* global setup */
1721         pcm->info_flags = 0;
1722         strcpy(pcm->name, "CS46xx - IEC958");
1723         chip->pcm_rear = pcm;
1724
1725         snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1726                                               snd_dma_pci_data(chip->pci), 64*1024, 256*1024);
1727
1728         if (rpcm)
1729                 *rpcm = pcm;
1730
1731         return 0;
1732 }
1733 #endif
1734
1735 /*
1736  *  Mixer routines
1737  */
1738 static void snd_cs46xx_mixer_free_ac97_bus(ac97_bus_t *bus)
1739 {
1740         cs46xx_t *chip = bus->private_data;
1741
1742         chip->ac97_bus = NULL;
1743 }
1744
1745 static void snd_cs46xx_mixer_free_ac97(ac97_t *ac97)
1746 {
1747         cs46xx_t *chip = ac97->private_data;
1748
1749         snd_assert ((ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) ||
1750                     (ac97 == chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]),
1751                     return);
1752
1753         if (ac97 == chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]) {
1754                 chip->ac97[CS46XX_PRIMARY_CODEC_INDEX] = NULL;
1755                 chip->eapd_switch = NULL;
1756         }
1757         else
1758                 chip->ac97[CS46XX_SECONDARY_CODEC_INDEX] = NULL;
1759 }
1760
1761 static int snd_cs46xx_vol_info(snd_kcontrol_t *kcontrol, 
1762                                snd_ctl_elem_info_t *uinfo)
1763 {
1764         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1765         uinfo->count = 2;
1766         uinfo->value.integer.min = 0;
1767         uinfo->value.integer.max = 0x7fff;
1768         return 0;
1769 }
1770
1771 static int snd_cs46xx_vol_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1772 {
1773         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1774         int reg = kcontrol->private_value;
1775         unsigned int val = snd_cs46xx_peek(chip, reg);
1776         ucontrol->value.integer.value[0] = 0xffff - (val >> 16);
1777         ucontrol->value.integer.value[1] = 0xffff - (val & 0xffff);
1778         return 0;
1779 }
1780
1781 static int snd_cs46xx_vol_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1782 {
1783         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1784         int reg = kcontrol->private_value;
1785         unsigned int val = ((0xffff - ucontrol->value.integer.value[0]) << 16 | 
1786                             (0xffff - ucontrol->value.integer.value[1]));
1787         unsigned int old = snd_cs46xx_peek(chip, reg);
1788         int change = (old != val);
1789
1790         if (change) {
1791                 snd_cs46xx_poke(chip, reg, val);
1792         }
1793
1794         return change;
1795 }
1796
1797 #ifdef CONFIG_SND_CS46XX_NEW_DSP
1798
1799 static int snd_cs46xx_vol_dac_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1800 {
1801         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1802
1803         ucontrol->value.integer.value[0] = chip->dsp_spos_instance->dac_volume_left;
1804         ucontrol->value.integer.value[1] = chip->dsp_spos_instance->dac_volume_right;
1805
1806         return 0;
1807 }
1808
1809 static int snd_cs46xx_vol_dac_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1810 {
1811         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1812         int change = 0;
1813
1814         if (chip->dsp_spos_instance->dac_volume_right != ucontrol->value.integer.value[0] ||
1815             chip->dsp_spos_instance->dac_volume_left != ucontrol->value.integer.value[1]) {
1816                 cs46xx_dsp_set_dac_volume(chip,
1817                                           ucontrol->value.integer.value[0],
1818                                           ucontrol->value.integer.value[1]);
1819                 change = 1;
1820         }
1821
1822         return change;
1823 }
1824
1825 #if 0
1826 static int snd_cs46xx_vol_iec958_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1827 {
1828         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1829
1830         ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_input_volume_left;
1831         ucontrol->value.integer.value[1] = chip->dsp_spos_instance->spdif_input_volume_right;
1832         return 0;
1833 }
1834
1835 static int snd_cs46xx_vol_iec958_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1836 {
1837         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1838         int change = 0;
1839
1840         if (chip->dsp_spos_instance->spdif_input_volume_left  != ucontrol->value.integer.value[0] ||
1841             chip->dsp_spos_instance->spdif_input_volume_right!= ucontrol->value.integer.value[1]) {
1842                 cs46xx_dsp_set_iec958_volume (chip,
1843                                               ucontrol->value.integer.value[0],
1844                                               ucontrol->value.integer.value[1]);
1845                 change = 1;
1846         }
1847
1848         return change;
1849 }
1850 #endif
1851
1852 static int snd_mixer_boolean_info(snd_kcontrol_t *kcontrol, 
1853                                   snd_ctl_elem_info_t *uinfo)
1854 {
1855         uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1856         uinfo->count = 1;
1857         uinfo->value.integer.min = 0;
1858         uinfo->value.integer.max = 1;
1859         return 0;
1860 }
1861
1862 static int snd_cs46xx_iec958_get(snd_kcontrol_t *kcontrol, 
1863                                  snd_ctl_elem_value_t *ucontrol)
1864 {
1865         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1866         int reg = kcontrol->private_value;
1867
1868         if (reg == CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT)
1869                 ucontrol->value.integer.value[0] = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
1870         else
1871                 ucontrol->value.integer.value[0] = chip->dsp_spos_instance->spdif_status_in;
1872
1873         return 0;
1874 }
1875
1876 static int snd_cs46xx_iec958_put(snd_kcontrol_t *kcontrol, 
1877                                   snd_ctl_elem_value_t *ucontrol)
1878 {
1879         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1880         int change, res;
1881
1882         switch (kcontrol->private_value) {
1883         case CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT:
1884                 down (&chip->spos_mutex);
1885                 change = (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED);
1886                 if (ucontrol->value.integer.value[0] && !change) 
1887                         cs46xx_dsp_enable_spdif_out(chip);
1888                 else if (change && !ucontrol->value.integer.value[0])
1889                         cs46xx_dsp_disable_spdif_out(chip);
1890
1891                 res = (change != (chip->dsp_spos_instance->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED));
1892                 up (&chip->spos_mutex);
1893                 break;
1894         case CS46XX_MIXER_SPDIF_INPUT_ELEMENT:
1895                 change = chip->dsp_spos_instance->spdif_status_in;
1896                 if (ucontrol->value.integer.value[0] && !change) {
1897                         cs46xx_dsp_enable_spdif_in(chip);
1898                         /* restore volume */
1899                 }
1900                 else if (change && !ucontrol->value.integer.value[0])
1901                         cs46xx_dsp_disable_spdif_in(chip);
1902                 
1903                 res = (change != chip->dsp_spos_instance->spdif_status_in);
1904                 break;
1905         default:
1906                 res = -EINVAL;
1907                 snd_assert(0, (void)0);
1908         }
1909
1910         return res;
1911 }
1912
1913 static int snd_cs46xx_adc_capture_get(snd_kcontrol_t *kcontrol, 
1914                                       snd_ctl_elem_value_t *ucontrol)
1915 {
1916         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1917         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
1918
1919         if (ins->adc_input != NULL) 
1920                 ucontrol->value.integer.value[0] = 1;
1921         else 
1922                 ucontrol->value.integer.value[0] = 0;
1923         
1924         return 0;
1925 }
1926
1927 static int snd_cs46xx_adc_capture_put(snd_kcontrol_t *kcontrol, 
1928                                       snd_ctl_elem_value_t *ucontrol)
1929 {
1930         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1931         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
1932         int change = 0;
1933
1934         if (ucontrol->value.integer.value[0] && !ins->adc_input) {
1935                 cs46xx_dsp_enable_adc_capture(chip);
1936                 change = 1;
1937         } else  if (!ucontrol->value.integer.value[0] && ins->adc_input) {
1938                 cs46xx_dsp_disable_adc_capture(chip);
1939                 change = 1;
1940         }
1941         return change;
1942 }
1943
1944 static int snd_cs46xx_pcm_capture_get(snd_kcontrol_t *kcontrol, 
1945                                       snd_ctl_elem_value_t *ucontrol)
1946 {
1947         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1948         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
1949
1950         if (ins->pcm_input != NULL) 
1951                 ucontrol->value.integer.value[0] = 1;
1952         else 
1953                 ucontrol->value.integer.value[0] = 0;
1954
1955         return 0;
1956 }
1957
1958
1959 static int snd_cs46xx_pcm_capture_put(snd_kcontrol_t *kcontrol, 
1960                                       snd_ctl_elem_value_t *ucontrol)
1961 {
1962         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1963         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
1964         int change = 0;
1965
1966         if (ucontrol->value.integer.value[0] && !ins->pcm_input) {
1967                 cs46xx_dsp_enable_pcm_capture(chip);
1968                 change = 1;
1969         } else  if (!ucontrol->value.integer.value[0] && ins->pcm_input) {
1970                 cs46xx_dsp_disable_pcm_capture(chip);
1971                 change = 1;
1972         }
1973
1974         return change;
1975 }
1976
1977 static int snd_herc_spdif_select_get(snd_kcontrol_t *kcontrol, 
1978                                      snd_ctl_elem_value_t *ucontrol)
1979 {
1980         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1981
1982         int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
1983
1984         if (val1 & EGPIODR_GPOE0)
1985                 ucontrol->value.integer.value[0] = 1;
1986         else
1987                 ucontrol->value.integer.value[0] = 0;
1988
1989         return 0;
1990 }
1991
1992 /*
1993  *      Game Theatre XP card - EGPIO[0] is used to select SPDIF input optical or coaxial.
1994  */ 
1995 static int snd_herc_spdif_select_put(snd_kcontrol_t *kcontrol, 
1996                                        snd_ctl_elem_value_t *ucontrol)
1997 {
1998         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
1999         int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
2000         int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
2001
2002         if (ucontrol->value.integer.value[0]) {
2003                 /* optical is default */
2004                 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 
2005                                    EGPIODR_GPOE0 | val1);  /* enable EGPIO0 output */
2006                 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 
2007                                    EGPIOPTR_GPPT0 | val2); /* open-drain on output */
2008         } else {
2009                 /* coaxial */
2010                 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE0); /* disable */
2011                 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT0); /* disable */
2012         }
2013
2014         /* checking diff from the EGPIO direction register 
2015            should be enough */
2016         return (val1 != (int)snd_cs46xx_peekBA0(chip, BA0_EGPIODR));
2017 }
2018
2019
2020 static int snd_cs46xx_spdif_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
2021 {
2022         uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
2023         uinfo->count = 1;
2024         return 0;
2025 }
2026
2027 static int snd_cs46xx_spdif_default_get(snd_kcontrol_t * kcontrol,
2028                                         snd_ctl_elem_value_t * ucontrol)
2029 {
2030         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2031         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
2032
2033         down (&chip->spos_mutex);
2034         ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_default >> 24) & 0xff);
2035         ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_default >> 16) & 0xff);
2036         ucontrol->value.iec958.status[2] = 0;
2037         ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_default) & 0xff);
2038         up (&chip->spos_mutex);
2039
2040         return 0;
2041 }
2042
2043 static int snd_cs46xx_spdif_default_put(snd_kcontrol_t * kcontrol,
2044                                         snd_ctl_elem_value_t * ucontrol)
2045 {
2046         cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
2047         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
2048         unsigned int val;
2049         int change;
2050
2051         down (&chip->spos_mutex);
2052         val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
2053                 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[2]) << 16) |
2054                 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3]))  |
2055                 /* left and right validity bit */
2056                 (1 << 13) | (1 << 12);
2057
2058
2059         change = (unsigned int)ins->spdif_csuv_default != val;
2060         ins->spdif_csuv_default = val;
2061
2062         if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) )
2063                 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
2064
2065         up (&chip->spos_mutex);
2066
2067         return change;
2068 }
2069
2070 static int snd_cs46xx_spdif_mask_get(snd_kcontrol_t * kcontrol,
2071                                      snd_ctl_elem_value_t * ucontrol)
2072 {
2073         ucontrol->value.iec958.status[0] = 0xff;
2074         ucontrol->value.iec958.status[1] = 0xff;
2075         ucontrol->value.iec958.status[2] = 0x00;
2076         ucontrol->value.iec958.status[3] = 0xff;
2077         return 0;
2078 }
2079
2080 static int snd_cs46xx_spdif_stream_get(snd_kcontrol_t * kcontrol,
2081                                          snd_ctl_elem_value_t * ucontrol)
2082 {
2083         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2084         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
2085
2086         down (&chip->spos_mutex);
2087         ucontrol->value.iec958.status[0] = _wrap_all_bits((ins->spdif_csuv_stream >> 24) & 0xff);
2088         ucontrol->value.iec958.status[1] = _wrap_all_bits((ins->spdif_csuv_stream >> 16) & 0xff);
2089         ucontrol->value.iec958.status[2] = 0;
2090         ucontrol->value.iec958.status[3] = _wrap_all_bits((ins->spdif_csuv_stream) & 0xff);
2091         up (&chip->spos_mutex);
2092
2093         return 0;
2094 }
2095
2096 static int snd_cs46xx_spdif_stream_put(snd_kcontrol_t * kcontrol,
2097                                         snd_ctl_elem_value_t * ucontrol)
2098 {
2099         cs46xx_t * chip = snd_kcontrol_chip(kcontrol);
2100         dsp_spos_instance_t * ins = chip->dsp_spos_instance;
2101         unsigned int val;
2102         int change;
2103
2104         down (&chip->spos_mutex);
2105         val = ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[0]) << 24) |
2106                 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[1]) << 16) |
2107                 ((unsigned int)_wrap_all_bits(ucontrol->value.iec958.status[3])) |
2108                 /* left and right validity bit */
2109                 (1 << 13) | (1 << 12);
2110
2111
2112         change = ins->spdif_csuv_stream != val;
2113         ins->spdif_csuv_stream = val;
2114
2115         if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN )
2116                 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV,val);
2117
2118         up (&chip->spos_mutex);
2119
2120         return change;
2121 }
2122
2123 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
2124
2125
2126 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
2127 static int snd_cs46xx_egpio_select_info(snd_kcontrol_t *kcontrol, 
2128                                         snd_ctl_elem_info_t *uinfo)
2129 {
2130         uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
2131         uinfo->count = 1;
2132         uinfo->value.integer.min = 0;
2133         uinfo->value.integer.max = 8;
2134         return 0;
2135 }
2136
2137 static int snd_cs46xx_egpio_select_get(snd_kcontrol_t *kcontrol, 
2138                                        snd_ctl_elem_value_t *ucontrol)
2139 {
2140         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2141         ucontrol->value.integer.value[0] = chip->current_gpio;
2142
2143         return 0;
2144 }
2145
2146 static int snd_cs46xx_egpio_select_put(snd_kcontrol_t *kcontrol, 
2147                                        snd_ctl_elem_value_t *ucontrol)
2148 {
2149         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2150         int change = (chip->current_gpio != ucontrol->value.integer.value[0]);
2151         chip->current_gpio = ucontrol->value.integer.value[0];
2152
2153         return change;
2154 }
2155
2156
2157 static int snd_cs46xx_egpio_get(snd_kcontrol_t *kcontrol, 
2158                                        snd_ctl_elem_value_t *ucontrol)
2159 {
2160         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2161         int reg = kcontrol->private_value;
2162
2163         snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
2164         ucontrol->value.integer.value[0] = 
2165                 (snd_cs46xx_peekBA0(chip, reg) & (1 << chip->current_gpio)) ? 1 : 0;
2166   
2167         return 0;
2168 }
2169
2170 static int snd_cs46xx_egpio_put(snd_kcontrol_t *kcontrol, 
2171                                        snd_ctl_elem_value_t *ucontrol)
2172 {
2173         cs46xx_t *chip = snd_kcontrol_chip(kcontrol);
2174         int reg = kcontrol->private_value;
2175         int val = snd_cs46xx_peekBA0(chip, reg);
2176         int oldval = val;
2177         snd_printdd ("put: reg = %04x, gpio %02x\n",reg,chip->current_gpio);
2178
2179         if (ucontrol->value.integer.value[0])
2180                 val |= (1 << chip->current_gpio);
2181         else
2182                 val &= ~(1 << chip->current_gpio);
2183
2184         snd_cs46xx_pokeBA0(chip, reg,val);
2185         snd_printdd ("put: val %08x oldval %08x\n",val,oldval);
2186
2187         return (oldval != val);
2188 }
2189 #endif /* CONFIG_SND_CS46XX_DEBUG_GPIO */
2190
2191 static snd_kcontrol_new_t snd_cs46xx_controls[] __devinitdata = {
2192 {
2193         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2194         .name = "DAC Volume",
2195         .info = snd_cs46xx_vol_info,
2196 #ifndef CONFIG_SND_CS46XX_NEW_DSP
2197         .get = snd_cs46xx_vol_get,
2198         .put = snd_cs46xx_vol_put,
2199         .private_value = BA1_PVOL,
2200 #else
2201         .get = snd_cs46xx_vol_dac_get,
2202         .put = snd_cs46xx_vol_dac_put,
2203 #endif
2204 },
2205
2206 {
2207         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2208         .name = "ADC Volume",
2209         .info = snd_cs46xx_vol_info,
2210         .get = snd_cs46xx_vol_get,
2211         .put = snd_cs46xx_vol_put,
2212 #ifndef CONFIG_SND_CS46XX_NEW_DSP
2213         .private_value = BA1_CVOL,
2214 #else
2215         .private_value = (VARIDECIMATE_SCB_ADDR + 0xE) << 2,
2216 #endif
2217 },
2218 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2219 {
2220         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2221         .name = "ADC Capture Switch",
2222         .info = snd_mixer_boolean_info,
2223         .get = snd_cs46xx_adc_capture_get,
2224         .put = snd_cs46xx_adc_capture_put
2225 },
2226 {
2227         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2228         .name = "DAC Capture Switch",
2229         .info = snd_mixer_boolean_info,
2230         .get = snd_cs46xx_pcm_capture_get,
2231         .put = snd_cs46xx_pcm_capture_put
2232 },
2233 {
2234         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2235         .name = "IEC958 Output Switch",
2236         .info = snd_mixer_boolean_info,
2237         .get = snd_cs46xx_iec958_get,
2238         .put = snd_cs46xx_iec958_put,
2239         .private_value = CS46XX_MIXER_SPDIF_OUTPUT_ELEMENT,
2240 },
2241 {
2242         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2243         .name = "IEC958 Input Switch",
2244         .info = snd_mixer_boolean_info,
2245         .get = snd_cs46xx_iec958_get,
2246         .put = snd_cs46xx_iec958_put,
2247         .private_value = CS46XX_MIXER_SPDIF_INPUT_ELEMENT,
2248 },
2249 #if 0
2250 /* Input IEC958 volume does not work for the moment. (Benny) */
2251 {
2252         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2253         .name = "IEC958 Input Volume",
2254         .info = snd_cs46xx_vol_info,
2255         .get = snd_cs46xx_vol_iec958_get,
2256         .put = snd_cs46xx_vol_iec958_put,
2257         .private_value = (ASYNCRX_SCB_ADDR + 0xE) << 2,
2258 },
2259 #endif
2260 {
2261         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2262         .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
2263         .info =  snd_cs46xx_spdif_info,
2264         .get =   snd_cs46xx_spdif_default_get,
2265         .put =   snd_cs46xx_spdif_default_put,
2266 },
2267 {
2268         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2269         .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK),
2270         .info =  snd_cs46xx_spdif_info,
2271         .get =   snd_cs46xx_spdif_mask_get,
2272         .access = SNDRV_CTL_ELEM_ACCESS_READ
2273 },
2274 {
2275         .iface = SNDRV_CTL_ELEM_IFACE_PCM,
2276         .name =  SNDRV_CTL_NAME_IEC958("",PLAYBACK,PCM_STREAM),
2277         .info =  snd_cs46xx_spdif_info,
2278         .get =   snd_cs46xx_spdif_stream_get,
2279         .put =   snd_cs46xx_spdif_stream_put
2280 },
2281
2282 #endif
2283 #ifdef CONFIG_SND_CS46XX_DEBUG_GPIO
2284 {
2285         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2286         .name = "EGPIO select",
2287         .info = snd_cs46xx_egpio_select_info,
2288         .get = snd_cs46xx_egpio_select_get,
2289         .put = snd_cs46xx_egpio_select_put,
2290         .private_value = 0,
2291 },
2292 {
2293         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2294         .name = "EGPIO Input/Output",
2295         .info = snd_mixer_boolean_info,
2296         .get = snd_cs46xx_egpio_get,
2297         .put = snd_cs46xx_egpio_put,
2298         .private_value = BA0_EGPIODR,
2299 },
2300 {
2301         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2302         .name = "EGPIO CMOS/Open drain",
2303         .info = snd_mixer_boolean_info,
2304         .get = snd_cs46xx_egpio_get,
2305         .put = snd_cs46xx_egpio_put,
2306         .private_value = BA0_EGPIOPTR,
2307 },
2308 {
2309         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2310         .name = "EGPIO On/Off",
2311         .info = snd_mixer_boolean_info,
2312         .get = snd_cs46xx_egpio_get,
2313         .put = snd_cs46xx_egpio_put,
2314         .private_value = BA0_EGPIOSR,
2315 },
2316 #endif
2317 };
2318
2319 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2320 /* Only available on the Hercules Game Theater XP soundcard */
2321 static snd_kcontrol_new_t snd_hercules_controls[] __devinitdata = {
2322 {
2323         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2324         .name = "Optical/Coaxial SPDIF Input Switch",
2325         .info = snd_mixer_boolean_info,
2326         .get = snd_herc_spdif_select_get,
2327         .put = snd_herc_spdif_select_put,
2328 },
2329 };
2330
2331
2332 static void snd_cs46xx_codec_reset (ac97_t * ac97)
2333 {
2334         unsigned long end_time;
2335         int err;
2336         cs46xx_t * chip = ac97->private_data;
2337
2338         /* reset to defaults */
2339         snd_ac97_write(ac97, AC97_RESET, 0);    
2340
2341         /* set the desired CODEC mode */
2342         if (chip->nr_ac97_codecs == 0) {
2343                 snd_printdd("cs46xx: CODOEC1 mode %04x\n",0x0);
2344                 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x0);
2345         } else if (chip->nr_ac97_codecs == 1) {
2346                 snd_printdd("cs46xx: CODOEC2 mode %04x\n",0x3);
2347                 snd_cs46xx_ac97_write(ac97,AC97_CSR_ACMODE,0x3);
2348         } else {
2349                 snd_assert(0); /* should never happen ... */
2350         }
2351
2352         udelay(50);
2353
2354         /* it's necessary to wait awhile until registers are accessible after RESET */
2355         /* because the PCM or MASTER volume registers can be modified, */
2356         /* the REC_GAIN register is used for tests */
2357         end_time = jiffies + HZ;
2358         do {
2359                 unsigned short ext_mid;
2360     
2361                 /* use preliminary reads to settle the communication */
2362                 snd_ac97_read(ac97, AC97_RESET);
2363                 snd_ac97_read(ac97, AC97_VENDOR_ID1);
2364                 snd_ac97_read(ac97, AC97_VENDOR_ID2);
2365                 /* modem? */
2366                 ext_mid = snd_ac97_read(ac97, AC97_EXTENDED_MID);
2367                 if (ext_mid != 0xffff && (ext_mid & 1) != 0)
2368                         return;
2369
2370                 /* test if we can write to the record gain volume register */
2371                 snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x8a05);
2372                 if ((err = snd_ac97_read(ac97, AC97_REC_GAIN)) == 0x8a05)
2373                         return;
2374
2375                 set_current_state(TASK_UNINTERRUPTIBLE);
2376                 schedule_timeout(HZ/100);
2377         } while (time_after_eq(end_time, jiffies));
2378
2379         snd_printk("CS46xx secondary codec dont respond!\n");  
2380 }
2381 #endif
2382
2383 int __devinit snd_cs46xx_mixer(cs46xx_t *chip)
2384 {
2385         snd_card_t *card = chip->card;
2386         ac97_template_t ac97;
2387         snd_ctl_elem_id_t id;
2388         int err;
2389         unsigned int idx;
2390         static ac97_bus_ops_t ops = {
2391 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2392                 .reset = snd_cs46xx_codec_reset,
2393 #endif
2394                 .write = snd_cs46xx_ac97_write,
2395                 .read = snd_cs46xx_ac97_read,
2396         };
2397
2398         /* detect primary codec */
2399         chip->nr_ac97_codecs = 0;
2400         snd_printdd("snd_cs46xx: detecting primary codec\n");
2401         if ((err = snd_ac97_bus(card, 0, &ops, chip, &chip->ac97_bus)) < 0)
2402                 return err;
2403         chip->ac97_bus->private_free = snd_cs46xx_mixer_free_ac97_bus;
2404
2405         memset(&ac97, 0, sizeof(ac97));
2406         ac97.private_data = chip;
2407         ac97.private_free = snd_cs46xx_mixer_free_ac97;
2408
2409         snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
2410                                CS46XX_PRIMARY_CODEC_INDEX);
2411         for (idx = 0; idx < 100; ++idx) {
2412                 if (snd_cs46xx_codec_read(chip, AC97_MASTER,
2413                                           CS46XX_PRIMARY_CODEC_INDEX) == 0x8000)
2414                         goto _ok;
2415                 set_current_state(TASK_INTERRUPTIBLE);
2416                 schedule_timeout(HZ/100);
2417         }
2418         return -ENXIO;
2419
2420  _ok:
2421         if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_PRIMARY_CODEC_INDEX])) < 0)
2422                 return err;
2423         snd_printdd("snd_cs46xx: primary codec phase one\n");
2424         chip->nr_ac97_codecs = 1;
2425
2426 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2427         snd_printdd("snd_cs46xx: detecting seconadry codec\n");
2428         /* try detect a secondary codec */
2429         memset(&ac97, 0, sizeof(ac97));    
2430         ac97.private_data = chip;
2431         ac97.private_free = snd_cs46xx_mixer_free_ac97;
2432         ac97.num = CS46XX_SECONDARY_CODEC_INDEX;
2433
2434         snd_cs46xx_codec_write(chip, AC97_RESET, 0,
2435                                CS46XX_SECONDARY_CODEC_INDEX);
2436         udelay(10);
2437
2438         if (snd_cs46xx_codec_read(chip, AC97_RESET,
2439                                   CS46XX_SECONDARY_CODEC_INDEX) & 0x8000) {
2440                 snd_printdd("snd_cs46xx: seconadry codec not present\n");
2441                 goto _no_sec_codec;
2442         }
2443
2444         snd_cs46xx_codec_write(chip, AC97_MASTER, 0x8000,
2445                                CS46XX_SECONDARY_CODEC_INDEX);
2446         for (idx = 0; idx < 100; ++idx) {
2447                 if (snd_cs46xx_codec_read(chip, AC97_MASTER,
2448                                           CS46XX_SECONDARY_CODEC_INDEX) == 0x8000) {
2449                         goto _ok2;
2450                 }
2451                 set_current_state(TASK_INTERRUPTIBLE);
2452                 schedule_timeout(HZ/100);
2453         }
2454
2455  _no_sec_codec:
2456         snd_printdd("snd_cs46xx: secondary codec did not respond ...\n");
2457
2458         chip->nr_ac97_codecs = 1;
2459     
2460         /* well, one codec only ... */
2461         goto _end;
2462  _ok2:
2463         if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])) < 0)
2464                 return err;
2465         chip->nr_ac97_codecs = 2;
2466
2467  _end:
2468
2469 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
2470
2471         /* add cs4630 mixer controls */
2472         for (idx = 0; idx < ARRAY_SIZE(snd_cs46xx_controls); idx++) {
2473                 snd_kcontrol_t *kctl;
2474                 kctl = snd_ctl_new1(&snd_cs46xx_controls[idx], chip);
2475                 if ((err = snd_ctl_add(card, kctl)) < 0)
2476                         return err;
2477         }
2478
2479         /* get EAPD mixer switch (for voyetra hack) */
2480         memset(&id, 0, sizeof(id));
2481         id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2482         strcpy(id.name, "External Amplifier");
2483         chip->eapd_switch = snd_ctl_find_id(chip->card, &id);
2484     
2485 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2486         if (chip->nr_ac97_codecs == 1 && 
2487             (snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
2488                                   CS46XX_PRIMARY_CODEC_INDEX) == 0x592b ||
2489              snd_cs46xx_codec_read(chip, AC97_VENDOR_ID2,
2490                                    CS46XX_PRIMARY_CODEC_INDEX) == 0x592d)) {
2491                 /* set primary cs4294 codec into Extended Audio Mode */
2492                 snd_printdd("setting EAM bit on cs4294 CODEC\n");
2493                 snd_cs46xx_codec_write(chip, AC97_CSR_ACMODE, 0x200,
2494                                        CS46XX_PRIMARY_CODEC_INDEX);
2495         }
2496         /* do soundcard specific mixer setup */
2497         if (chip->mixer_init) {
2498                 snd_printdd ("calling chip->mixer_init(chip);\n");
2499                 chip->mixer_init(chip);
2500         }
2501 #endif
2502
2503         /* turn on amplifier */
2504         chip->amplifier_ctrl(chip, 1);
2505     
2506         return 0;
2507 }
2508
2509 /*
2510  *  RawMIDI interface
2511  */
2512
2513 static void snd_cs46xx_midi_reset(cs46xx_t *chip)
2514 {
2515         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, MIDCR_MRST);
2516         udelay(100);
2517         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2518 }
2519
2520 static int snd_cs46xx_midi_input_open(snd_rawmidi_substream_t * substream)
2521 {
2522         cs46xx_t *chip = substream->rmidi->private_data;
2523
2524         chip->active_ctrl(chip, 1);
2525         spin_lock_irq(&chip->reg_lock);
2526         chip->uartm |= CS46XX_MODE_INPUT;
2527         chip->midcr |= MIDCR_RXE;
2528         chip->midi_input = substream;
2529         if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
2530                 snd_cs46xx_midi_reset(chip);
2531         } else {
2532                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2533         }
2534         spin_unlock_irq(&chip->reg_lock);
2535         return 0;
2536 }
2537
2538 static int snd_cs46xx_midi_input_close(snd_rawmidi_substream_t * substream)
2539 {
2540         cs46xx_t *chip = substream->rmidi->private_data;
2541
2542         spin_lock_irq(&chip->reg_lock);
2543         chip->midcr &= ~(MIDCR_RXE | MIDCR_RIE);
2544         chip->midi_input = NULL;
2545         if (!(chip->uartm & CS46XX_MODE_OUTPUT)) {
2546                 snd_cs46xx_midi_reset(chip);
2547         } else {
2548                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2549         }
2550         chip->uartm &= ~CS46XX_MODE_INPUT;
2551         spin_unlock_irq(&chip->reg_lock);
2552         chip->active_ctrl(chip, -1);
2553         return 0;
2554 }
2555
2556 static int snd_cs46xx_midi_output_open(snd_rawmidi_substream_t * substream)
2557 {
2558         cs46xx_t *chip = substream->rmidi->private_data;
2559
2560         chip->active_ctrl(chip, 1);
2561
2562         spin_lock_irq(&chip->reg_lock);
2563         chip->uartm |= CS46XX_MODE_OUTPUT;
2564         chip->midcr |= MIDCR_TXE;
2565         chip->midi_output = substream;
2566         if (!(chip->uartm & CS46XX_MODE_INPUT)) {
2567                 snd_cs46xx_midi_reset(chip);
2568         } else {
2569                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2570         }
2571         spin_unlock_irq(&chip->reg_lock);
2572         return 0;
2573 }
2574
2575 static int snd_cs46xx_midi_output_close(snd_rawmidi_substream_t * substream)
2576 {
2577         cs46xx_t *chip = substream->rmidi->private_data;
2578
2579         spin_lock_irq(&chip->reg_lock);
2580         chip->midcr &= ~(MIDCR_TXE | MIDCR_TIE);
2581         chip->midi_output = NULL;
2582         if (!(chip->uartm & CS46XX_MODE_INPUT)) {
2583                 snd_cs46xx_midi_reset(chip);
2584         } else {
2585                 snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2586         }
2587         chip->uartm &= ~CS46XX_MODE_OUTPUT;
2588         spin_unlock_irq(&chip->reg_lock);
2589         chip->active_ctrl(chip, -1);
2590         return 0;
2591 }
2592
2593 static void snd_cs46xx_midi_input_trigger(snd_rawmidi_substream_t * substream, int up)
2594 {
2595         unsigned long flags;
2596         cs46xx_t *chip = substream->rmidi->private_data;
2597
2598         spin_lock_irqsave(&chip->reg_lock, flags);
2599         if (up) {
2600                 if ((chip->midcr & MIDCR_RIE) == 0) {
2601                         chip->midcr |= MIDCR_RIE;
2602                         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2603                 }
2604         } else {
2605                 if (chip->midcr & MIDCR_RIE) {
2606                         chip->midcr &= ~MIDCR_RIE;
2607                         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2608                 }
2609         }
2610         spin_unlock_irqrestore(&chip->reg_lock, flags);
2611 }
2612
2613 static void snd_cs46xx_midi_output_trigger(snd_rawmidi_substream_t * substream, int up)
2614 {
2615         unsigned long flags;
2616         cs46xx_t *chip = substream->rmidi->private_data;
2617         unsigned char byte;
2618
2619         spin_lock_irqsave(&chip->reg_lock, flags);
2620         if (up) {
2621                 if ((chip->midcr & MIDCR_TIE) == 0) {
2622                         chip->midcr |= MIDCR_TIE;
2623                         /* fill UART FIFO buffer at first, and turn Tx interrupts only if necessary */
2624                         while ((chip->midcr & MIDCR_TIE) &&
2625                                (snd_cs46xx_peekBA0(chip, BA0_MIDSR) & MIDSR_TBF) == 0) {
2626                                 if (snd_rawmidi_transmit(substream, &byte, 1) != 1) {
2627                                         chip->midcr &= ~MIDCR_TIE;
2628                                 } else {
2629                                         snd_cs46xx_pokeBA0(chip, BA0_MIDWP, byte);
2630                                 }
2631                         }
2632                         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2633                 }
2634         } else {
2635                 if (chip->midcr & MIDCR_TIE) {
2636                         chip->midcr &= ~MIDCR_TIE;
2637                         snd_cs46xx_pokeBA0(chip, BA0_MIDCR, chip->midcr);
2638                 }
2639         }
2640         spin_unlock_irqrestore(&chip->reg_lock, flags);
2641 }
2642
2643 static snd_rawmidi_ops_t snd_cs46xx_midi_output =
2644 {
2645         .open =         snd_cs46xx_midi_output_open,
2646         .close =        snd_cs46xx_midi_output_close,
2647         .trigger =      snd_cs46xx_midi_output_trigger,
2648 };
2649
2650 static snd_rawmidi_ops_t snd_cs46xx_midi_input =
2651 {
2652         .open =         snd_cs46xx_midi_input_open,
2653         .close =        snd_cs46xx_midi_input_close,
2654         .trigger =      snd_cs46xx_midi_input_trigger,
2655 };
2656
2657 int __devinit snd_cs46xx_midi(cs46xx_t *chip, int device, snd_rawmidi_t **rrawmidi)
2658 {
2659         snd_rawmidi_t *rmidi;
2660         int err;
2661
2662         if (rrawmidi)
2663                 *rrawmidi = NULL;
2664         if ((err = snd_rawmidi_new(chip->card, "CS46XX", device, 1, 1, &rmidi)) < 0)
2665                 return err;
2666         strcpy(rmidi->name, "CS46XX");
2667         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_cs46xx_midi_output);
2668         snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_cs46xx_midi_input);
2669         rmidi->info_flags |= SNDRV_RAWMIDI_INFO_OUTPUT | SNDRV_RAWMIDI_INFO_INPUT | SNDRV_RAWMIDI_INFO_DUPLEX;
2670         rmidi->private_data = chip;
2671         chip->rmidi = rmidi;
2672         if (rrawmidi)
2673                 *rrawmidi = NULL;
2674         return 0;
2675 }
2676
2677
2678 /*
2679  * gameport interface
2680  */
2681
2682 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
2683
2684 typedef struct snd_cs46xx_gameport {
2685         struct gameport info;
2686         cs46xx_t *chip;
2687 } cs46xx_gameport_t;
2688
2689 static void snd_cs46xx_gameport_trigger(struct gameport *gameport)
2690 {
2691         cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
2692         cs46xx_t *chip;
2693         snd_assert(gp, return);
2694         chip = gp->chip;
2695         snd_cs46xx_pokeBA0(chip, BA0_JSPT, 0xFF);  //outb(gameport->io, 0xFF);
2696 }
2697
2698 static unsigned char snd_cs46xx_gameport_read(struct gameport *gameport)
2699 {
2700         cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
2701         cs46xx_t *chip;
2702         snd_assert(gp, return 0);
2703         chip = gp->chip;
2704         return snd_cs46xx_peekBA0(chip, BA0_JSPT); //inb(gameport->io);
2705 }
2706
2707 static int snd_cs46xx_gameport_cooked_read(struct gameport *gameport, int *axes, int *buttons)
2708 {
2709         cs46xx_gameport_t *gp = (cs46xx_gameport_t *)gameport;
2710         cs46xx_t *chip;
2711         unsigned js1, js2, jst;
2712         
2713         snd_assert(gp, return 0);
2714         chip = gp->chip;
2715
2716         js1 = snd_cs46xx_peekBA0(chip, BA0_JSC1);
2717         js2 = snd_cs46xx_peekBA0(chip, BA0_JSC2);
2718         jst = snd_cs46xx_peekBA0(chip, BA0_JSPT);
2719         
2720         *buttons = (~jst >> 4) & 0x0F; 
2721         
2722         axes[0] = ((js1 & JSC1_Y1V_MASK) >> JSC1_Y1V_SHIFT) & 0xFFFF;
2723         axes[1] = ((js1 & JSC1_X1V_MASK) >> JSC1_X1V_SHIFT) & 0xFFFF;
2724         axes[2] = ((js2 & JSC2_Y2V_MASK) >> JSC2_Y2V_SHIFT) & 0xFFFF;
2725         axes[3] = ((js2 & JSC2_X2V_MASK) >> JSC2_X2V_SHIFT) & 0xFFFF;
2726
2727         for(jst=0;jst<4;++jst)
2728                 if(axes[jst]==0xFFFF) axes[jst] = -1;
2729         return 0;
2730 }
2731
2732 static int snd_cs46xx_gameport_open(struct gameport *gameport, int mode)
2733 {
2734         switch (mode) {
2735         case GAMEPORT_MODE_COOKED:
2736                 return 0;
2737         case GAMEPORT_MODE_RAW:
2738                 return 0;
2739         default:
2740                 return -1;
2741         }
2742         return 0;
2743 }
2744
2745 void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
2746 {
2747         cs46xx_gameport_t *gp;
2748         gp = kmalloc(sizeof(*gp), GFP_KERNEL);
2749         if (! gp) {
2750                 snd_printk("cannot allocate gameport area\n");
2751                 return;
2752         }
2753         memset(gp, 0, sizeof(*gp));
2754         gp->info.open = snd_cs46xx_gameport_open;
2755         gp->info.read = snd_cs46xx_gameport_read;
2756         gp->info.trigger = snd_cs46xx_gameport_trigger;
2757         gp->info.cooked_read = snd_cs46xx_gameport_cooked_read;
2758         gp->chip = chip;
2759         chip->gameport = gp;
2760
2761         snd_cs46xx_pokeBA0(chip, BA0_JSIO, 0xFF); // ?
2762         snd_cs46xx_pokeBA0(chip, BA0_JSCTL, JSCTL_SP_MEDIUM_SLOW);
2763         gameport_register_port(&gp->info);
2764 }
2765
2766 #else
2767
2768 void __devinit snd_cs46xx_gameport(cs46xx_t *chip)
2769 {
2770 }
2771
2772 #endif /* CONFIG_GAMEPORT */
2773
2774 /*
2775  *  proc interface
2776  */
2777
2778 static long snd_cs46xx_io_read(snd_info_entry_t *entry, void *file_private_data,
2779                                struct file *file, char __user *buf,
2780                                unsigned long count, unsigned long pos)
2781 {
2782         long size;
2783         snd_cs46xx_region_t *region = (snd_cs46xx_region_t *)entry->private_data;
2784         
2785         size = count;
2786         if (pos + (size_t)size > region->size)
2787                 size = region->size - pos;
2788         if (size > 0) {
2789                 if (copy_to_user_fromio(buf, region->remap_addr + pos, size))
2790                         return -EFAULT;
2791         }
2792         return size;
2793 }
2794
2795 static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
2796         .read = snd_cs46xx_io_read,
2797 };
2798
2799 static int __devinit snd_cs46xx_proc_init(snd_card_t * card, cs46xx_t *chip)
2800 {
2801         snd_info_entry_t *entry;
2802         int idx;
2803         
2804         for (idx = 0; idx < 5; idx++) {
2805                 snd_cs46xx_region_t *region = &chip->region.idx[idx];
2806                 if (! snd_card_proc_new(card, region->name, &entry)) {
2807                         entry->content = SNDRV_INFO_CONTENT_DATA;
2808                         entry->private_data = chip;
2809                         entry->c.ops = &snd_cs46xx_proc_io_ops;
2810                         entry->size = region->size;
2811                         entry->mode = S_IFREG | S_IRUSR;
2812                 }
2813         }
2814 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2815         cs46xx_dsp_proc_init(card, chip);
2816 #endif
2817         return 0;
2818 }
2819
2820 static int snd_cs46xx_proc_done(cs46xx_t *chip)
2821 {
2822 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2823         cs46xx_dsp_proc_done(chip);
2824 #endif
2825         return 0;
2826 }
2827
2828 /*
2829  * stop the h/w
2830  */
2831 static void snd_cs46xx_hw_stop(cs46xx_t *chip)
2832 {
2833         unsigned int tmp;
2834
2835         tmp = snd_cs46xx_peek(chip, BA1_PFIE);
2836         tmp &= ~0x0000f03f;
2837         tmp |=  0x00000010;
2838         snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt disable */
2839
2840         tmp = snd_cs46xx_peek(chip, BA1_CIE);
2841         tmp &= ~0x0000003f;
2842         tmp |=  0x00000011;
2843         snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt disable */
2844
2845         /*
2846          *  Stop playback DMA.
2847          */
2848         tmp = snd_cs46xx_peek(chip, BA1_PCTL);
2849         snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
2850
2851         /*
2852          *  Stop capture DMA.
2853          */
2854         tmp = snd_cs46xx_peek(chip, BA1_CCTL);
2855         snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
2856
2857         /*
2858          *  Reset the processor.
2859          */
2860         snd_cs46xx_reset(chip);
2861
2862         snd_cs46xx_proc_stop(chip);
2863
2864         /*
2865          *  Power down the PLL.
2866          */
2867         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
2868
2869         /*
2870          *  Turn off the Processor by turning off the software clock enable flag in 
2871          *  the clock control register.
2872          */
2873         tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE;
2874         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
2875 }
2876
2877
2878 static int snd_cs46xx_free(cs46xx_t *chip)
2879 {
2880         int idx;
2881
2882         snd_assert(chip != NULL, return -EINVAL);
2883
2884         if (chip->active_ctrl)
2885                 chip->active_ctrl(chip, 1);
2886
2887 #if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
2888         if (chip->gameport) {
2889                 gameport_unregister_port(&chip->gameport->info);
2890                 kfree(chip->gameport);
2891         }
2892 #endif
2893
2894         if (chip->amplifier_ctrl)
2895                 chip->amplifier_ctrl(chip, -chip->amplifier); /* force to off */
2896         
2897         snd_cs46xx_proc_done(chip);
2898
2899         if (chip->region.idx[0].resource)
2900                 snd_cs46xx_hw_stop(chip);
2901
2902         for (idx = 0; idx < 5; idx++) {
2903                 snd_cs46xx_region_t *region = &chip->region.idx[idx];
2904                 if (region->remap_addr)
2905                         iounmap((void *) region->remap_addr);
2906                 if (region->resource) {
2907                         release_resource(region->resource);
2908                         kfree_nocheck(region->resource);
2909                 }
2910         }
2911         if (chip->irq >= 0)
2912                 free_irq(chip->irq, (void *)chip);
2913
2914         if (chip->active_ctrl)
2915                 chip->active_ctrl(chip, -chip->amplifier);
2916         
2917 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2918         if (chip->dsp_spos_instance) {
2919                 cs46xx_dsp_spos_destroy(chip);
2920                 chip->dsp_spos_instance = NULL;
2921         }
2922 #endif
2923         
2924         kfree(chip);
2925         return 0;
2926 }
2927
2928 static int snd_cs46xx_dev_free(snd_device_t *device)
2929 {
2930         cs46xx_t *chip = device->device_data;
2931         return snd_cs46xx_free(chip);
2932 }
2933
2934 /*
2935  *  initialize chip
2936  */
2937 static int snd_cs46xx_chip_init(cs46xx_t *chip)
2938 {
2939         int timeout;
2940
2941         /* 
2942          *  First, blast the clock control register to zero so that the PLL starts
2943          *  out in a known state, and blast the master serial port control register
2944          *  to zero so that the serial ports also start out in a known state.
2945          */
2946         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, 0);
2947         snd_cs46xx_pokeBA0(chip, BA0_SERMC1, 0);
2948
2949         /*
2950          *  If we are in AC97 mode, then we must set the part to a host controlled
2951          *  AC-link.  Otherwise, we won't be able to bring up the link.
2952          */        
2953 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2954         snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0 | 
2955                            SERACC_TWO_CODECS);  /* 2.00 dual codecs */
2956         /* snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_2_0); */ /* 2.00 codec */
2957 #else
2958         snd_cs46xx_pokeBA0(chip, BA0_SERACC, SERACC_HSP | SERACC_CHIP_TYPE_1_03); /* 1.03 codec */
2959 #endif
2960
2961         /*
2962          *  Drive the ARST# pin low for a minimum of 1uS (as defined in the AC97
2963          *  spec) and then drive it high.  This is done for non AC97 modes since
2964          *  there might be logic external to the CS461x that uses the ARST# line
2965          *  for a reset.
2966          */
2967         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, 0);
2968 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2969         snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, 0);
2970 #endif
2971         udelay(50);
2972         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_RSTN);
2973 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2974         snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_RSTN);
2975 #endif
2976     
2977         /*
2978          *  The first thing we do here is to enable sync generation.  As soon
2979          *  as we start receiving bit clock, we'll start producing the SYNC
2980          *  signal.
2981          */
2982         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_ESYN | ACCTL_RSTN);
2983 #ifdef CONFIG_SND_CS46XX_NEW_DSP
2984         snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_ESYN | ACCTL_RSTN);
2985 #endif
2986
2987         /*
2988          *  Now wait for a short while to allow the AC97 part to start
2989          *  generating bit clock (so we don't try to start the PLL without an
2990          *  input clock).
2991          */
2992         mdelay(10);
2993
2994         /*
2995          *  Set the serial port timing configuration, so that
2996          *  the clock control circuit gets its clock from the correct place.
2997          */
2998         snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97);
2999
3000         /*
3001          *  Write the selected clock control setup to the hardware.  Do not turn on
3002          *  SWCE yet (if requested), so that the devices clocked by the output of
3003          *  PLL are not clocked until the PLL is stable.
3004          */
3005         snd_cs46xx_pokeBA0(chip, BA0_PLLCC, PLLCC_LPF_1050_2780_KHZ | PLLCC_CDR_73_104_MHZ);
3006         snd_cs46xx_pokeBA0(chip, BA0_PLLM, 0x3a);
3007         snd_cs46xx_pokeBA0(chip, BA0_CLKCR2, CLKCR2_PDIVS_8);
3008
3009         /*
3010          *  Power up the PLL.
3011          */
3012         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP);
3013
3014         /*
3015          *  Wait until the PLL has stabilized.
3016          */
3017         set_current_state(TASK_UNINTERRUPTIBLE);
3018         schedule_timeout(HZ/10); /* 100ms */
3019
3020         /*
3021          *  Turn on clocking of the core so that we can setup the serial ports.
3022          */
3023         snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, CLKCR1_PLLP | CLKCR1_SWCE);
3024
3025         /*
3026          * Enable FIFO  Host Bypass
3027          */
3028         snd_cs46xx_pokeBA0(chip, BA0_SERBCF, SERBCF_HBP);
3029
3030         /*
3031          *  Fill the serial port FIFOs with silence.
3032          */
3033         snd_cs46xx_clear_serial_FIFOs(chip);
3034
3035         /*
3036          *  Set the serial port FIFO pointer to the first sample in the FIFO.
3037          */
3038         /* snd_cs46xx_pokeBA0(chip, BA0_SERBSP, 0); */
3039
3040         /*
3041          *  Write the serial port configuration to the part.  The master
3042          *  enable bit is not set until all other values have been written.
3043          */
3044         snd_cs46xx_pokeBA0(chip, BA0_SERC1, SERC1_SO1F_AC97 | SERC1_SO1EN);
3045         snd_cs46xx_pokeBA0(chip, BA0_SERC2, SERC2_SI1F_AC97 | SERC1_SO1EN);
3046         snd_cs46xx_pokeBA0(chip, BA0_SERMC1, SERMC1_PTC_AC97 | SERMC1_MSPE);
3047
3048
3049 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3050         snd_cs46xx_pokeBA0(chip, BA0_SERC7, SERC7_ASDI2EN);
3051         snd_cs46xx_pokeBA0(chip, BA0_SERC3, 0);
3052         snd_cs46xx_pokeBA0(chip, BA0_SERC4, 0);
3053         snd_cs46xx_pokeBA0(chip, BA0_SERC5, 0);
3054         snd_cs46xx_pokeBA0(chip, BA0_SERC6, 1);
3055 #endif
3056
3057         mdelay(5);
3058
3059
3060         /*
3061          * Wait for the codec ready signal from the AC97 codec.
3062          */
3063         timeout = 150;
3064         while (timeout-- > 0) {
3065                 /*
3066                  *  Read the AC97 status register to see if we've seen a CODEC READY
3067                  *  signal from the AC97 codec.
3068                  */
3069                 if (snd_cs46xx_peekBA0(chip, BA0_ACSTS) & ACSTS_CRDY)
3070                         goto ok1;
3071                 set_current_state(TASK_UNINTERRUPTIBLE);
3072                 schedule_timeout((HZ+99)/100);
3073         }
3074
3075
3076         snd_printk("create - never read codec ready from AC'97\n");
3077         snd_printk("it is not probably bug, try to use CS4236 driver\n");
3078         return -EIO;
3079  ok1:
3080 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3081         {
3082                 int count;
3083                 for (count = 0; count < 150; count++) {
3084                         /* First, we want to wait for a short time. */
3085                         udelay(25);
3086         
3087                         if (snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY)
3088                                 break;
3089                 }
3090
3091                 /*
3092                  *  Make sure CODEC is READY.
3093                  */
3094                 if (!(snd_cs46xx_peekBA0(chip, BA0_ACSTS2) & ACSTS_CRDY))
3095                         snd_printdd("cs46xx: never read card ready from secondary AC'97\n");
3096         }
3097 #endif
3098
3099         /*
3100          *  Assert the vaid frame signal so that we can start sending commands
3101          *  to the AC97 codec.
3102          */
3103         snd_cs46xx_pokeBA0(chip, BA0_ACCTL, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
3104 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3105         snd_cs46xx_pokeBA0(chip, BA0_ACCTL2, ACCTL_VFRM | ACCTL_ESYN | ACCTL_RSTN);
3106 #endif
3107
3108
3109         /*
3110          *  Wait until we've sampled input slots 3 and 4 as valid, meaning that
3111          *  the codec is pumping ADC data across the AC-link.
3112          */
3113         timeout = 150;
3114         while (timeout-- > 0) {
3115                 /*
3116                  *  Read the input slot valid register and see if input slots 3 and
3117                  *  4 are valid yet.
3118                  */
3119                 if ((snd_cs46xx_peekBA0(chip, BA0_ACISV) & (ACISV_ISV3 | ACISV_ISV4)) == (ACISV_ISV3 | ACISV_ISV4))
3120                         goto ok2;
3121                 set_current_state(TASK_UNINTERRUPTIBLE);
3122                 schedule_timeout((HZ+99)/100);
3123         }
3124
3125 #ifndef CONFIG_SND_CS46XX_NEW_DSP
3126         snd_printk("create - never read ISV3 & ISV4 from AC'97\n");
3127         return -EIO;
3128 #else
3129         /* This may happen on a cold boot with a Terratec SiXPack 5.1.
3130            Reloading the driver may help, if there's other soundcards 
3131            with the same problem I would like to know. (Benny) */
3132
3133         snd_printk("ERROR: snd-cs46xx: never read ISV3 & ISV4 from AC'97\n");
3134         snd_printk("       Try reloading the ALSA driver, if you find something\n");
3135         snd_printk("       broken or not working on your soundcard upon\n");
3136         snd_printk("       this message please report to alsa-devel@lists.sourceforge.net\n");
3137
3138         return -EIO;
3139 #endif
3140  ok2:
3141
3142         /*
3143          *  Now, assert valid frame and the slot 3 and 4 valid bits.  This will
3144          *  commense the transfer of digital audio data to the AC97 codec.
3145          */
3146
3147         snd_cs46xx_pokeBA0(chip, BA0_ACOSV, ACOSV_SLV3 | ACOSV_SLV4);
3148
3149
3150         /*
3151          *  Power down the DAC and ADC.  We will power them up (if) when we need
3152          *  them.
3153          */
3154         /* snd_cs46xx_pokeBA0(chip, BA0_AC97_POWERDOWN, 0x300); */
3155
3156         /*
3157          *  Turn off the Processor by turning off the software clock enable flag in 
3158          *  the clock control register.
3159          */
3160         /* tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1) & ~CLKCR1_SWCE; */
3161         /* snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp); */
3162
3163         return 0;
3164 }
3165
3166 /*
3167  *  start and load DSP 
3168  */
3169 int __devinit snd_cs46xx_start_dsp(cs46xx_t *chip)
3170 {       
3171         unsigned int tmp;
3172         /*
3173          *  Reset the processor.
3174          */
3175         snd_cs46xx_reset(chip);
3176         /*
3177          *  Download the image to the processor.
3178          */
3179 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3180 #if 0
3181         if (cs46xx_dsp_load_module(chip, &cwcemb80_module) < 0) {
3182                 snd_printk(KERN_ERR "image download error\n");
3183                 return -EIO;
3184         }
3185 #endif
3186
3187         if (cs46xx_dsp_load_module(chip, &cwc4630_module) < 0) {
3188                 snd_printk(KERN_ERR "image download error [cwc4630]\n");
3189                 return -EIO;
3190         }
3191
3192         if (cs46xx_dsp_load_module(chip, &cwcasync_module) < 0) {
3193                 snd_printk(KERN_ERR "image download error [cwcasync]\n");
3194                 return -EIO;
3195         }
3196
3197         if (cs46xx_dsp_load_module(chip, &cwcsnoop_module) < 0) {
3198                 snd_printk(KERN_ERR "image download error [cwcsnoop]\n");
3199                 return -EIO;
3200         }
3201
3202         if (cs46xx_dsp_load_module(chip, &cwcbinhack_module) < 0) {
3203                 snd_printk(KERN_ERR "image download error [cwcbinhack]\n");
3204                 return -EIO;
3205         }
3206
3207         if (cs46xx_dsp_load_module(chip, &cwcdma_module) < 0) {
3208                 snd_printk(KERN_ERR "image download error [cwcdma]\n");
3209                 return -EIO;
3210         }
3211
3212         if (cs46xx_dsp_scb_and_task_init(chip) < 0)
3213                 return -EIO;
3214 #else
3215         /* old image */
3216         if (snd_cs46xx_download_image(chip) < 0) {
3217                 snd_printk("image download error\n");
3218                 return -EIO;
3219         }
3220
3221         /*
3222          *  Stop playback DMA.
3223          */
3224         tmp = snd_cs46xx_peek(chip, BA1_PCTL);
3225         chip->play_ctl = tmp & 0xffff0000;
3226         snd_cs46xx_poke(chip, BA1_PCTL, tmp & 0x0000ffff);
3227 #endif
3228
3229         /*
3230          *  Stop capture DMA.
3231          */
3232         tmp = snd_cs46xx_peek(chip, BA1_CCTL);
3233         chip->capt.ctl = tmp & 0x0000ffff;
3234         snd_cs46xx_poke(chip, BA1_CCTL, tmp & 0xffff0000);
3235
3236         mdelay(5);
3237
3238         snd_cs46xx_set_play_sample_rate(chip, 8000);
3239         snd_cs46xx_set_capture_sample_rate(chip, 8000);
3240
3241         snd_cs46xx_proc_start(chip);
3242
3243         /*
3244          *  Enable interrupts on the part.
3245          */
3246         snd_cs46xx_pokeBA0(chip, BA0_HICR, HICR_IEV | HICR_CHGM);
3247         
3248         tmp = snd_cs46xx_peek(chip, BA1_PFIE);
3249         tmp &= ~0x0000f03f;
3250         snd_cs46xx_poke(chip, BA1_PFIE, tmp);   /* playback interrupt enable */
3251
3252         tmp = snd_cs46xx_peek(chip, BA1_CIE);
3253         tmp &= ~0x0000003f;
3254         tmp |=  0x00000001;
3255         snd_cs46xx_poke(chip, BA1_CIE, tmp);    /* capture interrupt enable */
3256         
3257 #ifndef CONFIG_SND_CS46XX_NEW_DSP
3258         /* set the attenuation to 0dB */ 
3259         snd_cs46xx_poke(chip, BA1_PVOL, 0x80008000);
3260         snd_cs46xx_poke(chip, BA1_CVOL, 0x80008000);
3261 #endif
3262
3263         return 0;
3264 }
3265
3266
3267 /*
3268  *      AMP control - null AMP
3269  */
3270  
3271 static void amp_none(cs46xx_t *chip, int change)
3272 {       
3273 }
3274
3275 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3276 static int voyetra_setup_eapd_slot(cs46xx_t *chip)
3277 {
3278         
3279         u32 idx, valid_slots,tmp,powerdown = 0;
3280         u16 modem_power,pin_config,logic_type;
3281
3282         snd_printdd ("cs46xx: cs46xx_setup_eapd_slot()+\n");
3283
3284         /*
3285          *  See if the devices are powered down.  If so, we must power them up first
3286          *  or they will not respond.
3287          */
3288         tmp = snd_cs46xx_peekBA0(chip, BA0_CLKCR1);
3289
3290         if (!(tmp & CLKCR1_SWCE)) {
3291                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp | CLKCR1_SWCE);
3292                 powerdown = 1;
3293         }
3294
3295         /*
3296          * Clear PRA.  The Bonzo chip will be used for GPIO not for modem
3297          * stuff.
3298          */
3299         if(chip->nr_ac97_codecs != 2) {
3300                 snd_printk (KERN_ERR "cs46xx: cs46xx_setup_eapd_slot() - no secondary codec configured\n");
3301                 return -EINVAL;
3302         }
3303
3304         modem_power = snd_cs46xx_codec_read (chip, 
3305                                              AC97_EXTENDED_MSTATUS,
3306                                              CS46XX_SECONDARY_CODEC_INDEX);
3307         modem_power &=0xFEFF;
3308
3309         snd_cs46xx_codec_write(chip, 
3310                                AC97_EXTENDED_MSTATUS, modem_power,
3311                                CS46XX_SECONDARY_CODEC_INDEX);
3312
3313         /*
3314          * Set GPIO pin's 7 and 8 so that they are configured for output.
3315          */
3316         pin_config = snd_cs46xx_codec_read (chip, 
3317                                             AC97_GPIO_CFG,
3318                                             CS46XX_SECONDARY_CODEC_INDEX);
3319         pin_config &=0x27F;
3320
3321         snd_cs46xx_codec_write(chip, 
3322                                AC97_GPIO_CFG, pin_config,
3323                                CS46XX_SECONDARY_CODEC_INDEX);
3324     
3325         /*
3326          * Set GPIO pin's 7 and 8 so that they are compatible with CMOS logic.
3327          */
3328
3329         logic_type = snd_cs46xx_codec_read(chip, AC97_GPIO_POLARITY,
3330                                            CS46XX_SECONDARY_CODEC_INDEX);
3331         logic_type &=0x27F; 
3332
3333         snd_cs46xx_codec_write (chip, AC97_GPIO_POLARITY, logic_type,
3334                                 CS46XX_SECONDARY_CODEC_INDEX);
3335
3336         valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV);
3337         valid_slots |= 0x200;
3338         snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots);
3339
3340         if ( cs46xx_wait_for_fifo(chip,1) ) {
3341           snd_printdd("FIFO is busy\n");
3342           
3343           return -EINVAL;
3344         }
3345
3346         /*
3347          * Fill slots 12 with the correct value for the GPIO pins. 
3348          */
3349         for(idx = 0x90; idx <= 0x9F; idx++) {
3350                 /*
3351                  * Initialize the fifo so that bits 7 and 8 are on.
3352                  *
3353                  * Remember that the GPIO pins in bonzo are shifted by 4 bits to
3354                  * the left.  0x1800 corresponds to bits 7 and 8.
3355                  */
3356                 snd_cs46xx_pokeBA0(chip, BA0_SERBWP, 0x1800);
3357
3358                 /*
3359                  * Wait for command to complete
3360                  */
3361                 if ( cs46xx_wait_for_fifo(chip,200) ) {
3362                         snd_printdd("failed waiting for FIFO at addr (%02X)\n",idx);
3363
3364                         return -EINVAL;
3365                 }
3366             
3367                 /*
3368                  * Write the serial port FIFO index.
3369                  */
3370                 snd_cs46xx_pokeBA0(chip, BA0_SERBAD, idx);
3371       
3372                 /*
3373                  * Tell the serial port to load the new value into the FIFO location.
3374                  */
3375                 snd_cs46xx_pokeBA0(chip, BA0_SERBCM, SERBCM_WRC);
3376         }
3377
3378         /* wait for last command to complete */
3379         cs46xx_wait_for_fifo(chip,200);
3380
3381         /*
3382          *  Now, if we powered up the devices, then power them back down again.
3383          *  This is kinda ugly, but should never happen.
3384          */
3385         if (powerdown)
3386                 snd_cs46xx_pokeBA0(chip, BA0_CLKCR1, tmp);
3387
3388         return 0;
3389 }
3390 #endif
3391
3392 /*
3393  *      Crystal EAPD mode
3394  */
3395  
3396 static void amp_voyetra(cs46xx_t *chip, int change)
3397 {
3398         /* Manage the EAPD bit on the Crystal 4297 
3399            and the Analog AD1885 */
3400            
3401 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3402         int old = chip->amplifier;
3403 #endif
3404         int oval, val;
3405         
3406         chip->amplifier += change;
3407         oval = snd_cs46xx_codec_read(chip, AC97_POWERDOWN,
3408                                      CS46XX_PRIMARY_CODEC_INDEX);
3409         val = oval;
3410         if (chip->amplifier) {
3411                 /* Turn the EAPD amp on */
3412                 val |= 0x8000;
3413         } else {
3414                 /* Turn the EAPD amp off */
3415                 val &= ~0x8000;
3416         }
3417         if (val != oval) {
3418                 snd_cs46xx_codec_write(chip, AC97_POWERDOWN, val,
3419                                        CS46XX_PRIMARY_CODEC_INDEX);
3420                 if (chip->eapd_switch)
3421                         snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
3422                                        &chip->eapd_switch->id);
3423         }
3424
3425 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3426         if (chip->amplifier && !old) {
3427                 voyetra_setup_eapd_slot(chip);
3428         }
3429 #endif
3430 }
3431
3432 static void hercules_init(cs46xx_t *chip) 
3433 {
3434         /* default: AMP off, and SPDIF input optical */
3435         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
3436         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
3437 }
3438
3439
3440 /*
3441  *      Game Theatre XP card - EGPIO[2] is used to enable the external amp.
3442  */ 
3443 static void amp_hercules(cs46xx_t *chip, int change)
3444 {
3445         int old = chip->amplifier;
3446         int val1 = snd_cs46xx_peekBA0(chip, BA0_EGPIODR);
3447         int val2 = snd_cs46xx_peekBA0(chip, BA0_EGPIOPTR);
3448
3449         chip->amplifier += change;
3450         if (chip->amplifier && !old) {
3451                 snd_printdd ("Hercules amplifier ON\n");
3452
3453                 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, 
3454                                    EGPIODR_GPOE2 | val1);     /* enable EGPIO2 output */
3455                 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, 
3456                                    EGPIOPTR_GPPT2 | val2);   /* open-drain on output */
3457         } else if (old && !chip->amplifier) {
3458                 snd_printdd ("Hercules amplifier OFF\n");
3459                 snd_cs46xx_pokeBA0(chip, BA0_EGPIODR,  val1 & ~EGPIODR_GPOE2); /* disable */
3460                 snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, val2 & ~EGPIOPTR_GPPT2); /* disable */
3461         }
3462 }
3463
3464 static void voyetra_mixer_init (cs46xx_t *chip)
3465 {
3466         snd_printdd ("initializing Voyetra mixer\n");
3467
3468         /* Enable SPDIF out */
3469         snd_cs46xx_pokeBA0(chip, BA0_EGPIODR, EGPIODR_GPOE0);
3470         snd_cs46xx_pokeBA0(chip, BA0_EGPIOPTR, EGPIODR_GPOE0);
3471 }
3472
3473 static void hercules_mixer_init (cs46xx_t *chip)
3474 {
3475 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3476         unsigned int idx;
3477         int err;
3478         snd_card_t *card = chip->card;
3479 #endif
3480
3481         /* set EGPIO to default */
3482         hercules_init(chip);
3483
3484         snd_printdd ("initializing Hercules mixer\n");
3485
3486 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3487         for (idx = 0 ; idx < ARRAY_SIZE(snd_hercules_controls); idx++) {
3488                 snd_kcontrol_t *kctl;
3489
3490                 kctl = snd_ctl_new1(&snd_hercules_controls[idx], chip);
3491                 if ((err = snd_ctl_add(card, kctl)) < 0) {
3492                         printk (KERN_ERR "cs46xx: failed to initialize Hercules mixer (%d)\n",err);
3493                         break;
3494                 }
3495         }
3496 #endif
3497 }
3498
3499
3500 #if 0
3501 /*
3502  *      Untested
3503  */
3504  
3505 static void amp_voyetra_4294(cs46xx_t *chip, int change)
3506 {
3507         chip->amplifier += change;
3508
3509         if (chip->amplifier) {
3510                 /* Switch the GPIO pins 7 and 8 to open drain */
3511                 snd_cs46xx_codec_write(chip, 0x4C,
3512                                        snd_cs46xx_codec_read(chip, 0x4C) & 0xFE7F);
3513                 snd_cs46xx_codec_write(chip, 0x4E,
3514                                        snd_cs46xx_codec_read(chip, 0x4E) | 0x0180);
3515                 /* Now wake the AMP (this might be backwards) */
3516                 snd_cs46xx_codec_write(chip, 0x54,
3517                                        snd_cs46xx_codec_read(chip, 0x54) & ~0x0180);
3518         } else {
3519                 snd_cs46xx_codec_write(chip, 0x54,
3520                                        snd_cs46xx_codec_read(chip, 0x54) | 0x0180);
3521         }
3522 }
3523 #endif
3524
3525
3526 /*
3527  * piix4 pci ids
3528  */
3529 #ifndef PCI_VENDOR_ID_INTEL
3530 #define PCI_VENDOR_ID_INTEL 0x8086
3531 #endif /* PCI_VENDOR_ID_INTEL */
3532
3533 #ifndef PCI_DEVICE_ID_INTEL_82371AB_3
3534 #define PCI_DEVICE_ID_INTEL_82371AB_3 0x7113
3535 #endif /* PCI_DEVICE_ID_INTEL_82371AB_3 */
3536
3537 /*
3538  *      Handle the CLKRUN on a thinkpad. We must disable CLKRUN support
3539  *      whenever we need to beat on the chip.
3540  *
3541  *      The original idea and code for this hack comes from David Kaiser at
3542  *      Linuxcare. Perhaps one day Crystal will document their chips well
3543  *      enough to make them useful.
3544  */
3545  
3546 static void clkrun_hack(cs46xx_t *chip, int change)
3547 {
3548         u16 control, nval;
3549         
3550         if (chip->acpi_dev == NULL)
3551                 return;
3552
3553         chip->amplifier += change;
3554         
3555         /* Read ACPI port */    
3556         nval = control = inw(chip->acpi_port + 0x10);
3557
3558         /* Flip CLKRUN off while running */
3559         if (! chip->amplifier)
3560                 nval |= 0x2000;
3561         else
3562                 nval &= ~0x2000;
3563         if (nval != control)
3564                 outw(nval, chip->acpi_port + 0x10);
3565 }
3566
3567         
3568 /*
3569  * detect intel piix4
3570  */
3571 static void clkrun_init(cs46xx_t *chip)
3572 {
3573         u8 pp;
3574
3575         chip->acpi_dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, NULL);
3576         if (chip->acpi_dev == NULL)
3577                 return;         /* Not a thinkpad thats for sure */
3578
3579         /* Find the control port */             
3580         pci_read_config_byte(chip->acpi_dev, 0x41, &pp);
3581         chip->acpi_port = pp << 8;
3582 }
3583
3584
3585 /*
3586  * Card subid table
3587  */
3588  
3589 struct cs_card_type
3590 {
3591         u16 vendor;
3592         u16 id;
3593         char *name;
3594         void (*init)(cs46xx_t *);
3595         void (*amp)(cs46xx_t *, int);
3596         void (*active)(cs46xx_t *, int);
3597         void (*mixer_init)(cs46xx_t *);
3598 };
3599
3600 static struct cs_card_type __devinitdata cards[] = {
3601         {
3602                 .vendor = 0x1489,
3603                 .id = 0x7001,
3604                 .name = "Genius Soundmaker 128 value",
3605                 /* nothing special */
3606         },
3607         {
3608                 .vendor = 0x5053,
3609                 .id = 0x3357,
3610                 .name = "Voyetra",
3611                 .amp = amp_voyetra,
3612                 .mixer_init = voyetra_mixer_init,
3613         },
3614         {
3615                 .vendor = 0x1071,
3616                 .id = 0x6003,
3617                 .name = "Mitac MI6020/21",
3618                 .amp = amp_voyetra,
3619         },
3620         {
3621                 .vendor = 0x14AF,
3622                 .id = 0x0050,
3623                 .name = "Hercules Game Theatre XP",
3624                 .amp = amp_hercules,
3625                 .mixer_init = hercules_mixer_init,
3626         },
3627         {
3628                 .vendor = 0x1681,
3629                 .id = 0x0050,
3630                 .name = "Hercules Game Theatre XP",
3631                 .amp = amp_hercules,
3632                 .mixer_init = hercules_mixer_init,
3633         },
3634         {
3635                 .vendor = 0x1681,
3636                 .id = 0x0051,
3637                 .name = "Hercules Game Theatre XP",
3638                 .amp = amp_hercules,
3639                 .mixer_init = hercules_mixer_init,
3640
3641         },
3642         {
3643                 .vendor = 0x1681,
3644                 .id = 0x0052,
3645                 .name = "Hercules Game Theatre XP",
3646                 .amp = amp_hercules,
3647                 .mixer_init = hercules_mixer_init,
3648         },
3649         {
3650                 .vendor = 0x1681,
3651                 .id = 0x0053,
3652                 .name = "Hercules Game Theatre XP",
3653                 .amp = amp_hercules,
3654                 .mixer_init = hercules_mixer_init,
3655         },
3656         {
3657                 .vendor = 0x1681,
3658                 .id = 0x0054,
3659                 .name = "Hercules Game Theatre XP",
3660                 .amp = amp_hercules,
3661                 .mixer_init = hercules_mixer_init,
3662         },
3663         /* Teratec */
3664         {
3665                 .vendor = 0x153b,
3666                 .id = 0x1136,
3667                 .name = "Terratec SiXPack 5.1",
3668         },
3669         /* Not sure if the 570 needs the clkrun hack */
3670         {
3671                 .vendor = PCI_VENDOR_ID_IBM,
3672                 .id = 0x0132,
3673                 .name = "Thinkpad 570",
3674                 .init = clkrun_init,
3675                 .active = clkrun_hack,
3676         },
3677         {
3678                 .vendor = PCI_VENDOR_ID_IBM,
3679                 .id = 0x0153,
3680                 .name = "Thinkpad 600X/A20/T20",
3681                 .init = clkrun_init,
3682                 .active = clkrun_hack,
3683         },
3684         {
3685                 .vendor = PCI_VENDOR_ID_IBM,
3686                 .id = 0x1010,
3687                 .name = "Thinkpad 600E (unsupported)",
3688         },
3689         {} /* terminator */
3690 };
3691
3692
3693 /*
3694  * APM support
3695  */
3696 #ifdef CONFIG_PM
3697 static int snd_cs46xx_suspend(snd_card_t *card, unsigned int state)
3698 {
3699         cs46xx_t *chip = card->pm_private_data;
3700         int amp_saved;
3701
3702         snd_pcm_suspend_all(chip->pcm);
3703         // chip->ac97_powerdown = snd_cs46xx_codec_read(chip, AC97_POWER_CONTROL);
3704         // chip->ac97_general_purpose = snd_cs46xx_codec_read(chip, BA0_AC97_GENERAL_PURPOSE);
3705
3706         snd_ac97_suspend(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
3707         if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
3708                 snd_ac97_suspend(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
3709
3710         amp_saved = chip->amplifier;
3711         /* turn off amp */
3712         chip->amplifier_ctrl(chip, -chip->amplifier);
3713         snd_cs46xx_hw_stop(chip);
3714         /* disable CLKRUN */
3715         chip->active_ctrl(chip, -chip->amplifier);
3716         chip->amplifier = amp_saved; /* restore the status */
3717         snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
3718         return 0;
3719 }
3720
3721 static int snd_cs46xx_resume(snd_card_t *card, unsigned int state)
3722 {
3723         cs46xx_t *chip = card->pm_private_data;
3724         int amp_saved;
3725
3726         pci_enable_device(chip->pci);
3727         amp_saved = chip->amplifier;
3728         chip->amplifier = 0;
3729         chip->active_ctrl(chip, 1); /* force to on */
3730
3731         snd_cs46xx_chip_init(chip);
3732
3733 #if 0
3734         snd_cs46xx_codec_write(chip, BA0_AC97_GENERAL_PURPOSE, 
3735                                chip->ac97_general_purpose);
3736         snd_cs46xx_codec_write(chip, AC97_POWER_CONTROL, 
3737                                chip->ac97_powerdown);
3738         mdelay(10);
3739         snd_cs46xx_codec_write(chip, BA0_AC97_POWERDOWN,
3740                                chip->ac97_powerdown);
3741         mdelay(5);
3742 #endif
3743
3744         snd_ac97_resume(chip->ac97[CS46XX_PRIMARY_CODEC_INDEX]);
3745         if (chip->ac97[CS46XX_SECONDARY_CODEC_INDEX])
3746                 snd_ac97_resume(chip->ac97[CS46XX_SECONDARY_CODEC_INDEX]);
3747
3748         if (amp_saved)
3749                 chip->amplifier_ctrl(chip, 1); /* turn amp on */
3750         else
3751                 chip->active_ctrl(chip, -1); /* disable CLKRUN */
3752         chip->amplifier = amp_saved;
3753         snd_power_change_state(card, SNDRV_CTL_POWER_D0);
3754         return 0;
3755 }
3756 #endif /* CONFIG_PM */
3757
3758
3759 /*
3760  */
3761
3762 int __devinit snd_cs46xx_create(snd_card_t * card,
3763                       struct pci_dev * pci,
3764                       int external_amp, int thinkpad,
3765                       cs46xx_t ** rchip)
3766 {
3767         cs46xx_t *chip;
3768         int err, idx;
3769         snd_cs46xx_region_t *region;
3770         struct cs_card_type *cp;
3771         u16 ss_card, ss_vendor;
3772         static snd_device_ops_t ops = {
3773                 .dev_free =     snd_cs46xx_dev_free,
3774         };
3775         
3776         *rchip = NULL;
3777
3778         /* enable PCI device */
3779         if ((err = pci_enable_device(pci)) < 0)
3780                 return err;
3781
3782         chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
3783         if (chip == NULL)
3784                 return -ENOMEM;
3785         spin_lock_init(&chip->reg_lock);
3786 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3787         init_MUTEX(&chip->spos_mutex);
3788 #endif
3789         chip->card = card;
3790         chip->pci = pci;
3791         chip->irq = -1;
3792         chip->ba0_addr = pci_resource_start(pci, 0);
3793         chip->ba1_addr = pci_resource_start(pci, 1);
3794         if (chip->ba0_addr == 0 || chip->ba0_addr == (unsigned long)~0 ||
3795             chip->ba1_addr == 0 || chip->ba1_addr == (unsigned long)~0) {
3796                 snd_printk("wrong address(es) - ba0 = 0x%lx, ba1 = 0x%lx\n", chip->ba0_addr, chip->ba1_addr);
3797                 snd_cs46xx_free(chip);
3798                 return -ENOMEM;
3799         }
3800
3801         region = &chip->region.name.ba0;
3802         strcpy(region->name, "CS46xx_BA0");
3803         region->base = chip->ba0_addr;
3804         region->size = CS46XX_BA0_SIZE;
3805
3806         region = &chip->region.name.data0;
3807         strcpy(region->name, "CS46xx_BA1_data0");
3808         region->base = chip->ba1_addr + BA1_SP_DMEM0;
3809         region->size = CS46XX_BA1_DATA0_SIZE;
3810
3811         region = &chip->region.name.data1;
3812         strcpy(region->name, "CS46xx_BA1_data1");
3813         region->base = chip->ba1_addr + BA1_SP_DMEM1;
3814         region->size = CS46XX_BA1_DATA1_SIZE;
3815
3816         region = &chip->region.name.pmem;
3817         strcpy(region->name, "CS46xx_BA1_pmem");
3818         region->base = chip->ba1_addr + BA1_SP_PMEM;
3819         region->size = CS46XX_BA1_PRG_SIZE;
3820
3821         region = &chip->region.name.reg;
3822         strcpy(region->name, "CS46xx_BA1_reg");
3823         region->base = chip->ba1_addr + BA1_SP_REG;
3824         region->size = CS46XX_BA1_REG_SIZE;
3825
3826         /* set up amp and clkrun hack */
3827         pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &ss_vendor);
3828         pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &ss_card);
3829
3830         for (cp = &cards[0]; cp->name; cp++) {
3831                 if (cp->vendor == ss_vendor && cp->id == ss_card) {
3832                         snd_printdd ("hack for %s enabled\n", cp->name);
3833
3834                         chip->amplifier_ctrl = cp->amp;
3835                         chip->active_ctrl = cp->active;
3836                         chip->mixer_init = cp->mixer_init;
3837
3838                         if (cp->init)
3839                                 cp->init(chip);
3840                         break;
3841                 }
3842         }
3843
3844         if (external_amp) {
3845                 snd_printk("Crystal EAPD support forced on.\n");
3846                 chip->amplifier_ctrl = amp_voyetra;
3847         }
3848
3849         if (thinkpad) {
3850                 snd_printk("Activating CLKRUN hack for Thinkpad.\n");
3851                 chip->active_ctrl = clkrun_hack;
3852                 clkrun_init(chip);
3853         }
3854         
3855         if (chip->amplifier_ctrl == NULL)
3856                 chip->amplifier_ctrl = amp_none;
3857         if (chip->active_ctrl == NULL)
3858                 chip->active_ctrl = amp_none;
3859
3860         chip->active_ctrl(chip, 1); /* enable CLKRUN */
3861
3862         pci_set_master(pci);
3863
3864         for (idx = 0; idx < 5; idx++) {
3865                 region = &chip->region.idx[idx];
3866                 if ((region->resource = request_mem_region(region->base, region->size, region->name)) == NULL) {
3867                         snd_printk("unable to request memory region 0x%lx-0x%lx\n", region->base, region->base + region->size - 1);
3868                         snd_cs46xx_free(chip);
3869                         return -EBUSY;
3870                 }
3871                 region->remap_addr = (unsigned long) ioremap_nocache(region->base, region->size);
3872                 if (region->remap_addr == 0) {
3873                         snd_printk("%s ioremap problem\n", region->name);
3874                         snd_cs46xx_free(chip);
3875                         return -ENOMEM;
3876                 }
3877         }
3878
3879         if (request_irq(pci->irq, snd_cs46xx_interrupt, SA_INTERRUPT|SA_SHIRQ, "CS46XX", (void *) chip)) {
3880                 snd_printk("unable to grab IRQ %d\n", pci->irq);
3881                 snd_cs46xx_free(chip);
3882                 return -EBUSY;
3883         }
3884         chip->irq = pci->irq;
3885
3886 #ifdef CONFIG_SND_CS46XX_NEW_DSP
3887         chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
3888         if (chip->dsp_spos_instance == NULL) {
3889                 snd_cs46xx_free(chip);
3890                 return -ENOMEM;
3891         }
3892 #endif
3893
3894         err = snd_cs46xx_chip_init(chip);
3895         if (err < 0) {
3896                 snd_cs46xx_free(chip);
3897                 return err;
3898         }
3899
3900         snd_cs46xx_proc_init(card, chip);
3901
3902         snd_card_set_pm_callback(card, snd_cs46xx_suspend, snd_cs46xx_resume, chip);
3903
3904         if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
3905                 snd_cs46xx_free(chip);
3906                 return err;
3907         }
3908         
3909         chip->active_ctrl(chip, -1); /* disable CLKRUN */
3910
3911         snd_card_set_dev(card, &pci->dev);
3912
3913         *rchip = chip;
3914         return 0;
3915 }