diff options
author | Takashi Iwai <tiwai@suse.de> | 2009-03-06 04:00:05 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-03-06 04:04:24 -0500 |
commit | dc04d1b4d2043e2fca2d94d6d5542b930f2bc5b3 (patch) | |
tree | 2b0450ffcf9c64b6f8b3220262fd81bd934d08a7 /sound/pci/hda/patch_sigmatel.c | |
parent | b3225190c1991449086395f85a3cc07ac936e8f0 (diff) |
ALSA: hda - Create output controls according to pin types for IDT/STAC
Improve the parser to pick up more intuitive control names for the
outputs judging from the pin type, instead of fixed names assigned
to channels.
Also, revive the multi-HP workaround since this change fixes the
problem with the multi-HP detection.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 141 |
1 files changed, 72 insertions, 69 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 2e0a599f8c12..edd2ed7ebb49 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -3039,35 +3039,33 @@ static int add_spec_extra_dacs(struct sigmatel_spec *spec, hda_nid_t nid) | |||
3039 | return 1; | 3039 | return 1; |
3040 | } | 3040 | } |
3041 | 3041 | ||
3042 | static int is_unique_dac(struct sigmatel_spec *spec, hda_nid_t nid) | 3042 | /* Create output controls |
3043 | { | 3043 | * The mixer elements are named depending on the given type (AUTO_PIN_XXX_OUT) |
3044 | int i; | 3044 | */ |
3045 | 3045 | static int create_multi_out_ctls(struct hda_codec *codec, int num_outs, | |
3046 | if (spec->autocfg.line_outs != 1) | 3046 | const hda_nid_t *pins, |
3047 | return 0; | 3047 | const hda_nid_t *dac_nids, |
3048 | if (spec->multiout.hp_nid == nid) | 3048 | int type) |
3049 | return 0; | ||
3050 | for (i = 0; i < ARRAY_SIZE(spec->multiout.extra_out_nid); i++) | ||
3051 | if (spec->multiout.extra_out_nid[i] == nid) | ||
3052 | return 0; | ||
3053 | return 1; | ||
3054 | } | ||
3055 | |||
3056 | /* add playback controls from the parsed DAC table */ | ||
3057 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3058 | const struct auto_pin_cfg *cfg) | ||
3059 | { | 3049 | { |
3060 | struct sigmatel_spec *spec = codec->spec; | 3050 | struct sigmatel_spec *spec = codec->spec; |
3061 | static const char *chname[4] = { | 3051 | static const char *chname[4] = { |
3062 | "Front", "Surround", NULL /*CLFE*/, "Side" | 3052 | "Front", "Surround", NULL /*CLFE*/, "Side" |
3063 | }; | 3053 | }; |
3064 | hda_nid_t nid = 0; | 3054 | static const char *hp_pfxs[] = { |
3055 | "Headphone", "Headphone2", "Headphone3", "Headphone4" | ||
3056 | }; | ||
3057 | static const char *speaker_pfxs[] = { | ||
3058 | "Speaker", "External Speaker", "Speaker2", "Speaker3" | ||
3059 | }; | ||
3060 | hda_nid_t nid; | ||
3065 | int i, err; | 3061 | int i, err; |
3066 | unsigned int wid_caps; | 3062 | unsigned int wid_caps; |
3067 | 3063 | ||
3068 | for (i = 0; i < cfg->line_outs && spec->multiout.dac_nids[i]; i++) { | 3064 | for (i = 0; i < num_outs && i < ARRAY_SIZE(chname); i++) { |
3069 | nid = spec->multiout.dac_nids[i]; | 3065 | nid = dac_nids[i]; |
3070 | if (i == 2) { | 3066 | if (!nid) |
3067 | continue; | ||
3068 | if (type != AUTO_PIN_HP_OUT && i == 2) { | ||
3071 | /* Center/LFE */ | 3069 | /* Center/LFE */ |
3072 | err = create_controls(codec, "Center", nid, 1); | 3070 | err = create_controls(codec, "Center", nid, 1); |
3073 | if (err < 0) | 3071 | if (err < 0) |
@@ -3088,23 +3086,43 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3088 | } | 3086 | } |
3089 | 3087 | ||
3090 | } else { | 3088 | } else { |
3091 | const char *name = chname[i]; | 3089 | const char *name; |
3092 | /* if it's a single DAC, assign a better name */ | 3090 | switch (type) { |
3093 | if (!i && is_unique_dac(spec, nid)) { | 3091 | case AUTO_PIN_HP_OUT: |
3094 | switch (cfg->line_out_type) { | 3092 | name = hp_pfxs[i]; |
3095 | case AUTO_PIN_HP_OUT: | 3093 | break; |
3096 | name = "Headphone"; | 3094 | case AUTO_PIN_SPEAKER_OUT: |
3097 | break; | 3095 | name = speaker_pfxs[i]; |
3098 | case AUTO_PIN_SPEAKER_OUT: | 3096 | break; |
3099 | name = "Speaker"; | 3097 | default: |
3100 | break; | 3098 | name = chname[i]; |
3101 | } | 3099 | break; |
3102 | } | 3100 | } |
3103 | err = create_controls(codec, name, nid, 3); | 3101 | err = create_controls(codec, name, nid, 3); |
3104 | if (err < 0) | 3102 | if (err < 0) |
3105 | return err; | 3103 | return err; |
3104 | if (type == AUTO_PIN_HP_OUT && !spec->hp_detect) { | ||
3105 | wid_caps = get_wcaps(codec, pins[i]); | ||
3106 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3107 | spec->hp_detect = 1; | ||
3108 | } | ||
3106 | } | 3109 | } |
3107 | } | 3110 | } |
3111 | return 0; | ||
3112 | } | ||
3113 | |||
3114 | /* add playback controls from the parsed DAC table */ | ||
3115 | static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | ||
3116 | const struct auto_pin_cfg *cfg) | ||
3117 | { | ||
3118 | struct sigmatel_spec *spec = codec->spec; | ||
3119 | int err; | ||
3120 | |||
3121 | err = create_multi_out_ctls(codec, cfg->line_outs, cfg->line_out_pins, | ||
3122 | spec->multiout.dac_nids, | ||
3123 | cfg->line_out_type); | ||
3124 | if (err < 0) | ||
3125 | return err; | ||
3108 | 3126 | ||
3109 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { | 3127 | if (cfg->hp_outs > 1 && cfg->line_out_type == AUTO_PIN_LINE_OUT) { |
3110 | err = stac92xx_add_control(spec, | 3128 | err = stac92xx_add_control(spec, |
@@ -3139,40 +3157,18 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec, | |||
3139 | struct auto_pin_cfg *cfg) | 3157 | struct auto_pin_cfg *cfg) |
3140 | { | 3158 | { |
3141 | struct sigmatel_spec *spec = codec->spec; | 3159 | struct sigmatel_spec *spec = codec->spec; |
3142 | hda_nid_t nid; | 3160 | int err; |
3143 | int i, err, nums; | 3161 | |
3162 | err = create_multi_out_ctls(codec, cfg->hp_outs, cfg->hp_pins, | ||
3163 | spec->hp_dacs, AUTO_PIN_HP_OUT); | ||
3164 | if (err < 0) | ||
3165 | return err; | ||
3166 | |||
3167 | err = create_multi_out_ctls(codec, cfg->speaker_outs, cfg->speaker_pins, | ||
3168 | spec->speaker_dacs, AUTO_PIN_SPEAKER_OUT); | ||
3169 | if (err < 0) | ||
3170 | return err; | ||
3144 | 3171 | ||
3145 | nums = 0; | ||
3146 | for (i = 0; i < cfg->hp_outs; i++) { | ||
3147 | static const char *pfxs[] = { | ||
3148 | "Headphone", "Headphone2", "Headphone3", | ||
3149 | }; | ||
3150 | unsigned int wid_caps = get_wcaps(codec, cfg->hp_pins[i]); | ||
3151 | if (wid_caps & AC_WCAP_UNSOL_CAP) | ||
3152 | spec->hp_detect = 1; | ||
3153 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3154 | continue; | ||
3155 | nid = spec->hp_dacs[i]; | ||
3156 | if (!nid) | ||
3157 | continue; | ||
3158 | err = create_controls(codec, pfxs[nums++], nid, 3); | ||
3159 | if (err < 0) | ||
3160 | return err; | ||
3161 | } | ||
3162 | nums = 0; | ||
3163 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
3164 | static const char *pfxs[] = { | ||
3165 | "Speaker", "External Speaker", "Speaker2", | ||
3166 | }; | ||
3167 | if (nums >= ARRAY_SIZE(pfxs)) | ||
3168 | continue; | ||
3169 | nid = spec->speaker_dacs[i]; | ||
3170 | if (!nid) | ||
3171 | continue; | ||
3172 | err = create_controls(codec, pfxs[nums++], nid, 3); | ||
3173 | if (err < 0) | ||
3174 | return err; | ||
3175 | } | ||
3176 | return 0; | 3172 | return 0; |
3177 | } | 3173 | } |
3178 | 3174 | ||
@@ -3505,6 +3501,7 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec) | |||
3505 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) | 3501 | static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) |
3506 | { | 3502 | { |
3507 | struct sigmatel_spec *spec = codec->spec; | 3503 | struct sigmatel_spec *spec = codec->spec; |
3504 | int hp_swap = 0; | ||
3508 | int err; | 3505 | int err; |
3509 | 3506 | ||
3510 | if ((err = snd_hda_parse_pin_def_config(codec, | 3507 | if ((err = snd_hda_parse_pin_def_config(codec, |
@@ -3514,7 +3511,6 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3514 | if (! spec->autocfg.line_outs) | 3511 | if (! spec->autocfg.line_outs) |
3515 | return 0; /* can't find valid pin config */ | 3512 | return 0; /* can't find valid pin config */ |
3516 | 3513 | ||
3517 | #if 0 /* FIXME: temporarily disabled */ | ||
3518 | /* If we have no real line-out pin and multiple hp-outs, HPs should | 3514 | /* If we have no real line-out pin and multiple hp-outs, HPs should |
3519 | * be set up as multi-channel outputs. | 3515 | * be set up as multi-channel outputs. |
3520 | */ | 3516 | */ |
@@ -3533,8 +3529,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3533 | spec->autocfg.line_outs = spec->autocfg.hp_outs; | 3529 | spec->autocfg.line_outs = spec->autocfg.hp_outs; |
3534 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | 3530 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; |
3535 | spec->autocfg.hp_outs = 0; | 3531 | spec->autocfg.hp_outs = 0; |
3532 | hp_swap = 1; | ||
3536 | } | 3533 | } |
3537 | #endif /* FIXME: temporarily disabled */ | ||
3538 | if (spec->autocfg.mono_out_pin) { | 3534 | if (spec->autocfg.mono_out_pin) { |
3539 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & | 3535 | int dir = get_wcaps(codec, spec->autocfg.mono_out_pin) & |
3540 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); | 3536 | (AC_WCAP_OUT_AMP | AC_WCAP_IN_AMP); |
@@ -3627,12 +3623,19 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out | |||
3627 | #endif | 3623 | #endif |
3628 | 3624 | ||
3629 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); | 3625 | err = stac92xx_auto_create_hp_ctls(codec, &spec->autocfg); |
3630 | |||
3631 | if (err < 0) | 3626 | if (err < 0) |
3632 | return err; | 3627 | return err; |
3633 | 3628 | ||
3634 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | 3629 | /* All output parsing done, now restore the swapped hp pins */ |
3630 | if (hp_swap) { | ||
3631 | memcpy(spec->autocfg.hp_pins, spec->autocfg.line_out_pins, | ||
3632 | sizeof(spec->autocfg.hp_pins)); | ||
3633 | spec->autocfg.hp_outs = spec->autocfg.line_outs; | ||
3634 | spec->autocfg.line_out_type = AUTO_PIN_HP_OUT; | ||
3635 | spec->autocfg.line_outs = 0; | ||
3636 | } | ||
3635 | 3637 | ||
3638 | err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg); | ||
3636 | if (err < 0) | 3639 | if (err < 0) |
3637 | return err; | 3640 | return err; |
3638 | 3641 | ||