diff options
author | Takashi Iwai <tiwai@suse.de> | 2007-07-27 13:02:40 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2007-10-16 09:58:11 -0400 |
commit | 532d5381793f3c824f8ff68d7067fab8c76bb811 (patch) | |
tree | 41a27e08a905c28576167b711ccc2b06ea234a9f | |
parent | 2807314d467e7dd929c42050031aabbd28e78f0b (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>
-rw-r--r-- | sound/pci/hda/hda_codec.c | 87 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 47 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 177 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 28 |
4 files changed, 184 insertions, 155 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index e7843ffeeb2f..36879a93eac4 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1006,6 +1006,93 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | |||
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | /* | 1008 | /* |
1009 | * generic bound volume/swtich controls | ||
1010 | */ | ||
1011 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
1012 | struct snd_ctl_elem_info *uinfo) | ||
1013 | { | ||
1014 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1015 | struct hda_bind_ctls *c; | ||
1016 | int err; | ||
1017 | |||
1018 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1019 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1020 | kcontrol->private_value = *c->values; | ||
1021 | err = c->ops->info(kcontrol, uinfo); | ||
1022 | kcontrol->private_value = (long)c; | ||
1023 | mutex_unlock(&codec->spdif_mutex); | ||
1024 | return err; | ||
1025 | } | ||
1026 | |||
1027 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
1028 | struct snd_ctl_elem_value *ucontrol) | ||
1029 | { | ||
1030 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1031 | struct hda_bind_ctls *c; | ||
1032 | int err; | ||
1033 | |||
1034 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1035 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1036 | kcontrol->private_value = *c->values; | ||
1037 | err = c->ops->get(kcontrol, ucontrol); | ||
1038 | kcontrol->private_value = (long)c; | ||
1039 | mutex_unlock(&codec->spdif_mutex); | ||
1040 | return err; | ||
1041 | } | ||
1042 | |||
1043 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
1044 | struct snd_ctl_elem_value *ucontrol) | ||
1045 | { | ||
1046 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1047 | struct hda_bind_ctls *c; | ||
1048 | unsigned long *vals; | ||
1049 | int err = 0, change = 0; | ||
1050 | |||
1051 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1052 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1053 | for (vals = c->values; *vals; vals++) { | ||
1054 | kcontrol->private_value = *vals; | ||
1055 | err = c->ops->put(kcontrol, ucontrol); | ||
1056 | if (err < 0) | ||
1057 | break; | ||
1058 | change |= err; | ||
1059 | } | ||
1060 | kcontrol->private_value = (long)c; | ||
1061 | mutex_unlock(&codec->spdif_mutex); | ||
1062 | return err < 0 ? err : change; | ||
1063 | } | ||
1064 | |||
1065 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
1066 | unsigned int size, unsigned int __user *tlv) | ||
1067 | { | ||
1068 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
1069 | struct hda_bind_ctls *c; | ||
1070 | int err; | ||
1071 | |||
1072 | c = (struct hda_bind_ctls *)kcontrol->private_value; | ||
1073 | mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */ | ||
1074 | kcontrol->private_value = *c->values; | ||
1075 | err = c->ops->tlv(kcontrol, op_flag, size, tlv); | ||
1076 | kcontrol->private_value = (long)c; | ||
1077 | mutex_unlock(&codec->spdif_mutex); | ||
1078 | return err; | ||
1079 | } | ||
1080 | |||
1081 | struct hda_ctl_ops snd_hda_bind_vol = { | ||
1082 | .info = snd_hda_mixer_amp_volume_info, | ||
1083 | .get = snd_hda_mixer_amp_volume_get, | ||
1084 | .put = snd_hda_mixer_amp_volume_put, | ||
1085 | .tlv = snd_hda_mixer_amp_tlv | ||
1086 | }; | ||
1087 | |||
1088 | struct hda_ctl_ops snd_hda_bind_sw = { | ||
1089 | .info = snd_hda_mixer_amp_switch_info, | ||
1090 | .get = snd_hda_mixer_amp_switch_get, | ||
1091 | .put = snd_hda_mixer_amp_switch_put, | ||
1092 | .tlv = snd_hda_mixer_amp_tlv | ||
1093 | }; | ||
1094 | |||
1095 | /* | ||
1009 | * SPDIF out controls | 1096 | * SPDIF out controls |
1010 | */ | 1097 | */ |
1011 | 1098 | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 12428a67eb2a..fafcffe6fc79 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -102,6 +102,53 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol, | |||
102 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, | 102 | int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol, |
103 | struct snd_ctl_elem_value *ucontrol); | 103 | struct snd_ctl_elem_value *ucontrol); |
104 | 104 | ||
105 | /* more generic bound controls */ | ||
106 | struct hda_ctl_ops { | ||
107 | snd_kcontrol_info_t *info; | ||
108 | snd_kcontrol_get_t *get; | ||
109 | snd_kcontrol_put_t *put; | ||
110 | snd_kcontrol_tlv_rw_t *tlv; | ||
111 | }; | ||
112 | |||
113 | extern struct hda_ctl_ops snd_hda_bind_vol; /* for bind-volume with TLV */ | ||
114 | extern struct hda_ctl_ops snd_hda_bind_sw; /* for bind-switch */ | ||
115 | |||
116 | struct hda_bind_ctls { | ||
117 | struct hda_ctl_ops *ops; | ||
118 | long values[]; | ||
119 | }; | ||
120 | |||
121 | int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol, | ||
122 | struct snd_ctl_elem_info *uinfo); | ||
123 | int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol, | ||
124 | struct snd_ctl_elem_value *ucontrol); | ||
125 | int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol, | ||
126 | struct snd_ctl_elem_value *ucontrol); | ||
127 | int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag, | ||
128 | unsigned int size, unsigned int __user *tlv); | ||
129 | |||
130 | #define HDA_BIND_VOL(xname, bindrec) \ | ||
131 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ | ||
132 | .name = xname, \ | ||
133 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |\ | ||
134 | SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
135 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK,\ | ||
136 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
137 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
138 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
139 | .tlv = { .c = snd_hda_mixer_bind_tlv },\ | ||
140 | .private_value = (long) (bindrec) } | ||
141 | #define HDA_BIND_SW(xname, bindrec) \ | ||
142 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,\ | ||
143 | .name = xname, \ | ||
144 | .info = snd_hda_mixer_bind_ctls_info,\ | ||
145 | .get = snd_hda_mixer_bind_ctls_get,\ | ||
146 | .put = snd_hda_mixer_bind_ctls_put,\ | ||
147 | .private_value = (long) (bindrec) } | ||
148 | |||
149 | /* | ||
150 | * SPDIF I/O | ||
151 | */ | ||
105 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); | 152 | int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid); |
106 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | 153 | int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); |
107 | 154 | ||
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 | |||
433 | static 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 | ||
444 | static int ad1986a_pcm_amp_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) | 426 | static 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 | |||
462 | static 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 | |||
473 | static 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); | 436 | static 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 | */ |
492 | static struct snd_kcontrol_new ad1986a_mixers[] = { | 449 | static 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 */ |
599 | static int ad1986a_laptop_master_vol_put(struct snd_kcontrol *kcontrol, | 541 | static 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 | |||
617 | static 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, | 550 | static 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 | ||
635 | static struct hda_input_mux ad1986a_laptop_eapd_capture_source = { | 559 | static 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 | ||
644 | static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = { | 568 | static 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)) |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index d839d567f8e4..f27e073d22b1 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -7140,28 +7140,18 @@ static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = { | |||
7140 | { } /* end */ | 7140 | { } /* end */ |
7141 | }; | 7141 | }; |
7142 | 7142 | ||
7143 | static int alc262_sony_sw_put(struct snd_kcontrol *kcontrol, | 7143 | static struct hda_bind_ctls alc262_sony_bind_sw = { |
7144 | struct snd_ctl_elem_value *ucontrol) | 7144 | .ops = &snd_hda_bind_sw, |
7145 | { | 7145 | .values = { |
7146 | unsigned long private_save = kcontrol->private_value; | 7146 | HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), |
7147 | int change; | 7147 | HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT), |
7148 | kcontrol->private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT); | 7148 | 0, |
7149 | change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | 7149 | }, |
7150 | kcontrol->private_value = private_save; | 7150 | }; |
7151 | change |= snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
7152 | return change; | ||
7153 | } | ||
7154 | 7151 | ||
7155 | static struct snd_kcontrol_new alc262_sony_mixer[] = { | 7152 | static struct snd_kcontrol_new alc262_sony_mixer[] = { |
7156 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), | 7153 | HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), |
7157 | { | 7154 | HDA_BIND_SW("Front Playback Switch", &alc262_sony_bind_sw), |
7158 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
7159 | .name = "Front Playback Switch", | ||
7160 | .info = snd_hda_mixer_amp_switch_info, | ||
7161 | .get = snd_hda_mixer_amp_switch_get, | ||
7162 | .put = alc262_sony_sw_put, | ||
7163 | .private_value = HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT), | ||
7164 | }, | ||
7165 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), | 7155 | HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), |
7166 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), | 7156 | HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), |
7167 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), | 7157 | HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT), |