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

📄 sa1100-audio.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 2 页
字号:
		audio_buf_t *buf = &s->buffers[i];		if (!buf->master)			continue;		ret = remap_page_range(vma_addr, buf->dma_addr, buf->master, vma->vm_page_prot);		if (ret)			return ret;		vma_addr += buf->master;	}	s->mapped = 1;	return 0;}static unsigned int audio_poll(struct file *file,			       struct poll_table_struct *wait){	audio_state_t *state = (audio_state_t *)file->private_data;	audio_stream_t *is = state->input_stream;	audio_stream_t *os = state->output_stream;	unsigned int mask = 0;	int i;	DPRINTK("audio_poll(): mode=%s%s\n",		(file->f_mode & FMODE_READ) ? "r" : "",		(file->f_mode & FMODE_WRITE) ? "w" : "");	if (file->f_mode & FMODE_READ) {		/* Start audio input if not already active */		if (!is->active) {			if (!is->buffers && audio_setup_buf(is))				return -ENOMEM;			audio_check_tx_spin(state);			audio_prime_dma(is);		}		poll_wait(file, &is->wq, wait);	}	if (file->f_mode & FMODE_WRITE) {		if (!os->buffers && audio_setup_buf(os))			return -ENOMEM;		poll_wait(file, &os->wq, wait);	}	if (file->f_mode & FMODE_READ) {		if (is->mapped) {			if (is->bytecount > 0)				mask |= POLLIN | POLLRDNORM;		} else {			for (i = 0; i < is->nbfrags; i++) {				if (atomic_read(&is->buffers[i].sem.count) > 0) {					mask |= POLLIN | POLLRDNORM;					break;				}			}		}	}	if (file->f_mode & FMODE_WRITE) {		if (os->mapped) {			if (os->bytecount > 0)				mask |= POLLOUT | POLLWRNORM;		} else {			for (i = 0; i < os->nbfrags; i++) {				if (atomic_read(&os->buffers[i].sem.count) > 0) {					mask |= POLLOUT | POLLWRNORM;					break;				}			}		}	}	DPRINTK("audio_poll() returned mask of %s%s\n",		(mask & POLLIN) ? "r" : "",		(mask & POLLOUT) ? "w" : "");	return mask;}static loff_t audio_llseek(struct file *file, loff_t offset, int origin){	return -ESPIPE;}static int audio_set_fragments(audio_stream_t *s, int val){	if (s->active)		return -EBUSY;	if (s->buffers)		audio_clear_buf(s);	s->nbfrags = (val >> 16) & 0x7FFF;	val &= 0xffff;	if (val < 4)		val = 4;	if (val > 15)		val = 15;	s->fragsize = 1 << val;	if (s->nbfrags < 2)		s->nbfrags = 2;	if (s->nbfrags * s->fragsize > 128 * 1024)		s->nbfrags = 128 * 1024 / s->fragsize;	if (audio_setup_buf(s))		return -ENOMEM;	return val|(s->nbfrags << 16);}static int audio_ioctl(struct inode *inode, struct file *file,		       uint cmd, ulong arg){	audio_state_t *state = (audio_state_t *)file->private_data;	audio_stream_t *os = state->output_stream;	audio_stream_t *is = state->input_stream;	long val;	/* dispatch based on command */	switch (cmd) {	case OSS_GETVERSION:		return put_user(SOUND_VERSION, (int *)arg);	case SNDCTL_DSP_GETBLKSIZE:		if (file->f_mode & FMODE_WRITE)			return put_user(os->fragsize, (int *)arg);		else			return put_user(is->fragsize, (int *)arg);	case SNDCTL_DSP_GETCAPS:		val = DSP_CAP_REALTIME|DSP_CAP_TRIGGER|DSP_CAP_MMAP;		if (is && os)			val |= DSP_CAP_DUPLEX;		return put_user(val, (int *)arg);	case SNDCTL_DSP_SETFRAGMENT:		if (get_user(val, (long *) arg))			return -EFAULT;		if (file->f_mode & FMODE_READ) {			int ret = audio_set_fragments(is, val);			if (ret < 0)				return ret;			ret = put_user(ret, (int *)arg);			if (ret)				return ret;		}		if (file->f_mode & FMODE_WRITE) {			int ret = audio_set_fragments(os, val);			if (ret < 0)				return ret;			ret = put_user(ret, (int *)arg);			if (ret)				return ret;		}		return 0;	case SNDCTL_DSP_SYNC:		return audio_sync(file);	case SNDCTL_DSP_SETDUPLEX:		return 0;	case SNDCTL_DSP_POST:		return 0;	case SNDCTL_DSP_GETTRIGGER:		val = 0;		if (file->f_mode & FMODE_READ && is->active && !is->stopped)			val |= PCM_ENABLE_INPUT;		if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)			val |= PCM_ENABLE_OUTPUT;		return put_user(val, (int *)arg);	case SNDCTL_DSP_SETTRIGGER:		if (get_user(val, (int *)arg))			return -EFAULT;		if (file->f_mode & FMODE_READ) {			if (val & PCM_ENABLE_INPUT) {				if (!is->active) {					if (!is->buffers && audio_setup_buf(is))						return -ENOMEM;					audio_prime_dma(is);				}				audio_check_tx_spin(state);				if (is->stopped) {					is->stopped = 0;					sa1100_dma_resume(is->dma_ch);				}			} else {				sa1100_dma_stop(is->dma_ch);				is->stopped = 1;			}		}		if (file->f_mode & FMODE_WRITE) {			if (val & PCM_ENABLE_OUTPUT) {				if (!os->active) {					if (!os->buffers && audio_setup_buf(os))						return -ENOMEM;					if (os->mapped)						audio_prime_dma(os);				}				if (os->stopped) {					os->stopped = 0;					sa1100_dma_resume(os->dma_ch);				}			} else {				sa1100_dma_stop(os->dma_ch);				os->stopped = 1;			}		}		return 0;	case SNDCTL_DSP_GETOPTR:	case SNDCTL_DSP_GETIPTR:	    {		count_info inf = { 0, };		audio_stream_t *s = (cmd == SNDCTL_DSP_GETOPTR) ? os : is;		audio_buf_t *b;		dma_addr_t ptr;		int bytecount, offset, flags;		if ((s == is && !(file->f_mode & FMODE_READ)) ||		    (s == os && !(file->f_mode & FMODE_WRITE)))			return -EINVAL;		if (s->active) {			save_flags_cli(flags);			if (sa1100_dma_get_current(s->dma_ch, (void *)&b, &ptr) == 0) {				offset = ptr - b->dma_addr;				inf.ptr = (b - s->buffers) * s->fragsize + offset;			} else offset = 0;			bytecount = s->bytecount + offset;			s->bytecount = -offset;			inf.blocks = s->fragcount;			s->fragcount = 0;			restore_flags(flags);			if (bytecount < 0)				bytecount = 0;			inf.bytes = bytecount;		}		return copy_to_user((void *)arg, &inf, sizeof(inf));	    }	case SNDCTL_DSP_GETOSPACE:	    {		audio_buf_info inf = { 0, };		int i;		if (!(file->f_mode & FMODE_WRITE))			return -EINVAL;		if (!os->buffers && audio_setup_buf(os))			return -ENOMEM;		for (i = 0; i < os->nbfrags; i++) {			if (atomic_read(&os->buffers[i].sem.count) > 0) {				if (os->buffers[i].size == 0)					inf.fragments++;				inf.bytes += os->fragsize - os->buffers[i].size;			}		}		inf.fragstotal = os->nbfrags;		inf.fragsize = os->fragsize;		return copy_to_user((void *)arg, &inf, sizeof(inf));	    }	case SNDCTL_DSP_GETISPACE:	    {		audio_buf_info inf = { 0, };		int i;		if (!(file->f_mode & FMODE_READ))			return -EINVAL;		if (!is->buffers && audio_setup_buf(is))			return -ENOMEM;		for (i = 0; i < is->nbfrags; i++) {			if (atomic_read(&is->buffers[i].sem.count) > 0) {				if (is->buffers[i].size == is->fragsize)					inf.fragments++;				inf.bytes += is->buffers[i].size;			}		}		inf.fragstotal = is->nbfrags;		inf.fragsize = is->fragsize;		return copy_to_user((void *)arg, &inf, sizeof(inf));	    }	case SNDCTL_DSP_NONBLOCK:		file->f_flags |= O_NONBLOCK;		return 0;	case SNDCTL_DSP_RESET:		if (file->f_mode & FMODE_READ) {			if (state->tx_spinning) {				sa1100_dma_set_spin(os->dma_ch, 0, 0);				state->tx_spinning = 0;			}			audio_reset_buf(is);		}		if (file->f_mode & FMODE_WRITE) {			audio_reset_buf(os);		}		return 0;	default:		/*		 * Let the client of this module handle the		 * non generic ioctls		 */		return state->client_ioctl(inode, file, cmd, arg);	}	return 0;}static int audio_release(struct inode *inode, struct file *file){	audio_state_t *state = (audio_state_t *)file->private_data;	DPRINTK("audio_release\n");	down(&state->sem);	if (file->f_mode & FMODE_READ) {		if (state->tx_spinning) {			sa1100_dma_set_spin(state->output_stream->dma_ch, 0, 0);			state->tx_spinning = 0;		}		audio_clear_buf(state->input_stream);		if (!state->skip_dma_init) {			sa1100_free_dma(state->input_stream->dma_ch);			if (state->need_tx_for_rx && !state->wr_ref)				sa1100_free_dma(state->output_stream->dma_ch);		}		state->rd_ref = 0;	}	if (file->f_mode & FMODE_WRITE) {		audio_sync(file);		audio_clear_buf(state->output_stream);		if (!state->skip_dma_init)			if (!state->need_tx_for_rx || !state->rd_ref)				sa1100_free_dma(state->output_stream->dma_ch);		state->wr_ref = 0;	}	if (!AUDIO_ACTIVE(state)) {	       if (state->hw_shutdown)		       state->hw_shutdown(state->data);#ifdef CONFIG_PM	       pm_unregister(state->pm_dev);#endif	}	up(&state->sem);	return 0;}#ifdef CONFIG_PMstatic int audio_pm_callback(struct pm_dev *pm_dev, pm_request_t req, void *data){	audio_state_t *state = (audio_state_t *)pm_dev->data;	switch (req) {	case PM_SUSPEND: /* enter D1-D3 */		if (state->output_stream)			sa1100_dma_sleep(state->output_stream->dma_ch);		if (state->input_stream)			sa1100_dma_sleep(state->input_stream->dma_ch);		if (AUDIO_ACTIVE(state) && state->hw_shutdown)			state->hw_shutdown(state->data);		break;	case PM_RESUME:  /* enter D0 */		if (AUDIO_ACTIVE(state) && state->hw_init)			state->hw_init(state->data);		if (state->input_stream)			sa1100_dma_wakeup(state->input_stream->dma_ch);		if (state->output_stream)			sa1100_dma_wakeup(state->output_stream->dma_ch);		break;	}	return 0;}#endifint sa1100_audio_attach(struct inode *inode, struct file *file,			  audio_state_t *state){	int err, need_tx_dma;	DPRINTK("audio_open\n");	down(&state->sem);	/* access control */	err = -ENODEV;	if ((file->f_mode & FMODE_WRITE) && !state->output_stream)		goto out;	if ((file->f_mode & FMODE_READ) && !state->input_stream)		goto out;	err = -EBUSY;	if ((file->f_mode & FMODE_WRITE) && state->wr_ref)		goto out;	if ((file->f_mode & FMODE_READ) && state->rd_ref)		goto out;	err = -EINVAL;	if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)		goto out;	/* request DMA channels */	if (state->skip_dma_init)		goto skip_dma;	need_tx_dma = ((file->f_mode & FMODE_WRITE) ||		       ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));	if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))		need_tx_dma = 0;	if (need_tx_dma) {		err = sa1100_request_dma(&state->output_stream->dma_ch,					 state->output_id,					 state->output_dma);		if (err)			goto out;	}	if (file->f_mode & FMODE_READ) {		err = sa1100_request_dma(&state->input_stream->dma_ch,					 state->input_id,					 state->input_dma);		if (err) {			if (need_tx_dma)				sa1100_free_dma(state->output_stream->dma_ch);			goto out;		}	}skip_dma:	/* now complete initialisation */	if (!AUDIO_ACTIVE(state)) {		if (state->hw_init)			state->hw_init(state->data);#ifdef CONFIG_PM		state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);		if (state->pm_dev)			state->pm_dev->data = state;#endif	}	if ((file->f_mode & FMODE_WRITE)) {		state->wr_ref = 1;		audio_clear_buf(state->output_stream);		state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;		state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;		state->output_stream->mapped = 0;		sa1100_dma_set_callback(state->output_stream->dma_ch,					audio_dmaout_done_callback);		init_waitqueue_head(&state->output_stream->wq);	}	if (file->f_mode & FMODE_READ) {		state->rd_ref = 1;		audio_clear_buf(state->input_stream);		state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;		state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;		state->input_stream->mapped = 0;		sa1100_dma_set_callback(state->input_stream->dma_ch,					audio_dmain_done_callback);		init_waitqueue_head(&state->input_stream->wq);	}	file->private_data	= state;	file->f_op->release	= audio_release;	file->f_op->write	= audio_write;	file->f_op->read	= audio_read;	file->f_op->mmap	= audio_mmap;	file->f_op->poll	= audio_poll;	file->f_op->ioctl	= audio_ioctl;	file->f_op->llseek	= audio_llseek;	err = 0;out:	up(&state->sem);	return err;}EXPORT_SYMBOL(sa1100_audio_attach);MODULE_AUTHOR("Nicolas Pitre");MODULE_DESCRIPTION("Common audio handling for the SA11x0 processor");MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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