📄 via82xx.c
字号:
.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 + -