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

📄 forte.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 4 页
字号:
	DPRINTK ("%s: %s want %d format, got %d\n", __FUNCTION__, channel->name, 		 format, channel->format);	return channel->format;}/**  * forte_channel_stereo: * @channel: 	Channel to toggle * @stereo:  	0 for Mono, 1 for Stereo * * Locking:	Must be called with lock held. */static intforte_channel_stereo (struct forte_channel *channel, unsigned int stereo){	int ret;	if (!channel || !channel->iobase)		return -EINVAL;	DPRINTK ("%s: %s stereo = %d\n", __FUNCTION__, channel->name, stereo);	switch (stereo) {	case 0:		channel->ctrl &= ~(FORTE_STEREO | FORTE_CHANNELS_MASK);		channel-> stereo = stereo;		ret = stereo;		break;	case 1:		channel->ctrl &= ~FORTE_CHANNELS_MASK;		channel->ctrl |= FORTE_STEREO;		channel-> stereo = stereo;		ret = stereo;		break;	default:		DPRINTK ("Unsupported channel format");		ret = -EINVAL;		break;	}	return ret;}/**  * forte_channel_buffer: * @channel:	Channel whose buffer to set up * * Locking:	Must be called with lock held. */static voidforte_channel_buffer (struct forte_channel *channel, int sz, int num){	unsigned int msecs, shift;	/* Go away, I'm busy */	if (channel->filled_frags || channel->bytes)		return;	/* Fragment size must be a power of 2 */	shift = 0; sz++;	while (sz >>= 1)		shift++;	channel->frag_sz = 1 << shift;	/* Round fragment size to something reasonable */	if (channel->frag_sz < FORTE_MIN_FRAG_SIZE)		channel->frag_sz = FORTE_MIN_FRAG_SIZE;	if (channel->frag_sz > FORTE_MAX_FRAG_SIZE)		channel->frag_sz = FORTE_MAX_FRAG_SIZE;	/* Find fragment length in milliseconds */	msecs = channel->frag_sz /		(channel->format == AFMT_S16_LE ? 2 : 1) /		(channel->stereo ? 2 : 1) /		(channel->rate / 1000);	channel->frag_msecs = msecs;	/* Pick a suitable number of fragments */	if (msecs * num < FORTE_MIN_BUF_MSECS)	     num = FORTE_MIN_BUF_MSECS / msecs;	if (msecs * num > FORTE_MAX_BUF_MSECS)	     num = FORTE_MAX_BUF_MSECS / msecs;	/* Fragment number must be a power of 2 */	shift = 0;		while (num >>= 1)		shift++;	channel->frag_num = 1 << (shift + 1);	/* Round fragment number to something reasonable */	if (channel->frag_num < FORTE_MIN_FRAGMENTS)		channel->frag_num = FORTE_MIN_FRAGMENTS;	if (channel->frag_num > FORTE_MAX_FRAGMENTS)		channel->frag_num = FORTE_MAX_FRAGMENTS;	channel->buf_sz = channel->frag_sz * channel->frag_num;	DPRINTK ("%s: %s frag_sz = %d, frag_num = %d, buf_sz = %d\n",		 __FUNCTION__, channel->name, channel->frag_sz, 		 channel->frag_num, channel->buf_sz);}/**  * forte_channel_prep: * @channel:	Channel whose buffer to prepare * * Locking:	Lock held. */static voidforte_channel_prep (struct forte_channel *channel){	struct page *page;	int i;		if (channel->buf)		return;	forte_channel_buffer (channel, channel->frag_sz, channel->frag_num);	channel->buf_pages = channel->buf_sz >> PAGE_SHIFT;	if (channel->buf_sz % PAGE_SIZE)		channel->buf_pages++;	DPRINTK ("%s: %s frag_sz = %d, frag_num = %d, buf_sz = %d, pg = %d\n", 		 __FUNCTION__, channel->name, channel->frag_sz, 		 channel->frag_num, channel->buf_sz, channel->buf_pages);	/* DMA buffer */	channel->buf = pci_alloc_consistent (forte->pci_dev, 					     channel->buf_pages * PAGE_SIZE,					     &channel->buf_handle);	if (!channel->buf || !channel->buf_handle)		BUG();	page = virt_to_page (channel->buf);		/* FIXME: can this go away ? */	for (i = 0 ; i < channel->buf_pages ; i++)		SetPageReserved(page++);	/* Prep buffer registers */	outw (channel->frag_sz - 1, channel->iobase + FORTE_PLY_COUNT);	outl (channel->buf_handle, channel->iobase + FORTE_PLY_BUF1);	outl (channel->buf_handle + channel->frag_sz, 	      channel->iobase + FORTE_PLY_BUF2);	/* Reset hwptr */ 	channel->hwptr = channel->frag_sz;	channel->next_buf = 1;	DPRINTK ("%s: %s buffer @ %p (%p)\n", __FUNCTION__, channel->name, 		 channel->buf, channel->buf_handle);}/**  * forte_channel_drain: * @chip:	 * @channel:	 * * Locking:	Don't hold the lock. */static inline intforte_channel_drain (struct forte_channel *channel){	DECLARE_WAITQUEUE (wait, current);	unsigned long flags;	DPRINTK ("%s\n", __FUNCTION__);	if (channel->mapped) {		spin_lock_irqsave (&forte->lock, flags);		forte_channel_stop (channel);		spin_unlock_irqrestore (&forte->lock, flags);		return 0;	}	spin_lock_irqsave (&forte->lock, flags);	add_wait_queue (&channel->wait, &wait);	for (;;) {		if (channel->active == 0 || channel->filled_frags == 1)			break;		spin_unlock_irqrestore (&forte->lock, flags);		__set_current_state (TASK_INTERRUPTIBLE);		schedule();		spin_lock_irqsave (&forte->lock, flags);	}	forte_channel_stop (channel);	forte_channel_reset (channel);	set_current_state (TASK_RUNNING);	remove_wait_queue (&channel->wait, &wait);	spin_unlock_irqrestore (&forte->lock, flags);	return 0;}/**  * forte_channel_init: * @chip: 	Forte chip instance the channel hangs off * @channel: 	Channel to initialize * * Description: *	        Initializes a channel, sets defaults, and allocates *	        buffers. * * Locking:	No lock held. */static intforte_channel_init (struct forte_chip *chip, struct forte_channel *channel){	DPRINTK ("%s: chip iobase @ %p\n", __FUNCTION__, (void *)chip->iobase);	spin_lock_irq (&chip->lock);	memset (channel, 0x0, sizeof (*channel));	if (channel == &chip->play) {		channel->name = "PCM_OUT";		channel->iobase = chip->iobase;		DPRINTK ("%s: PCM-OUT iobase @ %p\n", __FUNCTION__,			 (void *) channel->iobase);	}	else if (channel == &chip->rec) {		channel->name = "PCM_IN";		channel->iobase = chip->iobase + FORTE_CAP_OFFSET;		channel->record = 1;		DPRINTK ("%s: PCM-IN iobase @ %p\n", __FUNCTION__, 			 (void *) channel->iobase);	}	else		BUG();	init_waitqueue_head (&channel->wait);	/* Defaults: 48kHz, 16-bit, stereo */	channel->ctrl = inw (channel->iobase + FORTE_PLY_CTRL);	forte_channel_reset (channel);	forte_channel_stereo (channel, 1);	forte_channel_format (channel, AFMT_S16_LE);	forte_channel_rate (channel, 48000);	channel->frag_sz = FORTE_DEF_FRAG_SIZE;	channel->frag_num = FORTE_DEF_FRAGMENTS;	chip->trigger = 0;	spin_unlock_irq (&chip->lock);	return 0;}/**  * forte_channel_free: * @chip:	Chip this channel hangs off * @channel:	Channel to nuke  * * Description: * 		Resets channel and frees buffers. * * Locking:	Hold your horses. */static voidforte_channel_free (struct forte_chip *chip, struct forte_channel *channel){	DPRINTK ("%s: %s\n", __FUNCTION__, channel->name);	if (!channel->buf_handle)		return;	pci_free_consistent (chip->pci_dev, channel->buf_pages * PAGE_SIZE, 			     channel->buf, channel->buf_handle);		memset (channel, 0x0, sizeof (*channel));}/* DSP --------------------------------------------------------------------- *//** * forte_dsp_ioctl: */static intforte_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd,		 unsigned long arg){	int ival=0, ret, rval=0, rd, wr, count;	struct forte_chip *chip;	struct audio_buf_info abi;	struct count_info cinfo;	void __user *argp = (void __user *)arg;	int __user *p = argp;	chip = file->private_data;		if (file->f_mode & FMODE_WRITE)		wr = 1;	else 		wr = 0;	if (file->f_mode & FMODE_READ)		rd = 1;	else		rd = 0;	switch (cmd) {	case OSS_GETVERSION:		return put_user (SOUND_VERSION, p);	case SNDCTL_DSP_GETCAPS:		DPRINTK ("%s: GETCAPS\n", __FUNCTION__);		ival = FORTE_CAPS; /* DUPLEX */		return put_user (ival, p);	case SNDCTL_DSP_GETFMTS:		DPRINTK ("%s: GETFMTS\n", __FUNCTION__);		ival = FORTE_FMTS; /* U8, 16LE */		return put_user (ival, p);	case SNDCTL_DSP_SETFMT:	/* U8, 16LE */		DPRINTK ("%s: SETFMT\n", __FUNCTION__);		if (get_user (ival, p))			return -EFAULT;		spin_lock_irq (&chip->lock);		if (rd) {			forte_channel_stop (&chip->rec);			rval = forte_channel_format (&chip->rec, ival);		}		if (wr) {			forte_channel_stop (&chip->rec);			rval = forte_channel_format (&chip->play, ival);		}		spin_unlock_irq (&chip->lock);			return put_user (rval, p);	case SNDCTL_DSP_STEREO:	/* 0 - mono, 1 - stereo */		DPRINTK ("%s: STEREO\n", __FUNCTION__);		if (get_user (ival, p))			return -EFAULT;		spin_lock_irq (&chip->lock);		if (rd) {			forte_channel_stop (&chip->rec);			rval = forte_channel_stereo (&chip->rec, ival);		}		if (wr) {			forte_channel_stop (&chip->rec);			rval = forte_channel_stereo (&chip->play, ival);		}		spin_unlock_irq (&chip->lock);                return put_user (rval, p);	case SNDCTL_DSP_CHANNELS: /* 1 - mono, 2 - stereo */		DPRINTK ("%s: CHANNELS\n", __FUNCTION__);		if (get_user (ival, p))			return -EFAULT;		spin_lock_irq (&chip->lock);		if (rd) {			forte_channel_stop (&chip->rec);			rval = forte_channel_stereo (&chip->rec, ival-1) + 1;		}		if (wr) {			forte_channel_stop (&chip->play);			rval = forte_channel_stereo (&chip->play, ival-1) + 1;		}		spin_unlock_irq (&chip->lock);                return put_user (rval, p);	case SNDCTL_DSP_SPEED:		DPRINTK ("%s: SPEED\n", __FUNCTION__);		if (get_user (ival, p))                        return -EFAULT;		spin_lock_irq (&chip->lock);		if (rd) {			forte_channel_stop (&chip->rec);			rval = forte_channel_rate (&chip->rec, ival);		}		if (wr) {			forte_channel_stop (&chip->play);			rval = forte_channel_rate (&chip->play, ival);		}		spin_unlock_irq (&chip->lock);                return put_user(rval, p);	case SNDCTL_DSP_GETBLKSIZE:		DPRINTK ("%s: GETBLKSIZE\n", __FUNCTION__);		spin_lock_irq (&chip->lock);		if (rd)			ival = chip->rec.frag_sz;		if (wr)			ival = chip->play.frag_sz;		spin_unlock_irq (&chip->lock);                return put_user (ival, p);	case SNDCTL_DSP_RESET:		DPRINTK ("%s: RESET\n", __FUNCTION__);		spin_lock_irq (&chip->lock);		if (rd)			forte_channel_reset (&chip->rec);		if (wr)			forte_channel_reset (&chip->play);		spin_unlock_irq (&chip->lock);                return 0;	case SNDCTL_DSP_SYNC:		DPRINTK ("%s: SYNC\n", __FUNCTION__);		if (wr)			ret = forte_channel_drain (&chip->play);		return 0;	case SNDCTL_DSP_POST:		DPRINTK ("%s: POST\n", __FUNCTION__);		if (wr) {			spin_lock_irq (&chip->lock);			if (chip->play.filled_frags)				forte_channel_start (&chip->play);			spin_unlock_irq (&chip->lock);		}                return 0;	case SNDCTL_DSP_SETFRAGMENT:		DPRINTK ("%s: SETFRAGMENT\n", __FUNCTION__);		if (get_user (ival, p))			return -EFAULT;		spin_lock_irq (&chip->lock);		if (rd) {			forte_channel_buffer (&chip->rec, ival & 0xffff, 					      (ival >> 16) & 0xffff);			ival = (chip->rec.frag_num << 16) + chip->rec.frag_sz;		}		if (wr) {			forte_channel_buffer (&chip->play, ival & 0xffff, 					      (ival >> 16) & 0xffff);			ival = (chip->play.frag_num << 16) +chip->play.frag_sz;		}		spin_unlock_irq (&chip->lock);		return put_user (ival, p);                        case SNDCTL_DSP_GETISPACE:		DPRINTK ("%s: GETISPACE\n", __FUNCTION__);		if (!rd)			return -EINVAL;		spin_lock_irq (&chip->lock);		abi.fragstotal = chip->rec.frag_num;		abi.fragsize = chip->rec.frag_sz;					if (chip->rec.mapped) {			abi.fragments = chip->rec.frag_num - 2;			abi.bytes = abi.fragments * abi.fragsize;		}		else {			abi.fragments = chip->rec.filled_frags;			abi.bytes = abi.fragments * abi.fragsize;		}		spin_unlock_irq (&chip->lock);		return copy_to_user (argp, &abi, sizeof (abi)) ? -EFAULT : 0;	case SNDCTL_DSP_GETIPTR:		DPRINTK ("%s: GETIPTR\n", __FUNCTION__);

⌨️ 快捷键说明

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