diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/hda_intel.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 65 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 67 | ||||
-rw-r--r-- | sound/pci/sis7019.c | 64 |
4 files changed, 129 insertions, 68 deletions
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 096507d2ca9a..7d98240def0b 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -2508,7 +2508,6 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = { | |||
2508 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), | 2508 | SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB), |
2509 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), | 2509 | SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB), |
2510 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), | 2510 | SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB), |
2511 | SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB), | ||
2512 | SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), | 2511 | SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB), |
2513 | SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), | 2512 | SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB), |
2514 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), | 2513 | SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB), |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index cbde019d3d52..1d07e8fa2433 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -297,6 +297,8 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx, | |||
297 | imux = &spec->input_mux[mux_idx]; | 297 | imux = &spec->input_mux[mux_idx]; |
298 | if (!imux->num_items && mux_idx > 0) | 298 | if (!imux->num_items && mux_idx > 0) |
299 | imux = &spec->input_mux[0]; | 299 | imux = &spec->input_mux[0]; |
300 | if (!imux->num_items) | ||
301 | return 0; | ||
300 | 302 | ||
301 | if (idx >= imux->num_items) | 303 | if (idx >= imux->num_items) |
302 | idx = imux->num_items - 1; | 304 | idx = imux->num_items - 1; |
@@ -2629,6 +2631,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch, | |||
2629 | case AUTO_PIN_SPEAKER_OUT: | 2631 | case AUTO_PIN_SPEAKER_OUT: |
2630 | if (cfg->line_outs == 1) | 2632 | if (cfg->line_outs == 1) |
2631 | return "Speaker"; | 2633 | return "Speaker"; |
2634 | if (cfg->line_outs == 2) | ||
2635 | return ch ? "Bass Speaker" : "Speaker"; | ||
2632 | break; | 2636 | break; |
2633 | case AUTO_PIN_HP_OUT: | 2637 | case AUTO_PIN_HP_OUT: |
2634 | /* for multi-io case, only the primary out */ | 2638 | /* for multi-io case, only the primary out */ |
@@ -2902,7 +2906,7 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin) | |||
2902 | if (!nid) | 2906 | if (!nid) |
2903 | continue; | 2907 | continue; |
2904 | if (found_in_nid_list(nid, spec->multiout.dac_nids, | 2908 | if (found_in_nid_list(nid, spec->multiout.dac_nids, |
2905 | spec->multiout.num_dacs)) | 2909 | ARRAY_SIZE(spec->private_dac_nids))) |
2906 | continue; | 2910 | continue; |
2907 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, | 2911 | if (found_in_nid_list(nid, spec->multiout.hp_out_nid, |
2908 | ARRAY_SIZE(spec->multiout.hp_out_nid))) | 2912 | ARRAY_SIZE(spec->multiout.hp_out_nid))) |
@@ -2923,6 +2927,7 @@ static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin) | |||
2923 | return 0; | 2927 | return 0; |
2924 | } | 2928 | } |
2925 | 2929 | ||
2930 | /* return 0 if no possible DAC is found, 1 if one or more found */ | ||
2926 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | 2931 | static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, |
2927 | const hda_nid_t *pins, hda_nid_t *dacs) | 2932 | const hda_nid_t *pins, hda_nid_t *dacs) |
2928 | { | 2933 | { |
@@ -2940,7 +2945,7 @@ static int alc_auto_fill_extra_dacs(struct hda_codec *codec, int num_outs, | |||
2940 | if (!dacs[i]) | 2945 | if (!dacs[i]) |
2941 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); | 2946 | dacs[i] = alc_auto_look_for_dac(codec, pins[i]); |
2942 | } | 2947 | } |
2943 | return 0; | 2948 | return 1; |
2944 | } | 2949 | } |
2945 | 2950 | ||
2946 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, | 2951 | static int alc_auto_fill_multi_ios(struct hda_codec *codec, |
@@ -2950,7 +2955,7 @@ static int alc_auto_fill_multi_ios(struct hda_codec *codec, | |||
2950 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) | 2955 | static int alc_auto_fill_dac_nids(struct hda_codec *codec) |
2951 | { | 2956 | { |
2952 | struct alc_spec *spec = codec->spec; | 2957 | struct alc_spec *spec = codec->spec; |
2953 | const struct auto_pin_cfg *cfg = &spec->autocfg; | 2958 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2954 | bool redone = false; | 2959 | bool redone = false; |
2955 | int i; | 2960 | int i; |
2956 | 2961 | ||
@@ -2961,6 +2966,7 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
2961 | spec->multiout.extra_out_nid[0] = 0; | 2966 | spec->multiout.extra_out_nid[0] = 0; |
2962 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); | 2967 | memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids)); |
2963 | spec->multiout.dac_nids = spec->private_dac_nids; | 2968 | spec->multiout.dac_nids = spec->private_dac_nids; |
2969 | spec->multi_ios = 0; | ||
2964 | 2970 | ||
2965 | /* fill hard-wired DACs first */ | 2971 | /* fill hard-wired DACs first */ |
2966 | if (!redone) { | 2972 | if (!redone) { |
@@ -2994,10 +3000,12 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
2994 | for (i = 0; i < cfg->line_outs; i++) { | 3000 | for (i = 0; i < cfg->line_outs; i++) { |
2995 | if (spec->private_dac_nids[i]) | 3001 | if (spec->private_dac_nids[i]) |
2996 | spec->multiout.num_dacs++; | 3002 | spec->multiout.num_dacs++; |
2997 | else | 3003 | else { |
2998 | memmove(spec->private_dac_nids + i, | 3004 | memmove(spec->private_dac_nids + i, |
2999 | spec->private_dac_nids + i + 1, | 3005 | spec->private_dac_nids + i + 1, |
3000 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); | 3006 | sizeof(hda_nid_t) * (cfg->line_outs - i - 1)); |
3007 | spec->private_dac_nids[cfg->line_outs - 1] = 0; | ||
3008 | } | ||
3001 | } | 3009 | } |
3002 | 3010 | ||
3003 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { | 3011 | if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
@@ -3019,9 +3027,28 @@ static int alc_auto_fill_dac_nids(struct hda_codec *codec) | |||
3019 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) | 3027 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
3020 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, | 3028 | alc_auto_fill_extra_dacs(codec, cfg->hp_outs, cfg->hp_pins, |
3021 | spec->multiout.hp_out_nid); | 3029 | spec->multiout.hp_out_nid); |
3022 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) | 3030 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
3023 | alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, cfg->speaker_pins, | 3031 | int err = alc_auto_fill_extra_dacs(codec, cfg->speaker_outs, |
3024 | spec->multiout.extra_out_nid); | 3032 | cfg->speaker_pins, |
3033 | spec->multiout.extra_out_nid); | ||
3034 | /* if no speaker volume is assigned, try again as the primary | ||
3035 | * output | ||
3036 | */ | ||
3037 | if (!err && cfg->speaker_outs > 0 && | ||
3038 | cfg->line_out_type == AUTO_PIN_HP_OUT) { | ||
3039 | cfg->hp_outs = cfg->line_outs; | ||
3040 | memcpy(cfg->hp_pins, cfg->line_out_pins, | ||
3041 | sizeof(cfg->hp_pins)); | ||
3042 | cfg->line_outs = cfg->speaker_outs; | ||
3043 | memcpy(cfg->line_out_pins, cfg->speaker_pins, | ||
3044 | sizeof(cfg->speaker_pins)); | ||
3045 | cfg->speaker_outs = 0; | ||
3046 | memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins)); | ||
3047 | cfg->line_out_type = AUTO_PIN_SPEAKER_OUT; | ||
3048 | redone = false; | ||
3049 | goto again; | ||
3050 | } | ||
3051 | } | ||
3025 | 3052 | ||
3026 | return 0; | 3053 | return 0; |
3027 | } | 3054 | } |
@@ -3171,7 +3198,8 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3171 | } | 3198 | } |
3172 | 3199 | ||
3173 | static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | 3200 | static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, |
3174 | hda_nid_t dac, const char *pfx) | 3201 | hda_nid_t dac, const char *pfx, |
3202 | int cidx) | ||
3175 | { | 3203 | { |
3176 | struct alc_spec *spec = codec->spec; | 3204 | struct alc_spec *spec = codec->spec; |
3177 | hda_nid_t sw, vol; | 3205 | hda_nid_t sw, vol; |
@@ -3187,15 +3215,15 @@ static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
3187 | if (is_ctl_used(spec->sw_ctls, val)) | 3215 | if (is_ctl_used(spec->sw_ctls, val)) |
3188 | return 0; /* already created */ | 3216 | return 0; /* already created */ |
3189 | mark_ctl_usage(spec->sw_ctls, val); | 3217 | mark_ctl_usage(spec->sw_ctls, val); |
3190 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); | 3218 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val); |
3191 | } | 3219 | } |
3192 | 3220 | ||
3193 | sw = alc_look_for_out_mute_nid(codec, pin, dac); | 3221 | sw = alc_look_for_out_mute_nid(codec, pin, dac); |
3194 | vol = alc_look_for_out_vol_nid(codec, pin, dac); | 3222 | vol = alc_look_for_out_vol_nid(codec, pin, dac); |
3195 | err = alc_auto_add_stereo_vol(codec, pfx, 0, vol); | 3223 | err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol); |
3196 | if (err < 0) | 3224 | if (err < 0) |
3197 | return err; | 3225 | return err; |
3198 | err = alc_auto_add_stereo_sw(codec, pfx, 0, sw); | 3226 | err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw); |
3199 | if (err < 0) | 3227 | if (err < 0) |
3200 | return err; | 3228 | return err; |
3201 | return 0; | 3229 | return 0; |
@@ -3236,16 +3264,21 @@ static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins, | |||
3236 | hda_nid_t dac = *dacs; | 3264 | hda_nid_t dac = *dacs; |
3237 | if (!dac) | 3265 | if (!dac) |
3238 | dac = spec->multiout.dac_nids[0]; | 3266 | dac = spec->multiout.dac_nids[0]; |
3239 | return alc_auto_create_extra_out(codec, *pins, dac, pfx); | 3267 | return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0); |
3240 | } | 3268 | } |
3241 | 3269 | ||
3242 | if (dacs[num_pins - 1]) { | 3270 | if (dacs[num_pins - 1]) { |
3243 | /* OK, we have a multi-output system with individual volumes */ | 3271 | /* OK, we have a multi-output system with individual volumes */ |
3244 | for (i = 0; i < num_pins; i++) { | 3272 | for (i = 0; i < num_pins; i++) { |
3245 | snprintf(name, sizeof(name), "%s %s", | 3273 | if (num_pins >= 3) { |
3246 | pfx, channel_name[i]); | 3274 | snprintf(name, sizeof(name), "%s %s", |
3247 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | 3275 | pfx, channel_name[i]); |
3248 | name); | 3276 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], |
3277 | name, 0); | ||
3278 | } else { | ||
3279 | err = alc_auto_create_extra_out(codec, pins[i], dacs[i], | ||
3280 | pfx, i); | ||
3281 | } | ||
3249 | if (err < 0) | 3282 | if (err < 0) |
3250 | return err; | 3283 | return err; |
3251 | } | 3284 | } |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index f3658658548e..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 | ||
@@ -4441,7 +4440,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4441 | int pinctl, def_conf; | 4440 | int pinctl, def_conf; |
4442 | 4441 | ||
4443 | /* power on when no jack detection is available */ | 4442 | /* power on when no jack detection is available */ |
4444 | if (!spec->hp_detect) { | 4443 | /* or when the VREF is used for controlling LED */ |
4444 | if (!spec->hp_detect || | ||
4445 | spec->vref_mute_led_nid == nid) { | ||
4445 | stac_toggle_power_map(codec, nid, 1); | 4446 | stac_toggle_power_map(codec, nid, 1); |
4446 | continue; | 4447 | continue; |
4447 | } | 4448 | } |
@@ -4913,8 +4914,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) | |||
4913 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", | 4914 | if (sscanf(dev->name, "HP_Mute_LED_%d_%x", |
4914 | &spec->gpio_led_polarity, | 4915 | &spec->gpio_led_polarity, |
4915 | &spec->gpio_led) == 2) { | 4916 | &spec->gpio_led) == 2) { |
4916 | 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) | ||
4917 | 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; | ||
4918 | return 1; | 4925 | return 1; |
4919 | } | 4926 | } |
4920 | if (sscanf(dev->name, "HP_Mute_LED_%d", | 4927 | if (sscanf(dev->name, "HP_Mute_LED_%d", |
@@ -5043,29 +5050,12 @@ static int stac92xx_pre_resume(struct hda_codec *codec) | |||
5043 | struct sigmatel_spec *spec = codec->spec; | 5050 | struct sigmatel_spec *spec = codec->spec; |
5044 | 5051 | ||
5045 | /* sync mute LED */ | 5052 | /* sync mute LED */ |
5046 | if (spec->gpio_led) { | 5053 | if (spec->vref_mute_led_nid) |
5047 | if (spec->gpio_led <= 8) { | 5054 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5048 | stac_gpio_set(codec, spec->gpio_mask, | 5055 | spec->vref_led); |
5049 | spec->gpio_dir, spec->gpio_data); | 5056 | else if (spec->gpio_led) |
5050 | } else { | 5057 | stac_gpio_set(codec, spec->gpio_mask, |
5051 | stac_vrefout_set(codec, | 5058 | spec->gpio_dir, spec->gpio_data); |
5052 | spec->gpio_led, spec->vref_led); | ||
5053 | } | ||
5054 | } | ||
5055 | return 0; | ||
5056 | } | ||
5057 | |||
5058 | static int stac92xx_post_suspend(struct hda_codec *codec) | ||
5059 | { | ||
5060 | struct sigmatel_spec *spec = codec->spec; | ||
5061 | if (spec->gpio_led > 8) { | ||
5062 | /* with vref-out pin used for mute led control | ||
5063 | * codec AFG is prevented from D3 state, but on | ||
5064 | * system suspend it can (and should) be used | ||
5065 | */ | ||
5066 | snd_hda_codec_read(codec, codec->afg, 0, | ||
5067 | AC_VERB_SET_POWER_STATE, AC_PWRST_D3); | ||
5068 | } | ||
5069 | return 0; | 5059 | return 0; |
5070 | } | 5060 | } |
5071 | 5061 | ||
@@ -5076,7 +5066,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg, | |||
5076 | struct sigmatel_spec *spec = codec->spec; | 5066 | struct sigmatel_spec *spec = codec->spec; |
5077 | 5067 | ||
5078 | if (power_state == AC_PWRST_D3) { | 5068 | if (power_state == AC_PWRST_D3) { |
5079 | if (spec->gpio_led > 8) { | 5069 | if (spec->vref_mute_led_nid) { |
5080 | /* with vref-out pin used for mute led control | 5070 | /* with vref-out pin used for mute led control |
5081 | * codec AFG is prevented from D3 state | 5071 | * codec AFG is prevented from D3 state |
5082 | */ | 5072 | */ |
@@ -5129,7 +5119,7 @@ static int stac92xx_update_led_status(struct hda_codec *codec) | |||
5129 | } | 5119 | } |
5130 | } | 5120 | } |
5131 | /*polarity defines *not* muted state level*/ | 5121 | /*polarity defines *not* muted state level*/ |
5132 | if (spec->gpio_led <= 8) { | 5122 | if (!spec->vref_mute_led_nid) { |
5133 | if (muted) | 5123 | if (muted) |
5134 | spec->gpio_data &= ~spec->gpio_led; /* orange */ | 5124 | spec->gpio_data &= ~spec->gpio_led; /* orange */ |
5135 | else | 5125 | else |
@@ -5147,7 +5137,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec) | |||
5147 | muted_lvl = spec->gpio_led_polarity ? | 5137 | muted_lvl = spec->gpio_led_polarity ? |
5148 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; | 5138 | AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; |
5149 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; | 5139 | spec->vref_led = muted ? muted_lvl : notmtd_lvl; |
5150 | stac_vrefout_set(codec, spec->gpio_led, spec->vref_led); | 5140 | stac_vrefout_set(codec, spec->vref_mute_led_nid, |
5141 | spec->vref_led); | ||
5151 | } | 5142 | } |
5152 | return 0; | 5143 | return 0; |
5153 | } | 5144 | } |
@@ -5661,15 +5652,13 @@ again: | |||
5661 | 5652 | ||
5662 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5653 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5663 | if (spec->gpio_led) { | 5654 | if (spec->gpio_led) { |
5664 | if (spec->gpio_led <= 8) { | 5655 | if (!spec->vref_mute_led_nid) { |
5665 | spec->gpio_mask |= spec->gpio_led; | 5656 | spec->gpio_mask |= spec->gpio_led; |
5666 | spec->gpio_dir |= spec->gpio_led; | 5657 | spec->gpio_dir |= spec->gpio_led; |
5667 | spec->gpio_data |= spec->gpio_led; | 5658 | spec->gpio_data |= spec->gpio_led; |
5668 | } else { | 5659 | } else { |
5669 | codec->patch_ops.set_power_state = | 5660 | codec->patch_ops.set_power_state = |
5670 | stac92xx_set_power_state; | 5661 | stac92xx_set_power_state; |
5671 | codec->patch_ops.post_suspend = | ||
5672 | stac92xx_post_suspend; | ||
5673 | } | 5662 | } |
5674 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5663 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5675 | codec->patch_ops.check_power_status = | 5664 | codec->patch_ops.check_power_status = |
@@ -5976,15 +5965,13 @@ again: | |||
5976 | 5965 | ||
5977 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 5966 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
5978 | if (spec->gpio_led) { | 5967 | if (spec->gpio_led) { |
5979 | if (spec->gpio_led <= 8) { | 5968 | if (!spec->vref_mute_led_nid) { |
5980 | spec->gpio_mask |= spec->gpio_led; | 5969 | spec->gpio_mask |= spec->gpio_led; |
5981 | spec->gpio_dir |= spec->gpio_led; | 5970 | spec->gpio_dir |= spec->gpio_led; |
5982 | spec->gpio_data |= spec->gpio_led; | 5971 | spec->gpio_data |= spec->gpio_led; |
5983 | } else { | 5972 | } else { |
5984 | codec->patch_ops.set_power_state = | 5973 | codec->patch_ops.set_power_state = |
5985 | stac92xx_set_power_state; | 5974 | stac92xx_set_power_state; |
5986 | codec->patch_ops.post_suspend = | ||
5987 | stac92xx_post_suspend; | ||
5988 | } | 5975 | } |
5989 | codec->patch_ops.pre_resume = stac92xx_pre_resume; | 5976 | codec->patch_ops.pre_resume = stac92xx_pre_resume; |
5990 | codec->patch_ops.check_power_status = | 5977 | codec->patch_ops.check_power_status = |
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; |