⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dsp_spos_scb_lib.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
				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 + -