aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_analog.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-07-27 13:02:40 -0400
committerJaroslav Kysela <perex@perex.cz>2007-10-16 09:58:11 -0400
commit532d5381793f3c824f8ff68d7067fab8c76bb811 (patch)
tree41a27e08a905c28576167b711ccc2b06ea234a9f /sound/pci/hda/patch_analog.c
parent2807314d467e7dd929c42050031aabbd28e78f0b (diff)
[ALSA] hda-codec - Add a generic bind-control helper
Added callbacks for a generic bind-control of mixer elements. This can be used for creating a mixer element controlling multiple widgets at the same time. Two macros, HDA_BIND_VOL() and HDA_BIND_SW(), are introduced for creating bind-volume and bind-switch, respectively. It taks the mixer element name and struct hda_bind_ctls pointer, which contains the real control callbacks in ops field and long array for private_value of each bound widget. All widgets have to be the same type (i.e. the same amp capability). Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/pci/hda/patch_analog.c')
-rw-r--r--sound/pci/hda/patch_analog.c177
1 files changed, 41 insertions, 136 deletions
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 488724f2e304..cc2e944cc59f 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -422,94 +422,36 @@ static struct hda_input_mux ad1986a_capture_source = {
422 }, 422 },
423}; 423};
424 424
425/*
426 * PCM control
427 *
428 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
429 */
430
431#define ad1986a_pcm_amp_vol_info snd_hda_mixer_amp_volume_info
432
433static int ad1986a_pcm_amp_vol_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
434{
435 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
436 struct ad198x_spec *ad = codec->spec;
437
438 mutex_lock(&ad->amp_mutex);
439 snd_hda_mixer_amp_volume_get(kcontrol, ucontrol);
440 mutex_unlock(&ad->amp_mutex);
441 return 0;
442}
443 425
444static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) 426static struct hda_bind_ctls ad1986a_bind_pcm_vol = {
445{ 427 .ops = &snd_hda_bind_vol,
446 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 428 .values = {
447 struct ad198x_spec *ad = codec->spec; 429 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
448 int i, change = 0; 430 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
449 431 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
450 mutex_lock(&ad->amp_mutex); 432 0
451 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { 433 },
452 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); 434};
453 change |= snd_hda_mixer_amp_volume_put(kcontrol, ucontrol);
454 }
455 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT);
456 mutex_unlock(&ad->amp_mutex);
457 return change;
458}
459
460#define ad1986a_pcm_amp_sw_info snd_hda_mixer_amp_switch_info
461
462static int ad1986a_pcm_amp_sw_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
463{
464 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
465 struct ad198x_spec *ad = codec->spec;
466
467 mutex_lock(&ad->amp_mutex);
468 snd_hda_mixer_amp_switch_get(kcontrol, ucontrol);
469 mutex_unlock(&ad->amp_mutex);
470 return 0;
471}
472
473static int ad1986a_pcm_amp_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
474{
475 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
476 struct ad198x_spec *ad = codec->spec;
477 int i, change = 0;
478 435
479 mutex_lock(&ad->amp_mutex); 436static struct hda_bind_ctls ad1986a_bind_pcm_sw = {
480 for (i = 0; i < ARRAY_SIZE(ad1986a_dac_nids); i++) { 437 .ops = &snd_hda_bind_sw,
481 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(ad1986a_dac_nids[i], 3, 0, HDA_OUTPUT); 438 .values = {
482 change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); 439 HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT),
483 } 440 HDA_COMPOSE_AMP_VAL(AD1986A_SURR_DAC, 3, 0, HDA_OUTPUT),
484 kcontrol->private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT); 441 HDA_COMPOSE_AMP_VAL(AD1986A_CLFE_DAC, 3, 0, HDA_OUTPUT),
485 mutex_unlock(&ad->amp_mutex); 442 0
486 return change; 443 },
487} 444};
488 445
489/* 446/*
490 * mixers 447 * mixers
491 */ 448 */
492static struct snd_kcontrol_new ad1986a_mixers[] = { 449static struct snd_kcontrol_new ad1986a_mixers[] = {
493 { 450 /*
494 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 451 * bind volumes/mutes of 3 DACs as a single PCM control for simplicity
495 .name = "PCM Playback Volume", 452 */
496 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 453 HDA_BIND_VOL("PCM Playback Volume", &ad1986a_bind_pcm_vol),
497 SNDRV_CTL_ELEM_ACCESS_TLV_READ | 454 HDA_BIND_SW("PCM Playback Switch", &ad1986a_bind_pcm_sw),
498 SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,
499 .info = ad1986a_pcm_amp_vol_info,
500 .get = ad1986a_pcm_amp_vol_get,
501 .put = ad1986a_pcm_amp_vol_put,
502 .tlv = { .c = snd_hda_mixer_amp_tlv },
503 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
504 },
505 {
506 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
507 .name = "PCM Playback Switch",
508 .info = ad1986a_pcm_amp_sw_info,
509 .get = ad1986a_pcm_amp_sw_get,
510 .put = ad1986a_pcm_amp_sw_put,
511 .private_value = HDA_COMPOSE_AMP_VAL(AD1986A_FRONT_DAC, 3, 0, HDA_OUTPUT)
512 },
513 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT), 455 HDA_CODEC_VOLUME("Front Playback Volume", 0x1b, 0x0, HDA_OUTPUT),
514 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT), 456 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
515 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT), 457 HDA_CODEC_VOLUME("Surround Playback Volume", 0x1c, 0x0, HDA_OUTPUT),
@@ -596,41 +538,23 @@ static struct snd_kcontrol_new ad1986a_laptop_mixers[] = {
596/* laptop-eapd model - 2ch only */ 538/* laptop-eapd model - 2ch only */
597 539
598/* master controls both pins 0x1a and 0x1b */ 540/* master controls both pins 0x1a and 0x1b */
599static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol, 541static struct hda_bind_ctls ad1986a_laptop_master_vol = {
600 struct snd_ctl_elem_value *ucontrol) 542 .ops = &snd_hda_bind_vol,
601{ 543 .values = {
602 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 544 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
603 long *valp = ucontrol->value.integer.value; 545 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
604 int change; 546 0,
605 547 },
606 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, 548};
607 0x7f, valp[0] & 0x7f);
608 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0,
609 0x7f, valp[1] & 0x7f);
610 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
611 0x7f, valp[0] & 0x7f);
612 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
613 0x7f, valp[1] & 0x7f);
614 return change;
615}
616
617static int ad1986a_laptop_master_sw_put(struct snd_kcontrol *kcontrol,
618 struct snd_ctl_elem_value *ucontrol)
619{
620 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
621 long *valp = ucontrol->value.integer.value;
622 int change;
623 549
624 change = snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_OUTPUT, 0, 550static struct hda_bind_ctls ad1986a_laptop_master_sw = {
625 0x80, valp[0] ? 0 : 0x80); 551 .ops = &snd_hda_bind_sw,
626 change |= snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_OUTPUT, 0, 552 .values = {
627 0x80, valp[1] ? 0 : 0x80); 553 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
628 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0, 554 HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
629 0x80, valp[0] ? 0 : 0x80); 555 0,
630 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0, 556 },
631 0x80, valp[1] ? 0 : 0x80); 557};
632 return change;
633}
634 558
635static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { 559static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
636 .num_items = 3, 560 .num_items = 3,
@@ -642,23 +566,8 @@ static struct hda_input_mux ad1986a_laptop_eapd_capture_source = {
642}; 566};
643 567
644static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { 568static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
645 { 569 HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
646 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 570 HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
647 .name = "Master Playback Volume",
648 .info = snd_hda_mixer_amp_volume_info,
649 .get = snd_hda_mixer_amp_volume_get,
650 .put = ad1986a_laptop_master_vol_put,
651 .tlv = { .c = snd_hda_mixer_amp_tlv },
652 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
653 },
654 {
655 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
656 .name = "Master Playback Switch",
657 .info = snd_hda_mixer_amp_switch_info,
658 .get = snd_hda_mixer_amp_switch_get,
659 .put = ad1986a_laptop_master_sw_put,
660 .private_value = HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT),
661 },
662 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT), 571 HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
663 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT), 572 HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
664 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT), 573 HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0x0, HDA_OUTPUT),
@@ -856,7 +765,6 @@ static int patch_ad1986a(struct hda_codec *codec)
856 if (spec == NULL) 765 if (spec == NULL)
857 return -ENOMEM; 766 return -ENOMEM;
858 767
859 mutex_init(&spec->amp_mutex);
860 codec->spec = spec; 768 codec->spec = spec;
861 769
862 spec->multiout.max_channels = 6; 770 spec->multiout.max_channels = 6;
@@ -1064,7 +972,6 @@ static int patch_ad1983(struct hda_codec *codec)
1064 if (spec == NULL) 972 if (spec == NULL)
1065 return -ENOMEM; 973 return -ENOMEM;
1066 974
1067 mutex_init(&spec->amp_mutex);
1068 codec->spec = spec; 975 codec->spec = spec;
1069 976
1070 spec->multiout.max_channels = 2; 977 spec->multiout.max_channels = 2;
@@ -1466,7 +1373,6 @@ static int patch_ad1981(struct hda_codec *codec)
1466 if (spec == NULL) 1373 if (spec == NULL)
1467 return -ENOMEM; 1374 return -ENOMEM;
1468 1375
1469 mutex_init(&spec->amp_mutex);
1470 codec->spec = spec; 1376 codec->spec = spec;
1471 1377
1472 spec->multiout.max_channels = 2; 1378 spec->multiout.max_channels = 2;
@@ -2672,7 +2578,6 @@ static int patch_ad1988(struct hda_codec *codec)
2672 if (spec == NULL) 2578 if (spec == NULL)
2673 return -ENOMEM; 2579 return -ENOMEM;
2674 2580
2675 mutex_init(&spec->amp_mutex);
2676 codec->spec = spec; 2581 codec->spec = spec;
2677 2582
2678 if (is_rev2(codec)) 2583 if (is_rev2(codec))