diff options
author | Trent Piepho <xyzzy@speakeasy.org> | 2007-07-25 18:39:59 +0200 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 15:57:58 +0200 |
commit | 485100706b4b397f8072c756839878f634e21f85 (patch) | |
tree | fa17ce759c9a6d7108523006747af252e15f6b12 /sound/pci/ca0106/ca0106_main.c | |
parent | bddcf5411ffd17bfb86c2baed4a1b859c7071c98 (diff) |
[ALSA] ca0106: power down SPI DAC channels when not in use
For cards with an SPI DAC (SB Live 24-bit / Audigy SE), power down channels
0-2 when not in use. They are powered up on PCM open and down again on PCM
close. Channel 4 (== Front) is not powered down, as it is used for capture
feedback. Powering it down would effectively kill line in pass-through.
Signed-off-by: Trent Piepho <xyzzy@speakeasy.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/ca0106/ca0106_main.c')
-rw-r--r-- | sound/pci/ca0106/ca0106_main.c | 37 |
1 files changed, 35 insertions, 2 deletions
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 512fda946c6..36b7cdda7c4 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2004 James Courtier-Dutton <James@superbug.demon.co.uk> * Driver CA0106 chips. e.g. Sound Blaster Audigy LS and Live 24bit - * Version: 0.0.24 + * Version: 0.0.25 * * FEATURES currently supported: * Front, Rear and Center/LFE. @@ -81,6 +81,8 @@ * Implement support for Line-in capture on SB Live 24bit. * 0.0.24 * Add support for mute control on SB Live 24bit (cards w/ SPI DAC) + * 0.0.25 + * Powerdown SPI DAC channels when not in use * * BUGS: * Some stability problems when unloading the snd-ca0106 kernel module. @@ -458,6 +460,19 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) kfree(runtime->private_data); } +static const int spi_dacd_reg[] = { + [PCM_FRONT_CHANNEL] = SPI_DACD4_REG, + [PCM_REAR_CHANNEL] = SPI_DACD0_REG, + [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_REG, + [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_REG, +}; +static const int spi_dacd_bit[] = { + [PCM_FRONT_CHANNEL] = 1<<SPI_DACD4_BIT, + [PCM_REAR_CHANNEL] = 1<<SPI_DACD0_BIT, + [PCM_CENTER_LFE_CHANNEL]= 1<<SPI_DACD2_BIT, + [PCM_UNKNOWN_CHANNEL] = 1<<SPI_DACD1_BIT, +}; + /* open_playback callback */ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) @@ -492,6 +507,16 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr return err; if ((err = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 64)) < 0) return err; + + if (chip->details->spi_dac && channel_id != PCM_FRONT_CHANNEL) { + const int reg = spi_dacd_reg[channel_id]; + + /* Power up dac */ + chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; + err = snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); + if (err < 0) + return err; + } return 0; } @@ -502,6 +527,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_ca0106_pcm *epcm = runtime->private_data; chip->playback_channels[epcm->channel_id].use = 0; + + if (chip->details->spi_dac && epcm->channel_id != PCM_FRONT_CHANNEL) { + const int reg = spi_dacd_reg[epcm->channel_id]; + + /* Power down DAC */ + chip->spi_dac_reg[reg] |= spi_dacd_bit[epcm->channel_id]; + snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); + } /* FIXME: maybe zero others */ return 0; } @@ -1246,7 +1279,7 @@ static unsigned int spi_dac_init[] = { 0x0530, 0x0602, 0x0622, - 0x1400, + 0x140e, }; static unsigned int i2c_adc_init[][2] = { |