mirror of
https://github.com/torvalds/linux.git
synced 2024-11-18 10:01:43 +00:00
ALSA: hda - Fix smart51 handling again
Fix the broken detection of smart51 and its handling. Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
370bafbdae
commit
e3d7a1431f
@ -165,12 +165,17 @@ struct via_spec {
|
|||||||
const struct hda_input_mux *hp_mux;
|
const struct hda_input_mux *hp_mux;
|
||||||
unsigned int hp_independent_mode;
|
unsigned int hp_independent_mode;
|
||||||
unsigned int hp_independent_mode_index;
|
unsigned int hp_independent_mode_index;
|
||||||
unsigned int can_smart51;
|
|
||||||
unsigned int smart51_enabled;
|
|
||||||
unsigned int dmic_enabled;
|
unsigned int dmic_enabled;
|
||||||
unsigned int no_pin_power_ctl;
|
unsigned int no_pin_power_ctl;
|
||||||
enum VIA_HDA_CODEC codec_type;
|
enum VIA_HDA_CODEC codec_type;
|
||||||
|
|
||||||
|
/* smart51 setup */
|
||||||
|
unsigned int smart51_nums;
|
||||||
|
hda_nid_t smart51_pins[2];
|
||||||
|
int smart51_idxs[2];
|
||||||
|
const char *smart51_labels[2];
|
||||||
|
unsigned int smart51_enabled;
|
||||||
|
|
||||||
/* work to check hp jack state */
|
/* work to check hp jack state */
|
||||||
struct hda_codec *codec;
|
struct hda_codec *codec;
|
||||||
struct delayed_work vt1708_hp_work;
|
struct delayed_work vt1708_hp_work;
|
||||||
@ -508,7 +513,7 @@ static void via_auto_init_multi_out(struct hda_codec *codec)
|
|||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < spec->autocfg.line_outs; i++)
|
for (i = 0; i < spec->autocfg.line_outs + spec->smart51_nums; i++)
|
||||||
via_auto_init_output(codec, spec->autocfg.line_out_pins[i],
|
via_auto_init_output(codec, spec->autocfg.line_out_pins[i],
|
||||||
PIN_OUT, &spec->out_path[i]);
|
PIN_OUT, &spec->out_path[i]);
|
||||||
}
|
}
|
||||||
@ -771,15 +776,15 @@ static int via_hp_build(struct hda_codec *codec)
|
|||||||
|
|
||||||
static void notify_aa_path_ctls(struct hda_codec *codec)
|
static void notify_aa_path_ctls(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
|
struct via_spec *spec = codec->spec;
|
||||||
int i;
|
int i;
|
||||||
struct snd_ctl_elem_id id;
|
|
||||||
const char *labels[] = {"Mic", "Front Mic", "Line", "Rear Mic"};
|
|
||||||
struct snd_kcontrol *ctl;
|
|
||||||
|
|
||||||
memset(&id, 0, sizeof(id));
|
for (i = 0; i < spec->smart51_nums; i++) {
|
||||||
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
struct snd_kcontrol *ctl;
|
||||||
for (i = 0; i < ARRAY_SIZE(labels); i++) {
|
struct snd_ctl_elem_id id;
|
||||||
sprintf(id.name, "%s Playback Volume", labels[i]);
|
memset(&id, 0, sizeof(id));
|
||||||
|
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
|
||||||
|
sprintf(id.name, "%s Playback Volume", spec->smart51_labels[i]);
|
||||||
ctl = snd_hda_find_mixer_ctl(codec, id.name);
|
ctl = snd_hda_find_mixer_ctl(codec, id.name);
|
||||||
if (ctl)
|
if (ctl)
|
||||||
snd_ctl_notify(codec->bus->card,
|
snd_ctl_notify(codec->bus->card,
|
||||||
@ -791,43 +796,20 @@ static void notify_aa_path_ctls(struct hda_codec *codec)
|
|||||||
static void mute_aa_path(struct hda_codec *codec, int mute)
|
static void mute_aa_path(struct hda_codec *codec, int mute)
|
||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
int start_idx;
|
int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE;
|
||||||
int end_idx;
|
|
||||||
int i;
|
int i;
|
||||||
/* get nid of MW0 and start & end index */
|
|
||||||
switch (spec->codec_type) {
|
|
||||||
case VT1708:
|
|
||||||
start_idx = 2;
|
|
||||||
end_idx = 4;
|
|
||||||
break;
|
|
||||||
case VT1709_10CH:
|
|
||||||
case VT1709_6CH:
|
|
||||||
start_idx = 2;
|
|
||||||
end_idx = 4;
|
|
||||||
break;
|
|
||||||
case VT1708B_8CH:
|
|
||||||
case VT1708B_4CH:
|
|
||||||
case VT1708S:
|
|
||||||
case VT1716S:
|
|
||||||
start_idx = 2;
|
|
||||||
end_idx = 4;
|
|
||||||
break;
|
|
||||||
case VT1718S:
|
|
||||||
start_idx = 1;
|
|
||||||
end_idx = 3;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* check AA path's mute status */
|
/* check AA path's mute status */
|
||||||
for (i = start_idx; i <= end_idx; i++) {
|
for (i = 0; i < spec->smart51_nums; i++) {
|
||||||
int val = mute ? HDA_AMP_MUTE : HDA_AMP_UNMUTE;
|
if (spec->smart51_idxs[i] < 0)
|
||||||
snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid, HDA_INPUT, i,
|
continue;
|
||||||
|
snd_hda_codec_amp_stereo(codec, spec->aa_mix_nid,
|
||||||
|
HDA_INPUT, spec->smart51_idxs[i],
|
||||||
HDA_AMP_MUTE, val);
|
HDA_AMP_MUTE, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin)
|
static bool is_smart51_candidate(struct hda_codec *codec, hda_nid_t pin)
|
||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
const struct auto_pin_cfg *cfg = &spec->autocfg;
|
const struct auto_pin_cfg *cfg = &spec->autocfg;
|
||||||
@ -847,6 +829,17 @@ static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_smart51_pins(struct hda_codec *codec, hda_nid_t pin)
|
||||||
|
{
|
||||||
|
struct via_spec *spec = codec->spec;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < spec->smart51_nums; i++)
|
||||||
|
if (spec->smart51_pins[i] == pin)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static int via_smart51_info(struct snd_kcontrol *kcontrol,
|
static int via_smart51_info(struct snd_kcontrol *kcontrol,
|
||||||
struct snd_ctl_elem_info *uinfo)
|
struct snd_ctl_elem_info *uinfo)
|
||||||
{
|
{
|
||||||
@ -862,18 +855,12 @@ 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;
|
||||||
const struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
||||||
int on = 1;
|
int on = 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
for (i = 0; i < spec->smart51_nums; i++) {
|
||||||
hda_nid_t nid = cfg->inputs[i].pin;
|
hda_nid_t nid = spec->smart51_pins[i];
|
||||||
unsigned int ctl;
|
unsigned int ctl;
|
||||||
if (cfg->inputs[i].type == AUTO_PIN_MIC &&
|
|
||||||
spec->hp_independent_mode && spec->codec_type != VT1718S)
|
|
||||||
continue; /* ignore FMic for independent HP */
|
|
||||||
if (!is_smart51_pins(codec, nid))
|
|
||||||
continue;
|
|
||||||
ctl = snd_hda_codec_read(codec, nid, 0,
|
ctl = snd_hda_codec_read(codec, nid, 0,
|
||||||
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
|
||||||
if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
|
if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN))
|
||||||
@ -888,21 +875,14 @@ 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 i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
for (i = 0; i < spec->smart51_nums; i++) {
|
||||||
hda_nid_t nid = cfg->inputs[i].pin;
|
hda_nid_t nid = spec->smart51_pins[i];
|
||||||
unsigned int parm;
|
unsigned int parm;
|
||||||
|
|
||||||
if (cfg->inputs[i].type == AUTO_PIN_MIC &&
|
|
||||||
spec->hp_independent_mode && spec->codec_type != VT1718S)
|
|
||||||
continue; /* don't retask FMic for independent HP */
|
|
||||||
if (!is_smart51_pins(codec, nid))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
parm = snd_hda_codec_read(codec, nid, 0,
|
parm = snd_hda_codec_read(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);
|
||||||
@ -932,26 +912,11 @@ static const struct snd_kcontrol_new via_smart51_mixer = {
|
|||||||
static int via_smart51_build(struct hda_codec *codec)
|
static int via_smart51_build(struct hda_codec *codec)
|
||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
struct snd_kcontrol_new *knew;
|
|
||||||
const struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
||||||
hda_nid_t nid;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (!spec->can_smart51)
|
if (!spec->smart51_nums)
|
||||||
return 0;
|
return 0;
|
||||||
|
if (!via_clone_control(spec, &via_smart51_mixer))
|
||||||
knew = via_clone_control(spec, &via_smart51_mixer);
|
|
||||||
if (knew == NULL)
|
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
|
||||||
nid = cfg->inputs[i].pin;
|
|
||||||
if (is_smart51_pins(codec, nid)) {
|
|
||||||
knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1751,12 +1716,18 @@ static void mangle_smart51(struct hda_codec *codec)
|
|||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
struct auto_pin_cfg *cfg = &spec->autocfg;
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
||||||
int i;
|
int i, nums = 0;
|
||||||
|
|
||||||
for (i = 0; i < cfg->num_inputs; i++) {
|
for (i = 0; i < cfg->num_inputs; i++) {
|
||||||
if (!is_smart51_pins(codec, cfg->inputs[i].pin))
|
if (is_smart51_candidate(codec, cfg->inputs[i].pin))
|
||||||
|
nums++;
|
||||||
|
}
|
||||||
|
if (cfg->line_outs + nums < 3)
|
||||||
|
return;
|
||||||
|
for (i = 0; i < cfg->num_inputs; i++) {
|
||||||
|
if (!is_smart51_candidate(codec, cfg->inputs[i].pin))
|
||||||
continue;
|
continue;
|
||||||
spec->can_smart51 = 1;
|
spec->smart51_pins[spec->smart51_nums++] = cfg->inputs[i].pin;
|
||||||
cfg->line_out_pins[cfg->line_outs++] = cfg->inputs[i].pin;
|
cfg->line_out_pins[cfg->line_outs++] = cfg->inputs[i].pin;
|
||||||
if (cfg->line_outs == 3)
|
if (cfg->line_outs == 3)
|
||||||
break;
|
break;
|
||||||
@ -1779,6 +1750,10 @@ static int via_auto_create_multi_out_ctls(struct hda_codec *codec)
|
|||||||
if (cfg->line_outs == 1)
|
if (cfg->line_outs == 1)
|
||||||
mangle_smart51(codec);
|
mangle_smart51(codec);
|
||||||
|
|
||||||
|
err = via_auto_fill_dac_nids(codec);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
for (i = 0; i < cfg->line_outs; i++) {
|
for (i = 0; i < cfg->line_outs; i++) {
|
||||||
hda_nid_t pin, dac;
|
hda_nid_t pin, dac;
|
||||||
pin = cfg->line_out_pins[i];
|
pin = cfg->line_out_pins[i];
|
||||||
@ -1926,7 +1901,7 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec,
|
|||||||
{
|
{
|
||||||
struct via_spec *spec = codec->spec;
|
struct via_spec *spec = codec->spec;
|
||||||
struct hda_input_mux *imux = &spec->private_imux[0];
|
struct hda_input_mux *imux = &spec->private_imux[0];
|
||||||
int i, err, idx, idx2, type, type_idx = 0;
|
int i, j, err, idx, idx2, type, type_idx = 0;
|
||||||
hda_nid_t cap_nid;
|
hda_nid_t cap_nid;
|
||||||
hda_nid_t pin_idxs[8];
|
hda_nid_t pin_idxs[8];
|
||||||
int num_idxs;
|
int num_idxs;
|
||||||
@ -1973,6 +1948,15 @@ static int via_auto_create_analog_input_ctls(struct hda_codec *codec,
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
snd_hda_add_imux_item(imux, label, idx, NULL);
|
snd_hda_add_imux_item(imux, label, idx, NULL);
|
||||||
|
|
||||||
|
/* remember the label for smart51 control */
|
||||||
|
for (j = 0; j < spec->smart51_nums; j++) {
|
||||||
|
if (spec->smart51_pins[j] == cfg->inputs[i].pin) {
|
||||||
|
spec->smart51_idxs[j] = idx;
|
||||||
|
spec->smart51_labels[j] = label;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create capture mixer elements */
|
/* create capture mixer elements */
|
||||||
@ -2105,9 +2089,6 @@ static int via_parse_auto_config(struct hda_codec *codec)
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
|
err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
err = via_auto_fill_dac_nids(codec);
|
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
return err;
|
return err;
|
||||||
if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
|
if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
|
||||||
|
Loading…
Reference in New Issue
Block a user