Commit 8b4a309a authored by Jaroslav Kysela's avatar Jaroslav Kysela

ALSA CVS update

D:2003/08/27 17:17:31
C:AC97 Codec Core
A:Takashi Iwai <tiwai@suse.de>
F:include/ac97_codec.h:1.31->1.32 
F:pci/ac97/ac97_codec.c:1.101->1.102 
F:pci/ac97/ac97_local.h:1.1->1.2 
F:pci/ac97/ac97_patch.c:1.19->1.20 
L:- added the support for stereo mute switches on AD198x.
L:- clean up of creation routines of normal stereo controls.
parent 0ceb4137
...@@ -248,6 +248,7 @@ ...@@ -248,6 +248,7 @@
#define AC97_AD_MULTI (1<<1) /* Analog Devices - multi codecs */ #define AC97_AD_MULTI (1<<1) /* Analog Devices - multi codecs */
#define AC97_CS_SPDIF (1<<2) /* Cirrus Logic uses funky SPDIF */ #define AC97_CS_SPDIF (1<<2) /* Cirrus Logic uses funky SPDIF */
#define AC97_CX_SPDIF (1<<3) /* Conexant's spdif interface */ #define AC97_CX_SPDIF (1<<3) /* Conexant's spdif interface */
#define AC97_STEREO_MUTES (1<<4) /* has stereo mute bits */
/* rates indexes */ /* rates indexes */
#define AC97_RATES_FRONT_DAC 0 #define AC97_RATES_FRONT_DAC 0
......
...@@ -545,7 +545,7 @@ int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr ...@@ -545,7 +545,7 @@ int snd_ac97_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontr
#define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ #define AC97_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_double, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .info = snd_ac97_info_double, \
.get = snd_ac97_get_double, .put = snd_ac97_put_double, \ .get = snd_ac97_get_double, .put = snd_ac97_put_double, \
.private_value = reg | (shift_left << 8) | (shift_right << 12) | (mask << 16) | (invert << 24) } .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) static int snd_ac97_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{ {
...@@ -599,16 +599,6 @@ static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ...@@ -599,16 +599,6 @@ static int snd_ac97_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *
(val1 << shift_left) | (val2 << shift_right)); (val1 << shift_left) | (val2 << shift_right));
} }
static const snd_kcontrol_new_t snd_ac97_controls_master[2] = {
AC97_SINGLE("Master Playback Switch", AC97_MASTER, 15, 1, 1),
AC97_DOUBLE("Master Playback Volume", AC97_MASTER, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_headphone[2] = {
AC97_SINGLE("Headphone Playback Switch", AC97_HEADPHONE, 15, 1, 1),
AC97_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = { static const snd_kcontrol_new_t snd_ac97_controls_master_mono[2] = {
AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1), AC97_SINGLE("Master Mono Playback Switch", AC97_MASTER_MONO, 15, 1, 1),
AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1) AC97_SINGLE("Master Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 1)
...@@ -635,43 +625,17 @@ AC97_SINGLE("Mic Playback Volume", AC97_MIC, 0, 15, 1), ...@@ -635,43 +625,17 @@ AC97_SINGLE("Mic Playback Volume", AC97_MIC, 0, 15, 1),
AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0) AC97_SINGLE("Mic Boost (+20dB)", AC97_MIC, 6, 1, 0)
}; };
static const snd_kcontrol_new_t snd_ac97_controls_line[2] = { static const snd_kcontrol_new_t snd_ac97_control_capture_src = {
AC97_SINGLE("Line Playback Switch", AC97_LINE, 15, 1, 1),
AC97_DOUBLE("Line Playback Volume", AC97_LINE, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_cd[2] = {
AC97_SINGLE("CD Playback Switch", AC97_CD, 15, 1, 1),
AC97_DOUBLE("CD Playback Volume", AC97_CD, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_video[2] = {
AC97_SINGLE("Video Playback Switch", AC97_VIDEO, 15, 1, 1),
AC97_DOUBLE("Video Playback Volume", AC97_VIDEO, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_aux[2] = {
AC97_SINGLE("Aux Playback Switch", AC97_AUX, 15, 1, 1),
AC97_DOUBLE("Aux Playback Volume", AC97_AUX, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_pcm[2] = {
AC97_SINGLE("PCM Playback Switch", AC97_PCM, 15, 1, 1),
AC97_DOUBLE("PCM Playback Volume", AC97_PCM, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_controls_capture[3] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source", .name = "Capture Source",
.info = snd_ac97_info_mux, .info = snd_ac97_info_mux,
.get = snd_ac97_get_mux, .get = snd_ac97_get_mux,
.put = snd_ac97_put_mux, .put = snd_ac97_put_mux,
},
AC97_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1),
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0)
}; };
static const snd_kcontrol_new_t snd_ac97_control_capture_vol =
AC97_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 15, 0);
static const snd_kcontrol_new_t snd_ac97_controls_mic_capture[2] = { static const snd_kcontrol_new_t snd_ac97_controls_mic_capture[2] = {
AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1), AC97_SINGLE("Mic Capture Switch", AC97_REC_GAIN_MIC, 15, 1, 1),
AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0) AC97_SINGLE("Mic Capture Volume", AC97_REC_GAIN_MIC, 0, 15, 0)
...@@ -717,11 +681,6 @@ AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1), ...@@ -717,11 +681,6 @@ AC97_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1), AC97_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
}; };
static const snd_kcontrol_new_t snd_ac97_sigmatel_surround[2] = {
AC97_SINGLE("Sigmatel Surround Playback Switch", AC97_HEADPHONE, 15, 1, 1),
AC97_DOUBLE("Sigmatel Surround Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1)
};
static const snd_kcontrol_new_t snd_ac97_control_eapd = static const snd_kcontrol_new_t snd_ac97_control_eapd =
AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0); AC97_SINGLE("External Amplifier Power Down", AC97_POWERDOWN, 15, 1, 0);
...@@ -899,17 +858,23 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = { ...@@ -899,17 +858,23 @@ const snd_kcontrol_new_t snd_ac97_controls_spdif[5] = {
}, },
}; };
#define AD18XX_PCM_BITS(xname, codec, shift, mask) \ #define AD18XX_PCM_BITS(xname, codec, lshift, rshift, mask) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_ad18xx_pcm_info_bits, \
.get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \ .get = snd_ac97_ad18xx_pcm_get_bits, .put = snd_ac97_ad18xx_pcm_put_bits, \
.private_value = codec | (shift << 8) | (mask << 16) } .private_value = (codec) | ((lshift) << 8) | ((rshift) << 12) | ((mask) << 24) }
static int snd_ac97_ad18xx_pcm_info_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo) static int snd_ac97_ad18xx_pcm_info_bits(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
{ {
int mask = (kcontrol->private_value >> 16) & 0xff; ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int mask = (kcontrol->private_value >> 16) & 0x0f;
int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 1; if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
uinfo->count = 2;
else
uinfo->count = 1;
uinfo->value.integer.min = 0; uinfo->value.integer.min = 0;
uinfo->value.integer.max = mask; uinfo->value.integer.max = mask;
return 0; return 0;
...@@ -919,10 +884,13 @@ static int snd_ac97_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_ ...@@ -919,10 +884,13 @@ static int snd_ac97_ad18xx_pcm_get_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
{ {
ac97_t *ac97 = snd_kcontrol_chip(kcontrol); ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3; int codec = kcontrol->private_value & 3;
int shift = (kcontrol->private_value >> 8) & 0xff; int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff;
ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> shift) & mask); ucontrol->value.integer.value[0] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> lshift) & mask);
if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES))
ucontrol->value.integer.value[1] = mask - ((ac97->spec.ad18xx.pcmreg[codec] >> rshift) & mask);
return 0; return 0;
} }
...@@ -930,12 +898,18 @@ static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_ ...@@ -930,12 +898,18 @@ static int snd_ac97_ad18xx_pcm_put_bits(snd_kcontrol_t * kcontrol, snd_ctl_elem_
{ {
ac97_t *ac97 = snd_kcontrol_chip(kcontrol); ac97_t *ac97 = snd_kcontrol_chip(kcontrol);
int codec = kcontrol->private_value & 3; int codec = kcontrol->private_value & 3;
int shift = (kcontrol->private_value >> 8) & 0xff; int lshift = (kcontrol->private_value >> 8) & 0x0f;
int rshift = (kcontrol->private_value >> 12) & 0x0f;
int mask = (kcontrol->private_value >> 16) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff;
unsigned short val; unsigned short val, valmask;
val = mask - (ucontrol->value.integer.value[0] & mask); val = (mask - (ucontrol->value.integer.value[0] & mask)) << lshift;
return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, mask << shift, val << shift); valmask = mask << lshift;
if (lshift != rshift && (ac97->flags & AC97_STEREO_MUTES)) {
val |= (mask - (ucontrol->value.integer.value[1] & mask)) << rshift;
valmask |= mask << rshift;
}
return snd_ac97_ad18xx_update_pcm_bits(ac97, codec, valmask, val);
} }
#define AD18XX_PCM_VOLUME(xname, codec) \ #define AD18XX_PCM_VOLUME(xname, codec) \
...@@ -976,22 +950,23 @@ static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele ...@@ -976,22 +950,23 @@ static int snd_ac97_ad18xx_pcm_put_volume(snd_kcontrol_t * kcontrol, snd_ctl_ele
} }
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_pcm[2] = { static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_pcm[2] = {
AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 1), AD18XX_PCM_BITS("PCM Playback Switch", 0, 15, 7, 1),
AD18XX_PCM_VOLUME("PCM Playback Volume", 0) AD18XX_PCM_VOLUME("PCM Playback Volume", 0)
}; };
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_surround[2] = { static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_surround[2] = {
AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 1), AD18XX_PCM_BITS("Surround Playback Switch", 1, 15, 7, 1),
AD18XX_PCM_VOLUME("Surround Playback Volume", 1) AD18XX_PCM_VOLUME("Surround Playback Volume", 1)
}; };
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_center[2] = { static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_center[2] = {
AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 1), AD18XX_PCM_BITS("Center Playback Switch", 2, 15, 15, 1),
AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 31) AD18XX_PCM_BITS("Center Playback Volume", 2, 8, 8, 31)
}; };
static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[1] = { static const snd_kcontrol_new_t snd_ac97_controls_ad18xx_lfe[2] = {
AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 31) AD18XX_PCM_BITS("LFE Playback Switch", 2, 7, 7, 1),
AD18XX_PCM_BITS("LFE Playback Volume", 2, 0, 0, 31)
}; };
/* /*
...@@ -1144,11 +1119,67 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97 ...@@ -1144,11 +1119,67 @@ snd_kcontrol_t *snd_ac97_cnew(const snd_kcontrol_new_t *_template, ac97_t * ac97
return snd_ctl_new1(&template, ac97); return snd_ctl_new1(&template, ac97);
} }
/*
* create mute switch(es) for normal stereo controls
*/
static int snd_ac97_cmute_new(snd_card_t *card, char *name, int reg, ac97_t *ac97)
{
snd_kcontrol_t *kctl;
if (ac97->flags & AC97_STEREO_MUTES) {
snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 15, 7, 1, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
} else {
snd_kcontrol_new_t tmp = AC97_SINGLE(name, reg, 15, 1, 1);
tmp.index = ac97->num;
kctl = snd_ctl_new1(&tmp, ac97);
}
return snd_ctl_add(card, kctl);
}
/*
* create volumes for normal stereo controls
*/
static int snd_ac97_cvol_new(snd_card_t *card, char *name, int reg, unsigned int max, ac97_t *ac97)
{
int err;
snd_kcontrol_new_t tmp = AC97_DOUBLE(name, reg, 8, 0, (unsigned int)max, 1);
tmp.index = ac97->num;
if ((err = snd_ctl_add(card, snd_ctl_new1(&tmp, ac97))) < 0)
return err;
snd_ac97_write_cache(ac97, reg,
((ac97->flags & AC97_STEREO_MUTES) ? 0x8080 : 0x8000) |
(unsigned short)max | ((unsigned short)max << 8));
return 0;
}
/*
* create mute-switch and volumes for normal stereo controls
*/
static int snd_ac97_cmix_new(snd_card_t *card, const char *pfx, int reg, int check_res, ac97_t *ac97)
{
int err;
char name[44];
unsigned char max;
sprintf(name, "%s Switch", pfx);
if ((err = snd_ac97_cmute_new(card, name, reg, ac97)) < 0)
return err;
sprintf(name, "%s Volume", pfx);
if (check_res)
snd_ac97_change_volume_params1(ac97, reg, &max);
else
max = 31; /* 5bit */
if ((err = snd_ac97_cvol_new(card, name, reg, max, ac97)) < 0)
return err;
return 0;
}
static int snd_ac97_mixer_build(ac97_t * ac97) static int snd_ac97_mixer_build(ac97_t * ac97)
{ {
snd_card_t *card = ac97->card; snd_card_t *card = ac97->card;
snd_kcontrol_t *kctl; snd_kcontrol_t *kctl;
const snd_kcontrol_new_t *knew;
int err; int err;
unsigned int idx; unsigned int idx;
unsigned char max; unsigned char max;
...@@ -1156,14 +1187,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97) ...@@ -1156,14 +1187,8 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build master controls */ /* build master controls */
/* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */ /* AD claims to remove this control from AD1887, although spec v2.2 does not allow this */
if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) { if (snd_ac97_try_volume_mix(ac97, AC97_MASTER)) {
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_master[0], ac97))) < 0) if ((err = snd_ac97_cmix_new(card, "Master Playback", AC97_MASTER, 1, ac97)) < 0)
return err;
if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(&snd_ac97_controls_master[1], ac97))) < 0)
return err; return err;
snd_ac97_change_volume_params1(ac97, AC97_MASTER, &max);
kctl->private_value &= ~(0xff << 16);
kctl->private_value |= (int)max << 16;
snd_ac97_write_cache(ac97, AC97_MASTER, 0x8000 | max | (max << 8));
} }
ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080; ac97->regs[AC97_CENTER_LFE_MASTER] = 0x8080;
...@@ -1206,15 +1231,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97) ...@@ -1206,15 +1231,11 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
/* build headphone controls */ /* build headphone controls */
if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) { if (snd_ac97_try_volume_mix(ac97, AC97_HEADPHONE) || ac97->id == AC97_ID_STAC9708) {
knew = ac97->id == AC97_ID_STAC9708 ? snd_ac97_sigmatel_surround : snd_ac97_controls_headphone; const char *name = ac97->id == AC97_ID_STAC9708 ?
if ((err = snd_ctl_add(card, snd_ac97_cnew(knew, ac97))) < 0) "Sigmatel Surround Playback" :
return err; "Headphone Playback";
if ((err = snd_ctl_add(card, kctl = snd_ac97_cnew(knew + 1, ac97))) < 0) if ((err = snd_ac97_cmix_new(card, name, AC97_HEADPHONE, 1, ac97)) < 0)
return err; return err;
snd_ac97_change_volume_params1(ac97, AC97_HEADPHONE, &max);
kctl->private_value &= ~(0xff << 16);
kctl->private_value |= (int)max << 16;
snd_ac97_write_cache(ac97, AC97_HEADPHONE, 0x8000 | max | (max << 8));
} }
/* build master mono controls */ /* build master mono controls */
...@@ -1276,70 +1297,73 @@ static int snd_ac97_mixer_build(ac97_t * ac97) ...@@ -1276,70 +1297,73 @@ static int snd_ac97_mixer_build(ac97_t * ac97)
snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max); snd_ac97_write_cache(ac97, AC97_MIC, 0x8000 | max);
/* build Line controls */ /* build Line controls */
for (idx = 0; idx < 2; idx++) if ((err = snd_ac97_cmix_new(card, "Line Playback", AC97_LINE, 0, ac97)) < 0)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_line[idx], ac97))) < 0) return err;
return err;
snd_ac97_write_cache(ac97, AC97_LINE, 0x9f1f);
/* build CD controls */ /* build CD controls */
for (idx = 0; idx < 2; idx++) if ((err = snd_ac97_cmix_new(card, "CD Playback", AC97_CD, 0, ac97)) < 0)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_cd[idx], ac97))) < 0) return err;
return err;
snd_ac97_write_cache(ac97, AC97_CD, 0x9f1f);
/* build Video controls */ /* build Video controls */
if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) { if (snd_ac97_try_volume_mix(ac97, AC97_VIDEO)) {
for (idx = 0; idx < 2; idx++) if ((err = snd_ac97_cmix_new(card, "Video Playback", AC97_VIDEO, 0, ac97)) < 0)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_video[idx], ac97))) < 0) return err;
return err;
snd_ac97_write_cache(ac97, AC97_VIDEO, 0x9f1f);
} }
/* build Aux controls */ /* build Aux controls */
if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) { if (snd_ac97_try_volume_mix(ac97, AC97_AUX)) {
for (idx = 0; idx < 2; idx++) if ((err = snd_ac97_cmix_new(card, "Aux Playback", AC97_AUX, 0, ac97)) < 0)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_aux[idx], ac97))) < 0) return err;
return err;
snd_ac97_write_cache(ac97, AC97_AUX, 0x9f1f);
} }
/* build PCM controls */ /* build PCM controls */
if (ac97->flags & AC97_AD_MULTI) { if (ac97->flags & AC97_AD_MULTI) {
unsigned short init_val;
if (ac97->flags & AC97_STEREO_MUTES)
init_val = 0x9f9f;
else
init_val = 0x9f1f;
for (idx = 0; idx < 2; idx++) for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_pcm[idx], ac97))) < 0)
return err; return err;
ac97->spec.ad18xx.pcmreg[0] = 0x9f1f; ac97->spec.ad18xx.pcmreg[0] = init_val;
if (ac97->scaps & AC97_SCAP_SURROUND_DAC) { if (ac97->scaps & AC97_SCAP_SURROUND_DAC) {
for (idx = 0; idx < 2; idx++) for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_surround[idx], ac97))) < 0)
return err; return err;
ac97->spec.ad18xx.pcmreg[1] = 0x9f1f; ac97->spec.ad18xx.pcmreg[1] = init_val;
} }
if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) { if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC) {
for (idx = 0; idx < 2; idx++) for (idx = 0; idx < 2; idx++)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_center[idx], ac97))) < 0)
return err; return err;
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[0], ac97))) < 0) for (idx = 0; idx < 2; idx++)
return err; if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_ad18xx_lfe[idx], ac97))) < 0)
ac97->spec.ad18xx.pcmreg[2] = 0x9f1f; return err;
ac97->spec.ad18xx.pcmreg[2] = init_val;
} }
snd_ac97_write_cache(ac97, AC97_PCM, init_val);
} else { } else {
unsigned int pcm_ctrls = 2; if ((err = snd_ac97_cmute_new(card, "PCM Playback Switch", AC97_PCM, ac97)) < 0)
return err;
/* FIXME: C-Media chips have no PCM volume!! */ /* FIXME: C-Media chips have no PCM volume!! */
if (/*ac97->id == 0x434d4941 ||*/ if (/*ac97->id == 0x434d4941 ||*/
ac97->id == 0x434d4942 || ac97->id == 0x434d4942 ||
ac97->id == 0x434d4961) ac97->id == 0x434d4961)
pcm_ctrls = 1; snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
for (idx = 0; idx < pcm_ctrls; idx++) else {
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_pcm[idx], ac97))) < 0) if ((err = snd_ac97_cvol_new(card, "PCM Playback Volume", AC97_PCM, 31, ac97)) < 0)
return err; return err;
}
} }
snd_ac97_write_cache(ac97, AC97_PCM, 0x9f1f);
/* build Capture controls */ /* build Capture controls */
for (idx = 0; idx < 3; idx++) if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_src, ac97))) < 0)
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_controls_capture[idx], ac97))) < 0) return err;
return err; if ((err = snd_ac97_cmute_new(card, "Capture Switch", AC97_REC_GAIN, ac97)) < 0)
return err;
if ((err = snd_ctl_add(card, snd_ac97_cnew(&snd_ac97_control_capture_vol, ac97))) < 0)
return err;
snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000); snd_ac97_write_cache(ac97, AC97_REC_SEL, 0x0000);
snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000); snd_ac97_write_cache(ac97, AC97_REC_GAIN, 0x0000);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#define AC97_SINGLE(xname, reg, shift, mask, invert) \ #define AC97_SINGLE(xname, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .info = snd_ac97_info_single, \
.get = snd_ac97_get_single, .put = snd_ac97_put_single, \ .get = snd_ac97_get_single, .put = snd_ac97_put_single, \
.private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) }
/* ac97_codec.c */ /* ac97_codec.c */
extern const char *snd_ac97_stereo_enhancements[]; extern const char *snd_ac97_stereo_enhancements[];
......
...@@ -776,10 +776,13 @@ int patch_ad1980(ac97_t * ac97) ...@@ -776,10 +776,13 @@ int patch_ad1980(ac97_t * ac97)
ac97->build_ops = &patch_ad1980_build_ops; ac97->build_ops = &patch_ad1980_build_ops;
/* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */ /* Switch FRONT/SURROUND LINE-OUT/HP-OUT default connection */
/* it seems that most vendors connect line-out connector to headphone out of AC'97 */ /* it seems that most vendors connect line-out connector to headphone out of AC'97 */
/* Stereo mutes enabled */
misc = snd_ac97_read(ac97, AC97_AD_MISC); misc = snd_ac97_read(ac97, AC97_AD_MISC);
snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
AC97_AD198X_LOSEL | AC97_AD198X_LOSEL |
AC97_AD198X_HPSEL); AC97_AD198X_HPSEL |
AC97_AD198X_MSPLT);
ac97->flags |= AC97_STEREO_MUTES;
return 0; return 0;
} }
...@@ -793,13 +796,16 @@ int patch_ad1985(ac97_t * ac97) ...@@ -793,13 +796,16 @@ int patch_ad1985(ac97_t * ac97)
/* switch front/surround line-out/hp-out */ /* switch front/surround line-out/hp-out */
/* center/LFE, surround in High-Z mode */ /* center/LFE, surround in High-Z mode */
/* AD-compatible mode */ /* AD-compatible mode */
/* Stereo mutes enabled */
snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
AC97_AD198X_VREFD | AC97_AD198X_VREFD |
AC97_AD198X_LOSEL | AC97_AD198X_LOSEL |
AC97_AD198X_HPSEL | AC97_AD198X_HPSEL |
AC97_AD198X_CLDIS | AC97_AD198X_CLDIS |
AC97_AD198X_LODIS | AC97_AD198X_LODIS |
AC97_AD198X_MSPLT |
AC97_AD198X_AC97NC); AC97_AD198X_AC97NC);
ac97->flags |= AC97_STEREO_MUTES;
return 0; return 0;
} }
......
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