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