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

📄 ite8172.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
    temp = rdcodec(codec, 0x26);    // If power down, power up    if (temp & 0x3f00) {	// Power on	wrcodec(codec, 0x26, 0);	it8172_delay(100);	// Reread	temp = rdcodec(codec, 0x26);    }        // Check if Codec REF,ANL,DAC,ADC ready***/    if ((temp & 0x3f0f) != 0x000f) {	printk(KERN_INFO PFX "codec reg 26 status (0x%x) not ready!!\n",	       temp);	return;    }}/* --------------------------------------------------------------------- */extern inline void stop_adc(struct it8172_state *s){    struct dmabuf* db = &s->dma_adc;    unsigned long flags;    unsigned char imc;        if (db->stopped)	return;    spin_lock_irqsave(&s->lock, flags);    s->capcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L);    s->capcc |= CC_CSP;    outw(s->capcc, s->io+IT_AC_CAPCC);        // disable capture interrupt    imc = inb(s->io+IT_AC_IMC);    outb(imc | IMC_CCIM, s->io+IT_AC_IMC);    db->stopped = 1;    spin_unlock_irqrestore(&s->lock, flags);}	extern inline void stop_dac(struct it8172_state *s){    struct dmabuf* db = &s->dma_dac;    unsigned long flags;    unsigned char imc;        if (db->stopped)	return;    spin_lock_irqsave(&s->lock, flags);    s->pcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L);    s->pcc |= CC_CSP;    outw(s->pcc, s->io+IT_AC_PCC);        // disable playback interrupt    imc = inb(s->io+IT_AC_IMC);    outb(imc | IMC_PCIM, s->io+IT_AC_IMC);    db->stopped = 1;        spin_unlock_irqrestore(&s->lock, flags);}	static void start_dac(struct it8172_state *s){    struct dmabuf* db = &s->dma_dac;    unsigned long flags;    unsigned char imc;    unsigned long buf1, buf2;        if (!db->stopped)	return;        spin_lock_irqsave(&s->lock, flags);    // reset Buffer 1 and 2 pointers to nextOut and nextOut+fragsize    buf1 = virt_to_bus(db->nextOut);    buf2 = buf1 + db->fragsize;    if (buf2 >= db->dmaaddr + db->dmasize)	buf2 -= db->dmasize;        outl(buf1, s->io+IT_AC_PCB1STA);    outl(buf2, s->io+IT_AC_PCB2STA);    db->curBufPtr = IT_AC_PCB1STA;        // enable playback interrupt    imc = inb(s->io+IT_AC_IMC);    outb(imc & ~IMC_PCIM, s->io+IT_AC_IMC);    s->pcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L);    s->pcc |= CC_CA;    outw(s->pcc, s->io+IT_AC_PCC);        db->stopped = 0;    spin_unlock_irqrestore(&s->lock, flags);}	static void start_adc(struct it8172_state *s){    struct dmabuf* db = &s->dma_adc;    unsigned long flags;    unsigned char imc;    unsigned long buf1, buf2;        if (!db->stopped)	return;    spin_lock_irqsave(&s->lock, flags);    // reset Buffer 1 and 2 pointers to nextIn and nextIn+fragsize    buf1 = virt_to_bus(db->nextIn);    buf2 = buf1 + db->fragsize;    if (buf2 >= db->dmaaddr + db->dmasize)	buf2 -= db->dmasize;        outl(buf1, s->io+IT_AC_CAPB1STA);    outl(buf2, s->io+IT_AC_CAPB2STA);    db->curBufPtr = IT_AC_CAPB1STA;    // enable capture interrupt    imc = inb(s->io+IT_AC_IMC);    outb(imc & ~IMC_CCIM, s->io+IT_AC_IMC);    s->capcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L);    s->capcc |= CC_CA;    outw(s->capcc, s->io+IT_AC_CAPCC);        db->stopped = 0;    spin_unlock_irqrestore(&s->lock, flags);}	/* --------------------------------------------------------------------- */#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT)#define DMABUF_MINORDER 1extern inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db){    struct page *page, *pend;    if (db->rawbuf) {	/* undo marking the pages as reserved */	pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);	for (page = virt_to_page(db->rawbuf); page <= pend; page++)	    mem_map_unreserve(page);	pci_free_consistent(s->dev, PAGE_SIZE << db->buforder,			    db->rawbuf, db->dmaaddr);    }    db->rawbuf = db->nextIn = db->nextOut = NULL;    db->mapped = db->ready = 0;}static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,		       unsigned rate, unsigned fmt, unsigned reg){    int order;    unsigned bytepersec;    unsigned bufs;    struct page *page, *pend;    if (!db->rawbuf) {	db->ready = db->mapped = 0;	for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--)	    if ((db->rawbuf = pci_alloc_consistent(s->dev,						   PAGE_SIZE << order,						   &db->dmaaddr)))		break;	if (!db->rawbuf)	    return -ENOMEM;	db->buforder = order;	/* now mark the pages as reserved;	   otherwise remap_page_range doesn't do what we want */	pend = virt_to_page(db->rawbuf + (PAGE_SIZE << db->buforder) - 1);	for (page = virt_to_page(db->rawbuf); page <= pend; page++)	    mem_map_reserve(page);    }    db->count = 0;    db->nextIn = db->nextOut = db->rawbuf;        bytepersec = rate << sample_shift[fmt];    bufs = PAGE_SIZE << db->buforder;    if (db->ossfragshift) {	if ((1000 << db->ossfragshift) < bytepersec)	    db->fragshift = ld2(bytepersec/1000);	else	    db->fragshift = db->ossfragshift;    } else {	db->fragshift = ld2(bytepersec/100/(db->subdivision ?					    db->subdivision : 1));	if (db->fragshift < 3)	    db->fragshift = 3;    }    db->numfrag = bufs >> db->fragshift;    while (db->numfrag < 4 && db->fragshift > 3) {	db->fragshift--;	db->numfrag = bufs >> db->fragshift;    }    db->fragsize = 1 << db->fragshift;    if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag)	db->numfrag = db->ossmaxfrags;    db->fragsamples = db->fragsize >> sample_shift[fmt];    db->dmasize = db->numfrag << db->fragshift;    memset(db->rawbuf, (fmt & (CC_DF>>CC_FMT_BIT)) ? 0 : 0x80, db->dmasize);        // set data length register    outw(db->fragsize, s->io+reg+2);    db->ready = 1;    return 0;}extern inline int prog_dmabuf_adc(struct it8172_state *s){    stop_adc(s);    return prog_dmabuf(s, &s->dma_adc, s->adcrate,		       (s->capcc & CC_FMT_MASK) >> CC_FMT_BIT,		       IT_AC_CAPCC);}extern inline int prog_dmabuf_dac(struct it8172_state *s){    stop_dac(s);    return prog_dmabuf(s, &s->dma_dac, s->dacrate,		       (s->pcc & CC_FMT_MASK) >> CC_FMT_BIT,		       IT_AC_PCC);}/* hold spinlock for the following! */static void it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs){    struct it8172_state *s = (struct it8172_state *)dev_id;    struct dmabuf* dac = &s->dma_dac;    struct dmabuf* adc = &s->dma_adc;    unsigned char isc, vs;    unsigned short vol, mute;    unsigned long newptr;        spin_lock(&s->lock);    isc = inb(s->io+IT_AC_ISC);    /* fastpath out, to ease interrupt sharing */    if (!(isc & (ISC_VCI | ISC_CCI | ISC_PCI)))	return;    /* clear audio interrupts first */    outb(isc | ISC_VCI | ISC_CCI | ISC_PCI, s->io+IT_AC_ISC);        /* handle volume button events */    if (isc & ISC_VCI) {	vs = inb(s->io+IT_AC_VS);	outb(0, s->io+IT_AC_VS);	vol = inw(s->io+IT_AC_PCMOV);	mute = vol & PCMOV_PCMOM;	vol &= PCMOV_PCMLCG_MASK;	if ((vs & VS_VUP) && vol > 0)	    vol--;	if ((vs & VS_VDP) && vol < 0x1f)	    vol++;	vol |= (vol << PCMOV_PCMRCG_BIT);	if (vs & VS_VMP)	    vol |= (mute ^ PCMOV_PCMOM);	outw(vol, s->io+IT_AC_PCMOV);    }        /* update capture pointers */    if (isc & ISC_CCI) {	if (adc->count > adc->dmasize - adc->fragsize) {	    // Overrun. Stop ADC and log the error	    stop_adc(s);	    adc->error++;	    printk(KERN_INFO PFX "adc overrun\n");	} else {	    newptr = virt_to_bus(adc->nextIn) + 2*adc->fragsize;	    if (newptr >= adc->dmaaddr + adc->dmasize)		newptr -= adc->dmasize;	    	    outl(newptr, s->io+adc->curBufPtr);	    adc->curBufPtr = (adc->curBufPtr == IT_AC_CAPB1STA) ?		IT_AC_CAPB2STA : IT_AC_CAPB1STA;	    	    adc->nextIn += adc->fragsize;	    if (adc->nextIn >= adc->rawbuf + adc->dmasize)		adc->nextIn -= adc->dmasize;	    	    adc->count += adc->fragsize;	    adc->total_bytes += adc->fragsize;	    /* wake up anybody listening */	    if (waitqueue_active(&adc->wait))		wake_up_interruptible(&adc->wait);	}    }        /* update playback pointers */    if (isc & ISC_PCI) {	newptr = virt_to_bus(dac->nextOut) + 2*dac->fragsize;	if (newptr >= dac->dmaaddr + dac->dmasize)	    newptr -= dac->dmasize;		outl(newptr, s->io+dac->curBufPtr);	dac->curBufPtr = (dac->curBufPtr == IT_AC_PCB1STA) ?	    IT_AC_PCB2STA : IT_AC_PCB1STA;		dac->nextOut += dac->fragsize;	if (dac->nextOut >= dac->rawbuf + dac->dmasize)	    dac->nextOut -= dac->dmasize;		dac->count -= dac->fragsize;	dac->total_bytes += dac->fragsize;	/* wake up anybody listening */	if (waitqueue_active(&dac->wait))	    wake_up_interruptible(&dac->wait);		if (dac->count <= 0)	    stop_dac(s);    }        spin_unlock(&s->lock);}/* --------------------------------------------------------------------- */static loff_t it8172_llseek(struct file *file, loff_t offset, int origin){    return -ESPIPE;}static int it8172_open_mixdev(struct inode *inode, struct file *file){    int minor = MINOR(inode->i_rdev);    struct list_head *list;    struct it8172_state *s;    for (list = devs.next; ; list = list->next) {	if (list == &devs)	    return -ENODEV;	s = list_entry(list, struct it8172_state, devs);	if (s->codec.dev_mixer == minor)	    break;    }    file->private_data = s;    return 0;}static int it8172_release_mixdev(struct inode *inode, struct file *file){    return 0;}static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd,			unsigned long arg){    return codec->mixer_ioctl(codec, cmd, arg);}static int it8172_ioctl_mixdev(struct inode *inode, struct file *file,			       unsigned int cmd, unsigned long arg){    struct it8172_state *s = (struct it8172_state *)file->private_data;    struct ac97_codec *codec = &s->codec;    return mixdev_ioctl(codec, cmd, arg);}static /*const*/ struct file_operations it8172_mixer_fops = {    owner:	THIS_MODULE,    llseek:	it8172_llseek,    ioctl:	it8172_ioctl_mixdev,    open:	it8172_open_mixdev,    release:	it8172_release_mixdev,};/* --------------------------------------------------------------------- */static int drain_dac(struct it8172_state *s, int nonblock){    unsigned long flags;    int count, tmo;	    if (s->dma_dac.mapped || !s->dma_dac.ready)	return 0;    for (;;) {	spin_lock_irqsave(&s->lock, flags);	count = s->dma_dac.count;	spin_unlock_irqrestore(&s->lock, flags);	if (count <= 0)	    break;	if (signal_pending(current))	    break;	if (nonblock)	    return -EBUSY;	tmo = 1000 * count / s->dacrate;	tmo >>= sample_shift[(s->pcc & CC_FMT_MASK) >> CC_FMT_BIT];	it8172_delay(tmo);    }    if (signal_pending(current))	return -ERESTARTSYS;    return 0;}/* --------------------------------------------------------------------- */static ssize_t it8172_read(struct file *file, char *buffer,			   size_t count, loff_t *ppos){    struct it8172_state *s = (struct it8172_state *)file->private_data;    struct dmabuf *db = &s->dma_adc;    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_WRITE, buffer, count))	return -EFAULT;    ret = 0;    while (count > 0) {	// wait for samples in capture buffer	do {	    spin_lock_irqsave(&s->lock, flags);	    if (db->stopped)		start_adc(s);	    avail = 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;	bufcnt = cnt;	if (cnt % db->fragsize) {	    // round count up to nearest fragment	    int newcnt = db->fragsize * ((cnt + db->fragsize) / db->fragsize);	    cnt = newcnt;	}	// copy from nextOut to user	if (copy_to_user(buffer, db->nextOut, bufcnt)) {	    if (!ret)		ret = -EFAULT;	    return ret;	}	spin_lock_irqsave(&s->lock, flags);	db->count -= cnt;	spin_unlock_irqrestore(&s->lock, flags);	db->nextOut += cnt;	if (db->nextOut >= db->rawbuf + db->dmasize)	    db->nextOut -= db->dmasize;		count -= bufcnt;	buffer += bufcnt;	ret += bufcnt;    } // while (count > 0)    return ret;}

⌨️ 快捷键说明

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