diff options
author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-06-19 12:08:46 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:03 -0400 |
commit | 43131a2ca6afbd8dcc940d5ad4b4b1c3d89a658b (patch) | |
tree | 98d94d5c2640174ca1a64d70062a2a471b302608 /drivers/media/video/em28xx/em28xx-audio.c | |
parent | 850d24a5a861238f583f59cd39de4dfe5142a4c9 (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.c | 87 |
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 | |||
453 | static int em28xx_vol_put(struct snd_kcontrol *kcontrol, | 451 | static 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 | ||
491 | static 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 | |||
510 | err: | ||
511 | mutex_unlock(&dev->lock); | ||
512 | return rc; | ||
513 | } | ||
514 | |||
515 | static 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 | |||
493 | static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0); | 535 | static const DECLARE_TLV_DB_SCALE(em28xx_db_scale, -3450, 150, 0); |
494 | 536 | ||
495 | static int em28xx_cvol_new(struct snd_card *card, struct em28xx *dev, | 537 | static 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 | */ |