Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 353115
b: refs/heads/master
c: 2c12c30
h: refs/heads/master
i:
  353113: e161447
  353111: 4e0fed9
v: v3
  • Loading branch information
Takashi Iwai committed Jan 12, 2013
1 parent 65005bb commit 938bac9
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 53 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 62f3a2f718131e6f42746ccd26dbf4eb5eab677a
refs/heads/master: 2c12c30d3fe5589d32ceddade09f13f1d3d6391d
137 changes: 85 additions & 52 deletions trunk/sound/pci/hda/hda_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,41 @@ void snd_hda_gen_spec_free(struct hda_gen_spec *spec)
}
EXPORT_SYMBOL_HDA(snd_hda_gen_spec_free);

/*
* pin control value accesses
*/

#define update_pin_ctl(codec, pin, val) \
snd_hda_codec_update_cache(codec, pin, 0, \
AC_VERB_SET_PIN_WIDGET_CONTROL, val)

/* restore the pinctl based on the cached value */
static inline void restore_pin_ctl(struct hda_codec *codec, hda_nid_t pin)
{
update_pin_ctl(codec, pin, snd_hda_codec_get_pin_target(codec, pin));
}

/* set the pinctl target value and write it if requested */
static void set_pin_target(struct hda_codec *codec, hda_nid_t pin,
unsigned int val, bool do_write)
{
if (!pin)
return;
val = snd_hda_correct_pin_ctl(codec, pin, val);
snd_hda_codec_set_pin_target(codec, pin, val);
if (do_write)
update_pin_ctl(codec, pin, val);
}

/* set pinctl target values for all given pins */
static void set_pin_targets(struct hda_codec *codec, int num_pins,
hda_nid_t *pins, unsigned int val)
{
int i;
for (i = 0; i < num_pins; i++)
set_pin_target(codec, pins[i], val, false);
}

/*
* parsing paths
*/
Expand Down Expand Up @@ -1317,6 +1352,15 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
spec->multiout.extra_out_nid,
spec->speaker_paths);

/* set initial pinctl targets */
set_pin_targets(codec, cfg->line_outs, cfg->line_out_pins,
cfg->line_out_type == AUTO_PIN_HP_OUT ? PIN_HP : PIN_OUT);
if (cfg->line_out_type != AUTO_PIN_HP_OUT)
set_pin_targets(codec, cfg->hp_outs, cfg->hp_pins, PIN_HP);
if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
set_pin_targets(codec, cfg->speaker_outs,
cfg->speaker_pins, PIN_OUT);

return badness;
}

Expand Down Expand Up @@ -1715,14 +1759,13 @@ static int set_multi_io(struct hda_codec *codec, int idx, bool output)
return 0;

if (output) {
snd_hda_set_pin_ctl_cache(codec, nid, PIN_OUT);
set_pin_target(codec, nid, PIN_OUT, true);
snd_hda_activate_path(codec, path, true, true);
set_pin_eapd(codec, nid, true);
} else {
set_pin_eapd(codec, nid, false);
snd_hda_activate_path(codec, path, false, true);
snd_hda_set_pin_ctl_cache(codec, nid,
spec->multi_io[idx].ctl_in);
set_pin_target(codec, nid, spec->multi_io[idx].ctl_in, true);
}
return 0;
}
Expand Down Expand Up @@ -1871,7 +1914,7 @@ static void update_shared_mic_hp(struct hda_codec *codec, bool set_as_mic)
}

val = set_as_mic ? val | PIN_IN : PIN_HP;
snd_hda_set_pin_ctl_cache(codec, pin, val);
set_pin_target(codec, pin, val, true);

spec->automute_speaker = !set_as_mic;
call_update_outputs(codec);
Expand Down Expand Up @@ -2126,6 +2169,7 @@ static int create_input_ctls(struct hda_codec *codec)
int num_adcs;
int i, err, type_idx = 0;
const char *prev_label = NULL;
unsigned int val;

num_adcs = fill_adc_nids(codec);
if (num_adcs < 0)
Expand All @@ -2146,6 +2190,11 @@ static int create_input_ctls(struct hda_codec *codec)
type_idx = 0;
prev_label = label;

val = PIN_IN;
if (cfg->inputs[i].type == AUTO_PIN_MIC)
val |= snd_hda_get_default_vref(codec, pin);
set_pin_target(codec, pin, val, false);

if (mixer) {
if (is_reachable_path(codec, pin, mixer)) {
err = new_analog_input(codec, i, pin,
Expand Down Expand Up @@ -2611,12 +2660,12 @@ static void parse_digital(struct hda_codec *codec)
struct hda_gen_spec *spec = codec->spec;
struct nid_path *path;
int i, nums;
hda_nid_t dig_nid;
hda_nid_t dig_nid, pin;

/* support multiple SPDIFs; the secondary is set up as a slave */
nums = 0;
for (i = 0; i < spec->autocfg.dig_outs; i++) {
hda_nid_t pin = spec->autocfg.dig_out_pins[i];
pin = spec->autocfg.dig_out_pins[i];
dig_nid = look_for_dac(codec, pin, true);
if (!dig_nid)
continue;
Expand All @@ -2626,6 +2675,7 @@ static void parse_digital(struct hda_codec *codec)
print_nid_path("digout", path);
path->active = true;
spec->digout_paths[i] = snd_hda_get_path_idx(codec, path);
set_pin_target(codec, pin, PIN_OUT, false);
if (!nums) {
spec->multiout.dig_out_nid = dig_nid;
spec->dig_out_type = spec->autocfg.dig_out_type[0];
Expand All @@ -2639,21 +2689,21 @@ static void parse_digital(struct hda_codec *codec)
}

if (spec->autocfg.dig_in_pin) {
pin = spec->autocfg.dig_in_pin;
dig_nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, dig_nid++) {
unsigned int wcaps = get_wcaps(codec, dig_nid);
if (get_wcaps_type(wcaps) != AC_WID_AUD_IN)
continue;
if (!(wcaps & AC_WCAP_DIGITAL))
continue;
path = snd_hda_add_new_path(codec,
spec->autocfg.dig_in_pin,
dig_nid, 0);
path = snd_hda_add_new_path(codec, pin, dig_nid, 0);
if (path) {
print_nid_path("digin", path);
path->active = true;
spec->dig_in_nid = dig_nid;
spec->digin_path = snd_hda_get_path_idx(codec, path);
set_pin_target(codec, pin, PIN_IN, false);
break;
}
}
Expand Down Expand Up @@ -2730,10 +2780,9 @@ static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)

/* standard HP/line-out auto-mute helper */
static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
bool mute, bool hp_out)
bool mute)
{
struct hda_gen_spec *spec = codec->spec;
unsigned int pin_bits = mute ? 0 : (hp_out ? PIN_HP : PIN_OUT);
int i;

for (i = 0; i < num_pins; i++) {
Expand All @@ -2744,14 +2793,18 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
/* don't reset VREF value in case it's controlling
* the amp (see alc861_fixup_asus_amp_vref_0f())
*/
if (spec->keep_vref_in_automute) {
val = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
val &= ~PIN_HP;
} else
if (spec->keep_vref_in_automute)
val = snd_hda_codec_get_pin_target(codec, nid) & ~PIN_HP;
else
val = 0;
val |= pin_bits;
snd_hda_set_pin_ctl_cache(codec, nid, val);
if (!mute)
val |= snd_hda_codec_get_pin_target(codec, nid);
/* here we call update_pin_ctl() so that the pinctl is changed
* without changing the pinctl target value;
* the original target value will be still referred at the
* init / resume again
*/
update_pin_ctl(codec, nid, val);
set_pin_eapd(codec, nid, !mute);
}
}
Expand All @@ -2768,15 +2821,15 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
*/
if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
spec->autocfg.hp_pins, spec->master_mute, true);
spec->autocfg.hp_pins, spec->master_mute);

if (!spec->automute_speaker)
on = 0;
else
on = spec->hp_jack_present | spec->line_jack_present;
on |= spec->master_mute;
do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
spec->autocfg.speaker_pins, on, false);
spec->autocfg.speaker_pins, on);

/* toggle line-out mutes if needed, too */
/* if LO is a copy of either HP or Speaker, don't need to handle it */
Expand All @@ -2789,7 +2842,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec)
on = spec->hp_jack_present;
on |= spec->master_mute;
do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
spec->autocfg.line_out_pins, on, false);
spec->autocfg.line_out_pins, on);
}
EXPORT_SYMBOL_HDA(snd_hda_gen_update_outputs);

Expand Down Expand Up @@ -3806,8 +3859,7 @@ EXPORT_SYMBOL_HDA(snd_hda_gen_build_pcms);
*/

/* configure the given path as a proper output */
static void set_output_and_unmute(struct hda_codec *codec,
int pin_type, int path_idx)
static void set_output_and_unmute(struct hda_codec *codec, int path_idx)
{
struct nid_path *path;
hda_nid_t pin;
Expand All @@ -3816,7 +3868,7 @@ static void set_output_and_unmute(struct hda_codec *codec,
if (!path || !path->depth)
return;
pin = path->path[path->depth - 1];
snd_hda_set_pin_ctl_cache(codec, pin, pin_type);
restore_pin_ctl(codec, pin);
snd_hda_activate_path(codec, path, path->active, true);
set_pin_eapd(codec, pin, path->active);
}
Expand All @@ -3825,26 +3877,19 @@ static void set_output_and_unmute(struct hda_codec *codec,
static void init_multi_out(struct hda_codec *codec)
{
struct hda_gen_spec *spec = codec->spec;
int pin_type;
int i;

if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
pin_type = PIN_HP;
else
pin_type = PIN_OUT;

for (i = 0; i < spec->autocfg.line_outs; i++)
set_output_and_unmute(codec, pin_type, spec->out_paths[i]);
set_output_and_unmute(codec, spec->out_paths[i]);
}


static void __init_extra_out(struct hda_codec *codec, int num_outs,
int *paths, int type)
static void __init_extra_out(struct hda_codec *codec, int num_outs, int *paths)
{
int i;

for (i = 0; i < num_outs; i++)
set_output_and_unmute(codec, type, paths[i]);
set_output_and_unmute(codec, paths[i]);
}

/* initialize hp and speaker paths */
Expand All @@ -3853,11 +3898,10 @@ static void init_extra_out(struct hda_codec *codec)
struct hda_gen_spec *spec = codec->spec;

if (spec->autocfg.line_out_type != AUTO_PIN_HP_OUT)
__init_extra_out(codec, spec->autocfg.hp_outs,
spec->hp_paths, PIN_HP);
__init_extra_out(codec, spec->autocfg.hp_outs, spec->hp_paths);
if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT)
__init_extra_out(codec, spec->autocfg.speaker_outs,
spec->speaker_paths, PIN_OUT);
spec->speaker_paths);
}

/* initialize multi-io paths */
Expand All @@ -3874,22 +3918,11 @@ static void init_multi_io(struct hda_codec *codec)
continue;
if (!spec->multi_io[i].ctl_in)
spec->multi_io[i].ctl_in =
snd_hda_codec_update_cache(codec, pin, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
snd_hda_codec_get_pin_target(codec, pin);
snd_hda_activate_path(codec, path, path->active, true);
}
}

/* set up the input pin config, depending on the given auto-pin type */
static void set_input_pin(struct hda_codec *codec, hda_nid_t nid,
int auto_pin_type)
{
unsigned int val = PIN_IN;
if (auto_pin_type == AUTO_PIN_MIC)
val |= snd_hda_get_default_vref(codec, nid);
snd_hda_set_pin_ctl_cache(codec, nid, val);
}

/* set up input pins and loopback paths */
static void init_analog_input(struct hda_codec *codec)
{
Expand All @@ -3900,7 +3933,7 @@ static void init_analog_input(struct hda_codec *codec)
for (i = 0; i < cfg->num_inputs; i++) {
hda_nid_t nid = cfg->inputs[i].pin;
if (is_input_pin(codec, nid))
set_input_pin(codec, nid, cfg->inputs[i].type);
restore_pin_ctl(codec, nid);

/* init loopback inputs */
if (spec->mixer_nid) {
Expand Down Expand Up @@ -3953,11 +3986,11 @@ static void init_digital(struct hda_codec *codec)
hda_nid_t pin;

for (i = 0; i < spec->autocfg.dig_outs; i++)
set_output_and_unmute(codec, PIN_OUT, spec->digout_paths[i]);
set_output_and_unmute(codec, spec->digout_paths[i]);
pin = spec->autocfg.dig_in_pin;
if (pin) {
struct nid_path *path;
snd_hda_set_pin_ctl_cache(codec, pin, PIN_IN);
restore_pin_ctl(codec, pin);
path = snd_hda_get_path_from_idx(codec, spec->digin_path);
if (path)
snd_hda_activate_path(codec, path, path->active, false);
Expand Down

0 comments on commit 938bac9

Please sign in to comment.