Commit 6f56c218 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6:
  sound: oss: rename local change_bits to avoid powerpc bitsops.h definition
  ALSA: hda - Fix duplicated DAC assignments for Realtek
  ALSA: asihpi - off by one in asihpi_hpi_ioctl()
  ALSA: hda - Fix Oops with Realtek quirks with NULL adc_nids
  ALSA: asihpi - bug fix pa use before init.
  ALSA: hda - Add support for vref-out based mute LED control on IDT codecs
parents 95b68865 8d34e6d3
...@@ -458,7 +458,7 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask) ...@@ -458,7 +458,7 @@ static int ad1848_set_recmask(ad1848_info * devc, int mask)
return mask; return mask;
} }
static void change_bits(ad1848_info * devc, unsigned char *regval, static void oss_change_bits(ad1848_info *devc, unsigned char *regval,
unsigned char *muteval, int dev, int chn, int newval) unsigned char *muteval, int dev, int chn, int newval)
{ {
unsigned char mask; unsigned char mask;
...@@ -516,10 +516,10 @@ static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int ...@@ -516,10 +516,10 @@ static void ad1848_mixer_set_channel(ad1848_info *devc, int dev, int value, int
if (muteregoffs != regoffs) { if (muteregoffs != regoffs) {
muteval = ad_read(devc, muteregoffs); muteval = ad_read(devc, muteregoffs);
change_bits(devc, &val, &muteval, dev, channel, value); oss_change_bits(devc, &val, &muteval, dev, channel, value);
} }
else else
change_bits(devc, &val, &val, dev, channel, value); oss_change_bits(devc, &val, &val, dev, channel, value);
spin_lock_irqsave(&devc->lock,flags); spin_lock_irqsave(&devc->lock,flags);
ad_write(devc, regoffs, val); ad_write(devc, regoffs, val);
......
...@@ -232,7 +232,7 @@ static int detect_mixer(sb_devc * devc) ...@@ -232,7 +232,7 @@ static int detect_mixer(sb_devc * devc)
return 1; return 1;
} }
static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval) static void oss_change_bits(sb_devc *devc, unsigned char *regval, int dev, int chn, int newval)
{ {
unsigned char mask; unsigned char mask;
int shift; int shift;
...@@ -284,7 +284,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right) ...@@ -284,7 +284,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
return -EINVAL; return -EINVAL;
val = sb_getmixer(devc, regoffs); val = sb_getmixer(devc, regoffs);
change_bits(devc, &val, dev, LEFT_CHN, left); oss_change_bits(devc, &val, dev, LEFT_CHN, left);
if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /* if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs) /*
* Change register * Change register
...@@ -304,7 +304,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right) ...@@ -304,7 +304,7 @@ int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
* Read the new one * Read the new one
*/ */
} }
change_bits(devc, &val, dev, RIGHT_CHN, right); oss_change_bits(devc, &val, dev, RIGHT_CHN, right);
sb_setmixer(devc, regoffs, val); sb_setmixer(devc, regoffs, val);
......
...@@ -107,7 +107,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -107,7 +107,6 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
union hpi_response_buffer_v1 *hr; union hpi_response_buffer_v1 *hr;
u16 res_max_size; u16 res_max_size;
u32 uncopied_bytes; u32 uncopied_bytes;
struct hpi_adapter *pa = NULL;
int err = 0; int err = 0;
if (cmd != HPI_IOCTL_LINUX) if (cmd != HPI_IOCTL_LINUX)
...@@ -182,8 +181,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -182,8 +181,9 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
/* -1=no data 0=read from user mem, 1=write to user mem */ /* -1=no data 0=read from user mem, 1=write to user mem */
int wrflag = -1; int wrflag = -1;
u32 adapter = hm->h.adapter_index; u32 adapter = hm->h.adapter_index;
struct hpi_adapter *pa = &adapters[adapter];
if ((adapter > HPI_MAX_ADAPTERS) || (!pa->type)) { if ((adapter >= HPI_MAX_ADAPTERS) || (!pa->type)) {
hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER, hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
HPI_ADAPTER_OPEN, HPI_ADAPTER_OPEN,
HPI_ERROR_BAD_ADAPTER_NUMBER); HPI_ERROR_BAD_ADAPTER_NUMBER);
...@@ -197,9 +197,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -197,9 +197,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
goto out; goto out;
} }
pa = &adapters[adapter]; if (mutex_lock_interruptible(&pa->mutex)) {
if (mutex_lock_interruptible(&adapters[adapter].mutex)) {
err = -EINTR; err = -EINTR;
goto out; goto out;
} }
...@@ -235,8 +233,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -235,8 +233,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
"stream buffer size %d\n", "stream buffer size %d\n",
size); size);
mutex_unlock(&adapters mutex_unlock(&pa->mutex);
[adapter].mutex);
err = -EINVAL; err = -EINVAL;
goto out; goto out;
} }
...@@ -277,7 +274,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -277,7 +274,7 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
uncopied_bytes, size); uncopied_bytes, size);
} }
mutex_unlock(&adapters[adapter].mutex); mutex_unlock(&pa->mutex);
} }
/* on return response size must be set */ /* on return response size must be set */
......
...@@ -895,13 +895,15 @@ static void alc_init_auto_hp(struct hda_codec *codec) ...@@ -895,13 +895,15 @@ static void alc_init_auto_hp(struct hda_codec *codec)
if (present == 3) if (present == 3)
spec->automute_hp_lo = 1; /* both HP and LO automute */ spec->automute_hp_lo = 1; /* both HP and LO automute */
if (!cfg->speaker_pins[0]) { if (!cfg->speaker_pins[0] &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
memcpy(cfg->speaker_pins, cfg->line_out_pins, memcpy(cfg->speaker_pins, cfg->line_out_pins,
sizeof(cfg->speaker_pins)); sizeof(cfg->speaker_pins));
cfg->speaker_outs = cfg->line_outs; cfg->speaker_outs = cfg->line_outs;
} }
if (!cfg->hp_pins[0]) { if (!cfg->hp_pins[0] &&
cfg->line_out_type == AUTO_PIN_HP_OUT) {
memcpy(cfg->hp_pins, cfg->line_out_pins, memcpy(cfg->hp_pins, cfg->line_out_pins,
sizeof(cfg->hp_pins)); sizeof(cfg->hp_pins));
cfg->hp_outs = cfg->line_outs; cfg->hp_outs = cfg->line_outs;
...@@ -920,6 +922,7 @@ static void alc_init_auto_hp(struct hda_codec *codec) ...@@ -920,6 +922,7 @@ static void alc_init_auto_hp(struct hda_codec *codec)
spec->automute_mode = ALC_AUTOMUTE_PIN; spec->automute_mode = ALC_AUTOMUTE_PIN;
} }
if (spec->automute && cfg->line_out_pins[0] && if (spec->automute && cfg->line_out_pins[0] &&
cfg->speaker_pins[0] &&
cfg->line_out_pins[0] != cfg->hp_pins[0] && cfg->line_out_pins[0] != cfg->hp_pins[0] &&
cfg->line_out_pins[0] != cfg->speaker_pins[0]) { cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
for (i = 0; i < cfg->line_outs; i++) { for (i = 0; i < cfg->line_outs; i++) {
...@@ -1911,7 +1914,7 @@ static int alc_build_controls(struct hda_codec *codec) ...@@ -1911,7 +1914,7 @@ static int alc_build_controls(struct hda_codec *codec)
return err; return err;
} }
} }
if (spec->cap_mixer) { if (spec->cap_mixer && spec->adc_nids) {
const char *kname = kctl ? kctl->id.name : NULL; const char *kname = kctl ? kctl->id.name : NULL;
for (knew = spec->cap_mixer; knew->name; knew++) { for (knew = spec->cap_mixer; knew->name; knew++) {
if (kname && strcmp(knew->name, kname) == 0) if (kname && strcmp(knew->name, kname) == 0)
...@@ -3677,7 +3680,7 @@ static int patch_alc880(struct hda_codec *codec) ...@@ -3677,7 +3680,7 @@ static int patch_alc880(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc880_presets[board_config]); setup_preset(codec, &alc880_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -3804,7 +3807,7 @@ static int patch_alc260(struct hda_codec *codec) ...@@ -3804,7 +3807,7 @@ static int patch_alc260(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc260_presets[board_config]); setup_preset(codec, &alc260_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -3983,7 +3986,7 @@ static int patch_alc882(struct hda_codec *codec) ...@@ -3983,7 +3986,7 @@ static int patch_alc882(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc882_presets[board_config]); setup_preset(codec, &alc882_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -4137,7 +4140,7 @@ static int patch_alc262(struct hda_codec *codec) ...@@ -4137,7 +4140,7 @@ static int patch_alc262(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc262_presets[board_config]); setup_preset(codec, &alc262_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -4293,7 +4296,7 @@ static int patch_alc268(struct hda_codec *codec) ...@@ -4293,7 +4296,7 @@ static int patch_alc268(struct hda_codec *codec)
(0 << AC_AMPCAP_MUTE_SHIFT)); (0 << AC_AMPCAP_MUTE_SHIFT));
} }
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -4705,7 +4708,7 @@ static int patch_alc269(struct hda_codec *codec) ...@@ -4705,7 +4708,7 @@ static int patch_alc269(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc269_presets[board_config]); setup_preset(codec, &alc269_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -4843,7 +4846,7 @@ static int patch_alc861(struct hda_codec *codec) ...@@ -4843,7 +4846,7 @@ static int patch_alc861(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc861_presets[board_config]); setup_preset(codec, &alc861_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -4984,7 +4987,7 @@ static int patch_alc861vd(struct hda_codec *codec) ...@@ -4984,7 +4987,7 @@ static int patch_alc861vd(struct hda_codec *codec)
add_verb(spec, alc660vd_eapd_verbs); add_verb(spec, alc660vd_eapd_verbs);
} }
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -5200,7 +5203,7 @@ static int patch_alc662(struct hda_codec *codec) ...@@ -5200,7 +5203,7 @@ static int patch_alc662(struct hda_codec *codec)
if (board_config != ALC_MODEL_AUTO) if (board_config != ALC_MODEL_AUTO)
setup_preset(codec, &alc662_presets[board_config]); setup_preset(codec, &alc662_presets[board_config]);
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
...@@ -5336,7 +5339,7 @@ static int patch_alc680(struct hda_codec *codec) ...@@ -5336,7 +5339,7 @@ static int patch_alc680(struct hda_codec *codec)
#endif #endif
} }
if (!spec->no_analog && !spec->adc_nids && spec->input_mux) { if (!spec->no_analog && !spec->adc_nids) {
alc_auto_fill_adc_caps(codec); alc_auto_fill_adc_caps(codec);
alc_rebuild_imux_for_auto_mic(codec); alc_rebuild_imux_for_auto_mic(codec);
alc_remove_invalid_adc_nids(codec); alc_remove_invalid_adc_nids(codec);
......
...@@ -213,6 +213,7 @@ struct sigmatel_spec { ...@@ -213,6 +213,7 @@ struct sigmatel_spec {
unsigned int gpio_mute; unsigned int gpio_mute;
unsigned int gpio_led; unsigned int gpio_led;
unsigned int gpio_led_polarity; unsigned int gpio_led_polarity;
unsigned int vref_led;
/* stream */ /* stream */
unsigned int stream_delay; unsigned int stream_delay;
...@@ -672,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol, ...@@ -672,6 +673,30 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
return 0; return 0;
} }
static int stac_vrefout_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
{
int error, pinctl;
snd_printdd("%s, nid %x ctl %x\n", __func__, nid, new_vref);
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
if (pinctl < 0)
return pinctl;
pinctl &= 0xff;
pinctl &= ~AC_PINCTL_VREFEN;
pinctl |= (new_vref & AC_PINCTL_VREFEN);
error = snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, pinctl);
if (error < 0)
return error;
return 1;
}
static unsigned int stac92xx_vref_set(struct hda_codec *codec, static unsigned int stac92xx_vref_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref) hda_nid_t nid, unsigned int new_vref)
{ {
...@@ -4069,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask, ...@@ -4069,6 +4094,8 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
{ {
unsigned int gpiostate, gpiomask, gpiodir; unsigned int gpiostate, gpiomask, gpiodir;
snd_printdd("%s msk %x dir %x gpio %x\n", __func__, mask, dir_mask, data);
gpiostate = snd_hda_codec_read(codec, codec->afg, 0, gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
AC_VERB_GET_GPIO_DATA, 0); AC_VERB_GET_GPIO_DATA, 0);
gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask); gpiostate = (gpiostate & ~dir_mask) | (data & dir_mask);
...@@ -4258,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec) ...@@ -4258,10 +4285,12 @@ static void stac_store_hints(struct hda_codec *codec)
spec->eapd_switch = val; spec->eapd_switch = val;
get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity); get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) { if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
spec->gpio_mask |= spec->gpio_led; if (spec->gpio_led <= 8) {
spec->gpio_dir |= spec->gpio_led; spec->gpio_mask |= spec->gpio_led;
if (spec->gpio_led_polarity) spec->gpio_dir |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led; if (spec->gpio_led_polarity)
spec->gpio_data |= spec->gpio_led;
}
} }
} }
...@@ -4431,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec) ...@@ -4431,11 +4460,26 @@ static void stac92xx_free_kctls(struct hda_codec *codec)
snd_array_free(&spec->kctls); snd_array_free(&spec->kctls);
} }
static void stac92xx_shutup_pins(struct hda_codec *codec)
{
unsigned int i, def_conf;
if (codec->bus->shutdown)
return;
for (i = 0; i < codec->init_pins.used; i++) {
struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
def_conf = snd_hda_codec_get_pincfg(codec, pin->nid);
if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
snd_hda_codec_write(codec, pin->nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0);
}
}
static void stac92xx_shutup(struct hda_codec *codec) static void stac92xx_shutup(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
snd_hda_shutup_pins(codec); stac92xx_shutup_pins(codec);
if (spec->eapd_mask) if (spec->eapd_mask)
stac_gpio_set(codec, spec->gpio_mask, stac_gpio_set(codec, spec->gpio_mask,
...@@ -4833,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity) ...@@ -4833,10 +4877,11 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) { if ((codec->subsystem_id >> 16) == PCI_VENDOR_ID_HP) {
while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING, while ((dev = dmi_find_device(DMI_DEV_TYPE_OEM_STRING,
NULL, dev))) { NULL, dev))) {
if (sscanf(dev->name, "HP_Mute_LED_%d_%d", if (sscanf(dev->name, "HP_Mute_LED_%d_%x",
&spec->gpio_led_polarity, &spec->gpio_led_polarity,
&spec->gpio_led) == 2) { &spec->gpio_led) == 2) {
spec->gpio_led = 1 << spec->gpio_led; if (spec->gpio_led < 4)
spec->gpio_led = 1 << spec->gpio_led;
return 1; return 1;
} }
if (sscanf(dev->name, "HP_Mute_LED_%d", if (sscanf(dev->name, "HP_Mute_LED_%d",
...@@ -4935,17 +4980,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer, ...@@ -4935,17 +4980,6 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
#endif #endif
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int stac92xx_pre_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
/* sync mute LED */
if (spec->gpio_led)
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data);
return 0;
}
static int stac92xx_resume(struct hda_codec *codec) static int stac92xx_resume(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
...@@ -4964,7 +4998,65 @@ static int stac92xx_resume(struct hda_codec *codec) ...@@ -4964,7 +4998,65 @@ static int stac92xx_resume(struct hda_codec *codec)
return 0; return 0;
} }
static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
{
stac92xx_shutup(codec);
return 0;
}
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
static int stac92xx_pre_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
/* sync mute LED */
if (spec->gpio_led) {
if (spec->gpio_led <= 8) {
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data);
} else {
stac_vrefout_set(codec,
spec->gpio_led, spec->vref_led);
}
}
return 0;
}
static int stac92xx_post_suspend(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
if (spec->gpio_led > 8) {
/* with vref-out pin used for mute led control
* codec AFG is prevented from D3 state, but on
* system suspend it can (and should) be used
*/
snd_hda_codec_read(codec, codec->afg, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
return 0;
}
static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
{
unsigned int afg_power_state = power_state;
struct sigmatel_spec *spec = codec->spec;
if (power_state == AC_PWRST_D3) {
if (spec->gpio_led > 8) {
/* with vref-out pin used for mute led control
* codec AFG is prevented from D3 state
*/
afg_power_state = AC_PWRST_D1;
}
/* this delay seems necessary to avoid click noise at power-down */
msleep(100);
}
snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE,
afg_power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
}
/* /*
* For this feature CONFIG_SND_HDA_POWER_SAVE is needed * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
* as mute LED state is updated in check_power_status hook * as mute LED state is updated in check_power_status hook
...@@ -4973,8 +5065,12 @@ static int stac92xx_update_led_status(struct hda_codec *codec) ...@@ -4973,8 +5065,12 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
{ {
struct sigmatel_spec *spec = codec->spec; struct sigmatel_spec *spec = codec->spec;
int i, num_ext_dacs, muted = 1; int i, num_ext_dacs, muted = 1;
unsigned int muted_lvl, notmtd_lvl;
hda_nid_t nid; hda_nid_t nid;
if (!spec->gpio_led)
return 0;
for (i = 0; i < spec->multiout.num_dacs; i++) { for (i = 0; i < spec->multiout.num_dacs; i++) {
nid = spec->multiout.dac_nids[i]; nid = spec->multiout.dac_nids[i];
if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) & if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
...@@ -4999,17 +5095,27 @@ static int stac92xx_update_led_status(struct hda_codec *codec) ...@@ -4999,17 +5095,27 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
muted = 0; /* extra output is not muted */ muted = 0; /* extra output is not muted */
} }
} }
if (muted) /*polarity defines *not* muted state level*/
spec->gpio_data &= ~spec->gpio_led; /* orange */ if (spec->gpio_led <= 8) {
else if (muted)
spec->gpio_data |= spec->gpio_led; /* white */ spec->gpio_data &= ~spec->gpio_led; /* orange */
else
spec->gpio_data |= spec->gpio_led; /* white */
if (!spec->gpio_led_polarity) { if (!spec->gpio_led_polarity) {
/* LED state is inverted on these systems */ /* LED state is inverted on these systems */
spec->gpio_data ^= spec->gpio_led; spec->gpio_data ^= spec->gpio_led;
}
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data);
} else {
notmtd_lvl = spec->gpio_led_polarity ?
AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
muted_lvl = spec->gpio_led_polarity ?
AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
spec->vref_led = muted ? muted_lvl : notmtd_lvl;
stac_vrefout_set(codec, spec->gpio_led, spec->vref_led);
} }
stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
return 0; return 0;
} }
...@@ -5023,13 +5129,7 @@ static int stac92xx_check_power_status(struct hda_codec *codec, ...@@ -5023,13 +5129,7 @@ static int stac92xx_check_power_status(struct hda_codec *codec,
return 0; return 0;
} }
#endif #endif /* CONFIG_SND_HDA_POWER_SAVE */
static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
{
stac92xx_shutup(codec);
return 0;
}
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
static const struct hda_codec_ops stac92xx_patch_ops = { static const struct hda_codec_ops stac92xx_patch_ops = {
...@@ -5041,7 +5141,6 @@ static const struct hda_codec_ops stac92xx_patch_ops = { ...@@ -5041,7 +5141,6 @@ static const struct hda_codec_ops stac92xx_patch_ops = {
#ifdef CONFIG_PM #ifdef CONFIG_PM
.suspend = stac92xx_suspend, .suspend = stac92xx_suspend,
.resume = stac92xx_resume, .resume = stac92xx_resume,
.pre_resume = stac92xx_pre_resume,
#endif #endif
.reboot_notify = stac92xx_shutup, .reboot_notify = stac92xx_shutup,
}; };
...@@ -5555,10 +5654,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) ...@@ -5555,10 +5654,17 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) { if (spec->gpio_led) {
spec->gpio_mask |= spec->gpio_led; if (spec->gpio_led <= 8) {
spec->gpio_dir |= spec->gpio_led; spec->gpio_mask |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led;
/* register check_power_status callback. */ spec->gpio_data |= spec->gpio_led;
} else {
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
codec->patch_ops.post_suspend =
stac92xx_post_suspend;
}
codec->patch_ops.pre_resume = stac92xx_pre_resume;
codec->patch_ops.check_power_status = codec->patch_ops.check_power_status =
stac92xx_check_power_status; stac92xx_check_power_status;
} }
...@@ -5883,10 +5989,17 @@ static int patch_stac92hd71bxx(struct hda_codec *codec) ...@@ -5883,10 +5989,17 @@ static int patch_stac92hd71bxx(struct hda_codec *codec)
#ifdef CONFIG_SND_HDA_POWER_SAVE #ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) { if (spec->gpio_led) {
spec->gpio_mask |= spec->gpio_led; if (spec->gpio_led <= 8) {
spec->gpio_dir |= spec->gpio_led; spec->gpio_mask |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led; spec->gpio_dir |= spec->gpio_led;
/* register check_power_status callback. */ spec->gpio_data |= spec->gpio_led;
} else {
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
codec->patch_ops.post_suspend =
stac92xx_post_suspend;
}
codec->patch_ops.pre_resume = stac92xx_pre_resume;
codec->patch_ops.check_power_status = codec->patch_ops.check_power_status =
stac92xx_check_power_status; stac92xx_check_power_status;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment