blob: 97d0760f4da2776676c05f0162118d904aefd67e [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>
Ben Romberger037dd2f2011-09-22 14:01:32 -070028#include <sound/q6asm.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070029#include <sound/q6afe.h>
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070030#include <sound/tlv.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070031#include "msm-pcm-routing.h"
32#include "qdsp6/q6voice.h"
33
Neema Shettyfeea7742011-09-11 12:30:36 -070034struct msm_pcm_routing_bdai_data {
35 u16 port_id; /* AFE port ID */
36 u8 active; /* track if this backend is enabled */
37 struct snd_pcm_hw_params *hw_params; /* to get freq and channel mode */
38 unsigned long fe_sessions; /* Front-end sessions */
39 unsigned long port_sessions; /* track Tx BE ports -> Rx BE */
40};
41
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070042#define INVALID_SESSION -1
Patrick Laicf999112011-08-23 11:27:20 -070043#define SESSION_TYPE_RX 0
44#define SESSION_TYPE_TX 1
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070045
Neema Shettyfeea7742011-09-11 12:30:36 -070046static struct mutex routing_lock;
47
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070048static int fm_switch_enable;
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -070049#define INT_FM_RX_VOL_MAX_STEPS 100
50#define INT_FM_RX_VOL_GAIN 2000
51
52static int msm_route_fm_vol_control;
53static const DECLARE_TLV_DB_SCALE(fm_rx_vol_gain, 0,
54 INT_FM_RX_VOL_MAX_STEPS, 0);
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -070055
Sriranjan Srikantam269de7f2011-09-06 18:24:45 -070056#define INT_LPA_RX_VOL_MAX_STEPS 100
57#define INT_LPA_RX_VOL_GAIN 0x2000
Asish Bhattacharya0ec76182011-07-29 16:58:11 +053058
59static int msm_route_lpa_vol_control;
60static const DECLARE_TLV_DB_SCALE(lpa_rx_vol_gain, 0,
61 INT_LPA_RX_VOL_MAX_STEPS, 0);
62
Ben Romberger037dd2f2011-09-22 14:01:32 -070063/* Equal to Frontend after last of the MULTIMEDIA SESSIONS */
64#define MAX_EQ_SESSIONS MSM_FRONTEND_DAI_CS_VOICE
65
66enum {
67 EQ_BAND1 = 0,
68 EQ_BAND2,
69 EQ_BAND3,
70 EQ_BAND4,
71 EQ_BAND5,
72 EQ_BAND6,
73 EQ_BAND7,
74 EQ_BAND8,
75 EQ_BAND9,
76 EQ_BAND10,
77 EQ_BAND11,
78 EQ_BAND12,
79 EQ_BAND_MAX,
80};
81
82struct msm_audio_eq_band {
83 uint16_t band_idx; /* The band index, 0 .. 11 */
84 uint32_t filter_type; /* Filter band type */
85 uint32_t center_freq_hz; /* Filter band center frequency */
86 uint32_t filter_gain; /* Filter band initial gain (dB) */
87 /* Range is +12 dB to -12 dB with 1dB increments. */
88 uint32_t q_factor;
89} __packed;
90
91struct msm_audio_eq_stream_config {
92 uint32_t enable; /* Number of consequtive bands specified */
93 uint32_t num_bands;
94 struct msm_audio_eq_band eq_bands[EQ_BAND_MAX];
95} __packed;
96
97struct msm_audio_eq_stream_config eq_data[MAX_EQ_SESSIONS];
98
99static void msm_send_eq_values(int eq_idx);
Neema Shettyfeea7742011-09-11 12:30:36 -0700100/* This array is indexed by back-end DAI ID defined in msm-pcm-routing.h
101 * If new back-end is defined, add new back-end DAI ID at the end of enum
102 */
103static struct msm_pcm_routing_bdai_data msm_bedais[MSM_BACKEND_DAI_MAX] = {
104 { PRIMARY_I2S_RX, 0, NULL, 0, 0},
105 { PRIMARY_I2S_TX, 0, NULL, 0, 0},
106 { SLIMBUS_0_RX, 0, NULL, 0, 0},
107 { SLIMBUS_0_TX, 0, NULL, 0, 0},
108 { HDMI_RX, 0, NULL, 0, 0},
109 { INT_BT_SCO_RX, 0, NULL, 0, 0},
110 { INT_BT_SCO_TX, 0, NULL, 0, 0},
111 { INT_FM_RX, 0, NULL, 0, 0},
112 { INT_FM_TX, 0, NULL, 0, 0},
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530113 { RT_PROXY_PORT_001_RX, 0, NULL, 0, 0},
114 { RT_PROXY_PORT_001_TX, 0, NULL, 0, 0},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700115 { PCM_RX, 0, NULL, 0, 0},
116 { PCM_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
Patrick Laicf999112011-08-23 11:27:20 -0700130static void msm_pcm_routing_build_matrix(int fedai_id, int dspst_id,
131 int path_type)
132{
133 int i, port_type;
134 struct route_payload payload;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700135
Patrick Laicf999112011-08-23 11:27:20 -0700136 payload.num_copps = 0;
137 port_type = (path_type == ADM_PATH_PLAYBACK ?
138 MSM_AFE_PORT_TYPE_RX : MSM_AFE_PORT_TYPE_TX);
139
140 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
141 if ((afe_get_port_type(msm_bedais[i].port_id) ==
142 port_type) &&
143 msm_bedais[i].active && (test_bit(fedai_id,
144 &msm_bedais[i].fe_sessions)))
145 payload.copp_ids[payload.num_copps++] =
146 msm_bedais[i].port_id;
147 }
148
149 if (payload.num_copps)
150 adm_matrix_map(dspst_id, path_type,
151 payload.num_copps, payload.copp_ids, 0);
152}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153
154void msm_pcm_routing_reg_phy_stream(int fedai_id, int dspst_id, int stream_type)
155{
Patrick Laicf999112011-08-23 11:27:20 -0700156 int i, session_type, path_type, port_type;
157 struct route_payload payload;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700158
159 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
Patrick Laicf999112011-08-23 11:27:20 -0700160 session_type = SESSION_TYPE_RX;
161 path_type = ADM_PATH_PLAYBACK;
162 port_type = MSM_AFE_PORT_TYPE_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700164 session_type = SESSION_TYPE_TX;
165 path_type = ADM_PATH_LIVE_REC;
166 port_type = MSM_AFE_PORT_TYPE_TX;
167 }
168
169 mutex_lock(&routing_lock);
170
171 payload.num_copps = 0; /* only RX needs to use payload */
172 fe_dai_map[fedai_id][session_type] = dspst_id;
Ben Romberger037dd2f2011-09-22 14:01:32 -0700173 /* re-enable EQ if active */
174 if (eq_data[fedai_id].enable)
175 msm_send_eq_values(fedai_id);
Patrick Laicf999112011-08-23 11:27:20 -0700176 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
177 if ((afe_get_port_type(msm_bedais[i].port_id) ==
178 port_type) && msm_bedais[i].active &&
179 (test_bit(fedai_id,
180 &msm_bedais[i].fe_sessions))) {
181 adm_open(msm_bedais[i].port_id,
182 path_type,
183 params_rate(msm_bedais[i].hw_params),
184 params_channels(msm_bedais[i].hw_params),
185 DEFAULT_COPP_TOPOLOGY);
186 payload.copp_ids[payload.num_copps++] =
187 msm_bedais[i].port_id;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700188 }
189 }
Patrick Laicf999112011-08-23 11:27:20 -0700190 if (payload.num_copps)
191 adm_matrix_map(dspst_id, path_type,
192 payload.num_copps, payload.copp_ids, 0);
193
194 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195}
196
197void msm_pcm_routing_dereg_phy_stream(int fedai_id, int stream_type)
198{
Patrick Laicf999112011-08-23 11:27:20 -0700199 int i, port_type, session_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700200
201 if (stream_type == SNDRV_PCM_STREAM_PLAYBACK) {
Patrick Laicf999112011-08-23 11:27:20 -0700202 port_type = MSM_AFE_PORT_TYPE_RX;
203 session_type = SESSION_TYPE_RX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700205 port_type = MSM_AFE_PORT_TYPE_TX;
206 session_type = SESSION_TYPE_TX;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700207 }
Patrick Laicf999112011-08-23 11:27:20 -0700208
209 mutex_lock(&routing_lock);
210
211 for (i = 0; i < MSM_BACKEND_DAI_MAX; i++) {
212 if ((afe_get_port_type(msm_bedais[i].port_id) ==
213 port_type) && msm_bedais[i].active &&
214 (test_bit(fedai_id,
215 &msm_bedais[i].fe_sessions)))
216 adm_close(msm_bedais[i].port_id);
217 }
218
219 fe_dai_map[fedai_id][session_type] = INVALID_SESSION;
220
221 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222}
223
224static void msm_pcm_routing_process_audio(u16 reg, u16 val, int set)
225{
Patrick Laicf999112011-08-23 11:27:20 -0700226 int session_type, path_type;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227
228 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
229
Patrick Laicf999112011-08-23 11:27:20 -0700230 if (afe_get_port_type(msm_bedais[reg].port_id) ==
231 MSM_AFE_PORT_TYPE_RX) {
232 session_type = SESSION_TYPE_RX;
233 path_type = ADM_PATH_PLAYBACK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700235 session_type = SESSION_TYPE_TX;
236 path_type = ADM_PATH_LIVE_REC;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700237 }
Patrick Laicf999112011-08-23 11:27:20 -0700238
239 mutex_lock(&routing_lock);
240
241 if (set) {
242 set_bit(val, &msm_bedais[reg].fe_sessions);
243 if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
244 INVALID_SESSION) {
245 adm_open(msm_bedais[reg].port_id, path_type,
246 params_rate(msm_bedais[reg].hw_params),
247 params_channels(msm_bedais[reg].hw_params),
248 DEFAULT_COPP_TOPOLOGY);
249 msm_pcm_routing_build_matrix(val,
250 fe_dai_map[val][session_type], path_type);
251 }
252 } else {
253 clear_bit(val, &msm_bedais[reg].fe_sessions);
254 if (msm_bedais[reg].active && fe_dai_map[val][session_type] !=
255 INVALID_SESSION) {
256 adm_close(msm_bedais[reg].port_id);
257 msm_pcm_routing_build_matrix(val,
258 fe_dai_map[val][session_type], path_type);
259 }
260 }
261
262 mutex_unlock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263}
264
265static int msm_routing_get_audio_mixer(struct snd_kcontrol *kcontrol,
266 struct snd_ctl_elem_value *ucontrol)
267{
268 struct soc_mixer_control *mc =
269 (struct soc_mixer_control *)kcontrol->private_value;
270
Patrick Laicf999112011-08-23 11:27:20 -0700271 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 ucontrol->value.integer.value[0] = 1;
273 else
274 ucontrol->value.integer.value[0] = 0;
275
276 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
277 ucontrol->value.integer.value[0]);
278
279 return 0;
280}
281
282static int msm_routing_put_audio_mixer(struct snd_kcontrol *kcontrol,
283 struct snd_ctl_elem_value *ucontrol)
284{
Patrick Laiec2b8942011-09-01 11:01:51 -0700285 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
286 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700287 struct soc_mixer_control *mc =
288 (struct soc_mixer_control *)kcontrol->private_value;
289
290
291 if (ucontrol->value.integer.value[0]) {
292 msm_pcm_routing_process_audio(mc->reg, mc->shift, 1);
293 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
294 } else {
295 msm_pcm_routing_process_audio(mc->reg, mc->shift, 0);
296 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
297 }
298
299 return 1;
300}
301
Neema Shettyfeea7742011-09-11 12:30:36 -0700302static void msm_pcm_routing_process_voice(u16 reg, u16 val, int set)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700303{
Neema Shetty2c07eb52011-08-21 20:33:52 -0700304 u16 session_id = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700305
Neema Shettyfeea7742011-09-11 12:30:36 -0700306 pr_debug("%s: reg %x val %x set %x\n", __func__, reg, val, set);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700307
Neema Shettyfeea7742011-09-11 12:30:36 -0700308 if (val == MSM_FRONTEND_DAI_CS_VOICE)
Neema Shetty2c07eb52011-08-21 20:33:52 -0700309 session_id = voc_get_session_id(VOICE_SESSION_NAME);
310 else
311 session_id = voc_get_session_id(VOIP_SESSION_NAME);
312
313 pr_debug("%s: FE DAI 0x%x session_id 0x%x\n",
Neema Shettyfeea7742011-09-11 12:30:36 -0700314 __func__, val, session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700315
Neema Shettyfeea7742011-09-11 12:30:36 -0700316 mutex_lock(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700317
318 if (set)
Neema Shettyfeea7742011-09-11 12:30:36 -0700319 set_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700320 else
Neema Shettyfeea7742011-09-11 12:30:36 -0700321 clear_bit(val, &msm_bedais[reg].fe_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700322
Neema Shettyfeea7742011-09-11 12:30:36 -0700323 mutex_unlock(&routing_lock);
324
325 if (afe_get_port_type(msm_bedais[reg].port_id) ==
326 MSM_AFE_PORT_TYPE_RX) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700327 voc_set_route_flag(session_id, RX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700328 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700329 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700330 msm_bedais[reg].port_id, DEV_RX);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700331
Neema Shetty2c07eb52011-08-21 20:33:52 -0700332 if (voc_get_route_flag(session_id, RX_PATH) &&
333 voc_get_route_flag(session_id, TX_PATH))
334 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700335 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700336 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700337 }
338 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700339 voc_set_route_flag(session_id, TX_PATH, set);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340 if (set) {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700341 voc_set_rxtx_port(session_id,
Neema Shettyfeea7742011-09-11 12:30:36 -0700342 msm_bedais[reg].port_id, DEV_TX);
Neema Shetty2c07eb52011-08-21 20:33:52 -0700343 if (voc_get_route_flag(session_id, RX_PATH) &&
344 voc_get_route_flag(session_id, TX_PATH))
345 voc_enable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700346 } else {
Neema Shetty2c07eb52011-08-21 20:33:52 -0700347 voc_disable_cvp(session_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700348 }
349 }
350}
351
352static int msm_routing_get_voice_mixer(struct snd_kcontrol *kcontrol,
353 struct snd_ctl_elem_value *ucontrol)
354{
355 struct soc_mixer_control *mc =
356 (struct soc_mixer_control *)kcontrol->private_value;
357
Neema Shettyfeea7742011-09-11 12:30:36 -0700358 mutex_lock(&routing_lock);
359
360 if (test_bit(mc->shift, &msm_bedais[mc->reg].fe_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700361 ucontrol->value.integer.value[0] = 1;
362 else
363 ucontrol->value.integer.value[0] = 0;
364
Neema Shettyfeea7742011-09-11 12:30:36 -0700365 mutex_unlock(&routing_lock);
366
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700367 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
368 ucontrol->value.integer.value[0]);
369
370 return 0;
371}
372
373static int msm_routing_put_voice_mixer(struct snd_kcontrol *kcontrol,
374 struct snd_ctl_elem_value *ucontrol)
375{
Patrick Laiec2b8942011-09-01 11:01:51 -0700376 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
377 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700378 struct soc_mixer_control *mc =
379 (struct soc_mixer_control *)kcontrol->private_value;
380
381 if (ucontrol->value.integer.value[0]) {
Neema Shettyfeea7742011-09-11 12:30:36 -0700382 msm_pcm_routing_process_voice(mc->reg, mc->shift, 1);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700383 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
384 } else {
Neema Shettyfeea7742011-09-11 12:30:36 -0700385 msm_pcm_routing_process_voice(mc->reg, mc->shift, 0);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
387 }
388
389 return 1;
390}
391
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700392static int msm_routing_get_switch_mixer(struct snd_kcontrol *kcontrol,
393 struct snd_ctl_elem_value *ucontrol)
394{
395 ucontrol->value.integer.value[0] = fm_switch_enable;
396 pr_debug("%s: FM Switch enable %ld\n", __func__,
397 ucontrol->value.integer.value[0]);
398 return 0;
399}
400
401static int msm_routing_put_switch_mixer(struct snd_kcontrol *kcontrol,
402 struct snd_ctl_elem_value *ucontrol)
403{
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -0700404 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
405 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700406
407 pr_debug("%s: FM Switch enable %ld\n", __func__,
408 ucontrol->value.integer.value[0]);
409 if (ucontrol->value.integer.value[0])
410 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
411 else
412 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
413 fm_switch_enable = ucontrol->value.integer.value[0];
414 return 1;
415}
416
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700417static int msm_routing_get_port_mixer(struct snd_kcontrol *kcontrol,
418 struct snd_ctl_elem_value *ucontrol)
419{
420 struct soc_mixer_control *mc =
421 (struct soc_mixer_control *)kcontrol->private_value;
422
Patrick Laicf999112011-08-23 11:27:20 -0700423 if (test_bit(mc->shift, &msm_bedais[mc->reg].port_sessions))
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700424 ucontrol->value.integer.value[0] = 1;
425 else
426 ucontrol->value.integer.value[0] = 0;
427
428 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg, mc->shift,
429 ucontrol->value.integer.value[0]);
430
431 return 0;
432}
433
434static int msm_routing_put_port_mixer(struct snd_kcontrol *kcontrol,
435 struct snd_ctl_elem_value *ucontrol)
436{
437 struct soc_mixer_control *mc =
438 (struct soc_mixer_control *)kcontrol->private_value;
439
440 pr_debug("%s: reg %x shift %x val %ld\n", __func__, mc->reg,
441 mc->shift, ucontrol->value.integer.value[0]);
442
443 if (ucontrol->value.integer.value[0]) {
Patrick Laicf999112011-08-23 11:27:20 -0700444 afe_loopback(1, msm_bedais[mc->reg].port_id,
445 msm_bedais[mc->shift].port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700446 set_bit(mc->shift,
Patrick Laicf999112011-08-23 11:27:20 -0700447 &msm_bedais[mc->reg].port_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700448 } else {
Patrick Laicf999112011-08-23 11:27:20 -0700449 afe_loopback(0, msm_bedais[mc->reg].port_id,
450 msm_bedais[mc->shift].port_id);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700451 clear_bit(mc->shift,
Patrick Laicf999112011-08-23 11:27:20 -0700452 &msm_bedais[mc->reg].port_sessions);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700453 }
454
455 return 1;
456}
457
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700458static int msm_routing_get_fm_vol_mixer(struct snd_kcontrol *kcontrol,
459 struct snd_ctl_elem_value *ucontrol)
460{
461 ucontrol->value.integer.value[0] = msm_route_fm_vol_control;
462 return 0;
463}
464
465static int msm_routing_set_fm_vol_mixer(struct snd_kcontrol *kcontrol,
466 struct snd_ctl_elem_value *ucontrol)
467{
468 afe_loopback_gain(INT_FM_TX , ucontrol->value.integer.value[0]);
469
470 msm_route_fm_vol_control = ucontrol->value.integer.value[0];
471
472 return 0;
473}
474
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530475static int msm_routing_get_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
476 struct snd_ctl_elem_value *ucontrol)
477{
478 ucontrol->value.integer.value[0] = msm_route_lpa_vol_control;
479 return 0;
480}
481
482static int msm_routing_set_lpa_vol_mixer(struct snd_kcontrol *kcontrol,
483 struct snd_ctl_elem_value *ucontrol)
484{
485 if (!lpa_set_volume(ucontrol->value.integer.value[0]))
486 msm_route_lpa_vol_control =
487 ucontrol->value.integer.value[0];
488
489 return 0;
490}
491
Ben Romberger037dd2f2011-09-22 14:01:32 -0700492static void msm_send_eq_values(int eq_idx)
493{
494 int result;
495 struct audio_client *ac =
496 q6asm_get_audio_client(fe_dai_map[eq_idx][SESSION_TYPE_RX]);
497
498 if (ac == NULL) {
499 pr_err("%s: Could not get audio client for session: %d\n",
500 __func__, fe_dai_map[eq_idx][SESSION_TYPE_RX]);
501 goto done;
502 }
503
504 result = q6asm_equalizer(ac, &eq_data[eq_idx]);
505
506 if (result < 0)
507 pr_err("%s: Call to ASM equalizer failed, returned = %d\n",
508 __func__, result);
509done:
510 return;
511}
512
513static int msm_routing_get_eq_enable_mixer(struct snd_kcontrol *kcontrol,
514 struct snd_ctl_elem_value *ucontrol)
515{
516 int eq_idx = ((struct soc_multi_mixer_control *)
517 kcontrol->private_value)->reg;
518
519 pr_debug("%s: EQ #%d enable %d\n", __func__,
520 eq_idx, eq_data[eq_idx].enable);
521 return eq_data[eq_idx].enable;
522}
523
524static int msm_routing_put_eq_enable_mixer(struct snd_kcontrol *kcontrol,
525 struct snd_ctl_elem_value *ucontrol)
526{
527 int eq_idx = ((struct soc_multi_mixer_control *)
528 kcontrol->private_value)->reg;
529 int value = ucontrol->value.integer.value[0];
530
531 pr_debug("%s: EQ #%d enable %d\n", __func__,
532 eq_idx, value);
533 eq_data[eq_idx].enable = value;
534
535 msm_send_eq_values(eq_idx);
536 return 0;
537}
538
539static int msm_routing_get_eq_band_count_audio_mixer(
540 struct snd_kcontrol *kcontrol,
541 struct snd_ctl_elem_value *ucontrol)
542{
543 int eq_idx = ((struct soc_multi_mixer_control *)
544 kcontrol->private_value)->reg;
545
546 pr_debug("%s: EQ #%d bands %d\n", __func__,
547 eq_idx, eq_data[eq_idx].num_bands);
548 return eq_data[eq_idx].num_bands;
549}
550
551static int msm_routing_put_eq_band_count_audio_mixer(
552 struct snd_kcontrol *kcontrol,
553 struct snd_ctl_elem_value *ucontrol)
554{
555 int eq_idx = ((struct soc_multi_mixer_control *)
556 kcontrol->private_value)->reg;
557 int value = ucontrol->value.integer.value[0];
558
559
560 pr_debug("%s: EQ #%d bands %d\n", __func__,
561 eq_idx, value);
562 eq_data[eq_idx].num_bands = value;
563 return 0;
564}
565
566static int msm_routing_get_eq_band_audio_mixer(struct snd_kcontrol *kcontrol,
567 struct snd_ctl_elem_value *ucontrol)
568{
569 int eq_idx = ((struct soc_multi_mixer_control *)
570 kcontrol->private_value)->reg;
571 int band_idx = ((struct soc_multi_mixer_control *)
572 kcontrol->private_value)->shift;
573
574 pr_debug("%s: band_idx = %d\n", __func__,
575 eq_data[eq_idx].eq_bands[band_idx].band_idx);
576 pr_debug("%s: filter_type = %d\n", __func__,
577 eq_data[eq_idx].eq_bands[band_idx].filter_type);
578 pr_debug("%s: center_freq_hz = %d\n", __func__,
579 eq_data[eq_idx].eq_bands[band_idx].center_freq_hz);
580 pr_debug("%s: filter_gain = %d\n", __func__,
581 eq_data[eq_idx].eq_bands[band_idx].filter_gain);
582 pr_debug("%s: q_factor = %d\n", __func__,
583 eq_data[eq_idx].eq_bands[band_idx].q_factor);
584 return 0;
585}
586
587static int msm_routing_put_eq_band_audio_mixer(struct snd_kcontrol *kcontrol,
588 struct snd_ctl_elem_value *ucontrol)
589{
590 int eq_idx = ((struct soc_multi_mixer_control *)
591 kcontrol->private_value)->reg;
592 int band_idx = ((struct soc_multi_mixer_control *)
593 kcontrol->private_value)->shift;
594
595 eq_data[eq_idx].eq_bands[band_idx].band_idx =
596 ucontrol->value.integer.value[0];
597 eq_data[eq_idx].eq_bands[band_idx].filter_type =
598 ucontrol->value.integer.value[1];
599 eq_data[eq_idx].eq_bands[band_idx].center_freq_hz =
600 ucontrol->value.integer.value[2];
601 eq_data[eq_idx].eq_bands[band_idx].filter_gain =
602 ucontrol->value.integer.value[3];
603 eq_data[eq_idx].eq_bands[band_idx].q_factor =
604 ucontrol->value.integer.value[4];
605 return 0;
606}
607
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700608static const struct snd_kcontrol_new pri_i2s_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700609 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_I2S_RX ,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700610 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
611 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700612 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_PRI_I2S_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700613 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
614 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700615 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_PRI_I2S_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700616 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
617 msm_routing_put_audio_mixer),
618};
619
620static const struct snd_kcontrol_new slimbus_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700621 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700622 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
623 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700624 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700625 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
626 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700627 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700628 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
629 msm_routing_put_audio_mixer),
630};
631
632static const struct snd_kcontrol_new hdmi_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700633 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_HDMI_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700634 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
635 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700636 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_HDMI_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700637 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
638 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700639 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_HDMI_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530640 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
641 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700642};
643
644static const struct snd_kcontrol_new int_bt_sco_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700645 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700646 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
647 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700648 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700649 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
650 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700651 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_BT_SCO_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530652 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
653 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700654};
655
656static const struct snd_kcontrol_new int_fm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700657 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_INT_FM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700658 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
659 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700660 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_INT_FM_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700661 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
662 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700663 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_INT_FM_RX,
Asish Bhattacharyac592eed2011-09-16 17:43:02 +0530664 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
665 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700666};
667
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530668static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700669 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530670 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
671 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700672 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530673 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
674 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700675 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AFE_PCM_RX,
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530676 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
677 msm_routing_put_audio_mixer),
678};
679
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700680static const struct snd_kcontrol_new auxpcm_rx_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700681 SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700682 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
683 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700684 SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700685 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
686 msm_routing_put_audio_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700687 SOC_SINGLE_EXT("MultiMedia3", MSM_BACKEND_DAI_AUXPCM_RX,
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700688 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_audio_mixer,
689 msm_routing_put_audio_mixer),
690};
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530691
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700692static const struct snd_kcontrol_new mmul1_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700693 SOC_SINGLE_EXT("PRI_TX", MSM_BACKEND_DAI_PRI_I2S_TX,
694 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
695 msm_routing_put_audio_mixer),
696 SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_TX,
697 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
698 msm_routing_put_audio_mixer),
699 SOC_SINGLE_EXT("AUX_PCM_UL_TX", MSM_BACKEND_DAI_AUXPCM_TX,
700 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
701 msm_routing_put_audio_mixer),
702 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX", MSM_BACKEND_DAI_INT_BT_SCO_TX,
703 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
704 msm_routing_put_audio_mixer),
705 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
706 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
707 msm_routing_put_audio_mixer),
708 SOC_SINGLE_EXT("AFE_PCM_TX", MSM_BACKEND_DAI_AFE_PCM_TX,
709 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
710 msm_routing_put_audio_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700711};
712
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700713static const struct snd_kcontrol_new mmul2_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700714 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_INT_FM_TX,
715 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_audio_mixer,
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -0700716 msm_routing_put_audio_mixer),
717};
718
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700719static const struct snd_kcontrol_new pri_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700720 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_PRI_I2S_RX,
721 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
722 msm_routing_put_voice_mixer),
723 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_PRI_I2S_RX,
724 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
725 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700726};
727
728static const struct snd_kcontrol_new slimbus_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700729 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_SLIMBUS_0_RX,
730 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
731 msm_routing_put_voice_mixer),
732 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_SLIMBUS_0_RX ,
733 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
734 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700735};
736
737static const struct snd_kcontrol_new bt_sco_rx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700738 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_INT_BT_SCO_RX,
739 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
740 msm_routing_put_voice_mixer),
741 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_INT_BT_SCO_RX ,
742 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
743 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744};
745
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530746static const struct snd_kcontrol_new afe_pcm_rx_voice_mixer_controls[] = {
747 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AFE_PCM_RX,
748 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
749 msm_routing_put_voice_mixer),
750 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AFE_PCM_RX,
751 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
752 msm_routing_put_voice_mixer),
753};
754
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700755static const struct snd_kcontrol_new aux_pcm_rx_voice_mixer_controls[] = {
756 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_AUXPCM_RX,
757 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
758 msm_routing_put_voice_mixer),
759 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_AUXPCM_RX,
760 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
761 msm_routing_put_voice_mixer),
762};
763
Alex Wong593576c2011-11-15 08:03:24 -0800764static const struct snd_kcontrol_new hdmi_rx_voice_mixer_controls[] = {
765 SOC_SINGLE_EXT("CSVoice", MSM_BACKEND_DAI_HDMI_RX,
766 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
767 msm_routing_put_voice_mixer),
768 SOC_SINGLE_EXT("Voip", MSM_BACKEND_DAI_HDMI_RX,
769 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
770 msm_routing_put_voice_mixer),
771};
772
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700773static const struct snd_kcontrol_new tx_voice_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700774 SOC_SINGLE_EXT("PRI_TX_Voice", MSM_BACKEND_DAI_PRI_I2S_TX,
775 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
776 msm_routing_put_voice_mixer),
777 SOC_SINGLE_EXT("SLIM_0_TX_Voice", MSM_BACKEND_DAI_SLIMBUS_0_TX,
778 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
779 msm_routing_put_voice_mixer),
780 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voice",
781 MSM_BACKEND_DAI_INT_BT_SCO_TX, MSM_FRONTEND_DAI_CS_VOICE, 1, 0,
Neema Shetty2c07eb52011-08-21 20:33:52 -0700782 msm_routing_get_voice_mixer, msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530783 SOC_SINGLE_EXT("AFE_PCM_TX_Voice", MSM_BACKEND_DAI_AFE_PCM_TX,
784 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
785 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700786 SOC_SINGLE_EXT("AUX_PCM_TX_Voice", MSM_BACKEND_DAI_AUXPCM_TX,
787 MSM_FRONTEND_DAI_CS_VOICE, 1, 0, msm_routing_get_voice_mixer,
788 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700789};
790
791static const struct snd_kcontrol_new tx_voip_mixer_controls[] = {
Neema Shettyfeea7742011-09-11 12:30:36 -0700792 SOC_SINGLE_EXT("PRI_TX_Voip", MSM_BACKEND_DAI_PRI_I2S_TX,
793 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
794 msm_routing_put_voice_mixer),
795 SOC_SINGLE_EXT("SLIM_0_TX_Voip", MSM_BACKEND_DAI_SLIMBUS_0_TX,
796 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
797 msm_routing_put_voice_mixer),
798 SOC_SINGLE_EXT("INTERNAL_BT_SCO_TX_Voip", MSM_BACKEND_DAI_INT_BT_SCO_TX,
799 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
800 msm_routing_put_voice_mixer),
Laxminath Kasam32657ec2011-08-01 19:26:57 +0530801 SOC_SINGLE_EXT("AFE_PCM_TX_Voip", MSM_BACKEND_DAI_AFE_PCM_TX,
802 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
803 msm_routing_put_voice_mixer),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -0700804 SOC_SINGLE_EXT("AUX_PCM_TX_Voip", MSM_BACKEND_DAI_AUXPCM_TX,
805 MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer,
806 msm_routing_put_voice_mixer),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700807};
808
809static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = {
Patrick Laicf999112011-08-23 11:27:20 -0700810 SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700811 MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer,
812 msm_routing_put_port_mixer),
Patrick Laicf999112011-08-23 11:27:20 -0700813 SOC_SINGLE_EXT("SLIM_0_TX", MSM_BACKEND_DAI_SLIMBUS_0_RX,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700814 MSM_BACKEND_DAI_SLIMBUS_0_TX, 1, 0, msm_routing_get_port_mixer,
815 msm_routing_put_port_mixer),
816};
817
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -0700818static const struct snd_kcontrol_new fm_switch_mixer_controls =
819 SOC_SINGLE_EXT("Switch", SND_SOC_NOPM,
820 0, 1, 0, msm_routing_get_switch_mixer,
821 msm_routing_put_switch_mixer);
822
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -0700823static const struct snd_kcontrol_new int_fm_vol_mixer_controls[] = {
824 SOC_SINGLE_EXT_TLV("Internal FM RX Volume", SND_SOC_NOPM, 0,
825 INT_FM_RX_VOL_GAIN, 0, msm_routing_get_fm_vol_mixer,
826 msm_routing_set_fm_vol_mixer, fm_rx_vol_gain),
827};
828
Asish Bhattacharya0ec76182011-07-29 16:58:11 +0530829static const struct snd_kcontrol_new lpa_vol_mixer_controls[] = {
830 SOC_SINGLE_EXT_TLV("LPA RX Volume", SND_SOC_NOPM, 0,
831 INT_LPA_RX_VOL_GAIN, 0, msm_routing_get_lpa_vol_mixer,
832 msm_routing_set_lpa_vol_mixer, lpa_rx_vol_gain),
833};
834
Ben Romberger037dd2f2011-09-22 14:01:32 -0700835static const struct snd_kcontrol_new eq_enable_mixer_controls[] = {
836 SOC_SINGLE_EXT("MultiMedia1 EQ Enable", SND_SOC_NOPM,
837 MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_eq_enable_mixer,
838 msm_routing_put_eq_enable_mixer),
839 SOC_SINGLE_EXT("MultiMedia2 EQ Enable", SND_SOC_NOPM,
840 MSM_FRONTEND_DAI_MULTIMEDIA2, 1, 0, msm_routing_get_eq_enable_mixer,
841 msm_routing_put_eq_enable_mixer),
842 SOC_SINGLE_EXT("MultiMedia3 EQ Enable", SND_SOC_NOPM,
843 MSM_FRONTEND_DAI_MULTIMEDIA3, 1, 0, msm_routing_get_eq_enable_mixer,
844 msm_routing_put_eq_enable_mixer),
845};
846
847static const struct snd_kcontrol_new eq_band_mixer_controls[] = {
848 SOC_SINGLE_EXT("MultiMedia1 EQ Band Count", SND_SOC_NOPM,
849 MSM_FRONTEND_DAI_MULTIMEDIA1, 11, 0,
850 msm_routing_get_eq_band_count_audio_mixer,
851 msm_routing_put_eq_band_count_audio_mixer),
852 SOC_SINGLE_EXT("MultiMedia2 EQ Band Count", SND_SOC_NOPM,
853 MSM_FRONTEND_DAI_MULTIMEDIA2, 11, 0,
854 msm_routing_get_eq_band_count_audio_mixer,
855 msm_routing_put_eq_band_count_audio_mixer),
856 SOC_SINGLE_EXT("MultiMedia3 EQ Band Count", SND_SOC_NOPM,
857 MSM_FRONTEND_DAI_MULTIMEDIA3, 11, 0,
858 msm_routing_get_eq_band_count_audio_mixer,
859 msm_routing_put_eq_band_count_audio_mixer),
860};
861
862static const struct snd_kcontrol_new eq_coeff_mixer_controls[] = {
863 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band1", EQ_BAND1,
864 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
865 msm_routing_get_eq_band_audio_mixer,
866 msm_routing_put_eq_band_audio_mixer),
867 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band2", EQ_BAND2,
868 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
869 msm_routing_get_eq_band_audio_mixer,
870 msm_routing_put_eq_band_audio_mixer),
871 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band3", EQ_BAND3,
872 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
873 msm_routing_get_eq_band_audio_mixer,
874 msm_routing_put_eq_band_audio_mixer),
875 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band4", EQ_BAND4,
876 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
877 msm_routing_get_eq_band_audio_mixer,
878 msm_routing_put_eq_band_audio_mixer),
879 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band5", EQ_BAND5,
880 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
881 msm_routing_get_eq_band_audio_mixer,
882 msm_routing_put_eq_band_audio_mixer),
883 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band6", EQ_BAND6,
884 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
885 msm_routing_get_eq_band_audio_mixer,
886 msm_routing_put_eq_band_audio_mixer),
887 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band7", EQ_BAND7,
888 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
889 msm_routing_get_eq_band_audio_mixer,
890 msm_routing_put_eq_band_audio_mixer),
891 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band8", EQ_BAND8,
892 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
893 msm_routing_get_eq_band_audio_mixer,
894 msm_routing_put_eq_band_audio_mixer),
895 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band9", EQ_BAND9,
896 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
897 msm_routing_get_eq_band_audio_mixer,
898 msm_routing_put_eq_band_audio_mixer),
899 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band10", EQ_BAND10,
900 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
901 msm_routing_get_eq_band_audio_mixer,
902 msm_routing_put_eq_band_audio_mixer),
903 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band11", EQ_BAND11,
904 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
905 msm_routing_get_eq_band_audio_mixer,
906 msm_routing_put_eq_band_audio_mixer),
907 SOC_SINGLE_MULTI_EXT("MultiMedia1 EQ Band12", EQ_BAND12,
908 MSM_FRONTEND_DAI_MULTIMEDIA1, 255, 0, 5,
909 msm_routing_get_eq_band_audio_mixer,
910 msm_routing_put_eq_band_audio_mixer),
911 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band1", EQ_BAND1,
912 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
913 msm_routing_get_eq_band_audio_mixer,
914 msm_routing_put_eq_band_audio_mixer),
915 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band2", EQ_BAND2,
916 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
917 msm_routing_get_eq_band_audio_mixer,
918 msm_routing_put_eq_band_audio_mixer),
919 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band3", EQ_BAND3,
920 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
921 msm_routing_get_eq_band_audio_mixer,
922 msm_routing_put_eq_band_audio_mixer),
923 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band4", EQ_BAND4,
924 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
925 msm_routing_get_eq_band_audio_mixer,
926 msm_routing_put_eq_band_audio_mixer),
927 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band5", EQ_BAND5,
928 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
929 msm_routing_get_eq_band_audio_mixer,
930 msm_routing_put_eq_band_audio_mixer),
931 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band6", EQ_BAND6,
932 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
933 msm_routing_get_eq_band_audio_mixer,
934 msm_routing_put_eq_band_audio_mixer),
935 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band7", EQ_BAND7,
936 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
937 msm_routing_get_eq_band_audio_mixer,
938 msm_routing_put_eq_band_audio_mixer),
939 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band8", EQ_BAND8,
940 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
941 msm_routing_get_eq_band_audio_mixer,
942 msm_routing_put_eq_band_audio_mixer),
943 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band9", EQ_BAND9,
944 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
945 msm_routing_get_eq_band_audio_mixer,
946 msm_routing_put_eq_band_audio_mixer),
947 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band10", EQ_BAND10,
948 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
949 msm_routing_get_eq_band_audio_mixer,
950 msm_routing_put_eq_band_audio_mixer),
951 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band11", EQ_BAND11,
952 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
953 msm_routing_get_eq_band_audio_mixer,
954 msm_routing_put_eq_band_audio_mixer),
955 SOC_SINGLE_MULTI_EXT("MultiMedia2 EQ Band12", EQ_BAND12,
956 MSM_FRONTEND_DAI_MULTIMEDIA2, 255, 0, 5,
957 msm_routing_get_eq_band_audio_mixer,
958 msm_routing_put_eq_band_audio_mixer),
959 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band1", EQ_BAND1,
960 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
961 msm_routing_get_eq_band_audio_mixer,
962 msm_routing_put_eq_band_audio_mixer),
963 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band2", EQ_BAND2,
964 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
965 msm_routing_get_eq_band_audio_mixer,
966 msm_routing_put_eq_band_audio_mixer),
967 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band3", EQ_BAND3,
968 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
969 msm_routing_get_eq_band_audio_mixer,
970 msm_routing_put_eq_band_audio_mixer),
971 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band4", EQ_BAND4,
972 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
973 msm_routing_get_eq_band_audio_mixer,
974 msm_routing_put_eq_band_audio_mixer),
975 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band5", EQ_BAND5,
976 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
977 msm_routing_get_eq_band_audio_mixer,
978 msm_routing_put_eq_band_audio_mixer),
979 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band6", EQ_BAND6,
980 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
981 msm_routing_get_eq_band_audio_mixer,
982 msm_routing_put_eq_band_audio_mixer),
983 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band7", EQ_BAND7,
984 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
985 msm_routing_get_eq_band_audio_mixer,
986 msm_routing_put_eq_band_audio_mixer),
987 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band8", EQ_BAND8,
988 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
989 msm_routing_get_eq_band_audio_mixer,
990 msm_routing_put_eq_band_audio_mixer),
991 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band9", EQ_BAND9,
992 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
993 msm_routing_get_eq_band_audio_mixer,
994 msm_routing_put_eq_band_audio_mixer),
995 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band10", EQ_BAND10,
996 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
997 msm_routing_get_eq_band_audio_mixer,
998 msm_routing_put_eq_band_audio_mixer),
999 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band11", EQ_BAND11,
1000 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
1001 msm_routing_get_eq_band_audio_mixer,
1002 msm_routing_put_eq_band_audio_mixer),
1003 SOC_SINGLE_MULTI_EXT("MultiMedia3 EQ Band12", EQ_BAND12,
1004 MSM_FRONTEND_DAI_MULTIMEDIA3, 255, 0, 5,
1005 msm_routing_get_eq_band_audio_mixer,
1006 msm_routing_put_eq_band_audio_mixer),
1007};
1008
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001009static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = {
1010 /* Frontend AIF */
1011 /* Widget name equals to Front-End DAI name<Need confirmation>,
1012 * Stream name must contains substring of front-end dai name
1013 */
1014 SND_SOC_DAPM_AIF_IN("MM_DL1", "MultiMedia1 Playback", 0, 0, 0, 0),
1015 SND_SOC_DAPM_AIF_IN("MM_DL2", "MultiMedia2 Playback", 0, 0, 0, 0),
1016 SND_SOC_DAPM_AIF_IN("MM_DL3", "MultiMedia3 Playback", 0, 0, 0, 0),
1017 SND_SOC_DAPM_AIF_IN("VOIP_DL", "VoIP Playback", 0, 0, 0, 0),
1018 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0, 0, 0, 0),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -07001019 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0, 0, 0, 0),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001020 SND_SOC_DAPM_AIF_IN("CS-VOICE_DL1", "CS-VOICE Playback", 0, 0, 0, 0),
1021 SND_SOC_DAPM_AIF_OUT("CS-VOICE_UL1", "CS-VOICE Capture", 0, 0, 0, 0),
1022 SND_SOC_DAPM_AIF_OUT("VOIP_UL", "VoIP Capture", 0, 0, 0, 0),
1023 SND_SOC_DAPM_AIF_IN("SLIM0_DL_HL", "SLIMBUS0_HOSTLESS Playback",
1024 0, 0, 0, 0),
1025 SND_SOC_DAPM_AIF_OUT("SLIM0_UL_HL", "SLIMBUS0_HOSTLESS Capture",
1026 0, 0, 0, 0),
1027 SND_SOC_DAPM_AIF_IN("INTFM_DL_HL", "INT_FM_HOSTLESS Playback",
1028 0, 0, 0, 0),
1029 SND_SOC_DAPM_AIF_OUT("INTFM_UL_HL", "INT_FM_HOSTLESS Capture",
1030 0, 0, 0, 0),
1031 /* Backend AIF */
1032 /* Stream name equals to backend dai link stream name
1033 */
1034 SND_SOC_DAPM_AIF_OUT("PRI_I2S_RX", "Primary I2S Playback", 0, 0, 0, 0),
1035 SND_SOC_DAPM_AIF_OUT("SLIMBUS_0_RX", "Slimbus Playback", 0, 0, 0, 0),
1036 SND_SOC_DAPM_AIF_OUT("HDMI", "HDMI Playback", 0, 0, 0 , 0),
1037 SND_SOC_DAPM_AIF_IN("PRI_I2S_TX", "Primary I2S Capture", 0, 0, 0, 0),
1038 SND_SOC_DAPM_AIF_IN("SLIMBUS_0_TX", "Slimbus Capture", 0, 0, 0, 0),
1039 SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback",
1040 0, 0, 0 , 0),
1041 SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture",
1042 0, 0, 0, 0),
1043 SND_SOC_DAPM_AIF_OUT("INT_FM_RX", "Internal FM Playback",
1044 0, 0, 0 , 0),
1045 SND_SOC_DAPM_AIF_IN("INT_FM_TX", "Internal FM Capture",
1046 0, 0, 0, 0),
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301047 SND_SOC_DAPM_AIF_OUT("PCM_RX", "AFE Playback",
1048 0, 0, 0 , 0),
1049 SND_SOC_DAPM_AIF_IN("PCM_TX", "AFE Capture",
1050 0, 0, 0, 0),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001051 SND_SOC_DAPM_AIF_OUT("AUX_PCM_RX", "AUX PCM Playback", 0, 0, 0, 0),
1052 SND_SOC_DAPM_AIF_IN("AUX_PCM_TX", "AUX PCM Capture", 0, 0, 0, 0),
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -07001053 /* Switch Definitions */
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -07001054 SND_SOC_DAPM_SWITCH("SLIMBUS_DL_HL", SND_SOC_NOPM, 0, 0,
Sriranjan Srikantama4969dd2011-07-14 00:34:56 -07001055 &fm_switch_mixer_controls),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001056 /* Mixer definitions */
1057 SND_SOC_DAPM_MIXER("PRI_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1058 pri_i2s_rx_mixer_controls, ARRAY_SIZE(pri_i2s_rx_mixer_controls)),
1059 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1060 slimbus_rx_mixer_controls, ARRAY_SIZE(slimbus_rx_mixer_controls)),
1061 SND_SOC_DAPM_MIXER("HDMI Mixer", SND_SOC_NOPM, 0, 0,
1062 hdmi_mixer_controls, ARRAY_SIZE(hdmi_mixer_controls)),
1063 SND_SOC_DAPM_MIXER("MultiMedia1 Mixer", SND_SOC_NOPM, 0, 0,
1064 mmul1_mixer_controls, ARRAY_SIZE(mmul1_mixer_controls)),
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -07001065 SND_SOC_DAPM_MIXER("MultiMedia2 Mixer", SND_SOC_NOPM, 0, 0,
1066 mmul2_mixer_controls, ARRAY_SIZE(mmul2_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001067 SND_SOC_DAPM_MIXER("AUX_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1068 auxpcm_rx_mixer_controls, ARRAY_SIZE(auxpcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001069 /* Voice Mixer */
1070 SND_SOC_DAPM_MIXER("PRI_RX_Voice Mixer",
1071 SND_SOC_NOPM, 0, 0, pri_rx_voice_mixer_controls,
1072 ARRAY_SIZE(pri_rx_voice_mixer_controls)),
1073 SND_SOC_DAPM_MIXER("SLIM_0_RX_Voice Mixer",
1074 SND_SOC_NOPM, 0, 0,
1075 slimbus_rx_voice_mixer_controls,
1076 ARRAY_SIZE(slimbus_rx_voice_mixer_controls)),
1077 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX_Voice Mixer",
1078 SND_SOC_NOPM, 0, 0,
1079 bt_sco_rx_voice_mixer_controls,
1080 ARRAY_SIZE(bt_sco_rx_voice_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301081 SND_SOC_DAPM_MIXER("AFE_PCM_RX_Voice Mixer",
1082 SND_SOC_NOPM, 0, 0,
1083 afe_pcm_rx_voice_mixer_controls,
1084 ARRAY_SIZE(afe_pcm_rx_voice_mixer_controls)),
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001085 SND_SOC_DAPM_MIXER("AUX_PCM_RX_Voice Mixer",
1086 SND_SOC_NOPM, 0, 0,
1087 aux_pcm_rx_voice_mixer_controls,
1088 ARRAY_SIZE(aux_pcm_rx_voice_mixer_controls)),
Alex Wong593576c2011-11-15 08:03:24 -08001089 SND_SOC_DAPM_MIXER("HDMI_RX_Voice Mixer",
1090 SND_SOC_NOPM, 0, 0,
1091 hdmi_rx_voice_mixer_controls,
1092 ARRAY_SIZE(hdmi_rx_voice_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001093 SND_SOC_DAPM_MIXER("Voice_Tx Mixer",
1094 SND_SOC_NOPM, 0, 0, tx_voice_mixer_controls,
1095 ARRAY_SIZE(tx_voice_mixer_controls)),
1096 SND_SOC_DAPM_MIXER("Voip_Tx Mixer",
1097 SND_SOC_NOPM, 0, 0, tx_voip_mixer_controls,
1098 ARRAY_SIZE(tx_voip_mixer_controls)),
1099 SND_SOC_DAPM_MIXER("INTERNAL_BT_SCO_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1100 int_bt_sco_rx_mixer_controls, ARRAY_SIZE(int_bt_sco_rx_mixer_controls)),
1101 SND_SOC_DAPM_MIXER("INTERNAL_FM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1102 int_fm_rx_mixer_controls, ARRAY_SIZE(int_fm_rx_mixer_controls)),
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301103 SND_SOC_DAPM_MIXER("AFE_PCM_RX Audio Mixer", SND_SOC_NOPM, 0, 0,
1104 afe_pcm_rx_mixer_controls, ARRAY_SIZE(afe_pcm_rx_mixer_controls)),
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001105 SND_SOC_DAPM_MIXER("SLIMBUS_0_RX Port Mixer",
1106 SND_SOC_NOPM, 0, 0, sbus_0_rx_port_mixer_controls,
1107 ARRAY_SIZE(sbus_0_rx_port_mixer_controls)),
1108};
1109
1110static const struct snd_soc_dapm_route intercon[] = {
1111 {"PRI_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1112 {"PRI_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
1113 {"PRI_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
1114 {"PRI_I2S_RX", NULL, "PRI_RX Audio Mixer"},
1115
1116 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1117 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
1118 {"SLIMBUS_0_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
1119 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Audio Mixer"},
1120
1121 {"HDMI Mixer", "MultiMedia1", "MM_DL1"},
1122 {"HDMI Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +05301123 {"HDMI Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001124 {"HDMI", NULL, "HDMI Mixer"},
1125
1126 {"MultiMedia1 Mixer", "PRI_TX", "PRI_I2S_TX"},
1127 {"MultiMedia1 Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001128 {"MultiMedia1 Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001129
1130 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1131 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +05301132 {"INTERNAL_BT_SCO_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001133 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX Audio Mixer"},
1134
1135 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1136 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
Asish Bhattacharyac592eed2011-09-16 17:43:02 +05301137 {"INTERNAL_FM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001138 {"INT_FM_RX", NULL, "INTERNAL_FM_RX Audio Mixer"},
1139
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301140 {"AFE_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1141 {"AFE_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
1142 {"AFE_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
1143 {"PCM_RX", NULL, "AFE_PCM_RX Audio Mixer"},
1144
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001145 {"MultiMedia1 Mixer", "INTERNAL_BT_SCO_TX", "INT_BT_SCO_TX"},
1146 {"MultiMedia1 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301147
1148 {"MultiMedia1 Mixer", "AFE_PCM_TX", "PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001149 {"MM_UL1", NULL, "MultiMedia1 Mixer"},
Jayasena Sangaraboina99fee652011-09-19 07:43:13 -07001150 {"MultiMedia2 Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
1151 {"MM_UL2", NULL, "MultiMedia2 Mixer"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001152
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001153 {"AUX_PCM_RX Audio Mixer", "MultiMedia1", "MM_DL1"},
1154 {"AUX_PCM_RX Audio Mixer", "MultiMedia2", "MM_DL2"},
1155 {"AUX_PCM_RX Audio Mixer", "MultiMedia3", "MM_DL3"},
1156 {"AUX_PCM_RX", NULL, "AUX_PCM_RX Audio Mixer"},
1157
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001158 {"PRI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1159 {"PRI_RX_Voice Mixer", "Voip", "VOIP_DL"},
1160 {"PRI_I2S_RX", NULL, "PRI_RX_Voice Mixer"},
1161
1162 {"SLIM_0_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1163 {"SLIM_0_RX_Voice Mixer", "Voip", "VOIP_DL"},
1164 {"SLIMBUS_0_RX", NULL, "SLIM_0_RX_Voice Mixer"},
1165
1166 {"INTERNAL_BT_SCO_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1167 {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voip", "VOIP_DL"},
1168 {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"},
1169
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301170 {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1171 {"AFE_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
1172 {"PCM_RX", NULL, "AFE_PCM_RX_Voice Mixer"},
1173
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001174 {"AUX_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1175 {"AUX_PCM_RX_Voice Mixer", "Voip", "VOIP_DL"},
1176 {"AUX_PCM_RX", NULL, "AUX_PCM_RX_Voice Mixer"},
1177
Alex Wong593576c2011-11-15 08:03:24 -08001178 {"HDMI_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"},
1179 {"HDMI_RX_Voice Mixer", "Voip", "VOIP_DL"},
1180 {"HDMI", NULL, "HDMI_RX_Voice Mixer"},
1181
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001182 {"Voice_Tx Mixer", "PRI_TX_Voice", "PRI_I2S_TX"},
1183 {"Voice_Tx Mixer", "SLIM_0_TX_Voice", "SLIMBUS_0_TX"},
1184 {"Voice_Tx Mixer", "INTERNAL_BT_SCO_TX_Voice", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301185 {"Voice_Tx Mixer", "AFE_PCM_TX_Voice", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001186 {"Voice_Tx Mixer", "AUX_PCM_TX_Voice", "AUX_PCM_TX"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001187 {"CS-VOICE_UL1", NULL, "Voice_Tx Mixer"},
1188 {"Voip_Tx Mixer", "PRI_TX_Voip", "PRI_I2S_TX"},
1189 {"Voip_Tx Mixer", "SLIM_0_TX_Voip", "SLIMBUS_0_TX"},
1190 {"Voip_Tx Mixer", "INTERNAL_BT_SCO_TX_Voip", "INT_BT_SCO_TX"},
Laxminath Kasam32657ec2011-08-01 19:26:57 +05301191 {"Voip_Tx Mixer", "AFE_PCM_TX_Voip", "PCM_TX"},
Bhalchandra Gajare0e795c42011-08-15 18:10:30 -07001192 {"Voip_Tx Mixer", "AUX_PCM_TX_Voip", "AUX_PCM_TX"},
1193
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001194 {"VOIP_UL", NULL, "Voip_Tx Mixer"},
Sriranjan Srikantamdf509d12011-10-24 17:53:27 -07001195 {"SLIMBUS_DL_HL", "Switch", "SLIM0_DL_HL"},
1196 {"SLIMBUS_0_RX", NULL, "SLIMBUS_DL_HL"},
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001197 {"SLIM0_UL_HL", NULL, "SLIMBUS_0_TX"},
1198 {"INT_FM_RX", NULL, "INTFM_DL_HL"},
1199 {"INTFM_UL_HL", NULL, "INT_FM_TX"},
1200 {"SLIMBUS_0_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"},
1201 {"SLIMBUS_0_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"},
1202 {"SLIMBUS_0_RX", NULL, "SLIMBUS_0_RX Port Mixer"},
1203};
1204
Patrick Laicf999112011-08-23 11:27:20 -07001205static int msm_pcm_routing_hw_params(struct snd_pcm_substream *substream,
1206 struct snd_pcm_hw_params *params)
1207{
1208 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1209 unsigned int be_id = rtd->dai_link->be_id;
1210
1211 mutex_lock(&routing_lock);
1212 msm_bedais[be_id].hw_params = params;
1213 mutex_unlock(&routing_lock);
1214 return 0;
1215}
1216
1217static int msm_pcm_routing_close(struct snd_pcm_substream *substream)
1218{
1219 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1220 unsigned int be_id = rtd->dai_link->be_id;
1221 int i, session_type;
1222 struct msm_pcm_routing_bdai_data *bedai;
1223
1224 if (be_id >= MSM_BACKEND_DAI_MAX) {
1225 pr_err("%s: unexpected be_id %d\n", __func__, be_id);
1226 return -EINVAL;
1227 }
1228
1229 bedai = &msm_bedais[be_id];
1230
1231 session_type = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
1232 0 : 1);
1233
1234 mutex_lock(&routing_lock);
1235
1236 for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
1237 if (fe_dai_map[i][session_type] != INVALID_SESSION)
1238 adm_close(bedai->port_id);
1239 }
1240
1241 bedai->active = 0;
1242 bedai->hw_params = NULL;
1243
1244 mutex_unlock(&routing_lock);
1245
1246 return 0;
1247}
1248
1249static int msm_pcm_routing_prepare(struct snd_pcm_substream *substream)
1250{
1251 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1252 unsigned int be_id = rtd->dai_link->be_id;
1253 int i, path_type, session_type;
1254 struct msm_pcm_routing_bdai_data *bedai;
1255
1256 if (be_id >= MSM_BACKEND_DAI_MAX) {
1257 pr_err("%s: unexpected be_id %d\n", __func__, be_id);
1258 return -EINVAL;
1259 }
1260
1261
1262 bedai = &msm_bedais[be_id];
1263
Jay Wangc8e03a82011-10-31 11:53:23 -07001264 if (bedai->hw_params == NULL) {
1265 pr_err("%s: HW param is not configured", __func__);
1266 return -EINVAL;
1267 }
1268
1269
Patrick Laicf999112011-08-23 11:27:20 -07001270 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1271 path_type = ADM_PATH_PLAYBACK;
1272 session_type = SESSION_TYPE_RX;
1273 } else {
1274 path_type = ADM_PATH_LIVE_REC;
1275 session_type = SESSION_TYPE_TX;
1276 }
1277
1278 mutex_lock(&routing_lock);
1279
1280 if (bedai->active == 1)
1281 goto done; /* Ignore prepare if back-end already active */
1282
1283 /* AFE port is not active at this point. However, still
1284 * go ahead setting active flag under the notion that
1285 * QDSP6 is able to handle ADM starting before AFE port
1286 * is started.
1287 */
1288 bedai->active = 1;
1289
1290 for_each_set_bit(i, &bedai->fe_sessions, MSM_FRONTEND_DAI_MAX) {
1291 if (fe_dai_map[i][session_type] != INVALID_SESSION) {
1292 adm_open(bedai->port_id, path_type,
1293 params_rate(bedai->hw_params),
1294 params_channels(bedai->hw_params),
1295 DEFAULT_COPP_TOPOLOGY);
1296 msm_pcm_routing_build_matrix(i,
1297 fe_dai_map[i][session_type], path_type);
1298 }
1299 }
1300
1301done:
1302 mutex_unlock(&routing_lock);
1303
1304 return 0;
1305}
1306
1307static struct snd_pcm_ops msm_routing_pcm_ops = {
1308 .hw_params = msm_pcm_routing_hw_params,
1309 .close = msm_pcm_routing_close,
1310 .prepare = msm_pcm_routing_prepare,
1311};
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001312
1313static unsigned int msm_routing_read(struct snd_soc_platform *platform,
1314 unsigned int reg)
1315{
1316 dev_dbg(platform->dev, "reg %x\n", reg);
1317 return 0;
1318}
1319
1320/* Not used but frame seems to require it */
1321static int msm_routing_write(struct snd_soc_platform *platform,
1322 unsigned int reg, unsigned int val)
1323{
1324 dev_dbg(platform->dev, "reg %x val %x\n", reg, val);
1325 return 0;
1326}
1327
1328/* Not used but frame seems to require it */
1329static int msm_routing_probe(struct snd_soc_platform *platform)
1330{
1331 snd_soc_dapm_new_controls(&platform->dapm, msm_qdsp6_widgets,
1332 ARRAY_SIZE(msm_qdsp6_widgets));
1333 snd_soc_dapm_add_routes(&platform->dapm, intercon,
1334 ARRAY_SIZE(intercon));
1335
1336 snd_soc_dapm_new_widgets(&platform->dapm);
1337
Jayasena Sangaraboinacb1e22f2011-07-18 10:36:57 -07001338 snd_soc_add_platform_controls(platform,
1339 int_fm_vol_mixer_controls,
1340 ARRAY_SIZE(int_fm_vol_mixer_controls));
Asish Bhattacharya0ec76182011-07-29 16:58:11 +05301341
1342 snd_soc_add_platform_controls(platform,
1343 lpa_vol_mixer_controls,
1344 ARRAY_SIZE(lpa_vol_mixer_controls));
Ben Romberger037dd2f2011-09-22 14:01:32 -07001345
1346 snd_soc_add_platform_controls(platform,
1347 eq_enable_mixer_controls,
1348 ARRAY_SIZE(eq_enable_mixer_controls));
1349
1350 snd_soc_add_platform_controls(platform,
1351 eq_band_mixer_controls,
1352 ARRAY_SIZE(eq_band_mixer_controls));
1353
1354 snd_soc_add_platform_controls(platform,
1355 eq_coeff_mixer_controls,
1356 ARRAY_SIZE(eq_coeff_mixer_controls));
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001357 return 0;
1358}
1359
1360static struct snd_soc_platform_driver msm_soc_routing_platform = {
1361 .ops = &msm_routing_pcm_ops,
1362 .probe = msm_routing_probe,
1363 .read = msm_routing_read,
1364 .write = msm_routing_write,
1365};
1366
1367static __devinit int msm_routing_pcm_probe(struct platform_device *pdev)
1368{
1369 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
1370 return snd_soc_register_platform(&pdev->dev,
1371 &msm_soc_routing_platform);
1372}
1373
1374static int msm_routing_pcm_remove(struct platform_device *pdev)
1375{
1376 snd_soc_unregister_platform(&pdev->dev);
1377 return 0;
1378}
1379
1380static struct platform_driver msm_routing_pcm_driver = {
1381 .driver = {
1382 .name = "msm-pcm-routing",
1383 .owner = THIS_MODULE,
1384 },
1385 .probe = msm_routing_pcm_probe,
1386 .remove = __devexit_p(msm_routing_pcm_remove),
1387};
1388
1389static int __init msm_soc_routing_platform_init(void)
1390{
Neema Shettyfeea7742011-09-11 12:30:36 -07001391 mutex_init(&routing_lock);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001392 return platform_driver_register(&msm_routing_pcm_driver);
1393}
1394module_init(msm_soc_routing_platform_init);
1395
1396static void __exit msm_soc_routing_platform_exit(void)
1397{
1398 platform_driver_unregister(&msm_routing_pcm_driver);
1399}
1400module_exit(msm_soc_routing_platform_exit);
1401
1402MODULE_DESCRIPTION("MSM routing platform driver");
1403MODULE_LICENSE("GPL v2");