blob: 2cae9c53dd1edbd6eb87fab4c9291371994deae8 [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,
56 AUDIO_MIXER_INT_BT_SCO_RX,
57 AUDIO_MIXER_INT_FM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053058 AUDIO_MIXER_AFE_PCM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070059 AUDIO_MIXER_MAX,
60};
61
62enum {
63 AUDIO_PORT_MIXER_SLIM_0_RX = 0,
64 AUDIO_PORT_MIXER_MAX,
65};
66
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070067static int fm_switch_enable;
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070068#define INT_FM_RX_VOL_MAX_STEPS 100
69#define INT_FM_RX_VOL_GAIN 2000
70
71static int msm_route_fm_vol_control;
72static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
73 INT_FM_RX_VOL_MAX_STEPS, 0);
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070074
Sriranjan Srikantam269de7f2011-09-06 18:24:45 -070075#define INT_LPA_RX_VOL_MAX_STEPS 100
76#define INT_LPA_RX_VOL_GAIN 0x2000
Asish Bhattacharya0ec76182011-07-29 16:58:11 +053077
78static int msm_route_lpa_vol_control;
79static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
80 INT_LPA_RX_VOL_MAX_STEPS, 0);
81
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082/* Tx mixer session is stored based on BE DAI ID
83 * Need to map to actual AFE port ID since AFE port
84 * ID can get really large.
85 * The table convert DAI back to AFE port ID
86 */
87static int bedai_port_map[MSM_BACKEND_DAI_MAX] = {
88 PRIMARY_I2S_RX,
89 PRIMARY_I2S_TX,
90 SLIMBUS_0_RX,
91 SLIMBUS_0_TX,
92 HDMI_RX,
93 INT_BT_SCO_RX,
94 INT_BT_SCO_TX,
95 INT_FM_RX,
96 INT_FM_TX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053097 RT_PROXY_PORT_001_RX,
98 RT_PROXY_PORT_001_TX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070099};
100
Neema Shettyfeea7742011-09-11 12:30:36 -0700101/* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
102 * If new back-end is defined, add new back-end DAI ID at the end of enum
103 */
104static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
105 { PRIMARY_I2S_RX, 0, NULL, 0, 0},
106 { PRIMARY_I2S_TX, 0, NULL, 0, 0},
107 { SLIMBUS_0_RX, 0, NULL, 0, 0},
108 { SLIMBUS_0_TX, 0, NULL, 0, 0},
109 { HDMI_RX, 0, NULL, 0, 0},
110 { INT_BT_SCO_RX, 0, NULL, 0, 0},
111 { INT_BT_SCO_TX, 0, NULL, 0, 0},
112 { INT_FM_RX, 0, NULL, 0, 0},
113 { INT_FM_TX, 0, NULL, 0, 0},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530114 { RT_PROXY_PORT_001_RX, 0, NULL, 0, 0},
115 { RT_PROXY_PORT_001_TX, 0, NULL, 0, 0},
Neema Shettyfeea7742011-09-11 12:30:36 -0700116};
117
118
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700119/* Track ASM playback & capture sessions of DAI */
120static int fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
121 /* MULTIMEDIA1 */
122 {INVALID_SESSION, INVALID_SESSION},
123 /* MULTIMEDIA2 */
124 {INVALID_SESSION, INVALID_SESSION},
125 /* MULTIMEDIA3 */
126 {INVALID_SESSION, INVALID_SESSION},
127};
128
129static struct audio_mixer_data audio_mixers[AUDIO_MIXER_MAX] = {
130 /* AUDIO_MIXER_PRI_I2S_RX */
131 {PRIMARY_I2S_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
132 /* AUDIO_MIXER_SLIMBUS_0_RX */
133 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
134 /* AUDIO_MIXER_HDMI_RX */
135 {HDMI_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
136 /* AUDIO_MIXER_MM_UL1 */
137 {MSM_FRONTEND_DAI_MULTIMEDIA1, 0, SNDRV_PCM_STREAM_CAPTURE},
138 /* AUDIO_MIXER_INT_BT_SCO_RX */
139 {INT_BT_SCO_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
140 /* AUDIO_MIXER_INT_FM_RX */
141 {INT_FM_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530142 /* AUDIO_MIXER_AFE_PCM_RX */
143 {RT_PROXY_PORT_001_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700145
146/* Reuse audio_mixer_data struct but ignore mixer type field
147 * unless there is use case for RX -> TX
148 */
149static struct audio_mixer_data audio_port_mixers[AUDIO_PORT_MIXER_MAX] = {
150 /* AUDIO_PORT_MIXER_SLIM_0_RX */
151 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
152};
153
154void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
155{
156 int i, be_id;
157
158 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
159 fe_dai_map[fedai_id][0] = dspst_id;
160 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
161 if ((audio_mixers[i].mixer_type == stream_type) &&
162 (test_bit(fedai_id, &audio_mixers[i].dai_sessions)))
163 /* To do: multiple devices case */
164 adm_route_session(audio_mixers[i].port_id,
165 dspst_id, 1);
166 }
167 } else {
168 fe_dai_map[fedai_id][1] = dspst_id;
169 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
170 if ((audio_mixers[i].mixer_type == stream_type) &&
171 (fedai_id == audio_mixers[i].port_id)) {
172 /* To-do: Handle mixing of inputs */
173 be_id = find_next_bit(
174 &audio_mixers[i].dai_sessions,
175 MSM_BACKEND_DAI_MAX, 0);
176 if (be_id < MSM_BACKEND_DAI_MAX)
177 adm_route_session(bedai_port_map[be_id],
178 dspst_id, 1);
179 else
180 pr_err("%s: no routing\n", __func__);
181 }
182 }
183 }
184}
185
186void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
187{
188 int i, be_id;
189
190 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
191 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
192 if ((audio_mixers[i].mixer_type == stream_type) &&
193 (test_bit(fedai_id, &audio_mixers[i].dai_sessions))) {
194 /* To do: multiple devices case */
195 adm_route_session(audio_mixers[i].port_id,
196 fe_dai_map[fedai_id][0], 0);
197 }
198 }
199 fe_dai_map[fedai_id][0] = INVALID_SESSION;
200 } else {
201 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
202 if ((audio_mixers[i].mixer_type == stream_type) &&
203 (fedai_id == audio_mixers[i].port_id)) {
204 /* To-do: Handle mixing of inputs */
205 be_id = find_next_bit(
206 &audio_mixers[i].dai_sessions,
207 MSM_BACKEND_DAI_MAX, 0);
208 if (be_id < MSM_BACKEND_DAI_MAX)
209 adm_route_session(bedai_port_map[be_id],
210 fe_dai_map[fedai_id][1], 0);
211 else
212 pr_err("%s: no routing\n", __func__);
213 }
214 }
215 fe_dai_map[fedai_id][1] = INVALID_SESSION;
216 }
217}
218
219static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
220{
221
222 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
223
224 if (set)
225 set_bit(val, &audio_mixers[reg].dai_sessions);
226 else
227 clear_bit(val, &audio_mixers[reg].dai_sessions);
228
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530229
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700230 if (audio_mixers[reg].mixer_type == SNDRV_PCM_STREAM_PLAYBACK) {
231 if (fe_dai_map[val][0] != INVALID_SESSION)
232 adm_route_session(audio_mixers[reg].port_id,
233 fe_dai_map[val][0], set);
234 } else {
235 int fe_id = audio_mixers[reg].port_id;
236 if (fe_dai_map[fe_id][1] != INVALID_SESSION)
237 adm_route_session(bedai_port_map[val],
238 fe_dai_map[fe_id][1], set);
239 }
240}
241
242static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol,
243 struct snd_ctl_elem_value *ucontrol)
244{
245 struct soc_mixer_control *mc =
246 (struct soc_mixer_control *)kcontrol->private_value;
247
248 if (test_bit(mc->shift, &audio_mixers[mc->reg].dai_sessions))
249 ucontrol->value.integer.value[0] = 1;
250 else
251 ucontrol->value.integer.value[0] = 0;
252
253 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
254 ucontrol->value.integer.value[0]);
255
256 return 0;
257}
258
259static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
260 struct snd_ctl_elem_value *ucontrol)
261{
Patrick Laiec2b8942011-09-01 11:01:51 -0700262 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
263 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264 struct soc_mixer_control *mc =
265 (struct soc_mixer_control *)kcontrol->private_value;
266
267
268 if (ucontrol->value.integer.value[0]) {
269 msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
270 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
271 } else {
272 msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
273 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
274 }
275
276 return 1;
277}
278
Neema Shettyfeea7742011-09-11 12:30:36 -0700279static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700280{
Neema Shetty2c07eb52011-08-21 20:33:52 -0700281 u16 session_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700282
Neema Shettyfeea7742011-09-11 12:30:36 -0700283 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700284
Neema Shettyfeea7742011-09-11 12:30:36 -0700285 if (val == MSM_FRONTEND_DAI_CS_VOICE)
Neema Shetty2c07eb52011-08-21 20:33:52 -0700286 session_id = voc_get_session_id(VOICE_SESSION_NAME);
287 else
288 session_id = voc_get_session_id(VOIP_SESSION_NAME);
289
290 pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
Neema Shettyfeea7742011-09-11 12:30:36 -0700291 __func__, val, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700292
Neema Shettyfeea7742011-09-11 12:30:36 -0700293 mutex_lock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700294
295 if (set)
Neema Shettyfeea7742011-09-11 12:30:36 -0700296 set_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297 else
Neema Shettyfeea7742011-09-11 12:30:36 -0700298 clear_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700299
Neema Shettyfeea7742011-09-11 12:30:36 -0700300 mutex_unlock(&routing_lock);
301
302 if (afe_get_port_type(msm_bedais[reg].port_id) ==
303 MSM_AFE_PORT_TYPE_RX) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700304 voc_set_route_flag(session_id, RX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700306 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700307 msm_bedais[reg].port_id, DEV_RX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308
Neema Shetty2c07eb52011-08-21 20:33:52 -0700309 if (voc_get_route_flag(session_id, RX_PATH) &&
310 voc_get_route_flag(session_id, TX_PATH))
311 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700312 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700313 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700314 }
315 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700316 voc_set_route_flag(session_id, TX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700318 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700319 msm_bedais[reg].port_id, DEV_TX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320
Neema Shetty2c07eb52011-08-21 20:33:52 -0700321 if (voc_get_route_flag(session_id, RX_PATH) &&
322 voc_get_route_flag(session_id, TX_PATH))
323 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700324 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700325 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700326 }
327 }
328}
329
330static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol,
331 struct snd_ctl_elem_value *ucontrol)
332{
333 struct soc_mixer_control *mc =
334 (struct soc_mixer_control *)kcontrol->private_value;
335
Neema Shettyfeea7742011-09-11 12:30:36 -0700336 mutex_lock(&routing_lock);
337
338 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700339 ucontrol->value.integer.value[0] = 1;
340 else
341 ucontrol->value.integer.value[0] = 0;
342
Neema Shettyfeea7742011-09-11 12:30:36 -0700343 mutex_unlock(&routing_lock);
344
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700345 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
346 ucontrol->value.integer.value[0]);
347
348 return 0;
349}
350
351static int msm_routing_put_voice_mixer(struct snd_kcontrol *kcontrol,
352 struct snd_ctl_elem_value *ucontrol)
353{
Patrick Laiec2b8942011-09-01 11:01:51 -0700354 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
355 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700356 struct soc_mixer_control *mc =
357 (struct soc_mixer_control *)kcontrol->private_value;
358
359 if (ucontrol->value.integer.value[0]) {
Neema Shettyfeea7742011-09-11 12:30:36 -0700360 msm_pcm_routing_process_voice(mc->reg, mc->shift, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700361 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
362 } else {
Neema Shettyfeea7742011-09-11 12:30:36 -0700363 msm_pcm_routing_process_voice(mc->reg, mc->shift, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
365 }
366
367 return 1;
368}
369
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700370static int msm_routing_get_switch_mixer(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 ucontrol->value.integer.value[0] = fm_switch_enable;
374 pr_debug("%s: FM Switch enable %ld\n", __func__,
375 ucontrol->value.integer.value[0]);
376 return 0;
377}
378
379static int msm_routing_put_switch_mixer(struct snd_kcontrol *kcontrol,
380 struct snd_ctl_elem_value *ucontrol)
381{
382 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
383
384 pr_debug("%s: FM Switch enable %ld\n", __func__,
385 ucontrol->value.integer.value[0]);
386 if (ucontrol->value.integer.value[0])
387 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
388 else
389 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
390 fm_switch_enable = ucontrol->value.integer.value[0];
391 return 1;
392}
393
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700394static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
395 struct snd_ctl_elem_value *ucontrol)
396{
397 struct soc_mixer_control *mc =
398 (struct soc_mixer_control *)kcontrol->private_value;
399
400 if (test_bit(mc->shift, &audio_port_mixers[mc->reg].dai_sessions))
401 ucontrol->value.integer.value[0] = 1;
402 else
403 ucontrol->value.integer.value[0] = 0;
404
405 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
406 ucontrol->value.integer.value[0]);
407
408 return 0;
409}
410
411static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
412 struct snd_ctl_elem_value *ucontrol)
413{
414 struct soc_mixer_control *mc =
415 (struct soc_mixer_control *)kcontrol->private_value;
416
417 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
418 mc->shift, ucontrol->value.integer.value[0]);
419
420 if (ucontrol->value.integer.value[0]) {
421 afe_loopback(1, audio_port_mixers[mc->reg].port_id,
422 bedai_port_map[mc->shift]);
423 set_bit(mc->shift,
424 &audio_port_mixers[mc->reg].dai_sessions);
425 } else {
426 afe_loopback(0, audio_port_mixers[mc->reg].port_id,
427 bedai_port_map[mc->shift]);
428 clear_bit(mc->shift,
429 &audio_port_mixers[mc->reg].dai_sessions);
430 }
431
432 return 1;
433}
434
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700435static int msm_routing_get_fm_vol_mixer(struct snd_kcontrol *kcontrol,
436 struct snd_ctl_elem_value *ucontrol)
437{
438 ucontrol->value.integer.value[0] = msm_route_fm_vol_control;
439 return 0;
440}
441
442static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
443 struct snd_ctl_elem_value *ucontrol)
444{
445 afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
446
447 msm_route_fm_vol_control = ucontrol->value.integer.value[0];
448
449 return 0;
450}
451
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530452static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
453 struct snd_ctl_elem_value *ucontrol)
454{
455 ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
456 return 0;
457}
458
459static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
460 struct snd_ctl_elem_value *ucontrol)
461{
462 if (!lpa_set_volume(ucontrol->value.integer.value[0]))
463 msm_route_lpa_vol_control =
464 ucontrol->value.integer.value[0];
465
466 return 0;
467}
468
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700469static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
470 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_PRI_I2S_RX ,
471 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
472 msm_routing_put_audio_mixer),
473 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_PRI_I2S_RX,
474 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
475 msm_routing_put_audio_mixer),
476 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_PRI_I2S_RX,
477 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
478 msm_routing_put_audio_mixer),
479};
480
481static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
482 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_SLIMBUS_0_RX ,
483 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
484 msm_routing_put_audio_mixer),
485 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_SLIMBUS_0_RX,
486 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
487 msm_routing_put_audio_mixer),
488 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_SLIMBUS_0_RX,
489 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
490 msm_routing_put_audio_mixer),
491};
492
493static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
494 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_HDMI_RX,
495 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
496 msm_routing_put_audio_mixer),
497 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_HDMI_RX,
498 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
499 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530500 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_HDMI_RX,
501 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
502 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700503};
504
505static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
506 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_BT_SCO_RX,
507 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
508 msm_routing_put_audio_mixer),
509 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_BT_SCO_RX,
510 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
511 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530512 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_BT_SCO_RX,
513 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
514 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700515};
516
517static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
518 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_FM_RX,
519 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
520 msm_routing_put_audio_mixer),
521 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_FM_RX,
522 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
523 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530524 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_FM_RX,
525 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
526 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700527};
528
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530529static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
530 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_AFE_PCM_RX,
531 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
532 msm_routing_put_audio_mixer),
533 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_AFE_PCM_RX,
534 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
535 msm_routing_put_audio_mixer),
536 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_AFE_PCM_RX,
537 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
538 msm_routing_put_audio_mixer),
539};
540
541
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700542static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
543 SOC_SINGLE_EXT("PRI_TX", AUDIO_MIXER_MM_UL1,
544 MSM_BACKEND_DAI_PRI_I2S_TX, 1, 0, msm_routing_get_audio_mixer,
545 msm_routing_put_audio_mixer),
546 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_MIXER_MM_UL1,
547 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_audio_mixer,
548 msm_routing_put_audio_mixer),
549 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", AUDIO_MIXER_MM_UL1,
550 MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_audio_mixer,
551 msm_routing_put_audio_mixer),
552 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL1,
553 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
554 msm_routing_put_audio_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530555 SOC_SINGLE_EXT("AFE_PCM_TX", AUDIO_MIXER_MM_UL1,
556 MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, msm_routing_get_audio_mixer,
557 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558};
559
560static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700561 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
562 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
563 msm_routing_put_voice_mixer),
564 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
565 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
566 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700567};
568
569static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700570 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
571 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
572 msm_routing_put_voice_mixer),
573 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
574 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
575 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700576};
577
578static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700579 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
580 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
581 msm_routing_put_voice_mixer),
582 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
583 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
584 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700585};
586
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530587static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
588 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
589 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
590 msm_routing_put_voice_mixer),
591 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
592 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
593 msm_routing_put_voice_mixer),
594};
595
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700596static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700597 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
598 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
599 msm_routing_put_voice_mixer),
600 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
601 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
602 msm_routing_put_voice_mixer),
603 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
604 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700605 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530606 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
607 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
608 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700609};
610
611static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700612 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
613 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
614 msm_routing_put_voice_mixer),
615 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
616 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
617 msm_routing_put_voice_mixer),
618 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
619 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
620 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530621 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
622 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
623 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700624};
625
626static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
627 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
628 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
629 msm_routing_put_port_mixer),
630 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
631 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
632 msm_routing_put_port_mixer),
633};
634
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700635static const struct snd_kcontrol_new fm_switch_mixer_controls =
636 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
637 0, 1, 0, msm_routing_get_switch_mixer,
638 msm_routing_put_switch_mixer);
639
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700640static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
641 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
642 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
643 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
644};
645
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530646static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
647 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
648 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
649 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
650};
651
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700652static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
653 /* Frontend AIF */
654 /* Widget name equals to Front-End DAI name<Need confirmation>,
655 * Stream name must contains substring of front-end dai name
656 */
657 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
658 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
659 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
660 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
661 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
662 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
663 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
664 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
665 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
666 0, 0, 0, 0),
667 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
668 0, 0, 0, 0),
669 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
670 0, 0, 0, 0),
671 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
672 0, 0, 0, 0),
673 /* Backend AIF */
674 /* Stream name equals to backend dai link stream name
675 */
676 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
677 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
678 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
679 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
680 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
681 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
682 0, 0, 0 , 0),
683 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
684 0, 0, 0, 0),
685 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
686 0, 0, 0 , 0),
687 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
688 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530689 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
690 0, 0, 0 , 0),
691 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
692 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700693 /* Switch Definitions */
694 SND_SOC_DAPM_SWITCH("SBUS_0_RX", SND_SOC_NOPM, 0, 0,
695 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700696 /* Mixer definitions */
697 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
698 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
699 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
700 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
701 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
702 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
703 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
704 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
705 /* Voice Mixer */
706 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
707 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
708 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
709 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
710 SND_SOC_NOPM, 0, 0,
711 slimbus_rx_voice_mixer_controls,
712 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
713 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
714 SND_SOC_NOPM, 0, 0,
715 bt_sco_rx_voice_mixer_controls,
716 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530717 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
718 SND_SOC_NOPM, 0, 0,
719 afe_pcm_rx_voice_mixer_controls,
720 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700721 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
722 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
723 ARRAY_SIZE(tx_voice_mixer_controls)),
724 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
725 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
726 ARRAY_SIZE(tx_voip_mixer_controls)),
727 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
728 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
729 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
730 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530731 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
732 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
734 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
735 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
736};
737
738static const struct snd_soc_dapm_route intercon[] = {
739 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
740 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
741 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
742 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
743
744 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
745 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
746 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
747 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
748
749 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
750 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530751 {"HDMI Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700752 {"HDMI", NULL, "HDMI Mixer"},
753
754 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
755 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
756
757 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
758 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530759 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
761
762 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
763 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530764 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700765 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
766
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530767 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
768 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
769 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
770 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
771
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
773 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530774
775 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700776 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
777
778 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
779 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
780 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
781
782 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
783 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
784 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
785
786 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
787 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
788 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
789
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530790 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
791 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
792 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
793
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
795 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
796 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530797 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700798 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
799 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
800 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
801 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530802 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700803 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700804 {"SLIMBUS_0_RX", "Switch", "SLIM0_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
806 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
807 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
808 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
809 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
810 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
811};
812
813static struct snd_pcm_ops msm_routing_pcm_ops = {};
814
815static unsigned int msm_routing_read(struct snd_soc_platform *platform,
816 unsigned int reg)
817{
818 dev_dbg(platform->dev, "reg %x\n", reg);
819 return 0;
820}
821
822/* Not used but frame seems to require it */
823static int msm_routing_write(struct snd_soc_platform *platform,
824 unsigned int reg, unsigned int val)
825{
826 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
827 return 0;
828}
829
830/* Not used but frame seems to require it */
831static int msm_routing_probe(struct snd_soc_platform *platform)
832{
833 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
834 ARRAY_SIZE(msm_qdsp6_widgets));
835 snd_soc_dapm_add_routes(&platform->dapm, intercon,
836 ARRAY_SIZE(intercon));
837
838 snd_soc_dapm_new_widgets(&platform->dapm);
839
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700840 snd_soc_add_platform_controls(platform,
841 int_fm_vol_mixer_controls,
842 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530843
844 snd_soc_add_platform_controls(platform,
845 lpa_vol_mixer_controls,
846 ARRAY_SIZE(lpa_vol_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700847 return 0;
848}
849
850static struct snd_soc_platform_driver msm_soc_routing_platform = {
851 .ops = &msm_routing_pcm_ops,
852 .probe = msm_routing_probe,
853 .read = msm_routing_read,
854 .write = msm_routing_write,
855};
856
857static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
858{
859 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
860 return snd_soc_register_platform(&pdev->dev,
861 &msm_soc_routing_platform);
862}
863
864static int msm_routing_pcm_remove(struct platform_device *pdev)
865{
866 snd_soc_unregister_platform(&pdev->dev);
867 return 0;
868}
869
870static struct platform_driver msm_routing_pcm_driver = {
871 .driver = {
872 .name = "msm-pcm-routing",
873 .owner = THIS_MODULE,
874 },
875 .probe = msm_routing_pcm_probe,
876 .remove = __devexit_p(msm_routing_pcm_remove),
877};
878
879static int __init msm_soc_routing_platform_init(void)
880{
Neema Shettyfeea7742011-09-11 12:30:36 -0700881 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700882 return platform_driver_register(&msm_routing_pcm_driver);
883}
884module_init(msm_soc_routing_platform_init);
885
886static void __exit msm_soc_routing_platform_exit(void)
887{
888 platform_driver_unregister(&msm_routing_pcm_driver);
889}
890module_exit(msm_soc_routing_platform_exit);
891
892MODULE_DESCRIPTION("MSM routing platform driver");
893MODULE_LICENSE("GPL v2");