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

📄 ice1724.c

📁 鼎力推荐!本程序是基于嵌入式LUNUX系统开发的源程序代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	.get = snd_vt1724_pro_peak_get};/* * */static struct snd_ice1712_card_info no_matched __devinitdata;static struct snd_ice1712_card_info *card_tables[] __devinitdata = {	snd_vt1724_revo_cards,	snd_vt1724_amp_cards, 	snd_vt1724_aureon_cards,	snd_vt1720_mobo_cards,	snd_vt1720_pontis_cards,	snd_vt1724_prodigy192_cards,	NULL,};/* */static void wait_i2c_busy(ice1712_t *ice){	int t = 0x10000;	while ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_BUSY) && t--)		;}unsigned char snd_vt1724_read_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr){	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));	outb(dev & ~VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));	wait_i2c_busy(ice);	return inb(ICEREG1724(ice, I2C_DATA));}void snd_vt1724_write_i2c(ice1712_t *ice, unsigned char dev, unsigned char addr, unsigned char data){	wait_i2c_busy(ice);	outb(addr, ICEREG1724(ice, I2C_BYTE_ADDR));	outb(data, ICEREG1724(ice, I2C_DATA));	outb(dev | VT1724_I2C_WRITE, ICEREG1724(ice, I2C_DEV_ADDR));	wait_i2c_busy(ice);}static int __devinit snd_vt1724_read_eeprom(ice1712_t *ice, const char *modelname){	const int dev = 0xa0;		/* EEPROM device address */	unsigned int i, size;	struct snd_ice1712_card_info **tbl, *c;	if (! modelname || ! *modelname) {		ice->eeprom.subvendor = 0;		if ((inb(ICEREG1724(ice, I2C_CTRL)) & VT1724_I2C_EEPROM) != 0)			ice->eeprom.subvendor = (snd_vt1724_read_i2c(ice, dev, 0x00) << 0) |				(snd_vt1724_read_i2c(ice, dev, 0x01) << 8) | 				(snd_vt1724_read_i2c(ice, dev, 0x02) << 16) | 				(snd_vt1724_read_i2c(ice, dev, 0x03) << 24);		if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {			/* invalid subvendor from EEPROM, try the PCI subststem ID instead */			u16 vendor, device;			pci_read_config_word(ice->pci, PCI_SUBSYSTEM_VENDOR_ID, &vendor);			pci_read_config_word(ice->pci, PCI_SUBSYSTEM_ID, &device);			ice->eeprom.subvendor = ((unsigned int)swab16(vendor) << 16) | swab16(device);			if (ice->eeprom.subvendor == 0 || ice->eeprom.subvendor == (unsigned int)-1) {				printk(KERN_ERR "ice1724: No valid ID is found\n");				return -ENXIO;			}		}	}	for (tbl = card_tables; *tbl; tbl++) {		for (c = *tbl; c->subvendor; c++) {			if (modelname && c->model && ! strcmp(modelname, c->model)) {				printk(KERN_INFO "ice1724: Using board model %s\n", c->name);				ice->eeprom.subvendor = c->subvendor;			} else if (c->subvendor != ice->eeprom.subvendor)				continue;			if (! c->eeprom_size || ! c->eeprom_data)				goto found;			/* if the EEPROM is given by the driver, use it */			snd_printdd("using the defined eeprom..\n");			ice->eeprom.version = 2;			ice->eeprom.size = c->eeprom_size + 6;			memcpy(ice->eeprom.data, c->eeprom_data, c->eeprom_size);			goto read_skipped;		}	}	printk(KERN_WARNING "ice1724: No matching model found for ID 0x%x\n", ice->eeprom.subvendor); found:	ice->eeprom.size = snd_vt1724_read_i2c(ice, dev, 0x04);	if (ice->eeprom.size < 6)		ice->eeprom.size = 32;	else if (ice->eeprom.size > 32) {		printk(KERN_ERR "ice1724: Invalid EEPROM (size = %i)\n", ice->eeprom.size);		return -EIO;	}	ice->eeprom.version = snd_vt1724_read_i2c(ice, dev, 0x05);	if (ice->eeprom.version != 2)		printk(KERN_WARNING "ice1724: Invalid EEPROM version %i\n", ice->eeprom.version);	size = ice->eeprom.size - 6;	for (i = 0; i < size; i++)		ice->eeprom.data[i] = snd_vt1724_read_i2c(ice, dev, i + 6); read_skipped:	ice->eeprom.gpiomask = eeprom_triple(ice, ICE_EEP2_GPIO_MASK);	ice->eeprom.gpiostate = eeprom_triple(ice, ICE_EEP2_GPIO_STATE);	ice->eeprom.gpiodir = eeprom_triple(ice, ICE_EEP2_GPIO_DIR);	return 0;}static int __devinit snd_vt1724_chip_init(ice1712_t *ice){	outb(VT1724_RESET , ICEREG1724(ice, CONTROL));	udelay(200);	outb(0, ICEREG1724(ice, CONTROL));	udelay(200);	outb(ice->eeprom.data[ICE_EEP2_SYSCONF], ICEREG1724(ice, SYS_CFG));	outb(ice->eeprom.data[ICE_EEP2_ACLINK], ICEREG1724(ice, AC97_CFG));	outb(ice->eeprom.data[ICE_EEP2_I2S], ICEREG1724(ice, I2S_FEATURES));	outb(ice->eeprom.data[ICE_EEP2_SPDIF], ICEREG1724(ice, SPDIF_CFG));	ice->gpio.write_mask = ice->eeprom.gpiomask;	ice->gpio.direction = ice->eeprom.gpiodir;	snd_vt1724_set_gpio_mask(ice, ice->eeprom.gpiomask);	snd_vt1724_set_gpio_dir(ice, ice->eeprom.gpiodir);	snd_vt1724_set_gpio_data(ice, ice->eeprom.gpiostate);	outb(0, ICEREG1724(ice, POWERDOWN));	return 0;}static int __devinit snd_vt1724_spdif_build_controls(ice1712_t *ice){	int err;	snd_kcontrol_t *kctl;	snd_assert(ice->pcm != NULL, return -EIO);	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_mixer_pro_spdif_route, ice));	if (err < 0)		return err;	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_spdif_switch, ice));	if (err < 0)		return err;	err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_default, ice));	if (err < 0)		return err;	kctl->id.device = ice->pcm->device;	err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_maskc, ice));	if (err < 0)		return err;	kctl->id.device = ice->pcm->device;	err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_maskp, ice));	if (err < 0)		return err;	kctl->id.device = ice->pcm->device;#if 0 /* use default only */	err = snd_ctl_add(ice->card, kctl = snd_ctl_new1(&snd_vt1724_spdif_stream, ice));	if (err < 0)		return err;	kctl->id.device = ice->pcm->device;	ice->spdif.stream_ctl = kctl;#endif	return 0;}static int __devinit snd_vt1724_build_controls(ice1712_t *ice){	int err;	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_eeprom, ice));	if (err < 0)		return err;	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_internal_clock, ice));	if (err < 0)		return err;	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_rate_locking, ice));	if (err < 0)		return err;	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_pro_rate_reset, ice));	if (err < 0)		return err;	if (ice->num_total_dacs > 0) {		snd_kcontrol_new_t tmp = snd_vt1724_mixer_pro_analog_route;		tmp.count = ice->num_total_dacs;		if (ice->vt1720 && tmp.count > 2)			tmp.count = 2;		err = snd_ctl_add(ice->card, snd_ctl_new1(&tmp, ice));		if (err < 0)			return err;	}	err = snd_ctl_add(ice->card, snd_ctl_new1(&snd_vt1724_mixer_pro_peak, ice));	if (err < 0)		return err;	return 0;}static int snd_vt1724_free(ice1712_t *ice){	if (! ice->port)		goto __hw_end;	/* mask all interrupts */	outb(0xff, ICEMT1724(ice, DMA_INT_MASK));	outb(0xff, ICEREG1724(ice, IRQMASK));	/* --- */      __hw_end:	if (ice->irq >= 0) {		synchronize_irq(ice->irq);		free_irq(ice->irq, (void *) ice);	}	pci_release_regions(ice->pci);	snd_ice1712_akm4xxx_free(ice);	pci_disable_device(ice->pci);	kfree(ice);	return 0;}static int snd_vt1724_dev_free(snd_device_t *device){	ice1712_t *ice = device->device_data;	return snd_vt1724_free(ice);}static int __devinit snd_vt1724_create(snd_card_t * card,				       struct pci_dev *pci,				       const char *modelname,				       ice1712_t ** r_ice1712){	ice1712_t *ice;	int err;	unsigned char mask;	static snd_device_ops_t ops = {		.dev_free =	snd_vt1724_dev_free,	};	*r_ice1712 = NULL;        /* enable PCI device */	if ((err = pci_enable_device(pci)) < 0)		return err;	ice = kcalloc(1, sizeof(*ice), GFP_KERNEL);	if (ice == NULL) {		pci_disable_device(pci);		return -ENOMEM;	}	ice->vt1724 = 1;	spin_lock_init(&ice->reg_lock);	init_MUTEX(&ice->gpio_mutex);	init_MUTEX(&ice->open_mutex);	ice->gpio.set_mask = snd_vt1724_set_gpio_mask;	ice->gpio.set_dir = snd_vt1724_set_gpio_dir;	ice->gpio.set_data = snd_vt1724_set_gpio_data;	ice->gpio.get_data = snd_vt1724_get_gpio_data;	ice->card = card;	ice->pci = pci;	ice->irq = -1;	pci_set_master(pci);	snd_vt1724_proc_init(ice);	synchronize_irq(pci->irq);	if ((err = pci_request_regions(pci, "ICE1724")) < 0) {		kfree(ice);		pci_disable_device(pci);		return err;	}	ice->port = pci_resource_start(pci, 0);	ice->profi_port = pci_resource_start(pci, 1);	if (request_irq(pci->irq, snd_vt1724_interrupt, SA_INTERRUPT|SA_SHIRQ, "ICE1724", (void *) ice)) {		snd_printk("unable to grab IRQ %d\n", pci->irq);		snd_vt1724_free(ice);		return -EIO;	}	ice->irq = pci->irq;	if (snd_vt1724_read_eeprom(ice, modelname) < 0) {		snd_vt1724_free(ice);		return -EIO;	}	if (snd_vt1724_chip_init(ice) < 0) {		snd_vt1724_free(ice);		return -EIO;	}	/* unmask used interrupts */	if (! (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401))		mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;	else		mask = 0;	outb(mask, ICEREG1724(ice, IRQMASK));	/* don't handle FIFO overrun/underruns (just yet), since they cause machine lockups */	outb(VT1724_MULTI_FIFO_ERR, ICEMT1724(ice, DMA_INT_MASK));	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, ice, &ops)) < 0) {		snd_vt1724_free(ice); 		return err;	}	snd_card_set_dev(card, &pci->dev);	*r_ice1712 = ice;	return 0;}/* * * Registration * */static int __devinit snd_vt1724_probe(struct pci_dev *pci,				      const struct pci_device_id *pci_id){	static int dev;	snd_card_t *card;	ice1712_t *ice;	int pcm_dev = 0, err;	struct snd_ice1712_card_info **tbl, *c;	if (dev >= SNDRV_CARDS)		return -ENODEV;	if (!enable[dev]) {		dev++;		return -ENOENT;	}	card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);	if (card == NULL)		return -ENOMEM;	strcpy(card->driver, "ICE1724");	strcpy(card->shortname, "ICEnsemble ICE1724");		if ((err = snd_vt1724_create(card, pci, model[dev], &ice)) < 0) {		snd_card_free(card);		return err;	}	for (tbl = card_tables; *tbl; tbl++) {		for (c = *tbl; c->subvendor; c++) {			if (c->subvendor == ice->eeprom.subvendor) {				strcpy(card->shortname, c->name);				if (c->driver) /* specific driver? */					strcpy(card->driver, c->driver);				if (c->chip_init) {					if ((err = c->chip_init(ice)) < 0) {						snd_card_free(card);						return err;					}				}				goto __found;			}		}	}	c = &no_matched; __found:	if ((err = snd_vt1724_pcm_profi(ice, pcm_dev++)) < 0) {		snd_card_free(card);		return err;	}		if ((err = snd_vt1724_pcm_spdif(ice, pcm_dev++)) < 0) {		snd_card_free(card);		return err;	}		if ((err = snd_vt1724_pcm_indep(ice, pcm_dev++)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_vt1724_ac97_mixer(ice)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_vt1724_build_controls(ice)) < 0) {		snd_card_free(card);		return err;	}	if (ice->pcm && ice->has_spdif) { /* has SPDIF I/O */		if ((err = snd_vt1724_spdif_build_controls(ice)) < 0) {			snd_card_free(card);			return err;		}	}	if (c->build_controls) {		if ((err = c->build_controls(ice)) < 0) {			snd_card_free(card);			return err;		}	}	if (! c->no_mpu401) {		if (ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_MPU401) {			if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,						       ICEREG1724(ice, MPU_CTRL), 1,						       ice->irq, 0,						       &ice->rmidi[0])) < 0) {				snd_card_free(card);				return err;			}		}	}	sprintf(card->longname, "%s at 0x%lx, irq %i",		card->shortname, ice->port, ice->irq);	if ((err = snd_card_register(card)) < 0) {		snd_card_free(card);		return err;	}	pci_set_drvdata(pci, card);	dev++;	return 0;}static void __devexit snd_vt1724_remove(struct pci_dev *pci){	snd_card_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	.name = "ICE1724",	.id_table = snd_vt1724_ids,	.probe = snd_vt1724_probe,	.remove = __devexit_p(snd_vt1724_remove),};static int __init alsa_card_ice1724_init(void){	return pci_module_init(&driver);}static void __exit alsa_card_ice1724_exit(void){	pci_unregister_driver(&driver);}m

⌨️ 快捷键说明

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