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.c120
1 files changed, 92 insertions, 28 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 799ba257090..dbffb5b5c69 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -2688,7 +2688,7 @@ static struct snd_kcontrol_new *
2688stac_control_new(struct sigmatel_spec *spec, 2688stac_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)
4160static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid, 4159static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
4161 int enable); 4160 int enable);
4162 4161
4162static 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 */
4164static void stac_store_hints(struct hda_codec *codec) 4178static 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
4193static int stac92xx_init(struct hda_codec *codec) 4210static int stac92xx_init(struct hda_codec *codec)
@@ -4372,18 +4389,8 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
4372static void stac92xx_shutup(struct hda_codec *codec) 4389static 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
5443static 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
5452static 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
5468static 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
5475static 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
5434static int patch_stac92hd71bxx(struct hda_codec *codec) 5489static 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;