diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-12-07 11:33:09 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-12-07 11:33:09 -0500 |
commit | ffe7e4063987678c00589717d7871f837c6e7300 (patch) | |
tree | 1aeee46780d9f7601909a4baa5f0c766c555e2e2 /sound/pci | |
parent | 9eb6e9b16f86ef94f05427bd7fc84d521aa57169 (diff) | |
parent | 0a34b42b6245ccc710be6759cded5b7fe41ea1f9 (diff) |
Merge branch 'fix/hda' into topic/hda
Conflicts:
sound/pci/hda/patch_realtek.c
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 65 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 47 | ||||
-rw-r--r-- | sound/pci/sis7019.c | 64 |
3 files changed, 127 insertions, 49 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 63186d7d18a9..8a74c1e8eedb 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -300,6 +300,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
300 | imux = &spec->input_mux[mux_idx]; | 300 | imux = &spec->input_mux[mux_idx]; |
301 | if (!imux->num_items && mux_idx > 0) | 301 | if (!imux->num_items && mux_idx > 0) |
302 | imux = &spec->input_mux[0]; | 302 | imux = &spec->input_mux[0]; |
303 | if (!imux->num_items) | ||
304 | return 0; | ||
303 | 305 | ||
304 | if (idx >= imux->num_items) | 306 | if (idx >= imux->num_items) |
305 | idx = imux->num_items - 1; | 307 | idx = imux->num_items - 1; |
@@ -2663,6 +2665,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
2663 | case AUTO_PIN_SPEAKER_OUT: | 2665 | case AUTO_PIN_SPEAKER_OUT: |
2664 | if (cfg->line_outs == 1) | 2666 | if (cfg->line_outs == 1) |
2665 | return "Speaker"; | 2667 | return "Speaker"; |
2668 | if (cfg->line_outs == 2) | ||
2669 | return ch ? "Bass Speaker" : "Speaker"; | ||
2666 | break; | 2670 | break; |
2667 | case AUTO_PIN_HP_OUT: | 2671 | case AUTO_PIN_HP_OUT: |
2668 | /* for multi-io case, only the primary out */ | 2672 | /* for multi-io case, only the primary out */ |
@@ -2974,7 +2978,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | |||
2974 | if (!nid) | 2978 | if (!nid) |
2975 | continue; | 2979 | continue; |
2976 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | 2980 | if (found_in_nid_list(nid, spec->multiout.dac_nids, |
2977 | spec->multiout.num_dacs)) | 2981 | ARRAY_SIZE(spec->private_dac_nids))) |
2978 | continue; | 2982 | continue; |
2979 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, | 2983 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, |
2980 | ARRAY_SIZE(spec->multiout.hp_out_nid))) | 2984 | ARRAY_SIZE(spec->multiout.hp_out_nid))) |
@@ -3012,6 +3016,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) | |||
3012 | return 0; | 3016 | return 0; |
3013 | } | 3017 | } |
3014 | 3018 | ||
3019 | /* return 0 if no possible DAC is found, 1 if one or more found */ | ||
3015 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | 3020 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, |
3016 | const hda_nid_t *pins, hda_nid_t *dacs) | 3021 | const hda_nid_t *pins, hda_nid_t *dacs) |
3017 | { | 3022 | { |
@@ -3029,7 +3034,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | |||
3029 | if (!dacs[i]) | 3034 | if (!dacs[i]) |
3030 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); | 3035 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); |
3031 | } | 3036 | } |
3032 | return 0; | 3037 | return 1; |
3033 | } | 3038 | } |
3034 | 3039 | ||
3035 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 3040 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
@@ -3039,7 +3044,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, | |||
3039 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | 3044 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) |
3040 | { | 3045 | { |
3041 | struct alc_spec *spec = codec->spec; | 3046 | struct alc_spec *spec = codec->spec; |
3042 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 3047 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3043 | unsigned int location, defcfg; | 3048 | unsigned int location, defcfg; |
3044 | int num_pins; | 3049 | int num_pins; |
3045 | bool redone = false; | 3050 | bool redone = false; |
@@ -3052,6 +3057,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3052 | spec->multiout.extra_out_nid[0] = 0; | 3057 | spec->multiout.extra_out_nid[0] = 0; |
3053 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | 3058 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); |
3054 | spec->multiout.dac_nids = spec->private_dac_nids; | 3059 | spec->multiout.dac_nids = spec->private_dac_nids; |
3060 | spec->multi_ios = 0; | ||
3055 | 3061 | ||
3056 | /* fill hard-wired DACs first */ | 3062 | /* fill hard-wired DACs first */ |
3057 | if (!redone) { | 3063 | if (!redone) { |
@@ -3085,10 +3091,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3085 | for (i = 0; i < cfg->line_outs; i++) { | 3091 | for (i = 0; i < cfg->line_outs; i++) { |
3086 | if (spec->private_dac_nids[i]) | 3092 | if (spec->private_dac_nids[i]) |
3087 | spec->multiout.num_dacs++; | 3093 | spec->multiout.num_dacs++; |
3088 | else | 3094 | else { |
3089 | memmove(spec->private_dac_nids + i, | 3095 | memmove(spec->private_dac_nids + i, |
3090 | spec->private_dac_nids + i + 1, | 3096 | spec->private_dac_nids + i + 1, |
3091 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); | 3097 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); |
3098 | spec->private_dac_nids[cfg->line_outs - 1] = 0; | ||
3099 | } | ||
3092 | } | 3100 | } |
3093 | 3101 | ||
3094 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3102 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
@@ -3107,9 +3115,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3107 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | 3115 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
3108 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, | 3116 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, |
3109 | spec->multiout.hp_out_nid); | 3117 | spec->multiout.hp_out_nid); |
3110 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) | 3118 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
3111 | alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, | 3119 | int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, |
3112 | spec->multiout.extra_out_nid); | 3120 | cfg->speaker_pins, |
3121 | spec->multiout.extra_out_nid); | ||
3122 | /* if no speaker volume is assigned, try again as the primary | ||
3123 | * output | ||
3124 | */ | ||
3125 | if (!err && cfg->speaker_outs > 0 && | ||
3126 | cfg->line_out_type == AUTO_PIN_HP_OUT) { | ||
3127 | cfg->hp_outs = cfg->line_outs; | ||
3128 | memcpy(cfg->hp_pins, cfg->line_out_pins, | ||
3129 | sizeof(cfg->hp_pins)); | ||
3130 | cfg->line_outs = cfg->speaker_outs; | ||
3131 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
3132 | sizeof(cfg->speaker_pins)); | ||
3133 | cfg->speaker_outs = 0; | ||
3134 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
3135 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | ||
3136 | redone = false; | ||
3137 | goto again; | ||
3138 | } | ||
3139 | } | ||
3113 | 3140 | ||
3114 | if (!spec->multi_ios && | 3141 | if (!spec->multi_ios && |
3115 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && | 3142 | cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && |
@@ -3287,7 +3314,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3287 | } | 3314 | } |
3288 | 3315 | ||
3289 | static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | 3316 | static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, |
3290 | hda_nid_t dac, const char *pfx) | 3317 | hda_nid_t dac, const char *pfx, |
3318 | int cidx) | ||
3291 | { | 3319 | { |
3292 | struct alc_spec *spec = codec->spec; | 3320 | struct alc_spec *spec = codec->spec; |
3293 | hda_nid_t sw, vol; | 3321 | hda_nid_t sw, vol; |
@@ -3303,15 +3331,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
3303 | if (is_ctl_used(spec->sw_ctls, val)) | 3331 | if (is_ctl_used(spec->sw_ctls, val)) |
3304 | return 0; /* already created */ | 3332 | return 0; /* already created */ |
3305 | mark_ctl_usage(spec->sw_ctls, val); | 3333 | mark_ctl_usage(spec->sw_ctls, val); |
3306 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); | 3334 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); |
3307 | } | 3335 | } |
3308 | 3336 | ||
3309 | sw = alc_look_for_out_mute_nid(codec, pin, dac); | 3337 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
3310 | vol = alc_look_for_out_vol_nid(codec, pin, dac); | 3338 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
3311 | err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); | 3339 | err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); |
3312 | if (err < 0) | 3340 | if (err < 0) |
3313 | return err; | 3341 | return err; |
3314 | err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); | 3342 | err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); |
3315 | if (err < 0) | 3343 | if (err < 0) |
3316 | return err; | 3344 | return err; |
3317 | return 0; | 3345 | return 0; |
@@ -3352,16 +3380,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, | |||
3352 | hda_nid_t dac = *dacs; | 3380 | hda_nid_t dac = *dacs; |
3353 | if (!dac) | 3381 | if (!dac) |
3354 | dac = spec->multiout.dac_nids[0]; | 3382 | dac = spec->multiout.dac_nids[0]; |
3355 | return alc_auto_create_extra_out(codec, *pins, dac, pfx); | 3383 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); |
3356 | } | 3384 | } |
3357 | 3385 | ||
3358 | if (dacs[num_pins - 1]) { | 3386 | if (dacs[num_pins - 1]) { |
3359 | /* OK, we have a multi-output system with individual volumes */ | 3387 | /* OK, we have a multi-output system with individual volumes */ |
3360 | for (i = 0; i < num_pins; i++) { | 3388 | for (i = 0; i < num_pins; i++) { |
3361 | snprintf(name, sizeof(name), "%s %s", | 3389 | if (num_pins >= 3) { |
3362 | pfx, channel_name[i]); | 3390 | snprintf(name, sizeof(name), "%s %s", |
3363 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | 3391 | pfx, channel_name[i]); |
3364 | name); | 3392 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], |
3393 | name, 0); | ||
3394 | } else { | ||
3395 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3396 | pfx, i); | ||
3397 | } | ||
3365 | if (err < 0) | 3398 | if (err < 0) |
3366 | return err; | 3399 | return err; |
3367 | } | 3400 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index d8d2f9dccd9b..eeb25d529e30 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -215,6 +215,7 @@ struct sigmatel_spec { | |||
215 | unsigned int gpio_mute; | 215 | unsigned int gpio_mute; |
216 | unsigned int gpio_led; | 216 | unsigned int gpio_led; |
217 | unsigned int gpio_led_polarity; | 217 | unsigned int gpio_led_polarity; |
218 | unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */ | ||
218 | unsigned int vref_led; | 219 | unsigned int vref_led; |
219 | 220 | ||
220 | /* stream */ | 221 | /* stream */ |
@@ -4318,12 +4319,10 @@ static void stac_store_hints(struct hda_codec *codec) | |||
4318 | spec->eapd_switch = val; | 4319 | spec->eapd_switch = val; |
4319 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); | 4320 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); |
4320 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | 4321 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { |
4321 | if (spec->gpio_led <= 8) { | 4322 | spec->gpio_mask |= spec->gpio_led; |
4322 | spec->gpio_mask |= spec->gpio_led; | 4323 | spec->gpio_dir |= spec->gpio_led; |
4323 | spec->gpio_dir |= spec->gpio_led; | 4324 | if (spec->gpio_led_polarity) |
4324 | if (spec->gpio_led_polarity) | 4325 | spec->gpio_data |= spec->gpio_led; |
4325 | spec->gpio_data |= spec->gpio_led; | ||
4326 | } | ||
4327 | } | 4326 | } |
4328 | } | 4327 | } |
4329 | 4328 | ||
@@ -4443,7 +4442,7 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4443 | /* power on when no jack detection is available */ | 4442 | /* power on when no jack detection is available */ |
4444 | /* or when the VREF is used for controlling LED */ | 4443 | /* or when the VREF is used for controlling LED */ |
4445 | if (!spec->hp_detect || | 4444 | if (!spec->hp_detect || |
4446 | (spec->gpio_led > 8 && spec->gpio_led == nid)) { | 4445 | spec->vref_mute_led_nid == nid) { |
4447 | stac_toggle_power_map(codec, nid, 1); | 4446 | stac_toggle_power_map(codec, nid, 1); |
4448 | continue; | 4447 | continue; |
4449 | } | 4448 | } |
@@ -4915,8 +4914,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) | |||
4915 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", | 4914 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", |
4916 | &spec->gpio_led_polarity, | 4915 | &spec->gpio_led_polarity, |
4917 | &spec->gpio_led) == 2) { | 4916 | &spec->gpio_led) == 2) { |
4918 | if (spec->gpio_led < 4) | 4917 | unsigned int max_gpio; |
4918 | max_gpio = snd_hda_param_read(codec, codec->afg, | ||
4919 | AC_PAR_GPIO_CAP); | ||
4920 | max_gpio &= AC_GPIO_IO_COUNT; | ||
4921 | if (spec->gpio_led < max_gpio) | ||
4919 | spec->gpio_led = 1 << spec->gpio_led; | 4922 | spec->gpio_led = 1 << spec->gpio_led; |
4923 | else | ||
4924 | spec->vref_mute_led_nid = spec->gpio_led; | ||
4920 | return 1; | 4925 | return 1; |
4921 | } | 4926 | } |
4922 | if (sscanf(dev->name, "HP_Mute_LED_%d", | 4927 | if (sscanf(dev->name, "HP_Mute_LED_%d", |
@@ -5045,15 +5050,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) | |||
5045 | struct sigmatel_spec *spec = codec->spec; | 5050 | struct sigmatel_spec *spec = codec->spec; |
5046 | 5051 | ||
5047 | /* sync mute LED */ | 5052 | /* sync mute LED */ |
5048 | if (spec->gpio_led) { | 5053 | if (spec->vref_mute_led_nid) |
5049 | if (spec->gpio_led <= 8) { | 5054 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5050 | stac_gpio_set(codec, spec->gpio_mask, | 5055 | spec->vref_led); |
5051 | spec->gpio_dir, spec->gpio_data); | 5056 | else if (spec->gpio_led) |
5052 | } else { | 5057 | stac_gpio_set(codec, spec->gpio_mask, |
5053 | stac_vrefout_set(codec, | 5058 | spec->gpio_dir, spec->gpio_data); |
5054 | spec->gpio_led, spec->vref_led); | ||
5055 | } | ||
5056 | } | ||
5057 | return 0; | 5059 | return 0; |
5058 | } | 5060 | } |
5059 | 5061 | ||
@@ -5064,7 +5066,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
5064 | struct sigmatel_spec *spec = codec->spec; | 5066 | struct sigmatel_spec *spec = codec->spec; |
5065 | 5067 | ||
5066 | if (power_state == AC_PWRST_D3) { | 5068 | if (power_state == AC_PWRST_D3) { |
5067 | if (spec->gpio_led > 8) { | 5069 | if (spec->vref_mute_led_nid) { |
5068 | /* with vref-out pin used for mute led control | 5070 | /* with vref-out pin used for mute led control |
5069 | * codec AFG is prevented from D3 state | 5071 | * codec AFG is prevented from D3 state |
5070 | */ | 5072 | */ |
@@ -5117,7 +5119,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) | |||
5117 | } | 5119 | } |
5118 | } | 5120 | } |
5119 | /*polarity defines *not* muted state level*/ | 5121 | /*polarity defines *not* muted state level*/ |
5120 | if (spec->gpio_led <= 8) { | 5122 | if (!spec->vref_mute_led_nid) { |
5121 | if (muted) | 5123 | if (muted) |
5122 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5124 | spec->gpio_data &= ~spec->gpio_led; /* orange */ |
5123 | else | 5125 | else |
@@ -5135,7 +5137,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) | |||
5135 | muted_lvl = spec->gpio_led_polarity ? | 5137 | muted_lvl = spec->gpio_led_polarity ? |
5136 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; | 5138 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; |
5137 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; | 5139 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; |
5138 | stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); | 5140 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5141 | spec->vref_led); | ||
5139 | } | 5142 | } |
5140 | return 0; | 5143 | return 0; |
5141 | } | 5144 | } |
@@ -5649,7 +5652,7 @@ again: | |||
5649 | 5652 | ||
5650 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5653 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5651 | if (spec->gpio_led) { | 5654 | if (spec->gpio_led) { |
5652 | if (spec->gpio_led <= 8) { | 5655 | if (!spec->vref_mute_led_nid) { |
5653 | spec->gpio_mask |= spec->gpio_led; | 5656 | spec->gpio_mask |= spec->gpio_led; |
5654 | spec->gpio_dir |= spec->gpio_led; | 5657 | spec->gpio_dir |= spec->gpio_led; |
5655 | spec->gpio_data |= spec->gpio_led; | 5658 | spec->gpio_data |= spec->gpio_led; |
@@ -5962,7 +5965,7 @@ again: | |||
5962 | 5965 | ||
5963 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5966 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5964 | if (spec->gpio_led) { | 5967 | if (spec->gpio_led) { |
5965 | if (spec->gpio_led <= 8) { | 5968 | if (!spec->vref_mute_led_nid) { |
5966 | spec->gpio_mask |= spec->gpio_led; | 5969 | spec->gpio_mask |= spec->gpio_led; |
5967 | spec->gpio_dir |= spec->gpio_led; | 5970 | spec->gpio_dir |= spec->gpio_led; |
5968 | spec->gpio_data |= spec->gpio_led; | 5971 | spec->gpio_data |= spec->gpio_led; |
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c index a391e622a192..28dfafb56dd1 100644 --- a/sound/pci/sis7019.c +++ b/sound/pci/sis7019.c | |||
@@ -41,6 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}"); | |||
41 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ | 41 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ |
42 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ | 42 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
43 | static int enable = 1; | 43 | static int enable = 1; |
44 | static int codecs = 1; | ||
44 | 45 | ||
45 | module_param(index, int, 0444); | 46 | module_param(index, int, 0444); |
46 | MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); | 47 | MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator."); |
@@ -48,6 +49,8 @@ module_param(id, charp, 0444); | |||
48 | MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); | 49 | MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator."); |
49 | module_param(enable, bool, 0444); | 50 | module_param(enable, bool, 0444); |
50 | MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); | 51 | MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator."); |
52 | module_param(codecs, int, 0444); | ||
53 | MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)"); | ||
51 | 54 | ||
52 | static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { | 55 | static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = { |
53 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, | 56 | { PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) }, |
@@ -140,6 +143,9 @@ struct sis7019 { | |||
140 | dma_addr_t silence_dma_addr; | 143 | dma_addr_t silence_dma_addr; |
141 | }; | 144 | }; |
142 | 145 | ||
146 | /* These values are also used by the module param 'codecs' to indicate | ||
147 | * which codecs should be present. | ||
148 | */ | ||
143 | #define SIS_PRIMARY_CODEC_PRESENT 0x0001 | 149 | #define SIS_PRIMARY_CODEC_PRESENT 0x0001 |
144 | #define SIS_SECONDARY_CODEC_PRESENT 0x0002 | 150 | #define SIS_SECONDARY_CODEC_PRESENT 0x0002 |
145 | #define SIS_TERTIARY_CODEC_PRESENT 0x0004 | 151 | #define SIS_TERTIARY_CODEC_PRESENT 0x0004 |
@@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1078 | { | 1084 | { |
1079 | unsigned long io = sis->ioport; | 1085 | unsigned long io = sis->ioport; |
1080 | void __iomem *ioaddr = sis->ioaddr; | 1086 | void __iomem *ioaddr = sis->ioaddr; |
1087 | unsigned long timeout; | ||
1081 | u16 status; | 1088 | u16 status; |
1082 | int count; | 1089 | int count; |
1083 | int i; | 1090 | int i; |
@@ -1104,21 +1111,45 @@ static int sis_chip_init(struct sis7019 *sis) | |||
1104 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) | 1111 | while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count) |
1105 | udelay(1); | 1112 | udelay(1); |
1106 | 1113 | ||
1114 | /* Command complete, we can let go of the semaphore now. | ||
1115 | */ | ||
1116 | outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); | ||
1117 | if (!count) | ||
1118 | return -EIO; | ||
1119 | |||
1107 | /* Now that we've finished the reset, find out what's attached. | 1120 | /* Now that we've finished the reset, find out what's attached. |
1121 | * There are some codec/board combinations that take an extremely | ||
1122 | * long time to come up. 350+ ms has been observed in the field, | ||
1123 | * so we'll give them up to 500ms. | ||
1108 | */ | 1124 | */ |
1109 | status = inl(io + SIS_AC97_STATUS); | 1125 | sis->codecs_present = 0; |
1110 | if (status & SIS_AC97_STATUS_CODEC_READY) | 1126 | timeout = msecs_to_jiffies(500) + jiffies; |
1111 | sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; | 1127 | while (time_before_eq(jiffies, timeout)) { |
1112 | if (status & SIS_AC97_STATUS_CODEC2_READY) | 1128 | status = inl(io + SIS_AC97_STATUS); |
1113 | sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; | 1129 | if (status & SIS_AC97_STATUS_CODEC_READY) |
1114 | if (status & SIS_AC97_STATUS_CODEC3_READY) | 1130 | sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT; |
1115 | sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; | 1131 | if (status & SIS_AC97_STATUS_CODEC2_READY) |
1116 | 1132 | sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT; | |
1117 | /* All done, let go of the semaphore, and check for errors | 1133 | if (status & SIS_AC97_STATUS_CODEC3_READY) |
1134 | sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT; | ||
1135 | |||
1136 | if (sis->codecs_present == codecs) | ||
1137 | break; | ||
1138 | |||
1139 | msleep(1); | ||
1140 | } | ||
1141 | |||
1142 | /* All done, check for errors. | ||
1118 | */ | 1143 | */ |
1119 | outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA); | 1144 | if (!sis->codecs_present) { |
1120 | if (!sis->codecs_present || !count) | 1145 | printk(KERN_ERR "sis7019: could not find any codecs\n"); |
1121 | return -EIO; | 1146 | return -EIO; |
1147 | } | ||
1148 | |||
1149 | if (sis->codecs_present != codecs) { | ||
1150 | printk(KERN_WARNING "sis7019: missing codecs, found %0x, expected %0x\n", | ||
1151 | sis->codecs_present, codecs); | ||
1152 | } | ||
1122 | 1153 | ||
1123 | /* Let the hardware know that the audio driver is alive, | 1154 | /* Let the hardware know that the audio driver is alive, |
1124 | * and enable PCM slots on the AC-link for L/R playback (3 & 4) and | 1155 | * and enable PCM slots on the AC-link for L/R playback (3 & 4) and |
@@ -1390,6 +1421,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci, | |||
1390 | if (!enable) | 1421 | if (!enable) |
1391 | goto error_out; | 1422 | goto error_out; |
1392 | 1423 | ||
1424 | /* The user can specify which codecs should be present so that we | ||
1425 | * can wait for them to show up if they are slow to recover from | ||
1426 | * the AC97 cold reset. We default to a single codec, the primary. | ||
1427 | * | ||
1428 | * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2. | ||
1429 | */ | ||
1430 | codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT | | ||
1431 | SIS_TERTIARY_CODEC_PRESENT; | ||
1432 | if (!codecs) | ||
1433 | codecs = SIS_PRIMARY_CODEC_PRESENT; | ||
1434 | |||
1393 | rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); | 1435 | rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card); |
1394 | if (rc < 0) | 1436 | if (rc < 0) |
1395 | goto error_out; | 1437 | goto error_out; |