📄 dsp_spos.c
字号:
dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * desc = NULL; int index; if (ins->nscb == DSP_MAX_SCB_DESC - 1) { snd_printk(KERN_ERR "dsp_spos: got no place for other SCB\n"); return NULL; } index = find_free_scb_index (ins); strcpy(ins->scbs[index].scb_name, name); ins->scbs[index].address = dest; ins->scbs[index].index = index; ins->scbs[index].proc_info = NULL; ins->scbs[index].ref_count = 1; ins->scbs[index].deleted = 0; spin_lock_init(&ins->scbs[index].lock); desc = (ins->scbs + index); ins->scbs[index].scb_symbol = add_symbol (chip, name, dest, SYMBOL_PARAMETER); if (index > ins->scb_highest_frag_index) ins->scb_highest_frag_index = index; if (index == ins->nscb) ins->nscb++; return desc;}static dsp_task_descriptor_t * _map_task_tree (cs46xx_t *chip,char * name,u32 dest,u32 size){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_task_descriptor_t * desc = NULL; if (ins->ntask == DSP_MAX_TASK_DESC - 1) { snd_printk(KERN_ERR "dsp_spos: got no place for other TASK\n"); return NULL; } strcpy(ins->tasks[ins->ntask].task_name,name); ins->tasks[ins->ntask].address = dest; ins->tasks[ins->ntask].size = size; /* quick find in list */ ins->tasks[ins->ntask].index = ins->ntask; desc = (ins->tasks + ins->ntask); ins->ntask++; add_symbol (chip,name,dest,SYMBOL_PARAMETER); return desc;}dsp_scb_descriptor_t * cs46xx_dsp_create_scb (cs46xx_t *chip,char * name, u32 * scb_data,u32 dest){ dsp_scb_descriptor_t * desc; desc = _map_scb (chip,name,dest); if (desc) { _dsp_create_scb(chip,scb_data,dest); } else { snd_printk(KERN_ERR "dsp_spos: failed to map SCB\n"); } return desc;}static dsp_task_descriptor_t * cs46xx_dsp_create_task_tree (cs46xx_t *chip,char * name, u32 * task_data,u32 dest,int size){ dsp_task_descriptor_t * desc; desc = _map_task_tree (chip,name,dest,size); if (desc) { _dsp_create_task_tree(chip,task_data,dest,size); } else { snd_printk(KERN_ERR "dsp_spos: failed to map TASK\n"); } return desc;}int cs46xx_dsp_scb_and_task_init (cs46xx_t *chip){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; symbol_entry_t * fg_task_tree_header_code; symbol_entry_t * task_tree_header_code; symbol_entry_t * task_tree_thread; symbol_entry_t * null_algorithm; symbol_entry_t * magic_snoop_task; dsp_scb_descriptor_t * timing_master_scb; dsp_scb_descriptor_t * codec_out_scb; dsp_scb_descriptor_t * codec_in_scb; dsp_scb_descriptor_t * src_task_scb; dsp_scb_descriptor_t * master_mix_scb; dsp_scb_descriptor_t * rear_mix_scb; dsp_scb_descriptor_t * record_mix_scb; dsp_scb_descriptor_t * write_back_scb; dsp_scb_descriptor_t * vari_decimate_scb; dsp_scb_descriptor_t * rear_codec_out_scb; dsp_scb_descriptor_t * clfe_codec_out_scb; dsp_scb_descriptor_t * magic_snoop_scb; int fifo_addr,fifo_span,valid_slots; static spos_control_block_t sposcb = { /* 0 */ HFG_TREE_SCB,HFG_STACK, /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR, /* 2 */ DSP_SPOS_DC,0, /* 3 */ DSP_SPOS_DC,DSP_SPOS_DC, /* 4 */ 0,0, /* 5 */ DSP_SPOS_UU,0, /* 6 */ FG_TASK_HEADER_ADDR,0, /* 7 */ 0,0, /* 8 */ DSP_SPOS_UU,DSP_SPOS_DC, /* 9 */ 0, /* A */ 0,HFG_FIRST_EXECUTE_MODE, /* B */ DSP_SPOS_UU,DSP_SPOS_UU, /* C */ DSP_SPOS_DC_DC, /* D */ DSP_SPOS_DC_DC, /* E */ DSP_SPOS_DC_DC, /* F */ DSP_SPOS_DC_DC }; cs46xx_dsp_create_task_tree(chip, "sposCB", (u32 *)&sposcb, SPOSCB_ADDR, 0x10); null_algorithm = cs46xx_dsp_lookup_symbol(chip, "NULLALGORITHM", SYMBOL_CODE); if (null_algorithm == NULL) { snd_printk(KERN_ERR "dsp_spos: symbol NULLALGORITHM not found\n"); return -EIO; } fg_task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "FGTASKTREEHEADERCODE", SYMBOL_CODE); if (fg_task_tree_header_code == NULL) { snd_printk(KERN_ERR "dsp_spos: symbol FGTASKTREEHEADERCODE not found\n"); return -EIO; } task_tree_header_code = cs46xx_dsp_lookup_symbol(chip, "TASKTREEHEADERCODE", SYMBOL_CODE); if (task_tree_header_code == NULL) { snd_printk(KERN_ERR "dsp_spos: symbol TASKTREEHEADERCODE not found\n"); return -EIO; } task_tree_thread = cs46xx_dsp_lookup_symbol(chip, "TASKTREETHREAD", SYMBOL_CODE); if (task_tree_thread == NULL) { snd_printk(KERN_ERR "dsp_spos: symbol TASKTREETHREAD not found\n"); return -EIO; } magic_snoop_task = cs46xx_dsp_lookup_symbol(chip, "MAGICSNOOPTASK", SYMBOL_CODE); if (magic_snoop_task == NULL) { snd_printk(KERN_ERR "dsp_spos: symbol MAGICSNOOPTASK not found\n"); return -EIO; } { /* create the null SCB */ static generic_scb_t null_scb = { { 0, 0, 0, 0 }, { 0, 0, 0, 0, 0 }, NULL_SCB_ADDR, NULL_SCB_ADDR, 0, 0, 0, 0, 0, { 0,0, 0,0, } }; null_scb.entry_point = null_algorithm->address; ins->the_null_scb = cs46xx_dsp_create_scb(chip, "nullSCB", (u32 *)&null_scb, NULL_SCB_ADDR); ins->the_null_scb->task_entry = null_algorithm; ins->the_null_scb->sub_list_ptr = ins->the_null_scb; ins->the_null_scb->next_scb_ptr = ins->the_null_scb; ins->the_null_scb->parent_scb_ptr = NULL; cs46xx_dsp_proc_register_scb_desc (chip,ins->the_null_scb); } { /* setup foreground task tree */ static task_tree_control_block_t fg_task_tree_hdr = { { FG_TASK_HEADER_ADDR | (DSP_SPOS_DC << 0x10), DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, 0x0000,DSP_SPOS_DC, DSP_SPOS_DC, DSP_SPOS_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC,DSP_SPOS_DC }, { BG_TREE_SCB_ADDR,TIMINGMASTER_SCB_ADDR, 0, FG_TASK_HEADER_ADDR + TCBData, }, { 4,0, 1,0, 2,SPOSCB_ADDR + HFGFlags, 0,0, FG_TASK_HEADER_ADDR + TCBContextBlk,FG_STACK }, { DSP_SPOS_DC,0, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DCDC, DSP_SPOS_UU,1, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC }, { FG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 0,0 } }; fg_task_tree_hdr.links.entry_point = fg_task_tree_header_code->address; fg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; cs46xx_dsp_create_task_tree(chip,"FGtaskTreeHdr",(u32 *)&fg_task_tree_hdr,FG_TASK_HEADER_ADDR,0x35); } { /* setup foreground task tree */ static task_tree_control_block_t bg_task_tree_hdr = { { DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC, DSP_SPOS_DC, DSP_SPOS_DC, DSP_SPOS_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC_DC, DSP_SPOS_DC,DSP_SPOS_DC }, { NULL_SCB_ADDR,NULL_SCB_ADDR, /* Set up the background to do nothing */ 0, BG_TREE_SCB_ADDR + TCBData, }, { 9999,0, 0,1, 0,SPOSCB_ADDR + HFGFlags, 0,0, BG_TREE_SCB_ADDR + TCBContextBlk,BG_STACK }, { DSP_SPOS_DC,0, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DC,DSP_SPOS_DC, DSP_SPOS_DCDC, DSP_SPOS_UU,1, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC, DSP_SPOS_DCDC }, { BG_INTERVAL_TIMER_PERIOD,DSP_SPOS_UU, 0,0 } }; bg_task_tree_hdr.links.entry_point = task_tree_header_code->address; bg_task_tree_hdr.context_blk.stack0 = task_tree_thread->address; cs46xx_dsp_create_task_tree(chip,"BGtaskTreeHdr",(u32 *)&bg_task_tree_hdr,BG_TREE_SCB_ADDR,0x35); } /* create timing master SCB */ timing_master_scb = cs46xx_dsp_create_timing_master_scb(chip); /* create the CODEC output task */ codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_I",0x0010,0x0000, MASTERMIX_SCB_ADDR, CODECOUT_SCB_ADDR,timing_master_scb, SCB_ON_PARENT_SUBLIST_SCB); if (!codec_out_scb) goto _fail_end; /* create the master mix SCB */ master_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"MasterMixSCB", MIX_SAMPLE_BUF1,MASTERMIX_SCB_ADDR, codec_out_scb, SCB_ON_PARENT_SUBLIST_SCB); ins->master_mix_scb = master_mix_scb; if (!master_mix_scb) goto _fail_end; /* create codec in */ codec_in_scb = cs46xx_dsp_create_codec_in_scb(chip,"CodecInSCB",0x0010,0x00A0, CODEC_INPUT_BUF1, CODECIN_SCB_ADDR,codec_out_scb, SCB_ON_PARENT_NEXT_SCB); if (!codec_in_scb) goto _fail_end; ins->codec_in_scb = codec_in_scb; /* create write back scb */ write_back_scb = cs46xx_dsp_create_mix_to_ostream_scb(chip,"WriteBackSCB", WRITE_BACK_BUF1,WRITE_BACK_SPB, WRITEBACK_SCB_ADDR, timing_master_scb, SCB_ON_PARENT_NEXT_SCB); if (!write_back_scb) goto _fail_end; { static mix2_ostream_spb_t mix2_ostream_spb = { 0x00020000, 0x0000ffff }; /* dirty hack ... */ _dsp_create_task_tree (chip,(u32 *)&mix2_ostream_spb,WRITE_BACK_SPB,2); } /* input sample converter */ vari_decimate_scb = cs46xx_dsp_create_vari_decimate_scb(chip,"VariDecimateSCB", VARI_DECIMATE_BUF0, VARI_DECIMATE_BUF1, VARIDECIMATE_SCB_ADDR, write_back_scb, SCB_ON_PARENT_SUBLIST_SCB); if (!vari_decimate_scb) goto _fail_end; /* create the record mixer SCB */ record_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RecordMixerSCB", MIX_SAMPLE_BUF2, RECORD_MIXER_SCB_ADDR, vari_decimate_scb, SCB_ON_PARENT_SUBLIST_SCB); ins->record_mixer_scb = record_mix_scb; if (!record_mix_scb) goto _fail_end; valid_slots = snd_cs46xx_peekBA0(chip, BA0_ACOSV); snd_assert (chip->nr_ac97_codecs == 1 || chip->nr_ac97_codecs == 2); if (chip->nr_ac97_codecs == 1) { /* output on slot 5 and 11 on primary CODEC */ fifo_addr = 0x20; fifo_span = 0x60; /* enable slot 5 and 11 */ valid_slots |= ACOSV_SLV5 | ACOSV_SLV11; } else { /* output on slot 7 and 8 on secondary CODEC */ fifo_addr = 0x40; fifo_span = 0x10; /* enable slot 7 and 8 */ valid_slots |= ACOSV_SLV7 | ACOSV_SLV8; } /* create CODEC tasklet for rear speakers output*/ rear_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_Rear",fifo_span,fifo_addr, REAR_MIXER_SCB_ADDR, REAR_CODECOUT_SCB_ADDR,codec_in_scb, SCB_ON_PARENT_NEXT_SCB); if (!rear_codec_out_scb) goto _fail_end; /* create the rear PCM channel mixer SCB */ rear_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"RearMixerSCB", MIX_SAMPLE_BUF3, REAR_MIXER_SCB_ADDR, rear_codec_out_scb, SCB_ON_PARENT_SUBLIST_SCB); ins->rear_mix_scb = rear_mix_scb; if (!rear_mix_scb) goto _fail_end; if (chip->nr_ac97_codecs == 2) { /* create CODEC tasklet for rear Center/LFE output slot 6 and 9 on seconadry CODEC */ clfe_codec_out_scb = cs46xx_dsp_create_codec_out_scb(chip,"CodecOutSCB_CLFE",0x0030,0x0030, CLFE_MIXER_SCB_ADDR, CLFE_CODEC_SCB_ADDR, rear_codec_out_scb, SCB_ON_PARENT_NEXT_SCB); if (!clfe_codec_out_scb) goto _fail_end; /* create the rear PCM channel mixer SCB */ ins->center_lfe_mix_scb = cs46xx_dsp_create_mix_only_scb(chip,"CLFEMixerSCB", MIX_SAMPLE_BUF4, CLFE_MIXER_SCB_ADDR, clfe_codec_out_scb, SCB_ON_PARENT_SUBLIST_SCB); if (!ins->center_lfe_mix_scb) goto _fail_end; /* enable slot 6 and 9 */ valid_slots |= ACOSV_SLV6 | ACOSV_SLV9; } else { clfe_codec_out_scb = rear_codec_out_scb; ins->center_lfe_mix_scb = rear_mix_scb; } /* enable slots depending on CODEC configuration */ snd_cs46xx_pokeBA0(chip, BA0_ACOSV, valid_slots); /* the magic snooper */ magic_snoop_scb = cs46xx_dsp_create_magic_snoop_scb (chip,"MagicSnoopSCB_I",OUTPUTSNOOP_SCB_ADDR, OUTPUT_SNOOP_BUFFER, codec_out_scb, clfe_codec_out_scb, SCB_ON_PARENT_NEXT_SCB); if (!magic_snoop_scb) goto _fail_end; ins->ref_snoop_scb = magic_snoop_scb; /* SP IO access */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -