📄 dsp_spos_scb_lib.c
字号:
snd_printdd( "dsp_spos: creating SRC \"%s\"\n",scb_name); src_scb = cs46xx_dsp_create_src_task_scb(chip,scb_name, sample_rate, src_output_buffer_addr[src_index], src_delay_buffer_addr[src_index], /* 0x400 - 0x600 source SCBs */ 0x400 + (src_index * 0x10) , src_parent_scb, insert_point, pass_through); if (!src_scb) { snd_printk (KERN_ERR "dsp_spos: failed to create SRCtaskSCB\n"); return NULL; } /* cs46xx_dsp_set_src_sample_rate(chip,src_scb,sample_rate); */ ins->nsrc_scb ++; } snprintf (scb_name,DSP_MAX_SCB_NAME,"PCMReader_SCB%d",pcm_index); snd_printdd( "dsp_spos: creating PCM \"%s\" (%d)\n",scb_name, pcm_channel_id); pcm_scb = cs46xx_dsp_create_pcm_reader_scb(chip,scb_name, pcm_reader_buffer_addr[pcm_index], /* 0x200 - 400 PCMreader SCBs */ (pcm_index * 0x10) + 0x200, pcm_index, /* virtual channel 0-31 */ hw_dma_addr, /* pcm hw addr */ NULL, /* parent SCB ptr */ 0 /* insert point */ ); if (!pcm_scb) { snd_printk (KERN_ERR "dsp_spos: failed to create PCMreaderSCB\n"); return NULL; } spin_lock_irqsave(&chip->reg_lock, flags); ins->pcm_channels[pcm_index].sample_rate = sample_rate; ins->pcm_channels[pcm_index].pcm_reader_scb = pcm_scb; ins->pcm_channels[pcm_index].src_scb = src_scb; ins->pcm_channels[pcm_index].unlinked = 1; ins->pcm_channels[pcm_index].private_data = private_data; ins->pcm_channels[pcm_index].src_slot = src_index; ins->pcm_channels[pcm_index].active = 1; ins->pcm_channels[pcm_index].pcm_slot = pcm_index; ins->pcm_channels[pcm_index].mixer_scb = mixer_scb; ins->npcm_channels ++; spin_unlock_irqrestore(&chip->reg_lock, flags); return (ins->pcm_channels + pcm_index);}int cs46xx_dsp_pcm_channel_set_period (cs46xx_t * chip, pcm_channel_descriptor_t * pcm_channel, int period_size){ u32 temp = snd_cs46xx_peek (chip,pcm_channel->pcm_reader_scb->address << 2); temp &= ~DMA_RQ_C1_SOURCE_SIZE_MASK; switch (period_size) { case 2048: temp |= DMA_RQ_C1_SOURCE_MOD1024; break; case 1024: temp |= DMA_RQ_C1_SOURCE_MOD512; break; case 512: temp |= DMA_RQ_C1_SOURCE_MOD256; break; case 256: temp |= DMA_RQ_C1_SOURCE_MOD128; break; case 128: temp |= DMA_RQ_C1_SOURCE_MOD64; break; case 64: temp |= DMA_RQ_C1_SOURCE_MOD32; break; case 32: temp |= DMA_RQ_C1_SOURCE_MOD16; break; default: snd_printdd ("period size (%d) not supported by HW\n", period_size); return -EINVAL; } snd_cs46xx_poke (chip,pcm_channel->pcm_reader_scb->address << 2,temp); return 0;}int cs46xx_dsp_pcm_ostream_set_period (cs46xx_t * chip, int period_size){ u32 temp = snd_cs46xx_peek (chip,WRITEBACK_SCB_ADDR << 2); temp &= ~DMA_RQ_C1_DEST_SIZE_MASK; switch (period_size) { case 2048: temp |= DMA_RQ_C1_DEST_MOD1024; break; case 1024: temp |= DMA_RQ_C1_DEST_MOD512; break; case 512: temp |= DMA_RQ_C1_DEST_MOD256; break; case 256: temp |= DMA_RQ_C1_DEST_MOD128; break; case 128: temp |= DMA_RQ_C1_DEST_MOD64; break; case 64: temp |= DMA_RQ_C1_DEST_MOD32; break; case 32: temp |= DMA_RQ_C1_DEST_MOD16; break; default: snd_printdd ("period size (%d) not supported by HW\n", period_size); return -EINVAL; } snd_cs46xx_poke (chip,WRITEBACK_SCB_ADDR << 2,temp); return 0;}void cs46xx_dsp_destroy_pcm_channel (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; unsigned long flags; snd_assert(pcm_channel->active, return ); snd_assert(ins->npcm_channels > 0, return ); snd_assert(pcm_channel->src_scb->ref_count > 0, return ); spin_lock_irqsave(&chip->reg_lock, flags); pcm_channel->unlinked = 1; pcm_channel->active = 0; pcm_channel->private_data = NULL; pcm_channel->src_scb->ref_count --; ins->npcm_channels --; spin_unlock_irqrestore(&chip->reg_lock, flags); cs46xx_dsp_remove_scb(chip,pcm_channel->pcm_reader_scb); if (!pcm_channel->src_scb->ref_count) { cs46xx_dsp_remove_scb(chip,pcm_channel->src_scb); snd_assert (pcm_channel->src_slot >= 0 && pcm_channel->src_slot <= DSP_MAX_SRC_NR, return ); ins->src_scb_slots[pcm_channel->src_slot] = 0; ins->nsrc_scb --; }}int cs46xx_dsp_pcm_unlink (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; unsigned long flags; snd_assert(pcm_channel->active,return -EIO); snd_assert(ins->npcm_channels > 0,return -EIO); spin_lock(&pcm_channel->src_scb->lock); if (pcm_channel->unlinked) { spin_unlock(&pcm_channel->src_scb->lock); return -EIO; } spin_lock_irqsave(&chip->reg_lock, flags); pcm_channel->unlinked = 1; spin_unlock_irqrestore(&chip->reg_lock, flags); _dsp_unlink_scb (chip,pcm_channel->pcm_reader_scb); spin_unlock(&pcm_channel->src_scb->lock); return 0;}int cs46xx_dsp_pcm_link (cs46xx_t * chip,pcm_channel_descriptor_t * pcm_channel){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * parent_scb; dsp_scb_descriptor_t * src_scb = pcm_channel->src_scb; unsigned long flags; spin_lock(&pcm_channel->src_scb->lock); if (pcm_channel->unlinked == 0) { spin_unlock(&pcm_channel->src_scb->lock); return -EIO; } parent_scb = src_scb; if (src_scb->sub_list_ptr != ins->the_null_scb) { src_scb->sub_list_ptr->parent_scb_ptr = pcm_channel->pcm_reader_scb; pcm_channel->pcm_reader_scb->next_scb_ptr = src_scb->sub_list_ptr; } src_scb->sub_list_ptr = pcm_channel->pcm_reader_scb; snd_assert (pcm_channel->pcm_reader_scb->parent_scb_ptr == NULL, ; ); pcm_channel->pcm_reader_scb->parent_scb_ptr = parent_scb; spin_lock_irqsave(&chip->reg_lock, flags); /* update SCB entry in DSP RAM */ cs46xx_dsp_spos_update_scb(chip,pcm_channel->pcm_reader_scb); /* update parent SCB entry */ cs46xx_dsp_spos_update_scb(chip,parent_scb); pcm_channel->unlinked = 0; spin_unlock_irqrestore(&chip->reg_lock, flags); spin_unlock(&pcm_channel->src_scb->lock); return 0;}dsp_scb_descriptor_t * cs46xx_add_record_source (cs46xx_t *chip,dsp_scb_descriptor_t * source, u16 addr,char * scb_name){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * parent; dsp_scb_descriptor_t * pcm_input; int insert_point; snd_assert (ins->record_mixer_scb != NULL,return NULL); if (ins->record_mixer_scb->sub_list_ptr != ins->the_null_scb) { parent = find_next_free_scb (chip,ins->record_mixer_scb->sub_list_ptr); insert_point = SCB_ON_PARENT_NEXT_SCB; } else { parent = ins->record_mixer_scb; insert_point = SCB_ON_PARENT_SUBLIST_SCB; } pcm_input = cs46xx_dsp_create_pcm_serial_input_scb(chip,scb_name,addr, source, parent, insert_point); return pcm_input;}int cs46xx_src_unlink(cs46xx_t *chip,dsp_scb_descriptor_t * src){ snd_assert (src->parent_scb_ptr != NULL, return -EINVAL ); /* mute SCB */ cs46xx_dsp_scb_set_volume (chip,src,0,0); _dsp_unlink_scb (chip,src); return 0;}int cs46xx_src_link(cs46xx_t *chip,dsp_scb_descriptor_t * src){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; dsp_scb_descriptor_t * parent_scb; snd_assert (src->parent_scb_ptr == NULL, return -EINVAL ); snd_assert(ins->master_mix_scb !=NULL, return -EINVAL ); if (ins->master_mix_scb->sub_list_ptr != ins->the_null_scb) { parent_scb = find_next_free_scb (chip,ins->master_mix_scb->sub_list_ptr); parent_scb->next_scb_ptr = src; } else { parent_scb = ins->master_mix_scb; parent_scb->sub_list_ptr = src; } src->parent_scb_ptr = parent_scb; /* update entry in DSP RAM */ cs46xx_dsp_spos_update_scb(chip,parent_scb); return 0;}int cs46xx_dsp_enable_spdif_out (cs46xx_t *chip){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) { cs46xx_dsp_enable_spdif_hw (chip); } /* dont touch anything if SPDIF is open */ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) { /* when cs46xx_iec958_post_close(...) is called it will call this function if necessary depending on this bit */ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; return -EBUSY; } snd_assert (ins->asynch_tx_scb == NULL, return -EINVAL); snd_assert (ins->master_mix_scb->next_scb_ptr == ins->the_null_scb, return -EINVAL); /* reset output snooper sample buffer pointer */ snd_cs46xx_poke (chip, (ins->ref_snoop_scb->address + 2) << 2, (OUTPUT_SNOOP_BUFFER + 0x10) << 0x10 ); /* The asynch. transfer task */ ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR, SPDIFO_SCB_INST, SPDIFO_IP_OUTPUT_BUFFER1, ins->master_mix_scb, SCB_ON_PARENT_NEXT_SCB); if (!ins->asynch_tx_scb) return -ENOMEM; ins->spdif_pcm_input_scb = cs46xx_dsp_create_pcm_serial_input_scb(chip,"PCMSerialInput_II", PCMSERIALINII_SCB_ADDR, ins->ref_snoop_scb, ins->asynch_tx_scb, SCB_ON_PARENT_SUBLIST_SCB); if (!ins->spdif_pcm_input_scb) return -ENOMEM; /* monitor state */ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; return 0;}int cs46xx_dsp_disable_spdif_out (cs46xx_t *chip){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; /* dont touch anything if SPDIF is open */ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_PLAYBACK_OPEN) { ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED; return -EBUSY; } /* check integrety */ snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL); snd_assert (ins->spdif_pcm_input_scb != NULL,return -EINVAL); snd_assert (ins->master_mix_scb->next_scb_ptr == ins->asynch_tx_scb, return -EINVAL); snd_assert (ins->asynch_tx_scb->parent_scb_ptr == ins->master_mix_scb, return -EINVAL); cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); ins->spdif_pcm_input_scb = NULL; ins->asynch_tx_scb = NULL; /* clear buffer to prevent any undesired noise */ _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256); /* monitor state */ ins->spdif_status_out &= ~DSP_SPDIF_STATUS_OUTPUT_ENABLED; return 0;}int cs46xx_iec958_pre_open (cs46xx_t *chip){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { /* remove AsynchFGTxSCB and and PCMSerialInput_II */ cs46xx_dsp_disable_spdif_out (chip); /* save state */ ins->spdif_status_out |= DSP_SPDIF_STATUS_OUTPUT_ENABLED; } /* if not enabled already */ if ( !(ins->spdif_status_out & DSP_SPDIF_STATUS_HW_ENABLED) ) { cs46xx_dsp_enable_spdif_hw (chip); } /* Create the asynch. transfer task for playback */ ins->asynch_tx_scb = cs46xx_dsp_create_asynch_fg_tx_scb(chip,"AsynchFGTxSCB",ASYNCTX_SCB_ADDR, SPDIFO_SCB_INST, SPDIFO_IP_OUTPUT_BUFFER1, ins->master_mix_scb, SCB_ON_PARENT_NEXT_SCB); /* set spdif channel status value for streaming */ cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_stream); ins->spdif_status_out |= DSP_SPDIF_STATUS_PLAYBACK_OPEN; return 0;}int cs46xx_iec958_post_close (cs46xx_t *chip){ dsp_spos_instance_t * ins = chip->dsp_spos_instance; snd_assert (ins->asynch_tx_scb != NULL, return -EINVAL); ins->spdif_status_out &= ~DSP_SPDIF_STATUS_PLAYBACK_OPEN; /* restore settings */ cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default); /* deallocate stuff */ if (ins->spdif_pcm_input_scb != NULL) { cs46xx_dsp_remove_scb (chip,ins->spdif_pcm_input_scb); ins->spdif_pcm_input_scb = NULL; } cs46xx_dsp_remove_scb (chip,ins->asynch_tx_scb); ins->asynch_tx_scb = NULL; /* clear buffer to prevent any undesired noise */ _dsp_clear_sample_buffer(chip,SPDIFO_IP_OUTPUT_BUFFER1,256); /* restore state */ if ( ins->spdif_status_out & DSP_SPDIF_STATUS_OUTPUT_ENABLED ) { cs46xx_dsp_enable_spdif_out (chip); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -