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

📄 dsp_spos.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (!cs46xx_dsp_create_spio_write_scb(chip,"SPIOWriteSCB",SPIOWRITE_SCB_ADDR,					      magic_snoop_scb,					      SCB_ON_PARENT_NEXT_SCB))		goto _fail_end;	/* SPDIF input sampel rate converter */	src_task_scb = cs46xx_dsp_create_src_task_scb(chip,"SrcTaskSCB_SPDIFI",						      ins->spdif_in_sample_rate,						      SRC_OUTPUT_BUF1,						      SRC_DELAY_BUF1,SRCTASK_SCB_ADDR,						      master_mix_scb,						      SCB_ON_PARENT_SUBLIST_SCB,1);	if (!src_task_scb) goto _fail_end;	cs46xx_src_unlink(chip,src_task_scb);	/* NOTE: when we now how to detect the SPDIF input	   sample rate we will use this SRC to adjust it */	ins->spdif_in_src = src_task_scb;	cs46xx_dsp_async_init(chip,timing_master_scb);	return 0; _fail_end:	snd_printk(KERN_ERR "dsp_spos: failed to setup SCB's in DSP\n");	return -EINVAL;}static int cs46xx_dsp_async_init (cs46xx_t *chip, dsp_scb_descriptor_t * fg_entry){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	symbol_entry_t * s16_async_codec_input_task;	symbol_entry_t * spdifo_task;	symbol_entry_t * spdifi_task;	dsp_scb_descriptor_t * spdifi_scb_desc,* spdifo_scb_desc,* async_codec_scb_desc;	s16_async_codec_input_task = cs46xx_dsp_lookup_symbol(chip, "S16_ASYNCCODECINPUTTASK", SYMBOL_CODE);	if (s16_async_codec_input_task == NULL) {		snd_printk(KERN_ERR "dsp_spos: symbol S16_ASYNCCODECINPUTTASK not found\n");		return -EIO;	}	spdifo_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFOTASK", SYMBOL_CODE);	if (spdifo_task == NULL) {		snd_printk(KERN_ERR "dsp_spos: symbol SPDIFOTASK not found\n");		return -EIO;	}	spdifi_task = cs46xx_dsp_lookup_symbol(chip, "SPDIFITASK", SYMBOL_CODE);	if (spdifi_task == NULL) {		snd_printk(KERN_ERR "dsp_spos: symbol SPDIFITASK not found\n");		return -EIO;	}	{		/* 0xBC0 */		spdifoscb_t spdifo_scb = {			/* 0 */ DSP_SPOS_UUUU,			{				/* 1 */ 0xb0, 				/* 2 */ 0, 				/* 3 */ 0, 				/* 4 */ 0, 			},			/* NOTE: the SPDIF output task read samples in mono			   format, the AsynchFGTxSCB task writes to buffer			   in stereo format			*/			/* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_256,			/* 6 */ ( SPDIFO_IP_OUTPUT_BUFFER1 << 0x10 )  |  0xFFFC,			/* 7 */ 0,0, 			/* 8 */ 0, 			/* 9 */ FG_TASK_HEADER_ADDR, NULL_SCB_ADDR, 			/* A */ spdifo_task->address,			SPDIFO_SCB_INST + SPDIFOFIFOPointer,			{				/* B */ 0x0040, /*DSP_SPOS_UUUU,*/				/* C */ 0x20ff, /*DSP_SPOS_UUUU,*/			},			/* D */ 0x804c,0,							  /* SPDIFOFIFOPointer:SPDIFOStatRegAddr; */			/* E */ 0x0108,0x0001,					  /* SPDIFOStMoFormat:SPDIFOFIFOBaseAddr; */			/* F */ DSP_SPOS_UUUU	  			          /* SPDIFOFree; */		};		/* 0xBB0 */		spdifiscb_t spdifi_scb = {			/* 0 */ DSP_SPOS_UULO,DSP_SPOS_UUHI,			/* 1 */ 0,			/* 2 */ 0,			/* 3 */ 1,4000,        /* SPDIFICountLimit SPDIFICount */ 			/* 4 */ DSP_SPOS_UUUU, /* SPDIFIStatusData */			/* 5 */ 0,DSP_SPOS_UUHI, /* StatusData, Free4 */			/* 6 */ DSP_SPOS_UUUU,  /* Free3 */			/* 7 */ DSP_SPOS_UU,DSP_SPOS_DC,  /* Free2 BitCount*/			/* 8 */ DSP_SPOS_UUUU,	/* TempStatus */			/* 9 */ SPDIFO_SCB_INST, NULL_SCB_ADDR,			/* A */ spdifi_task->address,			SPDIFI_SCB_INST + SPDIFIFIFOPointer,			/* NOTE: The SPDIF input task write the sample in mono			   format from the HW FIFO, the AsynchFGRxSCB task  reads 			   them in stereo 			*/			/* B */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_128,			/* C */ (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,			/* D */ 0x8048,0,			/* E */ 0x01f0,0x0001,			/* F */ DSP_SPOS_UUUU /* SPDIN_STATUS monitor */		};		/* 0xBA0 */		async_codec_input_scb_t async_codec_input_scb = {			/* 0 */ DSP_SPOS_UUUU,			/* 1 */ 0,			/* 2 */ 0,			/* 3 */ 1,4000,			/* 4 */ 0x0118,0x0001,			/* 5 */ RSCONFIG_SAMPLE_16MONO + RSCONFIG_MODULO_64,			/* 6 */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,			/* 7 */ DSP_SPOS_UU,0x3,			/* 8 */ DSP_SPOS_UUUU,			/* 9 */ SPDIFI_SCB_INST,NULL_SCB_ADDR,			/* A */ s16_async_codec_input_task->address,			HFG_TREE_SCB + AsyncCIOFIFOPointer,              			/* B */ RSCONFIG_SAMPLE_16STEREO + RSCONFIG_MODULO_64,			/* C */ (ASYNC_IP_OUTPUT_BUFFER1 << 0x10),  /*(ASYNC_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC,*/      #ifdef UseASER1Input			/* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;	       			   Init. 0000:8042: for ASER1			   0000:8044: for ASER2 */			/* D */ 0x8042,0,      			/* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;			   Init 1 stero:8050 ASER1			   Init 0  mono:8070 ASER2			   Init 1 Stereo : 0100 ASER1 (Set by script) */			/* E */ 0x0100,0x0001,      #endif      #ifdef UseASER2Input			/* short AsyncCIFIFOPointer:AsyncCIStatRegAddr;			   Init. 0000:8042: for ASER1			   0000:8044: for ASER2 */			/* D */ 0x8044,0,      			/* short AsyncCIStMoFormat:AsyncCIFIFOBaseAddr;			   Init 1 stero:8050 ASER1			   Init 0  mono:8070 ASER2			   Init 1 Stereo : 0100 ASER1 (Set by script) */			/* E */ 0x0110,0x0001,      #endif      			/* short AsyncCIOutputBufModulo:AsyncCIFree;			   AsyncCIOutputBufModulo: The modulo size for   			   the output buffer of this task */			/* F */ 0, /* DSP_SPOS_UUUU */		};		spdifo_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFOSCB",(u32 *)&spdifo_scb,SPDIFO_SCB_INST);		snd_assert(spdifo_scb_desc, return -EIO);		spdifi_scb_desc = cs46xx_dsp_create_scb(chip,"SPDIFISCB",(u32 *)&spdifi_scb,SPDIFI_SCB_INST);		snd_assert(spdifi_scb_desc, return -EIO);		async_codec_scb_desc = cs46xx_dsp_create_scb(chip,"AsynCodecInputSCB",(u32 *)&async_codec_input_scb, HFG_TREE_SCB);		snd_assert(async_codec_scb_desc, return -EIO);		async_codec_scb_desc->parent_scb_ptr = NULL;		async_codec_scb_desc->next_scb_ptr = spdifi_scb_desc;		async_codec_scb_desc->sub_list_ptr = ins->the_null_scb;		async_codec_scb_desc->task_entry = s16_async_codec_input_task;		spdifi_scb_desc->parent_scb_ptr = async_codec_scb_desc;		spdifi_scb_desc->next_scb_ptr = spdifo_scb_desc;		spdifi_scb_desc->sub_list_ptr = ins->the_null_scb;		spdifi_scb_desc->task_entry = spdifi_task;		spdifo_scb_desc->parent_scb_ptr = spdifi_scb_desc;		spdifo_scb_desc->next_scb_ptr = fg_entry;		spdifo_scb_desc->sub_list_ptr = ins->the_null_scb;		spdifo_scb_desc->task_entry = spdifo_task;		/* this one is faked, as the parnet of SPDIFO task		   is the FG task tree */		fg_entry->parent_scb_ptr = spdifo_scb_desc;		/* for proc fs */		cs46xx_dsp_proc_register_scb_desc (chip,spdifo_scb_desc);		cs46xx_dsp_proc_register_scb_desc (chip,spdifi_scb_desc);		cs46xx_dsp_proc_register_scb_desc (chip,async_codec_scb_desc);		/* Async MASTER ENABLE, affects both SPDIF input and output */		snd_cs46xx_pokeBA0(chip, BA0_ASER_MASTER, 0x1 );	}	return 0;}static void cs46xx_dsp_disable_spdif_hw (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	/* set SPDIF output FIFO slot */	snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, 0);	/* SPDIF output MASTER ENABLE */	cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0);	/* right and left validate bit */	/*cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);*/	cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, 0x0);	/* clear fifo pointer */	cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);	/* monitor state */	ins->spdif_status_out &= ~DSP_SPDIF_STATUS_HW_ENABLED;}int cs46xx_dsp_enable_spdif_hw (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	/* if hw-ctrl already enabled, turn off to reset logic ... */	cs46xx_dsp_disable_spdif_hw (chip);	udelay(50);	/* set SPDIF output FIFO slot */	snd_cs46xx_pokeBA0(chip, BA0_ASER_FADDR, ( 0x8000 | ((SP_SPDOUT_FIFO >> 4) << 4) ));	/* SPDIF output MASTER ENABLE */	cs46xx_poke_via_dsp (chip,SP_SPDOUT_CONTROL, 0x80000000);	/* right and left validate bit */	cs46xx_poke_via_dsp (chip,SP_SPDOUT_CSUV, ins->spdif_csuv_default);	/* monitor state */	ins->spdif_status_out |= DSP_SPDIF_STATUS_HW_ENABLED;	return 0;}int cs46xx_dsp_enable_spdif_in (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	/* turn on amplifier */	chip->active_ctrl(chip, 1);	chip->amplifier_ctrl(chip, 1);	snd_assert (ins->asynch_rx_scb == NULL,return -EINVAL);	snd_assert (ins->spdif_in_src != NULL,return -EINVAL);	down(&chip->spos_mutex);	if ( ! (ins->spdif_status_out & DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED) ) {		/* time countdown enable */		cs46xx_poke_via_dsp (chip,SP_ASER_COUNTDOWN, 0x80000005);		/* NOTE: 80000005 value is just magic. With all values		   that I've tested this one seem to give the best result.		   Got no explication why. (Benny) */		/* SPDIF input MASTER ENABLE */		cs46xx_poke_via_dsp (chip,SP_SPDIN_CONTROL, 0x800003ff);		ins->spdif_status_out |= DSP_SPDIF_STATUS_INPUT_CTRL_ENABLED;	}	/* create and start the asynchronous receiver SCB */	ins->asynch_rx_scb = cs46xx_dsp_create_asynch_fg_rx_scb(chip,"AsynchFGRxSCB",								ASYNCRX_SCB_ADDR,								SPDIFI_SCB_INST,								SPDIFI_IP_OUTPUT_BUFFER1,								ins->spdif_in_src,								SCB_ON_PARENT_SUBLIST_SCB);	spin_lock_irq(&chip->reg_lock);	/* reset SPDIF input sample buffer pointer */	/*snd_cs46xx_poke (chip, (SPDIFI_SCB_INST + 0x0c) << 2,	  (SPDIFI_IP_OUTPUT_BUFFER1 << 0x10) | 0xFFFC);*/	/* reset FIFO ptr */	/*cs46xx_poke_via_dsp (chip,SP_SPDIN_FIFOPTR, 0x0);*/	cs46xx_src_link(chip,ins->spdif_in_src);	/* unmute SRC volume */	cs46xx_dsp_scb_set_volume (chip,ins->spdif_in_src,0x7fff,0x7fff);	spin_unlock_irq(&chip->reg_lock);	/* set SPDIF input sample rate and unmute	   NOTE: only 48khz support for SPDIF input this time */	/* cs46xx_dsp_set_src_sample_rate(chip,ins->spdif_in_src,48000); */	/* monitor state */	ins->spdif_status_in = 1;	up(&chip->spos_mutex);	return 0;}int cs46xx_dsp_disable_spdif_in (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_assert (ins->asynch_rx_scb != NULL, return -EINVAL);	snd_assert (ins->spdif_in_src != NULL,return -EINVAL);		down(&chip->spos_mutex);	/* Remove the asynchronous receiver SCB */	cs46xx_dsp_remove_scb (chip,ins->asynch_rx_scb);	ins->asynch_rx_scb = NULL;	cs46xx_src_unlink(chip,ins->spdif_in_src);	/* monitor state */	ins->spdif_status_in = 0;	up(&chip->spos_mutex);	/* restore amplifier */	chip->active_ctrl(chip, -1);	chip->amplifier_ctrl(chip, -1);	return 0;}int cs46xx_dsp_enable_pcm_capture (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_assert (ins->pcm_input == NULL,return -EINVAL);	snd_assert (ins->ref_snoop_scb != NULL,return -EINVAL);	down(&chip->spos_mutex);	ins->pcm_input = cs46xx_add_record_source(chip,ins->ref_snoop_scb,PCMSERIALIN_PCM_SCB_ADDR,                                                  "PCMSerialInput_Wave");	up(&chip->spos_mutex);	return 0;}int cs46xx_dsp_disable_pcm_capture (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_assert (ins->pcm_input != NULL,return -EINVAL);	down(&chip->spos_mutex);	cs46xx_dsp_remove_scb (chip,ins->pcm_input);	ins->pcm_input = NULL;	up(&chip->spos_mutex);	return 0;}int cs46xx_dsp_enable_adc_capture (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_assert (ins->adc_input == NULL,return -EINVAL);	snd_assert (ins->codec_in_scb != NULL,return -EINVAL);	down(&chip->spos_mutex);	ins->adc_input = cs46xx_add_record_source(chip,ins->codec_in_scb,PCMSERIALIN_SCB_ADDR,						  "PCMSerialInput_ADC");	up(&chip->spos_mutex);	return 0;}int cs46xx_dsp_disable_adc_capture (cs46xx_t *chip){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	snd_assert (ins->adc_input != NULL,return -EINVAL);	down(&chip->spos_mutex);	cs46xx_dsp_remove_scb (chip,ins->adc_input);	ins->adc_input = NULL;	up(&chip->spos_mutex);	return 0;}int cs46xx_poke_via_dsp (cs46xx_t *chip,u32 address,u32 data){	u32 temp;	int  i;	/* santiy check the parameters.  (These numbers are not 100% correct.  They are	   a rough guess from looking at the controller spec.) */	if (address < 0x8000 || address >= 0x9000)		return -EINVAL;        	/* initialize the SP_IO_WRITE SCB with the data. */	temp = ( address << 16 ) | ( address & 0x0000FFFF);   /* offset 0 <-- address2 : address1 */	snd_cs46xx_poke(chip,( SPIOWRITE_SCB_ADDR      << 2), temp);	snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 1) << 2), data); /* offset 1 <-- data1 */	snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 2) << 2), data); /* offset 1 <-- data2 */    	/* Poke this location to tell the task to start */	snd_cs46xx_poke(chip,((SPIOWRITE_SCB_ADDR + 6) << 2), SPIOWRITE_SCB_ADDR << 0x10);	/* Verify that the task ran */	for (i=0; i<25; i++) {		udelay(125);		temp =  snd_cs46xx_peek(chip,((SPIOWRITE_SCB_ADDR + 6) << 2));		if (temp == 0x00000000)			break;	}	if (i == 25) {		snd_printk(KERN_ERR "dsp_spos: SPIOWriteTask not responding\n");		return -EBUSY;	}	return 0;}int cs46xx_dsp_set_dac_volume (cs46xx_t * chip,u16 left,u16 right){	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	dsp_scb_descriptor_t * scb; 	down(&chip->spos_mutex);		/* main output */	scb = ins->master_mix_scb->sub_list_ptr;	while (scb != ins->the_null_scb) {		cs46xx_dsp_scb_set_volume (chip,scb,left,right);		scb = scb->next_scb_ptr;	}	/* rear output */	scb = ins->rear_mix_scb->sub_list_ptr;	while (scb != ins->the_null_scb) {		cs46xx_dsp_scb_set_volume (chip,scb,left,right);		scb = scb->next_scb_ptr;	}	ins->dac_volume_left = left;	ins->dac_volume_right = right;	up(&chip->spos_mutex);	return 0;}int cs46xx_dsp_set_iec958_volume (cs46xx_t * chip,u16 left,u16 right) {	dsp_spos_instance_t * ins = chip->dsp_spos_instance;	down(&chip->spos_mutex);	if (ins->asynch_rx_scb != NULL)		cs46xx_dsp_scb_set_volume (chip,ins->asynch_rx_scb,					   left,right);	ins->spdif_input_volume_left = left;	ins->spdif_input_volume_right = right;	up(&chip->spos_mutex);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -