ens1370.c
来自「linux 内核源代码」· C语言 代码 · 共 1,967 行 · 第 1/5 页
C
1,967 行
ensoniq->u.es1371.ac97 = NULL;}struct es1371_quirk { unsigned short vid; /* vendor ID */ unsigned short did; /* device ID */ unsigned char rev; /* revision */};static int es1371_quirk_lookup(struct ensoniq *ensoniq, struct es1371_quirk *list){ while (list->vid != (unsigned short)PCI_ANY_ID) { if (ensoniq->pci->vendor == list->vid && ensoniq->pci->device == list->did && ensoniq->rev == list->rev) return 1; list++; } return 0;}static struct es1371_quirk 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 struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = { SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */ SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */ { } /* end */};static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq, int has_spdif, int has_line){ struct snd_card *card = ensoniq->card; struct snd_ac97_bus *pbus; struct snd_ac97_template ac97; int err; static struct snd_ac97_bus_ops ops = { .write = snd_es1371_codec_write, .read = snd_es1371_codec_read, .wait = snd_es1371_codec_wait, }; 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; if (has_spdif > 0 || (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) { struct snd_kcontrol *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 < 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; err = snd_ctl_add(card, kctl); if (err < 0) return err; } } 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 (has_line > 0 || snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) { 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 }#define snd_ensoniq_control_info snd_ctl_boolean_mono_infostatic int snd_ensoniq_control_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct ensoniq *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(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol){ struct ensoniq *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 struct snd_kcontrol_new 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(struct snd_ak4531 *ak4531){ struct ensoniq *ensoniq = ak4531->private_data; ensoniq->u.es1370.ak4531 = NULL;}static int __devinit snd_ensoniq_1370_mixer(struct ensoniq * ensoniq){ struct snd_card *card = ensoniq->card; struct snd_ak4531 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_JOYSTICK#ifdef CHIP1371static int __devinit snd_ensoniq_get_joystick_port(int dev){ switch (joystick_port[dev]) { case 0: /* disabled */ case 1: /* auto-detect */ case 0x200: case 0x208: case 0x210: case 0x218: return joystick_port[dev]; default: printk(KERN_ERR "ens1371: invalid joystick port %#x", joystick_port[dev]); return 0; }}#elsestatic inline int snd_ensoniq_get_joystick_port(int dev){ return joystick[dev] ? 0x200 : 0;}#endifstatic int __devinit snd_ensoniq_create_gameport(struct ensoniq *ensoniq, int dev){ struct gameport *gp; int io_port; io_port = snd_ensoniq_get_joystick_port(dev); switch (io_port) { case 0: return -ENOSYS; case 1: /* auto_detect */ for (io_port = 0x200; io_port <= 0x218; io_port += 8) if (request_region(io_port, 8, "ens137x: gameport")) break; if (io_port > 0x218) { printk(KERN_WARNING "ens137x: no gameport ports available\n"); return -EBUSY; } break; default: if (!request_region(io_port, 8, "ens137x: gameport")) { printk(KERN_WARNING "ens137x: gameport io port 0x%#x in use\n", io_port); return -EBUSY; } break; } ensoniq->gameport = gp = gameport_allocate_port(); if (!gp) { printk(KERN_ERR "ens137x: cannot allocate memory for gameport\n"); release_region(io_port, 8); return -ENOMEM; } gameport_set_name(gp, "ES137x"); gameport_set_phys(gp, "pci%s/gameport0", pci_name(ensoniq->pci)); gameport_set_dev_parent(gp, &ensoniq->pci->dev); gp->io = io_port; ensoniq->ctrl |= ES_JYSTK_EN;#ifdef CHIP1371 ensoniq->ctrl &= ~ES_1371_JOY_ASELM; ensoniq->ctrl |= ES_1371_JOY_ASEL((io_port - 0x200) / 8);#endif outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); gameport_register_port(ensoniq->gameport); return 0;}static void snd_ensoniq_free_gameport(struct ensoniq *ensoniq){ if (ensoniq->gameport) { int port = ensoniq->gameport->io; gameport_unregister_port(ensoniq->gameport); ensoniq->gameport = NULL; ensoniq->ctrl &= ~ES_JYSTK_EN; outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); release_region(port, 8); }}#elsestatic inline int snd_ensoniq_create_gameport(struct ensoniq *ensoniq, long port) { return -ENOSYS; }static inline void snd_ensoniq_free_gameport(struct ensoniq *ensoniq) { }#endif /* SUPPORT_JOYSTICK *//* */static void snd_ensoniq_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer){ struct ensoniq *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(struct ensoniq * ensoniq){ struct snd_info_entry *entry; if (! snd_card_proc_new(ensoniq->card, "audiopci", &entry)) snd_info_set_text_ops(entry, ensoniq, snd_ensoniq_proc_read);}/* */static int snd_ensoniq_free(struct ensoniq *ensoniq){ snd_ensoniq_free_gameport(ensoniq); 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, ensoniq); pci_release_regions(ensoniq->pci); pci_disable_device(ensoniq->pci); kfree(ensoniq); return 0;}static int snd_ensoniq_dev_free(struct snd_device *device){ struct ensoniq *ensoniq = device->device_data; return snd_ensoniq_free(ensoniq);}#ifdef CHIP1371static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = { SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */ SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */ SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */ SND_PCI_QUIRK_ID(0x1102, 0x8938), /* IPC Topnote G notebook */ { } /* end */};static struct es1371_quirk 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 void snd_ensoniq_chip_init(struct ensoniq *ensoniq){#ifdef CHIP1371 int idx;#endif /* this code was part of snd_ensoniq_create before intruduction * of suspend/resume */#ifdef CHIP1370 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)); out
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?