blob: 70e081c82227307f9f474d8e6b6567064de70483 [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
Neema Shettyfeea7742011-09-11 12:30:36 -070033struct msm_pcm_routing_bdai_data {
34 u16 port_id; /* AFE port ID */
35 u8 active; /* track if this backend is enabled */
36 struct snd_pcm_hw_params *hw_params; /* to get freq and channel mode */
37 unsigned long fe_sessions; /* Front-end sessions */
38 unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
39};
40
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070041#define INVALID_SESSION -1
Patrick Laicf999112011-08-23 11:27:20 -070042#define SESSION_TYPE_RX 0
43#define SESSION_TYPE_TX 1
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070044
Neema Shettyfeea7742011-09-11 12:30:36 -070045static struct mutex routing_lock;
46
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070047static int fm_switch_enable;
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070048#define INT_FM_RX_VOL_MAX_STEPS 100
49#define INT_FM_RX_VOL_GAIN 2000
50
51static int msm_route_fm_vol_control;
52static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
53 INT_FM_RX_VOL_MAX_STEPS, 0);
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070054
Sriranjan Srikantam269de7f2011-09-06 18:24:45 -070055#define INT_LPA_RX_VOL_MAX_STEPS 100
56#define INT_LPA_RX_VOL_GAIN 0x2000
Asish Bhattacharya0ec76182011-07-29 16:58:11 +053057
58static int msm_route_lpa_vol_control;
59static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
60 INT_LPA_RX_VOL_MAX_STEPS, 0);
61
Neema Shettyfeea7742011-09-11 12:30:36 -070062/* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
63 * If new back-end is defined, add new back-end DAI ID at the end of enum
64 */
65static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
66 { PRIMARY_I2S_RX, 0, NULL, 0, 0},
67 { PRIMARY_I2S_TX, 0, NULL, 0, 0},
68 { SLIMBUS_0_RX, 0, NULL, 0, 0},
69 { SLIMBUS_0_TX, 0, NULL, 0, 0},
70 { HDMI_RX, 0, NULL, 0, 0},
71 { INT_BT_SCO_RX, 0, NULL, 0, 0},
72 { INT_BT_SCO_TX, 0, NULL, 0, 0},
73 { INT_FM_RX, 0, NULL, 0, 0},
74 { INT_FM_TX, 0, NULL, 0, 0},
Laxminath Kasam32657ec2011-08-01 19:26:57 +053075 { RT_PROXY_PORT_001_RX, 0, NULL, 0, 0},
76 { RT_PROXY_PORT_001_TX, 0, NULL, 0, 0},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -070077 { PCM_RX, 0, NULL, 0, 0},
78 { PCM_TX, 0, NULL, 0, 0},
Neema Shettyfeea7742011-09-11 12:30:36 -070079};
80
81
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070082/* Track ASM playback & capture sessions of DAI */
83static int fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
84 /* MULTIMEDIA1 */
85 {INVALID_SESSION, INVALID_SESSION},
86 /* MULTIMEDIA2 */
87 {INVALID_SESSION, INVALID_SESSION},
88 /* MULTIMEDIA3 */
89 {INVALID_SESSION, INVALID_SESSION},
90};
91
Patrick Laicf999112011-08-23 11:27:20 -070092static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
93 int path_type)
94{
95 int i, port_type;
96 struct route_payload payload;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070097
Patrick Laicf999112011-08-23 11:27:20 -070098 payload.num_copps = 0;
99 port_type = (path_type == ADM_PATH_PLAYBACK ?
100 MSM_AFE_PORT_TYPE_RX : MSM_AFE_PORT_TYPE_TX);
101
102 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
103 if ((afe_get_port_type(msm_bedais[i].port_id) ==
104 port_type) &&
105 msm_bedais[i].active && (test_bit(fedai_id,
106 &msm_bedais[i].fe_sessions)))
107 payload.copp_ids[payload.num_copps++] =
108 msm_bedais[i].port_id;
109 }
110
111 if (payload.num_copps)
112 adm_matrix_map(dspst_id, path_type,
113 payload.num_copps, payload.copp_ids, 0);
114}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115
116void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
117{
Patrick Laicf999112011-08-23 11:27:20 -0700118 int i, session_type, path_type, port_type;
119 struct route_payload payload;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120
121 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
Patrick Laicf999112011-08-23 11:27:20 -0700122 session_type = SESSION_TYPE_RX;
123 path_type = ADM_PATH_PLAYBACK;
124 port_type = MSM_AFE_PORT_TYPE_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700125 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700126 session_type = SESSION_TYPE_TX;
127 path_type = ADM_PATH_LIVE_REC;
128 port_type = MSM_AFE_PORT_TYPE_TX;
129 }
130
131 mutex_lock(&routing_lock);
132
133 payload.num_copps = 0; /* only RX needs to use payload */
134 fe_dai_map[fedai_id][session_type] = dspst_id;
135 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
136 if ((afe_get_port_type(msm_bedais[i].port_id) ==
137 port_type) && msm_bedais[i].active &&
138 (test_bit(fedai_id,
139 &msm_bedais[i].fe_sessions))) {
140 adm_open(msm_bedais[i].port_id,
141 path_type,
142 params_rate(msm_bedais[i].hw_params),
143 params_channels(msm_bedais[i].hw_params),
144 DEFAULT_COPP_TOPOLOGY);
145 payload.copp_ids[payload.num_copps++] =
146 msm_bedais[i].port_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147 }
148 }
Patrick Laicf999112011-08-23 11:27:20 -0700149 if (payload.num_copps)
150 adm_matrix_map(dspst_id, path_type,
151 payload.num_copps, payload.copp_ids, 0);
152
153 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700154}
155
156void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
157{
Patrick Laicf999112011-08-23 11:27:20 -0700158 int i, port_type, session_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700159
160 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
Patrick Laicf999112011-08-23 11:27:20 -0700161 port_type = MSM_AFE_PORT_TYPE_RX;
162 session_type = SESSION_TYPE_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700164 port_type = MSM_AFE_PORT_TYPE_TX;
165 session_type = SESSION_TYPE_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700166 }
Patrick Laicf999112011-08-23 11:27:20 -0700167
168 mutex_lock(&routing_lock);
169
170 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
171 if ((afe_get_port_type(msm_bedais[i].port_id) ==
172 port_type) && msm_bedais[i].active &&
173 (test_bit(fedai_id,
174 &msm_bedais[i].fe_sessions)))
175 adm_close(msm_bedais[i].port_id);
176 }
177
178 fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
179
180 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181}
182
183static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
184{
Patrick Laicf999112011-08-23 11:27:20 -0700185 int session_type, path_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700186
187 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
188
Patrick Laicf999112011-08-23 11:27:20 -0700189 if (afe_get_port_type(msm_bedais[reg].port_id) ==
190 MSM_AFE_PORT_TYPE_RX) {
191 session_type = SESSION_TYPE_RX;
192 path_type = ADM_PATH_PLAYBACK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700193 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700194 session_type = SESSION_TYPE_TX;
195 path_type = ADM_PATH_LIVE_REC;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700196 }
Patrick Laicf999112011-08-23 11:27:20 -0700197
198 mutex_lock(&routing_lock);
199
200 if (set) {
201 set_bit(val, &msm_bedais[reg].fe_sessions);
202 if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
203 INVALID_SESSION) {
204 adm_open(msm_bedais[reg].port_id, path_type,
205 params_rate(msm_bedais[reg].hw_params),
206 params_channels(msm_bedais[reg].hw_params),
207 DEFAULT_COPP_TOPOLOGY);
208 msm_pcm_routing_build_matrix(val,
209 fe_dai_map[val][session_type], path_type);
210 }
211 } else {
212 clear_bit(val, &msm_bedais[reg].fe_sessions);
213 if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
214 INVALID_SESSION) {
215 adm_close(msm_bedais[reg].port_id);
216 msm_pcm_routing_build_matrix(val,
217 fe_dai_map[val][session_type], path_type);
218 }
219 }
220
221 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222}
223
224static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol,
225 struct snd_ctl_elem_value *ucontrol)
226{
227 struct soc_mixer_control *mc =
228 (struct soc_mixer_control *)kcontrol->private_value;
229
Patrick Laicf999112011-08-23 11:27:20 -0700230 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231 ucontrol->value.integer.value[0] = 1;
232 else
233 ucontrol->value.integer.value[0] = 0;
234
235 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
236 ucontrol->value.integer.value[0]);
237
238 return 0;
239}
240
241static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
242 struct snd_ctl_elem_value *ucontrol)
243{
Patrick Laiec2b8942011-09-01 11:01:51 -0700244 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
245 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700246 struct soc_mixer_control *mc =
247 (struct soc_mixer_control *)kcontrol->private_value;
248
249
250 if (ucontrol->value.integer.value[0]) {
251 msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
252 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
253 } else {
254 msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
255 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
256 }
257
258 return 1;
259}
260
Neema Shettyfeea7742011-09-11 12:30:36 -0700261static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262{
Neema Shetty2c07eb52011-08-21 20:33:52 -0700263 u16 session_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700264
Neema Shettyfeea7742011-09-11 12:30:36 -0700265 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700266
Neema Shettyfeea7742011-09-11 12:30:36 -0700267 if (val == MSM_FRONTEND_DAI_CS_VOICE)
Neema Shetty2c07eb52011-08-21 20:33:52 -0700268 session_id = voc_get_session_id(VOICE_SESSION_NAME);
269 else
270 session_id = voc_get_session_id(VOIP_SESSION_NAME);
271
272 pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
Neema Shettyfeea7742011-09-11 12:30:36 -0700273 __func__, val, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700274
Neema Shettyfeea7742011-09-11 12:30:36 -0700275 mutex_lock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276
277 if (set)
Neema Shettyfeea7742011-09-11 12:30:36 -0700278 set_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700279 else
Neema Shettyfeea7742011-09-11 12:30:36 -0700280 clear_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281
Neema Shettyfeea7742011-09-11 12:30:36 -0700282 mutex_unlock(&routing_lock);
283
284 if (afe_get_port_type(msm_bedais[reg].port_id) ==
285 MSM_AFE_PORT_TYPE_RX) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700286 voc_set_route_flag(session_id, RX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700288 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700289 msm_bedais[reg].port_id, DEV_RX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290
Neema Shetty2c07eb52011-08-21 20:33:52 -0700291 if (voc_get_route_flag(session_id, RX_PATH) &&
292 voc_get_route_flag(session_id, TX_PATH))
293 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700294 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700295 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700296 }
297 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700298 voc_set_route_flag(session_id, TX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700299 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700300 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700301 msm_bedais[reg].port_id, DEV_TX);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700302 if (voc_get_route_flag(session_id, RX_PATH) &&
303 voc_get_route_flag(session_id, TX_PATH))
304 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700306 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700307 }
308 }
309}
310
311static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol,
312 struct snd_ctl_elem_value *ucontrol)
313{
314 struct soc_mixer_control *mc =
315 (struct soc_mixer_control *)kcontrol->private_value;
316
Neema Shettyfeea7742011-09-11 12:30:36 -0700317 mutex_lock(&routing_lock);
318
319 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320 ucontrol->value.integer.value[0] = 1;
321 else
322 ucontrol->value.integer.value[0] = 0;
323
Neema Shettyfeea7742011-09-11 12:30:36 -0700324 mutex_unlock(&routing_lock);
325
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700326 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
327 ucontrol->value.integer.value[0]);
328
329 return 0;
330}
331
332static int msm_routing_put_voice_mixer(struct snd_kcontrol *kcontrol,
333 struct snd_ctl_elem_value *ucontrol)
334{
Patrick Laiec2b8942011-09-01 11:01:51 -0700335 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
336 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 struct soc_mixer_control *mc =
338 (struct soc_mixer_control *)kcontrol->private_value;
339
340 if (ucontrol->value.integer.value[0]) {
Neema Shettyfeea7742011-09-11 12:30:36 -0700341 msm_pcm_routing_process_voice(mc->reg, mc->shift, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
343 } else {
Neema Shettyfeea7742011-09-11 12:30:36 -0700344 msm_pcm_routing_process_voice(mc->reg, mc->shift, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700345 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
346 }
347
348 return 1;
349}
350
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700351static int msm_routing_get_switch_mixer(struct snd_kcontrol *kcontrol,
352 struct snd_ctl_elem_value *ucontrol)
353{
354 ucontrol->value.integer.value[0] = fm_switch_enable;
355 pr_debug("%s: FM Switch enable %ld\n", __func__,
356 ucontrol->value.integer.value[0]);
357 return 0;
358}
359
360static int msm_routing_put_switch_mixer(struct snd_kcontrol *kcontrol,
361 struct snd_ctl_elem_value *ucontrol)
362{
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -0700363 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
364 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700365
366 pr_debug("%s: FM Switch enable %ld\n", __func__,
367 ucontrol->value.integer.value[0]);
368 if (ucontrol->value.integer.value[0])
369 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
370 else
371 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
372 fm_switch_enable = ucontrol->value.integer.value[0];
373 return 1;
374}
375
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700376static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
377 struct snd_ctl_elem_value *ucontrol)
378{
379 struct soc_mixer_control *mc =
380 (struct soc_mixer_control *)kcontrol->private_value;
381
Patrick Laicf999112011-08-23 11:27:20 -0700382 if (test_bit(mc->shift, &msm_bedais[mc->reg].port_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 ucontrol->value.integer.value[0] = 1;
384 else
385 ucontrol->value.integer.value[0] = 0;
386
387 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
388 ucontrol->value.integer.value[0]);
389
390 return 0;
391}
392
393static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
394 struct snd_ctl_elem_value *ucontrol)
395{
396 struct soc_mixer_control *mc =
397 (struct soc_mixer_control *)kcontrol->private_value;
398
399 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
400 mc->shift, ucontrol->value.integer.value[0]);
401
402 if (ucontrol->value.integer.value[0]) {
Patrick Laicf999112011-08-23 11:27:20 -0700403 afe_loopback(1, msm_bedais[mc->reg].port_id,
404 msm_bedais[mc->shift].port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 set_bit(mc->shift,
Patrick Laicf999112011-08-23 11:27:20 -0700406 &msm_bedais[mc->reg].port_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700408 afe_loopback(0, msm_bedais[mc->reg].port_id,
409 msm_bedais[mc->shift].port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700410 clear_bit(mc->shift,
Patrick Laicf999112011-08-23 11:27:20 -0700411 &msm_bedais[mc->reg].port_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700412 }
413
414 return 1;
415}
416
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700417static int msm_routing_get_fm_vol_mixer(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419{
420 ucontrol->value.integer.value[0] = msm_route_fm_vol_control;
421 return 0;
422}
423
424static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
425 struct snd_ctl_elem_value *ucontrol)
426{
427 afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
428
429 msm_route_fm_vol_control = ucontrol->value.integer.value[0];
430
431 return 0;
432}
433
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530434static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
435 struct snd_ctl_elem_value *ucontrol)
436{
437 ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
438 return 0;
439}
440
441static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
442 struct snd_ctl_elem_value *ucontrol)
443{
444 if (!lpa_set_volume(ucontrol->value.integer.value[0]))
445 msm_route_lpa_vol_control =
446 ucontrol->value.integer.value[0];
447
448 return 0;
449}
450
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700452 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
454 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700455 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_I2S_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700456 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
457 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700458 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_I2S_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700459 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
460 msm_routing_put_audio_mixer),
461};
462
463static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700464 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700465 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
466 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700467 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700468 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
469 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700470 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700471 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
472 msm_routing_put_audio_mixer),
473};
474
475static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700476 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700477 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
478 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700479 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_HDMI_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700480 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
481 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700482 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_HDMI_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530483 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
484 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700485};
486
487static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700488 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700489 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
490 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700491 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700492 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
493 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700494 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530495 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
496 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700497};
498
499static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700500 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_FM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700501 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
502 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700503 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT_FM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700504 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
505 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700506 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_FM_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530507 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
508 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700509};
510
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530511static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700512 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530513 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
514 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700515 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530516 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
517 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700518 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530519 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
520 msm_routing_put_audio_mixer),
521};
522
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700523static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700524 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700525 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
526 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700527 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700528 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
529 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700530 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700531 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
532 msm_routing_put_audio_mixer),
533};
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530534
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700535static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700536 SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
537 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
538 msm_routing_put_audio_mixer),
539 SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
540 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
541 msm_routing_put_audio_mixer),
542 SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
543 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
544 msm_routing_put_audio_mixer),
545 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
546 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
547 msm_routing_put_audio_mixer),
548 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
549 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
550 msm_routing_put_audio_mixer),
551 SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
552 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
553 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700554};
555
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700556static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700557 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
558 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700559 msm_routing_put_audio_mixer),
560};
561
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700563 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
564 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
565 msm_routing_put_voice_mixer),
566 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
567 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
568 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569};
570
571static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700572 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
573 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
574 msm_routing_put_voice_mixer),
575 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
576 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
577 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700578};
579
580static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700581 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
582 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
583 msm_routing_put_voice_mixer),
584 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
585 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
586 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700587};
588
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530589static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
590 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
591 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
592 msm_routing_put_voice_mixer),
593 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
594 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
595 msm_routing_put_voice_mixer),
596};
597
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700598static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
599 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AUXPCM_RX,
600 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
601 msm_routing_put_voice_mixer),
602 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AUXPCM_RX,
603 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
604 msm_routing_put_voice_mixer),
605};
606
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700607static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700608 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
609 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
610 msm_routing_put_voice_mixer),
611 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
612 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
613 msm_routing_put_voice_mixer),
614 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
615 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700616 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530617 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
618 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
619 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700620 SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
621 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
622 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700623};
624
625static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700626 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
627 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
628 msm_routing_put_voice_mixer),
629 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
630 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
631 msm_routing_put_voice_mixer),
632 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
633 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
634 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530635 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
636 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
637 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700638 SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
639 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
640 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700641};
642
643static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700644 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700645 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
646 msm_routing_put_port_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700647 SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700648 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
649 msm_routing_put_port_mixer),
650};
651
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700652static const struct snd_kcontrol_new fm_switch_mixer_controls =
653 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
654 0, 1, 0, msm_routing_get_switch_mixer,
655 msm_routing_put_switch_mixer);
656
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700657static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
658 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
659 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
660 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
661};
662
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530663static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
664 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
665 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
666 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
667};
668
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700669static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
670 /* Frontend AIF */
671 /* Widget name equals to Front-End DAI name<Need confirmation>,
672 * Stream name must contains substring of front-end dai name
673 */
674 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
675 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
676 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
677 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
678 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700679 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700680 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
681 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
682 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
683 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
684 0, 0, 0, 0),
685 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
686 0, 0, 0, 0),
687 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
688 0, 0, 0, 0),
689 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
690 0, 0, 0, 0),
691 /* Backend AIF */
692 /* Stream name equals to backend dai link stream name
693 */
694 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
695 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
696 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
697 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
698 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
699 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
700 0, 0, 0 , 0),
701 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
702 0, 0, 0, 0),
703 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
704 0, 0, 0 , 0),
705 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
706 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530707 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
708 0, 0, 0 , 0),
709 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
710 0, 0, 0, 0),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700711 SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
712 SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700713 /* Switch Definitions */
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -0700714 SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700715 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700716 /* Mixer definitions */
717 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
718 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
719 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
720 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
721 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
722 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
723 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
724 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700725 SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
726 mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700727 SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
728 auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729 /* Voice Mixer */
730 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
731 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
732 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
733 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
734 SND_SOC_NOPM, 0, 0,
735 slimbus_rx_voice_mixer_controls,
736 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
737 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
738 SND_SOC_NOPM, 0, 0,
739 bt_sco_rx_voice_mixer_controls,
740 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530741 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
742 SND_SOC_NOPM, 0, 0,
743 afe_pcm_rx_voice_mixer_controls,
744 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700745 SND_SOC_DAPM_MIXER("AUX_PCM_RX_Voice Mixer",
746 SND_SOC_NOPM, 0, 0,
747 aux_pcm_rx_voice_mixer_controls,
748 ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700749 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
750 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
751 ARRAY_SIZE(tx_voice_mixer_controls)),
752 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
753 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
754 ARRAY_SIZE(tx_voip_mixer_controls)),
755 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
756 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
757 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
758 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530759 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
760 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700761 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
762 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
763 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
764};
765
766static const struct snd_soc_dapm_route intercon[] = {
767 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
768 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
769 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
770 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
771
772 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
773 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
774 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
775 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
776
777 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
778 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530779 {"HDMI Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700780 {"HDMI", NULL, "HDMI Mixer"},
781
782 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
783 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700784 {"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700785
786 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
787 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530788 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
790
791 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
792 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530793 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700794 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
795
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530796 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
797 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
798 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
799 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
800
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700801 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
802 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530803
804 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700805 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700806 {"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
807 {"MM_UL2", NULL, "MultiMedia2 Mixer"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700809 {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
810 {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
811 {"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
812 {"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
813
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
815 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
816 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
817
818 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
819 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
820 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
821
822 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
823 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
824 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
825
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530826 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
827 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
828 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
829
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700830 {"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
831 {"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
832 {"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
833
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700834 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
835 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
836 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530837 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700838 {"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700839 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
840 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
841 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
842 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530843 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700844 {"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
845
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700846 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -0700847 {"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
848 {"SLIMBUS_0_RX", NULL, "SLIMBUS_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700849 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
850 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
851 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
852 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
853 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
854 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
855};
856
Patrick Laicf999112011-08-23 11:27:20 -0700857static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
858 struct snd_pcm_hw_params *params)
859{
860 struct snd_soc_pcm_runtime *rtd = substream->private_data;
861 unsigned int be_id = rtd->dai_link->be_id;
862
863 mutex_lock(&routing_lock);
864 msm_bedais[be_id].hw_params = params;
865 mutex_unlock(&routing_lock);
866 return 0;
867}
868
869static int msm_pcm_routing_close(struct snd_pcm_substream *substream)
870{
871 struct snd_soc_pcm_runtime *rtd = substream->private_data;
872 unsigned int be_id = rtd->dai_link->be_id;
873 int i, session_type;
874 struct msm_pcm_routing_bdai_data *bedai;
875
876 if (be_id >= MSM_BACKEND_DAI_MAX) {
877 pr_err("%s: unexpected be_id %d\n", __func__, be_id);
878 return -EINVAL;
879 }
880
881 bedai = &msm_bedais[be_id];
882
883 session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
884 0 : 1);
885
886 mutex_lock(&routing_lock);
887
888 for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
889 if (fe_dai_map[i][session_type] != INVALID_SESSION)
890 adm_close(bedai->port_id);
891 }
892
893 bedai->active = 0;
894 bedai->hw_params = NULL;
895
896 mutex_unlock(&routing_lock);
897
898 return 0;
899}
900
901static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
902{
903 struct snd_soc_pcm_runtime *rtd = substream->private_data;
904 unsigned int be_id = rtd->dai_link->be_id;
905 int i, path_type, session_type;
906 struct msm_pcm_routing_bdai_data *bedai;
907
908 if (be_id >= MSM_BACKEND_DAI_MAX) {
909 pr_err("%s: unexpected be_id %d\n", __func__, be_id);
910 return -EINVAL;
911 }
912
913
914 bedai = &msm_bedais[be_id];
915
Jay Wangc8e03a82011-10-31 11:53:23 -0700916 if (bedai->hw_params == NULL) {
917 pr_err("%s: HW param is not configured", __func__);
918 return -EINVAL;
919 }
920
921
Patrick Laicf999112011-08-23 11:27:20 -0700922 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
923 path_type = ADM_PATH_PLAYBACK;
924 session_type = SESSION_TYPE_RX;
925 } else {
926 path_type = ADM_PATH_LIVE_REC;
927 session_type = SESSION_TYPE_TX;
928 }
929
930 mutex_lock(&routing_lock);
931
932 if (bedai->active == 1)
933 goto done; /* Ignore prepare if back-end already active */
934
935 /* AFE port is not active at this point. However, still
936 * go ahead setting active flag under the notion that
937 * QDSP6 is able to handle ADM starting before AFE port
938 * is started.
939 */
940 bedai->active = 1;
941
942 for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
943 if (fe_dai_map[i][session_type] != INVALID_SESSION) {
944 adm_open(bedai->port_id, path_type,
945 params_rate(bedai->hw_params),
946 params_channels(bedai->hw_params),
947 DEFAULT_COPP_TOPOLOGY);
948 msm_pcm_routing_build_matrix(i,
949 fe_dai_map[i][session_type], path_type);
950 }
951 }
952
953done:
954 mutex_unlock(&routing_lock);
955
956 return 0;
957}
958
959static struct snd_pcm_ops msm_routing_pcm_ops = {
960 .hw_params = msm_pcm_routing_hw_params,
961 .close = msm_pcm_routing_close,
962 .prepare = msm_pcm_routing_prepare,
963};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700964
965static unsigned int msm_routing_read(struct snd_soc_platform *platform,
966 unsigned int reg)
967{
968 dev_dbg(platform->dev, "reg %x\n", reg);
969 return 0;
970}
971
972/* Not used but frame seems to require it */
973static int msm_routing_write(struct snd_soc_platform *platform,
974 unsigned int reg, unsigned int val)
975{
976 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
977 return 0;
978}
979
980/* Not used but frame seems to require it */
981static int msm_routing_probe(struct snd_soc_platform *platform)
982{
983 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
984 ARRAY_SIZE(msm_qdsp6_widgets));
985 snd_soc_dapm_add_routes(&platform->dapm, intercon,
986 ARRAY_SIZE(intercon));
987
988 snd_soc_dapm_new_widgets(&platform->dapm);
989
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700990 snd_soc_add_platform_controls(platform,
991 int_fm_vol_mixer_controls,
992 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530993
994 snd_soc_add_platform_controls(platform,
995 lpa_vol_mixer_controls,
996 ARRAY_SIZE(lpa_vol_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700997 return 0;
998}
999
1000static struct snd_soc_platform_driver msm_soc_routing_platform = {
1001 .ops = &msm_routing_pcm_ops,
1002 .probe = msm_routing_probe,
1003 .read = msm_routing_read,
1004 .write = msm_routing_write,
1005};
1006
1007static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
1008{
1009 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1010 return snd_soc_register_platform(&pdev->dev,
1011 &msm_soc_routing_platform);
1012}
1013
1014static int msm_routing_pcm_remove(struct platform_device *pdev)
1015{
1016 snd_soc_unregister_platform(&pdev->dev);
1017 return 0;
1018}
1019
1020static struct platform_driver msm_routing_pcm_driver = {
1021 .driver = {
1022 .name = "msm-pcm-routing",
1023 .owner = THIS_MODULE,
1024 },
1025 .probe = msm_routing_pcm_probe,
1026 .remove = __devexit_p(msm_routing_pcm_remove),
1027};
1028
1029static int __init msm_soc_routing_platform_init(void)
1030{
Neema Shettyfeea7742011-09-11 12:30:36 -07001031 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001032 return platform_driver_register(&msm_routing_pcm_driver);
1033}
1034module_init(msm_soc_routing_platform_init);
1035
1036static void __exit msm_soc_routing_platform_exit(void)
1037{
1038 platform_driver_unregister(&msm_routing_pcm_driver);
1039}
1040module_exit(msm_soc_routing_platform_exit);
1041
1042MODULE_DESCRIPTION("MSM routing platform driver");
1043MODULE_LICENSE("GPL v2");