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

📄 via82xx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	},	{		.subvendor = 0x1019,		.subdevice = 0x0a85,		.name = "ECS L7VMM2",		.type = AC97_TUNE_HP_ONLY	},	{		.subvendor = 0x1849,		.subdevice = 0x3059,		.name = "ASRock K7VM2",		.type = AC97_TUNE_HP_ONLY	/* VT1616 */	},	{		.subvendor = 0x14cd,		.subdevice = 0x7002,		.name = "Unknown",		.type = AC97_TUNE_ALC_JACK	},	{		.subvendor = 0x1071,		.subdevice = 0x8590,		.name = "Mitac Mobo",		.type = AC97_TUNE_ALC_JACK	},	{		.subvendor = 0x161f,		.subdevice = 0x202b,		.name = "Arima Notebook",		.type = AC97_TUNE_HP_ONLY,	},	{		.subvendor = 0x161f,		.subdevice = 0x2032,		.name = "Targa Traveller 811",		.type = AC97_TUNE_HP_ONLY,	},	{		.subvendor = 0x161f,		.subdevice = 0x2032,		.name = "m680x",		.type = AC97_TUNE_HP_ONLY, /* http://launchpad.net/bugs/38546 */	},	{ } /* terminator */};static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_override){	struct snd_ac97_template ac97;	int err;	static struct snd_ac97_bus_ops ops = {		.write = snd_via82xx_codec_write,		.read = snd_via82xx_codec_read,		.wait = snd_via82xx_codec_wait,	};	if ((err = snd_ac97_bus(chip->card, 0, &ops, chip, &chip->ac97_bus)) < 0)		return err;	chip->ac97_bus->private_free = snd_via82xx_mixer_free_ac97_bus;	chip->ac97_bus->clock = chip->ac97_clock;	memset(&ac97, 0, sizeof(ac97));	ac97.private_data = chip;	ac97.private_free = snd_via82xx_mixer_free_ac97;	ac97.pci = chip->pci;	ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;	if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)		return err;	snd_ac97_tune_hardware(chip->ac97, ac97_quirks, quirk_override);	if (chip->chip_type != TYPE_VIA686) {		/* use slot 10/11 */		snd_ac97_update_bits(chip->ac97, AC97_EXTENDED_STATUS, 0x03 << 4, 0x03 << 4);	}	return 0;}#ifdef SUPPORT_JOYSTICK#define JOYSTICK_ADDR	0x200static int __devinit snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy){	struct gameport *gp;	struct resource *r;	if (!joystick)		return -ENODEV;	r = request_region(JOYSTICK_ADDR, 8, "VIA686 gameport");	if (!r) {		printk(KERN_WARNING "via82xx: cannot reserve joystick port 0x%#x\n",		       JOYSTICK_ADDR);		return -EBUSY;	}	chip->gameport = gp = gameport_allocate_port();	if (!gp) {		printk(KERN_ERR "via82xx: cannot allocate memory for gameport\n");		release_and_free_resource(r);		return -ENOMEM;	}	gameport_set_name(gp, "VIA686 Gameport");	gameport_set_phys(gp, "pci%s/gameport0", pci_name(chip->pci));	gameport_set_dev_parent(gp, &chip->pci->dev);	gp->io = JOYSTICK_ADDR;	gameport_set_port_data(gp, r);	/* Enable legacy joystick port */	*legacy |= VIA_FUNC_ENABLE_GAME;	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, *legacy);	gameport_register_port(chip->gameport);	return 0;}static void snd_via686_free_gameport(struct via82xx *chip){	if (chip->gameport) {		struct resource *r = gameport_get_port_data(chip->gameport);		gameport_unregister_port(chip->gameport);		chip->gameport = NULL;		release_and_free_resource(r);	}}#elsestatic inline int snd_via686_create_gameport(struct via82xx *chip, unsigned char *legacy){	return -ENOSYS;}static inline void snd_via686_free_gameport(struct via82xx *chip) { }#endif/* * */static int __devinit snd_via8233_init_misc(struct via82xx *chip){	int i, err, caps;	unsigned char val;	caps = chip->chip_type == TYPE_VIA8233A ? 1 : 2;	for (i = 0; i < caps; i++) {		snd_via8233_capture_source.index = i;		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_capture_source, chip));		if (err < 0)			return err;	}	if (ac97_can_spdif(chip->ac97)) {		err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs3_spdif_control, chip));		if (err < 0)			return err;	}	if (chip->chip_type != TYPE_VIA8233A) {		/* when no h/w PCM volume control is found, use DXS volume control		 * as the PCM vol control		 */		struct snd_ctl_elem_id sid;		memset(&sid, 0, sizeof(sid));		strcpy(sid.name, "PCM Playback Volume");		sid.iface = SNDRV_CTL_ELEM_IFACE_MIXER;		if (! snd_ctl_find_id(chip->card, &sid)) {			snd_printd(KERN_INFO "Using DXS as PCM Playback\n");			err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_pcmdxs_volume_control, chip));			if (err < 0)				return err;		}		else /* Using DXS when PCM emulation is enabled is really weird */		{			/* Standalone DXS controls */			err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip));			if (err < 0)				return err;		}	}	/* select spdif data slot 10/11 */	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);	val = (val & ~VIA8233_SPDIF_SLOT_MASK) | VIA8233_SPDIF_SLOT_1011;	val &= ~VIA8233_SPDIF_DX3; /* SPDIF off as default */	pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val);	return 0;}static int __devinit snd_via686_init_misc(struct via82xx *chip){	unsigned char legacy, legacy_cfg;	int rev_h = 0;	legacy = chip->old_legacy;	legacy_cfg = chip->old_legacy_cfg;	legacy |= VIA_FUNC_MIDI_IRQMASK;	/* FIXME: correct? (disable MIDI) */	legacy &= ~VIA_FUNC_ENABLE_GAME;	/* disable joystick */	if (chip->revision >= VIA_REV_686_H) {		rev_h = 1;		if (mpu_port >= 0x200) {	/* force MIDI */			mpu_port &= 0xfffc;			pci_write_config_dword(chip->pci, 0x18, mpu_port | 0x01);#ifdef CONFIG_PM			chip->mpu_port_saved = mpu_port;#endif		} else {			mpu_port = pci_resource_start(chip->pci, 2);		}	} else {		switch (mpu_port) {	/* force MIDI */		case 0x300:		case 0x310:		case 0x320:		case 0x330:			legacy_cfg &= ~(3 << 2);			legacy_cfg |= (mpu_port & 0x0030) >> 2;			break;		default:			/* no, use BIOS settings */			if (legacy & VIA_FUNC_ENABLE_MIDI)				mpu_port = 0x300 + ((legacy_cfg & 0x000c) << 2);			break;		}	}	if (mpu_port >= 0x200 &&	    (chip->mpu_res = request_region(mpu_port, 2, "VIA82xx MPU401"))	    != NULL) {		if (rev_h)			legacy |= VIA_FUNC_MIDI_PNP;	/* enable PCI I/O 2 */		legacy |= VIA_FUNC_ENABLE_MIDI;	} else {		if (rev_h)			legacy &= ~VIA_FUNC_MIDI_PNP;	/* disable PCI I/O 2 */		legacy &= ~VIA_FUNC_ENABLE_MIDI;		mpu_port = 0;	}	pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);	pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);	if (chip->mpu_res) {		if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A,					mpu_port, MPU401_INFO_INTEGRATED,					chip->irq, 0, &chip->rmidi) < 0) {			printk(KERN_WARNING "unable to initialize MPU-401"			       " at 0x%lx, skipping\n", mpu_port);			legacy &= ~VIA_FUNC_ENABLE_MIDI;		} else {			legacy &= ~VIA_FUNC_MIDI_IRQMASK;	/* enable MIDI interrupt */		}		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, legacy);	}	snd_via686_create_gameport(chip, &legacy);#ifdef CONFIG_PM	chip->legacy_saved = legacy;	chip->legacy_cfg_saved = legacy_cfg;#endif	return 0;}/* * proc interface */static void snd_via82xx_proc_read(struct snd_info_entry *entry,				  struct snd_info_buffer *buffer){	struct via82xx *chip = entry->private_data;	int i;		snd_iprintf(buffer, "%s\n\n", chip->card->longname);	for (i = 0; i < 0xa0; i += 4) {		snd_iprintf(buffer, "%02x: %08x\n", i, inl(chip->port + i));	}}static void __devinit snd_via82xx_proc_init(struct via82xx *chip){	struct snd_info_entry *entry;	if (! snd_card_proc_new(chip->card, "via82xx", &entry))		snd_info_set_text_ops(entry, chip, snd_via82xx_proc_read);}/* * */static int snd_via82xx_chip_init(struct via82xx *chip){	unsigned int val;	unsigned long end_time;	unsigned char pval;#if 0 /* broken on K7M? */	if (chip->chip_type == TYPE_VIA686)		/* disable all legacy ports */		pci_write_config_byte(chip->pci, VIA_FUNC_ENABLE, 0);#endif	pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);	if (! (pval & VIA_ACLINK_C00_READY)) { /* codec not ready? */		/* deassert ACLink reset, force SYNC */		pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,				      VIA_ACLINK_CTRL_ENABLE |				      VIA_ACLINK_CTRL_RESET |				      VIA_ACLINK_CTRL_SYNC);		udelay(100);#if 1 /* FIXME: should we do full reset here for all chip models? */		pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, 0x00);		udelay(100);#else		/* deassert ACLink reset, force SYNC (warm AC'97 reset) */		pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL,				      VIA_ACLINK_CTRL_RESET|VIA_ACLINK_CTRL_SYNC);		udelay(2);#endif		/* ACLink on, deassert ACLink reset, VSR, SGD data out */		/* note - FM data out has trouble with non VRA codecs !! */		pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);		udelay(100);	}		/* Make sure VRA is enabled, in case we didn't do a	 * complete codec reset, above */	pci_read_config_byte(chip->pci, VIA_ACLINK_CTRL, &pval);	if ((pval & VIA_ACLINK_CTRL_INIT) != VIA_ACLINK_CTRL_INIT) {		/* ACLink on, deassert ACLink reset, VSR, SGD data out */		/* note - FM data out has trouble with non VRA codecs !! */		pci_write_config_byte(chip->pci, VIA_ACLINK_CTRL, VIA_ACLINK_CTRL_INIT);		udelay(100);	}	/* wait until codec ready */	end_time = jiffies + msecs_to_jiffies(750);	do {		pci_read_config_byte(chip->pci, VIA_ACLINK_STAT, &pval);		if (pval & VIA_ACLINK_C00_READY) /* primary codec ready */			break;		schedule_timeout_uninterruptible(1);	} while (time_before(jiffies, end_time));	if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_BUSY)		snd_printk(KERN_ERR "AC'97 codec is not ready [0x%x]\n", val);#if 0 /* FIXME: we don't support the second codec yet so skip the detection now.. */	snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |				 VIA_REG_AC97_SECONDARY_VALID |				 (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));	end_time = jiffies + msecs_to_jiffies(750);	snd_via82xx_codec_xwrite(chip, VIA_REG_AC97_READ |				 VIA_REG_AC97_SECONDARY_VALID |				 (VIA_REG_AC97_CODEC_ID_SECONDARY << VIA_REG_AC97_CODEC_ID_SHIFT));	do {		if ((val = snd_via82xx_codec_xread(chip)) & VIA_REG_AC97_SECONDARY_VALID) {			chip->ac97_secondary = 1;			goto __ac97_ok2;		}		schedule_timeout_uninterruptible(1);	} while (time_before(jiffies, end_time));	/* This is ok, the most of motherboards have only one codec */      __ac97_ok2:#endif	if (chip->chip_type == TYPE_VIA686) {		/* route FM trap to IRQ, disable FM trap */		pci_write_config_byte(chip->pci, VIA_FM_NMI_CTRL, 0);		/* disable all GPI interrupts */		outl(0, VIAREG(chip, GPI_INTR));	}	if (chip->chip_type != TYPE_VIA686) {		/* Workaround for Award BIOS bug:		 * DXS channels don't work properly with VRA if MC97 is disabled.		 */		struct pci_dev *pci;		pci = pci_get_device(0x1106, 0x3068, NULL); /* MC97 */		if (pci) {			unsigned char data;			pci_read_config_byte(pci, 0x44, &data);			pci_write_config_byte(pci, 0x44, data | 0x40);			pci_dev_put(pci);		}	}	if (chip->chip_type != TYPE_VIA8233A) {		int i, idx;		for (idx = 0; idx < 4; idx++) {			unsigned long port = chip->port + 0x10 * idx;			for (i = 0; i < 2; i++) {				chip->playback_volume[idx][i]=chip->playback_volume_c[i];				outb(chip->playback_volume_c[i],				     port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);			}		}	}	return 0;}#ifdef CONFIG_PM/* * power management */static int snd_via82xx_suspend(struct pci_dev *pci, pm_message_t state){	struct snd_card *card = pci_get_drvdata(pci);	struct via82xx *chip = card->private_data;	int i;	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);	for (i = 0; i < 2; i++)		snd_pcm_suspend_all(chip->pcms[i]);	for (i = 0; i < chip->num_devs; i++)		snd_via82xx_channel_reset(chip, &chip->devs[i]);	synchronize_irq(chip->irq);	snd_ac97_suspend(chip->ac97);	/* save misc values */	if (chip->chip_type != TYPE_VIA686) {		pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &chip->spdif_ctrl_saved);		chip->capture_src_saved[0] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL);		chip->capture_src_saved[1] = inb(chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);	}	pci_disable_device(pci);	pci_save_state(pci);	pci_set_power_state(pci, pci_choose_state(pci, state));	return 0;}static int snd_via82xx_resume(struct pci_dev *p

⌨️ 快捷键说明

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