diff options
| -rw-r--r-- | include/sound/ak4xxx-adda.h | 2 | ||||
| -rw-r--r-- | sound/i2c/other/ak4xxx-adda.c | 89 | ||||
| -rw-r--r-- | sound/pci/ice1712/revo.c | 23 |
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 | ||
| 295 | static 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 | |||
| 307 | static 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 | |||
| 325 | static 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 | |||
| 295 | static int snd_akm4xxx_ipga_gain_info(struct snd_kcontrol *kcontrol, | 353 | static 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 | ||
| 90 | static unsigned int revo71_num_stereo_front[] = {2}; | ||
| 91 | static char *revo71_channel_names_front[] = {"PCM Playback Volume"}; | ||
| 92 | |||
| 93 | static unsigned int revo71_num_stereo_surround[] = {1, 1, 2, 2}; | ||
| 94 | static char *revo71_channel_names_surround[] = {"PCM Center Playback Volume", "PCM LFE Playback Volume", | ||
| 95 | "PCM Side Playback Volume", "PCM Rear Playback Volume"}; | ||
| 96 | |||
| 97 | static unsigned int revo51_num_stereo[] = {2, 1, 1, 2}; | ||
| 98 | static char *revo51_channel_names[] = {"PCM Playback Volume", "PCM Center Playback Volume", | ||
| 99 | "PCM LFE Playback Volume", "PCM Rear Playback Volume"}; | ||
| 100 | |||
| 90 | static struct snd_akm4xxx akm_revo_front __devinitdata = { | 101 | static 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 | ||
| 98 | static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { | 111 | static 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 | ||
| 119 | static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { | 134 | static 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 | ||
| 139 | static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { | 156 | static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { |
