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 /sound/pci/hda/hda_codec.c | |
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>
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 87 |
1 files changed, 87 insertions, 0 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 | ||