aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJani Alinikula <janialinikula@gmail.com>2006-06-27 09:00:55 -0400
committerJaroslav Kysela <perex@suse.cz>2006-06-28 13:31:03 -0400
commitc83c0c470565a0aed2f6fcbaa6c80a98ef250586 (patch)
tree5f6810822c019af78dcb95f67565101cb97198c0
parentbe7ee27822975cee5dabb2cfd7f03e7fde38e3f4 (diff)
[ALSA] Stereo controls for M-Audio Revolution cards
This patch adds stereo controls to revo cards by making the ak4xxx driver mixers configurable from the card driver. Signed-off-by: Jani Alinikula <janialinikula@gmail.com> Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
-rw-r--r--include/sound/ak4xxx-adda.h2
-rw-r--r--sound/i2c/other/ak4xxx-adda.c89
-rw-r--r--sound/pci/ice1712/revo.c23
3 files changed, 105 insertions, 9 deletions
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index 3bf5911fe827..acf8cc1292e0 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -53,6 +53,8 @@ struct snd_akm4xxx {
53 SND_AK4524, SND_AK4528, SND_AK4529, 53 SND_AK4524, SND_AK4528, SND_AK4529,
54 SND_AK4355, SND_AK4358, SND_AK4381 54 SND_AK4355, SND_AK4358, SND_AK4381
55 } type; 55 } type;
56 unsigned int *num_stereo; /* array of combined counts for the mixer */
57 char **channel_names; /* array of mixer channel names */
56 struct snd_ak4xxx_ops ops; 58 struct snd_ak4xxx_ops ops;
57}; 59};
58 60
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 045e32a311e0..f68bd740e1a1 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -292,6 +292,64 @@ static int snd_akm4xxx_volume_put(struct snd_kcontrol *kcontrol,
292 return change; 292 return change;
293} 293}
294 294
295static int snd_akm4xxx_stereo_volume_info(struct snd_kcontrol *kcontrol,
296 struct snd_ctl_elem_info *uinfo)
297{
298 unsigned int mask = AK_GET_MASK(kcontrol->private_value);
299
300 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
301 uinfo->count = 2;
302 uinfo->value.integer.min = 0;
303 uinfo->value.integer.max = mask;
304 return 0;
305}
306
307static int snd_akm4xxx_stereo_volume_get(struct snd_kcontrol *kcontrol,
308 struct snd_ctl_elem_value *ucontrol)
309{
310 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
311 int chip = AK_GET_CHIP(kcontrol->private_value);
312 int addr = AK_GET_ADDR(kcontrol->private_value);
313 int invert = AK_GET_INVERT(kcontrol->private_value);
314 unsigned int mask = AK_GET_MASK(kcontrol->private_value);
315 unsigned char val = snd_akm4xxx_get(ak, chip, addr);
316
317 ucontrol->value.integer.value[0] = invert ? mask - val : val;
318
319 val = snd_akm4xxx_get(ak, chip, addr+1);
320 ucontrol->value.integer.value[1] = invert ? mask - val : val;
321
322 return 0;
323}
324
325static int snd_akm4xxx_stereo_volume_put(struct snd_kcontrol *kcontrol,
326 struct snd_ctl_elem_value *ucontrol)
327{
328 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
329 int chip = AK_GET_CHIP(kcontrol->private_value);
330 int addr = AK_GET_ADDR(kcontrol->private_value);
331 int invert = AK_GET_INVERT(kcontrol->private_value);
332 unsigned int mask = AK_GET_MASK(kcontrol->private_value);
333 unsigned char nval = ucontrol->value.integer.value[0] % (mask+1);
334 int change0, change1;
335
336 if (invert)
337 nval = mask - nval;
338 change0 = snd_akm4xxx_get(ak, chip, addr) != nval;
339 if (change0)
340 snd_akm4xxx_write(ak, chip, addr, nval);
341
342 nval = ucontrol->value.integer.value[1] % (mask+1);
343 if (invert)
344 nval = mask - nval;
345 change1 = snd_akm4xxx_get(ak, chip, addr+1) != nval;
346 if (change1)
347 snd_akm4xxx_write(ak, chip, addr+1, nval);
348
349
350 return change0 || change1;
351}
352
295static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, 353static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol,
296 struct snd_ctl_elem_info *uinfo) 354 struct snd_ctl_elem_info *uinfo)
297{ 355{
@@ -377,20 +435,35 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
377 unsigned int idx, num_emphs; 435 unsigned int idx, num_emphs;
378 struct snd_kcontrol *ctl; 436 struct snd_kcontrol *ctl;
379 int err; 437 int err;
438 int mixer_ch = 0;
439 int num_stereo;
380 440
381 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); 441 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
382 if (! ctl) 442 if (! ctl)
383 return -ENOMEM; 443 return -ENOMEM;
384 444
385 for (idx = 0; idx < ak->num_dacs; ++idx) { 445 for (idx = 0; idx < ak->num_dacs; ) {
386 memset(ctl, 0, sizeof(*ctl)); 446 memset(ctl, 0, sizeof(*ctl));
387 strcpy(ctl->id.name, "DAC Volume"); 447 if (ak->channel_names == NULL) {
388 ctl->id.index = idx + ak->idx_offset * 2; 448 strcpy(ctl->id.name, "DAC Volume");
449 num_stereo = 1;
450 ctl->id.index = mixer_ch + ak->idx_offset * 2;
451 } else {
452 strcpy(ctl->id.name, ak->channel_names[mixer_ch]);
453 num_stereo = ak->num_stereo[mixer_ch];
454 ctl->id.index = 0; //mixer_ch + ak->idx_offset * 2;
455 }
389 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; 456 ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
390 ctl->count = 1; 457 ctl->count = 1;
391 ctl->info = snd_akm4xxx_volume_info; 458 if (num_stereo == 2) {
392 ctl->get = snd_akm4xxx_volume_get; 459 ctl->info = snd_akm4xxx_stereo_volume_info;
393 ctl->put = snd_akm4xxx_volume_put; 460 ctl->get = snd_akm4xxx_stereo_volume_get;
461 ctl->put = snd_akm4xxx_stereo_volume_put;
462 } else {
463 ctl->info = snd_akm4xxx_volume_info;
464 ctl->get = snd_akm4xxx_volume_get;
465 ctl->put = snd_akm4xxx_volume_put;
466 }
394 switch (ak->type) { 467 switch (ak->type) {
395 case SND_AK4524: 468 case SND_AK4524:
396 ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */ 469 ctl->private_value = AK_COMPOSE(idx/2, (idx%2) + 6, 0, 127); /* register 6 & 7 */
@@ -419,9 +492,13 @@ int snd_akm4xxx_build_controls(struct snd_akm4xxx *ak)
419 err = -EINVAL; 492 err = -EINVAL;
420 goto __error; 493 goto __error;
421 } 494 }
495
422 ctl->private_data = ak; 496 ctl->private_data = ak;
423 if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0) 497 if ((err = snd_ctl_add(ak->card, snd_ctl_new(ctl, SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE))) < 0)
424 goto __error; 498 goto __error;
499
500 idx += num_stereo;
501 mixer_ch++;
425 } 502 }
426 for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) { 503 for (idx = 0; idx < ak->num_adcs && ak->type == SND_AK4524; ++idx) {
427 memset(ctl, 0, sizeof(*ctl)); 504 memset(ctl, 0, sizeof(*ctl));
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index b5754b32b802..fec9440cb310 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -87,12 +87,25 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
87 * initialize the chips on M-Audio Revolution cards 87 * initialize the chips on M-Audio Revolution cards
88 */ 88 */
89 89
90static unsigned int revo71_num_stereo_front[] = {2};
91static char *revo71_channel_names_front[] = {"PCM Playback Volume"};
92
93static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2};
94static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume",
95 "PCM Side Playback Volume", "PCM Rear Playback Volume"};
96
97static unsigned int revo51_num_stereo[] = {2, 1, 1, 2};
98static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume",
99 "PCM LFE Playback Volume", "PCM Rear Playback Volume"};
100
90static struct snd_akm4xxx akm_revo_front __devinitdata = { 101static struct snd_akm4xxx akm_revo_front __devinitdata = {
91 .type = SND_AK4381, 102 .type = SND_AK4381,
92 .num_dacs = 2, 103 .num_dacs = 2,
93 .ops = { 104 .ops = {
94 .set_rate_val = revo_set_rate_val 105 .set_rate_val = revo_set_rate_val
95 } 106 },
107 .num_stereo = revo71_num_stereo_front,
108 .channel_names = revo71_channel_names_front
96}; 109};
97 110
98static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { 111static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
@@ -113,7 +126,9 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
113 .num_dacs = 6, 126 .num_dacs = 6,
114 .ops = { 127 .ops = {
115 .set_rate_val = revo_set_rate_val 128 .set_rate_val = revo_set_rate_val
116 } 129 },
130 .num_stereo = revo71_num_stereo_surround,
131 .channel_names = revo71_channel_names_surround
117}; 132};
118 133
119static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { 134static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
@@ -133,7 +148,9 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
133 .num_dacs = 6, 148 .num_dacs = 6,
134 .ops = { 149 .ops = {
135 .set_rate_val = revo_set_rate_val 150 .set_rate_val = revo_set_rate_val
136 } 151 },
152 .num_stereo = revo51_num_stereo,
153 .channel_names = revo51_channel_names
137}; 154};
138 155
139static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { 156static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {