提交 177a7cdb 编写于 作者: C Clemens Ladisch 提交者: Jaroslav Kysela

[ALSA] ymfpci: fix volume handling of the 44.1 kHz slot

The existing code for handling the 44.1 slot's volume has two problems:
the volume is not affected by the 'Wave Playback Volume' mixer control,
and the BUF441OUTVOL register, which is used to control the per-
substream volume for this slot, uses a different scale than the gain
fields of the other slots.
This patch makes the BUF441OUTVOL register a shadow of the
NATIVEDACOUTVOL register so that the Wave volume is consistent for all
substreams.
As a consequence of this, the per-substream PCM volume control gets no
longer activated for the substream using this slot.  The code for
(de)activating the mixer control is moved from the open/close to the
prepare/trigger_stop callbacks so that it is able to determine the
substream's slot.
Signed-off-by: NClemens Ladisch <clemens@ladisch.de>
Signed-off-by: NJaroslav Kysela <perex@suse.cz>
上级 eafe5708
...@@ -171,17 +171,6 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate) ...@@ -171,17 +171,6 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate)
return val[0]; return val[0];
} }
static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm)
{
unsigned int value;
struct snd_ymfpci_pcm_mixer *mixer;
mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number];
value = min_t(unsigned int, mixer->left, 0x7fff) >> 1;
value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16;
snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value);
}
/* /*
* Hardware start management * Hardware start management
*/ */
...@@ -389,6 +378,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ...@@ -389,6 +378,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
{ {
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
struct snd_kcontrol *kctl = NULL;
int result = 0; int result = 0;
spin_lock(&chip->reg_lock); spin_lock(&chip->reg_lock);
...@@ -406,6 +396,11 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ...@@ -406,6 +396,11 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
ypcm->running = 1; ypcm->running = 1;
break; break;
case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_STOP:
if (substream->pcm == chip->pcm && !ypcm->use_441_slot) {
kctl = chip->pcm_mixer[substream->number].ctl;
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
}
/* fall through */
case SNDRV_PCM_TRIGGER_PAUSE_PUSH: case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
case SNDRV_PCM_TRIGGER_SUSPEND: case SNDRV_PCM_TRIGGER_SUSPEND:
chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
...@@ -419,6 +414,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream, ...@@ -419,6 +414,8 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
} }
__unlock: __unlock:
spin_unlock(&chip->reg_lock); spin_unlock(&chip->reg_lock);
if (kctl)
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return result; return result;
} }
static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream, static int snd_ymfpci_capture_trigger(struct snd_pcm_substream *substream,
...@@ -526,7 +523,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int ...@@ -526,7 +523,6 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
ypcm->chip->src441_used = voice->number; ypcm->chip->src441_used = voice->number;
ypcm->use_441_slot = 1; ypcm->use_441_slot = 1;
format |= 0x10000000; format |= 0x10000000;
snd_ymfpci_pcm_441_volume_set(ypcm);
} }
if (ypcm->chip->src441_used == voice->number && if (ypcm->chip->src441_used == voice->number &&
(format & 0x10000000) == 0) { (format & 0x10000000) == 0) {
...@@ -667,6 +663,7 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) ...@@ -667,6 +663,7 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm = runtime->private_data; struct snd_ymfpci_pcm *ypcm = runtime->private_data;
struct snd_kcontrol *kctl;
unsigned int nvoice; unsigned int nvoice;
ypcm->period_size = runtime->period_size; ypcm->period_size = runtime->period_size;
...@@ -676,6 +673,12 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream) ...@@ -676,6 +673,12 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
for (nvoice = 0; nvoice < runtime->channels; nvoice++) for (nvoice = 0; nvoice < runtime->channels; nvoice++)
snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime, snd_ymfpci_pcm_init_voice(ypcm, nvoice, runtime,
substream->pcm == chip->pcm); substream->pcm == chip->pcm);
if (substream->pcm == chip->pcm && !ypcm->use_441_slot) {
kctl = chip->pcm_mixer[substream->number].ctl;
kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
}
return 0; return 0;
} }
...@@ -926,7 +929,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) ...@@ -926,7 +929,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm; struct snd_ymfpci_pcm *ypcm;
struct snd_kcontrol *kctl;
int err; int err;
if ((err = snd_ymfpci_playback_open_1(substream)) < 0) if ((err = snd_ymfpci_playback_open_1(substream)) < 0)
...@@ -941,10 +943,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream) ...@@ -941,10 +943,6 @@ static int snd_ymfpci_playback_open(struct snd_pcm_substream *substream)
chip->rear_opened++; chip->rear_opened++;
} }
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
kctl = chip->pcm_mixer[substream->number].ctl;
kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return 0; return 0;
} }
...@@ -1039,7 +1037,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) ...@@ -1039,7 +1037,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream)
{ {
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream); struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
struct snd_kcontrol *kctl;
spin_lock_irq(&chip->reg_lock); spin_lock_irq(&chip->reg_lock);
if (ypcm->output_rear && chip->rear_opened > 0) { if (ypcm->output_rear && chip->rear_opened > 0) {
...@@ -1047,9 +1044,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream) ...@@ -1047,9 +1044,6 @@ static int snd_ymfpci_playback_close(struct snd_pcm_substream *substream)
ymfpci_close_extension(chip); ymfpci_close_extension(chip);
} }
spin_unlock_irq(&chip->reg_lock); spin_unlock_irq(&chip->reg_lock);
kctl = chip->pcm_mixer[substream->number].ctl;
kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_INFO, &kctl->id);
return snd_ymfpci_playback_close_1(substream); return snd_ymfpci_playback_close_1(substream);
} }
...@@ -1552,6 +1546,26 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e ...@@ -1552,6 +1546,26 @@ static int snd_ymfpci_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return change; return change;
} }
static int snd_ymfpci_put_nativedacvol(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_ymfpci *chip = snd_kcontrol_chip(kcontrol);
unsigned int reg = YDSXGR_NATIVEDACOUTVOL;
unsigned int reg2 = YDSXGR_BUF441OUTVOL;
int change;
unsigned int value, oval;
value = ucontrol->value.integer.value[0] & 0x3fff;
value |= (ucontrol->value.integer.value[1] & 0x3fff) << 16;
spin_lock_irq(&chip->reg_lock);
oval = snd_ymfpci_readl(chip, reg);
change = value != oval;
snd_ymfpci_writel(chip, reg, value);
snd_ymfpci_writel(chip, reg2, value);
spin_unlock_irq(&chip->reg_lock);
return change;
}
/* /*
* 4ch duplication * 4ch duplication
*/ */
...@@ -1576,7 +1590,17 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e ...@@ -1576,7 +1590,17 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = { static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
YMFPCI_DOUBLE("Wave Playback Volume", 0, YDSXGR_NATIVEDACOUTVOL), {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Wave Playback Volume",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ,
.info = snd_ymfpci_info_double,
.get = snd_ymfpci_get_double,
.put = snd_ymfpci_put_nativedacvol,
.private_value = YDSXGR_NATIVEDACOUTVOL,
.tlv = { .p = db_scale_native },
},
YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL), YMFPCI_DOUBLE("Wave Capture Volume", 0, YDSXGR_NATIVEDACLOOPVOL),
YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL), YMFPCI_DOUBLE("Digital Capture Volume", 0, YDSXGR_NATIVEDACINVOL),
YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL), YMFPCI_DOUBLE("Digital Capture Volume", 1, YDSXGR_NATIVEADCINVOL),
...@@ -1719,8 +1743,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol, ...@@ -1719,8 +1743,6 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
if (!ypcm->use_441_slot) if (!ypcm->use_441_slot)
ypcm->update_pcm_vol = 2; ypcm->update_pcm_vol = 2;
else
snd_ymfpci_pcm_441_volume_set(ypcm);
} }
spin_unlock_irqrestore(&chip->voice_lock, flags); spin_unlock_irqrestore(&chip->voice_lock, flags);
return 1; return 1;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册