Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f56c218 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
Loading
Loading
Loading
Loading
+3 −3
Original line number Original line Diff line number Diff line
@@ -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


	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);
+3 −3
Original line number Original line Diff line number Diff line
@@ -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)
		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)
							 * 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);


+5 −8
Original line number Original line Diff line number Diff line
@@ -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)
		/* -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)
			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)
							"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)
					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 */
+16 −13
Original line number Original line Diff line number Diff line
@@ -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)
		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)
				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)
	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)
	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)
	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)
	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)
					  (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)
	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)
	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)
		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)
	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)
#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);
+156 −43
Original line number Original line Diff line number Diff line
@@ -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,
	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,
{
{
	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,12 +4285,14 @@ 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)) {
		if (spec->gpio_led <= 8) {
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			if (spec->gpio_led_polarity)
			if (spec->gpio_led_polarity)
				spec->gpio_data |= spec->gpio_led;
				spec->gpio_data |= spec->gpio_led;
		}
		}
	}
	}
}


static int stac92xx_init(struct hda_codec *codec)
static int stac92xx_init(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,9 +4877,10 @@ 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) {
				if (spec->gpio_led < 4)
					spec->gpio_led = 1 << spec->gpio_led;
					spec->gpio_led = 1 << spec->gpio_led;
				return 1;
				return 1;
			}
			}
@@ -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)
	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)
{
{
	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,6 +5095,8 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
			muted = 0; /* extra output is not muted */
			muted = 0; /* extra output is not muted */
		}
		}
	}
	}
	/*polarity defines *not* muted state level*/
	if (spec->gpio_led <= 8) {
		if (muted)
		if (muted)
			spec->gpio_data &= ~spec->gpio_led; /* orange */
			spec->gpio_data &= ~spec->gpio_led; /* orange */
		else
		else
@@ -5008,8 +5106,16 @@ static int stac92xx_update_led_status(struct hda_codec *codec)
			/* 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,
	stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
				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);
	}
	return 0;
	return 0;
}
}


@@ -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 = {
#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 @@ again:


#ifdef CONFIG_SND_HDA_POWER_SAVE
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (spec->gpio_led) {
	if (spec->gpio_led) {
		if (spec->gpio_led <= 8) {
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			spec->gpio_data |= spec->gpio_led;
			spec->gpio_data |= spec->gpio_led;
		/* register check_power_status callback. */
		} 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 @@ again:


#ifdef CONFIG_SND_HDA_POWER_SAVE
#ifdef CONFIG_SND_HDA_POWER_SAVE
	if (spec->gpio_led) {
	if (spec->gpio_led) {
		if (spec->gpio_led <= 8) {
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_mask |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			spec->gpio_dir |= spec->gpio_led;
			spec->gpio_data |= spec->gpio_led;
			spec->gpio_data |= spec->gpio_led;
		/* register check_power_status callback. */
		} 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;
	}
	}