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

📄 via82xx.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_via82xx_hw_params,	.hw_free =	snd_via82xx_hw_free,	.prepare =	snd_via686_capture_prepare,	.trigger =	snd_via82xx_pcm_trigger,	.pointer =	snd_via686_pcm_pointer,	.page =		snd_pcm_sgbuf_ops_page,};/* via823x DSX playback callbacks */static struct snd_pcm_ops snd_via8233_playback_ops = {	.open =		snd_via82xx_playback_open,	.close =	snd_via82xx_pcm_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_via82xx_hw_params,	.hw_free =	snd_via82xx_hw_free,	.prepare =	snd_via8233_playback_prepare,	.trigger =	snd_via82xx_pcm_trigger,	.pointer =	snd_via8233_pcm_pointer,	.page =		snd_pcm_sgbuf_ops_page,};/* via823x multi-channel playback callbacks */static struct snd_pcm_ops snd_via8233_multi_ops = {	.open =		snd_via8233_multi_open,	.close =	snd_via82xx_pcm_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_via82xx_hw_params,	.hw_free =	snd_via82xx_hw_free,	.prepare =	snd_via8233_multi_prepare,	.trigger =	snd_via82xx_pcm_trigger,	.pointer =	snd_via8233_pcm_pointer,	.page =		snd_pcm_sgbuf_ops_page,};/* via823x capture callbacks */static struct snd_pcm_ops snd_via8233_capture_ops = {	.open =		snd_via82xx_capture_open,	.close =	snd_via82xx_pcm_close,	.ioctl =	snd_pcm_lib_ioctl,	.hw_params =	snd_via82xx_hw_params,	.hw_free =	snd_via82xx_hw_free,	.prepare =	snd_via8233_capture_prepare,	.trigger =	snd_via82xx_pcm_trigger,	.pointer =	snd_via8233_pcm_pointer,	.page =		snd_pcm_sgbuf_ops_page,};static void init_viadev(struct via82xx *chip, int idx, unsigned int reg_offset,			int shadow_pos, int direction){	chip->devs[idx].reg_offset = reg_offset;	chip->devs[idx].shadow_shift = shadow_pos * 4;	chip->devs[idx].direction = direction;	chip->devs[idx].port = chip->port + reg_offset;}/* * create pcm instances for VIA8233, 8233C and 8235 (not 8233A) */static int __devinit snd_via8233_pcm_new(struct via82xx *chip){	struct snd_pcm *pcm;	int i, err;	chip->playback_devno = 0;	/* x 4 */	chip->multi_devno = 4;		/* x 1 */	chip->capture_devno = 5;	/* x 2 */	chip->num_devs = 7;	chip->intr_mask = 0x33033333; /* FLAG|EOL for rec0-1, mc, sdx0-3 */	/* PCM #0:  4 DSX playbacks and 1 capture */	err = snd_pcm_new(chip->card, chip->card->shortname, 0, 4, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);	pcm->private_data = chip;	strcpy(pcm->name, chip->card->shortname);	chip->pcms[0] = pcm;	/* set up playbacks */	for (i = 0; i < 4; i++)		init_viadev(chip, i, 0x10 * i, i, 0);	/* capture */	init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);	if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,							 snd_dma_pci_data(chip->pci),							 64*1024, 128*1024)) < 0)		return err;	/* PCM #1:  multi-channel playback and 2nd capture */	err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);	pcm->private_data = chip;	strcpy(pcm->name, chip->card->shortname);	chip->pcms[1] = pcm;	/* set up playback */	init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0);	/* set up capture */	init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1);	if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,						         snd_dma_pci_data(chip->pci),							 64*1024, 128*1024)) < 0)		return err;	return 0;}/* * create pcm instances for VIA8233A */static int __devinit snd_via8233a_pcm_new(struct via82xx *chip){	struct snd_pcm *pcm;	int err;	chip->multi_devno = 0;	chip->playback_devno = 1;	chip->capture_devno = 2;	chip->num_devs = 3;	chip->intr_mask = 0x03033000; /* FLAG|EOL for rec0, mc, sdx3 */	/* PCM #0:  multi-channel playback and capture */	err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_multi_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via8233_capture_ops);	pcm->private_data = chip;	strcpy(pcm->name, chip->card->shortname);	chip->pcms[0] = pcm;	/* set up playback */	init_viadev(chip, chip->multi_devno, VIA_REG_MULTPLAY_STATUS, 4, 0);	/* capture */	init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);	if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,							 snd_dma_pci_data(chip->pci),							 64*1024, 128*1024)) < 0)		return err;	/* SPDIF supported? */	if (! ac97_can_spdif(chip->ac97))		return 0;	/* PCM #1:  DXS3 playback (for spdif) */	err = snd_pcm_new(chip->card, chip->card->shortname, 1, 1, 0, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via8233_playback_ops);	pcm->private_data = chip;	strcpy(pcm->name, chip->card->shortname);	chip->pcms[1] = pcm;	/* set up playback */	init_viadev(chip, chip->playback_devno, 0x30, 3, 0);	if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,							 snd_dma_pci_data(chip->pci),							 64*1024, 128*1024)) < 0)		return err;	return 0;}/* * create a pcm instance for via686a/b */static int __devinit snd_via686_pcm_new(struct via82xx *chip){	struct snd_pcm *pcm;	int err;	chip->playback_devno = 0;	chip->capture_devno = 1;	chip->num_devs = 2;	chip->intr_mask = 0x77; /* FLAG | EOL for PB, CP, FM */	err = snd_pcm_new(chip->card, chip->card->shortname, 0, 1, 1, &pcm);	if (err < 0)		return err;	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_via686_playback_ops);	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_via686_capture_ops);	pcm->private_data = chip;	strcpy(pcm->name, chip->card->shortname);	chip->pcms[0] = pcm;	init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0);	init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1);	if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,							 snd_dma_pci_data(chip->pci),							 64*1024, 128*1024)) < 0)		return err;	return 0;}/* *  Mixer part */static int snd_via8233_capture_source_info(struct snd_kcontrol *kcontrol,					   struct snd_ctl_elem_info *uinfo){	/* formerly they were "Line" and "Mic", but it looks like that they	 * have nothing to do with the actual physical connections...	 */	static char *texts[2] = {		"Input1", "Input2"	};	uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;	uinfo->count = 1;	uinfo->value.enumerated.items = 2;	if (uinfo->value.enumerated.item >= 2)		uinfo->value.enumerated.item = 1;	strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);	return 0;}static int snd_via8233_capture_source_get(struct snd_kcontrol *kcontrol,					  struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);	ucontrol->value.enumerated.item[0] = inb(port) & VIA_REG_CAPTURE_CHANNEL_MIC ? 1 : 0;	return 0;}static int snd_via8233_capture_source_put(struct snd_kcontrol *kcontrol,					  struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	unsigned long port = chip->port + (kcontrol->id.index ? (VIA_REG_CAPTURE_CHANNEL + 0x10) : VIA_REG_CAPTURE_CHANNEL);	u8 val, oval;	spin_lock_irq(&chip->reg_lock);	oval = inb(port);	val = oval & ~VIA_REG_CAPTURE_CHANNEL_MIC;	if (ucontrol->value.enumerated.item[0])		val |= VIA_REG_CAPTURE_CHANNEL_MIC;	if (val != oval)		outb(val, port);	spin_unlock_irq(&chip->reg_lock);	return val != oval;}static struct snd_kcontrol_new snd_via8233_capture_source __devinitdata = {	.name = "Input Source Select",	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.info = snd_via8233_capture_source_info,	.get = snd_via8233_capture_source_get,	.put = snd_via8233_capture_source_put,};#define snd_via8233_dxs3_spdif_info	snd_ctl_boolean_mono_infostatic int snd_via8233_dxs3_spdif_get(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	u8 val;	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &val);	ucontrol->value.integer.value[0] = (val & VIA8233_SPDIF_DX3) ? 1 : 0;	return 0;}static int snd_via8233_dxs3_spdif_put(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	u8 val, oval;	pci_read_config_byte(chip->pci, VIA8233_SPDIF_CTRL, &oval);	val = oval & ~VIA8233_SPDIF_DX3;	if (ucontrol->value.integer.value[0])		val |= VIA8233_SPDIF_DX3;	/* save the spdif flag for rate filtering */	chip->spdif_on = ucontrol->value.integer.value[0] ? 1 : 0;	if (val != oval) {		pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, val);		return 1;	}	return 0;}static struct snd_kcontrol_new snd_via8233_dxs3_spdif_control __devinitdata = {	.name = SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH),	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.info = snd_via8233_dxs3_spdif_info,	.get = snd_via8233_dxs3_spdif_get,	.put = snd_via8233_dxs3_spdif_put,};static int snd_via8233_dxs_volume_info(struct snd_kcontrol *kcontrol,				       struct snd_ctl_elem_info *uinfo){	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;	uinfo->count = 2;	uinfo->value.integer.min = 0;	uinfo->value.integer.max = VIA_DXS_MAX_VOLUME;	return 0;}static int snd_via8233_dxs_volume_get(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);	ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][0];	ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];	return 0;}static int snd_via8233_pcmdxs_volume_get(struct snd_kcontrol *kcontrol,					 struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	ucontrol->value.integer.value[0] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[0];	ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume_c[1];	return 0;}static int snd_via8233_dxs_volume_put(struct snd_kcontrol *kcontrol,				      struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id);	unsigned long port = chip->port + 0x10 * idx;	unsigned char val;	int i, change = 0;	for (i = 0; i < 2; i++) {		val = ucontrol->value.integer.value[i];		if (val > VIA_DXS_MAX_VOLUME)			val = VIA_DXS_MAX_VOLUME;		val = VIA_DXS_MAX_VOLUME - val;		change |= val != chip->playback_volume[idx][i];		if (change) {			chip->playback_volume[idx][i] = val;			outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);		}	}	return change;}static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,					 struct snd_ctl_elem_value *ucontrol){	struct via82xx *chip = snd_kcontrol_chip(kcontrol);	unsigned int idx;	unsigned char val;	int i, change = 0;	for (i = 0; i < 2; i++) {		val = ucontrol->value.integer.value[i];		if (val > VIA_DXS_MAX_VOLUME)			val = VIA_DXS_MAX_VOLUME;		val = VIA_DXS_MAX_VOLUME - val;		if (val != chip->playback_volume_c[i]) {			change = 1;			chip->playback_volume_c[i] = val;			for (idx = 0; idx < 4; idx++) {				unsigned long port = chip->port + 0x10 * idx;				chip->playback_volume[idx][i] = val;				outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);			}		}	}	return change;}static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1);static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {	.name = "PCM Playback Volume",	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),	.info = snd_via8233_dxs_volume_info,	.get = snd_via8233_pcmdxs_volume_get,	.put = snd_via8233_pcmdxs_volume_put,	.tlv = { .p = db_scale_dxs }};static struct snd_kcontrol_new snd_via8233_dxs_volume_control __devinitdata = {	.name = "VIA DXS Playback Volume",	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,	.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |		   SNDRV_CTL_ELEM_ACCESS_TLV_READ),	.count = 4,	.info = snd_via8233_dxs_volume_info,	.get = snd_via8233_dxs_volume_get,	.put = snd_via8233_dxs_volume_put,	.tlv = { .p = db_scale_dxs }};/* */static void snd_via82xx_mixer_free_ac97_bus(struct snd_ac97_bus *bus){	struct via82xx *chip = bus->private_data;	chip->ac97_bus = NULL;}static void snd_via82xx_mixer_free_ac97(struct snd_ac97 *ac97){	struct via82xx *chip = ac97->private_data;	chip->ac97 = NULL;}static struct ac97_quirk ac97_quirks[] = {	{		.subvendor = 0x1106,		.subdevice = 0x4161,		.codec_id = 0x56494161, /* VT1612A */		.name = "Soltek SL-75DRV5",		.type = AC97_TUNE_NONE	},	{	/* FIXME: which codec? */		.subvendor = 0x1106,		.subdevice = 0x4161,		.name = "ASRock K7VT2",		.type = AC97_TUNE_HP_ONLY	},	{		.subvendor = 0x1019,		.subdevice = 0x0a81,		.name = "ECS K7VTA3",		.type = AC97_TUNE_HP_ONLY

⌨️ 快捷键说明

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