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