diff options
Diffstat (limited to 'sound/pci')
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 66 |
1 files changed, 64 insertions, 2 deletions
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 80ba6c753c33..4f6dea23d8b2 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -342,6 +342,58 @@ static int alc_pin_mode_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v | |||
342 | .put = alc_pin_mode_put, \ | 342 | .put = alc_pin_mode_put, \ |
343 | .private_value = nid | (dir<<16) } | 343 | .private_value = nid | (dir<<16) } |
344 | 344 | ||
345 | /* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged | ||
346 | * together using a mask with more than one bit set. This control is | ||
347 | * currently used only by the ALC260 test model. At this stage they are not | ||
348 | * needed for any "production" models. | ||
349 | */ | ||
350 | #ifdef CONFIG_SND_DEBUG | ||
351 | static int alc_gpio_data_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) | ||
352 | { | ||
353 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
354 | uinfo->count = 1; | ||
355 | uinfo->value.integer.min = 0; | ||
356 | uinfo->value.integer.max = 1; | ||
357 | return 0; | ||
358 | } | ||
359 | static int alc_gpio_data_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
360 | { | ||
361 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
362 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
363 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
364 | long *valp = ucontrol->value.integer.value; | ||
365 | unsigned int val = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | ||
366 | |||
367 | *valp = (val & mask) != 0; | ||
368 | return 0; | ||
369 | } | ||
370 | static int alc_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | ||
371 | { | ||
372 | signed int change; | ||
373 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
374 | hda_nid_t nid = kcontrol->private_value & 0xffff; | ||
375 | unsigned char mask = (kcontrol->private_value >> 16) & 0xff; | ||
376 | long val = *ucontrol->value.integer.value; | ||
377 | unsigned int gpio_data = snd_hda_codec_read(codec,nid,0,AC_VERB_GET_GPIO_DATA,0x00); | ||
378 | |||
379 | /* Set/unset the masked GPIO bit(s) as needed */ | ||
380 | change = (val==0?0:mask) != (gpio_data & mask); | ||
381 | if (val==0) | ||
382 | gpio_data &= ~mask; | ||
383 | else | ||
384 | gpio_data |= mask; | ||
385 | snd_hda_codec_write(codec,nid,0,AC_VERB_SET_GPIO_DATA,gpio_data); | ||
386 | |||
387 | return change; | ||
388 | } | ||
389 | #define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \ | ||
390 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \ | ||
391 | .info = alc_gpio_data_info, \ | ||
392 | .get = alc_gpio_data_get, \ | ||
393 | .put = alc_gpio_data_put, \ | ||
394 | .private_value = nid | (mask<<16) } | ||
395 | #endif /* CONFIG_SND_DEBUG */ | ||
396 | |||
345 | /* | 397 | /* |
346 | * set up from the preset table | 398 | * set up from the preset table |
347 | */ | 399 | */ |
@@ -2874,11 +2926,21 @@ static struct snd_kcontrol_new alc260_test_mixer[] = { | |||
2874 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), | 2926 | HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT), |
2875 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), | 2927 | HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT), |
2876 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), | 2928 | HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT), |
2929 | |||
2930 | /* Controls for GPIO pins, assuming they are configured as outputs */ | ||
2931 | ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01), | ||
2932 | ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02), | ||
2933 | ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04), | ||
2934 | ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08), | ||
2935 | |||
2877 | { } /* end */ | 2936 | { } /* end */ |
2878 | }; | 2937 | }; |
2879 | static struct hda_verb alc260_test_init_verbs[] = { | 2938 | static struct hda_verb alc260_test_init_verbs[] = { |
2880 | /* Disable all GPIOs */ | 2939 | /* Enable all GPIOs as outputs with an initial value of 0 */ |
2881 | {0x01, AC_VERB_SET_GPIO_MASK, 0}, | 2940 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f}, |
2941 | {0x01, AC_VERB_SET_GPIO_DATA, 0x00}, | ||
2942 | {0x01, AC_VERB_SET_GPIO_MASK, 0x0f}, | ||
2943 | |||
2882 | /* Enable retasking pins as output, initially without power amp */ | 2944 | /* Enable retasking pins as output, initially without power amp */ |
2883 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2945 | {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |
2884 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, | 2946 | {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, |