aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2009-03-06 04:00:05 -0500
committerTakashi Iwai <tiwai@suse.de>2009-03-06 04:04:24 -0500
commitdc04d1b4d2043e2fca2d94d6d5542b930f2bc5b3 (patch)
tree2b0450ffcf9c64b6f8b3220262fd81bd934d08a7 /sound/pci/hda/patch_sigmatel.c
parentb3225190c1991449086395f85a3cc07ac936e8f0 (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.c141
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
3042static 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 3045static 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 */
3057static 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 */
3115static 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)
3505static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) 3501static 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