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

📄 pcxhr_core.c

📁 linux2.6.16版本
💻 C
📖 第 1 页 / 共 3 页
字号:
	err = pcxhr_download_dsp(mgr, boot);	if (err)		return err;	/* wait for hf5 bit */	return pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,				   PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &dummy);}/* * load the final dsp image */int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp){	int err;	unsigned char dummy;	err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_BOARD_FUNC, 0);	if (err)		return err;	err = pcxhr_send_it_dsp(mgr, PCXHR_IT_DOWNLOAD_DSP, 0);	if (err)		return err;	err = pcxhr_download_dsp(mgr, dsp);	if (err)		return err;	/* wait for chk bit */	return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,				   PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy);}struct pcxhr_cmd_info {	u32 opcode;		/* command word */	u16 st_length;		/* status length */	u16 st_type;		/* status type (RMH_SSIZE_XXX) */};/* RMH status type */enum {	RMH_SSIZE_FIXED = 0,	/* status size fix (st_length = 0..x) */	RMH_SSIZE_ARG = 1,	/* status size given in the LSB byte (used with st_length = 1) */	RMH_SSIZE_MASK = 2,	/* status size given in bitmask  (used with st_length = 1) */};/* * Array of DSP commands */static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {[CMD_VERSION] =				{ 0x010000, 1, RMH_SSIZE_FIXED },[CMD_SUPPORTED] =			{ 0x020000, 4, RMH_SSIZE_FIXED },[CMD_TEST_IT] =				{ 0x040000, 1, RMH_SSIZE_FIXED },[CMD_SEND_IRQA] =			{ 0x070001, 0, RMH_SSIZE_FIXED },[CMD_ACCESS_IO_WRITE] =			{ 0x090000, 1, RMH_SSIZE_ARG },[CMD_ACCESS_IO_READ] =			{ 0x094000, 1, RMH_SSIZE_ARG },[CMD_ASYNC] =				{ 0x0a0000, 1, RMH_SSIZE_ARG },[CMD_MODIFY_CLOCK] =			{ 0x0d0000, 0, RMH_SSIZE_FIXED },[CMD_RESYNC_AUDIO_INPUTS] =		{ 0x0e0000, 0, RMH_SSIZE_FIXED },[CMD_GET_DSP_RESOURCES] =		{ 0x100000, 4, RMH_SSIZE_FIXED },[CMD_SET_TIMER_INTERRUPT] =		{ 0x110000, 0, RMH_SSIZE_FIXED },[CMD_RES_PIPE] =			{ 0x400000, 0, RMH_SSIZE_FIXED },[CMD_FREE_PIPE] =			{ 0x410000, 0, RMH_SSIZE_FIXED },[CMD_CONF_PIPE] =			{ 0x422101, 0, RMH_SSIZE_FIXED },[CMD_STOP_PIPE] =			{ 0x470004, 0, RMH_SSIZE_FIXED },[CMD_PIPE_SAMPLE_COUNT] =		{ 0x49a000, 2, RMH_SSIZE_FIXED },[CMD_CAN_START_PIPE] =			{ 0x4b0000, 1, RMH_SSIZE_FIXED },[CMD_START_STREAM] =			{ 0x802000, 0, RMH_SSIZE_FIXED },[CMD_STREAM_OUT_LEVEL_ADJUST] =		{ 0x822000, 0, RMH_SSIZE_FIXED },[CMD_STOP_STREAM] =			{ 0x832000, 0, RMH_SSIZE_FIXED },[CMD_UPDATE_R_BUFFERS] =		{ 0x840000, 0, RMH_SSIZE_FIXED },[CMD_FORMAT_STREAM_OUT] =		{ 0x860000, 0, RMH_SSIZE_FIXED },[CMD_FORMAT_STREAM_IN] =		{ 0x870000, 0, RMH_SSIZE_FIXED },[CMD_STREAM_SAMPLE_COUNT] =		{ 0x902000, 2, RMH_SSIZE_FIXED },	/* stat_len = nb_streams * 2 */[CMD_AUDIO_LEVEL_ADJUST] =		{ 0xc22000, 0, RMH_SSIZE_FIXED },};#ifdef CONFIG_SND_DEBUG_DETECTstatic char* cmd_names[] = {[CMD_VERSION] =				"CMD_VERSION",[CMD_SUPPORTED] =			"CMD_SUPPORTED",[CMD_TEST_IT] =				"CMD_TEST_IT",[CMD_SEND_IRQA] =			"CMD_SEND_IRQA",[CMD_ACCESS_IO_WRITE] =			"CMD_ACCESS_IO_WRITE",[CMD_ACCESS_IO_READ] =			"CMD_ACCESS_IO_READ",[CMD_ASYNC] =				"CMD_ASYNC",[CMD_MODIFY_CLOCK] =			"CMD_MODIFY_CLOCK",[CMD_RESYNC_AUDIO_INPUTS] =		"CMD_RESYNC_AUDIO_INPUTS",[CMD_GET_DSP_RESOURCES] =		"CMD_GET_DSP_RESOURCES",[CMD_SET_TIMER_INTERRUPT] =		"CMD_SET_TIMER_INTERRUPT",[CMD_RES_PIPE] =			"CMD_RES_PIPE",[CMD_FREE_PIPE] =			"CMD_FREE_PIPE",[CMD_CONF_PIPE] =			"CMD_CONF_PIPE",[CMD_STOP_PIPE] =			"CMD_STOP_PIPE",[CMD_PIPE_SAMPLE_COUNT] =		"CMD_PIPE_SAMPLE_COUNT",[CMD_CAN_START_PIPE] =			"CMD_CAN_START_PIPE",[CMD_START_STREAM] =			"CMD_START_STREAM",[CMD_STREAM_OUT_LEVEL_ADJUST] =		"CMD_STREAM_OUT_LEVEL_ADJUST",[CMD_STOP_STREAM] =			"CMD_STOP_STREAM",[CMD_UPDATE_R_BUFFERS] =		"CMD_UPDATE_R_BUFFERS",[CMD_FORMAT_STREAM_OUT] =		"CMD_FORMAT_STREAM_OUT",[CMD_FORMAT_STREAM_IN] =		"CMD_FORMAT_STREAM_IN",[CMD_STREAM_SAMPLE_COUNT] =		"CMD_STREAM_SAMPLE_COUNT",[CMD_AUDIO_LEVEL_ADJUST] =		"CMD_AUDIO_LEVEL_ADJUST",};#endifstatic int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh){	int err;	int i;	u32 data;	u32 size_mask;	unsigned char reg;	int max_stat_len;	if (rmh->stat_len < PCXHR_SIZE_MAX_STATUS)		max_stat_len = PCXHR_SIZE_MAX_STATUS;	else	max_stat_len = rmh->stat_len;	for (i = 0; i < rmh->stat_len; i++) {		/* wait for receiver full */		err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,					  PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);		if (err) {			snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n",				   reg, i);			return err;		}		/* read data */		data  = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;		data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;		data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);		/* need to update rmh->stat_len on the fly ?? */		if (i==0) {			if (rmh->dsp_stat != RMH_SSIZE_FIXED) {				if (rmh->dsp_stat == RMH_SSIZE_ARG) {					rmh->stat_len = (u16)(data & 0x0000ff) + 1;					data &= 0xffff00;				} else {					/* rmh->dsp_stat == RMH_SSIZE_MASK */					rmh->stat_len = 1;					size_mask = data;					while (size_mask) {						if (size_mask & 1)							rmh->stat_len++;						size_mask >>= 1;					}				}			}		}#ifdef CONFIG_SND_DEBUG_DETECT		if (rmh->cmd_idx < CMD_LAST_INDEX)			snd_printdd("    stat[%d]=%x\n", i, data);#endif		if (i < max_stat_len)			rmh->stat[i] = data;	}	if (rmh->stat_len > max_stat_len) {		snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len);		rmh->stat_len = max_stat_len;	}	return 0;}static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh){	int err;	int i;	u32 data;	unsigned char reg;	snd_assert(rmh->cmd_len<PCXHR_SIZE_MAX_CMD, return -EINVAL);	err = pcxhr_send_it_dsp(mgr, PCXHR_IT_MESSAGE, 1);	if (err) {		snd_printk(KERN_ERR "pcxhr_send_message : ED_DSP_CRASHED\n");		return err;	}	/* wait for chk bit */	err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,				  PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &reg);	if (err)		return err;	/* reset irq chk */	err = pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_CHK, 1);	if (err)		return err;	/* wait for chk bit == 0*/	err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK, 0,				  PCXHR_TIMEOUT_DSP, &reg);	if (err)		return err;	data = rmh->cmd[0];	if (rmh->cmd_len > 1)		data |= 0x008000;	/* MASK_MORE_THAN_1_WORD_COMMAND */	else		data &= 0xff7fff;	/* MASK_1_WORD_COMMAND */#ifdef CONFIG_SND_DEBUG_DETECT	if (rmh->cmd_idx < CMD_LAST_INDEX)		snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);#endif	err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,				  PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);	if (err)		return err;	PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);	PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);	PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));	if (rmh->cmd_len > 1) {		/* send length */		data = rmh->cmd_len - 1;		err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,					  PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);		if (err)			return err;		PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);		PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);		PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));		for (i=1; i < rmh->cmd_len; i++) {			/* send other words */			data = rmh->cmd[i];#ifdef CONFIG_SND_DEBUG_DETECT			if (rmh->cmd_idx < CMD_LAST_INDEX)				snd_printdd("    cmd[%d]=%x\n", i, data);#endif			err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,						  PCXHR_ISR_HI08_TRDY,						  PCXHR_ISR_HI08_TRDY,						  PCXHR_TIMEOUT_DSP, &reg);			if (err)				return err;			PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);			PCXHR_OUTPB(mgr, PCXHR_DSP_TXM, (data>>8)&0xFF);			PCXHR_OUTPB(mgr, PCXHR_DSP_TXL, (data&0xFF));		}	}	/* wait for chk bit */	err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,				  PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &reg);	if (err)		return err;	/* test status ISR */	if (reg & PCXHR_ISR_HI08_ERR) {		/* ERROR, wait for receiver full */		err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,					  PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);		if (err) {			snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg);			return err;		}		/* read error code */		data  = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;		data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;		data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);		snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data);		err = -EINVAL;	} else {		/* read the response data */		err = pcxhr_read_rmh_status(mgr, rmh);	}	/* reset semaphore */	if (pcxhr_send_it_dsp(mgr, PCXHR_IT_RESET_SEMAPHORE, 1) < 0)		return -EIO;	return err;}/** * pcxhr_init_rmh - initialize the RMH instance * @rmh: the rmh pointer to be initialized * @cmd: the rmh command to be set */void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd){	snd_assert(cmd < CMD_LAST_INDEX, return);	rmh->cmd[0] = pcxhr_dsp_cmds[cmd].opcode;	rmh->cmd_len = 1;	rmh->stat_len = pcxhr_dsp_cmds[cmd].st_length;	rmh->dsp_stat = pcxhr_dsp_cmds[cmd].st_type;	rmh->cmd_idx = cmd;}void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh *rmh, int capture,			       unsigned int param1, unsigned int param2,			       unsigned int param3){	snd_assert(param1 <= MASK_FIRST_FIELD);	if (capture)		rmh->cmd[0] |= 0x800;		/* COMMAND_RECORD_MASK */	if (param1)		rmh->cmd[0] |= (param1 << FIELD_SIZE);	if (param2) {		snd_assert(param2 <= MASK_FIRST_FIELD);		rmh->cmd[0] |= param2;	}	if(param3) {		snd_assert(param3 <= MASK_DSP_WORD);		rmh->cmd[1] = param3;		rmh->cmd_len = 2;	}}/* * pcxhr_send_msg - send a DSP message with spinlock * @rmh: the rmh record to send and receive * * returns 0 if successful, or a negative error code. */int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh){	unsigned long flags;	int err;	spin_lock_irqsave(&mgr->msg_lock, flags);	err = pcxhr_send_msg_nolock(mgr, rmh);	spin_unlock_irqrestore(&mgr->msg_lock, flags);	return err;}static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr){	int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2);	/* least segnificant 12 bits are the pipe states for the playback audios */	/* next 12 bits are the pipe states for the capture audios	 * (PCXHR_PIPE_STATE_CAPTURE_OFFSET)	 */	start_mask &= 0xffffff;	snd_printdd("CMD_PIPE_STATE MBOX2=0x%06x\n", start_mask);	return start_mask;}#define PCXHR_PIPE_STATE_CAPTURE_OFFSET		12#define MAX_WAIT_FOR_DSP			20static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry){	struct pcxhr_rmh rmh;	int err;	int audio = 0;	*retry = 0;	while (audio_mask) {		if (audio_mask & 1) {			pcxhr_init_rmh(&rmh, CMD_CAN_START_PIPE);			if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) {				/* can start playback pipe */				pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0);			} else {				/* can start capture pipe */				pcxhr_set_pipe_cmd_params(&rmh, 1, audio -							  PCXHR_PIPE_STATE_CAPTURE_OFFSET,							  0, 0);			}			err = pcxhr_send_msg(mgr, &rmh);			if (err) {				snd_printk(KERN_ERR					   "error pipe start (CMD_CAN_START_PIPE) err=%x!\n",					   err);				return err;			}			/* if the pipe couldn't be prepaired for start, retry it later */			if (rmh.stat[0] == 0)				*retry |= (1<<audio);		}		audio_mask>>=1;		audio++;	}	return 0;}static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask){	struct pcxhr_rmh rmh;	int err;	int audio = 0;	while (audio_mask) {		if (audio_mask & 1) {			pcxhr_init_rmh(&rmh, CMD_STOP_PIPE);			if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET) {				/* stop playback pipe */				pcxhr_set_pipe_cmd_params(&rmh, 0, audio, 0, 0);			} else {				/* stop capture pipe */				pcxhr_set_pipe_cmd_params(&rmh, 1, audio -							  PCXHR_PIPE_STATE_CAPTURE_OFFSET,							  0, 0);			}			err = pcxhr_send_msg(mgr, &rmh);			if (err) {				snd_printk(KERN_ERR					   "error pipe stop (CMD_STOP_PIPE) err=%x!\n",					   err);				return err;			}		}		audio_mask>>=1;		audio++;	}	return 0;}

⌨️ 快捷键说明

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