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