diff options
author | Sudheer Papothi <spapothi@codeaurora.org> | 2016-01-29 02:40:28 +0530 |
---|---|---|
committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:10:19 -0700 |
commit | abe342c13b3d2a6523eccc35ff4a9d124e48cc59 (patch) | |
tree | a91366fdfaba758fddd62644a3985d407d349b61 /sound | |
parent | 6ba6d2e98322dd4d8ea07b39d5129671c403ec03 (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.c | 4 | ||||
-rw-r--r-- | sound/core/pcm_lib.c | 93 |
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(®ister_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); |