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

📄 cs46xx.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 5 页
字号:
        }        if (wake)                wake_up(&card->midi.iwait);        wake = 0;        while (!(cs461x_peekBA0(card,  BA0_MIDSR) & MIDSR_TBF) && card->midi.ocnt > 0) {                temp1 = ( card->midi.obuf[card->midi.ord] ) & 0x000000ff;                cs461x_pokeBA0(card, BA0_MIDWP,temp1);                card->midi.ord = (card->midi.ord + 1) % CS_MIDIOUTBUF;                card->midi.ocnt--;                if (card->midi.ocnt < CS_MIDIOUTBUF-16)                        wake = 1;        }        if (wake)                wake_up(&card->midi.owait);}static void cs_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct cs_card *card = (struct cs_card *)dev_id;	/* Single channel card */	struct cs_state *recstate = card->channel[0].state;	struct cs_state *playstate = card->channel[1].state;	u32 status;	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()+ \n"));	spin_lock(&card->lock);	status = cs461x_peekBA0(card, BA0_HISR);		if ((status & 0x7fffffff) == 0)	{		cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);		spin_unlock(&card->lock);		return;	}		/*	 * check for playback or capture interrupt only	 */	if( ((status & HISR_VC0) && playstate && playstate->dmabuf.ready) || 	    (((status & HISR_VC1) && recstate && recstate->dmabuf.ready)) )	{		CS_DBGOUT(CS_INTERRUPT, 8, printk(			"cs46xx: cs_interrupt() interrupt bit(s) set (0x%x)\n",status));		cs_update_ptr(card, CS_TRUE);	}        if( status & HISR_MIDI )                cs_handle_midi(card);	 	/* clear 'em */	cs461x_pokeBA0(card, BA0_HICR, HICR_CHGM|HICR_IEV);	spin_unlock(&card->lock);	CS_DBGOUT(CS_INTERRUPT, 9, printk("cs46xx: cs_interrupt()- \n"));}/**********************************************************************/static ssize_t cs_midi_read(struct file *file, char *buffer, size_t count, loff_t *ppos){        struct cs_card *card = (struct cs_card *)file->private_data;        ssize_t ret;        unsigned long flags;        unsigned ptr;        int cnt;        if (ppos != &file->f_pos)                return -ESPIPE;        if (!access_ok(VERIFY_WRITE, buffer, count))                return -EFAULT;        ret = 0;        while (count > 0) {                spin_lock_irqsave(&card->lock, flags);                ptr = card->midi.ird;                cnt = CS_MIDIINBUF - ptr;                if (card->midi.icnt < cnt)                        cnt = card->midi.icnt;                spin_unlock_irqrestore(&card->lock, flags);                if (cnt > count)                        cnt = count;                if (cnt <= 0) {                        if (file->f_flags & O_NONBLOCK)                                return ret ? ret : -EAGAIN;                        interruptible_sleep_on(&card->midi.iwait);                        if (signal_pending(current))                                return ret ? ret : -ERESTARTSYS;                        continue;                }                if (copy_to_user(buffer, card->midi.ibuf + ptr, cnt))                        return ret ? ret : -EFAULT;                ptr = (ptr + cnt) % CS_MIDIINBUF;                spin_lock_irqsave(&card->lock, flags);                card->midi.ird = ptr;                card->midi.icnt -= cnt;                spin_unlock_irqrestore(&card->lock, flags);                count -= cnt;                buffer += cnt;                ret += cnt;        }        return ret;}static ssize_t cs_midi_write(struct file *file, const char *buffer, size_t count, loff_t *ppos){        struct cs_card *card = (struct cs_card *)file->private_data;        ssize_t ret;        unsigned long flags;        unsigned ptr;        int cnt;        if (ppos != &file->f_pos)                return -ESPIPE;        if (!access_ok(VERIFY_READ, buffer, count))                return -EFAULT;        ret = 0;        while (count > 0) {                spin_lock_irqsave(&card->lock, flags);                ptr = card->midi.owr;                cnt = CS_MIDIOUTBUF - ptr;                if (card->midi.ocnt + cnt > CS_MIDIOUTBUF)                        cnt = CS_MIDIOUTBUF - card->midi.ocnt;                if (cnt <= 0)                        cs_handle_midi(card);                spin_unlock_irqrestore(&card->lock, flags);                if (cnt > count)                        cnt = count;                if (cnt <= 0) {                        if (file->f_flags & O_NONBLOCK)                                return ret ? ret : -EAGAIN;                        interruptible_sleep_on(&card->midi.owait);                        if (signal_pending(current))                                return ret ? ret : -ERESTARTSYS;                        continue;                }                if (copy_from_user(card->midi.obuf + ptr, buffer, cnt))                        return ret ? ret : -EFAULT;                ptr = (ptr + cnt) % CS_MIDIOUTBUF;                spin_lock_irqsave(&card->lock, flags);                card->midi.owr = ptr;                card->midi.ocnt += cnt;                spin_unlock_irqrestore(&card->lock, flags);                count -= cnt;                buffer += cnt;                ret += cnt;                spin_lock_irqsave(&card->lock, flags);                cs_handle_midi(card);                spin_unlock_irqrestore(&card->lock, flags);        }        return ret;}static unsigned int cs_midi_poll(struct file *file, struct poll_table_struct *wait){        struct cs_card *card = (struct cs_card *)file->private_data;        unsigned long flags;        unsigned int mask = 0;        if (file->f_flags & FMODE_WRITE)                poll_wait(file, &card->midi.owait, wait);        if (file->f_flags & FMODE_READ)                poll_wait(file, &card->midi.iwait, wait);        spin_lock_irqsave(&card->lock, flags);        if (file->f_flags & FMODE_READ) {                if (card->midi.icnt > 0)                        mask |= POLLIN | POLLRDNORM;        }        if (file->f_flags & FMODE_WRITE) {                if (card->midi.ocnt < CS_MIDIOUTBUF)                        mask |= POLLOUT | POLLWRNORM;        }        spin_unlock_irqrestore(&card->lock, flags);        return mask;}static int cs_midi_open(struct inode *inode, struct file *file){        int minor = MINOR(inode->i_rdev);        struct cs_card *card=NULL;        unsigned long flags;	struct list_head *entry;	list_for_each(entry, &cs46xx_devs)	{		card = list_entry(entry, struct cs_card, list);		if (card->dev_midi == minor)			break;	}	if (entry == &cs46xx_devs)		return -ENODEV;	if (!card)	{		CS_DBGOUT(CS_FUNCTION | CS_OPEN, 2, printk(KERN_INFO			"cs46xx: cs46xx_midi_open(): Error - unable to find card struct\n"));		return -ENODEV;	}        file->private_data = card;        /* wait for device to become free */        down(&card->midi.open_sem);        while (card->midi.open_mode & file->f_mode) {                if (file->f_flags & O_NONBLOCK) {                        up(&card->midi.open_sem);                        return -EBUSY;                }                up(&card->midi.open_sem);                interruptible_sleep_on(&card->midi.open_wait);                if (signal_pending(current))                        return -ERESTARTSYS;                down(&card->midi.open_sem);        }        spin_lock_irqsave(&card->midi.lock, flags);        if (!(card->midi.open_mode & (FMODE_READ | FMODE_WRITE))) {                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;                cs461x_pokeBA0(card, BA0_MIDCR, 0x0000000f);            /* Enable xmit, rcv. */                cs461x_pokeBA0(card, BA0_HICR, HICR_IEV | HICR_CHGM);   /* Enable interrupts */        }        if (file->f_mode & FMODE_READ) {                card->midi.ird = card->midi.iwr = card->midi.icnt = 0;        }        if (file->f_mode & FMODE_WRITE) {                card->midi.ord = card->midi.owr = card->midi.ocnt = 0;        }        spin_unlock_irqrestore(&card->midi.lock, flags);        card->midi.open_mode |= (file->f_mode & (FMODE_READ | FMODE_WRITE));        up(&card->midi.open_sem);        MOD_INC_USE_COUNT; /* for 2.2 */        return 0;}static int cs_midi_release(struct inode *inode, struct file *file){        struct cs_card *card = (struct cs_card *)file->private_data;        DECLARE_WAITQUEUE(wait, current);        unsigned long flags;        unsigned count, tmo;        if (file->f_mode & FMODE_WRITE) {                current->state = TASK_INTERRUPTIBLE;                add_wait_queue(&card->midi.owait, &wait);                for (;;) {                        spin_lock_irqsave(&card->midi.lock, flags);                        count = card->midi.ocnt;                        spin_unlock_irqrestore(&card->midi.lock, flags);                        if (count <= 0)                                break;                        if (signal_pending(current))                                break;                        if (file->f_flags & O_NONBLOCK)                        	break;                        tmo = (count * HZ) / 3100;                        if (!schedule_timeout(tmo ? : 1) && tmo)                                printk(KERN_DEBUG "cs46xx: midi timed out??\n");                }                remove_wait_queue(&card->midi.owait, &wait);                current->state = TASK_RUNNING;        }        down(&card->midi.open_sem);        card->midi.open_mode &= (~(file->f_mode & (FMODE_READ | FMODE_WRITE)));        up(&card->midi.open_sem);        wake_up(&card->midi.open_wait);        MOD_DEC_USE_COUNT; /* for 2.2 */        return 0;}/* *   Midi file operations struct. */static /*const*/ struct file_operations cs_midi_fops = {	CS_OWNER	CS_THIS_MODULE	llseek:		no_llseek,	read:		cs_midi_read,	write:		cs_midi_write,	poll:		cs_midi_poll,	open:		cs_midi_open,	release:	cs_midi_release,};/* * * CopySamples copies 16-bit stereo signed samples from the source to the * destination, possibly converting down to unsigned 8-bit and/or mono. * count specifies the number of output bytes to write. * *  Arguments: * *  dst             - Pointer to a destination buffer. *  src             - Pointer to a source buffer *  count           - The number of bytes to copy into the destination buffer. *  fmt             - CS_FMT_16BIT and/or CS_FMT_STEREO bits *  dmabuf          - pointer to the dma buffer structure * * NOTES: only call this routine if the output desired is not 16 Signed Stereo * 	 * */static void CopySamples(char *dst, char *src, int count, unsigned fmt, 		struct dmabuf *dmabuf){    s32 s32AudioSample;    s16 *psSrc=(s16 *)src;    s16 *psDst=(s16 *)dst;    u8 *pucDst=(u8 *)dst;    CS_DBGOUT(CS_FUNCTION, 2, printk(KERN_INFO "cs46xx: CopySamples()+ ") );    CS_DBGOUT(CS_WAVE_READ, 8, printk(KERN_INFO	" dst=0x%x src=0x%x count=%d fmt=0x%x\n",	(unsigned)dst,(unsigned)src,(unsigned)count,(unsigned)fmt) );    /*     * See if the data should be output as 8-bit unsigned stereo.     */    if((fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 8-bit unsigned 	 * stereo using rounding.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {            *(pucDst++) = (u8)(((s16)(*psSrc++) + (s16)0x8000) >> 8);        }    }    /*     * See if the data should be output at 8-bit unsigned mono.     */    else if(!(fmt & CS_FMT_STEREO) && !(fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 8-bit unsigned 	 * mono using averaging and rounding.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {	    s32AudioSample = ((*psSrc)+(*(psSrc + 1)))/2 + (s32)0x80;	    if(s32AudioSample > 0x7fff)	    	s32AudioSample = 0x7fff;            *(pucDst++) = (u8)(((s16)s32AudioSample + (s16)0x8000) >> 8);	    psSrc += 2;        }    }    /*     * See if the data should be output at 16-bit signed mono.     */    else if(!(fmt & CS_FMT_STEREO) && (fmt & CS_FMT_16BIT))    {        /*         * Convert each 16-bit signed stereo sample to 16-bit signed 	 * mono using averaging.         */        psSrc = (s16 *)src;	count = count/2;        while(count--)        {            *(psDst++) = (s16)((*psSrc)+(*(psSrc + 1)))/2;	    psSrc += 2;        }    }}/* * cs_copy_to_user() * replacement for the standard copy_to_user, to allow for a conversion from * 16 bit to 8 bit and from stereo to mono, if the record conversion is active.   * The current CS46xx/CS4280 static image only records in 16bit unsigned Stereo,  * so we convert from any of the other format combinations. */static unsigned cs_copy_to_user(	struct cs_state *s, 	void *dest, 	void *hwsrc, 	unsigned cnt, 	unsigned *copied){	struct dmabuf *dmabuf = &s->dmabuf;	void *src = hwsrc;  /* default to the standard destination buffer addr */	CS_DBGOUT(CS_FUNCTION, 6, printk(KERN_INFO 		"cs_copy_to_user()+ fmt=0x%x cnt=%d dest=0x%.8x\n",		dmabuf->fmt,(unsigned)cnt,(unsigned)dest) );	if(cnt > dmabuf->dmasize)	{		cnt = dmabuf->dmasize;	}	if(!cnt)	{		*copied = 0;		return 0;	}	if(dmabuf->divisor != 1)	{		if(!dmabuf->tmpbuff)		{			*copied = cnt/dmabuf->divisor;			return 0;		}		CopySamples((char *)dmabuf->tmpbuff, (char *)hwsrc, cnt, 			dmabuf->fmt, dmabuf);		src =

⌨️ 快捷键说明

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