summaryrefslogtreecommitdiff
path: root/sound/pci/hda/hda_codec.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2007-07-27 19:02:40 +0200
committerJaroslav Kysela <perex@perex.cz>2007-10-16 15:58:11 +0200
commit532d5381793f3c824f8ff68d7067fab8c76bb811 (patch)
tree41a27e08a905c28576167b711ccc2b06ea234a9f /sound/pci/hda/hda_codec.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/hda_codec.c')
-rw-r--r--sound/pci/hda/hda_codec.c87
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,
}
/*
+ * generic bound volume/swtich controls
+ */
+int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->info(kcontrol, uinfo);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->get(kcontrol, ucontrol);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ unsigned long *vals;
+ int err = 0, change = 0;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ for (vals = c->values; *vals; vals++) {
+ kcontrol->private_value = *vals;
+ err = c->ops->put(kcontrol, ucontrol);
+ if (err < 0)
+ break;
+ change |= err;
+ }
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err < 0 ? err : change;
+}
+
+int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
+ unsigned int size, unsigned int __user *tlv)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hda_bind_ctls *c;
+ int err;
+
+ c = (struct hda_bind_ctls *)kcontrol->private_value;
+ mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
+ kcontrol->private_value = *c->values;
+ err = c->ops->tlv(kcontrol, op_flag, size, tlv);
+ kcontrol->private_value = (long)c;
+ mutex_unlock(&codec->spdif_mutex);
+ return err;
+}
+
+struct hda_ctl_ops snd_hda_bind_vol = {
+ .info = snd_hda_mixer_amp_volume_info,
+ .get = snd_hda_mixer_amp_volume_get,
+ .put = snd_hda_mixer_amp_volume_put,
+ .tlv = snd_hda_mixer_amp_tlv
+};
+
+struct hda_ctl_ops snd_hda_bind_sw = {
+ .info = snd_hda_mixer_amp_switch_info,
+ .get = snd_hda_mixer_amp_switch_get,
+ .put = snd_hda_mixer_amp_switch_put,
+ .tlv = snd_hda_mixer_amp_tlv
+};
+
+/*
* SPDIF out controls
*/