blob: 358dbdb9d801f6fde9dca1ede7edd20d8f85362d [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13
14#include <linux/init.h>
15#include <linux/err.h>
16#include <linux/module.h>
17#include <linux/moduleparam.h>
18#include <linux/platform_device.h>
19#include <linux/bitops.h>
Neema Shettyfeea7742011-09-11 12:30:36 -070020#include <linux/mutex.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070021#include <sound/core.h>
22#include <sound/soc.h>
23#include <sound/soc-dapm.h>
24#include <sound/pcm.h>
25#include <sound/initval.h>
26#include <sound/control.h>
27#include <sound/q6adm.h>
28#include <sound/q6afe.h>
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070029#include <sound/tlv.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070030#include "msm-pcm-routing.h"
31#include "qdsp6/q6voice.h"
32
33struct audio_mixer_data {
34 u32 port_id; /* AFE port ID for Rx, FE DAI ID for TX */
35 unsigned long dai_sessions; /* Rx: FE DAIs Tx: BE DAI */
36 u32 mixer_type; /* playback or capture */
37};
38
Neema Shettyfeea7742011-09-11 12:30:36 -070039struct msm_pcm_routing_bdai_data {
40 u16 port_id; /* AFE port ID */
41 u8 active; /* track if this backend is enabled */
42 struct snd_pcm_hw_params *hw_params; /* to get freq and channel mode */
43 unsigned long fe_sessions; /* Front-end sessions */
44 unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
45};
46
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047#define INVALID_SESSION -1
48
Neema Shettyfeea7742011-09-11 12:30:36 -070049static struct mutex routing_lock;
50
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070051enum {
52 AUDIO_MIXER_PRI_I2S_RX = 0,
53 AUDIO_MIXER_SLIMBUS_0_RX,
54 AUDIO_MIXER_HDMI_RX,
55 AUDIO_MIXER_MM_UL1,
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -070056 AUDIO_MIXER_MM_UL2,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070057 AUDIO_MIXER_INT_BT_SCO_RX,
58 AUDIO_MIXER_INT_FM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053059 AUDIO_MIXER_AFE_PCM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070060 AUDIO_MIXER_MAX,
61};
62
63enum {
64 AUDIO_PORT_MIXER_SLIM_0_RX = 0,
65 AUDIO_PORT_MIXER_MAX,
66};
67
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070068static int fm_switch_enable;
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070069#define INT_FM_RX_VOL_MAX_STEPS 100
70#define INT_FM_RX_VOL_GAIN 2000
71
72static int msm_route_fm_vol_control;
73static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
74 INT_FM_RX_VOL_MAX_STEPS, 0);
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070075
Sriranjan Srikantam269de7f2011-09-06 18:24:45 -070076#define INT_LPA_RX_VOL_MAX_STEPS 100
77#define INT_LPA_RX_VOL_GAIN 0x2000
Asish Bhattacharya0ec76182011-07-29 16:58:11 +053078
79static int msm_route_lpa_vol_control;
80static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
81 INT_LPA_RX_VOL_MAX_STEPS, 0);
82
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070083/* Tx mixer session is stored based on BE DAI ID
84 * Need to map to actual AFE port ID since AFE port
85 * ID can get really large.
86 * The table convert DAI back to AFE port ID
87 */
88static int bedai_port_map[MSM_BACKEND_DAI_MAX] = {
89 PRIMARY_I2S_RX,
90 PRIMARY_I2S_TX,
91 SLIMBUS_0_RX,
92 SLIMBUS_0_TX,
93 HDMI_RX,
94 INT_BT_SCO_RX,
95 INT_BT_SCO_TX,
96 INT_FM_RX,
97 INT_FM_TX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +053098 RT_PROXY_PORT_001_RX,
99 RT_PROXY_PORT_001_TX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700100};
101
Neema Shettyfeea7742011-09-11 12:30:36 -0700102/* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
103 * If new back-end is defined, add new back-end DAI ID at the end of enum
104 */
105static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
106 { PRIMARY_I2S_RX, 0, NULL, 0, 0},
107 { PRIMARY_I2S_TX, 0, NULL, 0, 0},
108 { SLIMBUS_0_RX, 0, NULL, 0, 0},
109 { SLIMBUS_0_TX, 0, NULL, 0, 0},
110 { HDMI_RX, 0, NULL, 0, 0},
111 { INT_BT_SCO_RX, 0, NULL, 0, 0},
112 { INT_BT_SCO_TX, 0, NULL, 0, 0},
113 { INT_FM_RX, 0, NULL, 0, 0},
114 { INT_FM_TX, 0, NULL, 0, 0},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530115 { RT_PROXY_PORT_001_RX, 0, NULL, 0, 0},
116 { RT_PROXY_PORT_001_TX, 0, NULL, 0, 0},
Neema Shettyfeea7742011-09-11 12:30:36 -0700117};
118
119
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120/* Track ASM playback & capture sessions of DAI */
121static int fe_dai_map[MSM_FRONTEND_DAI_MAX][2] = {
122 /* MULTIMEDIA1 */
123 {INVALID_SESSION, INVALID_SESSION},
124 /* MULTIMEDIA2 */
125 {INVALID_SESSION, INVALID_SESSION},
126 /* MULTIMEDIA3 */
127 {INVALID_SESSION, INVALID_SESSION},
128};
129
130static struct audio_mixer_data audio_mixers[AUDIO_MIXER_MAX] = {
131 /* AUDIO_MIXER_PRI_I2S_RX */
132 {PRIMARY_I2S_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
133 /* AUDIO_MIXER_SLIMBUS_0_RX */
134 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
135 /* AUDIO_MIXER_HDMI_RX */
136 {HDMI_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
137 /* AUDIO_MIXER_MM_UL1 */
138 {MSM_FRONTEND_DAI_MULTIMEDIA1, 0, SNDRV_PCM_STREAM_CAPTURE},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700139 /* AUDIO_MIXER_MM_UL2 */
140 {MSM_FRONTEND_DAI_MULTIMEDIA2, 0, SNDRV_PCM_STREAM_CAPTURE},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141 /* AUDIO_MIXER_INT_BT_SCO_RX */
142 {INT_BT_SCO_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
143 /* AUDIO_MIXER_INT_FM_RX */
144 {INT_FM_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530145 /* AUDIO_MIXER_AFE_PCM_RX */
146 {RT_PROXY_PORT_001_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148
149/* Reuse audio_mixer_data struct but ignore mixer type field
150 * unless there is use case for RX -> TX
151 */
152static struct audio_mixer_data audio_port_mixers[AUDIO_PORT_MIXER_MAX] = {
153 /* AUDIO_PORT_MIXER_SLIM_0_RX */
154 {SLIMBUS_0_RX, 0, SNDRV_PCM_STREAM_PLAYBACK},
155};
156
157void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
158{
159 int i, be_id;
160
161 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
162 fe_dai_map[fedai_id][0] = dspst_id;
163 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
164 if ((audio_mixers[i].mixer_type == stream_type) &&
165 (test_bit(fedai_id, &audio_mixers[i].dai_sessions)))
166 /* To do: multiple devices case */
167 adm_route_session(audio_mixers[i].port_id,
168 dspst_id, 1);
169 }
170 } else {
171 fe_dai_map[fedai_id][1] = dspst_id;
172 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
173 if ((audio_mixers[i].mixer_type == stream_type) &&
174 (fedai_id == audio_mixers[i].port_id)) {
175 /* To-do: Handle mixing of inputs */
176 be_id = find_next_bit(
177 &audio_mixers[i].dai_sessions,
178 MSM_BACKEND_DAI_MAX, 0);
179 if (be_id < MSM_BACKEND_DAI_MAX)
180 adm_route_session(bedai_port_map[be_id],
181 dspst_id, 1);
182 else
183 pr_err("%s: no routing\n", __func__);
184 }
185 }
186 }
187}
188
189void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
190{
191 int i, be_id;
192
193 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
194 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
195 if ((audio_mixers[i].mixer_type == stream_type) &&
196 (test_bit(fedai_id, &audio_mixers[i].dai_sessions))) {
197 /* To do: multiple devices case */
198 adm_route_session(audio_mixers[i].port_id,
199 fe_dai_map[fedai_id][0], 0);
200 }
201 }
202 fe_dai_map[fedai_id][0] = INVALID_SESSION;
203 } else {
204 for (i = 0; i < AUDIO_MIXER_MAX; i++) {
205 if ((audio_mixers[i].mixer_type == stream_type) &&
206 (fedai_id == audio_mixers[i].port_id)) {
207 /* To-do: Handle mixing of inputs */
208 be_id = find_next_bit(
209 &audio_mixers[i].dai_sessions,
210 MSM_BACKEND_DAI_MAX, 0);
211 if (be_id < MSM_BACKEND_DAI_MAX)
212 adm_route_session(bedai_port_map[be_id],
213 fe_dai_map[fedai_id][1], 0);
214 else
215 pr_err("%s: no routing\n", __func__);
216 }
217 }
218 fe_dai_map[fedai_id][1] = INVALID_SESSION;
219 }
220}
221
222static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
223{
224
225 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
226
227 if (set)
228 set_bit(val, &audio_mixers[reg].dai_sessions);
229 else
230 clear_bit(val, &audio_mixers[reg].dai_sessions);
231
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530232
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233 if (audio_mixers[reg].mixer_type == SNDRV_PCM_STREAM_PLAYBACK) {
234 if (fe_dai_map[val][0] != INVALID_SESSION)
235 adm_route_session(audio_mixers[reg].port_id,
236 fe_dai_map[val][0], set);
237 } else {
238 int fe_id = audio_mixers[reg].port_id;
239 if (fe_dai_map[fe_id][1] != INVALID_SESSION)
240 adm_route_session(bedai_port_map[val],
241 fe_dai_map[fe_id][1], set);
242 }
243}
244
245static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol,
246 struct snd_ctl_elem_value *ucontrol)
247{
248 struct soc_mixer_control *mc =
249 (struct soc_mixer_control *)kcontrol->private_value;
250
251 if (test_bit(mc->shift, &audio_mixers[mc->reg].dai_sessions))
252 ucontrol->value.integer.value[0] = 1;
253 else
254 ucontrol->value.integer.value[0] = 0;
255
256 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
257 ucontrol->value.integer.value[0]);
258
259 return 0;
260}
261
262static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
263 struct snd_ctl_elem_value *ucontrol)
264{
Patrick Laiec2b8942011-09-01 11:01:51 -0700265 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
266 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267 struct soc_mixer_control *mc =
268 (struct soc_mixer_control *)kcontrol->private_value;
269
270
271 if (ucontrol->value.integer.value[0]) {
272 msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
273 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
274 } else {
275 msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
276 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
277 }
278
279 return 1;
280}
281
Neema Shettyfeea7742011-09-11 12:30:36 -0700282static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700283{
Neema Shetty2c07eb52011-08-21 20:33:52 -0700284 u16 session_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700285
Neema Shettyfeea7742011-09-11 12:30:36 -0700286 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700287
Neema Shettyfeea7742011-09-11 12:30:36 -0700288 if (val == MSM_FRONTEND_DAI_CS_VOICE)
Neema Shetty2c07eb52011-08-21 20:33:52 -0700289 session_id = voc_get_session_id(VOICE_SESSION_NAME);
290 else
291 session_id = voc_get_session_id(VOIP_SESSION_NAME);
292
293 pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
Neema Shettyfeea7742011-09-11 12:30:36 -0700294 __func__, val, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295
Neema Shettyfeea7742011-09-11 12:30:36 -0700296 mutex_lock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700297
298 if (set)
Neema Shettyfeea7742011-09-11 12:30:36 -0700299 set_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700300 else
Neema Shettyfeea7742011-09-11 12:30:36 -0700301 clear_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700302
Neema Shettyfeea7742011-09-11 12:30:36 -0700303 mutex_unlock(&routing_lock);
304
305 if (afe_get_port_type(msm_bedais[reg].port_id) ==
306 MSM_AFE_PORT_TYPE_RX) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700307 voc_set_route_flag(session_id, RX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700308 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700309 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700310 msm_bedais[reg].port_id, DEV_RX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700311
Neema Shetty2c07eb52011-08-21 20:33:52 -0700312 if (voc_get_route_flag(session_id, RX_PATH) &&
313 voc_get_route_flag(session_id, TX_PATH))
314 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700316 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317 }
318 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700319 voc_set_route_flag(session_id, TX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700321 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700322 msm_bedais[reg].port_id, DEV_TX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700323
Neema Shetty2c07eb52011-08-21 20:33:52 -0700324 if (voc_get_route_flag(session_id, RX_PATH) &&
325 voc_get_route_flag(session_id, TX_PATH))
326 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700327 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700328 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700329 }
330 }
331}
332
333static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol,
334 struct snd_ctl_elem_value *ucontrol)
335{
336 struct soc_mixer_control *mc =
337 (struct soc_mixer_control *)kcontrol->private_value;
338
Neema Shettyfeea7742011-09-11 12:30:36 -0700339 mutex_lock(&routing_lock);
340
341 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700342 ucontrol->value.integer.value[0] = 1;
343 else
344 ucontrol->value.integer.value[0] = 0;
345
Neema Shettyfeea7742011-09-11 12:30:36 -0700346 mutex_unlock(&routing_lock);
347
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700348 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
349 ucontrol->value.integer.value[0]);
350
351 return 0;
352}
353
354static int msm_routing_put_voice_mixer(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
Patrick Laiec2b8942011-09-01 11:01:51 -0700357 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
358 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700359 struct soc_mixer_control *mc =
360 (struct soc_mixer_control *)kcontrol->private_value;
361
362 if (ucontrol->value.integer.value[0]) {
Neema Shettyfeea7742011-09-11 12:30:36 -0700363 msm_pcm_routing_process_voice(mc->reg, mc->shift, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
365 } else {
Neema Shettyfeea7742011-09-11 12:30:36 -0700366 msm_pcm_routing_process_voice(mc->reg, mc->shift, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
368 }
369
370 return 1;
371}
372
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700373static int msm_routing_get_switch_mixer(struct snd_kcontrol *kcontrol,
374 struct snd_ctl_elem_value *ucontrol)
375{
376 ucontrol->value.integer.value[0] = fm_switch_enable;
377 pr_debug("%s: FM Switch enable %ld\n", __func__,
378 ucontrol->value.integer.value[0]);
379 return 0;
380}
381
382static int msm_routing_put_switch_mixer(struct snd_kcontrol *kcontrol,
383 struct snd_ctl_elem_value *ucontrol)
384{
385 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
386
387 pr_debug("%s: FM Switch enable %ld\n", __func__,
388 ucontrol->value.integer.value[0]);
389 if (ucontrol->value.integer.value[0])
390 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
391 else
392 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
393 fm_switch_enable = ucontrol->value.integer.value[0];
394 return 1;
395}
396
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700397static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
398 struct snd_ctl_elem_value *ucontrol)
399{
400 struct soc_mixer_control *mc =
401 (struct soc_mixer_control *)kcontrol->private_value;
402
403 if (test_bit(mc->shift, &audio_port_mixers[mc->reg].dai_sessions))
404 ucontrol->value.integer.value[0] = 1;
405 else
406 ucontrol->value.integer.value[0] = 0;
407
408 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
409 ucontrol->value.integer.value[0]);
410
411 return 0;
412}
413
414static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
415 struct snd_ctl_elem_value *ucontrol)
416{
417 struct soc_mixer_control *mc =
418 (struct soc_mixer_control *)kcontrol->private_value;
419
420 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
421 mc->shift, ucontrol->value.integer.value[0]);
422
423 if (ucontrol->value.integer.value[0]) {
424 afe_loopback(1, audio_port_mixers[mc->reg].port_id,
425 bedai_port_map[mc->shift]);
426 set_bit(mc->shift,
427 &audio_port_mixers[mc->reg].dai_sessions);
428 } else {
429 afe_loopback(0, audio_port_mixers[mc->reg].port_id,
430 bedai_port_map[mc->shift]);
431 clear_bit(mc->shift,
432 &audio_port_mixers[mc->reg].dai_sessions);
433 }
434
435 return 1;
436}
437
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700438static int msm_routing_get_fm_vol_mixer(struct snd_kcontrol *kcontrol,
439 struct snd_ctl_elem_value *ucontrol)
440{
441 ucontrol->value.integer.value[0] = msm_route_fm_vol_control;
442 return 0;
443}
444
445static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
446 struct snd_ctl_elem_value *ucontrol)
447{
448 afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
449
450 msm_route_fm_vol_control = ucontrol->value.integer.value[0];
451
452 return 0;
453}
454
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530455static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
456 struct snd_ctl_elem_value *ucontrol)
457{
458 ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
459 return 0;
460}
461
462static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
463 struct snd_ctl_elem_value *ucontrol)
464{
465 if (!lpa_set_volume(ucontrol->value.integer.value[0]))
466 msm_route_lpa_vol_control =
467 ucontrol->value.integer.value[0];
468
469 return 0;
470}
471
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700472static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
473 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_PRI_I2S_RX ,
474 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
475 msm_routing_put_audio_mixer),
476 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_PRI_I2S_RX,
477 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
478 msm_routing_put_audio_mixer),
479 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_PRI_I2S_RX,
480 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
481 msm_routing_put_audio_mixer),
482};
483
484static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
485 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_SLIMBUS_0_RX ,
486 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
487 msm_routing_put_audio_mixer),
488 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_SLIMBUS_0_RX,
489 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
490 msm_routing_put_audio_mixer),
491 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_SLIMBUS_0_RX,
492 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
493 msm_routing_put_audio_mixer),
494};
495
496static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
497 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_HDMI_RX,
498 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
499 msm_routing_put_audio_mixer),
500 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_HDMI_RX,
501 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
502 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530503 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_HDMI_RX,
504 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
505 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700506};
507
508static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
509 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_BT_SCO_RX,
510 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
511 msm_routing_put_audio_mixer),
512 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_INT_BT_SCO_RX,
513 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
514 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530515 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_BT_SCO_RX,
516 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
517 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700518};
519
520static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
521 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_INT_FM_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_INT_FM_RX,
525 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
526 msm_routing_put_audio_mixer),
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530527 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_INT_FM_RX,
528 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
529 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700530};
531
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530532static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
533 SOC_SINGLE_EXT("MultiMedia1", AUDIO_MIXER_AFE_PCM_RX,
534 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
535 msm_routing_put_audio_mixer),
536 SOC_SINGLE_EXT("MultiMedia2", AUDIO_MIXER_AFE_PCM_RX,
537 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
538 msm_routing_put_audio_mixer),
539 SOC_SINGLE_EXT("MultiMedia3", AUDIO_MIXER_AFE_PCM_RX,
540 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
541 msm_routing_put_audio_mixer),
542};
543
544
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700545static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
546 SOC_SINGLE_EXT("PRI_TX", AUDIO_MIXER_MM_UL1,
547 MSM_BACKEND_DAI_PRI_I2S_TX, 1, 0, msm_routing_get_audio_mixer,
548 msm_routing_put_audio_mixer),
549 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_MIXER_MM_UL1,
550 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_audio_mixer,
551 msm_routing_put_audio_mixer),
552 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", AUDIO_MIXER_MM_UL1,
553 MSM_BACKEND_DAI_INT_BT_SCO_TX, 1, 0, msm_routing_get_audio_mixer,
554 msm_routing_put_audio_mixer),
555 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL1,
556 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
557 msm_routing_put_audio_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530558 SOC_SINGLE_EXT("AFE_PCM_TX", AUDIO_MIXER_MM_UL1,
559 MSM_BACKEND_DAI_AFE_PCM_TX, 1, 0, msm_routing_get_audio_mixer,
560 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700561};
562
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700563static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
564 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_MIXER_MM_UL2,
565 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_audio_mixer,
566 msm_routing_put_audio_mixer),
567};
568
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700570 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_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_PRI_I2S_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 slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700579 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_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_SLIMBUS_0_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
587static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700588 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_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_INT_BT_SCO_RX ,
592 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
593 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700594};
595
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530596static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
597 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
598 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
599 msm_routing_put_voice_mixer),
600 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
601 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
602 msm_routing_put_voice_mixer),
603};
604
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700605static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700606 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
607 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
608 msm_routing_put_voice_mixer),
609 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
610 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
611 msm_routing_put_voice_mixer),
612 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
613 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700614 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530615 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
616 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
617 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700618};
619
620static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700621 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
622 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
623 msm_routing_put_voice_mixer),
624 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
625 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
626 msm_routing_put_voice_mixer),
627 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
628 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
629 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530630 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
631 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
632 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700633};
634
635static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
636 SOC_SINGLE_EXT("INTERNAL_FM_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
637 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
638 msm_routing_put_port_mixer),
639 SOC_SINGLE_EXT("SLIM_0_TX", AUDIO_PORT_MIXER_SLIM_0_RX,
640 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
641 msm_routing_put_port_mixer),
642};
643
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700644static const struct snd_kcontrol_new fm_switch_mixer_controls =
645 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
646 0, 1, 0, msm_routing_get_switch_mixer,
647 msm_routing_put_switch_mixer);
648
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700649static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
650 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
651 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
652 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
653};
654
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530655static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
656 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
657 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
658 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
659};
660
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
662 /* Frontend AIF */
663 /* Widget name equals to Front-End DAI name<Need confirmation>,
664 * Stream name must contains substring of front-end dai name
665 */
666 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
667 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
668 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
669 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
670 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700671 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700672 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
673 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
674 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
675 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
676 0, 0, 0, 0),
677 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
678 0, 0, 0, 0),
679 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
680 0, 0, 0, 0),
681 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
682 0, 0, 0, 0),
683 /* Backend AIF */
684 /* Stream name equals to backend dai link stream name
685 */
686 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
687 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
688 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
689 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
690 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
691 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
692 0, 0, 0 , 0),
693 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
694 0, 0, 0, 0),
695 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
696 0, 0, 0 , 0),
697 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
698 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530699 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
700 0, 0, 0 , 0),
701 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
702 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700703 /* Switch Definitions */
704 SND_SOC_DAPM_SWITCH("SBUS_0_RX", SND_SOC_NOPM, 0, 0,
705 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700706 /* Mixer definitions */
707 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
708 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
709 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
710 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
711 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
712 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
713 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
714 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700715 SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
716 mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700717 /* Voice Mixer */
718 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
719 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
720 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
721 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
722 SND_SOC_NOPM, 0, 0,
723 slimbus_rx_voice_mixer_controls,
724 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
725 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
726 SND_SOC_NOPM, 0, 0,
727 bt_sco_rx_voice_mixer_controls,
728 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530729 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
730 SND_SOC_NOPM, 0, 0,
731 afe_pcm_rx_voice_mixer_controls,
732 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700733 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
734 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
735 ARRAY_SIZE(tx_voice_mixer_controls)),
736 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
737 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
738 ARRAY_SIZE(tx_voip_mixer_controls)),
739 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
740 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
741 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
742 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530743 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
744 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700745 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
746 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
747 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
748};
749
750static const struct snd_soc_dapm_route intercon[] = {
751 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
752 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
753 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
754 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
755
756 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
757 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
758 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
759 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
760
761 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
762 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530763 {"HDMI Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700764 {"HDMI", NULL, "HDMI Mixer"},
765
766 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
767 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
768
769 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
770 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530771 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700772 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
773
774 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
775 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530776 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700777 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
778
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530779 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
780 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
781 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
782 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
783
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700784 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
785 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530786
787 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700788 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700789 {"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
790 {"MM_UL2", NULL, "MultiMedia2 Mixer"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700791
792 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
793 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
794 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
795
796 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
797 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
798 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
799
800 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
801 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
802 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
803
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530804 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
805 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
806 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
807
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700808 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
809 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
810 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530811 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700812 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
813 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
814 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
815 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530816 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700817 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700818 {"SLIMBUS_0_RX", "Switch", "SLIM0_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700819 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
820 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
821 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
822 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
823 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
824 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
825};
826
827static struct snd_pcm_ops msm_routing_pcm_ops = {};
828
829static unsigned int msm_routing_read(struct snd_soc_platform *platform,
830 unsigned int reg)
831{
832 dev_dbg(platform->dev, "reg %x\n", reg);
833 return 0;
834}
835
836/* Not used but frame seems to require it */
837static int msm_routing_write(struct snd_soc_platform *platform,
838 unsigned int reg, unsigned int val)
839{
840 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
841 return 0;
842}
843
844/* Not used but frame seems to require it */
845static int msm_routing_probe(struct snd_soc_platform *platform)
846{
847 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
848 ARRAY_SIZE(msm_qdsp6_widgets));
849 snd_soc_dapm_add_routes(&platform->dapm, intercon,
850 ARRAY_SIZE(intercon));
851
852 snd_soc_dapm_new_widgets(&platform->dapm);
853
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700854 snd_soc_add_platform_controls(platform,
855 int_fm_vol_mixer_controls,
856 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530857
858 snd_soc_add_platform_controls(platform,
859 lpa_vol_mixer_controls,
860 ARRAY_SIZE(lpa_vol_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700861 return 0;
862}
863
864static struct snd_soc_platform_driver msm_soc_routing_platform = {
865 .ops = &msm_routing_pcm_ops,
866 .probe = msm_routing_probe,
867 .read = msm_routing_read,
868 .write = msm_routing_write,
869};
870
871static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
872{
873 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
874 return snd_soc_register_platform(&pdev->dev,
875 &msm_soc_routing_platform);
876}
877
878static int msm_routing_pcm_remove(struct platform_device *pdev)
879{
880 snd_soc_unregister_platform(&pdev->dev);
881 return 0;
882}
883
884static struct platform_driver msm_routing_pcm_driver = {
885 .driver = {
886 .name = "msm-pcm-routing",
887 .owner = THIS_MODULE,
888 },
889 .probe = msm_routing_pcm_probe,
890 .remove = __devexit_p(msm_routing_pcm_remove),
891};
892
893static int __init msm_soc_routing_platform_init(void)
894{
Neema Shettyfeea7742011-09-11 12:30:36 -0700895 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700896 return platform_driver_register(&msm_routing_pcm_driver);
897}
898module_init(msm_soc_routing_platform_init);
899
900static void __exit msm_soc_routing_platform_exit(void)
901{
902 platform_driver_unregister(&msm_routing_pcm_driver);
903}
904module_exit(msm_soc_routing_platform_exit);
905
906MODULE_DESCRIPTION("MSM routing platform driver");
907MODULE_LICENSE("GPL v2");