0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/io.h>
0011 #include <linux/delay.h>
0012 #include <linux/pm.h>
0013 #include <linux/init.h>
0014 #include <linux/slab.h>
0015 #include <linux/mutex.h>
0016
0017 #include <sound/core.h>
0018 #include <sound/control.h>
0019 #include <sound/info.h>
0020 #include "cs46xx.h"
0021
0022 #include "cs46xx_lib.h"
0023 #include "dsp_spos.h"
0024
0025 struct proc_scb_info {
0026 struct dsp_scb_descriptor * scb_desc;
0027 struct snd_cs46xx *chip;
0028 };
0029
0030 static void remove_symbol (struct snd_cs46xx * chip, struct dsp_symbol_entry * symbol)
0031 {
0032 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0033 int symbol_index = (int)(symbol - ins->symbol_table.symbols);
0034
0035 if (snd_BUG_ON(ins->symbol_table.nsymbols <= 0))
0036 return;
0037 if (snd_BUG_ON(symbol_index < 0 ||
0038 symbol_index >= ins->symbol_table.nsymbols))
0039 return;
0040
0041 ins->symbol_table.symbols[symbol_index].deleted = 1;
0042
0043 if (symbol_index < ins->symbol_table.highest_frag_index) {
0044 ins->symbol_table.highest_frag_index = symbol_index;
0045 }
0046
0047 if (symbol_index == ins->symbol_table.nsymbols - 1)
0048 ins->symbol_table.nsymbols --;
0049
0050 if (ins->symbol_table.highest_frag_index > ins->symbol_table.nsymbols) {
0051 ins->symbol_table.highest_frag_index = ins->symbol_table.nsymbols;
0052 }
0053
0054 }
0055
0056 #ifdef CONFIG_SND_PROC_FS
0057 static void cs46xx_dsp_proc_scb_info_read (struct snd_info_entry *entry,
0058 struct snd_info_buffer *buffer)
0059 {
0060 struct proc_scb_info * scb_info = entry->private_data;
0061 struct dsp_scb_descriptor * scb = scb_info->scb_desc;
0062 struct snd_cs46xx *chip = scb_info->chip;
0063 int j,col;
0064 void __iomem *dst = chip->region.idx[1].remap_addr + DSP_PARAMETER_BYTE_OFFSET;
0065
0066 mutex_lock(&chip->spos_mutex);
0067 snd_iprintf(buffer,"%04x %s:\n",scb->address,scb->scb_name);
0068
0069 for (col = 0,j = 0;j < 0x10; j++,col++) {
0070 if (col == 4) {
0071 snd_iprintf(buffer,"\n");
0072 col = 0;
0073 }
0074 snd_iprintf(buffer,"%08x ",readl(dst + (scb->address + j) * sizeof(u32)));
0075 }
0076
0077 snd_iprintf(buffer,"\n");
0078
0079 if (scb->parent_scb_ptr != NULL) {
0080 snd_iprintf(buffer,"parent [%s:%04x] ",
0081 scb->parent_scb_ptr->scb_name,
0082 scb->parent_scb_ptr->address);
0083 } else snd_iprintf(buffer,"parent [none] ");
0084
0085 snd_iprintf(buffer,"sub_list_ptr [%s:%04x]\nnext_scb_ptr [%s:%04x] task_entry [%s:%04x]\n",
0086 scb->sub_list_ptr->scb_name,
0087 scb->sub_list_ptr->address,
0088 scb->next_scb_ptr->scb_name,
0089 scb->next_scb_ptr->address,
0090 scb->task_entry->symbol_name,
0091 scb->task_entry->address);
0092
0093 snd_iprintf(buffer,"index [%d] ref_count [%d]\n",scb->index,scb->ref_count);
0094 mutex_unlock(&chip->spos_mutex);
0095 }
0096 #endif
0097
0098 static void _dsp_unlink_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
0099 {
0100 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0101
0102 if ( scb->parent_scb_ptr ) {
0103
0104 if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr != scb &&
0105 scb->parent_scb_ptr->next_scb_ptr != scb))
0106 return;
0107
0108 if (scb->parent_scb_ptr->sub_list_ptr == scb) {
0109
0110 if (scb->next_scb_ptr == ins->the_null_scb) {
0111
0112 scb->parent_scb_ptr->sub_list_ptr = scb->sub_list_ptr;
0113
0114 if (scb->sub_list_ptr != ins->the_null_scb) {
0115 scb->sub_list_ptr->parent_scb_ptr = scb->parent_scb_ptr;
0116 }
0117 scb->sub_list_ptr = ins->the_null_scb;
0118 } else {
0119
0120 scb->parent_scb_ptr->sub_list_ptr = scb->next_scb_ptr;
0121
0122 if (scb->next_scb_ptr != ins->the_null_scb) {
0123
0124 scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;
0125 }
0126 scb->next_scb_ptr = ins->the_null_scb;
0127 }
0128 } else {
0129 scb->parent_scb_ptr->next_scb_ptr = scb->next_scb_ptr;
0130
0131 if (scb->next_scb_ptr != ins->the_null_scb) {
0132
0133 scb->next_scb_ptr->parent_scb_ptr = scb->parent_scb_ptr;
0134 }
0135 scb->next_scb_ptr = ins->the_null_scb;
0136 }
0137
0138
0139 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
0140
0141
0142 cs46xx_dsp_spos_update_scb(chip,scb);
0143
0144 scb->parent_scb_ptr = NULL;
0145 }
0146 }
0147
0148 static void _dsp_clear_sample_buffer (struct snd_cs46xx *chip, u32 sample_buffer_addr,
0149 int dword_count)
0150 {
0151 void __iomem *dst = chip->region.idx[2].remap_addr + sample_buffer_addr;
0152 int i;
0153
0154 for (i = 0; i < dword_count ; ++i ) {
0155 writel(0, dst);
0156 dst += 4;
0157 }
0158 }
0159
0160 void cs46xx_dsp_remove_scb (struct snd_cs46xx *chip, struct dsp_scb_descriptor * scb)
0161 {
0162 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0163 unsigned long flags;
0164
0165
0166 if (snd_BUG_ON(scb->index < 0 ||
0167 scb->index >= ins->nscb ||
0168 (ins->scbs + scb->index) != scb))
0169 return;
0170
0171 #if 0
0172
0173
0174 if (snd_BUG_ON(scb->sub_list_ptr != ins->the_null_scb ||
0175 scb->next_scb_ptr != ins->the_null_scb))
0176 goto _end;
0177 #endif
0178
0179 spin_lock_irqsave(&chip->reg_lock, flags);
0180 _dsp_unlink_scb (chip,scb);
0181 spin_unlock_irqrestore(&chip->reg_lock, flags);
0182
0183 cs46xx_dsp_proc_free_scb_desc(scb);
0184 if (snd_BUG_ON(!scb->scb_symbol))
0185 return;
0186 remove_symbol (chip,scb->scb_symbol);
0187
0188 ins->scbs[scb->index].deleted = 1;
0189 #ifdef CONFIG_PM_SLEEP
0190 kfree(ins->scbs[scb->index].data);
0191 ins->scbs[scb->index].data = NULL;
0192 #endif
0193
0194 if (scb->index < ins->scb_highest_frag_index)
0195 ins->scb_highest_frag_index = scb->index;
0196
0197 if (scb->index == ins->nscb - 1) {
0198 ins->nscb --;
0199 }
0200
0201 if (ins->scb_highest_frag_index > ins->nscb) {
0202 ins->scb_highest_frag_index = ins->nscb;
0203 }
0204
0205 #if 0
0206
0207 for(i = scb->index + 1;i < ins->nscb; ++i) {
0208 ins->scbs[i - 1].index = i - 1;
0209 }
0210 #endif
0211 }
0212
0213
0214 #ifdef CONFIG_SND_PROC_FS
0215 void cs46xx_dsp_proc_free_scb_desc (struct dsp_scb_descriptor * scb)
0216 {
0217 if (scb->proc_info) {
0218 struct proc_scb_info * scb_info = scb->proc_info->private_data;
0219 struct snd_cs46xx *chip = scb_info->chip;
0220
0221 dev_dbg(chip->card->dev,
0222 "cs46xx_dsp_proc_free_scb_desc: freeing %s\n",
0223 scb->scb_name);
0224
0225 snd_info_free_entry(scb->proc_info);
0226 scb->proc_info = NULL;
0227
0228 kfree (scb_info);
0229 }
0230 }
0231
0232 void cs46xx_dsp_proc_register_scb_desc (struct snd_cs46xx *chip,
0233 struct dsp_scb_descriptor * scb)
0234 {
0235 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0236 struct snd_info_entry * entry;
0237 struct proc_scb_info * scb_info;
0238
0239
0240 if (ins->snd_card != NULL && ins->proc_dsp_dir != NULL &&
0241 scb->proc_info == NULL) {
0242
0243 entry = snd_info_create_card_entry(ins->snd_card, scb->scb_name,
0244 ins->proc_dsp_dir);
0245 if (entry) {
0246 scb_info = kmalloc(sizeof(struct proc_scb_info), GFP_KERNEL);
0247 if (!scb_info) {
0248 snd_info_free_entry(entry);
0249 entry = NULL;
0250 goto out;
0251 }
0252
0253 scb_info->chip = chip;
0254 scb_info->scb_desc = scb;
0255 snd_info_set_text_ops(entry, scb_info,
0256 cs46xx_dsp_proc_scb_info_read);
0257 }
0258 out:
0259 scb->proc_info = entry;
0260 }
0261 }
0262 #endif
0263
0264 static struct dsp_scb_descriptor *
0265 _dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data, u32 dest,
0266 struct dsp_symbol_entry * task_entry,
0267 struct dsp_scb_descriptor * parent_scb,
0268 int scb_child_type)
0269 {
0270 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0271 struct dsp_scb_descriptor * scb;
0272
0273 unsigned long flags;
0274
0275 if (snd_BUG_ON(!ins->the_null_scb))
0276 return NULL;
0277
0278
0279 scb_data[SCBsubListPtr] =
0280 (ins->the_null_scb->address << 0x10) | ins->the_null_scb->address;
0281
0282 scb_data[SCBfuncEntryPtr] &= 0xFFFF0000;
0283 scb_data[SCBfuncEntryPtr] |= task_entry->address;
0284
0285 dev_dbg(chip->card->dev, "dsp_spos: creating SCB <%s>\n", name);
0286
0287 scb = cs46xx_dsp_create_scb(chip,name,scb_data,dest);
0288
0289
0290 scb->sub_list_ptr = ins->the_null_scb;
0291 scb->next_scb_ptr = ins->the_null_scb;
0292
0293 scb->parent_scb_ptr = parent_scb;
0294 scb->task_entry = task_entry;
0295
0296
0297
0298 if (scb->parent_scb_ptr) {
0299 #if 0
0300 dev_dbg(chip->card->dev,
0301 "scb->parent_scb_ptr = %s\n",
0302 scb->parent_scb_ptr->scb_name);
0303 dev_dbg(chip->card->dev,
0304 "scb->parent_scb_ptr->next_scb_ptr = %s\n",
0305 scb->parent_scb_ptr->next_scb_ptr->scb_name);
0306 dev_dbg(chip->card->dev,
0307 "scb->parent_scb_ptr->sub_list_ptr = %s\n",
0308 scb->parent_scb_ptr->sub_list_ptr->scb_name);
0309 #endif
0310
0311 if (scb_child_type == SCB_ON_PARENT_NEXT_SCB) {
0312 if (snd_BUG_ON(scb->parent_scb_ptr->next_scb_ptr !=
0313 ins->the_null_scb))
0314 return NULL;
0315
0316 scb->parent_scb_ptr->next_scb_ptr = scb;
0317
0318 } else if (scb_child_type == SCB_ON_PARENT_SUBLIST_SCB) {
0319 if (snd_BUG_ON(scb->parent_scb_ptr->sub_list_ptr !=
0320 ins->the_null_scb))
0321 return NULL;
0322
0323 scb->parent_scb_ptr->sub_list_ptr = scb;
0324 } else {
0325 snd_BUG();
0326 }
0327
0328 spin_lock_irqsave(&chip->reg_lock, flags);
0329
0330
0331 cs46xx_dsp_spos_update_scb(chip,scb->parent_scb_ptr);
0332
0333 spin_unlock_irqrestore(&chip->reg_lock, flags);
0334 }
0335
0336
0337 cs46xx_dsp_proc_register_scb_desc (chip,scb);
0338
0339 return scb;
0340 }
0341
0342 static struct dsp_scb_descriptor *
0343 cs46xx_dsp_create_generic_scb (struct snd_cs46xx *chip, char * name, u32 * scb_data,
0344 u32 dest, char * task_entry_name,
0345 struct dsp_scb_descriptor * parent_scb,
0346 int scb_child_type)
0347 {
0348 struct dsp_symbol_entry * task_entry;
0349
0350 task_entry = cs46xx_dsp_lookup_symbol (chip,task_entry_name,
0351 SYMBOL_CODE);
0352
0353 if (task_entry == NULL) {
0354 dev_err(chip->card->dev,
0355 "dsp_spos: symbol %s not found\n", task_entry_name);
0356 return NULL;
0357 }
0358
0359 return _dsp_create_generic_scb (chip,name,scb_data,dest,task_entry,
0360 parent_scb,scb_child_type);
0361 }
0362
0363 struct dsp_scb_descriptor *
0364 cs46xx_dsp_create_timing_master_scb (struct snd_cs46xx *chip)
0365 {
0366 struct dsp_scb_descriptor * scb;
0367
0368 struct dsp_timing_master_scb timing_master_scb = {
0369 { 0,
0370 0,
0371 0,
0372 0
0373 },
0374 { 0,
0375 0,
0376 0,
0377 0,
0378 0
0379 },
0380 0,0,
0381 0,NULL_SCB_ADDR,
0382 0,0,
0383 0,0,
0384 0x0001,0x8000,
0385 0x0001,0x0000,
0386 0x00060000
0387 };
0388
0389 scb = cs46xx_dsp_create_generic_scb(chip,"TimingMasterSCBInst",(u32 *)&timing_master_scb,
0390 TIMINGMASTER_SCB_ADDR,
0391 "TIMINGMASTER",NULL,SCB_NO_PARENT);
0392
0393 return scb;
0394 }
0395
0396
0397 struct dsp_scb_descriptor *
0398 cs46xx_dsp_create_codec_out_scb(struct snd_cs46xx * chip, char * codec_name,
0399 u16 channel_disp, u16 fifo_addr, u16 child_scb_addr,
0400 u32 dest, struct dsp_scb_descriptor * parent_scb,
0401 int scb_child_type)
0402 {
0403 struct dsp_scb_descriptor * scb;
0404
0405 struct dsp_codec_output_scb codec_out_scb = {
0406 { 0,
0407 0,
0408 0,
0409 0
0410 },
0411 {
0412 0,
0413 0,
0414 0,
0415 0,
0416 0
0417 },
0418 0,0,
0419 0,NULL_SCB_ADDR,
0420 0,
0421 0,
0422 channel_disp,fifo_addr,
0423 0x0000,0x0080,
0424 0,child_scb_addr
0425 };
0426
0427
0428 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_out_scb,
0429 dest,"S16_CODECOUTPUTTASK",parent_scb,
0430 scb_child_type);
0431
0432 return scb;
0433 }
0434
0435 struct dsp_scb_descriptor *
0436 cs46xx_dsp_create_codec_in_scb(struct snd_cs46xx * chip, char * codec_name,
0437 u16 channel_disp, u16 fifo_addr, u16 sample_buffer_addr,
0438 u32 dest, struct dsp_scb_descriptor * parent_scb,
0439 int scb_child_type)
0440 {
0441
0442 struct dsp_scb_descriptor * scb;
0443 struct dsp_codec_input_scb codec_input_scb = {
0444 { 0,
0445 0,
0446 0,
0447 0
0448 },
0449 {
0450 0,
0451 0,
0452 0,
0453 0,
0454 0
0455 },
0456
0457 #if 0
0458 SyncIOSCB,NULL_SCB_ADDR
0459 #else
0460 0 , 0,
0461 #endif
0462 0,0,
0463
0464 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
0465 sample_buffer_addr << 0x10,
0466 channel_disp,fifo_addr,
0467
0468 0x0000,0x0000,
0469
0470 0x80008000
0471 };
0472
0473 scb = cs46xx_dsp_create_generic_scb(chip,codec_name,(u32 *)&codec_input_scb,
0474 dest,"S16_CODECINPUTTASK",parent_scb,
0475 scb_child_type);
0476 return scb;
0477 }
0478
0479
0480 static struct dsp_scb_descriptor *
0481 cs46xx_dsp_create_pcm_reader_scb(struct snd_cs46xx * chip, char * scb_name,
0482 u16 sample_buffer_addr, u32 dest,
0483 int virtual_channel, u32 playback_hw_addr,
0484 struct dsp_scb_descriptor * parent_scb,
0485 int scb_child_type)
0486 {
0487 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0488 struct dsp_scb_descriptor * scb;
0489
0490 struct dsp_generic_scb pcm_reader_scb = {
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516 { DMA_RQ_C1_SOURCE_ON_HOST +
0517 DMA_RQ_C1_SOURCE_MOD1024 +
0518 DMA_RQ_C1_DEST_MOD32 +
0519 DMA_RQ_C1_WRITEBACK_SRC_FLAG +
0520 DMA_RQ_C1_WRITEBACK_DEST_FLAG +
0521 15,
0522
0523
0524 DMA_RQ_C2_AC_NONE +
0525 DMA_RQ_C2_SIGNAL_SOURCE_PINGPONG +
0526
0527 virtual_channel,
0528 playback_hw_addr,
0529 DMA_RQ_SD_SP_SAMPLE_ADDR +
0530 sample_buffer_addr
0531 },
0532
0533 {
0534 0,
0535 0,
0536 0,
0537 0,
0538 0
0539 },
0540
0541 NULL_SCB_ADDR,NULL_SCB_ADDR,
0542
0543 0,NULL_SCB_ADDR,
0544
0545
0546 RSCONFIG_DMA_ENABLE +
0547 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
0548
0549 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
0550 RSCONFIG_SAMPLE_16STEREO +
0551 RSCONFIG_MODULO_32,
0552
0553 (sample_buffer_addr << 0x10),
0554
0555 0,
0556 {
0557
0558
0559 0xffff,0xffff,
0560 0xffff,0xffff
0561 }
0562 };
0563
0564 if (ins->null_algorithm == NULL) {
0565 ins->null_algorithm = cs46xx_dsp_lookup_symbol (chip,"NULLALGORITHM",
0566 SYMBOL_CODE);
0567
0568 if (ins->null_algorithm == NULL) {
0569 dev_err(chip->card->dev,
0570 "dsp_spos: symbol NULLALGORITHM not found\n");
0571 return NULL;
0572 }
0573 }
0574
0575 scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_reader_scb,
0576 dest,ins->null_algorithm,parent_scb,
0577 scb_child_type);
0578
0579 return scb;
0580 }
0581
0582 #define GOF_PER_SEC 200
0583
0584 struct dsp_scb_descriptor *
0585 cs46xx_dsp_create_src_task_scb(struct snd_cs46xx * chip, char * scb_name,
0586 int rate,
0587 u16 src_buffer_addr,
0588 u16 src_delay_buffer_addr, u32 dest,
0589 struct dsp_scb_descriptor * parent_scb,
0590 int scb_child_type,
0591 int pass_through)
0592 {
0593
0594 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0595 struct dsp_scb_descriptor * scb;
0596 unsigned int tmp1, tmp2;
0597 unsigned int phiIncr;
0598 unsigned int correctionPerGOF, correctionPerSec;
0599
0600 dev_dbg(chip->card->dev, "dsp_spos: setting %s rate to %u\n",
0601 scb_name, rate);
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620 tmp1 = rate << 16;
0621 phiIncr = tmp1 / 48000;
0622 tmp1 -= phiIncr * 48000;
0623 tmp1 <<= 10;
0624 phiIncr <<= 10;
0625 tmp2 = tmp1 / 48000;
0626 phiIncr += tmp2;
0627 tmp1 -= tmp2 * 48000;
0628 correctionPerGOF = tmp1 / GOF_PER_SEC;
0629 tmp1 -= correctionPerGOF * GOF_PER_SEC;
0630 correctionPerSec = tmp1;
0631
0632 {
0633 struct dsp_src_task_scb src_task_scb = {
0634 0x0028,0x00c8,
0635 0x5555,0x0000,
0636 0x0000,0x0000,
0637 src_buffer_addr,1,
0638 correctionPerGOF,correctionPerSec,
0639 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
0640 0x0000,src_delay_buffer_addr,
0641 0x0,
0642 0x080,(src_delay_buffer_addr + (24 * 4)),
0643 0,0,
0644 0,0,
0645 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
0646 src_buffer_addr << 0x10,
0647 phiIncr,
0648 {
0649 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left,
0650 0xffff - ins->dac_volume_right,0xffff - ins->dac_volume_left
0651 }
0652 };
0653
0654 if (ins->s16_up == NULL) {
0655 ins->s16_up = cs46xx_dsp_lookup_symbol (chip,"S16_UPSRC",
0656 SYMBOL_CODE);
0657
0658 if (ins->s16_up == NULL) {
0659 dev_err(chip->card->dev,
0660 "dsp_spos: symbol S16_UPSRC not found\n");
0661 return NULL;
0662 }
0663 }
0664
0665
0666 _dsp_clear_sample_buffer (chip,src_buffer_addr,8);
0667 _dsp_clear_sample_buffer (chip,src_delay_buffer_addr,32);
0668
0669 if (pass_through) {
0670
0671
0672 snd_BUG_ON(rate != 48000);
0673
0674 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
0675 dest,"DMAREADER",parent_scb,
0676 scb_child_type);
0677 } else {
0678 scb = _dsp_create_generic_scb(chip,scb_name,(u32 *)&src_task_scb,
0679 dest,ins->s16_up,parent_scb,
0680 scb_child_type);
0681 }
0682
0683
0684 }
0685
0686 return scb;
0687 }
0688
0689 #if 0
0690 struct dsp_scb_descriptor *
0691 cs46xx_dsp_create_filter_scb(struct snd_cs46xx * chip, char * scb_name,
0692 u16 buffer_addr, u32 dest,
0693 struct dsp_scb_descriptor * parent_scb,
0694 int scb_child_type) {
0695 struct dsp_scb_descriptor * scb;
0696
0697 struct dsp_filter_scb filter_scb = {
0698 .a0_right = 0x41a9,
0699 .a0_left = 0x41a9,
0700 .a1_right = 0xb8e4,
0701 .a1_left = 0xb8e4,
0702 .a2_right = 0x3e55,
0703 .a2_left = 0x3e55,
0704
0705 .filter_unused3 = 0x0000,
0706 .filter_unused2 = 0x0000,
0707
0708 .output_buf_ptr = buffer_addr,
0709 .init = 0x000,
0710
0711 .prev_sample_output1 = 0x00000000,
0712 .prev_sample_output2 = 0x00000000,
0713
0714 .prev_sample_input1 = 0x00000000,
0715 .prev_sample_input2 = 0x00000000,
0716
0717 .next_scb_ptr = 0x0000,
0718 .sub_list_ptr = 0x0000,
0719
0720 .entry_point = 0x0000,
0721 .spb_ptr = 0x0000,
0722
0723 .b0_right = 0x0e38,
0724 .b0_left = 0x0e38,
0725 .b1_right = 0x1c71,
0726 .b1_left = 0x1c71,
0727 .b2_right = 0x0e38,
0728 .b2_left = 0x0e38,
0729 };
0730
0731
0732 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&filter_scb,
0733 dest,"FILTERTASK",parent_scb,
0734 scb_child_type);
0735
0736 return scb;
0737 }
0738 #endif
0739
0740 struct dsp_scb_descriptor *
0741 cs46xx_dsp_create_mix_only_scb(struct snd_cs46xx * chip, char * scb_name,
0742 u16 mix_buffer_addr, u32 dest,
0743 struct dsp_scb_descriptor * parent_scb,
0744 int scb_child_type)
0745 {
0746 struct dsp_scb_descriptor * scb;
0747
0748 struct dsp_mix_only_scb master_mix_scb = {
0749 { 0,
0750 0,
0751 mix_buffer_addr,
0752 0
0753 },
0754 {
0755 0,
0756 0,
0757 0,
0758 0,
0759 0x00000080
0760 },
0761 0,0,
0762 0,0,
0763 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_32,
0764 (mix_buffer_addr + (16 * 4)) << 0x10,
0765 0,
0766 {
0767 0x8000,0x8000,
0768 0x8000,0x8000
0769 }
0770 };
0771
0772
0773 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&master_mix_scb,
0774 dest,"S16_MIX",parent_scb,
0775 scb_child_type);
0776 return scb;
0777 }
0778
0779
0780 struct dsp_scb_descriptor *
0781 cs46xx_dsp_create_mix_to_ostream_scb(struct snd_cs46xx * chip, char * scb_name,
0782 u16 mix_buffer_addr, u16 writeback_spb, u32 dest,
0783 struct dsp_scb_descriptor * parent_scb,
0784 int scb_child_type)
0785 {
0786 struct dsp_scb_descriptor * scb;
0787
0788 struct dsp_mix2_ostream_scb mix2_ostream_scb = {
0789
0790 {
0791 DMA_RQ_C1_SOURCE_MOD64 +
0792 DMA_RQ_C1_DEST_ON_HOST +
0793 DMA_RQ_C1_DEST_MOD1024 +
0794 DMA_RQ_C1_WRITEBACK_SRC_FLAG +
0795 DMA_RQ_C1_WRITEBACK_DEST_FLAG +
0796 15,
0797
0798 DMA_RQ_C2_AC_NONE +
0799 DMA_RQ_C2_SIGNAL_DEST_PINGPONG +
0800
0801 CS46XX_DSP_CAPTURE_CHANNEL,
0802 DMA_RQ_SD_SP_SAMPLE_ADDR +
0803 mix_buffer_addr,
0804 0x0
0805 },
0806
0807 { 0, 0, 0, 0, 0, },
0808 0,0,
0809 0,writeback_spb,
0810
0811 RSCONFIG_DMA_ENABLE +
0812 (19 << RSCONFIG_MAX_DMA_SIZE_SHIFT) +
0813
0814 ((dest >> 4) << RSCONFIG_STREAM_NUM_SHIFT) +
0815 RSCONFIG_DMA_TO_HOST +
0816 RSCONFIG_SAMPLE_16STEREO +
0817 RSCONFIG_MODULO_64,
0818 (mix_buffer_addr + (32 * 4)) << 0x10,
0819 1,0,
0820 0x0001,0x0080,
0821 0xFFFF,0
0822 };
0823
0824
0825 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&mix2_ostream_scb,
0826
0827 dest,"S16_MIX_TO_OSTREAM",parent_scb,
0828 scb_child_type);
0829
0830 return scb;
0831 }
0832
0833
0834 struct dsp_scb_descriptor *
0835 cs46xx_dsp_create_vari_decimate_scb(struct snd_cs46xx * chip,char * scb_name,
0836 u16 vari_buffer_addr0,
0837 u16 vari_buffer_addr1,
0838 u32 dest,
0839 struct dsp_scb_descriptor * parent_scb,
0840 int scb_child_type)
0841 {
0842
0843 struct dsp_scb_descriptor * scb;
0844
0845 struct dsp_vari_decimate_scb vari_decimate_scb = {
0846 0x0028,0x00c8,
0847 0x5555,0x0000,
0848 0x0000,0x0000,
0849 vari_buffer_addr0,vari_buffer_addr1,
0850
0851 0x0028,0x00c8,
0852 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256,
0853
0854 0xFF800000,
0855 0,
0856 0x0080,vari_buffer_addr1 + (25 * 4),
0857
0858 0,0,
0859 0,0,
0860
0861 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_8,
0862 vari_buffer_addr0 << 0x10,
0863 0x04000000,
0864 {
0865 0x8000,0x8000,
0866 0xFFFF,0xFFFF
0867 }
0868 };
0869
0870 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&vari_decimate_scb,
0871 dest,"VARIDECIMATE",parent_scb,
0872 scb_child_type);
0873
0874 return scb;
0875 }
0876
0877
0878 static struct dsp_scb_descriptor *
0879 cs46xx_dsp_create_pcm_serial_input_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
0880 struct dsp_scb_descriptor * input_scb,
0881 struct dsp_scb_descriptor * parent_scb,
0882 int scb_child_type)
0883 {
0884
0885 struct dsp_scb_descriptor * scb;
0886
0887
0888 struct dsp_pcm_serial_input_scb pcm_serial_input_scb = {
0889 { 0,
0890 0,
0891 0,
0892 0
0893 },
0894 {
0895 0,
0896 0,
0897 0,
0898 0,
0899 0
0900 },
0901
0902 0,0,
0903 0,0,
0904
0905 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_16,
0906 0,
0907 0,input_scb->address,
0908 {
0909 0x8000,0x8000,
0910 0x8000,0x8000
0911 }
0912 };
0913
0914 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&pcm_serial_input_scb,
0915 dest,"PCMSERIALINPUTTASK",parent_scb,
0916 scb_child_type);
0917 return scb;
0918 }
0919
0920
0921 static struct dsp_scb_descriptor *
0922 cs46xx_dsp_create_asynch_fg_tx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
0923 u16 hfg_scb_address,
0924 u16 asynch_buffer_address,
0925 struct dsp_scb_descriptor * parent_scb,
0926 int scb_child_type)
0927 {
0928
0929 struct dsp_scb_descriptor * scb;
0930
0931 struct dsp_asynch_fg_tx_scb asynch_fg_tx_scb = {
0932 0xfc00,0x03ff,
0933 0x0058,0x0028,
0934
0935 0,hfg_scb_address,
0936 0,0,
0937 0,
0938 0,0x2aab,
0939
0940 {
0941 0,
0942 0,
0943 0
0944 },
0945
0946 0,0,
0947 0,dest + AFGTxAccumPhi,
0948
0949 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_256,
0950 (asynch_buffer_address) << 0x10,
0951
0952
0953
0954
0955 0x18000000,
0956 0x8000,0x8000,
0957 0x8000,0x8000
0958 };
0959
0960 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_tx_scb,
0961 dest,"ASYNCHFGTXCODE",parent_scb,
0962 scb_child_type);
0963
0964 return scb;
0965 }
0966
0967
0968 struct dsp_scb_descriptor *
0969 cs46xx_dsp_create_asynch_fg_rx_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
0970 u16 hfg_scb_address,
0971 u16 asynch_buffer_address,
0972 struct dsp_scb_descriptor * parent_scb,
0973 int scb_child_type)
0974 {
0975 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
0976 struct dsp_scb_descriptor * scb;
0977
0978 struct dsp_asynch_fg_rx_scb asynch_fg_rx_scb = {
0979 0xfe00,0x01ff,
0980 0x0064,0x001c,
0981
0982 0,hfg_scb_address,
0983 0,0,
0984 {
0985 0,
0986 0,
0987 0,
0988 0,
0989 0
0990 },
0991
0992 0,0,
0993 0,dest,
0994
0995 RSCONFIG_MODULO_128 |
0996 RSCONFIG_SAMPLE_16STEREO,
0997 ( (asynch_buffer_address + (16 * 4)) << 0x10),
0998
0999
1000
1001
1002 0x18000000,
1003
1004
1005 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
1006 0xffff - ins->spdif_input_volume_right,0xffff - ins->spdif_input_volume_left,
1007 };
1008
1009 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&asynch_fg_rx_scb,
1010 dest,"ASYNCHFGRXCODE",parent_scb,
1011 scb_child_type);
1012
1013 return scb;
1014 }
1015
1016
1017 #if 0
1018 struct dsp_scb_descriptor *
1019 cs46xx_dsp_create_output_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1020 u16 snoop_buffer_address,
1021 struct dsp_scb_descriptor * snoop_scb,
1022 struct dsp_scb_descriptor * parent_scb,
1023 int scb_child_type)
1024 {
1025
1026 struct dsp_scb_descriptor * scb;
1027
1028 struct dsp_output_snoop_scb output_snoop_scb = {
1029 { 0,
1030 0,
1031 0,
1032 0,
1033 },
1034 {
1035 0,
1036 0,
1037 0,
1038 0,
1039 0
1040 },
1041
1042 0,0,
1043 0,0,
1044
1045 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1046 snoop_buffer_address << 0x10,
1047 0,0,
1048 0,
1049 0,snoop_scb->address
1050 };
1051
1052 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&output_snoop_scb,
1053 dest,"OUTPUTSNOOP",parent_scb,
1054 scb_child_type);
1055 return scb;
1056 }
1057 #endif
1058
1059
1060 struct dsp_scb_descriptor *
1061 cs46xx_dsp_create_spio_write_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1062 struct dsp_scb_descriptor * parent_scb,
1063 int scb_child_type)
1064 {
1065 struct dsp_scb_descriptor * scb;
1066
1067 struct dsp_spio_write_scb spio_write_scb = {
1068 0,0,
1069 0,
1070 0,
1071 0,0,
1072 0,
1073 0,
1074 0,0,
1075 { 0,0 },
1076
1077 0,0,
1078 0,0,
1079
1080 {
1081 0,
1082 0,
1083 0,
1084 0,
1085 0
1086 }
1087 };
1088
1089 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&spio_write_scb,
1090 dest,"SPIOWRITE",parent_scb,
1091 scb_child_type);
1092
1093 return scb;
1094 }
1095
1096 struct dsp_scb_descriptor *
1097 cs46xx_dsp_create_magic_snoop_scb(struct snd_cs46xx * chip, char * scb_name, u32 dest,
1098 u16 snoop_buffer_address,
1099 struct dsp_scb_descriptor * snoop_scb,
1100 struct dsp_scb_descriptor * parent_scb,
1101 int scb_child_type)
1102 {
1103 struct dsp_scb_descriptor * scb;
1104
1105 struct dsp_magic_snoop_task magic_snoop_scb = {
1106 0,
1107 0,
1108 snoop_buffer_address << 0x10,
1109 0,snoop_scb->address,
1110 0,
1111 0,
1112 0,
1113 0,
1114 0,
1115 0,0,
1116 0,0,
1117 RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,
1118 snoop_buffer_address << 0x10,
1119 0,
1120 { 0x8000,0x8000,
1121 0xffff,0xffff
1122 }
1123 };
1124
1125 scb = cs46xx_dsp_create_generic_scb(chip,scb_name,(u32 *)&magic_snoop_scb,
1126 dest,"MAGICSNOOPTASK",parent_scb,
1127 scb_child_type);
1128
1129 return scb;
1130 }
1131
1132 static struct dsp_scb_descriptor *
1133 find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from)
1134 {
1135 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1136 struct dsp_scb_descriptor * scb = from;
1137
1138 while (scb->next_scb_ptr != ins->the_null_scb) {
1139 if (snd_BUG_ON(!scb->next_scb_ptr))
1140 return NULL;
1141
1142 scb = scb->next_scb_ptr;
1143 }
1144
1145 return scb;
1146 }
1147
1148 static const u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = {
1149 0x0600,
1150 0x1500,
1151 0x1580,
1152 0x1600,
1153 0x1680,
1154 0x1700,
1155 0x1780,
1156 0x1800,
1157 0x1880,
1158 0x1900,
1159 0x1980,
1160 0x1A00,
1161 0x1A80,
1162 0x1B00,
1163 0x1B80,
1164 0x1C00,
1165 0x1C80,
1166 0x1D00,
1167 0x1D80,
1168 0x1E00,
1169 0x1E80,
1170 0x1F00,
1171 0x1F80,
1172 0x2000,
1173 0x2080,
1174 0x2100,
1175 0x2180,
1176 0x2200,
1177 0x2280,
1178 0x2300,
1179 0x2380,
1180 0x2400,
1181 };
1182
1183 static const u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = {
1184 0x2B80,
1185 0x2BA0,
1186 0x2BC0,
1187 0x2BE0,
1188 0x2D00,
1189 0x2D20,
1190 0x2D40,
1191 0x2D60,
1192 0x2D80,
1193 0x2DA0,
1194 0x2DC0,
1195 0x2DE0,
1196 0x2E00,
1197 0x2E20
1198 };
1199
1200 static const u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
1201 0x2480,
1202 0x2500,
1203 0x2580,
1204 0x2600,
1205 0x2680,
1206 0x2700,
1207 0x2780,
1208 0x2800,
1209 0x2880,
1210 0x2900,
1211 0x2980,
1212 0x2A00,
1213 0x2A80,
1214 0x2B00
1215 };
1216
1217 struct dsp_pcm_channel_descriptor *
1218 cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip,
1219 u32 sample_rate, void * private_data,
1220 u32 hw_dma_addr,
1221 int pcm_channel_id)
1222 {
1223 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1224 struct dsp_scb_descriptor * src_scb = NULL, * pcm_scb, * mixer_scb = NULL;
1225 struct dsp_scb_descriptor * src_parent_scb = NULL;
1226
1227
1228 char scb_name[DSP_MAX_SCB_NAME];
1229 int i, pcm_index = -1, insert_point, src_index = -1, pass_through = 0;
1230 unsigned long flags;
1231
1232 switch (pcm_channel_id) {
1233 case DSP_PCM_MAIN_CHANNEL:
1234 mixer_scb = ins->master_mix_scb;
1235 break;
1236 case DSP_PCM_REAR_CHANNEL:
1237 mixer_scb = ins->rear_mix_scb;
1238 break;
1239 case DSP_PCM_CENTER_LFE_CHANNEL:
1240 mixer_scb = ins->center_lfe_mix_scb;
1241 break;
1242 case DSP_PCM_S71_CHANNEL:
1243
1244 snd_BUG();
1245 break;
1246 case DSP_IEC958_CHANNEL:
1247 if (snd_BUG_ON(!ins->asynch_tx_scb))
1248 return NULL;
1249 mixer_scb = ins->asynch_tx_scb;
1250
1251
1252
1253
1254 if (sample_rate == 48000) {
1255 dev_dbg(chip->card->dev, "IEC958 pass through\n");
1256
1257 pass_through = 1;
1258 }
1259 break;
1260 default:
1261 snd_BUG();
1262 return NULL;
1263 }
1264
1265 if (!sample_rate) sample_rate = 44100;
1266
1267
1268 for (i = 0; i < DSP_MAX_PCM_CHANNELS &&
1269 (pcm_index == -1 || src_scb == NULL); ++i) {
1270
1271
1272
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 dev_err(chip->card->dev, "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 dev_err(chip->card->dev,
1296 "dsp_spos: too many SRC instances\n!");
1297 return NULL;
1298 }
1299
1300
1301 for (i = 0; i < DSP_MAX_SRC_NR; ++i) {
1302 if (ins->src_scb_slots[i] == 0) {
1303 src_index = i;
1304 ins->src_scb_slots[i] = 1;
1305 break;
1306 }
1307 }
1308 if (snd_BUG_ON(src_index == -1))
1309 return NULL;
1310
1311
1312 if (mixer_scb->sub_list_ptr == ins->the_null_scb) {
1313 src_parent_scb = mixer_scb;
1314 insert_point = SCB_ON_PARENT_SUBLIST_SCB;
1315 } else {
1316 src_parent_scb = find_next_free_scb(chip,mixer_scb->sub_list_ptr);
1317 insert_point = SCB_ON_PARENT_NEXT_SCB;
1318 }
1319
1320 snprintf (scb_name,DSP_MAX_SCB_NAME,"SrcTask_SCB%d",src_index);
1321
1322 dev_dbg(chip->card->dev,
1323 "dsp_spos: creating SRC \"%s\"\n", scb_name);
1324 src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name,
1325 sample_rate,
1326 src_output_buffer_addr[src_index],
1327 src_delay_buffer_addr[src_index],
1328
1329 0x400 + (src_index * 0x10) ,
1330 src_parent_scb,
1331 insert_point,
1332 pass_through);
1333
1334 if (!src_scb) {
1335 dev_err(chip->card->dev,
1336 "dsp_spos: failed to create SRCtaskSCB\n");
1337 return NULL;
1338 }
1339
1340
1341
1342 ins->nsrc_scb ++;
1343 }
1344
1345
1346 snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index);
1347
1348 dev_dbg(chip->card->dev, "dsp_spos: creating PCM \"%s\" (%d)\n",
1349 scb_name, pcm_channel_id);
1350
1351 pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name,
1352 pcm_reader_buffer_addr[pcm_index],
1353
1354 (pcm_index * 0x10) + 0x200,
1355 pcm_index,
1356 hw_dma_addr,
1357 NULL,
1358 0
1359 );
1360
1361 if (!pcm_scb) {
1362 dev_err(chip->card->dev,
1363 "dsp_spos: failed to create PCMreaderSCB\n");
1364 return NULL;
1365 }
1366
1367 spin_lock_irqsave(&chip->reg_lock, flags);
1368 ins->pcm_channels[pcm_index].sample_rate = sample_rate;
1369 ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb;
1370 ins->pcm_channels[pcm_index].src_scb = src_scb;
1371 ins->pcm_channels[pcm_index].unlinked = 1;
1372 ins->pcm_channels[pcm_index].private_data = private_data;
1373 ins->pcm_channels[pcm_index].src_slot = src_index;
1374 ins->pcm_channels[pcm_index].active = 1;
1375 ins->pcm_channels[pcm_index].pcm_slot = pcm_index;
1376 ins->pcm_channels[pcm_index].mixer_scb = mixer_scb;
1377 ins->npcm_channels ++;
1378 spin_unlock_irqrestore(&chip->reg_lock, flags);
1379
1380 return (ins->pcm_channels + pcm_index);
1381 }
1382
1383 int cs46xx_dsp_pcm_channel_set_period (struct snd_cs46xx * chip,
1384 struct dsp_pcm_channel_descriptor * pcm_channel,
1385 int period_size)
1386 {
1387 u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2);
1388 temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK;
1389
1390 switch (period_size) {
1391 case 2048:
1392 temp |= DMA_RQ_C1_SOURCE_MOD1024;
1393 break;
1394 case 1024:
1395 temp |= DMA_RQ_C1_SOURCE_MOD512;
1396 break;
1397 case 512:
1398 temp |= DMA_RQ_C1_SOURCE_MOD256;
1399 break;
1400 case 256:
1401 temp |= DMA_RQ_C1_SOURCE_MOD128;
1402 break;
1403 case 128:
1404 temp |= DMA_RQ_C1_SOURCE_MOD64;
1405 break;
1406 case 64:
1407 temp |= DMA_RQ_C1_SOURCE_MOD32;
1408 break;
1409 case 32:
1410 temp |= DMA_RQ_C1_SOURCE_MOD16;
1411 break;
1412 default:
1413 dev_dbg(chip->card->dev,
1414 "period size (%d) not supported by HW\n", period_size);
1415 return -EINVAL;
1416 }
1417
1418 snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp);
1419
1420 return 0;
1421 }
1422
1423 int cs46xx_dsp_pcm_ostream_set_period (struct snd_cs46xx * chip,
1424 int period_size)
1425 {
1426 u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2);
1427 temp &= ~DMA_RQ_C1_DEST_SIZE_MASK;
1428
1429 switch (period_size) {
1430 case 2048:
1431 temp |= DMA_RQ_C1_DEST_MOD1024;
1432 break;
1433 case 1024:
1434 temp |= DMA_RQ_C1_DEST_MOD512;
1435 break;
1436 case 512:
1437 temp |= DMA_RQ_C1_DEST_MOD256;
1438 break;
1439 case 256:
1440 temp |= DMA_RQ_C1_DEST_MOD128;
1441 break;
1442 case 128:
1443 temp |= DMA_RQ_C1_DEST_MOD64;
1444 break;
1445 case 64:
1446 temp |= DMA_RQ_C1_DEST_MOD32;
1447 break;
1448 case 32:
1449 temp |= DMA_RQ_C1_DEST_MOD16;
1450 break;
1451 default:
1452 dev_dbg(chip->card->dev,
1453 "period size (%d) not supported by HW\n", period_size);
1454 return -EINVAL;
1455 }
1456
1457 snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp);
1458
1459 return 0;
1460 }
1461
1462 void cs46xx_dsp_destroy_pcm_channel (struct snd_cs46xx * chip,
1463 struct dsp_pcm_channel_descriptor * pcm_channel)
1464 {
1465 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1466 unsigned long flags;
1467
1468 if (snd_BUG_ON(!pcm_channel->active ||
1469 ins->npcm_channels <= 0 ||
1470 pcm_channel->src_scb->ref_count <= 0))
1471 return;
1472
1473 spin_lock_irqsave(&chip->reg_lock, flags);
1474 pcm_channel->unlinked = 1;
1475 pcm_channel->active = 0;
1476 pcm_channel->private_data = NULL;
1477 pcm_channel->src_scb->ref_count --;
1478 ins->npcm_channels --;
1479 spin_unlock_irqrestore(&chip->reg_lock, flags);
1480
1481 cs46xx_dsp_remove_scb(chip,pcm_channel->pcm_reader_scb);
1482
1483 if (!pcm_channel->src_scb->ref_count) {
1484 cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb);
1485
1486 if (snd_BUG_ON(pcm_channel->src_slot < 0 ||
1487 pcm_channel->src_slot >= DSP_MAX_SRC_NR))
1488 return;
1489
1490 ins->src_scb_slots[pcm_channel->src_slot] = 0;
1491 ins->nsrc_scb --;
1492 }
1493 }
1494
1495 int cs46xx_dsp_pcm_unlink (struct snd_cs46xx * chip,
1496 struct dsp_pcm_channel_descriptor * pcm_channel)
1497 {
1498 unsigned long flags;
1499
1500 if (snd_BUG_ON(!pcm_channel->active ||
1501 chip->dsp_spos_instance->npcm_channels <= 0))
1502 return -EIO;
1503
1504 spin_lock_irqsave(&chip->reg_lock, flags);
1505 if (pcm_channel->unlinked) {
1506 spin_unlock_irqrestore(&chip->reg_lock, flags);
1507 return -EIO;
1508 }
1509
1510 pcm_channel->unlinked = 1;
1511
1512 _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb);
1513 spin_unlock_irqrestore(&chip->reg_lock, flags);
1514
1515 return 0;
1516 }
1517
1518 int cs46xx_dsp_pcm_link (struct snd_cs46xx * chip,
1519 struct dsp_pcm_channel_descriptor * pcm_channel)
1520 {
1521 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1522 struct dsp_scb_descriptor * parent_scb;
1523 struct dsp_scb_descriptor * src_scb = pcm_channel->src_scb;
1524 unsigned long flags;
1525
1526 spin_lock_irqsave(&chip->reg_lock, flags);
1527
1528 if (pcm_channel->unlinked == 0) {
1529 spin_unlock_irqrestore(&chip->reg_lock, flags);
1530 return -EIO;
1531 }
1532
1533 parent_scb = src_scb;
1534
1535 if (src_scb->sub_list_ptr != ins->the_null_scb) {
1536 src_scb->sub_list_ptr->parent_scb_ptr = pcm_channel->pcm_reader_scb;
1537 pcm_channel->pcm_reader_scb->next_scb_ptr = src_scb->sub_list_ptr;
1538 }
1539
1540 src_scb->sub_list_ptr = pcm_channel->pcm_reader_scb;
1541
1542 snd_BUG_ON(pcm_channel->pcm_reader_scb->parent_scb_ptr);
1543 pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb;
1544
1545
1546 cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb);
1547
1548
1549 cs46xx_dsp_spos_update_scb(chip,parent_scb);
1550
1551 pcm_channel->unlinked = 0;
1552 spin_unlock_irqrestore(&chip->reg_lock, flags);
1553 return 0;
1554 }
1555
1556 struct dsp_scb_descriptor *
1557 cs46xx_add_record_source (struct snd_cs46xx *chip, struct dsp_scb_descriptor * source,
1558 u16 addr, char * scb_name)
1559 {
1560 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1561 struct dsp_scb_descriptor * parent;
1562 struct dsp_scb_descriptor * pcm_input;
1563 int insert_point;
1564
1565 if (snd_BUG_ON(!ins->record_mixer_scb))
1566 return NULL;
1567
1568 if (ins->record_mixer_scb->sub_list_ptr != ins->the_null_scb) {
1569 parent = find_next_free_scb (chip,ins->record_mixer_scb->sub_list_ptr);
1570 insert_point = SCB_ON_PARENT_NEXT_SCB;
1571 } else {
1572 parent = ins->record_mixer_scb;
1573 insert_point = SCB_ON_PARENT_SUBLIST_SCB;
1574 }
1575
1576 pcm_input = cs46xx_dsp_create_pcm_serial_input_scb(chip,scb_name,addr,
1577 source, parent,
1578 insert_point);
1579
1580 return pcm_input;
1581 }
1582
1583 int cs46xx_src_unlink(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
1584 {
1585 unsigned long flags;
1586
1587 if (snd_BUG_ON(!src->parent_scb_ptr))
1588 return -EINVAL;
1589
1590
1591 cs46xx_dsp_scb_set_volume (chip,src,0,0);
1592
1593 spin_lock_irqsave(&chip->reg_lock, flags);
1594 _dsp_unlink_scb (chip,src);
1595 spin_unlock_irqrestore(&chip->reg_lock, flags);
1596
1597 return 0;
1598 }
1599
1600 int cs46xx_src_link(struct snd_cs46xx *chip, struct dsp_scb_descriptor * src)
1601 {
1602 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1603 struct dsp_scb_descriptor * parent_scb;
1604
1605 if (snd_BUG_ON(src->parent_scb_ptr))
1606 return -EINVAL;
1607 if (snd_BUG_ON(!ins->master_mix_scb))
1608 return -EINVAL;
1609
1610 if (ins->master_mix_scb->sub_list_ptr != ins->the_null_scb) {
1611 parent_scb = find_next_free_scb (chip,ins->master_mix_scb->sub_list_ptr);
1612 parent_scb->next_scb_ptr = src;
1613 } else {
1614 parent_scb = ins->master_mix_scb;
1615 parent_scb->sub_list_ptr = src;
1616 }
1617
1618 src->parent_scb_ptr = parent_scb;
1619
1620
1621 cs46xx_dsp_spos_update_scb(chip,parent_scb);
1622
1623 return 0;
1624 }
1625
1626 int cs46xx_dsp_enable_spdif_out (struct snd_cs46xx *chip)
1627 {
1628 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1629
1630 if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
1631 cs46xx_dsp_enable_spdif_hw (chip);
1632 }
1633
1634
1635 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
1636
1637
1638
1639 ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1640
1641 return -EBUSY;
1642 }
1643
1644 if (snd_BUG_ON(ins->asynch_tx_scb))
1645 return -EINVAL;
1646 if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr !=
1647 ins->the_null_scb))
1648 return -EINVAL;
1649
1650
1651 snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2,
1652 (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 );
1653
1654
1655 ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1656 SPDIFO_SCB_INST,
1657 SPDIFO_IP_OUTPUT_BUFFER1,
1658 ins->master_mix_scb,
1659 SCB_ON_PARENT_NEXT_SCB);
1660 if (!ins->asynch_tx_scb) return -ENOMEM;
1661
1662 ins->spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II",
1663 PCMSERIALINII_SCB_ADDR,
1664 ins->ref_snoop_scb,
1665 ins->asynch_tx_scb,
1666 SCB_ON_PARENT_SUBLIST_SCB);
1667
1668
1669 if (!ins->spdif_pcm_input_scb) return -ENOMEM;
1670
1671
1672 ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1673
1674 return 0;
1675 }
1676
1677 int cs46xx_dsp_disable_spdif_out (struct snd_cs46xx *chip)
1678 {
1679 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1680
1681
1682 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) {
1683 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1684 return -EBUSY;
1685 }
1686
1687
1688 if (snd_BUG_ON(!ins->asynch_tx_scb))
1689 return -EINVAL;
1690 if (snd_BUG_ON(!ins->spdif_pcm_input_scb))
1691 return -EINVAL;
1692 if (snd_BUG_ON(ins->master_mix_scb->next_scb_ptr != ins->asynch_tx_scb))
1693 return -EINVAL;
1694 if (snd_BUG_ON(ins->asynch_tx_scb->parent_scb_ptr !=
1695 ins->master_mix_scb))
1696 return -EINVAL;
1697
1698 cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
1699 cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
1700
1701 ins->spdif_pcm_input_scb = NULL;
1702 ins->asynch_tx_scb = NULL;
1703
1704
1705 _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
1706
1707
1708 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1709
1710
1711 return 0;
1712 }
1713
1714 int cs46xx_iec958_pre_open (struct snd_cs46xx *chip)
1715 {
1716 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1717
1718 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
1719
1720 cs46xx_dsp_disable_spdif_out (chip);
1721
1722
1723 ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED;
1724 }
1725
1726
1727 if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) {
1728 cs46xx_dsp_enable_spdif_hw (chip);
1729 }
1730
1731
1732 ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR,
1733 SPDIFO_SCB_INST,
1734 SPDIFO_IP_OUTPUT_BUFFER1,
1735 ins->master_mix_scb,
1736 SCB_ON_PARENT_NEXT_SCB);
1737
1738
1739
1740 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_stream);
1741
1742 ins->spdif_status_out |= DSP_SPDIF_STATUS_PLAYBACK_OPEN;
1743
1744 return 0;
1745 }
1746
1747 int cs46xx_iec958_post_close (struct snd_cs46xx *chip)
1748 {
1749 struct dsp_spos_instance * ins = chip->dsp_spos_instance;
1750
1751 if (snd_BUG_ON(!ins->asynch_tx_scb))
1752 return -EINVAL;
1753
1754 ins->spdif_status_out &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN;
1755
1756
1757 cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);
1758
1759
1760 if (ins->spdif_pcm_input_scb != NULL) {
1761 cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb);
1762 ins->spdif_pcm_input_scb = NULL;
1763 }
1764
1765 cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb);
1766 ins->asynch_tx_scb = NULL;
1767
1768
1769 _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256);
1770
1771
1772 if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) {
1773 cs46xx_dsp_enable_spdif_out (chip);
1774 }
1775
1776 return 0;
1777 }