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