Commit e4a745cc authored by Jaroslav Kysela's avatar Jaroslav Kysela

[ALSA] Use DXS volumes as PCM

VIA82xx driver
Use DXS volumes as PCM control in cases with no volume control on codec
(e.g. C-Media).  'DXS Playback Volume' controls are removed.
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent a45e0114
...@@ -367,7 +367,7 @@ struct _snd_via82xx { ...@@ -367,7 +367,7 @@ struct _snd_via82xx {
unsigned int mpu_port_saved; unsigned int mpu_port_saved;
#endif #endif
unsigned char playback_volume[4][2]; /* for VIA8233/C/8235; default = 0 */ unsigned char playback_volume[2]; /* for VIA8233/C/8235; default = 0 */
unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */ unsigned int intr_mask; /* SGD_SHADOW mask to check interrupts */
...@@ -942,8 +942,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream) ...@@ -942,8 +942,8 @@ static int snd_via8233_playback_prepare(snd_pcm_substream_t *substream)
snd_assert((rbits & ~0xfffff) == 0, return -EINVAL); snd_assert((rbits & ~0xfffff) == 0, return -EINVAL);
snd_via82xx_channel_reset(chip, viadev); snd_via82xx_channel_reset(chip, viadev);
snd_via82xx_set_table_ptr(chip, viadev); snd_via82xx_set_table_ptr(chip, viadev);
outb(chip->playback_volume[viadev->reg_offset / 0x10][0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L)); outb(chip->playback_volume[0], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_L));
outb(chip->playback_volume[viadev->reg_offset / 0x10][1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R)); outb(chip->playback_volume[1], VIADEV_REG(viadev, OFS_PLAYBACK_VOLUME_R));
outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */ outl((runtime->format == SNDRV_PCM_FORMAT_S16_LE ? VIA8233_REG_TYPE_16BIT : 0) | /* format */
(runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */ (runtime->channels > 1 ? VIA8233_REG_TYPE_STEREO : 0) | /* stereo */
rbits | /* rate */ rbits | /* rate */
...@@ -1497,17 +1497,15 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in ...@@ -1497,17 +1497,15 @@ static int snd_via8233_dxs_volume_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_in
static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) static int snd_via8233_dxs_volume_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{ {
via82xx_t *chip = snd_kcontrol_chip(kcontrol); via82xx_t *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[0];
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[1];
ucontrol->value.integer.value[1] = VIA_DXS_MAX_VOLUME - chip->playback_volume[idx][1];
return 0; return 0;
} }
static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
{ {
via82xx_t *chip = snd_kcontrol_chip(kcontrol); via82xx_t *chip = snd_kcontrol_chip(kcontrol);
unsigned int idx = snd_ctl_get_ioff(kcontrol, &ucontrol->id); unsigned int idx;
unsigned long port = chip->port + 0x10 * idx;
unsigned char val; unsigned char val;
int i, change = 0; int i, change = 0;
...@@ -1516,19 +1514,21 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val ...@@ -1516,19 +1514,21 @@ static int snd_via8233_dxs_volume_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_val
if (val > VIA_DXS_MAX_VOLUME) if (val > VIA_DXS_MAX_VOLUME)
val = VIA_DXS_MAX_VOLUME; val = VIA_DXS_MAX_VOLUME;
val = VIA_DXS_MAX_VOLUME - val; val = VIA_DXS_MAX_VOLUME - val;
change |= val != chip->playback_volume[idx][i]; if (val != chip->playback_volume[i]) {
if (change) { change = 1;
chip->playback_volume[idx][i] = val; chip->playback_volume[i] = val;
outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i); for (idx = 0; idx < 4; idx++) {
unsigned long port = chip->port + 0x10 * idx;
outb(val, port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
}
} }
} }
return change; return change;
} }
static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = { static snd_kcontrol_new_t snd_via8233_dxs_volume_control __devinitdata = {
.name = "VIA DXS Playback Volume", .name = "PCM Playback Volume",
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.count = 4,
.info = snd_via8233_dxs_volume_info, .info = snd_via8233_dxs_volume_info,
.get = snd_via8233_dxs_volume_get, .get = snd_via8233_dxs_volume_get,
.put = snd_via8233_dxs_volume_put, .put = snd_via8233_dxs_volume_put,
...@@ -1657,9 +1657,18 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev) ...@@ -1657,9 +1657,18 @@ static int snd_via8233_init_misc(via82xx_t *chip, int dev)
return err; return err;
} }
if (chip->chip_type != TYPE_VIA8233A) { if (chip->chip_type != TYPE_VIA8233A) {
err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_via8233_dxs_volume_control, chip)); /* when no h/w PCM volume control is found, use DXS volume control
if (err < 0) * as the PCM vol control
return err; */
snd_ctl_elem_id_t 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)) {
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 */ /* select spdif data slot 10/11 */
...@@ -1888,6 +1897,15 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip) ...@@ -1888,6 +1897,15 @@ static int __devinit snd_via82xx_chip_init(via82xx_t *chip)
} }
} }
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++)
outb(chip->playback_volume[i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
}
}
return 0; return 0;
} }
...@@ -1923,7 +1941,7 @@ static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state) ...@@ -1923,7 +1941,7 @@ static int snd_via82xx_suspend(snd_card_t *card, pm_message_t state)
static int snd_via82xx_resume(snd_card_t *card) static int snd_via82xx_resume(snd_card_t *card)
{ {
via82xx_t *chip = card->pm_private_data; via82xx_t *chip = card->pm_private_data;
int idx, i; int i;
pci_enable_device(chip->pci); pci_enable_device(chip->pci);
pci_set_power_state(chip->pci, 0); pci_set_power_state(chip->pci, 0);
...@@ -1939,11 +1957,6 @@ static int snd_via82xx_resume(snd_card_t *card) ...@@ -1939,11 +1957,6 @@ static int snd_via82xx_resume(snd_card_t *card)
pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved); pci_write_config_byte(chip->pci, VIA8233_SPDIF_CTRL, chip->spdif_ctrl_saved);
outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL); outb(chip->capture_src_saved[0], chip->port + VIA_REG_CAPTURE_CHANNEL);
outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10); outb(chip->capture_src_saved[1], chip->port + VIA_REG_CAPTURE_CHANNEL + 0x10);
for (idx = 0; idx < 4; idx++) {
unsigned long port = chip->port + 0x10 * idx;
for (i = 0; i < 2; i++)
outb(chip->playback_volume[idx][i], port + VIA_REG_OFS_PLAYBACK_VOLUME_L + i);
}
} }
snd_ac97_resume(chip->ac97); snd_ac97_resume(chip->ac97);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment