[ALSA] Remove xxx_t typedefs: USB-USX2Y
[linux-2.6] / sound / pci / cs46xx / dsp_spos_scb_lib.c
1 /*
2  *
3  *   This program is free software; you can redistribute it and/or modify
4  *   it under the terms of the GNU General Public License as published by
5  *   the Free Software Foundation; either version 2 of the License, or
6  *   (at your option) any later version.
7  *
8  *   This program is distributed in the hope that it will be useful,
9  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *   GNU General Public License for more details.
12  *
13  *   You should have received a copy of the GNU General Public License
14  *   along with this program; if not, write to the Free Software
15  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16  *
17  */
18
19 /*
20  * 2002-07 Benny Sjostrand benny@hostmobility.com
21  */
22
23
24 #include <sound/driver.h>
25 #include <asm/io.h>
26 #include <linux/delay.h>
27 #include <linux/pci.h>
28 #include <linux/pm.h>
29 #include <linux/init.h>
30 #include <linux/slab.h>
31 #include <sound/core.h>
32 #include <sound/control.h>
33 #include <sound/info.h>
34 #include <sound/cs46xx.h>
35
36 #include "cs46xx_lib.h"
37 #include "dsp_spos.h"
38
39 struct proc_scb_info {
40         struct dsp_scb_descriptor * scb_desc;
41         struct snd_cs46xx *chip;
42 };
43
44 static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol)
45 {
46         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
47         int symbol_index = (int)(symbol - ins->symbol_table.symbols);
48
49         snd_assert(ins->symbol_table.nsymbols > 0,return);
50         snd_assert(symbol_index >= 0 && symbol_index < ins->symbol_table.nsymbols, return);
51
52         ins->symbol_table.symbols[symbol_index].deleted = 1;
53
54         if (symbol_index < ins->symbol_table.highest_frag_index) {
55                 ins->symbol_table.highest_frag_index = symbol_index;
56         }
57   
58         if (symbol_index == ins->symbol_table.nsymbols - 1)
59                 ins->symbol_table.nsymbols --;
60
61         if (ins->symbol_table.highest_frag_index > ins->symbol_table.nsymbols) {
62                 ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols;
63         }
64
65 }
66
67 static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry,
68                                            struct snd_info_buffer *buffer)
69 {
70         struct proc_scb_info * scb_info  = entry->private_data;
71         struct dsp_scb_descriptor * scb = scb_info->scb_desc;
72         struct dsp_spos_instance * ins;
73         struct snd_cs46xx *chip = scb_info->chip;
74         int j,col;
75         void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
76
77         ins = chip->dsp_spos_instance;
78
79         down(&chip->spos_mutex);
80         snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name);
81
82         for (col = 0,j = 0;j < 0x10; j++,col++) {
83                 if (col == 4) {
84                         snd_iprintf(buffer,"\n");
85                         col = 0;
86                 }
87                 snd_iprintf(buffer,"%08x ",readl(dst + (scb->address + j) * sizeof(u32)));
88         }
89   
90         snd_iprintf(buffer,"\n");
91
92         if (scb->parent_scb_ptr != NULL) {
93                 snd_iprintf(buffer,"parent [%s:%04x] ", 
94                             scb->parent_scb_ptr->scb_name,
95                             scb->parent_scb_ptr->address);
96         } else snd_iprintf(buffer,"parent [none] ");
97   
98         snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x]  task_entry [%s:%04x]\n",
99                     scb->sub_list_ptr->scb_name,
100                     scb->sub_list_ptr->address,
101                     scb->next_scb_ptr->scb_name,
102                     scb->next_scb_ptr->address,
103                     scb->task_entry->symbol_name,
104                     scb->task_entry->address);
105
106         snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count);  
107         up(&chip->spos_mutex);
108 }
109
110 static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
111 {
112         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
113         unsigned long flags;
114
115         if ( scb->parent_scb_ptr ) {
116                 /* unlink parent SCB */
117                 snd_assert ((scb->parent_scb_ptr->sub_list_ptr == scb ||
118                              scb->parent_scb_ptr->next_scb_ptr == scb),return);
119   
120                 if (scb->parent_scb_ptr->sub_list_ptr == scb) {
121
122                         if (scb->next_scb_ptr == ins->the_null_scb) {
123                                 /* last and only node in parent sublist */
124                                 scb->parent_scb_ptr->sub_list_ptr = scb->sub_list_ptr;
125
126                                 if (scb->sub_list_ptr != ins->the_null_scb) {
127                                         scb->sub_list_ptr->parent_scb_ptr = scb->parent_scb_ptr;
128                                 }
129                                 scb->sub_list_ptr = ins->the_null_scb;
130                         } else {
131                                 /* first node in parent sublist */
132                                 scb->parent_scb_ptr->sub_list_ptr = scb->next_scb_ptr;
133
134                                 if (scb->next_scb_ptr != ins->the_null_scb) {
135                                         /* update next node parent ptr. */
136                                         scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;
137                                 }
138                                 scb->next_scb_ptr = ins->the_null_scb;
139                         }
140                 } else {
141                         /* snd_assert ( (scb->sub_list_ptr == ins->the_null_scb), return); */
142                         scb->parent_scb_ptr->next_scb_ptr = scb->next_scb_ptr;
143
144                         if (scb->next_scb_ptr != ins->the_null_scb) {
145                                 /* update next node parent ptr. */
146                                 scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;
147                         }
148                         scb->next_scb_ptr = ins->the_null_scb;
149                 }
150
151                 spin_lock_irqsave(&chip->reg_lock, flags);    
152
153                 /* update parent first entry in DSP RAM */
154                 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
155
156                 /* then update entry in DSP RAM */
157                 cs46xx_dsp_spos_update_scb(chip,scb);
158
159                 scb->parent_scb_ptr = NULL;
160                 spin_unlock_irqrestore(&chip->reg_lock, flags);
161         }
162 }
163
164 static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr,
165                                       int dword_count) 
166 {
167         void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
168         int i;
169   
170         for (i = 0; i < dword_count ; ++i ) {
171                 writel(0, dst);
172                 dst += 4;
173         }  
174 }
175
176 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
177 {
178         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
179
180         /* check integrety */
181         snd_assert ( (scb->index >= 0 && 
182                       scb->index < ins->nscb && 
183                       (ins->scbs + scb->index) == scb), return );
184
185 #if 0
186         /* can't remove a SCB with childs before 
187            removing childs first  */
188         snd_assert ( (scb->sub_list_ptr == ins->the_null_scb &&
189                       scb->next_scb_ptr == ins->the_null_scb),
190                      goto _end);
191 #endif
192
193         spin_lock(&scb->lock);
194         _dsp_unlink_scb (chip,scb);
195         spin_unlock(&scb->lock);
196
197         cs46xx_dsp_proc_free_scb_desc(scb);
198         snd_assert (scb->scb_symbol != NULL, return );
199         remove_symbol (chip,scb->scb_symbol);
200
201         ins->scbs[scb->index].deleted = 1;
202
203         if (scb->index < ins->scb_highest_frag_index)
204                 ins->scb_highest_frag_index = scb->index;
205
206         if (scb->index == ins->nscb - 1) {
207                 ins->nscb --;
208         }
209
210         if (ins->scb_highest_frag_index > ins->nscb) {
211                 ins->scb_highest_frag_index = ins->nscb;
212         }
213
214 #if 0
215         /* !!!! THIS IS A PIECE OF SHIT MADE BY ME !!! */
216         for(i = scb->index + 1;i < ins->nscb; ++i) {
217                 ins->scbs[i - 1].index = i - 1;
218         }
219 #endif
220 }
221
222
223 void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb)
224 {
225         if (scb->proc_info) {
226                 struct proc_scb_info * scb_info = scb->proc_info->private_data;
227
228                 snd_printdd("cs46xx_dsp_proc_free_scb_desc: freeing %s\n",scb->scb_name);
229
230                 snd_info_unregister(scb->proc_info);
231                 scb->proc_info = NULL;
232
233                 snd_assert (scb_info != NULL, return);
234                 kfree (scb_info);
235         }
236 }
237
238 void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
239                                         struct dsp_scb_descriptor * scb)
240 {
241         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
242         struct snd_info_entry * entry;
243         struct proc_scb_info * scb_info;
244
245         /* register to proc */
246         if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL &&
247             scb->proc_info == NULL) {
248   
249                 if ((entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name, 
250                                                         ins->proc_dsp_dir)) != NULL) {
251                         scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL);
252                         if (!scb_info) {
253                                 snd_info_free_entry(entry);
254                                 entry = NULL;
255                                 goto out;
256                         }
257
258                         scb_info->chip = chip;
259                         scb_info->scb_desc = scb;
260       
261                         entry->content = SNDRV_INFO_CONTENT_TEXT;
262                         entry->private_data = scb_info;
263                         entry->mode = S_IFREG | S_IRUGO | S_IWUSR;
264       
265                         entry->c.text.read_size = 512;
266                         entry->c.text.read = cs46xx_dsp_proc_scb_info_read;
267       
268                         if (snd_info_register(entry) < 0) {
269                                 snd_info_free_entry(entry);
270                                 kfree (scb_info);
271                                 entry = NULL;
272                         }
273                 }
274 out:
275                 scb->proc_info = entry;
276         }
277 }
278
279 static struct dsp_scb_descriptor * 
280 _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest,
281                          struct dsp_symbol_entry * task_entry,
282                          struct dsp_scb_descriptor * parent_scb,
283                          int scb_child_type)
284 {
285         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
286         struct dsp_scb_descriptor * scb;
287   
288         unsigned long flags;
289
290         snd_assert (ins->the_null_scb != NULL,return NULL);
291
292         /* fill the data that will be wroten to DSP */
293         scb_data[SCBsubListPtr] = 
294                 (ins->the_null_scb->address << 0x10) | ins->the_null_scb->address;
295
296         scb_data[SCBfuncEntryPtr] &= 0xFFFF0000;
297         scb_data[SCBfuncEntryPtr] |= task_entry->address;
298
299         snd_printdd("dsp_spos: creating SCB <%s>\n",name);
300
301         scb = cs46xx_dsp_create_scb(chip,name,scb_data,dest);
302
303
304         scb->sub_list_ptr = ins->the_null_scb;
305         scb->next_scb_ptr = ins->the_null_scb;
306
307         scb->parent_scb_ptr = parent_scb;
308         scb->task_entry = task_entry;
309
310   
311         /* update parent SCB */
312         if (scb->parent_scb_ptr) {
313 #if 0
314                 printk ("scb->parent_scb_ptr = %s\n",scb->parent_scb_ptr->scb_name);
315                 printk ("scb->parent_scb_ptr->next_scb_ptr = %s\n",scb->parent_scb_ptr->next_scb_ptr->scb_name);
316                 printk ("scb->parent_scb_ptr->sub_list_ptr = %s\n",scb->parent_scb_ptr->sub_list_ptr->scb_name);
317 #endif
318                 /* link to  parent SCB */
319                 if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) {
320                         snd_assert ( (scb->parent_scb_ptr->next_scb_ptr == ins->the_null_scb),
321                                      return NULL);
322
323                         scb->parent_scb_ptr->next_scb_ptr = scb;
324
325                 } else if (scb_child_type == SCB_ON_PARENT_SUBLIST_SCB) {
326                         snd_assert ( (scb->parent_scb_ptr->sub_list_ptr == ins->the_null_scb),
327                                      return NULL);
328
329                         scb->parent_scb_ptr->sub_list_ptr = scb;
330                 } else {
331                         snd_assert (0,return NULL);
332                 }
333
334                 spin_lock_irqsave(&chip->reg_lock, flags);
335
336                 /* update entry in DSP RAM */
337                 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
338
339                 spin_unlock_irqrestore(&chip->reg_lock, flags);
340         }
341
342
343         cs46xx_dsp_proc_register_scb_desc (chip,scb);
344
345         return scb;
346 }
347
348 static struct dsp_scb_descriptor * 
349 cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data,
350                                u32 dest, char * task_entry_name,
351                                struct dsp_scb_descriptor * parent_scb,
352                                int scb_child_type)
353 {
354         struct dsp_symbol_entry * task_entry;
355
356         task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name,
357                                                SYMBOL_CODE);
358   
359         if (task_entry == NULL) {
360                 snd_printk (KERN_ERR "dsp_spos: symbol %s not found\n",task_entry_name);
361                 return NULL;
362         }
363   
364         return _dsp_create_generic_scb (chip,name,scb_data,dest,task_entry,
365                                         parent_scb,scb_child_type);
366 }
367
368 struct dsp_scb_descriptor * 
369 cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip)
370 {
371         struct dsp_scb_descriptor * scb;
372   
373         struct dsp_timing_master_scb timing_master_scb = {
374                 { 0,
375                   0,
376                   0,
377                   0
378                 },
379                 { 0,
380                   0,
381                   0,
382                   0,
383                   0
384                 },
385                 0,0,
386                 0,NULL_SCB_ADDR,
387                 0,0,             /* extraSampleAccum:TMreserved */
388                 0,0,             /* codecFIFOptr:codecFIFOsyncd */
389                 0x0001,0x8000,   /* fracSampAccumQm1:TMfrmsLeftInGroup */
390                 0x0001,0x0000,   /* fracSampCorrectionQm1:TMfrmGroupLength */
391                 0x00060000       /* nSampPerFrmQ15 */
392         };    
393   
394         scb = cs46xx_dsp_create_generic_scb(chip,"TimingMasterSCBInst",(u32 *)&timing_master_scb,
395                                             TIMINGMASTER_SCB_ADDR,
396                                             "TIMINGMASTER",NULL,SCB_NO_PARENT);
397
398         return scb;
399 }
400
401
402 struct dsp_scb_descriptor * 
403 cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name,
404                                 u16 channel_disp, u16 fifo_addr, u16 child_scb_addr,
405                                 u32 dest, struct dsp_scb_descriptor * parent_scb,
406                                 int scb_child_type)
407 {
408         struct dsp_scb_descriptor * scb;
409   
410         struct dsp_codec_output_scb codec_out_scb = {
411                 { 0,
412                   0,
413                   0,
414                   0
415                 },
416                 {
417                         0,
418                         0,
419                         0,
420                         0,
421                         0
422                 },
423                 0,0,
424                 0,NULL_SCB_ADDR,
425                 0,                      /* COstrmRsConfig */
426                 0,                      /* COstrmBufPtr */
427                 channel_disp,fifo_addr, /* leftChanBaseIOaddr:rightChanIOdisp */
428                 0x0000,0x0080,          /* (!AC97!) COexpVolChangeRate:COscaleShiftCount */
429                 0,child_scb_addr        /* COreserved - need child scb to work with rom code */
430         };
431   
432   
433         scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb,
434                                             dest,"S16_CODECOUTPUTTASK",parent_scb,
435                                             scb_child_type);
436   
437         return scb;
438 }
439
440 struct dsp_scb_descriptor * 
441 cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
442                                u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr,
443                                u32 dest, struct dsp_scb_descriptor * parent_scb,
444                                int scb_child_type)
445 {
446
447         struct dsp_scb_descriptor * scb;
448         struct dsp_codec_input_scb codec_input_scb = {
449                 { 0,
450                   0,
451                   0,
452                   0
453                 },
454                 {
455                         0,
456                         0,
457                         0,
458                         0,
459                         0
460                 },
461     
462 #if 0  /* cs4620 */
463                 SyncIOSCB,NULL_SCB_ADDR
464 #else
465                 0 , 0,
466 #endif
467                 0,0,
468
469                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,  /* strmRsConfig */
470                 sample_buffer_addr << 0x10,       /* strmBufPtr; defined as a dword ptr, used as a byte ptr */
471                 channel_disp,fifo_addr,           /* (!AC97!) leftChanBaseINaddr=AC97primary 
472                                                      link input slot 3 :rightChanINdisp=""slot 4 */
473                 0x0000,0x0000,                    /* (!AC97!) ????:scaleShiftCount; no shift needed 
474                                                      because AC97 is already 20 bits */
475                 0x80008000                        /* ??clw cwcgame.scb has 0 */
476         };
477   
478         scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_input_scb,
479                                             dest,"S16_CODECINPUTTASK",parent_scb,
480                                             scb_child_type);
481         return scb;
482 }
483
484
485 static struct dsp_scb_descriptor * 
486 cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name,
487                                  u16 sample_buffer_addr, u32 dest,
488                                  int virtual_channel, u32 playback_hw_addr,
489                                  struct dsp_scb_descriptor * parent_scb,
490                                  int scb_child_type)
491 {
492         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
493         struct dsp_scb_descriptor * scb;
494   
495         struct dsp_generic_scb pcm_reader_scb = {
496     
497                 /*
498                   Play DMA Task xfers data from host buffer to SP buffer
499                   init/runtime variables:
500                   PlayAC: Play Audio Data Conversion - SCB loc: 2nd dword, mask: 0x0000F000L
501                   DATA_FMT_16BIT_ST_LTLEND(0x00000000L)   from 16-bit stereo, little-endian
502                   DATA_FMT_8_BIT_ST_SIGNED(0x00001000L)   from 8-bit stereo, signed
503                   DATA_FMT_16BIT_MN_LTLEND(0x00002000L)   from 16-bit mono, little-endian
504                   DATA_FMT_8_BIT_MN_SIGNED(0x00003000L)   from 8-bit mono, signed
505                   DATA_FMT_16BIT_ST_BIGEND(0x00004000L)   from 16-bit stereo, big-endian
506                   DATA_FMT_16BIT_MN_BIGEND(0x00006000L)   from 16-bit mono, big-endian
507                   DATA_FMT_8_BIT_ST_UNSIGNED(0x00009000L) from 8-bit stereo, unsigned
508                   DATA_FMT_8_BIT_MN_UNSIGNED(0x0000b000L) from 8-bit mono, unsigned
509                   ? Other combinations possible from:
510                   DMA_RQ_C2_AUDIO_CONVERT_MASK    0x0000F000L
511                   DMA_RQ_C2_AC_NONE               0x00000000L
512                   DMA_RQ_C2_AC_8_TO_16_BIT        0x00001000L
513                   DMA_RQ_C2_AC_MONO_TO_STEREO     0x00002000L
514                   DMA_RQ_C2_AC_ENDIAN_CONVERT     0x00004000L
515                   DMA_RQ_C2_AC_SIGNED_CONVERT     0x00008000L
516         
517                   HostBuffAddr: Host Buffer Physical Byte Address - SCB loc:3rd dword, Mask: 0xFFFFFFFFL
518                   aligned to dword boundary
519                 */
520                 /* Basic (non scatter/gather) DMA requestor (4 ints) */
521                 { DMA_RQ_C1_SOURCE_ON_HOST +        /* source buffer is on the host */
522                   DMA_RQ_C1_SOURCE_MOD1024 +        /* source buffer is 1024 dwords (4096 bytes) */
523                   DMA_RQ_C1_DEST_MOD32 +            /* dest buffer(PCMreaderBuf) is 32 dwords*/
524                   DMA_RQ_C1_WRITEBACK_SRC_FLAG +    /* ?? */
525                   DMA_RQ_C1_WRITEBACK_DEST_FLAG +   /* ?? */
526                   15,                             /* DwordCount-1: picked 16 for DwordCount because Jim */
527                   /*        Barnette said that is what we should use since */
528                   /*        we are not running in optimized mode? */
529                   DMA_RQ_C2_AC_NONE +
530                   DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG + /* set play interrupt (bit0) in HISR when source */
531                   /*   buffer (on host) crosses half-way point */
532                   virtual_channel,                   /* Play DMA channel arbitrarily set to 0 */
533                   playback_hw_addr,                  /* HostBuffAddr (source) */
534                   DMA_RQ_SD_SP_SAMPLE_ADDR +         /* destination buffer is in SP Sample Memory */
535                   sample_buffer_addr                 /* SP Buffer Address (destination) */
536                 },
537                 /* Scatter/gather DMA requestor extension   (5 ints) */
538                 {
539                         0,
540                         0,
541                         0,
542                         0,
543                         0 
544                 },
545                 /* Sublist pointer & next stream control block (SCB) link. */
546                 NULL_SCB_ADDR,NULL_SCB_ADDR,
547                 /* Pointer to this tasks parameter block & stream function pointer */
548                 0,NULL_SCB_ADDR,
549                 /* rsConfig register for stream buffer (rsDMA reg. is loaded from basicReq.daw */
550                 /*   for incoming streams, or basicReq.saw, for outgoing streams) */
551                 RSCONFIG_DMA_ENABLE +                 /* enable DMA */
552                 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + /* MAX_DMA_SIZE picked to be 19 since SPUD  */
553                 /*  uses it for some reason */
554                 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) + /* stream number = SCBaddr/16 */
555                 RSCONFIG_SAMPLE_16STEREO +
556                 RSCONFIG_MODULO_32,             /* dest buffer(PCMreaderBuf) is 32 dwords (256 bytes) */
557                 /* Stream sample pointer & MAC-unit mode for this stream */
558                 (sample_buffer_addr << 0x10),
559                 /* Fractional increment per output sample in the input sample buffer */
560                 0, 
561                 {
562                         /* Standard stereo volume control
563                            default muted */
564                         0xffff,0xffff,
565                         0xffff,0xffff
566                 }
567         };
568
569         if (ins->null_algorithm == NULL) {
570                 ins->null_algorithm =  cs46xx_dsp_lookup_symbol (chip,"NULLALGORITHM",
571                                                                  SYMBOL_CODE);
572     
573                 if (ins->null_algorithm == NULL) {
574                         snd_printk (KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n");
575                         return NULL;
576                 }    
577         }
578
579         scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_reader_scb,
580                                       dest,ins->null_algorithm,parent_scb,
581                                       scb_child_type);
582   
583         return scb;
584 }
585
586 #define GOF_PER_SEC 200
587
588 struct dsp_scb_descriptor * 
589 cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
590                                int rate,
591                                u16 src_buffer_addr,
592                                u16 src_delay_buffer_addr, u32 dest,
593                                struct dsp_scb_descriptor * parent_scb,
594                                int scb_child_type,
595                                int pass_through)
596 {
597
598         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
599         struct dsp_scb_descriptor * scb;
600         unsigned int tmp1, tmp2;
601         unsigned int phiIncr;
602         unsigned int correctionPerGOF, correctionPerSec;
603
604         snd_printdd( "dsp_spos: setting %s rate to %u\n",scb_name,rate);
605
606         /*
607          *  Compute the values used to drive the actual sample rate conversion.
608          *  The following formulas are being computed, using inline assembly
609          *  since we need to use 64 bit arithmetic to compute the values:
610          *
611          *  phiIncr = floor((Fs,in * 2^26) / Fs,out)
612          *  correctionPerGOF = floor((Fs,in * 2^26 - Fs,out * phiIncr) /
613          *                                   GOF_PER_SEC)
614          *  ulCorrectionPerSec = Fs,in * 2^26 - Fs,out * phiIncr -M
615          *                       GOF_PER_SEC * correctionPerGOF
616          *
617          *  i.e.
618          *
619          *  phiIncr:other = dividend:remainder((Fs,in * 2^26) / Fs,out)
620          *  correctionPerGOF:correctionPerSec =
621          *      dividend:remainder(ulOther / GOF_PER_SEC)
622          */
623         tmp1 = rate << 16;
624         phiIncr = tmp1 / 48000;
625         tmp1 -= phiIncr * 48000;
626         tmp1 <<= 10;
627         phiIncr <<= 10;
628         tmp2 = tmp1 / 48000;
629         phiIncr += tmp2;
630         tmp1 -= tmp2 * 48000;
631         correctionPerGOF = tmp1 / GOF_PER_SEC;
632         tmp1 -= correctionPerGOF * GOF_PER_SEC;
633         correctionPerSec = tmp1;
634
635         {
636                 struct dsp_src_task_scb src_task_scb = {
637                         0x0028,0x00c8,
638                         0x5555,0x0000,
639                         0x0000,0x0000,
640                         src_buffer_addr,1,
641                         correctionPerGOF,correctionPerSec,
642                         RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,  
643                         0x0000,src_delay_buffer_addr,                  
644                         0x0,                                            
645                         0x080,(src_delay_buffer_addr + (24 * 4)),
646                         0,0, /* next_scb, sub_list_ptr */
647                         0,0, /* entry, this_spb */
648                         RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
649                         src_buffer_addr << 0x10,
650                         phiIncr,
651                         { 
652                                 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left,
653                                 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left
654                         }
655                 };
656                 
657                 if (ins->s16_up == NULL) {
658                         ins->s16_up =  cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC",
659                                                                  SYMBOL_CODE);
660                         
661                         if (ins->s16_up == NULL) {
662                                 snd_printk (KERN_ERR "dsp_spos: symbol S16_UPSRC not found\n");
663                                 return NULL;
664                         }    
665                 }
666                 
667                 /* clear buffers */
668                 _dsp_clear_sample_buffer (chip,src_buffer_addr,8);
669                 _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32);
670                                 
671                 if (pass_through) {
672                         /* wont work with any other rate than
673                            the native DSP rate */
674                         snd_assert (rate = 48000);
675
676                         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
677                                                             dest,"DMAREADER",parent_scb,
678                                                             scb_child_type);
679                 } else {
680                         scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
681                                                       dest,ins->s16_up,parent_scb,
682                                                       scb_child_type);
683                 }
684
685
686         }
687
688         return scb;
689 }
690
691 #if 0 /* not used */
692 struct dsp_scb_descriptor * 
693 cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name,
694                              u16 buffer_addr, u32 dest,
695                              struct dsp_scb_descriptor * parent_scb,
696                              int scb_child_type) {
697         struct dsp_scb_descriptor * scb;
698         
699         struct dsp_filter_scb filter_scb = {
700                 .a0_right            = 0x41a9,
701                 .a0_left             = 0x41a9,
702                 .a1_right            = 0xb8e4,
703                 .a1_left             = 0xb8e4,
704                 .a2_right            = 0x3e55,
705                 .a2_left             = 0x3e55,
706                 
707                 .filter_unused3      = 0x0000,
708                 .filter_unused2      = 0x0000,
709
710                 .output_buf_ptr      = buffer_addr,
711                 .init                = 0x000,
712
713                 .prev_sample_output1 = 0x00000000,
714                 .prev_sample_output2 = 0x00000000,
715
716                 .prev_sample_input1  = 0x00000000,
717                 .prev_sample_input2  = 0x00000000,
718
719                 .next_scb_ptr        = 0x0000,
720                 .sub_list_ptr        = 0x0000,
721
722                 .entry_point         = 0x0000,
723                 .spb_ptr             = 0x0000,
724
725                 .b0_right            = 0x0e38,
726                 .b0_left             = 0x0e38,
727                 .b1_right            = 0x1c71,
728                 .b1_left             = 0x1c71,
729                 .b2_right            = 0x0e38,
730                 .b2_left             = 0x0e38,
731         };
732
733
734         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&filter_scb,
735                                             dest,"FILTERTASK",parent_scb,
736                                             scb_child_type);
737
738         return scb;
739 }
740 #endif /* not used */
741
742 struct dsp_scb_descriptor * 
743 cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
744                                u16 mix_buffer_addr, u32 dest,
745                                struct dsp_scb_descriptor * parent_scb,
746                                int scb_child_type)
747 {
748         struct dsp_scb_descriptor * scb;
749   
750         struct dsp_mix_only_scb master_mix_scb = {
751                 /* 0 */ { 0,
752                           /* 1 */   0,
753                           /* 2 */  mix_buffer_addr,
754                           /* 3 */  0
755                           /*   */ },
756                 {
757                         /* 4 */  0,
758                         /* 5 */  0,
759                         /* 6 */  0,
760                         /* 7 */  0,
761                         /* 8 */  0x00000080
762                 },
763                 /* 9 */ 0,0,
764                 /* A */ 0,0,
765                 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
766                 /* C */ (mix_buffer_addr  + (16 * 4)) << 0x10, 
767                 /* D */ 0,
768                 {
769                         /* E */ 0x8000,0x8000,
770                         /* F */ 0x8000,0x8000
771                 }
772         };
773
774
775         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&master_mix_scb,
776                                             dest,"S16_MIX",parent_scb,
777                                             scb_child_type);
778         return scb;
779 }
780
781
782 struct dsp_scb_descriptor * 
783 cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
784                                      u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
785                                      struct dsp_scb_descriptor * parent_scb,
786                                      int scb_child_type)
787 {
788         struct dsp_scb_descriptor * scb;
789
790         struct dsp_mix2_ostream_scb mix2_ostream_scb = {
791                 /* Basic (non scatter/gather) DMA requestor (4 ints) */
792                 { 
793                         DMA_RQ_C1_SOURCE_MOD64 +
794                         DMA_RQ_C1_DEST_ON_HOST +
795                         DMA_RQ_C1_DEST_MOD1024 +
796                         DMA_RQ_C1_WRITEBACK_SRC_FLAG + 
797                         DMA_RQ_C1_WRITEBACK_DEST_FLAG +
798                         15,                            
799       
800                         DMA_RQ_C2_AC_NONE +
801                         DMA_RQ_C2_SIGNAL_DEST_PINGPONG + 
802       
803                         CS46XX_DSP_CAPTURE_CHANNEL,                                 
804                         DMA_RQ_SD_SP_SAMPLE_ADDR + 
805                         mix_buffer_addr, 
806                         0x0                   
807                 },
808     
809                 { 0, 0, 0, 0, 0, },
810                 0,0,
811                 0,writeback_spb,
812     
813                 RSCONFIG_DMA_ENABLE + 
814                 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) + 
815     
816                 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
817                 RSCONFIG_DMA_TO_HOST + 
818                 RSCONFIG_SAMPLE_16STEREO +
819                 RSCONFIG_MODULO_64,    
820                 (mix_buffer_addr + (32 * 4)) << 0x10,
821                 1,0,            
822                 0x0001,0x0080,
823                 0xFFFF,0
824         };
825
826
827         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&mix2_ostream_scb,
828                                 
829             dest,"S16_MIX_TO_OSTREAM",parent_scb,
830                                             scb_child_type);
831   
832         return scb;
833 }
834
835
836 struct dsp_scb_descriptor * 
837 cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name,
838                                     u16 vari_buffer_addr0,
839                                     u16 vari_buffer_addr1,
840                                     u32 dest,
841                                     struct dsp_scb_descriptor * parent_scb,
842                                     int scb_child_type)
843 {
844
845         struct dsp_scb_descriptor * scb;
846   
847         struct dsp_vari_decimate_scb vari_decimate_scb = {
848                 0x0028,0x00c8,
849                 0x5555,0x0000,
850                 0x0000,0x0000,
851                 vari_buffer_addr0,vari_buffer_addr1,
852     
853                 0x0028,0x00c8,
854                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, 
855     
856                 0xFF800000,   
857                 0,
858                 0x0080,vari_buffer_addr1 + (25 * 4), 
859     
860                 0,0, 
861                 0,0,
862
863                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
864                 vari_buffer_addr0 << 0x10,   
865                 0x04000000,                   
866                 {
867                         0x8000,0x8000, 
868                         0xFFFF,0xFFFF
869                 }
870         };
871
872         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&vari_decimate_scb,
873                                             dest,"VARIDECIMATE",parent_scb,
874                                             scb_child_type);
875   
876         return scb;
877 }
878
879
880 static struct dsp_scb_descriptor * 
881 cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
882                                        struct dsp_scb_descriptor * input_scb,
883                                        struct dsp_scb_descriptor * parent_scb,
884                                        int scb_child_type)
885 {
886
887         struct dsp_scb_descriptor * scb;
888
889
890         struct dsp_pcm_serial_input_scb pcm_serial_input_scb = {
891                 { 0,
892                   0,
893                   0,
894                   0
895                 },
896                 {
897                         0,
898                         0,
899                         0,
900                         0,
901                         0
902                 },
903
904                 0,0,
905                 0,0,
906
907                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16,
908                 0,
909       /* 0xD */ 0,input_scb->address,
910                 {
911       /* 0xE */   0x8000,0x8000,
912       /* 0xF */   0x8000,0x8000
913                 }
914         };
915
916         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_serial_input_scb,
917                                             dest,"PCMSERIALINPUTTASK",parent_scb,
918                                             scb_child_type);
919         return scb;
920 }
921
922
923 static struct dsp_scb_descriptor * 
924 cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
925                                    u16 hfg_scb_address,
926                                    u16 asynch_buffer_address,
927                                    struct dsp_scb_descriptor * parent_scb,
928                                    int scb_child_type)
929 {
930
931         struct dsp_scb_descriptor * scb;
932
933         struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = {
934                 0xfc00,0x03ff,      /*  Prototype sample buffer size of 256 dwords */
935                 0x0058,0x0028,      /* Min Delta 7 dwords == 28 bytes */
936                 /* : Max delta 25 dwords == 100 bytes */
937                 0,hfg_scb_address,  /* Point to HFG task SCB */
938                 0,0,                /* Initialize current Delta and Consumer ptr adjustment count */
939                 0,                  /* Initialize accumulated Phi to 0 */
940                 0,0x2aab,           /* Const 1/3 */
941     
942                 {
943                         0,         /* Define the unused elements */
944                         0,
945                         0
946                 },
947     
948                 0,0,
949                 0,dest + AFGTxAccumPhi,
950     
951                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256, /* Stereo, 256 dword */
952                 (asynch_buffer_address) << 0x10,  /* This should be automagically synchronized
953                                                      to the producer pointer */
954     
955                 /* There is no correct initial value, it will depend upon the detected
956                    rate etc  */
957                 0x18000000,                     /* Phi increment for approx 32k operation */
958                 0x8000,0x8000,                  /* Volume controls are unused at this time */
959                 0x8000,0x8000
960         };
961   
962         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb,
963                                             dest,"ASYNCHFGTXCODE",parent_scb,
964                                             scb_child_type);
965
966         return scb;
967 }
968
969
970 struct dsp_scb_descriptor * 
971 cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
972                                    u16 hfg_scb_address,
973                                    u16 asynch_buffer_address,
974                                    struct dsp_scb_descriptor * parent_scb,
975                                    int scb_child_type)
976 {
977         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
978         struct dsp_scb_descriptor * scb;
979
980         struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = {
981                 0xfe00,0x01ff,      /*  Prototype sample buffer size of 128 dwords */
982                 0x0064,0x001c,      /* Min Delta 7 dwords == 28 bytes */
983                                     /* : Max delta 25 dwords == 100 bytes */
984                 0,hfg_scb_address,  /* Point to HFG task SCB */
985                 0,0,                            /* Initialize current Delta and Consumer ptr adjustment count */
986                 {
987                         0,                /* Define the unused elements */
988                         0,
989                         0,
990                         0,
991                         0
992                 },
993       
994                 0,0,
995                 0,dest,
996     
997                 RSCONFIG_MODULO_128 |
998         RSCONFIG_SAMPLE_16STEREO,                         /* Stereo, 128 dword */
999                 ( (asynch_buffer_address + (16 * 4))  << 0x10),   /* This should be automagically 
1000                                                                                           synchrinized to the producer pointer */
1001     
1002                 /* There is no correct initial value, it will depend upon the detected
1003                    rate etc  */
1004                 0x18000000,         
1005
1006                 /* Set IEC958 input volume */
1007                 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
1008                 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
1009         };
1010
1011         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_rx_scb,
1012                                             dest,"ASYNCHFGRXCODE",parent_scb,
1013                                             scb_child_type);
1014
1015         return scb;
1016 }
1017
1018
1019 #if 0 /* not used */
1020 struct dsp_scb_descriptor * 
1021 cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1022                                    u16 snoop_buffer_address,
1023                                    struct dsp_scb_descriptor * snoop_scb,
1024                                    struct dsp_scb_descriptor * parent_scb,
1025                                    int scb_child_type)
1026 {
1027
1028         struct dsp_scb_descriptor * scb;
1029   
1030         struct dsp_output_snoop_scb output_snoop_scb = {
1031                 { 0,    /*  not used.  Zero */
1032                   0,
1033                   0,
1034                   0,
1035                 },
1036                 {
1037                         0, /* not used.  Zero */
1038                         0,
1039                         0,
1040                         0,
1041                         0
1042                 },
1043     
1044                 0,0,
1045                 0,0,
1046     
1047                 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1048                 snoop_buffer_address << 0x10,  
1049                 0,0,
1050                 0,
1051                 0,snoop_scb->address
1052         };
1053   
1054         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&output_snoop_scb,
1055                                             dest,"OUTPUTSNOOP",parent_scb,
1056                                             scb_child_type);
1057         return scb;
1058 }
1059 #endif /* not used */
1060
1061
1062 struct dsp_scb_descriptor * 
1063 cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1064                                  struct dsp_scb_descriptor * parent_scb,
1065                                  int scb_child_type)
1066 {
1067         struct dsp_scb_descriptor * scb;
1068   
1069         struct dsp_spio_write_scb spio_write_scb = {
1070                 0,0,         /*   SPIOWAddress2:SPIOWAddress1; */
1071                 0,           /*   SPIOWData1; */
1072                 0,           /*   SPIOWData2; */
1073                 0,0,         /*   SPIOWAddress4:SPIOWAddress3; */
1074                 0,           /*   SPIOWData3; */
1075                 0,           /*   SPIOWData4; */
1076                 0,0,         /*   SPIOWDataPtr:Unused1; */
1077                 { 0,0 },     /*   Unused2[2]; */
1078     
1079                 0,0,         /*   SPIOWChildPtr:SPIOWSiblingPtr; */
1080                 0,0,         /*   SPIOWThisPtr:SPIOWEntryPoint; */
1081     
1082                 { 
1083                         0,
1084                         0,
1085                         0,
1086                         0,
1087                         0          /*   Unused3[5];  */
1088                 }
1089         };
1090
1091         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&spio_write_scb,
1092                                             dest,"SPIOWRITE",parent_scb,
1093                                             scb_child_type);
1094
1095         return scb;
1096 }
1097
1098 struct dsp_scb_descriptor *
1099 cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1100                                   u16 snoop_buffer_address,
1101                                   struct dsp_scb_descriptor * snoop_scb,
1102                                   struct dsp_scb_descriptor * parent_scb,
1103                                   int scb_child_type)
1104 {
1105         struct dsp_scb_descriptor * scb;
1106   
1107         struct dsp_magic_snoop_task magic_snoop_scb = {
1108                 /* 0 */ 0, /* i0 */
1109                 /* 1 */ 0, /* i1 */
1110                 /* 2 */ snoop_buffer_address << 0x10,
1111                 /* 3 */ 0,snoop_scb->address,
1112                 /* 4 */ 0, /* i3 */
1113                 /* 5 */ 0, /* i4 */
1114                 /* 6 */ 0, /* i5 */
1115                 /* 7 */ 0, /* i6 */
1116                 /* 8 */ 0, /* i7 */
1117                 /* 9 */ 0,0, /* next_scb, sub_list_ptr */
1118                 /* A */ 0,0, /* entry_point, this_ptr */
1119                 /* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1120                 /* C */ snoop_buffer_address  << 0x10,
1121                 /* D */ 0,
1122                 /* E */ { 0x8000,0x8000,
1123                 /* F */   0xffff,0xffff
1124                 }
1125         };
1126
1127         scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&magic_snoop_scb,
1128                                             dest,"MAGICSNOOPTASK",parent_scb,
1129                                             scb_child_type);
1130
1131         return scb;
1132 }
1133
1134 static struct dsp_scb_descriptor *
1135 find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from)
1136 {
1137         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1138         struct dsp_scb_descriptor * scb = from;
1139
1140         while (scb->next_scb_ptr != ins->the_null_scb) {
1141                 snd_assert (scb->next_scb_ptr != NULL, return NULL);
1142
1143                 scb = scb->next_scb_ptr;
1144         }
1145
1146         return scb;
1147 }
1148
1149 static u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = {
1150         0x0600, /* 1 */
1151         0x1500, /* 2 */
1152         0x1580, /* 3 */
1153         0x1600, /* 4 */
1154         0x1680, /* 5 */
1155         0x1700, /* 6 */
1156         0x1780, /* 7 */
1157         0x1800, /* 8 */
1158         0x1880, /* 9 */
1159         0x1900, /* 10 */
1160         0x1980, /* 11 */
1161         0x1A00, /* 12 */
1162         0x1A80, /* 13 */
1163         0x1B00, /* 14 */
1164         0x1B80, /* 15 */
1165         0x1C00, /* 16 */
1166         0x1C80, /* 17 */
1167         0x1D00, /* 18 */
1168         0x1D80, /* 19 */
1169         0x1E00, /* 20 */
1170         0x1E80, /* 21 */
1171         0x1F00, /* 22 */
1172         0x1F80, /* 23 */
1173         0x2000, /* 24 */
1174         0x2080, /* 25 */
1175         0x2100, /* 26 */
1176         0x2180, /* 27 */
1177         0x2200, /* 28 */
1178         0x2280, /* 29 */
1179         0x2300, /* 30 */
1180         0x2380, /* 31 */
1181         0x2400, /* 32 */
1182 };
1183
1184 static u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = {
1185         0x2B80,
1186         0x2BA0,
1187         0x2BC0,
1188         0x2BE0,
1189         0x2D00,  
1190         0x2D20,  
1191         0x2D40,  
1192         0x2D60,
1193         0x2D80,
1194         0x2DA0,
1195         0x2DC0,
1196         0x2DE0,
1197         0x2E00,
1198         0x2E20
1199 };
1200
1201 static u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
1202         0x2480,
1203         0x2500,
1204         0x2580,
1205         0x2600,
1206         0x2680,
1207         0x2700,
1208         0x2780,
1209         0x2800,
1210         0x2880,
1211         0x2900,
1212         0x2980,
1213         0x2A00,
1214         0x2A80,
1215         0x2B00
1216 };
1217
1218 struct dsp_pcm_channel_descriptor *
1219 cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip,
1220                                u32 sample_rate, void * private_data, 
1221                                u32 hw_dma_addr,
1222                                int pcm_channel_id)
1223 {
1224         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1225         struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL;
1226         struct dsp_scb_descriptor * src_parent_scb = NULL;
1227
1228         /* struct dsp_scb_descriptor * pcm_parent_scb; */
1229         char scb_name[DSP_MAX_SCB_NAME];
1230         int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0;
1231         unsigned long flags;
1232
1233         switch (pcm_channel_id) {
1234         case DSP_PCM_MAIN_CHANNEL:
1235                 mixer_scb = ins->master_mix_scb;
1236                 break;
1237         case DSP_PCM_REAR_CHANNEL:
1238                 mixer_scb = ins->rear_mix_scb;
1239                 break;
1240         case DSP_PCM_CENTER_LFE_CHANNEL:
1241                 mixer_scb = ins->center_lfe_mix_scb;
1242                 break;
1243         case DSP_PCM_S71_CHANNEL:
1244                 /* TODO */
1245                 snd_assert(0);
1246                 break;
1247         case DSP_IEC958_CHANNEL:
1248                 snd_assert (ins->asynch_tx_scb != NULL, return NULL);
1249                 mixer_scb = ins->asynch_tx_scb;
1250
1251                 /* if sample rate is set to 48khz we pass
1252                    the Sample Rate Converted (which could
1253                    alter the raw data stream ...) */
1254                 if (sample_rate == 48000) {
1255                         snd_printdd ("IEC958 pass through\n");
1256                         /* Hack to bypass creating a new SRC */
1257                         pass_through = 1;
1258                 }
1259                 break;
1260         default:
1261                 snd_assert (0);
1262                 return NULL;
1263         }
1264         /* default sample rate is 44100 */
1265         if (!sample_rate) sample_rate = 44100;
1266
1267         /* search for a already created SRC SCB with the same sample rate */
1268         for (i = 0; i < DSP_MAX_PCM_CHANNELS && 
1269                      (pcm_index == -1 || src_scb == NULL); ++i) {
1270
1271                 /* virtual channel reserved 
1272                    for capture */
1273                 if (i == CS46XX_DSP_CAPTURE_CHANNEL) continue;
1274
1275                 if (ins->pcm_channels[i].active) {
1276                         if (!src_scb && 
1277                             ins->pcm_channels[i].sample_rate == sample_rate &&
1278                             ins->pcm_channels[i].mixer_scb == mixer_scb) {
1279                                 src_scb = ins->pcm_channels[i].src_scb;
1280                                 ins->pcm_channels[i].src_scb->ref_count ++;
1281                                 src_index = ins->pcm_channels[i].src_slot;
1282                         }
1283                 } else if (pcm_index == -1) {
1284                         pcm_index = i;
1285                 }
1286         }
1287
1288         if (pcm_index == -1) {
1289                 snd_printk (KERN_ERR "dsp_spos: no free PCM channel\n");
1290                 return NULL;
1291         }
1292
1293         if (src_scb == NULL) {
1294                 if (ins->nsrc_scb >= DSP_MAX_SRC_NR) {
1295                         snd_printk(KERN_ERR "dsp_spos: to many SRC instances\n!");
1296                         return NULL;
1297                 }
1298
1299                 /* find a free slot */
1300                 for (i = 0; i < DSP_MAX_SRC_NR; ++i) {
1301                         if (ins->src_scb_slots[i] == 0) {
1302                                 src_index = i;
1303                                 ins->src_scb_slots[i] = 1;
1304                                 break;
1305                         }
1306                 }
1307                 snd_assert (src_index != -1,return NULL);
1308
1309                 /* we need to create a new SRC SCB */
1310                 if (mixer_scb->sub_list_ptr == ins->the_null_scb) {
1311                         src_parent_scb = mixer_scb;
1312                         insert_point = SCB_ON_PARENT_SUBLIST_SCB;
1313                 } else {
1314                         src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr);
1315                         insert_point = SCB_ON_PARENT_NEXT_SCB;
1316                 }
1317
1318                 snprintf (scb_name,DSP_MAX_SCB_NAME,"SrcTask_SCB%d",src_index);
1319                 
1320                 snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name);
1321                 src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name,
1322                                                          sample_rate,
1323                                                          src_output_buffer_addr[src_index],
1324                                                          src_delay_buffer_addr[src_index],
1325                                                          /* 0x400 - 0x600 source SCBs */
1326                                                          0x400 + (src_index * 0x10) ,
1327                                                          src_parent_scb,
1328                                                          insert_point,
1329                                                          pass_through);
1330
1331                 if (!src_scb) {
1332                         snd_printk (KERN_ERR "dsp_spos: failed to create SRCtaskSCB\n");
1333                         return NULL;
1334                 }
1335
1336                 /* cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate); */
1337
1338                 ins->nsrc_scb ++;
1339         } 
1340   
1341   
1342         snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index);
1343
1344         snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name,
1345                  pcm_channel_id);
1346
1347         pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name,
1348                                                    pcm_reader_buffer_addr[pcm_index],
1349                                                    /* 0x200 - 400 PCMreader SCBs */
1350                                                    (pcm_index * 0x10) + 0x200,
1351                                                    pcm_index,    /* virtual channel 0-31 */
1352                                                    hw_dma_addr,  /* pcm hw addr */
1353                            NULL,         /* parent SCB ptr */
1354                            0             /* insert point */ 
1355                            );
1356
1357         if (!pcm_scb) {
1358                 snd_printk (KERN_ERR "dsp_spos: failed to create PCMreaderSCB\n");
1359                 return NULL;
1360         }
1361         
1362         spin_lock_irqsave(&chip->reg_lock, flags);
1363         ins->pcm_channels[pcm_index].sample_rate = sample_rate;
1364         ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb;
1365         ins->pcm_channels[pcm_index].src_scb = src_scb;
1366         ins->pcm_channels[pcm_index].unlinked = 1;
1367         ins->pcm_channels[pcm_index].private_data = private_data;
1368         ins->pcm_channels[pcm_index].src_slot = src_index;
1369         ins->pcm_channels[pcm_index].active = 1;
1370         ins->pcm_channels[pcm_index].pcm_slot = pcm_index;
1371         ins->pcm_channels[pcm_index].mixer_scb = mixer_scb;
1372         ins->npcm_channels ++;
1373         spin_unlock_irqrestore(&chip->reg_lock, flags);
1374
1375         return (ins->pcm_channels + pcm_index);
1376 }
1377
1378 int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
1379                                        struct dsp_pcm_channel_descriptor * pcm_channel,
1380                                        int period_size)
1381 {
1382         u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2);
1383         temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK;
1384
1385         switch (period_size) {
1386         case 2048:
1387                 temp |= DMA_RQ_C1_SOURCE_MOD1024;
1388                 break;
1389         case 1024:
1390                 temp |= DMA_RQ_C1_SOURCE_MOD512;
1391                 break;
1392         case 512:
1393                 temp |= DMA_RQ_C1_SOURCE_MOD256;
1394                 break;
1395         case 256:
1396                 temp |= DMA_RQ_C1_SOURCE_MOD128;
1397                 break;
1398         case 128:
1399                 temp |= DMA_RQ_C1_SOURCE_MOD64;
1400                 break;
1401         case 64:
1402                 temp |= DMA_RQ_C1_SOURCE_MOD32;
1403                 break;                
1404         case 32:
1405                 temp |= DMA_RQ_C1_SOURCE_MOD16;
1406                 break; 
1407         default:
1408                 snd_printdd ("period size (%d) not supported by HW\n", period_size);
1409                 return -EINVAL;
1410         }
1411
1412         snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp);
1413
1414         return 0;
1415 }
1416
1417 int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip,
1418                                        int period_size)
1419 {
1420         u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
1421         temp &= ~DMA_RQ_C1_DEST_SIZE_MASK;
1422
1423         switch (period_size) {
1424         case 2048:
1425                 temp |= DMA_RQ_C1_DEST_MOD1024;
1426                 break;
1427         case 1024:
1428                 temp |= DMA_RQ_C1_DEST_MOD512;
1429                 break;
1430         case 512:
1431                 temp |= DMA_RQ_C1_DEST_MOD256;
1432                 break;
1433         case 256:
1434                 temp |= DMA_RQ_C1_DEST_MOD128;
1435                 break;
1436         case 128:
1437                 temp |= DMA_RQ_C1_DEST_MOD64;
1438                 break;
1439         case 64:
1440                 temp |= DMA_RQ_C1_DEST_MOD32;
1441                 break;                
1442         case 32:
1443                 temp |= DMA_RQ_C1_DEST_MOD16;
1444                 break; 
1445         default:
1446                 snd_printdd ("period size (%d) not supported by HW\n", period_size);
1447                 return -EINVAL;
1448         }
1449
1450         snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp);
1451
1452         return 0;
1453 }
1454
1455 void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
1456                                      struct dsp_pcm_channel_descriptor * pcm_channel)
1457 {
1458         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1459         unsigned long flags;
1460
1461         snd_assert(pcm_channel->active, return );
1462         snd_assert(ins->npcm_channels > 0, return );
1463         snd_assert(pcm_channel->src_scb->ref_count > 0, return );
1464
1465         spin_lock_irqsave(&chip->reg_lock, flags);
1466         pcm_channel->unlinked = 1;
1467         pcm_channel->active = 0;
1468         pcm_channel->private_data = NULL;
1469         pcm_channel->src_scb->ref_count --;
1470         ins->npcm_channels --;
1471         spin_unlock_irqrestore(&chip->reg_lock, flags);
1472
1473         cs46xx_dsp_remove_scb(chip,pcm_channel->pcm_reader_scb);
1474
1475         if (!pcm_channel->src_scb->ref_count) {
1476                 cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb);
1477
1478                 snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot <= DSP_MAX_SRC_NR,
1479                             return );
1480
1481                 ins->src_scb_slots[pcm_channel->src_slot] = 0;
1482                 ins->nsrc_scb --;
1483         }
1484 }
1485
1486 int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
1487                            struct dsp_pcm_channel_descriptor * pcm_channel)
1488 {
1489         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1490         unsigned long flags;
1491
1492         snd_assert(pcm_channel->active,return -EIO);
1493         snd_assert(ins->npcm_channels > 0,return -EIO);
1494
1495         spin_lock(&pcm_channel->src_scb->lock);
1496
1497         if (pcm_channel->unlinked) {
1498                 spin_unlock(&pcm_channel->src_scb->lock);
1499                 return -EIO;
1500         }
1501
1502         spin_lock_irqsave(&chip->reg_lock, flags);
1503         pcm_channel->unlinked = 1;
1504         spin_unlock_irqrestore(&chip->reg_lock, flags);
1505
1506         _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb);
1507
1508         spin_unlock(&pcm_channel->src_scb->lock);
1509         return 0;
1510 }
1511
1512 int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
1513                          struct dsp_pcm_channel_descriptor * pcm_channel)
1514 {
1515         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1516         struct dsp_scb_descriptor * parent_scb;
1517         struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb;
1518         unsigned long flags;
1519
1520         spin_lock(&pcm_channel->src_scb->lock);
1521
1522         if (pcm_channel->unlinked == 0) {
1523                 spin_unlock(&pcm_channel->src_scb->lock);
1524                 return -EIO;
1525         }
1526
1527         parent_scb = src_scb;
1528
1529         if (src_scb->sub_list_ptr != ins->the_null_scb) {
1530                 src_scb->sub_list_ptr->parent_scb_ptr = pcm_channel->pcm_reader_scb;
1531                 pcm_channel->pcm_reader_scb->next_scb_ptr = src_scb->sub_list_ptr;
1532         }
1533
1534         src_scb->sub_list_ptr = pcm_channel->pcm_reader_scb;
1535
1536         snd_assert (pcm_channel->pcm_reader_scb->parent_scb_ptr == NULL, ; );
1537         pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb;
1538
1539         spin_lock_irqsave(&chip->reg_lock, flags);
1540
1541         /* update SCB entry in DSP RAM */
1542         cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb);
1543
1544         /* update parent SCB entry */
1545         cs46xx_dsp_spos_update_scb(chip,parent_scb);
1546
1547         pcm_channel->unlinked = 0;
1548         spin_unlock_irqrestore(&chip->reg_lock, flags);
1549
1550         spin_unlock(&pcm_channel->src_scb->lock);
1551         return 0;
1552 }
1553
1554 struct dsp_scb_descriptor *
1555 cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
1556                           u16 addr, char * scb_name)
1557 {
1558         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1559         struct dsp_scb_descriptor * parent;
1560         struct dsp_scb_descriptor * pcm_input;
1561         int insert_point;
1562
1563         snd_assert (ins->record_mixer_scb != NULL,return NULL);
1564
1565         if (ins->record_mixer_scb->sub_list_ptr != ins->the_null_scb) {
1566                 parent = find_next_free_scb (chip,ins->record_mixer_scb->sub_list_ptr);
1567                 insert_point = SCB_ON_PARENT_NEXT_SCB;
1568         } else {
1569                 parent = ins->record_mixer_scb;
1570                 insert_point = SCB_ON_PARENT_SUBLIST_SCB;
1571         }
1572
1573         pcm_input = cs46xx_dsp_create_pcm_serial_input_scb(chip,scb_name,addr,
1574                                                            source, parent,
1575                                                            insert_point);
1576
1577         return pcm_input;
1578 }
1579
1580 int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
1581 {
1582         snd_assert (src->parent_scb_ptr != NULL,  return -EINVAL );
1583
1584         /* mute SCB */
1585         cs46xx_dsp_scb_set_volume (chip,src,0,0);
1586
1587         _dsp_unlink_scb (chip,src);
1588
1589         return 0;
1590 }
1591
1592 int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
1593 {
1594         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1595         struct dsp_scb_descriptor * parent_scb;
1596
1597         snd_assert (src->parent_scb_ptr == NULL,   return -EINVAL );
1598         snd_assert(ins->master_mix_scb !=NULL,   return -EINVAL );
1599
1600         if (ins->master_mix_scb->sub_list_ptr != ins->the_null_scb) {
1601                 parent_scb = find_next_free_scb (chip,ins->master_mix_scb->sub_list_ptr);
1602                 parent_scb->next_scb_ptr = src;
1603         } else {
1604                 parent_scb = ins->master_mix_scb;
1605                 parent_scb->sub_list_ptr = src;
1606         }
1607
1608         src->parent_scb_ptr = parent_scb;
1609
1610         /* update entry in DSP RAM */
1611         cs46xx_dsp_spos_update_scb(chip,parent_scb);
1612   
1613         return 0;
1614 }
1615
1616 int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip)
1617 {
1618         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1619
1620         if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
1621                 cs46xx_dsp_enable_spdif_hw (chip);
1622         }
1623
1624         /* dont touch anything if SPDIF is open */
1625         if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
1626                 /* when cs46xx_iec958_post_close(...) is called it
1627                    will call this function if necessary depending on
1628                    this bit */
1629                 ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1630
1631                 return -EBUSY;
1632         }
1633
1634         snd_assert (ins->asynch_tx_scb == NULL, return -EINVAL);
1635         snd_assert (ins->master_mix_scb->next_scb_ptr == ins->the_null_scb, return -EINVAL);
1636
1637         /* reset output snooper sample buffer pointer */
1638         snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2,
1639                          (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 );
1640         
1641         /* The asynch. transfer task */
1642         ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1643                                                                 SPDIFO_SCB_INST,
1644                                                                 SPDIFO_IP_OUTPUT_BUFFER1,
1645                                                                 ins->master_mix_scb,
1646                                                                 SCB_ON_PARENT_NEXT_SCB);
1647         if (!ins->asynch_tx_scb) return -ENOMEM;
1648
1649         ins->spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
1650                                                                           PCMSERIALINII_SCB_ADDR,
1651                                                                           ins->ref_snoop_scb,
1652                                                                           ins->asynch_tx_scb,
1653                                                                           SCB_ON_PARENT_SUBLIST_SCB);
1654   
1655         
1656         if (!ins->spdif_pcm_input_scb) return -ENOMEM;
1657
1658         /* monitor state */
1659         ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1660
1661         return 0;
1662 }
1663
1664 int  cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip)
1665 {
1666         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1667
1668         /* dont touch anything if SPDIF is open */
1669         if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
1670                 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1671                 return -EBUSY;
1672         }
1673
1674         /* check integrety */
1675         snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
1676         snd_assert (ins->spdif_pcm_input_scb != NULL,return -EINVAL);
1677         snd_assert (ins->master_mix_scb->next_scb_ptr == ins->asynch_tx_scb, return -EINVAL);
1678         snd_assert (ins->asynch_tx_scb->parent_scb_ptr == ins->master_mix_scb, return -EINVAL);
1679
1680         cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
1681         cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
1682
1683         ins->spdif_pcm_input_scb = NULL;
1684         ins->asynch_tx_scb = NULL;
1685
1686         /* clear buffer to prevent any undesired noise */
1687         _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
1688
1689         /* monitor state */
1690         ins->spdif_status_out  &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1691
1692
1693         return 0;
1694 }
1695
1696 int cs46xx_iec958_pre_open (struct snd_cs46xx *chip)
1697 {
1698         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1699
1700         if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
1701                 /* remove AsynchFGTxSCB and and PCMSerialInput_II */
1702                 cs46xx_dsp_disable_spdif_out (chip);
1703
1704                 /* save state */
1705                 ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1706         }
1707         
1708         /* if not enabled already */
1709         if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
1710                 cs46xx_dsp_enable_spdif_hw (chip);
1711         }
1712
1713         /* Create the asynch. transfer task  for playback */
1714         ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1715                                                                 SPDIFO_SCB_INST,
1716                                                                 SPDIFO_IP_OUTPUT_BUFFER1,
1717                                                                 ins->master_mix_scb,
1718                                                                 SCB_ON_PARENT_NEXT_SCB);
1719
1720
1721         /* set spdif channel status value for streaming */
1722         cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_stream);
1723
1724         ins->spdif_status_out  |= DSP_SPDIF_STATUS_PLAYBACK_OPEN;
1725
1726         return 0;
1727 }
1728
1729 int cs46xx_iec958_post_close (struct snd_cs46xx *chip)
1730 {
1731         struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1732
1733         snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL);
1734
1735         ins->spdif_status_out  &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN;
1736
1737         /* restore settings */
1738         cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);
1739         
1740         /* deallocate stuff */
1741         if (ins->spdif_pcm_input_scb != NULL) {
1742                 cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
1743                 ins->spdif_pcm_input_scb = NULL;
1744         }
1745
1746         cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
1747         ins->asynch_tx_scb = NULL;
1748
1749         /* clear buffer to prevent any undesired noise */
1750         _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
1751
1752         /* restore state */
1753         if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
1754                 cs46xx_dsp_enable_spdif_out (chip);
1755         }
1756         
1757         return 0;
1758 }