提交 f1a63a38 编写于 作者: T Takashi Iwai 提交者: Jaroslav Kysela

[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: NTakashi Iwai <tiwai@suse.de>
Signed-off-by: NJaroslav Kysela <perex@suse.cz>
上级 7cdbff94
...@@ -375,6 +375,7 @@ ...@@ -375,6 +375,7 @@
#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */ #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_NO_SPDIF (1<<9) /* don't build SPDIF controls */
#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */ #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 */ /* ac97->flags */
#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */ #define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
...@@ -511,7 +512,6 @@ struct snd_ac97 { ...@@ -511,7 +512,6 @@ struct snd_ac97 {
#ifdef CONFIG_SND_AC97_POWER_SAVE #ifdef CONFIG_SND_AC97_POWER_SAVE
unsigned int power_up; /* power states */ unsigned int power_up; /* power states */
struct workqueue_struct *power_workq;
struct delayed_work power_work; struct delayed_work power_work;
#endif #endif
struct device dev; struct device dev;
......
...@@ -194,6 +194,13 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = { ...@@ -194,6 +194,13 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
static void update_power_regs(struct snd_ac97 *ac97); 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 * I/O routines
...@@ -982,8 +989,7 @@ static int snd_ac97_free(struct snd_ac97 *ac97) ...@@ -982,8 +989,7 @@ static int snd_ac97_free(struct snd_ac97 *ac97)
{ {
if (ac97) { if (ac97) {
#ifdef CONFIG_SND_AC97_POWER_SAVE #ifdef CONFIG_SND_AC97_POWER_SAVE
if (ac97->power_workq) cancel_delayed_work(&ac97->power_work);
destroy_workqueue(ac97->power_workq);
#endif #endif
snd_ac97_proc_done(ac97); snd_ac97_proc_done(ac97);
if (ac97->bus) if (ac97->bus)
...@@ -1989,7 +1995,6 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template, ...@@ -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->reg_mutex);
mutex_init(&ac97->page_mutex); mutex_init(&ac97->page_mutex);
#ifdef CONFIG_SND_AC97_POWER_SAVE #ifdef CONFIG_SND_AC97_POWER_SAVE
ac97->power_workq = create_workqueue("ac97");
INIT_DELAYED_WORK(&ac97->power_work, do_update_power); INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
#endif #endif
...@@ -2275,15 +2280,13 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97) ...@@ -2275,15 +2280,13 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97)
udelay(100); udelay(100);
power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */ power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */
snd_ac97_write(ac97, AC97_POWERDOWN, power); snd_ac97_write(ac97, AC97_POWERDOWN, power);
#ifdef CONFIG_SND_AC97_POWER_SAVE if (ac97_is_power_save_mode(ac97)) {
if (power_save) {
udelay(100); udelay(100);
/* AC-link powerdown, internal Clk disable */ /* AC-link powerdown, internal Clk disable */
/* FIXME: this may cause click noises on some boards */ /* FIXME: this may cause click noises on some boards */
power |= AC97_PD_PR4 | AC97_PD_PR5; power |= AC97_PD_PR4 | AC97_PD_PR5;
snd_ac97_write(ac97, AC97_POWERDOWN, power); 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) ...@@ -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 /* adjust power-down bits after two seconds delay
* (for avoiding loud click noises for many (OSS) apps * (for avoiding loud click noises for many (OSS) apps
* that open/close frequently) * that open/close frequently)
*/ */
queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2); schedule_delayed_work(&ac97->power_work, HZ*2);
else else {
cancel_delayed_work(&ac97->power_work);
update_power_regs(ac97); update_power_regs(ac97);
}
return 0; return 0;
} }
...@@ -2357,19 +2362,15 @@ static void update_power_regs(struct snd_ac97 *ac97) ...@@ -2357,19 +2362,15 @@ static void update_power_regs(struct snd_ac97 *ac97)
unsigned int power_up, bits; unsigned int power_up, bits;
int i; int i;
power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
power_up |= (1 << PWIDX_MIC);
if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
power_up |= (1 << PWIDX_SURR);
if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
power_up |= (1 << PWIDX_CLFE);
#ifdef CONFIG_SND_AC97_POWER_SAVE #ifdef CONFIG_SND_AC97_POWER_SAVE
if (power_save) if (ac97_is_power_save_mode(ac97))
power_up = ac97->power_up; 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)
power_up |= (1 << PWIDX_SURR);
if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
power_up |= (1 << PWIDX_CLFE);
#ifdef CONFIG_SND_AC97_POWER_SAVE
}
#endif #endif
if (power_up) { if (power_up) {
if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) { if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) {
......
...@@ -1396,7 +1396,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock, ...@@ -1396,7 +1396,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
ac97.private_data = chip; ac97.private_data = chip;
ac97.pci = chip->pci; ac97.pci = chip->pci;
ac97.num = i; ac97.num = i;
ac97.scaps = AC97_SCAP_SKIP_MODEM; ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
if (! chip->spdif_over_aclink) if (! chip->spdif_over_aclink)
ac97.scaps |= AC97_SCAP_NO_SPDIF; ac97.scaps |= AC97_SCAP_NO_SPDIF;
if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
......
...@@ -1090,7 +1090,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock) ...@@ -1090,7 +1090,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
ac97.private_data = chip; ac97.private_data = chip;
ac97.pci = chip->pci; ac97.pci = chip->pci;
ac97.num = i; 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) { if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
chip->ac97[i] = NULL; /* to be sure */ chip->ac97[i] = NULL; /* to be sure */
snd_printdd("atiixp-modem: codec %d not available for modem\n", i); snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
......
...@@ -2057,7 +2057,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, ...@@ -2057,7 +2057,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
memset(&ac97, 0, sizeof(ac97)); memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip; ac97.private_data = chip;
ac97.private_free = snd_intel8x0_mixer_free_ac97; 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) if (chip->xbox)
ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR; ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
if (chip->device_type != DEVICE_ALI) { if (chip->device_type != DEVICE_ALI) {
......
...@@ -830,7 +830,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock) ...@@ -830,7 +830,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
memset(&ac97, 0, sizeof(ac97)); memset(&ac97, 0, sizeof(ac97));
ac97.private_data = chip; ac97.private_data = chip;
ac97.private_free = snd_intel8x0_mixer_free_ac97; ac97.private_free = snd_intel8x0_mixer_free_ac97;
ac97.scaps = AC97_SCAP_SKIP_AUDIO; ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
glob_sta = igetdword(chip, ICHREG(GLOB_STA)); glob_sta = igetdword(chip, ICHREG(GLOB_STA));
......
...@@ -1823,7 +1823,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui ...@@ -1823,7 +1823,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui
ac97.private_data = chip; ac97.private_data = chip;
ac97.private_free = snd_via82xx_mixer_free_ac97; ac97.private_free = snd_via82xx_mixer_free_ac97;
ac97.pci = chip->pci; ac97.pci = chip->pci;
ac97.scaps = AC97_SCAP_SKIP_MODEM; ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
return err; return err;
......
...@@ -900,7 +900,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip) ...@@ -900,7 +900,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
ac97.private_data = chip; ac97.private_data = chip;
ac97.private_free = snd_via82xx_mixer_free_ac97; ac97.private_free = snd_via82xx_mixer_free_ac97;
ac97.pci = chip->pci; ac97.pci = chip->pci;
ac97.scaps = AC97_SCAP_SKIP_AUDIO; ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
ac97.num = chip->ac97_secondary; ac97.num = chip->ac97_secondary;
if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册