diff options
Diffstat (limited to 'sound/pci/hda/patch_sigmatel.c')
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 120 |
1 files changed, 92 insertions, 28 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 799ba2570902..dbffb5b5c69d 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -2688,7 +2688,7 @@ static struct snd_kcontrol_new * | |||
2688 | stac_control_new(struct sigmatel_spec *spec, | 2688 | stac_control_new(struct sigmatel_spec *spec, |
2689 | struct snd_kcontrol_new *ktemp, | 2689 | struct snd_kcontrol_new *ktemp, |
2690 | const char *name, | 2690 | const char *name, |
2691 | hda_nid_t nid) | 2691 | unsigned int subdev) |
2692 | { | 2692 | { |
2693 | struct snd_kcontrol_new *knew; | 2693 | struct snd_kcontrol_new *knew; |
2694 | 2694 | ||
@@ -2704,8 +2704,7 @@ stac_control_new(struct sigmatel_spec *spec, | |||
2704 | spec->kctls.alloced--; | 2704 | spec->kctls.alloced--; |
2705 | return NULL; | 2705 | return NULL; |
2706 | } | 2706 | } |
2707 | if (nid) | 2707 | knew->subdevice = subdev; |
2708 | knew->subdevice = HDA_SUBDEV_NID_FLAG | nid; | ||
2709 | return knew; | 2708 | return knew; |
2710 | } | 2709 | } |
2711 | 2710 | ||
@@ -2715,7 +2714,7 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec, | |||
2715 | unsigned long val) | 2714 | unsigned long val) |
2716 | { | 2715 | { |
2717 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, | 2716 | struct snd_kcontrol_new *knew = stac_control_new(spec, ktemp, name, |
2718 | get_amp_nid_(val)); | 2717 | HDA_SUBDEV_AMP_FLAG); |
2719 | if (!knew) | 2718 | if (!knew) |
2720 | return -ENOMEM; | 2719 | return -ENOMEM; |
2721 | knew->index = idx; | 2720 | knew->index = idx; |
@@ -4160,34 +4159,52 @@ static void stac92xx_power_down(struct hda_codec *codec) | |||
4160 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, | 4159 | static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, |
4161 | int enable); | 4160 | int enable); |
4162 | 4161 | ||
4162 | static inline int get_int_hint(struct hda_codec *codec, const char *key, | ||
4163 | int *valp) | ||
4164 | { | ||
4165 | const char *p; | ||
4166 | p = snd_hda_get_hint(codec, key); | ||
4167 | if (p) { | ||
4168 | unsigned long val; | ||
4169 | if (!strict_strtoul(p, 0, &val)) { | ||
4170 | *valp = val; | ||
4171 | return 1; | ||
4172 | } | ||
4173 | } | ||
4174 | return 0; | ||
4175 | } | ||
4176 | |||
4163 | /* override some hints from the hwdep entry */ | 4177 | /* override some hints from the hwdep entry */ |
4164 | static void stac_store_hints(struct hda_codec *codec) | 4178 | static void stac_store_hints(struct hda_codec *codec) |
4165 | { | 4179 | { |
4166 | struct sigmatel_spec *spec = codec->spec; | 4180 | struct sigmatel_spec *spec = codec->spec; |
4167 | const char *p; | ||
4168 | int val; | 4181 | int val; |
4169 | 4182 | ||
4170 | val = snd_hda_get_bool_hint(codec, "hp_detect"); | 4183 | val = snd_hda_get_bool_hint(codec, "hp_detect"); |
4171 | if (val >= 0) | 4184 | if (val >= 0) |
4172 | spec->hp_detect = val; | 4185 | spec->hp_detect = val; |
4173 | p = snd_hda_get_hint(codec, "gpio_mask"); | 4186 | if (get_int_hint(codec, "gpio_mask", &spec->gpio_mask)) { |
4174 | if (p) { | ||
4175 | spec->gpio_mask = simple_strtoul(p, NULL, 0); | ||
4176 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = | 4187 | spec->eapd_mask = spec->gpio_dir = spec->gpio_data = |
4177 | spec->gpio_mask; | 4188 | spec->gpio_mask; |
4178 | } | 4189 | } |
4179 | p = snd_hda_get_hint(codec, "gpio_dir"); | 4190 | if (get_int_hint(codec, "gpio_dir", &spec->gpio_dir)) |
4180 | if (p) | 4191 | spec->gpio_mask &= spec->gpio_mask; |
4181 | spec->gpio_dir = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4192 | if (get_int_hint(codec, "gpio_data", &spec->gpio_data)) |
4182 | p = snd_hda_get_hint(codec, "gpio_data"); | 4193 | spec->gpio_dir &= spec->gpio_mask; |
4183 | if (p) | 4194 | if (get_int_hint(codec, "eapd_mask", &spec->eapd_mask)) |
4184 | spec->gpio_data = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | 4195 | spec->eapd_mask &= spec->gpio_mask; |
4185 | p = snd_hda_get_hint(codec, "eapd_mask"); | 4196 | if (get_int_hint(codec, "gpio_mute", &spec->gpio_mute)) |
4186 | if (p) | 4197 | spec->gpio_mute &= spec->gpio_mask; |
4187 | spec->eapd_mask = simple_strtoul(p, NULL, 0) & spec->gpio_mask; | ||
4188 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); | 4198 | val = snd_hda_get_bool_hint(codec, "eapd_switch"); |
4189 | if (val >= 0) | 4199 | if (val >= 0) |
4190 | spec->eapd_switch = val; | 4200 | spec->eapd_switch = val; |
4201 | get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); | ||
4202 | if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { | ||
4203 | spec->gpio_mask |= spec->gpio_led; | ||
4204 | spec->gpio_dir |= spec->gpio_led; | ||
4205 | if (spec->gpio_led_polarity) | ||
4206 | spec->gpio_data |= spec->gpio_led; | ||
4207 | } | ||
4191 | } | 4208 | } |
4192 | 4209 | ||
4193 | static int stac92xx_init(struct hda_codec *codec) | 4210 | static int stac92xx_init(struct hda_codec *codec) |
@@ -4372,18 +4389,8 @@ static void stac92xx_free_kctls(struct hda_codec *codec) | |||
4372 | static void stac92xx_shutup(struct hda_codec *codec) | 4389 | static void stac92xx_shutup(struct hda_codec *codec) |
4373 | { | 4390 | { |
4374 | struct sigmatel_spec *spec = codec->spec; | 4391 | struct sigmatel_spec *spec = codec->spec; |
4375 | int i; | ||
4376 | hda_nid_t nid; | ||
4377 | 4392 | ||
4378 | /* reset each pin before powering down DAC/ADC to avoid click noise */ | 4393 | snd_hda_shutup_pins(codec); |
4379 | nid = codec->start_nid; | ||
4380 | for (i = 0; i < codec->num_nodes; i++, nid++) { | ||
4381 | unsigned int wcaps = get_wcaps(codec, nid); | ||
4382 | unsigned int wid_type = get_wcaps_type(wcaps); | ||
4383 | if (wid_type == AC_WID_PIN) | ||
4384 | snd_hda_codec_read(codec, nid, 0, | ||
4385 | AC_VERB_SET_PIN_WIDGET_CONTROL, 0); | ||
4386 | } | ||
4387 | 4394 | ||
4388 | if (spec->eapd_mask) | 4395 | if (spec->eapd_mask) |
4389 | stac_gpio_set(codec, spec->gpio_mask, | 4396 | stac_gpio_set(codec, spec->gpio_mask, |
@@ -5431,6 +5438,54 @@ static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | |||
5431 | return 0; | 5438 | return 0; |
5432 | } | 5439 | } |
5433 | 5440 | ||
5441 | /* HP dv7 bass switch - GPIO5 */ | ||
5442 | #define stac_hp_bass_gpio_info snd_ctl_boolean_mono_info | ||
5443 | static int stac_hp_bass_gpio_get(struct snd_kcontrol *kcontrol, | ||
5444 | struct snd_ctl_elem_value *ucontrol) | ||
5445 | { | ||
5446 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5447 | struct sigmatel_spec *spec = codec->spec; | ||
5448 | ucontrol->value.integer.value[0] = !!(spec->gpio_data & 0x20); | ||
5449 | return 0; | ||
5450 | } | ||
5451 | |||
5452 | static int stac_hp_bass_gpio_put(struct snd_kcontrol *kcontrol, | ||
5453 | struct snd_ctl_elem_value *ucontrol) | ||
5454 | { | ||
5455 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
5456 | struct sigmatel_spec *spec = codec->spec; | ||
5457 | unsigned int gpio_data; | ||
5458 | |||
5459 | gpio_data = (spec->gpio_data & ~0x20) | | ||
5460 | (ucontrol->value.integer.value[0] ? 0x20 : 0); | ||
5461 | if (gpio_data == spec->gpio_data) | ||
5462 | return 0; | ||
5463 | spec->gpio_data = gpio_data; | ||
5464 | stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data); | ||
5465 | return 1; | ||
5466 | } | ||
5467 | |||
5468 | static struct snd_kcontrol_new stac_hp_bass_sw_ctrl = { | ||
5469 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
5470 | .info = stac_hp_bass_gpio_info, | ||
5471 | .get = stac_hp_bass_gpio_get, | ||
5472 | .put = stac_hp_bass_gpio_put, | ||
5473 | }; | ||
5474 | |||
5475 | static int stac_add_hp_bass_switch(struct hda_codec *codec) | ||
5476 | { | ||
5477 | struct sigmatel_spec *spec = codec->spec; | ||
5478 | |||
5479 | if (!stac_control_new(spec, &stac_hp_bass_sw_ctrl, | ||
5480 | "Bass Speaker Playback Switch", 0)) | ||
5481 | return -ENOMEM; | ||
5482 | |||
5483 | spec->gpio_mask |= 0x20; | ||
5484 | spec->gpio_dir |= 0x20; | ||
5485 | spec->gpio_data |= 0x20; | ||
5486 | return 0; | ||
5487 | } | ||
5488 | |||
5434 | static int patch_stac92hd71bxx(struct hda_codec *codec) | 5489 | static int patch_stac92hd71bxx(struct hda_codec *codec) |
5435 | { | 5490 | { |
5436 | struct sigmatel_spec *spec; | 5491 | struct sigmatel_spec *spec; |
@@ -5674,6 +5729,15 @@ again: | |||
5674 | return err; | 5729 | return err; |
5675 | } | 5730 | } |
5676 | 5731 | ||
5732 | /* enable bass on HP dv7 */ | ||
5733 | if (spec->board_config == STAC_HP_DV5) { | ||
5734 | unsigned int cap; | ||
5735 | cap = snd_hda_param_read(codec, 0x1, AC_PAR_GPIO_CAP); | ||
5736 | cap &= AC_GPIO_IO_COUNT; | ||
5737 | if (cap >= 6) | ||
5738 | stac_add_hp_bass_switch(codec); | ||
5739 | } | ||
5740 | |||
5677 | codec->proc_widget_hook = stac92hd7x_proc_hook; | 5741 | codec->proc_widget_hook = stac92hd7x_proc_hook; |
5678 | 5742 | ||
5679 | return 0; | 5743 | return 0; |