blob: f136646eeb107b54a954da482908192584db8be6 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13
14#include <linux/init.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/platform_device.h>
19#include <linux/bitops.h>
Neema Shettyfeea7742011-09-11 12:30:36 -070020#include <linux/mutex.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <sound/core.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/pcm.h>
25#include <sound/initval.h>
26#include <sound/control.h>
27#include <sound/q6adm.h>
28#include <sound/q6afe.h>
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070029#include <sound/tlv.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030#include "msm-pcm-routing.h"
31#include "qdsp6/q6voice.h"
32
33struct audio_mixer_data {
34 u32 port_id; /* AFE port ID for Rx, FE DAI ID for TX */
35 unsigned long dai_sessions; /* Rx: FE DAIs Tx: BE DAI */
36 u32 mixer_type; /* playback or capture */
37};
38
Neema Shettyfeea7742011-09-11 12:30:36 -070039struct msm_pcm_routing_bdai_data {
40 u16 port_id; /* AFE port ID */
41 u8 active; /* track if this backend is enabled */
42 struct snd_pcm_hw_params *hw_params; /* to get freq and channel mode */
43 unsigned long fe_sessions; /* Front-end sessions */
44 unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
45};
46
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047#define INVALID_SESSION -1
48
Neema Shettyfeea7742011-09-11 12:30:36 -070049static struct mutex routing_lock;
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051enum {
52 AUDIO_MIXER_PRI_I2S_RX = 0,
53 AUDIO_MIXER_SLIMBUS_0_RX,
54 AUDIO_MIXER_HDMI_RX,
55 AUDIO_MIXER_MM_UL1,
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -070056 AUDIO_MIXER_MM_UL2,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070057 AUDIO_MIXER_INT_BT_SCO_RX,
58 AUDIO_MIXER_INT_FM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053059 AUDIO_MIXER_AFE_PCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070060 AUDIO_MIXER_AUX_PCM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070061 AUDIO_MIXER_MAX,
62};
63
64enum {
65 AUDIO_PORT_MIXER_SLIM_0_RX = 0,
66 AUDIO_PORT_MIXER_MAX,
67};
68
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070069static int fm_switch_enable;
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070070#define INT_FM_RX_VOL_MAX_STEPS 100
71#define INT_FM_RX_VOL_GAIN 2000
72
73static int msm_route_fm_vol_control;
74static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
75 INT_FM_RX_VOL_MAX_STEPS, 0);
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070076
Sriranjan Srikantam269de7f2011-09-06 18:24:45 -070077#define INT_LPA_RX_VOL_MAX_STEPS 100
78#define INT_LPA_RX_VOL_GAIN 0x2000
Asish Bhattacharya0ec76182011-07-29 16:58:11 +053079
80static int msm_route_lpa_vol_control;
81static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
82 INT_LPA_RX_VOL_MAX_STEPS, 0);
83
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070084/* Tx mixer session is stored based on BE DAI ID
85 * Need to map to actual AFE port ID since AFE port
86 * ID can get really large.
87 * The table convert DAI back to AFE port ID
88 */
89static int bedai_port_map[MSM_BACKEND_DAI_MAX] = {
90 PRIMARY_I2S_RX,
91 PRIMARY_I2S_TX,
92 SLIMBUS_0_RX,
93 SLIMBUS_0_TX,
94 HDMI_RX,
95 INT_BT_SCO_RX,
96 INT_BT_SCO_TX,
97 INT_FM_RX,
98 INT_FM_TX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053099 RT_PROXY_PORT_001_RX,
100 RT_PROXY_PORT_001_TX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700101 PCM_RX,
102 PCM_TX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700103};
104
Neema Shettyfeea7742011-09-11 12:30:36 -0700105/* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
106 * If new back-end is defined, add new back-end DAI ID at the end of enum
107 */
108static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
109 { PRIMARY_I2S_RX, 0, NULL, 0, 0},
110 { PRIMARY_I2S_TX, 0, NULL, 0, 0},
111 { SLIMBUS_0_RX, 0, NULL, 0, 0},
112 { SLIMBUS_0_TX, 0, NULL, 0, 0},
113 { HDMI_RX, 0, NULL, 0, 0},
114 { INT_BT_SCO_RX, 0, NULL, 0, 0},
115 { INT_BT_SCO_TX, 0, NULL, 0, 0},
116 { INT_FM_RX, 0, NULL, 0, 0},
117 { INT_FM_TX, 0, NULL, 0, 0},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530118 { RT_PROXY_PORT_001_RX, 0, NULL, 0, 0},
119 { RT_PROXY_PORT_001_TX, 0, NULL, 0, 0},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700120 { PCM_RX, 0, NULL, 0, 0},
121 { PCM_TX, 0, NULL, 0, 0},
Neema Shettyfeea7742011-09-11 12:30:36 -0700122};
123
124
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125/* Track ASM playback & capture sessions of DAI */
126static int fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
127 /* MULTIMEDIA1 */
128 {INVALID_SESSION, INVALID_SESSION},
129 /* MULTIMEDIA2 */
130 {INVALID_SESSION, INVALID_SESSION},
131 /* MULTIMEDIA3 */
132 {INVALID_SESSION, INVALID_SESSION},
133};
134
135static struct audio_mixer_data audio_mixers[AUDIO_MIXER_MAX] = {
136 /* AUDIO_MIXER_PRI_I2S_RX */
137 {PRIMARY_I2S_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
138 /* AUDIO_MIXER_SLIMBUS_0_RX */
139 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
140 /* AUDIO_MIXER_HDMI_RX */
141 {HDMI_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
142 /* AUDIO_MIXER_MM_UL1 */
143 {MSM_FRONTEND_DAI_MULTIMEDIA1, 0, SNDRV_PCM_STREAM_CAPTURE},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700144 /* AUDIO_MIXER_MM_UL2 */
145 {MSM_FRONTEND_DAI_MULTIMEDIA2, 0, SNDRV_PCM_STREAM_CAPTURE},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700146 /* AUDIO_MIXER_INT_BT_SCO_RX */
147 {INT_BT_SCO_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
148 /* AUDIO_MIXER_INT_FM_RX */
149 {INT_FM_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530150 /* AUDIO_MIXER_AFE_PCM_RX */
151 {RT_PROXY_PORT_001_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700152 /* AUDIO_MIXER_AUX_PCM_RX */
153 {PCM_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700155
156/* Reuse audio_mixer_data struct but ignore mixer type field
157 * unless there is use case for RX -> TX
158 */
159static struct audio_mixer_data audio_port_mixers[AUDIO_PORT_MIXER_MAX] = {
160 /* AUDIO_PORT_MIXER_SLIM_0_RX */
161 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
162};
163
164void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
165{
166 int i, be_id;
167
168 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
169 fe_dai_map[fedai_id][0] = dspst_id;
170 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
171 if ((audio_mixers[i].mixer_type == stream_type) &&
172 (test_bit(fedai_id, &audio_mixers[i].dai_sessions)))
173 /* To do: multiple devices case */
174 adm_route_session(audio_mixers[i].port_id,
175 dspst_id, 1);
176 }
177 } else {
178 fe_dai_map[fedai_id][1] = dspst_id;
179 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
180 if ((audio_mixers[i].mixer_type == stream_type) &&
181 (fedai_id == audio_mixers[i].port_id)) {
182 /* To-do: Handle mixing of inputs */
183 be_id = find_next_bit(
184 &audio_mixers[i].dai_sessions,
185 MSM_BACKEND_DAI_MAX, 0);
186 if (be_id < MSM_BACKEND_DAI_MAX)
187 adm_route_session(bedai_port_map[be_id],
188 dspst_id, 1);
189 else
190 pr_err("%s: no routing\n", __func__);
191 }
192 }
193 }
194}
195
196void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
197{
198 int i, be_id;
199
200 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
201 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
202 if ((audio_mixers[i].mixer_type == stream_type) &&
203 (test_bit(fedai_id, &audio_mixers[i].dai_sessions))) {
204 /* To do: multiple devices case */
205 adm_route_session(audio_mixers[i].port_id,
206 fe_dai_map[fedai_id][0], 0);
207 }
208 }
209 fe_dai_map[fedai_id][0] = INVALID_SESSION;
210 } else {
211 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
212 if ((audio_mixers[i].mixer_type == stream_type) &&
213 (fedai_id == audio_mixers[i].port_id)) {
214 /* To-do: Handle mixing of inputs */
215 be_id = find_next_bit(
216 &audio_mixers[i].dai_sessions,
217 MSM_BACKEND_DAI_MAX, 0);
218 if (be_id < MSM_BACKEND_DAI_MAX)
219 adm_route_session(bedai_port_map[be_id],
220 fe_dai_map[fedai_id][1], 0);
221 else
222 pr_err("%s: no routing\n", __func__);
223 }
224 }
225 fe_dai_map[fedai_id][1] = INVALID_SESSION;
226 }
227}
228
229static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
230{
231
232 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
233
234 if (set)
235 set_bit(val, &audio_mixers[reg].dai_sessions);
236 else
237 clear_bit(val, &audio_mixers[reg].dai_sessions);
238
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530239
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700240 if (audio_mixers[reg].mixer_type == SNDRV_PCM_STREAM_PLAYBACK) {
241 if (fe_dai_map[val][0] != INVALID_SESSION)
242 adm_route_session(audio_mixers[reg].port_id,
243 fe_dai_map[val][0], set);
244 } else {
245 int fe_id = audio_mixers[reg].port_id;
246 if (fe_dai_map[fe_id][1] != INVALID_SESSION)
247 adm_route_session(bedai_port_map[val],
248 fe_dai_map[fe_id][1], set);
249 }
250}
251
252static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol,
253 struct snd_ctl_elem_value *ucontrol)
254{
255 struct soc_mixer_control *mc =
256 (struct soc_mixer_control *)kcontrol->private_value;
257
258 if (test_bit(mc->shift, &audio_mixers[mc->reg].dai_sessions))
259 ucontrol->value.integer.value[0] = 1;
260 else
261 ucontrol->value.integer.value[0] = 0;
262
263 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
264 ucontrol->value.integer.value[0]);
265
266 return 0;
267}
268
269static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
270 struct snd_ctl_elem_value *ucontrol)
271{
Patrick Laiec2b8942011-09-01 11:01:51 -0700272 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
273 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274 struct soc_mixer_control *mc =
275 (struct soc_mixer_control *)kcontrol->private_value;
276
277
278 if (ucontrol->value.integer.value[0]) {
279 msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
280 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
281 } else {
282 msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
283 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
284 }
285
286 return 1;
287}
288
Neema Shettyfeea7742011-09-11 12:30:36 -0700289static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290{
Neema Shetty2c07eb52011-08-21 20:33:52 -0700291 u16 session_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292
Neema Shettyfeea7742011-09-11 12:30:36 -0700293 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700294
Neema Shettyfeea7742011-09-11 12:30:36 -0700295 if (val == MSM_FRONTEND_DAI_CS_VOICE)
Neema Shetty2c07eb52011-08-21 20:33:52 -0700296 session_id = voc_get_session_id(VOICE_SESSION_NAME);
297 else
298 session_id = voc_get_session_id(VOIP_SESSION_NAME);
299
300 pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
Neema Shettyfeea7742011-09-11 12:30:36 -0700301 __func__, val, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700302
Neema Shettyfeea7742011-09-11 12:30:36 -0700303 mutex_lock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700304
305 if (set)
Neema Shettyfeea7742011-09-11 12:30:36 -0700306 set_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307 else
Neema Shettyfeea7742011-09-11 12:30:36 -0700308 clear_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700309
Neema Shettyfeea7742011-09-11 12:30:36 -0700310 mutex_unlock(&routing_lock);
311
312 if (afe_get_port_type(msm_bedais[reg].port_id) ==
313 MSM_AFE_PORT_TYPE_RX) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700314 voc_set_route_flag(session_id, RX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700316 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700317 msm_bedais[reg].port_id, DEV_RX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700318
Neema Shetty2c07eb52011-08-21 20:33:52 -0700319 if (voc_get_route_flag(session_id, RX_PATH) &&
320 voc_get_route_flag(session_id, TX_PATH))
321 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700322 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700323 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700324 }
325 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700326 voc_set_route_flag(session_id, TX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700327 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700328 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700329 msm_bedais[reg].port_id, DEV_TX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700330
Neema Shetty2c07eb52011-08-21 20:33:52 -0700331 if (voc_get_route_flag(session_id, RX_PATH) &&
332 voc_get_route_flag(session_id, TX_PATH))
333 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700334 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700335 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336 }
337 }
338}
339
340static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol,
341 struct snd_ctl_elem_value *ucontrol)
342{
343 struct soc_mixer_control *mc =
344 (struct soc_mixer_control *)kcontrol->private_value;
345
Neema Shettyfeea7742011-09-11 12:30:36 -0700346 mutex_lock(&routing_lock);
347
348 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700349 ucontrol->value.integer.value[0] = 1;
350 else
351 ucontrol->value.integer.value[0] = 0;
352
Neema Shettyfeea7742011-09-11 12:30:36 -0700353 mutex_unlock(&routing_lock);
354
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
356 ucontrol->value.integer.value[0]);
357
358 return 0;
359}
360
361static int msm_routing_put_voice_mixer(struct snd_kcontrol *kcontrol,
362 struct snd_ctl_elem_value *ucontrol)
363{
Patrick Laiec2b8942011-09-01 11:01:51 -0700364 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
365 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 struct soc_mixer_control *mc =
367 (struct soc_mixer_control *)kcontrol->private_value;
368
369 if (ucontrol->value.integer.value[0]) {
Neema Shettyfeea7742011-09-11 12:30:36 -0700370 msm_pcm_routing_process_voice(mc->reg, mc->shift, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
372 } else {
Neema Shettyfeea7742011-09-11 12:30:36 -0700373 msm_pcm_routing_process_voice(mc->reg, mc->shift, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700374 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
375 }
376
377 return 1;
378}
379
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700380static int msm_routing_get_switch_mixer(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 ucontrol->value.integer.value[0] = fm_switch_enable;
384 pr_debug("%s: FM Switch enable %ld\n", __func__,
385 ucontrol->value.integer.value[0]);
386 return 0;
387}
388
389static int msm_routing_put_switch_mixer(struct snd_kcontrol *kcontrol,
390 struct snd_ctl_elem_value *ucontrol)
391{
392 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
393
394 pr_debug("%s: FM Switch enable %ld\n", __func__,
395 ucontrol->value.integer.value[0]);
396 if (ucontrol->value.integer.value[0])
397 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
398 else
399 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
400 fm_switch_enable = ucontrol->value.integer.value[0];
401 return 1;
402}
403
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700404static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
405 struct snd_ctl_elem_value *ucontrol)
406{
407 struct soc_mixer_control *mc =
408 (struct soc_mixer_control *)kcontrol->private_value;
409
410 if (test_bit(mc->shift, &audio_port_mixers[mc->reg].dai_sessions))
411 ucontrol->value.integer.value[0] = 1;
412 else
413 ucontrol->value.integer.value[0] = 0;
414
415 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
416 ucontrol->value.integer.value[0]);
417
418 return 0;
419}
420
421static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
422 struct snd_ctl_elem_value *ucontrol)
423{
424 struct soc_mixer_control *mc =
425 (struct soc_mixer_control *)kcontrol->private_value;
426
427 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
428 mc->shift, ucontrol->value.integer.value[0]);
429
430 if (ucontrol->value.integer.value[0]) {
431 afe_loopback(1, audio_port_mixers[mc->reg].port_id,
432 bedai_port_map[mc->shift]);
433 set_bit(mc->shift,
434 &audio_port_mixers[mc->reg].dai_sessions);
435 } else {
436 afe_loopback(0, audio_port_mixers[mc->reg].port_id,
437 bedai_port_map[mc->shift]);
438 clear_bit(mc->shift,
439 &audio_port_mixers[mc->reg].dai_sessions);
440 }
441
442 return 1;
443}
444
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700445static int msm_routing_get_fm_vol_mixer(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol)
447{
448 ucontrol->value.integer.value[0] = msm_route_fm_vol_control;
449 return 0;
450}
451
452static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
453 struct snd_ctl_elem_value *ucontrol)
454{
455 afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
456
457 msm_route_fm_vol_control = ucontrol->value.integer.value[0];
458
459 return 0;
460}
461
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530462static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_value *ucontrol)
464{
465 ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
466 return 0;
467}
468
469static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
471{
472 if (!lpa_set_volume(ucontrol->value.integer.value[0]))
473 msm_route_lpa_vol_control =
474 ucontrol->value.integer.value[0];
475
476 return 0;
477}
478
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700479static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
480 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_PRI_I2S_RX ,
481 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
482 msm_routing_put_audio_mixer),
483 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_PRI_I2S_RX,
484 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
485 msm_routing_put_audio_mixer),
486 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_PRI_I2S_RX,
487 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
488 msm_routing_put_audio_mixer),
489};
490
491static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
492 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_SLIMBUS_0_RX ,
493 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
494 msm_routing_put_audio_mixer),
495 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_SLIMBUS_0_RX,
496 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
497 msm_routing_put_audio_mixer),
498 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_SLIMBUS_0_RX,
499 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
500 msm_routing_put_audio_mixer),
501};
502
503static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
504 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_HDMI_RX,
505 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
506 msm_routing_put_audio_mixer),
507 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_HDMI_RX,
508 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
509 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530510 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_HDMI_RX,
511 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
512 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700513};
514
515static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
516 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_BT_SCO_RX,
517 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
518 msm_routing_put_audio_mixer),
519 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_BT_SCO_RX,
520 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
521 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530522 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_BT_SCO_RX,
523 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
524 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700525};
526
527static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
528 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_FM_RX,
529 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
530 msm_routing_put_audio_mixer),
531 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_FM_RX,
532 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
533 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530534 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_FM_RX,
535 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
536 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700537};
538
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530539static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
540 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_AFE_PCM_RX,
541 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
542 msm_routing_put_audio_mixer),
543 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_AFE_PCM_RX,
544 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
545 msm_routing_put_audio_mixer),
546 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_AFE_PCM_RX,
547 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
548 msm_routing_put_audio_mixer),
549};
550
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700551static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
552 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_AUX_PCM_RX ,
553 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
554 msm_routing_put_audio_mixer),
555 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_AUX_PCM_RX,
556 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
557 msm_routing_put_audio_mixer),
558 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_AUX_PCM_RX,
559 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
560 msm_routing_put_audio_mixer),
561};
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530562
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700563static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
564 SOC_SINGLE_EXT("PRI_TX", AUDIO_MIXER_MM_UL1,
565 MSM_BACKEND_DAI_PRI_I2S_TX, 1, 0, msm_routing_get_audio_mixer,
566 msm_routing_put_audio_mixer),
567 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_MIXER_MM_UL1,
568 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_audio_mixer,
569 msm_routing_put_audio_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700570 SOC_SINGLE_EXT("AUX_PCM_UL_TX", AUDIO_MIXER_MM_UL1,
571 MSM_BACKEND_DAI_AUXPCM_TX, 1, 0, msm_routing_get_audio_mixer,
572 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", AUDIO_MIXER_MM_UL1,
574 MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_audio_mixer,
575 msm_routing_put_audio_mixer),
576 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL1,
577 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
578 msm_routing_put_audio_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530579 SOC_SINGLE_EXT("AFE_PCM_TX", AUDIO_MIXER_MM_UL1,
580 MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, msm_routing_get_audio_mixer,
581 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700582};
583
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700584static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
585 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL2,
586 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
587 msm_routing_put_audio_mixer),
588};
589
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700590static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700591 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
592 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
593 msm_routing_put_voice_mixer),
594 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
595 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
596 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700597};
598
599static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700600 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
601 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
602 msm_routing_put_voice_mixer),
603 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
604 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
605 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700606};
607
608static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700609 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
610 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
611 msm_routing_put_voice_mixer),
612 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
613 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
614 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700615};
616
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530617static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
618 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
619 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
620 msm_routing_put_voice_mixer),
621 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
622 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
623 msm_routing_put_voice_mixer),
624};
625
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700626static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
627 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AUXPCM_RX,
628 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
629 msm_routing_put_voice_mixer),
630 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AUXPCM_RX,
631 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
632 msm_routing_put_voice_mixer),
633};
634
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700635static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700636 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
637 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
638 msm_routing_put_voice_mixer),
639 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
640 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
641 msm_routing_put_voice_mixer),
642 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
643 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700644 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530645 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
646 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
647 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700648 SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
649 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
650 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700651};
652
653static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700654 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
655 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
656 msm_routing_put_voice_mixer),
657 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
658 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
659 msm_routing_put_voice_mixer),
660 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
661 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
662 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530663 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
664 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
665 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700666 SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
667 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
668 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700669};
670
671static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
672 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
673 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
674 msm_routing_put_port_mixer),
675 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
676 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
677 msm_routing_put_port_mixer),
678};
679
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700680static const struct snd_kcontrol_new fm_switch_mixer_controls =
681 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
682 0, 1, 0, msm_routing_get_switch_mixer,
683 msm_routing_put_switch_mixer);
684
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700685static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
686 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
687 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
688 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
689};
690
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530691static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
692 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
693 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
694 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
695};
696
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
698 /* Frontend AIF */
699 /* Widget name equals to Front-End DAI name<Need confirmation>,
700 * Stream name must contains substring of front-end dai name
701 */
702 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
703 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
704 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
705 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
706 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700707 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700708 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
709 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
710 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
711 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
712 0, 0, 0, 0),
713 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
714 0, 0, 0, 0),
715 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
716 0, 0, 0, 0),
717 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
718 0, 0, 0, 0),
719 /* Backend AIF */
720 /* Stream name equals to backend dai link stream name
721 */
722 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
723 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
724 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
725 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
726 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
727 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
728 0, 0, 0 , 0),
729 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
730 0, 0, 0, 0),
731 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
732 0, 0, 0 , 0),
733 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
734 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530735 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
736 0, 0, 0 , 0),
737 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
738 0, 0, 0, 0),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700739 SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
740 SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700741 /* Switch Definitions */
742 SND_SOC_DAPM_SWITCH("SBUS_0_RX", SND_SOC_NOPM, 0, 0,
743 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744 /* Mixer definitions */
745 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
746 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
747 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
748 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
749 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
750 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
751 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
752 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700753 SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
754 mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700755 SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
756 auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700757 /* Voice Mixer */
758 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
759 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
760 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
761 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
762 SND_SOC_NOPM, 0, 0,
763 slimbus_rx_voice_mixer_controls,
764 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
765 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
766 SND_SOC_NOPM, 0, 0,
767 bt_sco_rx_voice_mixer_controls,
768 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530769 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
770 SND_SOC_NOPM, 0, 0,
771 afe_pcm_rx_voice_mixer_controls,
772 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700773 SND_SOC_DAPM_MIXER("AUX_PCM_RX_Voice Mixer",
774 SND_SOC_NOPM, 0, 0,
775 aux_pcm_rx_voice_mixer_controls,
776 ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
778 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
779 ARRAY_SIZE(tx_voice_mixer_controls)),
780 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
781 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
782 ARRAY_SIZE(tx_voip_mixer_controls)),
783 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
784 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
785 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
786 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530787 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
788 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
790 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
791 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
792};
793
794static const struct snd_soc_dapm_route intercon[] = {
795 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
796 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
797 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
798 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
799
800 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
801 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
802 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
803 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
804
805 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
806 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530807 {"HDMI Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 {"HDMI", NULL, "HDMI Mixer"},
809
810 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
811 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700812 {"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700813
814 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
815 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530816 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
818
819 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
820 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530821 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700822 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
823
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530824 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
825 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
826 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
827 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
828
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700829 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
830 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530831
832 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700833 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700834 {"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
835 {"MM_UL2", NULL, "MultiMedia2 Mixer"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700836
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700837 {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
838 {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
839 {"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
840 {"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
841
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700842 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
843 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
844 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
845
846 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
847 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
848 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
849
850 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
851 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
852 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
853
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530854 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
855 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
856 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
857
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700858 {"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
859 {"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
860 {"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
861
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700862 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
863 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
864 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530865 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700866 {"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700867 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
868 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
869 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
870 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530871 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700872 {"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
873
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700874 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700875 {"SLIMBUS_0_RX", "Switch", "SLIM0_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700876 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
877 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
878 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
879 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
880 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
881 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
882};
883
884static struct snd_pcm_ops msm_routing_pcm_ops = {};
885
886static unsigned int msm_routing_read(struct snd_soc_platform *platform,
887 unsigned int reg)
888{
889 dev_dbg(platform->dev, "reg %x\n", reg);
890 return 0;
891}
892
893/* Not used but frame seems to require it */
894static int msm_routing_write(struct snd_soc_platform *platform,
895 unsigned int reg, unsigned int val)
896{
897 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
898 return 0;
899}
900
901/* Not used but frame seems to require it */
902static int msm_routing_probe(struct snd_soc_platform *platform)
903{
904 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
905 ARRAY_SIZE(msm_qdsp6_widgets));
906 snd_soc_dapm_add_routes(&platform->dapm, intercon,
907 ARRAY_SIZE(intercon));
908
909 snd_soc_dapm_new_widgets(&platform->dapm);
910
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700911 snd_soc_add_platform_controls(platform,
912 int_fm_vol_mixer_controls,
913 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530914
915 snd_soc_add_platform_controls(platform,
916 lpa_vol_mixer_controls,
917 ARRAY_SIZE(lpa_vol_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700918 return 0;
919}
920
921static struct snd_soc_platform_driver msm_soc_routing_platform = {
922 .ops = &msm_routing_pcm_ops,
923 .probe = msm_routing_probe,
924 .read = msm_routing_read,
925 .write = msm_routing_write,
926};
927
928static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
929{
930 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
931 return snd_soc_register_platform(&pdev->dev,
932 &msm_soc_routing_platform);
933}
934
935static int msm_routing_pcm_remove(struct platform_device *pdev)
936{
937 snd_soc_unregister_platform(&pdev->dev);
938 return 0;
939}
940
941static struct platform_driver msm_routing_pcm_driver = {
942 .driver = {
943 .name = "msm-pcm-routing",
944 .owner = THIS_MODULE,
945 },
946 .probe = msm_routing_pcm_probe,
947 .remove = __devexit_p(msm_routing_pcm_remove),
948};
949
950static int __init msm_soc_routing_platform_init(void)
951{
Neema Shettyfeea7742011-09-11 12:30:36 -0700952 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700953 return platform_driver_register(&msm_routing_pcm_driver);
954}
955module_init(msm_soc_routing_platform_init);
956
957static void __exit msm_soc_routing_platform_exit(void)
958{
959 platform_driver_unregister(&msm_routing_pcm_driver);
960}
961module_exit(msm_soc_routing_platform_exit);
962
963MODULE_DESCRIPTION("MSM routing platform driver");
964MODULE_LICENSE("GPL v2");