summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorSudheer Papothi <spapothi@codeaurora.org>2016-01-29 02:40:28 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 20:10:19 -0700
commitabe342c13b3d2a6523eccc35ff4a9d124e48cc59 (patch)
treea91366fdfaba758fddd62644a3985d407d349b61 /sound
parent6ba6d2e98322dd4d8ea07b39d5129671c403ec03 (diff)
ALSA: PCM: User contol API implementation
Introduced a new helper function snd_pcm_add_usr_ctls() to create control elements representing the user control for each PCM (sub)stream Signed-off-by: Jayasena Sangaraboina <jsanga@codeaurora.org> Signed-off-by: Banajit Goswami <bgoswami@codeaurora.org> Signed-off-by: Sudheer Papothi <spapothi@codeaurora.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/core/pcm.c4
-rw-r--r--sound/core/pcm_lib.c93
2 files changed, 97 insertions, 0 deletions
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index e43571e70ef6..019751a83e25 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -1143,6 +1143,10 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
snd_ctl_remove(pcm->card, pcm->streams[cidx].vol_kctl);
pcm->streams[cidx].vol_kctl = NULL;
}
+ if (pcm->streams[cidx].usr_kctl) {
+ snd_ctl_remove(pcm->card, pcm->streams[cidx].usr_kctl);
+ pcm->streams[cidx].usr_kctl = NULL;
+ }
}
mutex_unlock(&pcm->open_mutex);
mutex_unlock(&register_mutex);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0632ebf0d971..9b17cc9bd459 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -42,6 +42,7 @@
#endif
#define STRING_LENGTH_OF_INT 12
+#define MAX_USR_CTRL_CNT 128
/*
* fill ring buffer with silence
@@ -2728,3 +2729,95 @@ int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream,
return 0;
}
EXPORT_SYMBOL_GPL(snd_pcm_add_volume_ctls);
+
+static int pcm_usr_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = MAX_USR_CTRL_CNT;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = INT_MAX;
+ return 0;
+}
+
+static void pcm_usr_ctl_private_free(struct snd_kcontrol *kcontrol)
+{
+ struct snd_pcm_usr *info = snd_kcontrol_chip(kcontrol);
+ info->pcm->streams[info->stream].usr_kctl = NULL;
+ kfree(info);
+}
+
+/**
+ * snd_pcm_add_usr_ctls - create user control elements
+ * @pcm: the assigned PCM instance
+ * @stream: stream direction
+ * @max_length: the max length of the user parameter of stream
+ * @private_value: the value passed to each kcontrol's private_value field
+ * @info_ret: store struct snd_pcm_usr instance if non-NULL
+ *
+ * Create usr control elements assigned to the given PCM stream(s).
+ * Returns zero if succeed, or a negative error value.
+ */
+int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream,
+ const struct snd_pcm_usr_elem *usr,
+ int max_length, int max_kctrl_str_len,
+ unsigned long private_value,
+ struct snd_pcm_usr **info_ret)
+{
+ struct snd_pcm_usr *info;
+ struct snd_kcontrol_new knew = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = pcm_usr_ctl_info,
+ };
+ int err;
+ char *buf;
+
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info) {
+ pr_err("%s: snd_pcm_usr alloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ info->pcm = pcm;
+ info->stream = stream;
+ info->usr = usr;
+ info->max_length = max_length;
+ buf = kzalloc(max_kctrl_str_len, GFP_KERNEL);
+ if (!buf) {
+ pr_err("%s: buffer allocation failed\n", __func__);
+ kfree(info);
+ return -ENOMEM;
+ }
+ knew.name = buf;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snprintf(buf, max_kctrl_str_len, "%s %d %s",
+ "Playback", pcm->device, "User kcontrol");
+ else
+ snprintf(buf, max_kctrl_str_len, "%s %d %s",
+ "Capture", pcm->device, "User kcontrol");
+ knew.device = pcm->device;
+ knew.count = pcm->streams[stream].substream_count;
+ knew.private_value = private_value;
+ info->kctl = snd_ctl_new1(&knew, info);
+ if (!info->kctl) {
+ kfree(info);
+ kfree(knew.name);
+ pr_err("%s: snd_ctl_new failed\n", __func__);
+ return -ENOMEM;
+ }
+ info->kctl->private_free = pcm_usr_ctl_private_free;
+ err = snd_ctl_add(pcm->card, info->kctl);
+ if (err < 0) {
+ kfree(info);
+ kfree(knew.name);
+ pr_err("%s: snd_ctl_add failed:%d\n", __func__,
+ err);
+ return -ENOMEM;
+ }
+ pcm->streams[stream].usr_kctl = info->kctl;
+ if (info_ret)
+ *info_ret = info;
+ kfree(knew.name);
+ return 0;
+}
+EXPORT_SYMBOL(snd_pcm_add_usr_ctls);