Commit f1a63a38 authored by Takashi Iwai's avatar Takashi Iwai Committed by Jaroslav Kysela
Browse files

[ALSA] ac97 - Suppress power-saving mode on non-supporting drivers



Don't enable power-saving mode on drivers that don't support
it.  The supporting drivers set AC97_SCAP_POWER_SAVE to scaps
at creation of ac97 instance.
Currently enable on the following drivers: intel8x0, intel8x0m,
atiixp, atiixp-modem, via82xx and via82xx-modem.
Also, a bit clean up of power-saving stuff:
- Don't create an own workq
- Remove superfluous ifdefs

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarJaroslav Kysela <perex@suse.cz>
parent 7cdbff94
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -375,6 +375,7 @@
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
#define AC97_SCAP_NO_SPDIF	(1<<9)	/* don't build SPDIF controls */
#define AC97_SCAP_EAPD_LED	(1<<10)	/* EAPD as mute LED */
#define AC97_SCAP_POWER_SAVE	(1<<11)	/* capable for aggresive power-saving */

/* ac97->flags */
#define AC97_HAS_PC_BEEP	(1<<0)	/* force PC Speaker usage */
@@ -511,7 +512,6 @@ struct snd_ac97 {

#ifdef CONFIG_SND_AC97_POWER_SAVE
	unsigned int power_up;	/* power states */
	struct workqueue_struct *power_workq;
	struct delayed_work power_work;
#endif
	struct device dev;
+21 −20
Original line number Diff line number Diff line
@@ -194,6 +194,13 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {


static void update_power_regs(struct snd_ac97 *ac97);
#ifdef CONFIG_SND_AC97_POWER_SAVE
#define ac97_is_power_save_mode(ac97) \
	((ac97->scaps & AC97_SCAP_POWER_SAVE) && power_save)
#else
#define ac97_is_power_save_mode(ac97) 0
#endif


/*
 *  I/O routines
@@ -982,8 +989,7 @@ static int snd_ac97_free(struct snd_ac97 *ac97)
{
	if (ac97) {
#ifdef CONFIG_SND_AC97_POWER_SAVE
		if (ac97->power_workq)
			destroy_workqueue(ac97->power_workq);
		cancel_delayed_work(&ac97->power_work);
#endif
		snd_ac97_proc_done(ac97);
		if (ac97->bus)
@@ -1989,7 +1995,6 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
	mutex_init(&ac97->reg_mutex);
	mutex_init(&ac97->page_mutex);
#ifdef CONFIG_SND_AC97_POWER_SAVE
	ac97->power_workq = create_workqueue("ac97");
	INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
#endif

@@ -2275,15 +2280,13 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97)
	udelay(100);
	power |= AC97_PD_PR2 | AC97_PD_PR3;	/* Analog Mixer powerdown */
	snd_ac97_write(ac97, AC97_POWERDOWN, power);
#ifdef CONFIG_SND_AC97_POWER_SAVE
	if (power_save) {
	if (ac97_is_power_save_mode(ac97)) {
		udelay(100);
		/* AC-link powerdown, internal Clk disable */
		/* FIXME: this may cause click noises on some boards */
		power |= AC97_PD_PR4 | AC97_PD_PR5;
		snd_ac97_write(ac97, AC97_POWERDOWN, power);
	}
#endif
}


@@ -2337,14 +2340,16 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
		}
	}

	if (power_save && !powerup && ac97->power_workq)
	if (ac97_is_power_save_mode(ac97) && !powerup)
		/* adjust power-down bits after two seconds delay
		 * (for avoiding loud click noises for many (OSS) apps
		 *  that open/close frequently)
		 */
		queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2);
	else
		schedule_delayed_work(&ac97->power_work, HZ*2);
	else {
		cancel_delayed_work(&ac97->power_work);
		update_power_regs(ac97);
	}

	return 0;
}
@@ -2357,11 +2362,6 @@ static void update_power_regs(struct snd_ac97 *ac97)
	unsigned int power_up, bits;
	int i;

#ifdef CONFIG_SND_AC97_POWER_SAVE
	if (power_save)
		power_up = ac97->power_up;
	else {
#endif
	power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
	power_up |= (1 << PWIDX_MIC);
	if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
@@ -2369,7 +2369,8 @@ static void update_power_regs(struct snd_ac97 *ac97)
	if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
		power_up |= (1 << PWIDX_CLFE);
#ifdef CONFIG_SND_AC97_POWER_SAVE
	}
	if (ac97_is_power_save_mode(ac97))
		power_up = ac97->power_up;
#endif
	if (power_up) {
		if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) {
+1 −1
Original line number Diff line number Diff line
@@ -1396,7 +1396,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
		ac97.private_data = chip;
		ac97.pci = chip->pci;
		ac97.num = i;
		ac97.scaps = AC97_SCAP_SKIP_MODEM;
		ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
		if (! chip->spdif_over_aclink)
			ac97.scaps |= AC97_SCAP_NO_SPDIF;
		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
+1 −1
Original line number Diff line number Diff line
@@ -1090,7 +1090,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
		ac97.private_data = chip;
		ac97.pci = chip->pci;
		ac97.num = i;
		ac97.scaps = AC97_SCAP_SKIP_AUDIO;
		ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
		if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
			chip->ac97[i] = NULL; /* to be sure */
			snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
+1 −1
Original line number Diff line number Diff line
@@ -2057,7 +2057,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
	memset(&ac97, 0, sizeof(ac97));
	ac97.private_data = chip;
	ac97.private_free = snd_intel8x0_mixer_free_ac97;
	ac97.scaps = AC97_SCAP_SKIP_MODEM;
	ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
	if (chip->xbox)
		ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
	if (chip->device_type != DEVICE_ALI) {
Loading