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

📄 ite8172.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
static ssize_t it8172_write(struct file *file, const char *buffer,			    size_t count, loff_t *ppos){    struct it8172_state *s = (struct it8172_state *)file->private_data;    struct dmabuf *db = &s->dma_dac;    ssize_t ret;    unsigned long flags;    int cnt, bufcnt, avail;    if (ppos != &file->f_pos)	return -ESPIPE;    if (db->mapped)	return -ENXIO;    if (!access_ok(VERIFY_READ, buffer, count))	return -EFAULT;    ret = 0;        while (count > 0) {	// wait for space in playback buffer	do {	    spin_lock_irqsave(&s->lock, flags);	    avail = db->dmasize - db->count;	    spin_unlock_irqrestore(&s->lock, flags);	    if (avail <= 0) {		if (file->f_flags & O_NONBLOCK) {		    if (!ret)			ret = -EAGAIN;		    return ret;		}		interruptible_sleep_on(&db->wait);		if (signal_pending(current)) {		    if (!ret)			ret = -ERESTARTSYS;		    return ret;		}	    }	} while (avail <= 0);		cnt = count > avail ? avail : count;	// copy to nextIn	if (copy_from_user(db->nextIn, buffer, cnt)) {	    if (!ret)		ret = -EFAULT;	    return ret;	}	bufcnt = cnt;	if (cnt % db->fragsize) {	    // round count up to nearest fragment, and fill remainder of	    // fragment with silence	    int newcnt = db->fragsize * ((cnt + db->fragsize) / db->fragsize);	    memset(db->nextIn + cnt, (s->pcc & CC_DF) ? 0 : 0x80, newcnt - cnt);	    cnt = newcnt;	}	spin_lock_irqsave(&s->lock, flags);	db->count += cnt;	if (db->stopped)	    start_dac(s);	spin_unlock_irqrestore(&s->lock, flags);		db->nextIn += cnt;	if (db->nextIn >= db->rawbuf + db->dmasize)	    db->nextIn -= db->dmasize;		count -= bufcnt;	buffer += bufcnt;	ret += bufcnt;    } // while (count > 0)	    return ret;}/* No kernel lock - we have our own spinlock */static unsigned int it8172_poll(struct file *file,				struct poll_table_struct *wait){    struct it8172_state *s = (struct it8172_state *)file->private_data;    unsigned long flags;    unsigned int mask = 0;    if (file->f_mode & FMODE_WRITE)	poll_wait(file, &s->dma_dac.wait, wait);    if (file->f_mode & FMODE_READ)	poll_wait(file, &s->dma_adc.wait, wait);    spin_lock_irqsave(&s->lock, flags);    if (file->f_mode & FMODE_READ) {	if (s->dma_adc.count >= (signed)s->dma_adc.fragsize)	    mask |= POLLIN | POLLRDNORM;    }    if (file->f_mode & FMODE_WRITE) {	if (s->dma_dac.mapped) {	    if (s->dma_dac.count >= (signed)s->dma_dac.fragsize) 		mask |= POLLOUT | POLLWRNORM;	} else {	    if ((signed)s->dma_dac.dmasize >=		s->dma_dac.count + (signed)s->dma_dac.fragsize)		mask |= POLLOUT | POLLWRNORM;	}    }    spin_unlock_irqrestore(&s->lock, flags);    return mask;}static int it8172_mmap(struct file *file, struct vm_area_struct *vma){    struct it8172_state *s = (struct it8172_state *)file->private_data;    struct dmabuf *db;    unsigned long size;    lock_kernel();    if (vma->vm_flags & VM_WRITE)	db = &s->dma_dac;    else if (vma->vm_flags & VM_READ)	db = &s->dma_adc;    else {	unlock_kernel();	return -EINVAL;    }    if (vma->vm_pgoff != 0) {	unlock_kernel();	return -EINVAL;    }    size = vma->vm_end - vma->vm_start;    if (size > (PAGE_SIZE << db->buforder)) {	unlock_kernel();	return -EINVAL;    }    if (remap_page_range(vma->vm_start, virt_to_phys(db->rawbuf),			 size, vma->vm_page_prot)) {	unlock_kernel();	return -EAGAIN;    }    db->mapped = 1;    unlock_kernel();    return 0;}#ifdef IT8172_VERBOSE_DEBUGstatic struct ioctl_str_t {    unsigned int cmd;    const char* str;} ioctl_str[] = {    {SNDCTL_DSP_RESET, "SNDCTL_DSP_RESET"},    {SNDCTL_DSP_SYNC, "SNDCTL_DSP_SYNC"},    {SNDCTL_DSP_SPEED, "SNDCTL_DSP_SPEED"},    {SNDCTL_DSP_STEREO, "SNDCTL_DSP_STEREO"},    {SNDCTL_DSP_GETBLKSIZE, "SNDCTL_DSP_GETBLKSIZE"},    {SNDCTL_DSP_SAMPLESIZE, "SNDCTL_DSP_SAMPLESIZE"},    {SNDCTL_DSP_CHANNELS, "SNDCTL_DSP_CHANNELS"},    {SOUND_PCM_WRITE_CHANNELS, "SOUND_PCM_WRITE_CHANNELS"},    {SOUND_PCM_WRITE_FILTER, "SOUND_PCM_WRITE_FILTER"},    {SNDCTL_DSP_POST, "SNDCTL_DSP_POST"},    {SNDCTL_DSP_SUBDIVIDE, "SNDCTL_DSP_SUBDIVIDE"},    {SNDCTL_DSP_SETFRAGMENT, "SNDCTL_DSP_SETFRAGMENT"},    {SNDCTL_DSP_GETFMTS, "SNDCTL_DSP_GETFMTS"},    {SNDCTL_DSP_SETFMT, "SNDCTL_DSP_SETFMT"},    {SNDCTL_DSP_GETOSPACE, "SNDCTL_DSP_GETOSPACE"},    {SNDCTL_DSP_GETISPACE, "SNDCTL_DSP_GETISPACE"},    {SNDCTL_DSP_NONBLOCK, "SNDCTL_DSP_NONBLOCK"},    {SNDCTL_DSP_GETCAPS, "SNDCTL_DSP_GETCAPS"},    {SNDCTL_DSP_GETTRIGGER, "SNDCTL_DSP_GETTRIGGER"},    {SNDCTL_DSP_SETTRIGGER, "SNDCTL_DSP_SETTRIGGER"},    {SNDCTL_DSP_GETIPTR, "SNDCTL_DSP_GETIPTR"},    {SNDCTL_DSP_GETOPTR, "SNDCTL_DSP_GETOPTR"},    {SNDCTL_DSP_MAPINBUF, "SNDCTL_DSP_MAPINBUF"},    {SNDCTL_DSP_MAPOUTBUF, "SNDCTL_DSP_MAPOUTBUF"},    {SNDCTL_DSP_SETSYNCRO, "SNDCTL_DSP_SETSYNCRO"},    {SNDCTL_DSP_SETDUPLEX, "SNDCTL_DSP_SETDUPLEX"},    {SNDCTL_DSP_GETODELAY, "SNDCTL_DSP_GETODELAY"},    {SNDCTL_DSP_GETCHANNELMASK, "SNDCTL_DSP_GETCHANNELMASK"},    {SNDCTL_DSP_BIND_CHANNEL, "SNDCTL_DSP_BIND_CHANNEL"},    {OSS_GETVERSION, "OSS_GETVERSION"},    {SOUND_PCM_READ_RATE, "SOUND_PCM_READ_RATE"},    {SOUND_PCM_READ_CHANNELS, "SOUND_PCM_READ_CHANNELS"},    {SOUND_PCM_READ_BITS, "SOUND_PCM_READ_BITS"},    {SOUND_PCM_READ_FILTER, "SOUND_PCM_READ_FILTER"}};#endif    static int it8172_ioctl(struct inode *inode, struct file *file,			unsigned int cmd, unsigned long arg){    struct it8172_state *s = (struct it8172_state *)file->private_data;    unsigned long flags;    audio_buf_info abinfo;    count_info cinfo;    int count;    int val, mapped, ret, diff;    mapped = ((file->f_mode & FMODE_WRITE) && s->dma_dac.mapped) ||	((file->f_mode & FMODE_READ) && s->dma_adc.mapped);#ifdef IT8172_VERBOSE_DEBUG    for (count=0; count<sizeof(ioctl_str)/sizeof(ioctl_str[0]); count++) {	if (ioctl_str[count].cmd == cmd)	    break;    }    if (count < sizeof(ioctl_str)/sizeof(ioctl_str[0]))	printk(KERN_INFO PFX "ioctl %s\n", ioctl_str[count].str);    else	printk(KERN_INFO PFX "ioctl unknown, 0x%x\n", cmd);#endif        switch (cmd) {    case OSS_GETVERSION:	return put_user(SOUND_VERSION, (int *)arg);    case SNDCTL_DSP_SYNC:	if (file->f_mode & FMODE_WRITE)	    return drain_dac(s, file->f_flags & O_NONBLOCK);	return 0;		    case SNDCTL_DSP_SETDUPLEX:	return 0;    case SNDCTL_DSP_GETCAPS:	return put_user(DSP_CAP_DUPLEX | DSP_CAP_REALTIME |			DSP_CAP_TRIGGER | DSP_CAP_MMAP, (int *)arg);		    case SNDCTL_DSP_RESET:	if (file->f_mode & FMODE_WRITE) {	    stop_dac(s);	    synchronize_irq();	    s->dma_dac.count = s->dma_dac.total_bytes = 0;	    s->dma_dac.nextIn = s->dma_dac.nextOut = s->dma_dac.rawbuf;	}	if (file->f_mode & FMODE_READ) {	    stop_adc(s);	    synchronize_irq();	    s->dma_adc.count = s->dma_adc.total_bytes = 0;	    s->dma_adc.nextIn = s->dma_adc.nextOut = s->dma_adc.rawbuf;	}	return 0;    case SNDCTL_DSP_SPEED:	if (get_user(val, (int *)arg))	    return -EFAULT;	if (val >= 0) {	    if (file->f_mode & FMODE_READ) {		stop_adc(s);		set_adc_rate(s, val);		if ((ret = prog_dmabuf_adc(s)))		    return ret;	    }	    if (file->f_mode & FMODE_WRITE) {		stop_dac(s);		set_dac_rate(s, val);		if ((ret = prog_dmabuf_dac(s)))		    return ret;	    }	}	return put_user((file->f_mode & FMODE_READ) ?			s->adcrate : s->dacrate, (int *)arg);    case SNDCTL_DSP_STEREO:	if (get_user(val, (int *)arg))	    return -EFAULT;	if (file->f_mode & FMODE_READ) {	    stop_adc(s);	    if (val)		s->capcc |= CC_SM;	    else		s->capcc &= ~CC_SM;	    outw(s->capcc, s->io+IT_AC_CAPCC);	    if ((ret = prog_dmabuf_adc(s)))		return ret;	}	if (file->f_mode & FMODE_WRITE) {	    stop_dac(s);	    if (val)		s->pcc |= CC_SM;	    else		s->pcc &= ~CC_SM;	    outw(s->pcc, s->io+IT_AC_PCC);	    if ((ret = prog_dmabuf_dac(s)))		return ret;	}	return 0;    case SNDCTL_DSP_CHANNELS:	if (get_user(val, (int *)arg))	    return -EFAULT;	if (val != 0) {	    if (file->f_mode & FMODE_READ) {		stop_adc(s);		if (val >= 2) {		    val = 2;		    s->capcc |= CC_SM;		}		else		    s->capcc &= ~CC_SM;		outw(s->capcc, s->io+IT_AC_CAPCC);		if ((ret = prog_dmabuf_adc(s)))		    return ret;	    }	    if (file->f_mode & FMODE_WRITE) {		stop_dac(s);		switch (val) {		case 1:		    s->pcc &= ~CC_SM;		    break;		case 2:		    s->pcc |= CC_SM;		    break;		default:		    // FIX! support multichannel???		    val = 2;		    s->pcc |= CC_SM;		    break;		}		outw(s->pcc, s->io+IT_AC_PCC);		if ((ret = prog_dmabuf_dac(s)))		    return ret;	    }	}	return put_user(val, (int *)arg);		    case SNDCTL_DSP_GETFMTS: /* Returns a mask */	return put_user(AFMT_S16_LE|AFMT_U8, (int *)arg);		    case SNDCTL_DSP_SETFMT: /* Selects ONE fmt*/	if (get_user(val, (int *)arg))	    return -EFAULT;	if (val != AFMT_QUERY) {	    if (file->f_mode & FMODE_READ) {		stop_adc(s);		if (val == AFMT_S16_LE)		    s->capcc |= CC_DF;		else {		    val = AFMT_U8;		    s->capcc &= ~CC_DF;		}		outw(s->capcc, s->io+IT_AC_CAPCC);		if ((ret = prog_dmabuf_adc(s)))		    return ret;	    }	    if (file->f_mode & FMODE_WRITE) {		stop_dac(s);		if (val == AFMT_S16_LE)		    s->pcc |= CC_DF;		else {		    val = AFMT_U8;		    s->pcc &= ~CC_DF;		}		outw(s->pcc, s->io+IT_AC_PCC);		if ((ret = prog_dmabuf_dac(s)))		    return ret;	    }	} else {	    if (file->f_mode & FMODE_READ)		val = (s->capcc & CC_DF) ? AFMT_S16_LE : AFMT_U8;	    else		val = (s->pcc & CC_DF) ? AFMT_S16_LE : AFMT_U8;	}	return put_user(val, (int *)arg);		    case SNDCTL_DSP_POST:	return 0;    case SNDCTL_DSP_GETTRIGGER:	val = 0;	spin_lock_irqsave(&s->lock, flags);	if (file->f_mode & FMODE_READ && !s->dma_adc.stopped)	    val |= PCM_ENABLE_INPUT;	if (file->f_mode & FMODE_WRITE && !s->dma_dac.stopped)	    val |= PCM_ENABLE_OUTPUT;	spin_unlock_irqrestore(&s->lock, flags);	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)		start_adc(s);	    else		stop_adc(s);	}	if (file->f_mode & FMODE_WRITE) {	    if (val & PCM_ENABLE_OUTPUT)		start_dac(s);	    else		stop_dac(s);	}	return 0;    case SNDCTL_DSP_GETOSPACE:	if (!(file->f_mode & FMODE_WRITE))	    return -EINVAL;	abinfo.fragsize = s->dma_dac.fragsize;	spin_lock_irqsave(&s->lock, flags);	count = s->dma_dac.count;	if (!s->dma_dac.stopped)	    count -= (s->dma_dac.fragsize - inw(s->io+IT_AC_PCDL));	spin_unlock_irqrestore(&s->lock, flags);	if (count < 0)	    count = 0;	abinfo.bytes = s->dma_dac.dmasize - count;	abinfo.fragstotal = s->dma_dac.numfrag;	abinfo.fragments = abinfo.bytes >> s->dma_dac.fragshift;      	return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;    case SNDCTL_DSP_GETISPACE:	if (!(file->f_mode & FMODE_READ))	    return -EINVAL;	abinfo.fragsize = s->dma_adc.fragsize;	spin_lock_irqsave(&s->lock, flags);	count = s->dma_adc.count;	if (!s->dma_adc.stopped)	    count += (s->dma_adc.fragsize - inw(s->io+IT_AC_CAPCDL));	spin_unlock_irqrestore(&s->lock, flags);	if (count < 0)	    count = 0;	abinfo.bytes = count;	abinfo.fragstotal = s->dma_adc.numfrag;	abinfo.fragments = abinfo.bytes >> s->dma_adc.fragshift;      	return copy_to_user((void *)arg, &abinfo, sizeof(abinfo)) ? -EFAULT : 0;		    case SNDCTL_DSP_NONBLOCK:	file->f_flags |= O_NONBLOCK;	return 0;    case SNDCTL_DSP_GETODELAY:	if (!(file->f_mode & FMODE_WRITE))	    return -EINVAL;	spin_lock_irqsave(&s->lock, flags);	count = s->dma_dac.count;	if (!s->dma_dac.stopped)	    count -= (s->dma_dac.fragsize - inw(s->io+IT_AC_PCDL));	spin_unlock_irqrestore(&s->lock, flags);	if (count < 0)	    count = 0;	return put_user(count, (int *)arg);    case SNDCTL_DSP_GETIPTR:	if (!(file->f_mode & FMODE_READ))	    return -EINVAL;	spin_lock_irqsave(&s->lock, flags);	cinfo.bytes = s->dma_adc.total_bytes;	count = s->dma_adc.count;	if (!s->dma_adc.stopped) {	    diff = s->dma_adc.fragsize - inw(s->io+IT_AC_CAPCDL);	    count += diff;	    cinfo.bytes += diff;	    cinfo.ptr = inl(s->io+s->dma_adc.curBufPtr) - s->dma_adc.dmaaddr;	} else	    cinfo.ptr = virt_to_bus(s->dma_adc.nextIn) - s->dma_adc.dmaaddr;	if (s->dma_adc.mapped)	    s->dma_adc.count &= s->dma_adc.fragsize-1;	spin_unlock_irqrestore(&s->lock, flags);	if (count < 0)	    count = 0;	cinfo.blocks = count >> s->dma_adc.fragshift;	return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));    case SNDCTL_DSP_GETOPTR:	if (!(file->f_mode & FMODE_READ))	    return -EINVAL;	spin_lock_irqsave(&s->lock, flags);	cinfo.bytes = s->dma_dac.total_bytes;	count = s->dma_dac.count;	if (!s->dma_dac.stopped) {	    diff = s->dma_dac.fragsize - inw(s->io+IT_AC_CAPCDL);	    count -= diff;	    cinfo.bytes += diff;	    cinfo.ptr = inl(s->io+s->dma_dac.curBufPtr) - s->dma_dac.dmaaddr;	} else	    cinfo.ptr = virt_to_bus(s->dma_dac.nextOut) - s->dma_dac.dmaaddr;	if (s->dma_dac.mapped)	    s->dma_dac.count &= s->dma_dac.fragsize-1;	spin_unlock_irqrestore(&s->lock, flags);	if (count < 0)	    count = 0;	cinfo.blocks = count >> s->dma_dac.fragshift;	return copy_to_user((void *)arg, &cinfo, sizeof(cinfo));    case SNDCTL_DSP_GETBLKSIZE:	if (file->f_mode & FMODE_WRITE)	    return put_user(s->dma_dac.fragsize, (int *)arg);	else	    return put_user(s->dma_adc.fragsize, (int *)arg);    case SNDCTL_DSP_SETFRAGMENT:	if (get_user(val, (int *)arg))	    return -EFAULT;	if (file->f_mode & FMODE_READ) {	    stop_adc(s);	    s->dma_adc.ossfragshift = val & 0xffff;

⌨️ 快捷键说明

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