From 7dfadb9409b0046e6f9ac1fc5930146b41d6562d Mon Sep 17 00:00:00 2001 From: Meng Wang Date: Mon, 13 Apr 2020 10:41:16 +0800 Subject: [PATCH] asoc: routing: move volume and app type cfg controls from asoc to driver Move volume and app type cfg controls from asoc to audio drivers. Change-Id: I5c5d84a9a0536c7d8d95a8ca20cc176b31ca5b63 Signed-off-by: Meng Wang --- asoc/msm-pcm-routing-v2.c | 184 ++++++++++++++++++++++++++++++++++++++ asoc/msm-pcm-routing-v2.h | 51 +++++++++++ 2 files changed, 235 insertions(+) diff --git a/asoc/msm-pcm-routing-v2.c b/asoc/msm-pcm-routing-v2.c index e8dbaf402cb0..2d6a4d5a5534 100644 --- a/asoc/msm-pcm-routing-v2.c +++ b/asoc/msm-pcm-routing-v2.c @@ -49,6 +49,9 @@ #define DS2_ADM_COPP_TOPOLOGY_ID 0xFFFFFFFF #endif +#define STRING_LENGTH_OF_INT 12 +#define MAX_USR_CTRL_CNT 128 + static struct mutex routing_lock; static struct cal_type_data *cal_data[MAX_ROUTING_CAL_TYPES]; @@ -167,6 +170,187 @@ static int msm_routing_send_device_pp_params(int port_id, int copp_idx, static void msm_routing_load_topology(size_t data_size, void *data); static void msm_routing_unload_topology(uint32_t topology_id); +#ifndef SND_PCM_ADD_VOLUME_CTL +static int pcm_volume_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0x2000; + return 0; +} + +static void pcm_volume_ctl_private_free(struct snd_kcontrol *kcontrol) +{ + struct snd_pcm_volume *info = snd_kcontrol_chip(kcontrol); + + kfree(info); +} + +/** + * snd_pcm_add_volume_ctls - create volume control elements + * @pcm: the assigned PCM instance + * @stream: stream direction + * @max_length: the max length of the volume parameter of stream + * @private_value: the value passed to each kcontrol's private_value field + * @info_ret: store struct snd_pcm_volume instance if non-NULL + * + * Create volume control elements assigned to the given PCM stream(s). + * Returns zero if succeed, or a negative error value. + */ +int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_volume_elem *volume, + int max_length, + unsigned long private_value, + struct snd_pcm_volume **info_ret) +{ + int err = 0; + int size = 0; + struct snd_pcm_volume *info; + struct snd_kcontrol_new knew = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = pcm_volume_ctl_info, + }; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + info->pcm = pcm; + info->stream = stream; + info->volume = volume; + info->max_length = max_length; + size = sizeof("Playback ") + sizeof(" Volume") + + STRING_LENGTH_OF_INT*sizeof(char) + 1; + knew.name = kzalloc(size, GFP_KERNEL); + if (!knew.name) { + kfree(info); + return -ENOMEM; + } + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snprintf((char *)knew.name, size, "%s %d %s", + "Playback", pcm->device, "Volume"); + else + snprintf((char *)knew.name, size, "%s %d %s", + "Capture", pcm->device, "Volume"); + 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); + return -ENOMEM; + } + info->kctl->private_free = pcm_volume_ctl_private_free; + err = snd_ctl_add(pcm->card, info->kctl); + if (err < 0) { + kfree(info); + kfree(knew.name); + return -ENOMEM; + } + if (info_ret) + *info_ret = info; + kfree(knew.name); + return 0; +} +EXPORT_SYMBOL(snd_pcm_add_volume_ctls); +#endif + +#ifndef SND_PCM_ADD_USR_CTL +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); + + 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) +{ + int err = 0; + char *buf = NULL; + 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, + }; + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + 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; + } + if (info_ret) + *info_ret = info; + kfree(knew.name); + return 0; +} +EXPORT_SYMBOL(snd_pcm_add_usr_ctls); +#endif + static int msm_routing_get_bit_width(unsigned int format) { int bit_width; diff --git a/asoc/msm-pcm-routing-v2.h b/asoc/msm-pcm-routing-v2.h index 337875909a66..fafe0eba2663 100644 --- a/asoc/msm-pcm-routing-v2.h +++ b/asoc/msm-pcm-routing-v2.h @@ -653,4 +653,55 @@ int msm_pcm_routing_set_channel_mixer_runtime( int be_id, int session_id, int session_type, struct msm_pcm_channel_mixer *params); + +#ifndef SND_PCM_ADD_VOLUME_CTL +/* PCM Volume control API + */ +/* array element of volume */ +struct snd_pcm_volume_elem { + int volume; +}; + /* pp information; retrieved via snd_kcontrol_chip() */ +struct snd_pcm_volume { + struct snd_pcm *pcm; /* assigned PCM instance */ + int stream; /* PLAYBACK or CAPTURE */ + struct snd_kcontrol *kctl; + const struct snd_pcm_volume_elem *volume; + int max_length; + void *private_data; /* optional: private data pointer */ +}; + +int snd_pcm_add_volume_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_volume_elem *volume, + int max_length, + unsigned long private_value, + struct snd_pcm_volume **info_ret); + +#endif + +#ifndef SND_PCM_ADD_USR_CTL +/* + * PCM User control API 1450 + */ +/* array element of usr elem */ +struct snd_pcm_usr_elem { + int val[128]; +}; + +/* pp information; retrieved via snd_kcontrol_chip() */ +struct snd_pcm_usr { + struct snd_pcm *pcm; /* assigned PCM instance */ + int stream; /* PLAYBACK or CAPTURE */ + struct snd_kcontrol *kctl; + const struct snd_pcm_usr_elem *usr; + int max_length; + void *private_data; /* optional: private data pointer */ +}; + +int snd_pcm_add_usr_ctls(struct snd_pcm *pcm, int stream, + const struct snd_pcm_usr_elem *usr, + int max_length, int max_control_str_len, + unsigned long private_value, + struct snd_pcm_usr **info_ret); +#endif #endif /*_MSM_PCM_H*/