Эх сурвалжийг харах

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 <[email protected]>
Meng Wang 5 жил өмнө
parent
commit
7dfadb9409

+ 184 - 0
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;

+ 51 - 0
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*/