aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-audio.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2011-06-19 12:08:46 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:03 -0400
commit43131a2ca6afbd8dcc940d5ad4b4b1c3d89a658b (patch)
tree98d94d5c2640174ca1a64d70062a2a471b302608 /drivers/media/video/em28xx/em28xx-audio.c
parent850d24a5a861238f583f59cd39de4dfe5142a4c9 (diff)
[media] em28xx-audio: add support for mute controls
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-audio.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-audio.c87
1 files changed, 73 insertions, 14 deletions
diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c
index a75c779640df..c7b96b46d346 100644
--- a/drivers/media/video/em28xx/em28xx-audio.c
+++ b/drivers/media/video/em28xx/em28xx-audio.c
@@ -448,8 +448,6 @@ static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
448 return 0; 448 return 0;
449} 449}
450 450
451/* FIXME: should also add mute controls for each */
452
453static int em28xx_vol_put(struct snd_kcontrol *kcontrol, 451static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
454 struct snd_ctl_elem_value *value) 452 struct snd_ctl_elem_value *value)
455{ 453{
@@ -463,7 +461,7 @@ static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
463 if (rc < 0) 461 if (rc < 0)
464 goto err; 462 goto err;
465 463
466 val |= rc & 0x8080; /* Preserve the mute flags */ 464 val |= rc & 0x8000; /* Preserve the mute flag */
467 465
468 rc = em28xx_write_ac97(dev, kcontrol->private_value, val); 466 rc = em28xx_write_ac97(dev, kcontrol->private_value, val);
469 467
@@ -490,25 +488,87 @@ static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
490 return 0; 488 return 0;
491} 489}
492 490
491static int em28xx_vol_put_mute(struct snd_kcontrol *kcontrol,
492 struct snd_ctl_elem_value *value)
493{
494 struct em28xx *dev = snd_kcontrol_chip(kcontrol);
495 u16 val = value->value.integer.value[0];
496 int rc;
497
498 mutex_lock(&dev->lock);
499 rc = em28xx_read_ac97(dev, kcontrol->private_value);
500 if (rc < 0)
501 goto err;
502
503 if (val)
504 rc |= 0x8000;
505 else
506 rc &= 0x7f7f;
507
508 rc = em28xx_write_ac97(dev, kcontrol->private_value, rc);
509
510err:
511 mutex_unlock(&dev->lock);
512 return rc;
513}
514
515static int em28xx_vol_get_mute(struct snd_kcontrol *kcontrol,
516 struct snd_ctl_elem_value *value)
517{
518 struct em28xx *dev = snd_kcontrol_chip(kcontrol);
519 int val;
520
521 mutex_lock(&dev->lock);
522 val = em28xx_read_ac97(dev, kcontrol->private_value);
523 mutex_unlock(&dev->lock);
524 if (val < 0)
525 return val;
526
527 if (val & 0x8000)
528 value->value.integer.value[0] = 1;
529 else
530 value->value.integer.value[0] = 0;
531
532 return 0;
533}
534
493static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0); 535static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0);
494 536
495static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev, 537static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
496 char *name, int id) 538 char *name, int id)
497{ 539{
498 int err; 540 int err;
541 char ctl_name[44];
499 struct snd_kcontrol *kctl; 542 struct snd_kcontrol *kctl;
500 struct snd_kcontrol_new tmp = { 543 struct snd_kcontrol_new tmp;
501 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 544
502 .name = name, 545 memset (&tmp, 0, sizeof(tmp));
503 .info = em28xx_vol_info, 546 tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
504 .get = em28xx_vol_get, 547 tmp.private_value = id,
505 .put = em28xx_vol_put, 548 tmp.name = ctl_name,
506 .private_value = id, 549
507 .tlv.p = em28xx_db_scale, 550 /* Add Mute Control */
508 }; 551 sprintf(ctl_name, "%s Switch", name);
509 552 tmp.get = em28xx_vol_get_mute;
553 tmp.put = em28xx_vol_put_mute;
554 tmp.info = snd_ctl_boolean_mono_info;
510 kctl = snd_ctl_new1(&tmp, dev); 555 kctl = snd_ctl_new1(&tmp, dev);
556 err = snd_ctl_add(card, kctl);
557 if (err < 0)
558 return err;
511 559
560 memset (&tmp, 0, sizeof(tmp));
561 tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
562 tmp.private_value = id,
563 tmp.name = ctl_name,
564
565 /* Add Volume Control */
566 sprintf(ctl_name, "%s Volume", name);
567 tmp.get = em28xx_vol_get;
568 tmp.put = em28xx_vol_put;
569 tmp.info = em28xx_vol_info;
570 tmp.tlv.p = em28xx_db_scale,
571 kctl = snd_ctl_new1(&tmp, dev);
512 err = snd_ctl_add(card, kctl); 572 err = snd_ctl_add(card, kctl);
513 if (err < 0) 573 if (err < 0)
514 return err; 574 return err;
@@ -516,7 +576,6 @@ static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev,
516 return 0; 576 return 0;
517} 577}
518 578
519
520/* 579/*
521 * register/unregister code and data 580 * register/unregister code and data
522 */ 581 */