aboutsummaryrefslogtreecommitdiffstats
path: root/sound/i2c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/i2c')
-rw-r--r--sound/i2c/other/ak4xxx-adda.c89
1 files changed, 83 insertions, 6 deletions
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));