blob: 2f917060069f78fbabea9f9bd976285f3315a2c1 [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),
500};
501
502static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
503 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_BT_SCO_RX,
504 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
505 msm_routing_put_audio_mixer),
506 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_BT_SCO_RX,
507 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
508 msm_routing_put_audio_mixer),
509};
510
511static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
512 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_FM_RX,
513 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
514 msm_routing_put_audio_mixer),
515 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_FM_RX,
516 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
517 msm_routing_put_audio_mixer),
518};
519
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530520static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
521 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_AFE_PCM_RX,
522 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
523 msm_routing_put_audio_mixer),
524 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_AFE_PCM_RX,
525 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
526 msm_routing_put_audio_mixer),
527 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_AFE_PCM_RX,
528 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
529 msm_routing_put_audio_mixer),
530};
531
532
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
534 SOC_SINGLE_EXT("PRI_TX", AUDIO_MIXER_MM_UL1,
535 MSM_BACKEND_DAI_PRI_I2S_TX, 1, 0, msm_routing_get_audio_mixer,
536 msm_routing_put_audio_mixer),
537 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_MIXER_MM_UL1,
538 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_audio_mixer,
539 msm_routing_put_audio_mixer),
540 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", AUDIO_MIXER_MM_UL1,
541 MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_audio_mixer,
542 msm_routing_put_audio_mixer),
543 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL1,
544 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
545 msm_routing_put_audio_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530546 SOC_SINGLE_EXT("AFE_PCM_TX", AUDIO_MIXER_MM_UL1,
547 MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, msm_routing_get_audio_mixer,
548 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700549};
550
551static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700552 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
553 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
554 msm_routing_put_voice_mixer),
555 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
556 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
557 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700558};
559
560static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700561 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_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_SLIMBUS_0_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 bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700570 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_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_INT_BT_SCO_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
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530578static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
579 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_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_AFE_PCM_RX,
583 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
584 msm_routing_put_voice_mixer),
585};
586
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700587static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700588 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
589 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
590 msm_routing_put_voice_mixer),
591 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
592 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
593 msm_routing_put_voice_mixer),
594 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
595 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700596 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530597 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
598 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
599 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700600};
601
602static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700603 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
604 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
605 msm_routing_put_voice_mixer),
606 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
607 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
608 msm_routing_put_voice_mixer),
609 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
610 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
611 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530612 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
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
617static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
618 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
619 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
620 msm_routing_put_port_mixer),
621 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
622 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
623 msm_routing_put_port_mixer),
624};
625
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700626static const struct snd_kcontrol_new fm_switch_mixer_controls =
627 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
628 0, 1, 0, msm_routing_get_switch_mixer,
629 msm_routing_put_switch_mixer);
630
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700631static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
632 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
633 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
634 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
635};
636
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530637static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
638 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
639 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
640 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
641};
642
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700643static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
644 /* Frontend AIF */
645 /* Widget name equals to Front-End DAI name<Need confirmation>,
646 * Stream name must contains substring of front-end dai name
647 */
648 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
649 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
650 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
651 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
652 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
653 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
654 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
655 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
656 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
657 0, 0, 0, 0),
658 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
659 0, 0, 0, 0),
660 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
661 0, 0, 0, 0),
662 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
663 0, 0, 0, 0),
664 /* Backend AIF */
665 /* Stream name equals to backend dai link stream name
666 */
667 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
668 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
669 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
670 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
671 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
672 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
673 0, 0, 0 , 0),
674 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
675 0, 0, 0, 0),
676 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
677 0, 0, 0 , 0),
678 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
679 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530680 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
681 0, 0, 0 , 0),
682 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
683 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700684 /* Switch Definitions */
685 SND_SOC_DAPM_SWITCH("SBUS_0_RX", SND_SOC_NOPM, 0, 0,
686 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700687 /* Mixer definitions */
688 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
689 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
690 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
691 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
692 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
693 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
694 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
695 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
696 /* Voice Mixer */
697 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
698 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
699 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
700 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
701 SND_SOC_NOPM, 0, 0,
702 slimbus_rx_voice_mixer_controls,
703 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
704 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
705 SND_SOC_NOPM, 0, 0,
706 bt_sco_rx_voice_mixer_controls,
707 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530708 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
709 SND_SOC_NOPM, 0, 0,
710 afe_pcm_rx_voice_mixer_controls,
711 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700712 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
713 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
714 ARRAY_SIZE(tx_voice_mixer_controls)),
715 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
716 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
717 ARRAY_SIZE(tx_voip_mixer_controls)),
718 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
719 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
720 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
721 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530722 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
723 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700724 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
725 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
726 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
727};
728
729static const struct snd_soc_dapm_route intercon[] = {
730 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
731 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
732 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
733 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
734
735 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
736 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
737 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
738 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
739
740 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
741 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
742 {"HDMI", NULL, "HDMI Mixer"},
743
744 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
745 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
746
747 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
748 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
749 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
750
751 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
752 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
753 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
754
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530755 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
756 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
757 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
758 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
759
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700760 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
761 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530762
763 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
765
766 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
767 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
768 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
769
770 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
771 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
772 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
773
774 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
775 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
776 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
777
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530778 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
779 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
780 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
781
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700782 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
783 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
784 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530785 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700786 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
787 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
788 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
789 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530790 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700792 {"SLIMBUS_0_RX", "Switch", "SLIM0_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700793 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
794 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
795 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
796 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
797 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
798 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
799};
800
801static struct snd_pcm_ops msm_routing_pcm_ops = {};
802
803static unsigned int msm_routing_read(struct snd_soc_platform *platform,
804 unsigned int reg)
805{
806 dev_dbg(platform->dev, "reg %x\n", reg);
807 return 0;
808}
809
810/* Not used but frame seems to require it */
811static int msm_routing_write(struct snd_soc_platform *platform,
812 unsigned int reg, unsigned int val)
813{
814 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
815 return 0;
816}
817
818/* Not used but frame seems to require it */
819static int msm_routing_probe(struct snd_soc_platform *platform)
820{
821 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
822 ARRAY_SIZE(msm_qdsp6_widgets));
823 snd_soc_dapm_add_routes(&platform->dapm, intercon,
824 ARRAY_SIZE(intercon));
825
826 snd_soc_dapm_new_widgets(&platform->dapm);
827
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700828 snd_soc_add_platform_controls(platform,
829 int_fm_vol_mixer_controls,
830 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530831
832 snd_soc_add_platform_controls(platform,
833 lpa_vol_mixer_controls,
834 ARRAY_SIZE(lpa_vol_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700835 return 0;
836}
837
838static struct snd_soc_platform_driver msm_soc_routing_platform = {
839 .ops = &msm_routing_pcm_ops,
840 .probe = msm_routing_probe,
841 .read = msm_routing_read,
842 .write = msm_routing_write,
843};
844
845static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
846{
847 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
848 return snd_soc_register_platform(&pdev->dev,
849 &msm_soc_routing_platform);
850}
851
852static int msm_routing_pcm_remove(struct platform_device *pdev)
853{
854 snd_soc_unregister_platform(&pdev->dev);
855 return 0;
856}
857
858static struct platform_driver msm_routing_pcm_driver = {
859 .driver = {
860 .name = "msm-pcm-routing",
861 .owner = THIS_MODULE,
862 },
863 .probe = msm_routing_pcm_probe,
864 .remove = __devexit_p(msm_routing_pcm_remove),
865};
866
867static int __init msm_soc_routing_platform_init(void)
868{
Neema Shettyfeea7742011-09-11 12:30:36 -0700869 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700870 return platform_driver_register(&msm_routing_pcm_driver);
871}
872module_init(msm_soc_routing_platform_init);
873
874static void __exit msm_soc_routing_platform_exit(void)
875{
876 platform_driver_unregister(&msm_routing_pcm_driver);
877}
878module_exit(msm_soc_routing_platform_exit);
879
880MODULE_DESCRIPTION("MSM routing platform driver");
881MODULE_LICENSE("GPL v2");