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