[alsa-devel] [PATCH - ca0106 1/6] ALSA: ca0106 - add Sound Blaster 5.1vx info.
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 8e69620..6dc9a5d 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -239,6 +239,16 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .gpio_type = 1, .i2c_adc = 1, .spi_dac = 1 } , + /* Sound Blaster 5.1vx + * Tested: Playback on front, rear, center/lfe speakers + * Not-Tested: Capture + */ + { .serial = 0x10041102, + .name = "Sound Blaster 5.1vx [SB1070]", + .gpio_type = 1, + .i2c_adc = 0, + .spi_dac = 1 + } , /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ /* SB0438 * CTRL:CA0106-DAT
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 6dc9a5d..22d2f6b 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -514,6 +514,23 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) } }
+static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id, + int power) +{ + if (chip->details->spi_dac) { + const int reg = spi_dacd_reg[channel_id]; + + if (power) + /* Power up */ + chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; + else + /* Power down */ + chip->spi_dac_reg[reg] |= spi_dacd_bit[channel_id]; + return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); + } + return 0; +} + /* open_playback callback */ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substream, int channel_id) @@ -553,12 +570,9 @@ static int snd_ca0106_pcm_open_playback_channel(struct snd_pcm_substream *substr return err; snd_pcm_set_sync(substream);
- 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]); + /* Front channel dac should already be on */ + if (channel_id != PCM_FRONT_CHANNEL) { + err = snd_ca0106_pcm_power_dac(chip, channel_id, 1); if (err < 0) return err; } @@ -578,13 +592,14 @@ static int snd_ca0106_pcm_close_playback(struct snd_pcm_substream *substream)
restore_spdif_bits(chip, epcm->channel_id);
- 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]); + /* Front channel dac should stay on */ + if (epcm->channel_id != PCM_FRONT_CHANNEL) { + int err; + err = snd_ca0106_pcm_power_dac(chip, epcm->channel_id, 0); + if (err < 0) + return err; } + /* FIXME: maybe zero others */ return 0; }
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 22d2f6b..46ae98d 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -1385,7 +1385,7 @@ static unsigned int spi_dac_init[] = { SPI_REG(12, 0x00), SPI_REG(SPI_LDA4_REG, SPI_DA_BIT_0dB), SPI_REG(SPI_RDA4_REG, SPI_DA_BIT_0dB | SPI_DA_BIT_UPDATE), - SPI_REG(SPI_DACD4_REG, 0x00), + SPI_REG(SPI_DACD4_REG, SPI_DACD4_BIT), };
static unsigned int i2c_adc_init[][2] = { @@ -1576,6 +1576,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) if (reg < ARRAY_SIZE(chip->spi_dac_reg)) chip->spi_dac_reg[reg] = spi_dac_init[n]; } + + /* Enable front dac only */ + snd_ca0106_pcm_power_dac(chip, PCM_FRONT_CHANNEL, 1); } }
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 46ae98d..da91003 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -493,16 +493,18 @@ static void snd_ca0106_pcm_free_substream(struct snd_pcm_runtime *runtime) }
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, + SPI_DACD0_REG, + SPI_DACD1_REG, + SPI_DACD2_REG, + 0, + SPI_DACD4_REG, }; static const int spi_dacd_bit[] = { - [PCM_FRONT_CHANNEL] = SPI_DACD4_BIT, - [PCM_REAR_CHANNEL] = SPI_DACD0_BIT, - [PCM_CENTER_LFE_CHANNEL]= SPI_DACD2_BIT, - [PCM_UNKNOWN_CHANNEL] = SPI_DACD1_BIT, + SPI_DACD0_BIT, + SPI_DACD1_BIT, + SPI_DACD2_BIT, + 0, + SPI_DACD4_BIT, };
static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) @@ -514,18 +516,34 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx) } }
+static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, + int channel_id) +{ + switch (channel_id) { + case PCM_FRONT_CHANNEL: return 4; + case PCM_REAR_CHANNEL: return 0; + case PCM_CENTER_LFE_CHANNEL: return 2; + case PCM_UNKNOWN_CHANNEL: return 1; + } + snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", channel_id); + return 0; +} + static int snd_ca0106_pcm_power_dac(struct snd_ca0106 *chip, int channel_id, int power) { if (chip->details->spi_dac) { - const int reg = spi_dacd_reg[channel_id]; + const int dac = snd_ca0106_channel_dac(chip->details, + channel_id); + const int reg = spi_dacd_reg[dac]; + const int bit = spi_dacd_bit[dac];
if (power) /* Power up */ - chip->spi_dac_reg[reg] &= ~spi_dacd_bit[channel_id]; + chip->spi_dac_reg[reg] &= ~bit; else /* Power down */ - chip->spi_dac_reg[reg] |= spi_dacd_bit[channel_id]; + chip->spi_dac_reg[reg] |= bit; return snd_ca0106_spi_write(chip, chip->spi_dac_reg[reg]); } return 0;
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h index 14b8d9a..f19c110 100644 --- a/sound/pci/ca0106/ca0106.h +++ b/sound/pci/ca0106/ca0106.h @@ -670,8 +670,9 @@ struct snd_ca0106_details { gpio_type = 2 -> shared side-out/line-in. */ int i2c_adc; /* with i2c_adc=1, the driver adds some capture volume controls, phone, mic, line-in and aux. */ - int spi_dac; /* spi_dac=1 adds the mute switch for each analog - output, front, rear, etc. */ + u16 spi_dac; /* spi_dac = 0 -> no spi interface for DACs + spi_dac = 0x<front><rear><center-lfe><side> + -> specifies DAC id for each channel pair. */ };
// definition of the chip-specific record diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index da91003..d2d12c0 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -227,7 +227,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "Audigy SE [SB0570]", .gpio_type = 1, .i2c_adc = 1, - .spi_dac = 1 } , + .spi_dac = 0x4021 } , /* New Audigy LS. Has a different DAC. */ /* SB0570: * CTRL:CA0106-DAT @@ -238,7 +238,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "Audigy SE OEM [SB0570a]", .gpio_type = 1, .i2c_adc = 1, - .spi_dac = 1 } , + .spi_dac = 0x4021 } , /* Sound Blaster 5.1vx * Tested: Playback on front, rear, center/lfe speakers * Not-Tested: Capture @@ -247,7 +247,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "Sound Blaster 5.1vx [SB1070]", .gpio_type = 1, .i2c_adc = 0, - .spi_dac = 1 + .spi_dac = 0x0124 } , /* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ /* SB0438 @@ -264,7 +264,7 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .name = "MSI K8N Diamond MB", .gpio_type = 2, .i2c_adc = 1, - .spi_dac = 1 } , + .spi_dac = 0x4021 } , /* Giga-byte GA-G1975X mobo * Novell bnc#395807 */ @@ -520,12 +520,18 @@ static int snd_ca0106_channel_dac(struct snd_ca0106_details *details, int channel_id) { switch (channel_id) { - case PCM_FRONT_CHANNEL: return 4; - case PCM_REAR_CHANNEL: return 0; - case PCM_CENTER_LFE_CHANNEL: return 2; - case PCM_UNKNOWN_CHANNEL: return 1; + case PCM_FRONT_CHANNEL: + return (details->spi_dac & 0xf000) >> (4 * 3); + case PCM_REAR_CHANNEL: + return (details->spi_dac & 0x0f00) >> (4 * 2); + case PCM_CENTER_LFE_CHANNEL: + return (details->spi_dac & 0x00f0) >> (4 * 1); + case PCM_UNKNOWN_CHANNEL: + return (details->spi_dac & 0x000f) >> (4 * 0); + default: + snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", + channel_id); } - snd_printk(KERN_DEBUG "ca0106: unknown channel_id %d\n", channel_id); return 0; }
@@ -1582,7 +1588,7 @@ static void ca0106_init_chip(struct snd_ca0106 *chip, int resume) /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */ }
- if (chip->details->spi_dac == 1) { + if (chip->details->spi_dac) { /* The SB0570 use SPI to control DAC. */ int size, n;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index 85fd315..b522401 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -832,7 +832,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) if (err < 0) return err; } - if (emu->details->spi_dac == 1) + if (emu->details->spi_dac) ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls);
/* Create virtual master controls */ @@ -845,7 +845,7 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) return err; add_slaves(card, vmaster, slave_vols);
- if (emu->details->spi_dac == 1) { + if (emu->details->spi_dac) { vmaster = snd_ctl_make_virtual_master("Master Playback Switch", NULL); if (!vmaster)
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c index b522401..630aa49 100644 --- a/sound/pci/ca0106/ca0106_mixer.c +++ b/sound/pci/ca0106/ca0106_mixer.c @@ -676,28 +676,65 @@ static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = I2C_VOLUME("Aux Capture Volume", 3), };
-#define SPI_SWITCH(xname,reg,bit) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = spi_mute_info, \ - .get = spi_mute_get, \ - .put = spi_mute_put, \ - .private_value = (reg<<SPI_REG_SHIFT) | (bit) \ -} - -static struct snd_kcontrol_new snd_ca0106_volume_spi_dac_ctls[] -__devinitdata = { - SPI_SWITCH("Analog Front Playback Switch", - SPI_DMUTE4_REG, SPI_DMUTE4_BIT), - SPI_SWITCH("Analog Rear Playback Switch", - SPI_DMUTE0_REG, SPI_DMUTE0_BIT), - SPI_SWITCH("Analog Center/LFE Playback Switch", - SPI_DMUTE2_REG, SPI_DMUTE2_BIT), - SPI_SWITCH("Analog Side Playback Switch", - SPI_DMUTE1_REG, SPI_DMUTE1_BIT), +static const int spi_dmute_reg[] = { + SPI_DMUTE0_REG, + SPI_DMUTE1_REG, + SPI_DMUTE2_REG, + 0, + SPI_DMUTE4_REG, +}; +static const int spi_dmute_bit[] = { + SPI_DMUTE0_BIT, + SPI_DMUTE1_BIT, + SPI_DMUTE2_BIT, + 0, + SPI_DMUTE4_BIT, };
+static struct snd_kcontrol_new __devinit +snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details, + int channel_id) +{ + struct snd_kcontrol_new spi_switch = {0}; + int reg, bit; + int dac_id; + + spi_switch.iface = SNDRV_CTL_ELEM_IFACE_MIXER; + spi_switch.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; + spi_switch.info = spi_mute_info; + spi_switch.get = spi_mute_get; + spi_switch.put = spi_mute_put; + + switch (channel_id) { + case PCM_FRONT_CHANNEL: + spi_switch.name = "Analog Front Playback Switch"; + dac_id = (details->spi_dac & 0xf000) >> (4 * 3); + break; + case PCM_REAR_CHANNEL: + spi_switch.name = "Analog Rear Playback Switch"; + dac_id = (details->spi_dac & 0x0f00) >> (4 * 2); + break; + case PCM_CENTER_LFE_CHANNEL: + spi_switch.name = "Analog Center/LFE Playback Switch"; + dac_id = (details->spi_dac & 0x00f0) >> (4 * 1); + break; + case PCM_UNKNOWN_CHANNEL: + spi_switch.name = "Analog Side Playback Switch"; + dac_id = (details->spi_dac & 0x000f) >> (4 * 0); + break; + default: + /* Unused channel */ + spi_switch.name = NULL; + dac_id = 0; + } + reg = spi_dmute_reg[dac_id]; + bit = spi_dmute_bit[dac_id]; + + spi_switch.private_value = (reg << SPI_REG_SHIFT) | bit; + + return spi_switch; +} + static int __devinit remove_ctl(struct snd_card *card, const char *name) { struct snd_ctl_elem_id id; @@ -832,8 +869,18 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu) if (err < 0) return err; } - if (emu->details->spi_dac) - ADD_CTLS(emu, snd_ca0106_volume_spi_dac_ctls); + if (emu->details->spi_dac) { + int i; + for (i = 0;; i++) { + struct snd_kcontrol_new ctl; + ctl = snd_ca0106_volume_spi_dac_ctl(emu->details, i); + if (!ctl.name) + break; + err = snd_ctl_add(card, snd_ctl_new1(&ctl, emu)); + if (err < 0) + return err; + } + }
/* Create virtual master controls */ vmaster = snd_ctl_make_virtual_master("Master Playback Volume",
At Thu, 21 Oct 2010 23:39:19 +1100, Andy Owen wrote:
Signed-off-by: Andy Owen andy-alsa@ultra-premium.com
Thanks for patches. All changes look good in your patches, but could you give more changelog for clarifying a bit more details what the patch is actually for?
For example, I wondered why the patch 4 was necessary, and first after looking at the next patch, I understood its necessity. If it's written in the changelog that it's a preliminary work, it'd be helpful for better understanding.
thanks,
Takashi
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c index 8e69620..6dc9a5d 100644 --- a/sound/pci/ca0106/ca0106_main.c +++ b/sound/pci/ca0106/ca0106_main.c @@ -239,6 +239,16 @@ static struct snd_ca0106_details ca0106_chip_details[] = { .gpio_type = 1, .i2c_adc = 1, .spi_dac = 1 } ,
- /* Sound Blaster 5.1vx
* Tested: Playback on front, rear, center/lfe speakers
* Not-Tested: Capture
*/
- { .serial = 0x10041102,
.name = "Sound Blaster 5.1vx [SB1070]",
.gpio_type = 1,
.i2c_adc = 0,
.spi_dac = 1
/* MSI K8N Diamond Motherboard with onboard SB Live 24bit without AC97 */ /* SB0438} ,
- CTRL:CA0106-DAT
-- 1.7.3.1.127.g1bb28
On Thu, 2010-10-21 at 23:16 +0200, Takashi Iwai wrote:
Thanks for patches. All changes look good in your patches, but could you give more changelog for clarifying a bit more details what the patch is actually for?
Sure.
Before I send another round of patches, could I just check that sending to patch@alsa-project.org and cc-ing alsa-devel@alsa-project.org is correct. I seem to be the only person double spamming like this, which I'm doing just because the wiki says to:
http://www.alsa-project.org/main/index.php/GIT_Server#Occasional_Developers
(and if the wiki is out of date, and someone feels like editing it to be right, then that will save me from having to make an account :)
Andy
participants (2)
-
Andy Owen
-
Takashi Iwai