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

📄 ens1370.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 5 页
字号:
	.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 + -