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