📄 ens1370.c
字号:
.name = "Line In->Rear Out Switch", .info = snd_es1373_line_info, .get = snd_es1373_line_get, .put = snd_es1373_line_put,};static void snd_ensoniq_mixer_free_ac97(ac97_t *ac97){ ensoniq_t *ensoniq = ac97->private_data; ensoniq->u.es1371.ac97 = NULL;}static struct { unsigned short vid; /* vendor ID */ unsigned short did; /* device ID */ unsigned char rev; /* revision */} es1371_spdif_present[] __devinitdata = { { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 }, { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }};static int snd_ensoniq_1371_mixer(ensoniq_t * ensoniq){ snd_card_t *card = ensoniq->card; ac97_bus_t *pbus; ac97_template_t ac97; int err, idx; static ac97_bus_ops_t ops = { .write = snd_es1371_codec_write, .read = snd_es1371_codec_read, }; if ((err = snd_ac97_bus(card, 0, &ops, NULL, &pbus)) < 0) return err; memset(&ac97, 0, sizeof(ac97)); ac97.private_data = ensoniq; ac97.private_free = snd_ensoniq_mixer_free_ac97; ac97.scaps = AC97_SCAP_AUDIO; if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) return err; for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++) if (ensoniq->pci->vendor == es1371_spdif_present[idx].vid && ensoniq->pci->device == es1371_spdif_present[idx].did && ensoniq->rev == es1371_spdif_present[idx].rev) { snd_kcontrol_t *kctl; int i, index = 0; ensoniq->spdif_default = ensoniq->spdif_stream = SNDRV_PCM_DEFAULT_CON_SPDIF; outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS)); if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) index++; for (i = 0; i < (int)ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); if (! kctl) return -ENOMEM; kctl->id.index = index; if ((err = snd_ctl_add(card, kctl)) < 0) return err; } break; } if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { /* mirror rear to front speakers */ ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); ensoniq->cssr |= ES_1373_REAR_BIT26; err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_rear, ensoniq)); if (err < 0) return err; } if ((ensoniq->subsystem_vendor_id == 0x1274) && (ensoniq->subsystem_device_id == 0x2000)) { /* GA-7DXR */ err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq)); if (err < 0) return err; } return 0;}#endif /* CHIP1371 *//* generic control callbacks for ens1370 */#ifdef CHIP1370#define ENSONIQ_CONTROL(xname, mask) \{ .iface = SNDRV_CTL_ELEM_IFACE_CARD, .name = xname, .info = snd_ensoniq_control_info, \ .get = snd_ensoniq_control_get, .put = snd_ensoniq_control_put, \ .private_value = mask }static int snd_ensoniq_control_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 1; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int snd_ensoniq_control_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol); int mask = kcontrol->private_value; spin_lock_irq(&ensoniq->reg_lock); ucontrol->value.integer.value[0] = ensoniq->ctrl & mask ? 1 : 0; spin_unlock_irq(&ensoniq->reg_lock); return 0;}static int snd_ensoniq_control_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol){ ensoniq_t *ensoniq = snd_kcontrol_chip(kcontrol); int mask = kcontrol->private_value; unsigned int nval; int change; nval = ucontrol->value.integer.value[0] ? mask : 0; spin_lock_irq(&ensoniq->reg_lock); change = (ensoniq->ctrl & mask) != nval; ensoniq->ctrl &= ~mask; ensoniq->ctrl |= nval; outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); spin_unlock_irq(&ensoniq->reg_lock); return change;}/* * ENS1370 mixer */static snd_kcontrol_new_t snd_es1370_controls[2] __devinitdata = {ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)};#define ES1370_CONTROLS ARRAY_SIZE(snd_es1370_controls)static void snd_ensoniq_mixer_free_ak4531(ak4531_t *ak4531){ ensoniq_t *ensoniq = ak4531->private_data; ensoniq->u.es1370.ak4531 = NULL;}static int __devinit snd_ensoniq_1370_mixer(ensoniq_t * ensoniq){ snd_card_t *card = ensoniq->card; ak4531_t ak4531; unsigned int idx; int err; /* try reset AK4531 */ outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x02), ES_REG(ensoniq, 1370_CODEC)); inw(ES_REG(ensoniq, 1370_CODEC)); udelay(100); outw(ES_1370_CODEC_WRITE(AK4531_RESET, 0x03), ES_REG(ensoniq, 1370_CODEC)); inw(ES_REG(ensoniq, 1370_CODEC)); udelay(100); memset(&ak4531, 0, sizeof(ak4531)); ak4531.write = snd_es1370_codec_write; ak4531.private_data = ensoniq; ak4531.private_free = snd_ensoniq_mixer_free_ak4531; if ((err = snd_ak4531_mixer(card, &ak4531, &ensoniq->u.es1370.ak4531)) < 0) return err; for (idx = 0; idx < ES1370_CONTROLS; idx++) { err = snd_ctl_add(card, snd_ctl_new1(&snd_es1370_controls[idx], ensoniq)); if (err < 0) return err; } return 0;}#endif /* CHIP1370 */#ifdef SUPPORT_JOYSTICKstatic int snd_ensoniq_joystick(ensoniq_t *ensoniq, long port){#ifdef CHIP1371 if (port == 1) { /* auto-detect */ for (port = 0x200; port <= 0x218; port += 8) if (request_region(port, 8, "ens137x: gameport")) break; if (port > 0x218) { snd_printk("no gameport available\n"); return -EBUSY; } } else#endif { if (!request_region(port, 8, "ens137x: gameport")) { snd_printk("gameport io port 0x%03x in use", ensoniq->gameport.io); return -EBUSY; } } ensoniq->gameport.io = port; ensoniq->ctrl |= ES_JYSTK_EN;#ifdef CHIP1371 ensoniq->ctrl &= ~ES_1371_JOY_ASELM; ensoniq->ctrl |= ES_1371_JOY_ASEL((ensoniq->gameport.io - 0x200) / 8);#endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); gameport_register_port(&ensoniq->gameport); return 0;}static void snd_ensoniq_joystick_free(ensoniq_t *ensoniq){ gameport_unregister_port(&ensoniq->gameport); ensoniq->ctrl &= ~ES_JYSTK_EN; outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); release_region(ensoniq->gameport.io, 8);}#endif /* SUPPORT_JOYSTICK *//* */static void snd_ensoniq_proc_read(snd_info_entry_t *entry, snd_info_buffer_t * buffer){ ensoniq_t *ensoniq = entry->private_data;#ifdef CHIP1370 snd_iprintf(buffer, "Ensoniq AudioPCI ES1370\n\n");#else snd_iprintf(buffer, "Ensoniq AudioPCI ES1371\n\n");#endif snd_iprintf(buffer, "Joystick enable : %s\n", ensoniq->ctrl & ES_JYSTK_EN ? "on" : "off");#ifdef CHIP1370 snd_iprintf(buffer, "MIC +5V bias : %s\n", ensoniq->ctrl & ES_1370_XCTL1 ? "on" : "off"); snd_iprintf(buffer, "Line In to AOUT : %s\n", ensoniq->ctrl & ES_1370_XCTL0 ? "on" : "off");#else snd_iprintf(buffer, "Joystick port : 0x%x\n", (ES_1371_JOY_ASELI(ensoniq->ctrl) * 8) + 0x200);#endif}static void __devinit snd_ensoniq_proc_init(ensoniq_t * ensoniq){ snd_info_entry_t *entry; if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) snd_info_set_text_ops(entry, ensoniq, 1024, snd_ensoniq_proc_read);}/* */static int snd_ensoniq_free(ensoniq_t *ensoniq){#ifdef SUPPORT_JOYSTICK if (ensoniq->ctrl & ES_JYSTK_EN) snd_ensoniq_joystick_free(ensoniq);#endif if (ensoniq->irq < 0) goto __hw_end;#ifdef CHIP1370 outl(ES_1370_SERR_DISABLE, ES_REG(ensoniq, CONTROL)); /* switch everything off */ outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */#else outl(0, ES_REG(ensoniq, CONTROL)); /* switch everything off */ outl(0, ES_REG(ensoniq, SERIAL)); /* clear serial interface */#endif synchronize_irq(ensoniq->irq); pci_set_power_state(ensoniq->pci, 3); __hw_end:#ifdef CHIP1370 if (ensoniq->dma_bug.area) snd_dma_free_pages(&ensoniq->dma_bug);#endif if (ensoniq->irq >= 0) free_irq(ensoniq->irq, (void *)ensoniq); pci_release_regions(ensoniq->pci); kfree(ensoniq); return 0;}static int snd_ensoniq_dev_free(snd_device_t *device){ ensoniq_t *ensoniq = device->device_data; return snd_ensoniq_free(ensoniq);}#ifdef CHIP1371static struct { unsigned short svid; /* subsystem vendor ID */ unsigned short sdid; /* subsystem device ID */} es1371_amplifier_hack[] = { { .svid = 0x107b, .sdid = 0x2150 }, /* Gateway Solo 2150 */ { .svid = 0x13bd, .sdid = 0x100c }, /* EV1938 on Mebius PC-MJ100V */ { .svid = 0x1102, .sdid = 0x5938 }, /* Targa Xtender300 */ { .svid = 0x1102, .sdid = 0x8938 }, /* IPC Topnote G notebook */ { .svid = PCI_ANY_ID, .sdid = PCI_ANY_ID }};static struct { unsigned short vid; /* vendor ID */ unsigned short did; /* device ID */ unsigned char rev; /* revision */} es1371_ac97_reset_hack[] = { { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_CT5880_A }, { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_ES1371, .rev = ES1371REV_ES1373_8 }, { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }};#endifstatic int __devinit snd_ensoniq_create(snd_card_t * card, struct pci_dev *pci, ensoniq_t ** rensoniq){ ensoniq_t *ensoniq; unsigned short cmdw; unsigned char cmdb;#ifdef CHIP1371 int idx;#endif int err; static snd_device_ops_t ops = { .dev_free = snd_ensoniq_dev_free, }; *rensoniq = NULL; if ((err = pci_enable_device(pci)) < 0) return err; ensoniq = kcalloc(1, sizeof(*ensoniq), GFP_KERNEL); if (ensoniq == NULL) return -ENOMEM; spin_lock_init(&ensoniq->reg_lock); ensoniq->card = card; ensoniq->pci = pci; ensoniq->irq = -1; if ((err = pci_request_regions(pci, "Ensoniq AudioPCI")) < 0) { kfree(ensoniq); return err; } ensoniq->port = pci_resource_start(pci, 0); if (request_irq(pci->irq, snd_audiopci_interrupt, SA_INTERRUPT|SA_SHIRQ, "Ensoniq AudioPCI", (void *)ensoniq)) { snd_printk("unable to grab IRQ %d\n", pci->irq); snd_ensoniq_free(ensoniq); return -EBUSY; } ensoniq->irq = pci->irq;#ifdef CHIP1370 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 16, &ensoniq->dma_bug) < 0) { snd_printk("unable to allocate space for phantom area - dma_bug\n"); snd_ensoniq_free(ensoniq); return -EBUSY; }#endif pci_set_master(pci); pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb); ensoniq->rev = cmdb; pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw); ensoniq->subsystem_vendor_id = cmdw; pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw); ensoniq->subsystem_device_id = cmdw; snd_ensoniq_proc_init(ensoniq);#ifdef CHIP1370#if 0 ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));#else /* get microphone working */ ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_PCLKDIVO(ES_1370_SRTODIV(8000));#endif ensoniq->sctrl = 0; /* initialize the chips */ outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); outl(ES_MEM_PAGEO(ES_PAGE_ADC), ES_REG(ensoniq, MEM_PAGE)); outl(ensoniq->dma_bug.addr, ES_REG(ensoniq, PHANTOM_FRAME)); outl(0, ES_REG(ensoniq, PHANTOM_COUNT));#else ensoni
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -