📄 cs46xx.c
字号:
} 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 + -