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

📄 intel8x0m.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	return -EIO;      __ok:	if (probing) {		/* wait for any codec ready status.		 * Once it becomes ready it should remain ready		 * as long as we do not disable the ac97 link.		 */		end_time = jiffies + HZ;		do {			status = igetdword(chip, ICHREG(GLOB_STA)) &				(ICH_PCR | ICH_SCR | ICH_TCR);			if (status)				break;			schedule_timeout_uninterruptible(1);		} while (time_after_eq(end_time, jiffies));		if (! status) {			/* no codec is found */			snd_printk(KERN_ERR "codec_ready: codec is not ready [0x%x]\n",				   igetdword(chip, ICHREG(GLOB_STA)));			return -EIO;		}		/* up to two codecs (modem cannot be tertiary with ICH4) */		nstatus = ICH_PCR | ICH_SCR;		/* wait for other codecs ready status. */		end_time = jiffies + HZ / 4;		while (status != nstatus && time_after_eq(end_time, jiffies)) {			schedule_timeout_uninterruptible(1);			status |= igetdword(chip, ICHREG(GLOB_STA)) & nstatus;		}	} else {		/* resume phase */		status = 0;		if (chip->ac97)			status |= get_ich_codec_bit(chip, chip->ac97->num);		/* wait until all the probed codecs are ready */		end_time = jiffies + HZ;		do {			nstatus = igetdword(chip, ICHREG(GLOB_STA)) &				(ICH_PCR | ICH_SCR | ICH_TCR);			if (status == nstatus)				break;			schedule_timeout_uninterruptible(1);		} while (time_after_eq(end_time, jiffies));	}	if (chip->device_type == DEVICE_SIS) {		/* unmute the output on SIS7012 */		iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);	}      	return 0;}static int snd_intel8x0_chip_init(struct intel8x0m *chip, int probing){	unsigned int i;	int err;		if ((err = snd_intel8x0m_ich_chip_init(chip, probing)) < 0)		return err;	iagetword(chip, 0);	/* clear semaphore flag */	/* disable interrupts */	for (i = 0; i < chip->bdbars_count; i++)		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00);	/* reset channels */	for (i = 0; i < chip->bdbars_count; i++)		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);	/* initialize Buffer Descriptor Lists */	for (i = 0; i < chip->bdbars_count; i++)		iputdword(chip, ICH_REG_OFF_BDBAR + chip->ichd[i].reg_offset, chip->ichd[i].bdbar_addr);	return 0;}static int snd_intel8x0_free(struct intel8x0m *chip){	unsigned int i;	if (chip->irq < 0)		goto __hw_end;	/* disable interrupts */	for (i = 0; i < chip->bdbars_count; i++)		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, 0x00);	/* reset channels */	for (i = 0; i < chip->bdbars_count; i++)		iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);	/* --- */	synchronize_irq(chip->irq);      __hw_end:	if (chip->bdbars.area)		snd_dma_free_pages(&chip->bdbars);	if (chip->addr)		pci_iounmap(chip->pci, chip->addr);	if (chip->bmaddr)		pci_iounmap(chip->pci, chip->bmaddr);	if (chip->irq >= 0)		free_irq(chip->irq, chip);	pci_release_regions(chip->pci);	pci_disable_device(chip->pci);	kfree(chip);	return 0;}#ifdef CONFIG_PM/* * power management */static int intel8x0m_suspend(struct pci_dev *pci, pm_message_t state){	struct snd_card *card = pci_get_drvdata(pci);	struct intel8x0m *chip = card->private_data;	int i;	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);	for (i = 0; i < chip->pcm_devs; i++)		snd_pcm_suspend_all(chip->pcm[i]);	snd_ac97_suspend(chip->ac97);	if (chip->irq >= 0) {		synchronize_irq(chip->irq);		free_irq(chip->irq, chip);		chip->irq = -1;	}	pci_disable_device(pci);	pci_save_state(pci);	pci_set_power_state(pci, pci_choose_state(pci, state));	return 0;}static int intel8x0m_resume(struct pci_dev *pci){	struct snd_card *card = pci_get_drvdata(pci);	struct intel8x0m *chip = card->private_data;	pci_set_power_state(pci, PCI_D0);	pci_restore_state(pci);	if (pci_enable_device(pci) < 0) {		printk(KERN_ERR "intel8x0m: pci_enable_device failed, "		       "disabling device\n");		snd_card_disconnect(card);		return -EIO;	}	pci_set_master(pci);	if (request_irq(pci->irq, snd_intel8x0_interrupt,			IRQF_SHARED, card->shortname, chip)) {		printk(KERN_ERR "intel8x0m: unable to grab IRQ %d, "		       "disabling device\n", pci->irq);		snd_card_disconnect(card);		return -EIO;	}	chip->irq = pci->irq;	snd_intel8x0_chip_init(chip, 0);	snd_ac97_resume(chip->ac97);	snd_power_change_state(card, SNDRV_CTL_POWER_D0);	return 0;}#endif /* CONFIG_PM */#ifdef CONFIG_PROC_FSstatic void snd_intel8x0m_proc_read(struct snd_info_entry * entry,				   struct snd_info_buffer *buffer){	struct intel8x0m *chip = entry->private_data;	unsigned int tmp;	snd_iprintf(buffer, "Intel8x0m\n\n");	if (chip->device_type == DEVICE_ALI)		return;	tmp = igetdword(chip, ICHREG(GLOB_STA));	snd_iprintf(buffer, "Global control        : 0x%08x\n",		    igetdword(chip, ICHREG(GLOB_CNT)));	snd_iprintf(buffer, "Global status         : 0x%08x\n", tmp);	snd_iprintf(buffer, "AC'97 codecs ready    :%s%s%s%s\n",			tmp & ICH_PCR ? " primary" : "",			tmp & ICH_SCR ? " secondary" : "",			tmp & ICH_TCR ? " tertiary" : "",			(tmp & (ICH_PCR | ICH_SCR | ICH_TCR)) == 0 ? " none" : "");}static void __devinit snd_intel8x0m_proc_init(struct intel8x0m * chip){	struct snd_info_entry *entry;	if (! snd_card_proc_new(chip->card, "intel8x0m", &entry))		snd_info_set_text_ops(entry, chip, snd_intel8x0m_proc_read);}#else /* !CONFIG_PROC_FS */#define snd_intel8x0m_proc_init(chip)#endif /* CONFIG_PROC_FS */static int snd_intel8x0_dev_free(struct snd_device *device){	struct intel8x0m *chip = device->device_data;	return snd_intel8x0_free(chip);}struct ich_reg_info {	unsigned int int_sta_mask;	unsigned int offset;};static int __devinit snd_intel8x0m_create(struct snd_card *card,					 struct pci_dev *pci,					 unsigned long device_type,					 struct intel8x0m ** r_intel8x0){	struct intel8x0m *chip;	int err;	unsigned int i;	unsigned int int_sta_masks;	struct ichdev *ichdev;	static struct snd_device_ops ops = {		.dev_free =	snd_intel8x0_dev_free,	};	static struct ich_reg_info intel_regs[2] = {		{ ICH_MIINT, 0 },		{ ICH_MOINT, 0x10 },	};	struct ich_reg_info *tbl;	*r_intel8x0 = NULL;	if ((err = pci_enable_device(pci)) < 0)		return err;	chip = kzalloc(sizeof(*chip), GFP_KERNEL);	if (chip == NULL) {		pci_disable_device(pci);		return -ENOMEM;	}	spin_lock_init(&chip->reg_lock);	chip->device_type = device_type;	chip->card = card;	chip->pci = pci;	chip->irq = -1;	if ((err = pci_request_regions(pci, card->shortname)) < 0) {		kfree(chip);		pci_disable_device(pci);		return err;	}	if (device_type == DEVICE_ALI) {		/* ALI5455 has no ac97 region */		chip->bmaddr = pci_iomap(pci, 0, 0);		goto port_inited;	}	if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */		chip->addr = pci_iomap(pci, 2, 0);	else		chip->addr = pci_iomap(pci, 0, 0);	if (!chip->addr) {		snd_printk(KERN_ERR "AC'97 space ioremap problem\n");		snd_intel8x0_free(chip);		return -EIO;	}	if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */		chip->bmaddr = pci_iomap(pci, 3, 0);	else		chip->bmaddr = pci_iomap(pci, 1, 0);	if (!chip->bmaddr) {		snd_printk(KERN_ERR "Controller space ioremap problem\n");		snd_intel8x0_free(chip);		return -EIO;	} port_inited:	if (request_irq(pci->irq, snd_intel8x0_interrupt, IRQF_SHARED,			card->shortname, chip)) {		snd_printk(KERN_ERR "unable to grab IRQ %d\n", pci->irq);		snd_intel8x0_free(chip);		return -EBUSY;	}	chip->irq = pci->irq;	pci_set_master(pci);	synchronize_irq(chip->irq);	/* initialize offsets */	chip->bdbars_count = 2;	tbl = intel_regs;	for (i = 0; i < chip->bdbars_count; i++) {		ichdev = &chip->ichd[i];		ichdev->ichd = i;		ichdev->reg_offset = tbl[i].offset;		ichdev->int_sta_mask = tbl[i].int_sta_mask;		if (device_type == DEVICE_SIS) {			/* SiS 7013 swaps the registers */			ichdev->roff_sr = ICH_REG_OFF_PICB;			ichdev->roff_picb = ICH_REG_OFF_SR;		} else {			ichdev->roff_sr = ICH_REG_OFF_SR;			ichdev->roff_picb = ICH_REG_OFF_PICB;		}		if (device_type == DEVICE_ALI)			ichdev->ali_slot = (ichdev->reg_offset - 0x40) / 0x10;	}	/* SIS7013 handles the pcm data in bytes, others are in words */	chip->pcm_pos_shift = (device_type == DEVICE_SIS) ? 0 : 1;	/* allocate buffer descriptor lists */	/* the start of each lists must be aligned to 8 bytes */	if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),				chip->bdbars_count * sizeof(u32) * ICH_MAX_FRAGS * 2,				&chip->bdbars) < 0) {		snd_intel8x0_free(chip);		return -ENOMEM;	}	/* tables must be aligned to 8 bytes here, but the kernel pages	   are much bigger, so we don't care (on i386) */	int_sta_masks = 0;	for (i = 0; i < chip->bdbars_count; i++) {		ichdev = &chip->ichd[i];		ichdev->bdbar = ((u32 *)chip->bdbars.area) + (i * ICH_MAX_FRAGS * 2);		ichdev->bdbar_addr = chip->bdbars.addr + (i * sizeof(u32) * ICH_MAX_FRAGS * 2);		int_sta_masks |= ichdev->int_sta_mask;	}	chip->int_sta_reg = ICH_REG_GLOB_STA;	chip->int_sta_mask = int_sta_masks;	if ((err = snd_intel8x0_chip_init(chip, 1)) < 0) {		snd_intel8x0_free(chip);		return err;	}	if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {		snd_intel8x0_free(chip);		return err;	}	snd_card_set_dev(card, &pci->dev);	*r_intel8x0 = chip;	return 0;}static struct shortname_table {	unsigned int id;	const char *s;} shortnames[] __devinitdata = {	{ PCI_DEVICE_ID_INTEL_82801AA_6, "Intel 82801AA-ICH" },	{ PCI_DEVICE_ID_INTEL_82801AB_6, "Intel 82901AB-ICH0" },	{ PCI_DEVICE_ID_INTEL_82801BA_6, "Intel 82801BA-ICH2" },	{ PCI_DEVICE_ID_INTEL_440MX_6, "Intel 440MX" },	{ PCI_DEVICE_ID_INTEL_82801CA_6, "Intel 82801CA-ICH3" },	{ PCI_DEVICE_ID_INTEL_82801DB_6, "Intel 82801DB-ICH4" },	{ PCI_DEVICE_ID_INTEL_82801EB_6, "Intel ICH5" },	{ PCI_DEVICE_ID_INTEL_ICH6_17, "Intel ICH6" },	{ PCI_DEVICE_ID_INTEL_ICH7_19, "Intel ICH7" },	{ 0x7446, "AMD AMD768" },	{ PCI_DEVICE_ID_SI_7013, "SiS SI7013" },	{ PCI_DEVICE_ID_NVIDIA_MCP1_MODEM, "NVidia nForce" },	{ PCI_DEVICE_ID_NVIDIA_MCP2_MODEM, "NVidia nForce2" },	{ PCI_DEVICE_ID_NVIDIA_MCP2S_MODEM, "NVidia nForce2s" },	{ PCI_DEVICE_ID_NVIDIA_MCP3_MODEM, "NVidia nForce3" },#if 0	{ 0x5455, "ALi M5455" },	{ 0x746d, "AMD AMD8111" },#endif	{ 0 },};static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,					const struct pci_device_id *pci_id){	struct snd_card *card;	struct intel8x0m *chip;	int err;	struct shortname_table *name;	card = snd_card_new(index, id, THIS_MODULE, 0);	if (card == NULL)		return -ENOMEM;	strcpy(card->driver, "ICH-MODEM");	strcpy(card->shortname, "Intel ICH");	for (name = shortnames; name->id; name++) {		if (pci->device == name->id) {			strcpy(card->shortname, name->s);			break;		}	}	strcat(card->shortname," Modem");	if ((err = snd_intel8x0m_create(card, pci, pci_id->driver_data, &chip)) < 0) {		snd_card_free(card);		return err;	}	card->private_data = chip;	if ((err = snd_intel8x0_mixer(chip, ac97_clock)) < 0) {		snd_card_free(card);		return err;	}	if ((err = snd_intel8x0_pcm(chip)) < 0) {		snd_card_free(card);		return err;	}		snd_intel8x0m_proc_init(chip);	sprintf(card->longname, "%s at irq %i",		card->shortname, chip->irq);	if ((err = snd_card_register(card)) < 0) {		snd_card_free(card);		return err;	}	pci_set_drvdata(pci, card);	return 0;}static void __devexit snd_intel8x0m_remove(struct pci_dev *pci){	snd_card_free(pci_get_drvdata(pci));	pci_set_drvdata(pci, NULL);}static struct pci_driver driver = {	.name = "Intel ICH Modem",	.id_table = snd_intel8x0m_ids,	.probe = snd_intel8x0m_probe,	.remove = __devexit_p(snd_intel8x0m_remove),#ifdef CONFIG_PM	.suspend = intel8x0m_suspend,	.resume = intel8x0m_resume,#endif};static int __init alsa_card_intel8x0m_init(void){	return pci_register_driver(&driver);}static void __exit alsa_card_intel8x0m_exit(void){	pci_unregister_driver(&driver);}module_init(alsa_card_intel8x0m_init)module_exit(alsa_card_intel8x0m_exit)

⌨️ 快捷键说明

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