aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_sigmatel.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r--sound/pci/hda/patch_sigmatel.c143
1 files changed, 106 insertions, 37 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index ec25262e59e7..6b0bc040c3b1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -93,6 +93,7 @@ enum {
93 STAC_92HD83XXX_REF, 93 STAC_92HD83XXX_REF,
94 STAC_92HD83XXX_PWR_REF, 94 STAC_92HD83XXX_PWR_REF,
95 STAC_DELL_S14, 95 STAC_DELL_S14,
96 STAC_92HD83XXX_HP,
96 STAC_92HD83XXX_MODELS 97 STAC_92HD83XXX_MODELS
97}; 98};
98 99
@@ -1085,7 +1086,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1085 if (!spec->auto_mic && spec->num_dmuxes > 0 && 1086 if (!spec->auto_mic && spec->num_dmuxes > 0 &&
1086 snd_hda_get_bool_hint(codec, "separate_dmux") == 1) { 1087 snd_hda_get_bool_hint(codec, "separate_dmux") == 1) {
1087 stac_dmux_mixer.count = spec->num_dmuxes; 1088 stac_dmux_mixer.count = spec->num_dmuxes;
1088 err = snd_hda_ctl_add(codec, 1089 err = snd_hda_ctl_add(codec, 0,
1089 snd_ctl_new1(&stac_dmux_mixer, codec)); 1090 snd_ctl_new1(&stac_dmux_mixer, codec));
1090 if (err < 0) 1091 if (err < 0)
1091 return err; 1092 return err;
@@ -1101,7 +1102,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1101 spec->spdif_mute = 1; 1102 spec->spdif_mute = 1;
1102 } 1103 }
1103 stac_smux_mixer.count = spec->num_smuxes; 1104 stac_smux_mixer.count = spec->num_smuxes;
1104 err = snd_hda_ctl_add(codec, 1105 err = snd_hda_ctl_add(codec, 0,
1105 snd_ctl_new1(&stac_smux_mixer, codec)); 1106 snd_ctl_new1(&stac_smux_mixer, codec));
1106 if (err < 0) 1107 if (err < 0)
1107 return err; 1108 return err;
@@ -1624,6 +1625,7 @@ static const char *stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
1624 [STAC_92HD83XXX_REF] = "ref", 1625 [STAC_92HD83XXX_REF] = "ref",
1625 [STAC_92HD83XXX_PWR_REF] = "mic-ref", 1626 [STAC_92HD83XXX_PWR_REF] = "mic-ref",
1626 [STAC_DELL_S14] = "dell-s14", 1627 [STAC_DELL_S14] = "dell-s14",
1628 [STAC_92HD83XXX_HP] = "hp",
1627}; 1629};
1628 1630
1629static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = { 1631static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1634,6 +1636,8 @@ static struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
1634 "DFI LanParty", STAC_92HD83XXX_REF), 1636 "DFI LanParty", STAC_92HD83XXX_REF),
1635 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba, 1637 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
1636 "unknown Dell", STAC_DELL_S14), 1638 "unknown Dell", STAC_DELL_S14),
1639 SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
1640 "HP", STAC_92HD83XXX_HP),
1637 {} /* terminator */ 1641 {} /* terminator */
1638}; 1642};
1639 1643
@@ -2648,6 +2652,7 @@ static int stac92xx_clfe_switch_put(struct snd_kcontrol *kcontrol,
2648enum { 2652enum {
2649 STAC_CTL_WIDGET_VOL, 2653 STAC_CTL_WIDGET_VOL,
2650 STAC_CTL_WIDGET_MUTE, 2654 STAC_CTL_WIDGET_MUTE,
2655 STAC_CTL_WIDGET_MUTE_BEEP,
2651 STAC_CTL_WIDGET_MONO_MUX, 2656 STAC_CTL_WIDGET_MONO_MUX,
2652 STAC_CTL_WIDGET_HP_SWITCH, 2657 STAC_CTL_WIDGET_HP_SWITCH,
2653 STAC_CTL_WIDGET_IO_SWITCH, 2658 STAC_CTL_WIDGET_IO_SWITCH,
@@ -2658,6 +2663,7 @@ enum {
2658static struct snd_kcontrol_new stac92xx_control_templates[] = { 2663static struct snd_kcontrol_new stac92xx_control_templates[] = {
2659 HDA_CODEC_VOLUME(NULL, 0, 0, 0), 2664 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
2660 HDA_CODEC_MUTE(NULL, 0, 0, 0), 2665 HDA_CODEC_MUTE(NULL, 0, 0, 0),
2666 HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0),
2661 STAC_MONO_MUX, 2667 STAC_MONO_MUX,
2662 STAC_CODEC_HP_SWITCH(NULL), 2668 STAC_CODEC_HP_SWITCH(NULL),
2663 STAC_CODEC_IO_SWITCH(NULL, 0), 2669 STAC_CODEC_IO_SWITCH(NULL, 0),
@@ -2669,7 +2675,8 @@ static struct snd_kcontrol_new stac92xx_control_templates[] = {
2669static struct snd_kcontrol_new * 2675static struct snd_kcontrol_new *
2670stac_control_new(struct sigmatel_spec *spec, 2676stac_control_new(struct sigmatel_spec *spec,
2671 struct snd_kcontrol_new *ktemp, 2677 struct snd_kcontrol_new *ktemp,
2672 const char *name) 2678 const char *name,
2679 hda_nid_t nid)
2673{ 2680{
2674 struct snd_kcontrol_new *knew; 2681 struct snd_kcontrol_new *knew;
2675 2682
@@ -2685,6 +2692,8 @@ stac_control_new(struct sigmatel_spec *spec,
2685 spec->kctls.alloced--; 2692 spec->kctls.alloced--;
2686 return NULL; 2693 return NULL;
2687 } 2694 }
2695 if (nid)
2696 knew->subdevice = HDA_SUBDEV_NID_FLAG | nid;
2688 return knew; 2697 return knew;
2689} 2698}
2690 2699
@@ -2693,7 +2702,8 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
2693 int idx, const char *name, 2702 int idx, const char *name,
2694 unsigned long val) 2703 unsigned long val)
2695{ 2704{
2696 struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name); 2705 struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name,
2706 get_amp_nid_(val));
2697 if (!knew) 2707 if (!knew)
2698 return -ENOMEM; 2708 return -ENOMEM;
2699 knew->index = idx; 2709 knew->index = idx;
@@ -2764,7 +2774,7 @@ static int stac92xx_add_input_source(struct sigmatel_spec *spec)
2764 if (!spec->num_adcs || imux->num_items <= 1) 2774 if (!spec->num_adcs || imux->num_items <= 1)
2765 return 0; /* no need for input source control */ 2775 return 0; /* no need for input source control */
2766 knew = stac_control_new(spec, &stac_input_src_temp, 2776 knew = stac_control_new(spec, &stac_input_src_temp,
2767 stac_input_src_temp.name); 2777 stac_input_src_temp.name, 0);
2768 if (!knew) 2778 if (!knew)
2769 return -ENOMEM; 2779 return -ENOMEM;
2770 knew->count = spec->num_adcs; 2780 knew->count = spec->num_adcs;
@@ -3221,11 +3231,14 @@ static int stac92xx_auto_create_beep_ctls(struct hda_codec *codec,
3221{ 3231{
3222 struct sigmatel_spec *spec = codec->spec; 3232 struct sigmatel_spec *spec = codec->spec;
3223 u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT); 3233 u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
3224 int err; 3234 int err, type = STAC_CTL_WIDGET_MUTE_BEEP;
3235
3236 if (spec->anabeep_nid == nid)
3237 type = STAC_CTL_WIDGET_MUTE;
3225 3238
3226 /* check for mute support for the the amp */ 3239 /* check for mute support for the the amp */
3227 if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) { 3240 if ((caps & AC_AMPCAP_MUTE) >> AC_AMPCAP_MUTE_SHIFT) {
3228 err = stac92xx_add_control(spec, STAC_CTL_WIDGET_MUTE, 3241 err = stac92xx_add_control(spec, type,
3229 "Beep Playback Switch", 3242 "Beep Playback Switch",
3230 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT)); 3243 HDA_COMPOSE_AMP_VAL(nid, 1, 0, HDA_OUTPUT));
3231 if (err < 0) 3244 if (err < 0)
@@ -3258,12 +3271,7 @@ static int stac92xx_dig_beep_switch_put(struct snd_kcontrol *kcontrol,
3258 struct snd_ctl_elem_value *ucontrol) 3271 struct snd_ctl_elem_value *ucontrol)
3259{ 3272{
3260 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 3273 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
3261 int enabled = !!ucontrol->value.integer.value[0]; 3274 return snd_hda_enable_beep_device(codec, ucontrol->value.integer.value[0]);
3262 if (codec->beep->enabled != enabled) {
3263 codec->beep->enabled = enabled;
3264 return 1;
3265 }
3266 return 0;
3267} 3275}
3268 3276
3269static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = { 3277static struct snd_kcontrol_new stac92xx_dig_beep_ctrl = {
@@ -3631,6 +3639,26 @@ static void stac92xx_auto_init_hp_out(struct hda_codec *codec)
3631 } 3639 }
3632} 3640}
3633 3641
3642static int is_dual_headphones(struct hda_codec *codec)
3643{
3644 struct sigmatel_spec *spec = codec->spec;
3645 int i, valid_hps;
3646
3647 if (spec->autocfg.line_out_type != AUTO_PIN_SPEAKER_OUT ||
3648 spec->autocfg.hp_outs <= 1)
3649 return 0;
3650 valid_hps = 0;
3651 for (i = 0; i < spec->autocfg.hp_outs; i++) {
3652 hda_nid_t nid = spec->autocfg.hp_pins[i];
3653 unsigned int cfg = snd_hda_codec_get_pincfg(codec, nid);
3654 if (get_defcfg_location(cfg) & AC_JACK_LOC_SEPARATE)
3655 continue;
3656 valid_hps++;
3657 }
3658 return (valid_hps > 1);
3659}
3660
3661
3634static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in) 3662static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
3635{ 3663{
3636 struct sigmatel_spec *spec = codec->spec; 3664 struct sigmatel_spec *spec = codec->spec;
@@ -3647,8 +3675,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
3647 /* If we have no real line-out pin and multiple hp-outs, HPs should 3675 /* If we have no real line-out pin and multiple hp-outs, HPs should
3648 * be set up as multi-channel outputs. 3676 * be set up as multi-channel outputs.
3649 */ 3677 */
3650 if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT && 3678 if (is_dual_headphones(codec)) {
3651 spec->autocfg.hp_outs > 1) {
3652 /* Copy hp_outs to line_outs, backup line_outs in 3679 /* Copy hp_outs to line_outs, backup line_outs in
3653 * speaker_outs so that the following routines can handle 3680 * speaker_outs so that the following routines can handle
3654 * HP pins as primary outputs. 3681 * HP pins as primary outputs.
@@ -4329,6 +4356,28 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
4329 snd_array_free(&spec->kctls); 4356 snd_array_free(&spec->kctls);
4330} 4357}
4331 4358
4359static void stac92xx_shutup(struct hda_codec *codec)
4360{
4361 struct sigmatel_spec *spec = codec->spec;
4362 int i;
4363 hda_nid_t nid;
4364
4365 /* reset each pin before powering down DAC/ADC to avoid click noise */
4366 nid = codec->start_nid;
4367 for (i = 0; i < codec->num_nodes; i++, nid++) {
4368 unsigned int wcaps = get_wcaps(codec, nid);
4369 unsigned int wid_type = get_wcaps_type(wcaps);
4370 if (wid_type == AC_WID_PIN)
4371 snd_hda_codec_read(codec, nid, 0,
4372 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
4373 }
4374
4375 if (spec->eapd_mask)
4376 stac_gpio_set(codec, spec->gpio_mask,
4377 spec->gpio_dir, spec->gpio_data &
4378 ~spec->eapd_mask);
4379}
4380
4332static void stac92xx_free(struct hda_codec *codec) 4381static void stac92xx_free(struct hda_codec *codec)
4333{ 4382{
4334 struct sigmatel_spec *spec = codec->spec; 4383 struct sigmatel_spec *spec = codec->spec;
@@ -4336,6 +4385,7 @@ static void stac92xx_free(struct hda_codec *codec)
4336 if (! spec) 4385 if (! spec)
4337 return; 4386 return;
4338 4387
4388 stac92xx_shutup(codec);
4339 stac92xx_free_jacks(codec); 4389 stac92xx_free_jacks(codec);
4340 snd_array_free(&spec->events); 4390 snd_array_free(&spec->events);
4341 4391
@@ -4386,12 +4436,16 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
4386 pin_ctl & ~flag); 4436 pin_ctl & ~flag);
4387} 4437}
4388 4438
4389static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid) 4439static inline int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
4390{ 4440{
4391 if (!nid) 4441 if (!nid)
4392 return 0; 4442 return 0;
4393 if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00) 4443 /* NOTE: we can't use snd_hda_jack_detect() here because STAC/IDT
4394 & (1 << 31)) 4444 * codecs behave wrongly when SET_PIN_SENSE is triggered, although
4445 * the pincap gives TRIG_REQ bit.
4446 */
4447 if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0) &
4448 AC_PINSENSE_PRESENCE)
4395 return 1; 4449 return 1;
4396 return 0; 4450 return 0;
4397} 4451}
@@ -4791,28 +4845,28 @@ static int stac92xx_hp_check_power_status(struct hda_codec *codec,
4791 4845
4792 return 0; 4846 return 0;
4793} 4847}
4794#endif
4795 4848
4796static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state) 4849static int idt92hd83xxx_hp_check_power_status(struct hda_codec *codec,
4850 hda_nid_t nid)
4797{ 4851{
4798 struct sigmatel_spec *spec = codec->spec; 4852 struct sigmatel_spec *spec = codec->spec;
4799 int i;
4800 hda_nid_t nid;
4801 4853
4802 /* reset each pin before powering down DAC/ADC to avoid click noise */ 4854 if (nid != 0x13)
4803 nid = codec->start_nid; 4855 return 0;
4804 for (i = 0; i < codec->num_nodes; i++, nid++) { 4856 if (snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & HDA_AMP_MUTE)
4805 unsigned int wcaps = get_wcaps(codec, nid); 4857 spec->gpio_data |= spec->gpio_led; /* mute LED on */
4806 unsigned int wid_type = get_wcaps_type(wcaps); 4858 else
4807 if (wid_type == AC_WID_PIN) 4859 spec->gpio_data &= ~spec->gpio_led; /* mute LED off */
4808 snd_hda_codec_read(codec, nid, 0, 4860 stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
4809 AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
4810 }
4811 4861
4812 if (spec->eapd_mask) 4862 return 0;
4813 stac_gpio_set(codec, spec->gpio_mask, 4863}
4814 spec->gpio_dir, spec->gpio_data & 4864
4815 ~spec->eapd_mask); 4865#endif
4866
4867static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
4868{
4869 stac92xx_shutup(codec);
4816 return 0; 4870 return 0;
4817} 4871}
4818#endif 4872#endif
@@ -4827,6 +4881,7 @@ static struct hda_codec_ops stac92xx_patch_ops = {
4827 .suspend = stac92xx_suspend, 4881 .suspend = stac92xx_suspend,
4828 .resume = stac92xx_resume, 4882 .resume = stac92xx_resume,
4829#endif 4883#endif
4884 .reboot_notify = stac92xx_shutup,
4830}; 4885};
4831 4886
4832static int patch_stac9200(struct hda_codec *codec) 4887static int patch_stac9200(struct hda_codec *codec)
@@ -5172,6 +5227,22 @@ again:
5172 break; 5227 break;
5173 } 5228 }
5174 5229
5230 codec->patch_ops = stac92xx_patch_ops;
5231
5232 if (spec->board_config == STAC_92HD83XXX_HP)
5233 spec->gpio_led = 0x01;
5234
5235#ifdef CONFIG_SND_HDA_POWER_SAVE
5236 if (spec->gpio_led) {
5237 spec->gpio_mask |= spec->gpio_led;
5238 spec->gpio_dir |= spec->gpio_led;
5239 spec->gpio_data |= spec->gpio_led;
5240 /* register check_power_status callback. */
5241 codec->patch_ops.check_power_status =
5242 idt92hd83xxx_hp_check_power_status;
5243 }
5244#endif
5245
5175 err = stac92xx_parse_auto_config(codec, 0x1d, 0); 5246 err = stac92xx_parse_auto_config(codec, 0x1d, 0);
5176 if (!err) { 5247 if (!err) {
5177 if (spec->board_config < 0) { 5248 if (spec->board_config < 0) {
@@ -5207,8 +5278,6 @@ again:
5207 snd_hda_codec_write_cache(codec, nid, 0, 5278 snd_hda_codec_write_cache(codec, nid, 0,
5208 AC_VERB_SET_CONNECT_SEL, num_dacs); 5279 AC_VERB_SET_CONNECT_SEL, num_dacs);
5209 5280
5210 codec->patch_ops = stac92xx_patch_ops;
5211
5212 codec->proc_widget_hook = stac92hd_proc_hook; 5281 codec->proc_widget_hook = stac92hd_proc_hook;
5213 5282
5214 return 0; 5283 return 0;