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

📄 ite8172.c

📁 iis s3c2410-uda1341语音系统的 开发
💻 C
📖 第 1 页 / 共 4 页
字号:
	    s->dma_adc.ossmaxfrags = (val >> 16) & 0xffff;	    if (s->dma_adc.ossfragshift < 4)		s->dma_adc.ossfragshift = 4;	    if (s->dma_adc.ossfragshift > 15)		s->dma_adc.ossfragshift = 15;	    if (s->dma_adc.ossmaxfrags < 4)		s->dma_adc.ossmaxfrags = 4;	    if ((ret = prog_dmabuf_adc(s)))		return ret;	}	if (file->f_mode & FMODE_WRITE) {	    stop_dac(s);	    s->dma_dac.ossfragshift = val & 0xffff;	    s->dma_dac.ossmaxfrags = (val >> 16) & 0xffff;	    if (s->dma_dac.ossfragshift < 4)		s->dma_dac.ossfragshift = 4;	    if (s->dma_dac.ossfragshift > 15)		s->dma_dac.ossfragshift = 15;	    if (s->dma_dac.ossmaxfrags < 4)		s->dma_dac.ossmaxfrags = 4;	    if ((ret = prog_dmabuf_dac(s)))		return ret;	}	return 0;    case SNDCTL_DSP_SUBDIVIDE:	if ((file->f_mode & FMODE_READ && s->dma_adc.subdivision) ||	    (file->f_mode & FMODE_WRITE && s->dma_dac.subdivision))	    return -EINVAL;	if (get_user(val, (int *)arg))	    return -EFAULT;	if (val != 1 && val != 2 && val != 4)	    return -EINVAL;	if (file->f_mode & FMODE_READ) {	    stop_adc(s);	    s->dma_adc.subdivision = val;	    if ((ret = prog_dmabuf_adc(s)))		return ret;	}	if (file->f_mode & FMODE_WRITE) {	    stop_dac(s);	    s->dma_dac.subdivision = val;	    if ((ret = prog_dmabuf_dac(s)))		return ret;	}	return 0;    case SOUND_PCM_READ_RATE:	return put_user((file->f_mode & FMODE_READ) ?			s->adcrate : s->dacrate, (int *)arg);    case SOUND_PCM_READ_CHANNELS:	if (file->f_mode & FMODE_READ)	    return put_user((s->capcc & CC_SM) ? 2 : 1, (int *)arg);	else	    return put_user((s->pcc & CC_SM) ? 2 : 1, (int *)arg);	        case SOUND_PCM_READ_BITS:	if (file->f_mode & FMODE_READ)	    return put_user((s->capcc & CC_DF) ? 16 : 8, (int *)arg);	else	    return put_user((s->pcc & CC_DF) ? 16 : 8, (int *)arg);    case SOUND_PCM_WRITE_FILTER:    case SNDCTL_DSP_SETSYNCRO:    case SOUND_PCM_READ_FILTER:	return -EINVAL;    }    return mixdev_ioctl(&s->codec, cmd, arg);}static int it8172_open(struct inode *inode, struct file *file){    int minor = MINOR(inode->i_rdev);    DECLARE_WAITQUEUE(wait, current);    unsigned long flags;    struct list_head *list;    struct it8172_state *s;    int ret;        for (list = devs.next; ; list = list->next) {	if (list == &devs)	    return -ENODEV;	s = list_entry(list, struct it8172_state, devs);	if (!((s->dev_audio ^ minor) & ~0xf))	    break;    }    file->private_data = s;    /* wait for device to become free */    down(&s->open_sem);    while (s->open_mode & file->f_mode) {	if (file->f_flags & O_NONBLOCK) {	    up(&s->open_sem);	    return -EBUSY;	}	add_wait_queue(&s->open_wait, &wait);	__set_current_state(TASK_INTERRUPTIBLE);	up(&s->open_sem);	schedule();	remove_wait_queue(&s->open_wait, &wait);	set_current_state(TASK_RUNNING);	if (signal_pending(current))	    return -ERESTARTSYS;	down(&s->open_sem);    }    spin_lock_irqsave(&s->lock, flags);    if (file->f_mode & FMODE_READ) {	s->dma_adc.ossfragshift = s->dma_adc.ossmaxfrags =	    s->dma_adc.subdivision = s->dma_adc.total_bytes = 0;	s->capcc &= ~(CC_SM | CC_DF);	set_adc_rate(s, 8000);	if ((minor & 0xf) == SND_DEV_DSP16)	    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) {	s->dma_dac.ossfragshift = s->dma_dac.ossmaxfrags =	    s->dma_dac.subdivision = s->dma_dac.total_bytes = 0;	s->pcc &= ~(CC_SM | CC_DF);	set_dac_rate(s, 8000);	if ((minor & 0xf) == SND_DEV_DSP16)	    s->pcc |= CC_DF;	outw(s->pcc, s->io+IT_AC_PCC);	if ((ret = prog_dmabuf_dac(s)))	    return ret;    }    spin_unlock_irqrestore(&s->lock, flags);    s->open_mode |= file->f_mode & (FMODE_READ | FMODE_WRITE);    up(&s->open_sem);    return 0;}static int it8172_release(struct inode *inode, struct file *file){    struct it8172_state *s = (struct it8172_state *)file->private_data;    lock_kernel();    if (file->f_mode & FMODE_WRITE)	drain_dac(s, file->f_flags & O_NONBLOCK);    down(&s->open_sem);    if (file->f_mode & FMODE_WRITE) {	stop_dac(s);	dealloc_dmabuf(s, &s->dma_dac);    }    if (file->f_mode & FMODE_READ) {	stop_adc(s);	dealloc_dmabuf(s, &s->dma_adc);    }    s->open_mode &= (~file->f_mode) & (FMODE_READ|FMODE_WRITE);    up(&s->open_sem);    wake_up(&s->open_wait);    unlock_kernel();    return 0;}static /*const*/ struct file_operations it8172_audio_fops = {    owner:	THIS_MODULE,    llseek:	it8172_llseek,    read:	it8172_read,    write:	it8172_write,    poll:	it8172_poll,    ioctl:	it8172_ioctl,    mmap:	it8172_mmap,    open:	it8172_open,    release:	it8172_release,};/* --------------------------------------------------------------------- *//* --------------------------------------------------------------------- *//* * for debugging purposes, we'll create a proc device that dumps the * CODEC chipstate */#ifdef IT8172_DEBUGstatic int proc_it8172_dump (char *buf, char **start, off_t fpos,			     int length, int *eof, void *data){    struct it8172_state *s;    int cnt, len = 0;    if (list_empty(&devs))	return 0;    s = list_entry(devs.next, struct it8172_state, devs);    /* print out header */    len += sprintf(buf + len, "\n\t\tIT8172 Audio Debug\n\n");    // print out digital controller state    len += sprintf (buf + len, "IT8172 Audio Controller registers\n");    len += sprintf (buf + len, "---------------------------------\n");    cnt=0;    while (cnt < 0x72) {	if (cnt == IT_AC_PCB1STA || cnt == IT_AC_PCB2STA ||	    cnt == IT_AC_CAPB1STA || cnt == IT_AC_CAPB2STA ||	    cnt == IT_AC_PFDP) {	    len+= sprintf (buf + len, "reg %02x = %08x\n",			   cnt, inl(s->io+cnt));	    cnt += 4;	} else {	    len+= sprintf (buf + len, "reg %02x = %04x\n",			   cnt, inw(s->io+cnt));	    cnt += 2;	}    }        /* print out CODEC state */    len += sprintf (buf + len, "\nAC97 CODEC registers\n");    len += sprintf (buf + len, "----------------------\n");    for (cnt=0; cnt <= 0x7e; cnt = cnt +2)	len+= sprintf (buf + len, "reg %02x = %04x\n",		       cnt, rdcodec(&s->codec, cnt));    if (fpos >=len){	*start = buf;	*eof =1;	return 0;    }    *start = buf + fpos;    if ((len -= fpos) > length)	return length;    *eof =1;    return len;}#endif /* IT8172_DEBUG *//* --------------------------------------------------------------------- *//* maximum number of devices; only used for command line params */#define NR_DEVICE 5static int spdif[NR_DEVICE] = { 0, };static unsigned int devindex = 0;MODULE_PARM(spdif, "1-" __MODULE_STRING(NR_DEVICE) "i");MODULE_PARM_DESC(spdif, "if 1 the S/PDIF digital output is enabled");MODULE_AUTHOR("Monta Vista Software, stevel@mvista.com");MODULE_DESCRIPTION("IT8172 AudioPCI97 Driver");MODULE_LICENSE("GPL");/* --------------------------------------------------------------------- */static int __devinit it8172_probe(struct pci_dev *pcidev,				  const struct pci_device_id *pciid){    struct it8172_state *s;    int i, val;    unsigned short pcisr, vol;    unsigned char legacy, imc;    char proc_str[80];        if (pcidev->irq == 0) 	return -1;    if (!(s = kmalloc(sizeof(struct it8172_state), GFP_KERNEL))) {	printk(KERN_ERR PFX "alloc of device struct failed\n");	return -1;    }	    memset(s, 0, sizeof(struct it8172_state));    init_waitqueue_head(&s->dma_adc.wait);    init_waitqueue_head(&s->dma_dac.wait);    init_waitqueue_head(&s->open_wait);    init_MUTEX(&s->open_sem);    spin_lock_init(&s->lock);    s->dev = pcidev;    s->io = pci_resource_start(pcidev, 0);    s->irq = pcidev->irq;    s->vendor = pcidev->vendor;    s->device = pcidev->device;    pci_read_config_byte(pcidev, PCI_REVISION_ID, &s->rev);    s->codec.private_data = s;    s->codec.id = 0;    s->codec.codec_read = rdcodec;    s->codec.codec_write = wrcodec;    s->codec.codec_wait = waitcodec;    if (!request_region(s->io, pci_resource_len(pcidev,0),			IT8172_MODULE_NAME)) {	printk(KERN_ERR PFX "io ports %#lx->%#lx in use\n",		s->io, s->io + pci_resource_len(pcidev,0)-1);	goto err_region;    }    if (request_irq(s->irq, it8172_interrupt, SA_INTERRUPT,		    IT8172_MODULE_NAME, s)) {	printk(KERN_ERR PFX "irq %u in use\n", s->irq);	goto err_irq;    }    printk(KERN_INFO PFX "IO at %#lx, IRQ %d\n", s->io, s->irq);    /* register devices */    if ((s->dev_audio = register_sound_dsp(&it8172_audio_fops, -1)) < 0)	goto err_dev1;    if ((s->codec.dev_mixer =	 register_sound_mixer(&it8172_mixer_fops, -1)) < 0)	goto err_dev2;#ifdef IT8172_DEBUG    /* intialize the debug proc device */    s->ps = create_proc_read_entry(IT8172_MODULE_NAME, 0, NULL,				   proc_it8172_dump, NULL);#endif /* IT8172_DEBUG */	    /*     * Reset the Audio device using the IT8172 PCI Reset register. This     * creates an audible double click on a speaker connected to Line-out.     */    IT_IO_READ16(IT_PM_PCISR, pcisr);    pcisr |= IT_PM_PCISR_ACSR;    IT_IO_WRITE16(IT_PM_PCISR, pcisr);    /* wait up to 100msec for reset to complete */    for (i=0; pcisr & IT_PM_PCISR_ACSR; i++) {	it8172_delay(10);	if (i == 10)	    break;	IT_IO_READ16(IT_PM_PCISR, pcisr);    }    if (i == 10) {	printk(KERN_ERR PFX "chip reset timeout!\n");	goto err_dev3;    }        /* enable pci io and bus mastering */    if (pci_enable_device(pcidev))	goto err_dev3;    pci_set_master(pcidev);    /* get out of legacy mode */    pci_read_config_byte (pcidev, 0x40, &legacy);    pci_write_config_byte (pcidev, 0x40, legacy & ~1);        s->spdif_volume = -1;    /* check to see if s/pdif mode is being requested */    if (spdif[devindex]) {	printk(KERN_INFO PFX "enabling S/PDIF output\n");	s->spdif_volume = 0;	outb(GC_SOE, s->io+IT_AC_GC);    } else {	printk(KERN_INFO PFX "disabling S/PDIF output\n");	outb(0, s->io+IT_AC_GC);    }        /* cold reset the AC97 */    outw(CODECC_CR, s->io+IT_AC_CODECC);    udelay(1000);    outw(0, s->io+IT_AC_CODECC);    /* need to delay around 500msec(bleech) to give       some CODECs enough time to wakeup */    it8172_delay(500);        /* AC97 warm reset to start the bitclk */    outw(CODECC_WR, s->io+IT_AC_CODECC);    udelay(1000);    outw(0, s->io+IT_AC_CODECC);        /* codec init */    if (!ac97_probe_codec(&s->codec))	goto err_dev3;    /* Enable Volume button interrupts */    imc = inb(s->io+IT_AC_IMC);    outb(imc & ~IMC_VCIM, s->io+IT_AC_IMC);    /* Un-mute PCM and FM out on the controller */    vol = inw(s->io+IT_AC_PCMOV);    outw(vol & ~PCMOV_PCMOM, s->io+IT_AC_PCMOV);    vol = inw(s->io+IT_AC_FMOV);    outw(vol & ~FMOV_FMOM, s->io+IT_AC_FMOV);    /* set channel defaults to 8-bit, mono, 8 Khz */    s->pcc = 0;    s->capcc = 0;    set_dac_rate(s, 8000);    set_adc_rate(s, 8000);    /* set mic to be the recording source */    val = SOUND_MASK_MIC;    mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_RECSRC, (unsigned long)&val);    /* mute master and PCM when in S/PDIF mode */    if (s->spdif_volume != -1) {	val = 0x0000;	mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_VOLUME,		     (unsigned long)&val);	mixdev_ioctl(&s->codec, SOUND_MIXER_WRITE_PCM,		     (unsigned long)&val);    }    #ifdef IT8172_DEBUG    sprintf(proc_str, "driver/%s/%d/ac97", IT8172_MODULE_NAME, s->codec.id);    s->ac97_ps = create_proc_read_entry (proc_str, 0, NULL,					 ac97_read_proc, &s->codec);#endif        /* store it in the driver field */    pci_set_drvdata(pcidev, s);    pcidev->dma_mask = 0xffffffff;    /* put it into driver list */    list_add_tail(&s->devs, &devs);    /* increment devindex */    if (devindex < NR_DEVICE-1)	devindex++;    return 0; err_dev3:    unregister_sound_mixer(s->codec.dev_mixer); err_dev2:    unregister_sound_dsp(s->dev_audio); err_dev1:    printk(KERN_ERR PFX "cannot register misc device\n");    free_irq(s->irq, s); err_irq:    release_region(s->io, pci_resource_len(pcidev,0)); err_region:    kfree(s);    return -1;}static void __devinit it8172_remove(struct pci_dev *dev){    struct it8172_state *s = pci_get_drvdata(dev);    if (!s)	return;    list_del(&s->devs);#ifdef IT8172_DEBUG    if (s->ps)	remove_proc_entry(IT8172_MODULE_NAME, NULL);#endif /* IT8172_DEBUG */    synchronize_irq();    free_irq(s->irq, s);    release_region(s->io, pci_resource_len(dev,0));    unregister_sound_dsp(s->dev_audio);    unregister_sound_mixer(s->codec.dev_mixer);    kfree(s);    pci_set_drvdata(dev, NULL);}static struct pci_device_id id_table[] __devinitdata = {    { PCI_VENDOR_ID_ITE, PCI_DEVICE_ID_ITE_IT8172G_AUDIO, PCI_ANY_ID,      PCI_ANY_ID, 0, 0 },    { 0, }};MODULE_DEVICE_TABLE(pci, id_table);static struct pci_driver it8172_driver = {    name: IT8172_MODULE_NAME,    id_table: id_table,    probe: it8172_probe,    remove: it8172_remove};static int __init init_it8172(void){    if (!pci_present())   /* No PCI bus in this machine! */	return -ENODEV;    printk("version v0.26 time " __TIME__ " " __DATE__ "\n");    return pci_module_init(&it8172_driver);}static void __exit cleanup_it8172(void){    printk(KERN_INFO PFX "unloading\n");    pci_unregister_driver(&it8172_driver);}module_init(init_it8172);module_exit(cleanup_it8172);

⌨️ 快捷键说明

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