ALSA: hda - Use new inputs[] field to parse input-pins for VIA codecs

Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Takashi Iwai 2010-08-30 13:06:30 +02:00
parent eea7dc932b
commit 7b315bb498
1 changed files with 73 additions and 71 deletions

View File

@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = {
/* add dynamic controls */ /* add dynamic controls */
static int via_add_control(struct via_spec *spec, int type, const char *name, static int __via_add_control(struct via_spec *spec, int type, const char *name,
unsigned long val) int idx, unsigned long val)
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
return 0; return 0;
} }
#define via_add_control(spec, type, name, val) \
__via_add_control(spec, type, name, 0, val)
static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec,
struct snd_kcontrol_new *tmpl) struct snd_kcontrol_new *tmpl)
{ {
@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec)
/* create input playback/capture controls for the given pin */ /* create input playback/capture controls for the given pin */
static int via_new_analog_input(struct via_spec *spec, const char *ctlname, static int via_new_analog_input(struct via_spec *spec, const char *ctlname,
int idx, int mix_nid) int type_idx, int idx, int mix_nid)
{ {
char name[32]; char name[32];
int err; int err;
sprintf(name, "%s Playback Volume", ctlname); sprintf(name, "%s Playback Volume", ctlname);
err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0) if (err < 0)
return err; return err;
sprintf(name, "%s Playback Switch", ctlname); sprintf(name, "%s Playback Switch", ctlname);
err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0) if (err < 0)
return err; return err;
@ -557,14 +560,12 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin);
static void via_auto_init_analog_input(struct hda_codec *codec) static void via_auto_init_analog_input(struct hda_codec *codec)
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int ctl; unsigned int ctl;
int i; int i;
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = spec->autocfg.input_pins[i]; hda_nid_t nid = cfg->inputs[i].pin;
if (!nid)
continue;
if (spec->smart51_enabled && is_smart51_pins(spec, nid)) if (spec->smart51_enabled && is_smart51_pins(spec, nid))
ctl = PIN_OUT; ctl = PIN_OUT;
else if (i <= AUTO_PIN_FRONT_MIC) else if (i <= AUTO_PIN_FRONT_MIC)
@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute)
} }
static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin)
{ {
int res = 0; const struct auto_pin_cfg *cfg = &spec->autocfg;
int index; int i;
for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) {
if (pin == spec->autocfg.input_pins[index]) { for (i = 0; i < cfg->num_inputs; i++) {
res = 1; if (pin == cfg->inputs[i].pin)
break; return cfg->inputs[i].type < AUTO_PIN_FRONT_LINE;
} }
} return 0;
return res;
} }
static int via_smart51_info(struct snd_kcontrol *kcontrol, static int via_smart51_info(struct snd_kcontrol *kcontrol,
@ -1348,26 +1348,22 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol,
{ {
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; const struct auto_pin_cfg *cfg = &spec->autocfg;
int on = 1; int on = 1;
int i; int i;
for (i = 0; i < ARRAY_SIZE(index); i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = spec->autocfg.input_pins[index[i]]; hda_nid_t nid = cfg->inputs[i].pin;
if (nid) { int ctl = snd_hda_codec_read(codec, nid, 0,
int ctl = AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
snd_hda_codec_read(codec, nid, 0, if (cfg->inputs[i].type >= AUTO_PIN_FRONT_LINE)
AC_VERB_GET_PIN_WIDGET_CONTROL, continue;
0); if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC &&
if (i == AUTO_PIN_FRONT_MIC spec->hp_independent_mode && spec->codec_type != VT1718S)
&& spec->hp_independent_mode
&& spec->codec_type != VT1718S)
continue; /* ignore FMic for independent HP */ continue; /* ignore FMic for independent HP */
if (ctl & AC_PINCTL_IN_EN if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
&& !(ctl & AC_PINCTL_OUT_EN))
on = 0; on = 0;
} }
}
*ucontrol->value.integer.value = on; *ucontrol->value.integer.value = on;
return 0; return 0;
} }
@ -1377,20 +1373,22 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
{ {
struct hda_codec *codec = snd_kcontrol_chip(kcontrol); struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
int out_in = *ucontrol->value.integer.value int out_in = *ucontrol->value.integer.value
? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN;
int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE };
int i; int i;
for (i = 0; i < ARRAY_SIZE(index); i++) { for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = spec->autocfg.input_pins[index[i]]; hda_nid_t nid = cfg->inputs[i].pin;
if (i == AUTO_PIN_FRONT_MIC unsigned int parm;
&& spec->hp_independent_mode
&& spec->codec_type != VT1718S) if (cfg->inputs[i].type >= AUTO_PIN_FRONT_LINE)
continue;
if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC &&
spec->hp_independent_mode && spec->codec_type != VT1718S)
continue; /* don't retask FMic for independent HP */ continue; /* don't retask FMic for independent HP */
if (nid) {
unsigned int parm = snd_hda_codec_read( parm = snd_hda_codec_read(codec, nid, 0,
codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0); AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN);
parm |= out_in; parm |= out_in;
@ -1401,12 +1399,12 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol,
mute_aa_path(codec, 1); mute_aa_path(codec, 1);
notify_aa_path_ctls(codec); notify_aa_path_ctls(codec);
} }
if (spec->codec_type == VT1718S) if (spec->codec_type == VT1718S) {
snd_hda_codec_amp_stereo( snd_hda_codec_amp_stereo(
codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE,
HDA_AMP_UNMUTE); HDA_AMP_UNMUTE);
} }
if (i == AUTO_PIN_FRONT_MIC) { if (cfg->inputs[i].type == AUTO_PIN_FRONT_MIC) {
if (spec->codec_type == VT1708S if (spec->codec_type == VT1708S
|| spec->codec_type == VT1716S) { || spec->codec_type == VT1716S) {
/* input = index 1 (AOW3) */ /* input = index 1 (AOW3) */
@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = {
static int via_smart51_build(struct via_spec *spec) static int via_smart51_build(struct via_spec *spec)
{ {
struct snd_kcontrol_new *knew; struct snd_kcontrol_new *knew;
int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; const struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid; hda_nid_t nid;
int i; int i;
@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec)
if (knew == NULL) if (knew == NULL)
return -ENOMEM; return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(index); i++) { for (i = 0; i < cfg->num_inputs; i++) {
nid = spec->autocfg.input_pins[index[i]]; nid = cfg->inputs[i].pin;
if (nid) { if (cfg->inputs[i].type < AUTO_PIN_FRONT_LINE) {
knew = via_clone_control(spec, &via_smart51_mixer[1]); knew = via_clone_control(spec, &via_smart51_mixer[1]);
if (knew == NULL) if (knew == NULL)
return -ENOMEM; return -ENOMEM;
knew->subdevice = nid; knew->subdevice = nid;
break;
} }
} }
@ -2419,7 +2418,7 @@ static int vt_auto_create_analog_input_ctls(struct via_spec *spec,
hda_nid_t pin_idxs[], int num_idxs) hda_nid_t pin_idxs[], int num_idxs)
{ {
struct hda_input_mux *imux = &spec->private_imux[0]; struct hda_input_mux *imux = &spec->private_imux[0];
int i, err, idx; int i, err, idx, type, type_idx = 0;
/* for internal loopback recording select */ /* for internal loopback recording select */
for (idx = 0; idx < num_idxs; idx++) { for (idx = 0; idx < num_idxs; idx++) {
@ -2431,20 +2430,23 @@ static int vt_auto_create_analog_input_ctls(struct via_spec *spec,
} }
} }
for (i = 0; i < AUTO_PIN_LAST; i++) { for (i = 0; i < cfg->num_inputs; i++) {
if (!cfg->input_pins[i]) type = cfg->inputs[i].type;
continue;
for (idx = 0; idx < num_idxs; idx++) for (idx = 0; idx < num_idxs; idx++)
if (pin_idxs[idx] == cfg->input_pins[i]) if (pin_idxs[idx] == cfg->inputs[i].pin)
break; break;
if (idx >= num_idxs) if (idx >= num_idxs)
continue; continue;
err = via_new_analog_input(spec, auto_pin_cfg_labels[i], if (i > 0 && type == cfg->inputs[i - 1].type)
idx, cap_nid); type_idx++;
else
type_idx = 0;
err = via_new_analog_input(spec, auto_pin_cfg_labels[type],
type_idx, idx, cap_nid);
if (err < 0) if (err < 0)
return err; return err;
imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; imux->items[imux->num_items].label =
snd_hda_get_input_pin_label(cfg, i);
imux->items[imux->num_items].index = idx; imux->items[imux->num_items].index = idx;
imux->num_items++; imux->num_items++;
} }
@ -5513,7 +5515,7 @@ static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec,
if (err < 0) if (err < 0)
return err; return err;
/* build volume/mute control of loopback */ /* build volume/mute control of loopback */
err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21);
if (err < 0) if (err < 0)
return err; return err;
@ -5836,7 +5838,7 @@ static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec,
return err; return err;
/* build volume/mute control of loopback */ /* build volume/mute control of loopback */
err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21);
if (err < 0) if (err < 0)
return err; return err;