Merge "ASoC: msm: Add channel map control for multi channel pcm driver"
diff --git a/sound/soc/msm/msm-lowlatency-pcm-q6.c b/sound/soc/msm/msm-lowlatency-pcm-q6.c
index fcfcb66..98c28aa 100644
--- a/sound/soc/msm/msm-lowlatency-pcm-q6.c
+++ b/sound/soc/msm/msm-lowlatency-pcm-q6.c
@@ -224,14 +224,14 @@
 			prtd->channel_map[0] = PCM_CHANNEL_FL;
 		} else if (prtd->channel_mode == 2) {
 			prtd->channel_map[0] = PCM_CHANNEL_FL;
-			prtd->channel_map[0] = PCM_CHANNEL_FR;
+			prtd->channel_map[1] = PCM_CHANNEL_FR;
 		} else if (prtd->channel_mode == 6) {
 			prtd->channel_map[0] = PCM_CHANNEL_FC;
-			prtd->channel_map[0] = PCM_CHANNEL_FL;
-			prtd->channel_map[0] = PCM_CHANNEL_FR;
-			prtd->channel_map[0] = PCM_CHANNEL_LB;
-			prtd->channel_map[0] = PCM_CHANNEL_RB;
-			prtd->channel_map[0] = PCM_CHANNEL_LFE;
+			prtd->channel_map[1] = PCM_CHANNEL_FL;
+			prtd->channel_map[2] = PCM_CHANNEL_FR;
+			prtd->channel_map[3] = PCM_CHANNEL_LB;
+			prtd->channel_map[4] = PCM_CHANNEL_RB;
+			prtd->channel_map[5] = PCM_CHANNEL_LFE;
 		} else {
 			pr_err("%s: ERROR.unsupported num_ch = %u\n", __func__,
 				prtd->channel_mode);
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 7d04f95..bd4a521 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -276,8 +276,8 @@
 		if (prtd->channel_mode == 1) {
 			prtd->channel_map[0] = PCM_CHANNEL_FL;
 		} else if (prtd->channel_mode == 2) {
-			prtd->channel_map[1] = PCM_CHANNEL_FL;
-			prtd->channel_map[2] = PCM_CHANNEL_FR;
+			prtd->channel_map[0] = PCM_CHANNEL_FL;
+			prtd->channel_map[1] = PCM_CHANNEL_FR;
 		} else if (prtd->channel_mode == 6) {
 			prtd->channel_map[0] = PCM_CHANNEL_FC;
 			prtd->channel_map[1] = PCM_CHANNEL_FL;
@@ -513,16 +513,6 @@
 	return rc;
 }
 
-void multi_ch_pcm_set_channel_map(char *channel_mapping)
-{
-	pr_debug("%s\n", __func__);
-	if (multi_ch_pcm_audio.prtd) {
-		multi_ch_pcm_audio.prtd->set_channel_map = true;
-		memcpy(multi_ch_pcm_audio.prtd->channel_map, channel_mapping,
-			 PCM_FORMAT_MAX_NUM_CHANNEL);
-	}
-}
-
 static int msm_pcm_playback_copy(struct snd_pcm_substream *substream, int a,
 	snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
 {
@@ -823,13 +813,51 @@
 	.mmap		= msm_pcm_mmap,
 };
 
+
+static int pcm_chmap_ctl_put(struct snd_kcontrol *kcontrol,
+				struct snd_ctl_elem_value *ucontrol)
+{
+	int i;
+	char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
+
+	pr_debug("%s", __func__);
+	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
+		channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
+	if (multi_ch_pcm_audio.prtd) {
+		multi_ch_pcm_audio.prtd->set_channel_map = true;
+		memcpy(multi_ch_pcm_audio.prtd->channel_map, channel_mapping,
+			 PCM_FORMAT_MAX_NUM_CHANNEL);
+	}
+	return 0;
+}
+
+
 static int msm_asoc_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
 	struct snd_card *card = rtd->card->snd_card;
-	int ret = 0;
+	struct snd_pcm *pcm = rtd->pcm->streams[0].pcm;
+	struct snd_pcm_chmap *chmap_info;
+	struct snd_kcontrol *kctl;
+	char device_num[3];
 
+	int i, ret = 0;
 	if (!card->dev->coherent_dma_mask)
 		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	pr_debug("%s, Channel map cntrl add\n", __func__);
+	ret = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
+				NULL, PCM_FORMAT_MAX_NUM_CHANNEL, 0,
+				&chmap_info);
+	if (ret < 0)
+		return ret;
+	kctl = chmap_info->kctl;
+	for (i = 0; i < kctl->count; i++)
+		kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE;
+	snprintf(device_num, sizeof(device_num), "%d", pcm->device);
+	strlcat(kctl->id.name, device_num, sizeof(kctl->id.name));
+	pr_debug("%s, Overwriting channel map control name to: %s",
+			 __func__, kctl->id.name);
+	kctl->put = pcm_chmap_ctl_put;
 	return ret;
 }
 
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index 2b889b5..800bea8 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -78,7 +78,6 @@
 static const DECLARE_TLV_DB_LINEAR(compressed2_rx_vol_gain, 0,
 			INT_RX_VOL_MAX_STEPS);
 static int msm_route_ec_ref_rx;
-static char channel_mapping[PCM_FORMAT_MAX_NUM_CHANNEL];
 
 /* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
 #define MAX_EQ_SESSIONS		MSM_FRONTEND_DAI_CS_VOICE
@@ -864,27 +863,6 @@
 	return 0;
 }
 
-static int msm_routing_get_channel_map_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	int i;
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
-		ucontrol->value.integer.value[i] = channel_mapping[i];
-	return 0;
-}
-
-static int msm_routing_put_channel_map_mixer(struct snd_kcontrol *kcontrol,
-				struct snd_ctl_elem_value *ucontrol)
-{
-	int i;
-
-	for (i = 0; i < PCM_FORMAT_MAX_NUM_CHANNEL; i++)
-		channel_mapping[i] = (char)(ucontrol->value.integer.value[i]);
-	multi_ch_pcm_set_channel_map(channel_mapping);
-
-	return 0;
-}
-
 static int msm_routing_set_compressed_vol_mixer(struct snd_kcontrol *kcontrol,
 				struct snd_ctl_elem_value *ucontrol)
 {
@@ -1938,12 +1916,6 @@
 	msm_routing_set_compressed2_vol_mixer, compressed2_rx_vol_gain),
 };
 
-static const struct snd_kcontrol_new multi_ch_channel_map_mixer_controls[] = {
-	SOC_SINGLE_MULTI_EXT("Playback Channel Map", SND_SOC_NOPM, 0, 8,
-	0, 8, msm_routing_get_channel_map_mixer,
-	msm_routing_put_channel_map_mixer),
-};
-
 static const struct snd_kcontrol_new lpa_SRS_trumedia_controls[] = {
 	{.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.name = "SRS TruMedia",
@@ -2931,9 +2903,6 @@
 				ec_ref_rx_mixer_controls,
 			ARRAY_SIZE(ec_ref_rx_mixer_controls));
 
-	snd_soc_add_platform_controls(platform,
-				multi_ch_channel_map_mixer_controls,
-			ARRAY_SIZE(multi_ch_channel_map_mixer_controls));
 	return 0;
 }