blob: 13ae8e9b4caaca985b6964699ec5a9902d633a2c [file] [log] [blame]
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001/*
2 * omap-abe-dsp.c
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
16 * 02110-1301 USA
17 *
18 * Copyright (C) 2010 Texas Instruments Inc.
19 *
20 * Authors: Liam Girdwood <lrg@ti.com>
21 * Misael Lopez Cruz <misael.lopez@ti.com>
22 * Sebastien Guiriec <s-guiriec@ti.com>
23 *
24 */
25
26#define DEBUG
27
28#include <linux/module.h>
29#include <linux/moduleparam.h>
30#include <linux/init.h>
31#include <linux/delay.h>
32#include <linux/pm.h>
33#include <linux/i2c.h>
34#include <linux/gpio.h>
35#include <linux/platform_device.h>
36#include <linux/workqueue.h>
37#include <linux/i2c/twl.h>
38#include <linux/clk.h>
39#include <linux/err.h>
40#include <linux/slab.h>
41#include <linux/pm_runtime.h>
42#include <linux/dma-mapping.h>
43#include <linux/wait.h>
44#include <linux/firmware.h>
45#include <linux/debugfs.h>
46
47#include <plat/omap_hwmod.h>
48#include <plat/omap_device.h>
49#include <plat/dma.h>
50
51#include <sound/core.h>
52#include <sound/pcm.h>
53#include <sound/pcm_params.h>
54#include <sound/soc.h>
55#include <sound/soc-dapm.h>
56#include <sound/initval.h>
57#include <sound/tlv.h>
58#include <sound/omap-abe-dsp.h>
59
60#include "omap-abe-dsp.h"
61#include "omap-abe.h"
62#include "abe/abe_main.h"
63#include "abe/port_mgr.h"
64
65#warning need omap_device_set_rate
66#define omap_device_set_rate(x, y, z)
67
68static const char *abe_memory_bank[5] = {
69 "dmem",
70 "cmem",
71 "smem",
72 "pmem",
73 "mpu"
74};
75
76
77/*
78 * ABE loadable coefficients.
79 * The coefficient and their mixer configurations are loaded with the firmware
80 * blob duing probe().
81 */
82
83struct coeff_config {
84 char name[ABE_COEFF_NAME_SIZE];
85 u32 count;
86 u32 coeff;
87 char texts[ABE_COEFF_NUM_TEXTS][ABE_COEFF_TEXT_SIZE];
88};
89
90/*
91 * ABE Firmware Header.
92 * The ABE firmware blob has a header that describes each data section. This
93 * way we can store coefficients etc in the firmware.
94 */
95struct fw_header {
96 u32 magic; /* magic number */
97 u32 crc; /* optional crc */
98 u32 firmware_size; /* payload size */
99 u32 coeff_size; /* payload size */
100 u32 coeff_version; /* coefficent version */
101 u32 firmware_version; /* min version of ABE firmware required */
102 u32 num_equ; /* number of equalizers */
103};
104
105/*
106 * ABE private data.
107 */
108struct abe_data {
109 struct omap4_abe_dsp_pdata *abe_pdata;
110 struct device *dev;
111 struct snd_soc_platform *platform;
112 struct delayed_work delayed_work;
113 struct mutex mutex;
114 struct mutex opp_mutex;
115 struct clk *clk;
116 void __iomem *io_base[5];
117 int irq;
118 int opp;
119 int active;
120
121 /* coefficients */
122 struct fw_header hdr;
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -0500123 u32 *firmware;
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000124 s32 *equ[ABE_MAX_EQU];
125 int equ_profile[ABE_MAX_EQU];
126 struct soc_enum equalizer_enum[ABE_MAX_EQU];
127 struct snd_kcontrol_new equalizer_control[ABE_MAX_EQU];
128 struct coeff_config *equ_texts;
129
130 /* DAPM mixer config - TODO: some of this can be replaced with HAL update */
131 u32 widget_opp[ABE_NUM_DAPM_REG + 1];
132
133 u16 router[16];
134 int loss_count;
135
136 struct snd_pcm_substream *ping_pong_substream;
137 int first_irq;
138
139 struct snd_pcm_substream *psubs;
140
141#ifdef CONFIG_DEBUG_FS
142 /* ABE runtime debug config */
143
144 /* its intended we can switch on/off individual debug items */
145 u32 dbg_format1; /* TODO: match flag names here to debug format flags */
146 u32 dbg_format2;
147 u32 dbg_format3;
148
149 u32 dbg_buffer_bytes;
150 u32 dbg_circular;
151 u32 dbg_buffer_msecs; /* size of buffer in secs */
152 u32 dbg_elem_bytes;
153 dma_addr_t dbg_buffer_addr;
154 wait_queue_head_t wait;
155 int dbg_reader_offset;
156 int dbg_dma_offset;
157 int dbg_complete;
158 struct dentry *debugfs_root;
159 struct dentry *debugfs_fmt1;
160 struct dentry *debugfs_fmt2;
161 struct dentry *debugfs_fmt3;
162 struct dentry *debugfs_size;
163 struct dentry *debugfs_data;
164 struct dentry *debugfs_circ;
165 struct dentry *debugfs_elem_bytes;
166 struct dentry *debugfs_opp_level;
167 char *dbg_buffer;
168 struct omap_pcm_dma_data *dma_data;
169 int dma_ch;
170 int dma_req;
171#endif
172};
173
174static struct abe_data *the_abe;
175
176// TODO: map to the new version of HAL
177static unsigned int abe_dsp_read(struct snd_soc_platform *platform,
178 unsigned int reg)
179{
180 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
181
182 BUG_ON(reg > ABE_NUM_DAPM_REG);
183 return abe->widget_opp[reg];
184}
185
186static int abe_dsp_write(struct snd_soc_platform *platform, unsigned int reg,
187 unsigned int val)
188{
189 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
190
191 BUG_ON(reg > ABE_NUM_DAPM_REG);
192 abe->widget_opp[reg] = val;
193 return 0;
194}
195
196static void abe_irq_pingpong_subroutine(u32 *data)
197{
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000198 u32 dst, n_bytes;
199
200 abe_read_next_ping_pong_buffer(MM_DL_PORT, &dst, &n_bytes);
201 abe_set_ping_pong_buffer(MM_DL_PORT, n_bytes);
202
203 /* Do not call ALSA function for first IRQ */
204 if (the_abe->first_irq) {
205 the_abe->first_irq = 0;
206 } else {
207 if (the_abe->ping_pong_substream)
208 snd_pcm_period_elapsed(the_abe->ping_pong_substream);
209 }
210}
211
212static irqreturn_t abe_irq_handler(int irq, void *dev_id)
213{
214 struct abe_data *abe = dev_id;
215
216 /* TODO: handle underruns/overruns/errors */
217 pm_runtime_get_sync(abe->dev);
218 abe_clear_irq(); // TODO: why is IRQ not cleared after processing ?
219 abe_irq_processing();
220 pm_runtime_put_sync(abe->dev);
221 return IRQ_HANDLED;
222}
223
224// TODO: these should really be called internally since we will know the McPDM state
225void abe_dsp_pm_get(void)
226{
227 pm_runtime_get_sync(the_abe->dev);
228}
229EXPORT_SYMBOL_GPL(abe_dsp_pm_get);
230
231void abe_dsp_pm_put(void)
232{
233 pm_runtime_put_sync(the_abe->dev);
234}
235EXPORT_SYMBOL_GPL(abe_dsp_pm_put);
236
237void abe_dsp_shutdown(void)
238{
239 if (!the_abe->active && !abe_check_activity()) {
240 abe_set_opp_processing(ABE_OPP25);
241 the_abe->opp = 25;
242 abe_stop_event_generator();
243 udelay(250);
244 omap_device_set_rate(the_abe->dev, the_abe->dev, 0);
245 }
246}
247EXPORT_SYMBOL_GPL(abe_dsp_shutdown);
248
249/*
250 * These TLV settings will need fine tuned for each individual control
251 */
252
253/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
254static DECLARE_TLV_DB_SCALE(mm_dl1_tlv, -12000, 100, 3000);
255
256/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
257static DECLARE_TLV_DB_SCALE(tones_dl1_tlv, -12000, 100, 3000);
258
259/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
260static DECLARE_TLV_DB_SCALE(voice_dl1_tlv, -12000, 100, 3000);
261
262/* Media DL1 volume control from -120 to 30 dB in 1 dB steps */
263static DECLARE_TLV_DB_SCALE(capture_dl1_tlv, -12000, 100, 3000);
264
265/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
266static DECLARE_TLV_DB_SCALE(mm_dl2_tlv, -12000, 100, 3000);
267
268/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
269static DECLARE_TLV_DB_SCALE(tones_dl2_tlv, -12000, 100, 3000);
270
271/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
272static DECLARE_TLV_DB_SCALE(voice_dl2_tlv, -12000, 100, 3000);
273
274/* Media DL2 volume control from -120 to 30 dB in 1 dB steps */
275static DECLARE_TLV_DB_SCALE(capture_dl2_tlv, -12000, 100, 3000);
276
277/* SDT volume control from -120 to 30 dB in 1 dB steps */
278static DECLARE_TLV_DB_SCALE(sdt_ul_tlv, -12000, 100, 3000);
279
280/* SDT volume control from -120 to 30 dB in 1 dB steps */
281static DECLARE_TLV_DB_SCALE(sdt_dl_tlv, -12000, 100, 3000);
282
283/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
284static DECLARE_TLV_DB_SCALE(audul_mm_tlv, -12000, 100, 3000);
285
286/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
287static DECLARE_TLV_DB_SCALE(audul_tones_tlv, -12000, 100, 3000);
288
289/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
290static DECLARE_TLV_DB_SCALE(audul_vx_ul_tlv, -12000, 100, 3000);
291
292/* AUDUL volume control from -120 to 30 dB in 1 dB steps */
293static DECLARE_TLV_DB_SCALE(audul_vx_dl_tlv, -12000, 100, 3000);
294
295/* VXREC volume control from -120 to 30 dB in 1 dB steps */
296static DECLARE_TLV_DB_SCALE(vxrec_mm_dl_tlv, -12000, 100, 3000);
297
298/* VXREC volume control from -120 to 30 dB in 1 dB steps */
299static DECLARE_TLV_DB_SCALE(vxrec_tones_tlv, -12000, 100, 3000);
300
301/* VXREC volume control from -120 to 30 dB in 1 dB steps */
302static DECLARE_TLV_DB_SCALE(vxrec_vx_dl_tlv, -12000, 100, 3000);
303
304/* VXREC volume control from -120 to 30 dB in 1 dB steps */
305static DECLARE_TLV_DB_SCALE(vxrec_vx_ul_tlv, -12000, 100, 3000);
306
307/* DMIC volume control from -120 to 30 dB in 1 dB steps */
308static DECLARE_TLV_DB_SCALE(dmic_tlv, -12000, 100, 3000);
309
310/* BT UL volume control from -120 to 30 dB in 1 dB steps */
311static DECLARE_TLV_DB_SCALE(btul_tlv, -12000, 100, 3000);
312
313/* AMIC volume control from -120 to 30 dB in 1 dB steps */
314static DECLARE_TLV_DB_SCALE(amic_tlv, -12000, 100, 3000);
315
316//TODO: we have to use the shift value atm to represent register id due to current HAL
317static int dl1_put_mixer(struct snd_kcontrol *kcontrol,
318 struct snd_ctl_elem_value *ucontrol)
319{
320 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
321 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
322 struct soc_mixer_control *mc =
323 (struct soc_mixer_control *)kcontrol->private_value;
324
325 pm_runtime_get_sync(the_abe->dev);
326
327 // TODO: optimise all of these to call HAL abe_enable_gain(mixer, enable)
328 if (ucontrol->value.integer.value[0]) {
329 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
330 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
331 abe_enable_gain(MIXDL1, mc->reg);
332 } else {
333 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
334 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
335 abe_disable_gain(MIXDL1, mc->reg);
336 }
337 pm_runtime_put_sync(the_abe->dev);
338
339 return 1;
340}
341
342static int dl2_put_mixer(struct snd_kcontrol *kcontrol,
343 struct snd_ctl_elem_value *ucontrol)
344{
345 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
346 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
347 struct soc_mixer_control *mc =
348 (struct soc_mixer_control *)kcontrol->private_value;
349
350 pm_runtime_get_sync(the_abe->dev);
351
352 if (ucontrol->value.integer.value[0]) {
353 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
354 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
355 abe_enable_gain(MIXDL2, mc->reg);
356 } else {
357 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
358 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
359 abe_disable_gain(MIXDL2, mc->reg);
360 }
361
362 pm_runtime_put_sync(the_abe->dev);
363 return 1;
364}
365
366static int audio_ul_put_mixer(struct snd_kcontrol *kcontrol,
367 struct snd_ctl_elem_value *ucontrol)
368{
369 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
370 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
371 struct soc_mixer_control *mc =
372 (struct soc_mixer_control *)kcontrol->private_value;
373
374 pm_runtime_get_sync(the_abe->dev);
375
376 if (ucontrol->value.integer.value[0]) {
377 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
378 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
379 abe_enable_gain(MIXAUDUL, mc->reg);
380 } else {
381 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
382 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
383 abe_disable_gain(MIXAUDUL, mc->reg);
384 }
385 pm_runtime_put_sync(the_abe->dev);
386
387 return 1;
388}
389
390static int vxrec_put_mixer(struct snd_kcontrol *kcontrol,
391 struct snd_ctl_elem_value *ucontrol)
392{
393 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
394 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
395 struct soc_mixer_control *mc =
396 (struct soc_mixer_control *)kcontrol->private_value;
397
398 pm_runtime_get_sync(the_abe->dev);
399
400 if (ucontrol->value.integer.value[0]) {
401 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
402 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
403 abe_enable_gain(MIXVXREC, mc->reg);
404 } else {
405 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
406 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
407 abe_disable_gain(MIXVXREC, mc->reg);
408 }
409 pm_runtime_put_sync(the_abe->dev);
410
411 return 1;
412}
413
414static int sdt_put_mixer(struct snd_kcontrol *kcontrol,
415 struct snd_ctl_elem_value *ucontrol)
416{
417 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
418 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
419 struct soc_mixer_control *mc =
420 (struct soc_mixer_control *)kcontrol->private_value;
421
422 pm_runtime_get_sync(the_abe->dev);
423
424 if (ucontrol->value.integer.value[0]) {
425 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
426 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
427 abe_enable_gain(MIXSDT, mc->reg);
428 } else {
429 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
430 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
431 abe_disable_gain(MIXSDT, mc->reg);
432 }
433 pm_runtime_put_sync(the_abe->dev);
434
435 return 1;
436}
437
438static int abe_get_mixer(struct snd_kcontrol *kcontrol,
439 struct snd_ctl_elem_value *ucontrol)
440{
441 struct soc_mixer_control *mc =
442 (struct soc_mixer_control *)kcontrol->private_value;
443
444 ucontrol->value.integer.value[0] = the_abe->widget_opp[mc->shift];
445 return 0;
446}
447
448/* router IDs that match our mixer strings */
449static const abe_router_t router[] = {
450 ZERO_labelID, /* strangely this is not 0 */
451 DMIC1_L_labelID, DMIC1_R_labelID,
452 DMIC2_L_labelID, DMIC2_R_labelID,
453 DMIC3_L_labelID, DMIC3_R_labelID,
454 BT_UL_L_labelID, BT_UL_R_labelID,
455 MM_EXT_IN_L_labelID, MM_EXT_IN_R_labelID,
456 AMIC_L_labelID, AMIC_R_labelID,
457 VX_REC_L_labelID, VX_REC_R_labelID,
458};
459
460static int ul_mux_put_route(struct snd_kcontrol *kcontrol,
461 struct snd_ctl_elem_value *ucontrol)
462{
463 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
464 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
465 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
466 int mux = ucontrol->value.enumerated.item[0];
467 int reg = e->reg - ABE_MUX(0);
468
469 pm_runtime_get_sync(the_abe->dev);
470
471 if (mux > ABE_ROUTES_UL)
472 return 0;
473
474 // TODO: get all this via firmware
475 if (reg < 8) {
476 /* 0 .. 9 = MM_UL */
477 the_abe->router[reg] = router[mux];
478 } else if (reg < 12) {
479 /* 10 .. 11 = MM_UL2 */
480 /* 12 .. 13 = VX_UL */
481 the_abe->router[reg + 2] = router[mux];
482 }
483
484 /* 2nd arg here is unused */
485 abe_set_router_configuration(UPROUTE, 0, (u32 *)the_abe->router);
486
487 if (router[mux] != ZERO_labelID)
488 the_abe->widget_opp[e->reg] = e->shift_l;
489 else
490 the_abe->widget_opp[e->reg] = 0;
491
492 snd_soc_dapm_mux_update_power(widget, kcontrol, 1, mux, e);
493 pm_runtime_put_sync(the_abe->dev);
494
495 return 1;
496}
497
498static int ul_mux_get_route(struct snd_kcontrol *kcontrol,
499 struct snd_ctl_elem_value *ucontrol)
500{
501 struct soc_enum *e =
502 (struct soc_enum *)kcontrol->private_value;
503 int reg = e->reg - ABE_MUX(0), i, rval = 0;
504
505 // TODO: get all this via firmware
506 if (reg < 8) {
507 /* 0 .. 9 = MM_UL */
508 rval = the_abe->router[reg];
509 } else if (reg < 12) {
510 /* 10 .. 11 = MM_UL2 */
511 /* 12 .. 13 = VX_UL */
512 rval = the_abe->router[reg + 2];
513 }
514
515 for (i = 0; i < ARRAY_SIZE(router); i++) {
516 if (router[i] == rval) {
517 ucontrol->value.integer.value[0] = i;
518 return 0;
519 }
520 }
521
522 return 1;
523}
524
525
526static int abe_put_switch(struct snd_kcontrol *kcontrol,
527 struct snd_ctl_elem_value *ucontrol)
528{
529 struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
530 struct snd_soc_dapm_widget *widget = wlist->widgets[0];
531 struct soc_mixer_control *mc =
532 (struct soc_mixer_control *)kcontrol->private_value;
533
534 pm_runtime_get_sync(the_abe->dev);
535
536 if (ucontrol->value.integer.value[0]) {
537 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
538 snd_soc_dapm_mixer_update_power(widget, kcontrol, 1);
539 } else {
540 the_abe->widget_opp[mc->shift] = ucontrol->value.integer.value[0];
541 snd_soc_dapm_mixer_update_power(widget, kcontrol, 0);
542 }
543 pm_runtime_put_sync(the_abe->dev);
544
545 return 1;
546}
547
548
549static int volume_put_sdt_mixer(struct snd_kcontrol *kcontrol,
550 struct snd_ctl_elem_value *ucontrol)
551{
552 struct soc_mixer_control *mc =
553 (struct soc_mixer_control *)kcontrol->private_value;
554
555 pm_runtime_get_sync(the_abe->dev);
556
557 abe_write_mixer(MIXSDT, abe_val_to_gain(ucontrol->value.integer.value[0]),
558 RAMP_0MS, mc->reg);
559 pm_runtime_put_sync(the_abe->dev);
560
561 return 1;
562}
563
564static int volume_put_audul_mixer(struct snd_kcontrol *kcontrol,
565 struct snd_ctl_elem_value *ucontrol)
566{
567 struct soc_mixer_control *mc =
568 (struct soc_mixer_control *)kcontrol->private_value;
569
570 pm_runtime_get_sync(the_abe->dev);
571 abe_write_mixer(MIXAUDUL, abe_val_to_gain(ucontrol->value.integer.value[0]),
572 RAMP_0MS, mc->reg);
573 pm_runtime_put_sync(the_abe->dev);
574
575 return 1;
576}
577
578static int volume_put_vxrec_mixer(struct snd_kcontrol *kcontrol,
579 struct snd_ctl_elem_value *ucontrol)
580{
581 struct soc_mixer_control *mc =
582 (struct soc_mixer_control *)kcontrol->private_value;
583
584 pm_runtime_get_sync(the_abe->dev);
585 abe_write_mixer(MIXVXREC, abe_val_to_gain(ucontrol->value.integer.value[0]),
586 RAMP_0MS, mc->reg);
587 pm_runtime_put_sync(the_abe->dev);
588
589 return 1;
590}
591
592static int volume_put_dl1_mixer(struct snd_kcontrol *kcontrol,
593 struct snd_ctl_elem_value *ucontrol)
594{
595 struct soc_mixer_control *mc =
596 (struct soc_mixer_control *)kcontrol->private_value;
597
598 pm_runtime_get_sync(the_abe->dev);
599 abe_write_mixer(MIXDL1, abe_val_to_gain(ucontrol->value.integer.value[0]),
600 RAMP_0MS, mc->reg);
601 pm_runtime_put_sync(the_abe->dev);
602
603 return 1;
604}
605
606static int volume_put_dl2_mixer(struct snd_kcontrol *kcontrol,
607 struct snd_ctl_elem_value *ucontrol)
608{
609 struct soc_mixer_control *mc =
610 (struct soc_mixer_control *)kcontrol->private_value;
611
612 pm_runtime_get_sync(the_abe->dev);
613 abe_write_mixer(MIXDL2, abe_val_to_gain(ucontrol->value.integer.value[0]),
614 RAMP_0MS, mc->reg);
615 pm_runtime_put_sync(the_abe->dev);
616
617 return 1;
618}
619
620static int volume_put_gain(struct snd_kcontrol *kcontrol,
621 struct snd_ctl_elem_value *ucontrol)
622{
623 struct soc_mixer_control *mc =
624 (struct soc_mixer_control *)kcontrol->private_value;
625
626 pm_runtime_get_sync(the_abe->dev);
627 abe_write_gain(mc->reg,
628 abe_val_to_gain(ucontrol->value.integer.value[0]),
629 RAMP_20MS, mc->shift);
630 abe_write_gain(mc->reg,
631 -12000 + (ucontrol->value.integer.value[1] * 100),
632 RAMP_20MS, mc->rshift);
633 pm_runtime_put_sync(the_abe->dev);
634
635 return 1;
636}
637
638static int volume_get_dl1_mixer(struct snd_kcontrol *kcontrol,
639 struct snd_ctl_elem_value *ucontrol)
640{
641 struct soc_mixer_control *mc =
642 (struct soc_mixer_control *)kcontrol->private_value;
643 u32 val;
644
645 pm_runtime_get_sync(the_abe->dev);
646 abe_read_mixer(MIXDL1, &val, mc->reg);
647 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
648 pm_runtime_put_sync(the_abe->dev);
649
650 return 0;
651}
652
653static int volume_get_dl2_mixer(struct snd_kcontrol *kcontrol,
654 struct snd_ctl_elem_value *ucontrol)
655{
656 struct soc_mixer_control *mc =
657 (struct soc_mixer_control *)kcontrol->private_value;
658 u32 val;
659
660 pm_runtime_get_sync(the_abe->dev);
661 abe_read_mixer(MIXDL2, &val, mc->reg);
662 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
663 pm_runtime_put_sync(the_abe->dev);
664
665 return 0;
666}
667
668static int volume_get_audul_mixer(struct snd_kcontrol *kcontrol,
669 struct snd_ctl_elem_value *ucontrol)
670{
671 struct soc_mixer_control *mc =
672 (struct soc_mixer_control *)kcontrol->private_value;
673 u32 val;
674
675 pm_runtime_get_sync(the_abe->dev);
676 abe_read_mixer(MIXAUDUL, &val, mc->reg);
677 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
678 pm_runtime_put_sync(the_abe->dev);
679
680 return 0;
681}
682
683static int volume_get_vxrec_mixer(struct snd_kcontrol *kcontrol,
684 struct snd_ctl_elem_value *ucontrol)
685{
686 struct soc_mixer_control *mc =
687 (struct soc_mixer_control *)kcontrol->private_value;
688 u32 val;
689
690 pm_runtime_get_sync(the_abe->dev);
691 abe_read_mixer(MIXVXREC, &val, mc->reg);
692 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
693 pm_runtime_put_sync(the_abe->dev);
694
695 return 0;
696}
697
698static int volume_get_sdt_mixer(struct snd_kcontrol *kcontrol,
699 struct snd_ctl_elem_value *ucontrol)
700{
701 struct soc_mixer_control *mc =
702 (struct soc_mixer_control *)kcontrol->private_value;
703 u32 val;
704
705 pm_runtime_get_sync(the_abe->dev);
706 abe_read_mixer(MIXSDT, &val, mc->reg);
707 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
708 pm_runtime_put_sync(the_abe->dev);
709
710 return 0;
711}
712
713static int volume_get_gain(struct snd_kcontrol *kcontrol,
714 struct snd_ctl_elem_value *ucontrol)
715{
716 struct soc_mixer_control *mc =
717 (struct soc_mixer_control *)kcontrol->private_value;
718 u32 val;
719
720 pm_runtime_get_sync(the_abe->dev);
721 abe_read_gain(mc->reg, &val, mc->shift);
722 ucontrol->value.integer.value[0] = abe_gain_to_val(val);
723 abe_read_gain(mc->reg, &val, mc->rshift);
724 ucontrol->value.integer.value[1] = abe_gain_to_val(val);
725 pm_runtime_put_sync(the_abe->dev);
726
727 return 0;
728}
729
730static int abe_get_equalizer(struct snd_kcontrol *kcontrol,
731 struct snd_ctl_elem_value *ucontrol)
732{
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000733 struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
734
735 ucontrol->value.integer.value[0] = the_abe->equ_profile[eqc->reg];
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000736 return 0;
737}
738
739static int abe_put_equalizer(struct snd_kcontrol *kcontrol,
740 struct snd_ctl_elem_value *ucontrol)
741{
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000742 struct soc_enum *eqc = (struct soc_enum *)kcontrol->private_value;
743 u16 val = ucontrol->value.enumerated.item[0];
744 abe_equ_t equ_params;
Sebastien Guiriec2c25e322011-07-13 02:54:44 -0500745 int len;
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000746
Sebastien Guiriec2c25e322011-07-13 02:54:44 -0500747 if (eqc->reg >= the_abe->hdr.num_equ)
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000748 return -EINVAL;
749
Sebastien Guiriec2c25e322011-07-13 02:54:44 -0500750 if (val >= the_abe->equ_texts[eqc->reg].count)
751 return -EINVAL;
752
753 len = the_abe->equ_texts[eqc->reg].coeff;
754 equ_params.equ_length = len;
755 memcpy(equ_params.coef.type1, the_abe->equ[eqc->reg] + val * len,
756 len * sizeof(u32));
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000757 the_abe->equ_profile[eqc->reg] = val;
758
759 pm_runtime_get_sync(the_abe->dev);
Sebastien Guiriec2c25e322011-07-13 02:54:44 -0500760 abe_write_equalizer(eqc->reg + 1, &equ_params);
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000761 pm_runtime_put_sync(the_abe->dev);
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -0500762
Liam Girdwooda8d99da2011-02-03 15:28:19 +0000763 return 1;
764}
765
766int snd_soc_info_enum_ext1(struct snd_kcontrol *kcontrol,
767 struct snd_ctl_elem_info *uinfo)
768{
769 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
770
771 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
772 uinfo->count = 1;
773 uinfo->value.enumerated.items = e->max;
774
775 if (uinfo->value.enumerated.item > e->max - 1)
776 uinfo->value.enumerated.item = e->max - 1;
777 strcpy(uinfo->value.enumerated.name,
778 snd_soc_get_enum_text(e, uinfo->value.enumerated.item));
779
780 return 0;
781}
782
783static const char *route_ul_texts[] = {
784 "None", "DMic0L", "DMic0R", "DMic1L", "DMic1R", "DMic2L", "DMic2R",
785 "BT Left", "BT Right", "MMExt Left", "MMExt Right", "AMic0", "AMic1",
786 "VX Left", "VX Right"
787};
788
789/* ROUTE_UL Mux table */
790static const struct soc_enum abe_enum[] = {
791 SOC_ENUM_SINGLE(MUX_MM_UL10, 0, 15, route_ul_texts),
792 SOC_ENUM_SINGLE(MUX_MM_UL11, 0, 15, route_ul_texts),
793 SOC_ENUM_SINGLE(MUX_MM_UL12, 0, 15, route_ul_texts),
794 SOC_ENUM_SINGLE(MUX_MM_UL13, 0, 15, route_ul_texts),
795 SOC_ENUM_SINGLE(MUX_MM_UL14, 0, 15, route_ul_texts),
796 SOC_ENUM_SINGLE(MUX_MM_UL15, 0, 15, route_ul_texts),
797 SOC_ENUM_SINGLE(MUX_MM_UL16, 0, 15, route_ul_texts),
798 SOC_ENUM_SINGLE(MUX_MM_UL17, 0, 15, route_ul_texts),
799 SOC_ENUM_SINGLE(MUX_MM_UL20, 0, 15, route_ul_texts),
800 SOC_ENUM_SINGLE(MUX_MM_UL21, 0, 15, route_ul_texts),
801 SOC_ENUM_SINGLE(MUX_VX_UL0, 0, 15, route_ul_texts),
802 SOC_ENUM_SINGLE(MUX_VX_UL1, 0, 15, route_ul_texts),
803};
804
805static const struct snd_kcontrol_new mm_ul00_control =
806 SOC_DAPM_ENUM_EXT("Route", abe_enum[0],
807 ul_mux_get_route, ul_mux_put_route);
808
809static const struct snd_kcontrol_new mm_ul01_control =
810 SOC_DAPM_ENUM_EXT("Route", abe_enum[1],
811 ul_mux_get_route, ul_mux_put_route);
812
813static const struct snd_kcontrol_new mm_ul02_control =
814 SOC_DAPM_ENUM_EXT("Route", abe_enum[2],
815 ul_mux_get_route, ul_mux_put_route);
816
817static const struct snd_kcontrol_new mm_ul03_control =
818 SOC_DAPM_ENUM_EXT("Route", abe_enum[3],
819 ul_mux_get_route, ul_mux_put_route);
820
821static const struct snd_kcontrol_new mm_ul04_control =
822 SOC_DAPM_ENUM_EXT("Route", abe_enum[4],
823 ul_mux_get_route, ul_mux_put_route);
824
825static const struct snd_kcontrol_new mm_ul05_control =
826 SOC_DAPM_ENUM_EXT("Route", abe_enum[5],
827 ul_mux_get_route, ul_mux_put_route);
828
829static const struct snd_kcontrol_new mm_ul06_control =
830 SOC_DAPM_ENUM_EXT("Route", abe_enum[6],
831 ul_mux_get_route, ul_mux_put_route);
832
833static const struct snd_kcontrol_new mm_ul07_control =
834 SOC_DAPM_ENUM_EXT("Route", abe_enum[7],
835 ul_mux_get_route, ul_mux_put_route);
836
837static const struct snd_kcontrol_new mm_ul10_control =
838 SOC_DAPM_ENUM_EXT("Route", abe_enum[8],
839 ul_mux_get_route, ul_mux_put_route);
840
841static const struct snd_kcontrol_new mm_ul11_control =
842 SOC_DAPM_ENUM_EXT("Route", abe_enum[9],
843 ul_mux_get_route, ul_mux_put_route);
844
845static const struct snd_kcontrol_new mm_vx0_control =
846 SOC_DAPM_ENUM_EXT("Route", abe_enum[10],
847 ul_mux_get_route, ul_mux_put_route);
848
849static const struct snd_kcontrol_new mm_vx1_control =
850 SOC_DAPM_ENUM_EXT("Route", abe_enum[11],
851 ul_mux_get_route, ul_mux_put_route);
852
853/* DL1 mixer paths */
854static const struct snd_kcontrol_new dl1_mixer_controls[] = {
855 SOC_SINGLE_EXT("Tones", MIX_DL1_INPUT_TONES, MIX_DL1_TONES, 1, 0,
856 abe_get_mixer, dl1_put_mixer),
857 SOC_SINGLE_EXT("Voice", MIX_DL1_INPUT_VX_DL, MIX_DL1_VOICE, 1, 0,
858 abe_get_mixer, dl1_put_mixer),
859 SOC_SINGLE_EXT("Capture", MIX_DL1_INPUT_MM_UL2, MIX_DL1_CAPTURE, 1, 0,
860 abe_get_mixer, dl1_put_mixer),
861 SOC_SINGLE_EXT("Multimedia", MIX_DL1_INPUT_MM_DL, MIX_DL1_MEDIA, 1, 0,
862 abe_get_mixer, dl1_put_mixer),
863};
864
865/* DL2 mixer paths */
866static const struct snd_kcontrol_new dl2_mixer_controls[] = {
867 SOC_SINGLE_EXT("Tones", MIX_DL2_INPUT_TONES, MIX_DL2_TONES, 1, 0,
868 abe_get_mixer, dl2_put_mixer),
869 SOC_SINGLE_EXT("Voice", MIX_DL2_INPUT_VX_DL, MIX_DL2_VOICE, 1, 0,
870 abe_get_mixer, dl2_put_mixer),
871 SOC_SINGLE_EXT("Capture", MIX_DL2_INPUT_MM_UL2, MIX_DL2_CAPTURE, 1, 0,
872 abe_get_mixer, dl2_put_mixer),
873 SOC_SINGLE_EXT("Multimedia", MIX_DL2_INPUT_MM_DL, MIX_DL2_MEDIA, 1, 0,
874 abe_get_mixer, dl2_put_mixer),
875};
876
877/* AUDUL ("Voice Capture Mixer") mixer paths */
878static const struct snd_kcontrol_new audio_ul_mixer_controls[] = {
879 SOC_SINGLE_EXT("Tones Playback", MIX_AUDUL_INPUT_TONES, MIX_AUDUL_TONES, 1, 0,
880 abe_get_mixer, audio_ul_put_mixer),
881 SOC_SINGLE_EXT("Media Playback", MIX_AUDUL_INPUT_MM_DL, MIX_AUDUL_MEDIA, 1, 0,
882 abe_get_mixer, audio_ul_put_mixer),
883 SOC_SINGLE_EXT("Capture", MIX_AUDUL_INPUT_UPLINK, MIX_AUDUL_CAPTURE, 1, 0,
884 abe_get_mixer, audio_ul_put_mixer),
885};
886
887/* VXREC ("Capture Mixer") mixer paths */
888static const struct snd_kcontrol_new vx_rec_mixer_controls[] = {
889 SOC_SINGLE_EXT("Tones", MIX_VXREC_INPUT_TONES, MIX_VXREC_TONES, 1, 0,
890 abe_get_mixer, vxrec_put_mixer),
891 SOC_SINGLE_EXT("Voice Playback", MIX_VXREC_INPUT_VX_DL,
892 MIX_VXREC_VOICE_PLAYBACK, 1, 0, abe_get_mixer, vxrec_put_mixer),
893 SOC_SINGLE_EXT("Voice Capture", MIX_VXREC_INPUT_VX_UL,
894 MIX_VXREC_VOICE_CAPTURE, 1, 0, abe_get_mixer, vxrec_put_mixer),
895 SOC_SINGLE_EXT("Media Playback", MIX_VXREC_INPUT_MM_DL,
896 MIX_VXREC_MEDIA, 1, 0, abe_get_mixer, vxrec_put_mixer),
897};
898
899/* SDT ("Sidetone Mixer") mixer paths */
900static const struct snd_kcontrol_new sdt_mixer_controls[] = {
901 SOC_SINGLE_EXT("Capture", MIX_SDT_INPUT_UP_MIXER, MIX_SDT_CAPTURE, 1, 0,
902 abe_get_mixer, sdt_put_mixer),
903 SOC_SINGLE_EXT("Playback", MIX_SDT_INPUT_DL1_MIXER, MIX_SDT_PLAYBACK, 1, 0,
904 abe_get_mixer, sdt_put_mixer),
905};
906
907/* Virtual PDM_DL Switch */
908static const struct snd_kcontrol_new pdm_dl1_switch_controls =
909 SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_PDM_DL, 1, 0,
910 abe_get_mixer, abe_put_switch);
911
912/* Virtual BT_VX_DL Switch */
913static const struct snd_kcontrol_new bt_vx_dl_switch_controls =
914 SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_BT_VX_DL, 1, 0,
915 abe_get_mixer, abe_put_switch);
916
917/* Virtual MM_EXT_DL Switch */
918static const struct snd_kcontrol_new mm_ext_dl_switch_controls =
919 SOC_SINGLE_EXT("Switch", ABE_VIRTUAL_SWITCH, MIX_SWITCH_MM_EXT_DL, 1, 0,
920 abe_get_mixer, abe_put_switch);
921
922static const struct snd_kcontrol_new abe_controls[] = {
923 /* DL1 mixer gains */
924 SOC_SINGLE_EXT_TLV("DL1 Media Playback Volume",
925 MIX_DL1_INPUT_MM_DL, 0, 149, 0,
926 volume_get_dl1_mixer, volume_put_dl1_mixer, mm_dl1_tlv),
927 SOC_SINGLE_EXT_TLV("DL1 Tones Playback Volume",
928 MIX_DL1_INPUT_TONES, 0, 149, 0,
929 volume_get_dl1_mixer, volume_put_dl1_mixer, tones_dl1_tlv),
930 SOC_SINGLE_EXT_TLV("DL1 Voice Playback Volume",
931 MIX_DL1_INPUT_VX_DL, 0, 149, 0,
932 volume_get_dl1_mixer, volume_put_dl1_mixer, voice_dl1_tlv),
933 SOC_SINGLE_EXT_TLV("DL1 Capture Playback Volume",
934 MIX_DL1_INPUT_MM_UL2, 0, 149, 0,
935 volume_get_dl1_mixer, volume_put_dl1_mixer, capture_dl1_tlv),
936
937 /* DL2 mixer gains */
938 SOC_SINGLE_EXT_TLV("DL2 Media Playback Volume",
939 MIX_DL2_INPUT_MM_DL, 0, 149, 0,
940 volume_get_dl2_mixer, volume_put_dl2_mixer, mm_dl2_tlv),
941 SOC_SINGLE_EXT_TLV("DL2 Tones Playback Volume",
942 MIX_DL2_INPUT_TONES, 0, 149, 0,
943 volume_get_dl2_mixer, volume_put_dl2_mixer, tones_dl2_tlv),
944 SOC_SINGLE_EXT_TLV("DL2 Voice Playback Volume",
945 MIX_DL2_INPUT_VX_DL, 0, 149, 0,
946 volume_get_dl2_mixer, volume_put_dl2_mixer, voice_dl2_tlv),
947 SOC_SINGLE_EXT_TLV("DL2 Capture Playback Volume",
948 MIX_DL2_INPUT_MM_UL2, 0, 149, 0,
949 volume_get_dl2_mixer, volume_put_dl2_mixer, capture_dl2_tlv),
950
951 /* VXREC mixer gains */
952 SOC_SINGLE_EXT_TLV("VXREC Media Volume",
953 MIX_VXREC_INPUT_MM_DL, 0, 149, 0,
954 volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_mm_dl_tlv),
955 SOC_SINGLE_EXT_TLV("VXREC Tones Volume",
956 MIX_VXREC_INPUT_TONES, 0, 149, 0,
957 volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_tones_tlv),
958 SOC_SINGLE_EXT_TLV("VXREC Voice DL Volume",
959 MIX_VXREC_INPUT_VX_UL, 0, 149, 0,
960 volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_vx_dl_tlv),
961 SOC_SINGLE_EXT_TLV("VXREC Voice UL Volume",
962 MIX_VXREC_INPUT_VX_DL, 0, 149, 0,
963 volume_get_vxrec_mixer, volume_put_vxrec_mixer, vxrec_vx_ul_tlv),
964
965 /* AUDUL mixer gains */
966 SOC_SINGLE_EXT_TLV("AUDUL Media Volume",
967 MIX_AUDUL_INPUT_MM_DL, 0, 149, 0,
968 volume_get_audul_mixer, volume_put_audul_mixer, audul_mm_tlv),
969 SOC_SINGLE_EXT_TLV("AUDUL Tones Volume",
970 MIX_AUDUL_INPUT_TONES, 0, 149, 0,
971 volume_get_audul_mixer, volume_put_audul_mixer, audul_tones_tlv),
972 SOC_SINGLE_EXT_TLV("AUDUL Voice UL Volume",
973 MIX_AUDUL_INPUT_UPLINK, 0, 149, 0,
974 volume_get_audul_mixer, volume_put_audul_mixer, audul_vx_ul_tlv),
975 SOC_SINGLE_EXT_TLV("AUDUL Voice DL Volume",
976 MIX_AUDUL_INPUT_VX_DL, 0, 149, 0,
977 volume_get_audul_mixer, volume_put_audul_mixer, audul_vx_dl_tlv),
978
979 /* SDT mixer gains */
980 SOC_SINGLE_EXT_TLV("SDT UL Volume",
981 MIX_SDT_INPUT_UP_MIXER, 0, 149, 0,
982 volume_get_sdt_mixer, volume_put_sdt_mixer, sdt_ul_tlv),
983 SOC_SINGLE_EXT_TLV("SDT DL Volume",
984 MIX_SDT_INPUT_DL1_MIXER, 0, 149, 0,
985 volume_get_sdt_mixer, volume_put_sdt_mixer, sdt_dl_tlv),
986
987 /* DMIC gains */
988 SOC_DOUBLE_EXT_TLV("DMIC1 UL Volume",
989 GAINS_DMIC1, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
990 volume_get_gain, volume_put_gain, dmic_tlv),
991
992 SOC_DOUBLE_EXT_TLV("DMIC2 UL Volume",
993 GAINS_DMIC2, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
994 volume_get_gain, volume_put_gain, dmic_tlv),
995
996 SOC_DOUBLE_EXT_TLV("DMIC3 UL Volume",
997 GAINS_DMIC3, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
998 volume_get_gain, volume_put_gain, dmic_tlv),
999
1000 SOC_DOUBLE_EXT_TLV("AMIC UL Volume",
1001 GAINS_AMIC, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
1002 volume_get_gain, volume_put_gain, amic_tlv),
1003
1004 SOC_DOUBLE_EXT_TLV("BT UL Volume",
1005 GAINS_BTUL, GAIN_LEFT_OFFSET, GAIN_RIGHT_OFFSET, 149, 0,
1006 volume_get_gain, volume_put_gain, btul_tlv),
1007};
1008
1009static const struct snd_soc_dapm_widget abe_dapm_widgets[] = {
1010
1011 /* Frontend AIFs */
1012 SND_SOC_DAPM_AIF_IN("TONES_DL", "Tones Playback", 0,
1013 W_AIF_TONES_DL, ABE_OPP_25, 0),
1014 SND_SOC_DAPM_AIF_IN("VX_DL", "Voice Playback", 0,
1015 W_AIF_VX_DL, ABE_OPP_50, 0),
1016 SND_SOC_DAPM_AIF_OUT("VX_UL", "Voice Capture", 0,
1017 W_AIF_VX_UL, ABE_OPP_50, 0),
1018 /* the MM_UL mapping is intentional */
1019 SND_SOC_DAPM_AIF_OUT("MM_UL1", "MultiMedia1 Capture", 0,
1020 W_AIF_MM_UL1, ABE_OPP_100, 0),
1021 SND_SOC_DAPM_AIF_OUT("MM_UL2", "MultiMedia2 Capture", 0,
1022 W_AIF_MM_UL2, ABE_OPP_50, 0),
1023 SND_SOC_DAPM_AIF_IN("MM_DL", " MultiMedia1 Playback", 0,
1024 W_AIF_MM_DL, ABE_OPP_25, 0),
1025 SND_SOC_DAPM_AIF_IN("MM_DL_LP", " MultiMedia1 LP Playback", 0,
1026 W_AIF_MM_DL_LP, ABE_OPP_25, 0),
1027 SND_SOC_DAPM_AIF_IN("VIB_DL", "Vibra Playback", 0,
1028 W_AIF_VIB_DL, ABE_OPP_100, 0),
1029 SND_SOC_DAPM_AIF_IN("MODEM_DL", "MODEM Playback", 0,
1030 W_AIF_MODEM_DL, ABE_OPP_50, 0),
1031 SND_SOC_DAPM_AIF_OUT("MODEM_UL", "MODEM Capture", 0,
1032 W_AIF_MODEM_UL, ABE_OPP_50, 0),
1033
1034 /* Backend DAIs */
1035 SND_SOC_DAPM_AIF_IN("PDM_UL1", "Analog Capture", 0,
1036 W_AIF_PDM_UL1, ABE_OPP_50, 0),
1037 SND_SOC_DAPM_AIF_OUT("PDM_DL1", "HS Playback", 0,
1038 W_AIF_PDM_DL1, ABE_OPP_25, 0),
1039 SND_SOC_DAPM_AIF_OUT("PDM_DL2", "HF Playback", 0,
1040 W_AIF_PDM_DL2, ABE_OPP_100, 0),
1041 SND_SOC_DAPM_AIF_OUT("PDM_VIB", "Vibra Playback", 0,
1042 W_AIF_PDM_VIB, ABE_OPP_100, 0),
1043 SND_SOC_DAPM_AIF_IN("BT_VX_UL", "BT Capture", 0,
1044 W_AIF_BT_VX_UL, ABE_OPP_50, 0),
1045 SND_SOC_DAPM_AIF_OUT("BT_VX_DL", "BT Playback", 0,
1046 W_AIF_BT_VX_DL, ABE_OPP_50, 0),
1047 SND_SOC_DAPM_AIF_IN("MM_EXT_UL", "FM Capture", 0,
1048 W_AIF_MM_EXT_UL, ABE_OPP_50, 0),
1049 SND_SOC_DAPM_AIF_OUT("MM_EXT_DL", "FM Playback", 0,
1050 W_AIF_MM_EXT_DL, ABE_OPP_25, 0),
1051 SND_SOC_DAPM_AIF_IN("DMIC0", "DMIC0 Capture", 0,
1052 W_AIF_DMIC0, ABE_OPP_50, 0),
1053 SND_SOC_DAPM_AIF_IN("DMIC1", "DMIC1 Capture", 0,
1054 W_AIF_DMIC1, ABE_OPP_50, 0),
1055 SND_SOC_DAPM_AIF_IN("DMIC2", "DMIC2 Capture", 0,
1056 W_AIF_DMIC2, ABE_OPP_50, 0),
1057
1058 /* ROUTE_UL Capture Muxes */
1059 SND_SOC_DAPM_MUX("MUX_UL00",
1060 W_MUX_UL00, ABE_OPP_50, 0, &mm_ul00_control),
1061 SND_SOC_DAPM_MUX("MUX_UL01",
1062 W_MUX_UL01, ABE_OPP_50, 0, &mm_ul01_control),
1063 SND_SOC_DAPM_MUX("MUX_UL02",
1064 W_MUX_UL02, ABE_OPP_50, 0, &mm_ul02_control),
1065 SND_SOC_DAPM_MUX("MUX_UL03",
1066 W_MUX_UL03, ABE_OPP_50, 0, &mm_ul03_control),
1067 SND_SOC_DAPM_MUX("MUX_UL04",
1068 W_MUX_UL04, ABE_OPP_50, 0, &mm_ul04_control),
1069 SND_SOC_DAPM_MUX("MUX_UL05",
1070 W_MUX_UL05, ABE_OPP_50, 0, &mm_ul05_control),
1071 SND_SOC_DAPM_MUX("MUX_UL06",
1072 W_MUX_UL06, ABE_OPP_50, 0, &mm_ul06_control),
1073 SND_SOC_DAPM_MUX("MUX_UL07",
1074 W_MUX_UL07, ABE_OPP_50, 0, &mm_ul07_control),
1075 SND_SOC_DAPM_MUX("MUX_UL10",
1076 W_MUX_UL10, ABE_OPP_50, 0, &mm_ul10_control),
1077 SND_SOC_DAPM_MUX("MUX_UL11",
1078 W_MUX_UL11, ABE_OPP_50, 0, &mm_ul11_control),
1079 SND_SOC_DAPM_MUX("MUX_VX0",
1080 W_MUX_VX00, ABE_OPP_50, 0, &mm_vx0_control),
1081 SND_SOC_DAPM_MUX("MUX_VX1",
1082 W_MUX_VX01, ABE_OPP_50, 0, &mm_vx1_control),
1083
1084 /* DL1 & DL2 Playback Mixers */
1085 SND_SOC_DAPM_MIXER("DL1 Mixer",
1086 W_MIXER_DL1, ABE_OPP_25, 0, dl1_mixer_controls,
1087 ARRAY_SIZE(dl1_mixer_controls)),
1088 SND_SOC_DAPM_MIXER("DL2 Mixer",
1089 W_MIXER_DL2, ABE_OPP_100, 0, dl2_mixer_controls,
1090 ARRAY_SIZE(dl2_mixer_controls)),
1091
1092 /* DL1 Mixer Input volumes ?????*/
1093 SND_SOC_DAPM_PGA("DL1 Media Volume",
1094 W_VOLUME_DL1, 0, 0, NULL, 0),
1095
1096 /* AUDIO_UL_MIXER */
1097 SND_SOC_DAPM_MIXER("Voice Capture Mixer",
1098 W_MIXER_AUDIO_UL, ABE_OPP_50, 0, audio_ul_mixer_controls,
1099 ARRAY_SIZE(audio_ul_mixer_controls)),
1100
1101 /* VX_REC_MIXER */
1102 SND_SOC_DAPM_MIXER("Capture Mixer",
1103 W_MIXER_VX_REC, ABE_OPP_50, 0, vx_rec_mixer_controls,
1104 ARRAY_SIZE(vx_rec_mixer_controls)),
1105
1106 /* SDT_MIXER - TODO: shoult this not be OPP25 ??? */
1107 SND_SOC_DAPM_MIXER("Sidetone Mixer",
1108 W_MIXER_SDT, ABE_OPP_25, 0, sdt_mixer_controls,
1109 ARRAY_SIZE(sdt_mixer_controls)),
1110
1111 /*
1112 * The Following three are virtual switches to select the output port
1113 * after DL1 Gain.
1114 */
1115
1116 /* Virtual PDM_DL1 Switch */
1117 SND_SOC_DAPM_MIXER("DL1 PDM",
1118 W_VSWITCH_DL1_PDM, ABE_OPP_25, 0, &pdm_dl1_switch_controls, 1),
1119
1120 /* Virtual BT_VX_DL Switch */
1121 SND_SOC_DAPM_MIXER("DL1 BT_VX",
1122 W_VSWITCH_DL1_BT_VX, ABE_OPP_50, 0, &bt_vx_dl_switch_controls, 1),
1123
1124 /* Virtual MM_EXT_DL Switch TODO: confrm OPP level here */
1125 SND_SOC_DAPM_MIXER("DL1 MM_EXT",
1126 W_VSWITCH_DL1_MM_EXT, ABE_OPP_50, 0, &mm_ext_dl_switch_controls, 1),
1127
1128 /* Virtuals to join our capture sources */
1129 SND_SOC_DAPM_MIXER("Sidetone Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1130 SND_SOC_DAPM_MIXER("Voice Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1131 SND_SOC_DAPM_MIXER("DL1 Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1132 SND_SOC_DAPM_MIXER("DL2 Capture VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1133
1134 /* Join our MM_DL and MM_DL_LP playback */
1135 SND_SOC_DAPM_MIXER("MM_DL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1136
1137 /* Virtual MODEM and VX_UL mixer */
1138 SND_SOC_DAPM_MIXER("VX UL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1139 SND_SOC_DAPM_MIXER("VX DL VMixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1140
1141 /* Virtual Pins to force backends ON atm */
1142 SND_SOC_DAPM_OUTPUT("BE_OUT"),
1143 SND_SOC_DAPM_INPUT("BE_IN"),
1144};
1145
1146static const struct snd_soc_dapm_route intercon[] = {
1147
1148 /* MUX_UL00 - ROUTE_UL - Chan 0 */
1149 {"MUX_UL00", "DMic0L", "DMIC0"},
1150 {"MUX_UL00", "DMic0R", "DMIC0"},
1151 {"MUX_UL00", "DMic1L", "DMIC1"},
1152 {"MUX_UL00", "DMic1R", "DMIC1"},
1153 {"MUX_UL00", "DMic2L", "DMIC2"},
1154 {"MUX_UL00", "DMic2R", "DMIC2"},
1155 {"MUX_UL00", "BT Left", "BT_VX_UL"},
1156 {"MUX_UL00", "BT Right", "BT_VX_UL"},
1157 {"MUX_UL00", "MMExt Left", "MM_EXT_UL"},
1158 {"MUX_UL00", "MMExt Right", "MM_EXT_UL"},
1159 {"MUX_UL00", "AMic0", "PDM_UL1"},
1160 {"MUX_UL00", "AMic1", "PDM_UL1"},
1161 {"MUX_UL00", "VX Left", "Capture Mixer"},
1162 {"MUX_UL00", "VX Right", "Capture Mixer"},
1163 {"MM_UL1", NULL, "MUX_UL00"},
1164
1165 /* MUX_UL01 - ROUTE_UL - Chan 1 */
1166 {"MUX_UL01", "DMic0L", "DMIC0"},
1167 {"MUX_UL01", "DMic0R", "DMIC0"},
1168 {"MUX_UL01", "DMic1L", "DMIC1"},
1169 {"MUX_UL01", "DMic1R", "DMIC1"},
1170 {"MUX_UL01", "DMic2L", "DMIC2"},
1171 {"MUX_UL01", "DMic2R", "DMIC2"},
1172 {"MUX_UL01", "BT Left", "BT_VX_UL"},
1173 {"MUX_UL01", "BT Right", "BT_VX_UL"},
1174 {"MUX_UL01", "MMExt Left", "MM_EXT_UL"},
1175 {"MUX_UL01", "MMExt Right", "MM_EXT_UL"},
1176 {"MUX_UL01", "AMic0", "PDM_UL1"},
1177 {"MUX_UL01", "AMic1", "PDM_UL1"},
1178 {"MUX_UL01", "VX Left", "Capture Mixer"},
1179 {"MUX_UL01", "VX Right", "Capture Mixer"},
1180 {"MM_UL1", NULL, "MUX_UL01"},
1181
1182 /* MUX_UL02 - ROUTE_UL - Chan 2 */
1183 {"MUX_UL02", "DMic0L", "DMIC0"},
1184 {"MUX_UL02", "DMic0R", "DMIC0"},
1185 {"MUX_UL02", "DMic1L", "DMIC1"},
1186 {"MUX_UL02", "DMic1R", "DMIC1"},
1187 {"MUX_UL02", "DMic2L", "DMIC2"},
1188 {"MUX_UL02", "DMic2R", "DMIC2"},
1189 {"MUX_UL02", "BT Left", "BT_VX_UL"},
1190 {"MUX_UL02", "BT Right", "BT_VX_UL"},
1191 {"MUX_UL02", "MMExt Left", "MM_EXT_UL"},
1192 {"MUX_UL02", "MMExt Right", "MM_EXT_UL"},
1193 {"MUX_UL02", "AMic0", "PDM_UL1"},
1194 {"MUX_UL02", "AMic1", "PDM_UL1"},
1195 {"MUX_UL02", "VX Left", "Capture Mixer"},
1196 {"MUX_UL02", "VX Right", "Capture Mixer"},
1197 {"MM_UL1", NULL, "MUX_UL02"},
1198
1199 /* MUX_UL03 - ROUTE_UL - Chan 3 */
1200 {"MUX_UL03", "DMic0L", "DMIC0"},
1201 {"MUX_UL03", "DMic0R", "DMIC0"},
1202 {"MUX_UL03", "DMic1L", "DMIC1"},
1203 {"MUX_UL03", "DMic1R", "DMIC1"},
1204 {"MUX_UL03", "DMic2L", "DMIC2"},
1205 {"MUX_UL03", "DMic2R", "DMIC2"},
1206 {"MUX_UL03", "BT Left", "BT_VX_UL"},
1207 {"MUX_UL03", "BT Right", "BT_VX_UL"},
1208 {"MUX_UL03", "MMExt Left", "MM_EXT_UL"},
1209 {"MUX_UL03", "MMExt Right", "MM_EXT_UL"},
1210 {"MUX_UL03", "AMic0", "PDM_UL1"},
1211 {"MUX_UL03", "AMic1", "PDM_UL1"},
1212 {"MUX_UL03", "VX Left", "Capture Mixer"},
1213 {"MUX_UL03", "VX Right", "Capture Mixer"},
1214 {"MM_UL1", NULL, "MUX_UL03"},
1215
1216 /* MUX_UL04 - ROUTE_UL - Chan 4 */
1217 {"MUX_UL04", "DMic0L", "DMIC0"},
1218 {"MUX_UL04", "DMic0R", "DMIC0"},
1219 {"MUX_UL04", "DMic1L", "DMIC1"},
1220 {"MUX_UL04", "DMic1R", "DMIC1"},
1221 {"MUX_UL04", "DMic2L", "DMIC2"},
1222 {"MUX_UL04", "DMic2R", "DMIC2"},
1223 {"MUX_UL04", "BT Left", "BT_VX_UL"},
1224 {"MUX_UL04", "BT Right", "BT_VX_UL"},
1225 {"MUX_UL04", "MMExt Left", "MM_EXT_UL"},
1226 {"MUX_UL04", "MMExt Right", "MM_EXT_UL"},
1227 {"MUX_UL04", "AMic0", "PDM_UL1"},
1228 {"MUX_UL04", "AMic1", "PDM_UL1"},
1229 {"MUX_UL04", "VX Left", "Capture Mixer"},
1230 {"MUX_UL04", "VX Right", "Capture Mixer"},
1231 {"MM_UL1", NULL, "MUX_UL04"},
1232
1233 /* MUX_UL05 - ROUTE_UL - Chan 5 */
1234 {"MUX_UL05", "DMic0L", "DMIC0"},
1235 {"MUX_UL05", "DMic0R", "DMIC0"},
1236 {"MUX_UL05", "DMic1L", "DMIC1"},
1237 {"MUX_UL05", "DMic1R", "DMIC1"},
1238 {"MUX_UL05", "DMic2L", "DMIC2"},
1239 {"MUX_UL05", "DMic2R", "DMIC2"},
1240 {"MUX_UL05", "BT Left", "BT_VX_UL"},
1241 {"MUX_UL05", "BT Right", "BT_VX_UL"},
1242 {"MUX_UL05", "MMExt Left", "MM_EXT_UL"},
1243 {"MUX_UL05", "MMExt Right", "MM_EXT_UL"},
1244 {"MUX_UL05", "AMic0", "PDM_UL1"},
1245 {"MUX_UL05", "AMic1", "PDM_UL1"},
1246 {"MUX_UL05", "VX Left", "Capture Mixer"},
1247 {"MUX_UL05", "VX Right", "Capture Mixer"},
1248 {"MM_UL1", NULL, "MUX_UL05"},
1249
1250 /* MUX_UL06 - ROUTE_UL - Chan 6 */
1251 {"MUX_UL06", "DMic0L", "DMIC0"},
1252 {"MUX_UL06", "DMic0R", "DMIC0"},
1253 {"MUX_UL06", "DMic1L", "DMIC1"},
1254 {"MUX_UL06", "DMic1R", "DMIC1"},
1255 {"MUX_UL06", "DMic2L", "DMIC2"},
1256 {"MUX_UL06", "DMic2R", "DMIC2"},
1257 {"MUX_UL06", "BT Left", "BT_VX_UL"},
1258 {"MUX_UL06", "BT Right", "BT_VX_UL"},
1259 {"MUX_UL06", "MMExt Left", "MM_EXT_UL"},
1260 {"MUX_UL06", "MMExt Right", "MM_EXT_UL"},
1261 {"MUX_UL06", "AMic0", "PDM_UL1"},
1262 {"MUX_UL06", "AMic1", "PDM_UL1"},
1263 {"MUX_UL06", "VX Left", "Capture Mixer"},
1264 {"MUX_UL06", "VX Right", "Capture Mixer"},
1265 {"MM_UL1", NULL, "MUX_UL06"},
1266
1267 /* MUX_UL07 - ROUTE_UL - Chan 7 */
1268 {"MUX_UL07", "DMic0L", "DMIC0"},
1269 {"MUX_UL07", "DMic0R", "DMIC0"},
1270 {"MUX_UL07", "DMic1L", "DMIC1"},
1271 {"MUX_UL07", "DMic1R", "DMIC1"},
1272 {"MUX_UL07", "DMic2L", "DMIC2"},
1273 {"MUX_UL07", "DMic2R", "DMIC2"},
1274 {"MUX_UL07", "BT Left", "BT_VX_UL"},
1275 {"MUX_UL07", "BT Right", "BT_VX_UL"},
1276 {"MUX_UL07", "MMExt Left", "MM_EXT_UL"},
1277 {"MUX_UL07", "MMExt Right", "MM_EXT_UL"},
1278 {"MUX_UL07", "AMic0", "PDM_UL1"},
1279 {"MUX_UL07", "AMic1", "PDM_UL1"},
1280 {"MUX_UL07", "VX Left", "Capture Mixer"},
1281 {"MUX_UL07", "VX Right", "Capture Mixer"},
1282 {"MM_UL1", NULL, "MUX_UL07"},
1283
1284 /* MUX_UL10 - ROUTE_UL - Chan 10 */
1285 {"MUX_UL10", "DMic0L", "DMIC0"},
1286 {"MUX_UL10", "DMic0R", "DMIC0"},
1287 {"MUX_UL10", "DMic1L", "DMIC1"},
1288 {"MUX_UL10", "DMic1R", "DMIC1"},
1289 {"MUX_UL10", "DMic2L", "DMIC2"},
1290 {"MUX_UL10", "DMic2R", "DMIC2"},
1291 {"MUX_UL10", "BT Left", "BT_VX_UL"},
1292 {"MUX_UL10", "BT Right", "BT_VX_UL"},
1293 {"MUX_UL10", "MMExt Left", "MM_EXT_UL"},
1294 {"MUX_UL10", "MMExt Right", "MM_EXT_UL"},
1295 {"MUX_UL10", "AMic0", "PDM_UL1"},
1296 {"MUX_UL10", "AMic1", "PDM_UL1"},
1297 {"MUX_UL10", "VX Left", "Capture Mixer"},
1298 {"MUX_UL10", "VX Right", "Capture Mixer"},
1299 {"MM_UL2", NULL, "MUX_UL10"},
1300
1301 /* MUX_UL11 - ROUTE_UL - Chan 11 */
1302 {"MUX_UL11", "DMic0L", "DMIC0"},
1303 {"MUX_UL11", "DMic0R", "DMIC0"},
1304 {"MUX_UL11", "DMic1L", "DMIC1"},
1305 {"MUX_UL11", "DMic1R", "DMIC1"},
1306 {"MUX_UL11", "DMic2L", "DMIC2"},
1307 {"MUX_UL11", "DMic2R", "DMIC2"},
1308 {"MUX_UL11", "BT Left", "BT_VX_UL"},
1309 {"MUX_UL11", "BT Right", "BT_VX_UL"},
1310 {"MUX_UL11", "MMExt Left", "MM_EXT_UL"},
1311 {"MUX_UL11", "MMExt Right", "MM_EXT_UL"},
1312 {"MUX_UL11", "AMic0", "PDM_UL1"},
1313 {"MUX_UL11", "AMic1", "PDM_UL1"},
1314 {"MUX_UL11", "VX Left", "Capture Mixer"},
1315 {"MUX_UL11", "VX Right", "Capture Mixer"},
1316 {"MM_UL2", NULL, "MUX_UL11"},
1317
1318 /* MUX_VX0 - ROUTE_UL - Chan 20 */
1319 {"MUX_VX0", "DMic0L", "DMIC0"},
1320 {"MUX_VX0", "DMic0R", "DMIC0"},
1321 {"MUX_VX0", "DMic1L", "DMIC1"},
1322 {"MUX_VX0", "DMic1R", "DMIC1"},
1323 {"MUX_VX0", "DMic2L", "DMIC2"},
1324 {"MUX_VX0", "DMic2R", "DMIC2"},
1325 {"MUX_VX0", "BT Left", "BT_VX_UL"},
1326 {"MUX_VX0", "BT Right", "BT_VX_UL"},
1327 {"MUX_VX0", "MMExt Left", "MM_EXT_UL"},
1328 {"MUX_VX0", "MMExt Right", "MM_EXT_UL"},
1329 {"MUX_VX0", "AMic0", "PDM_UL1"},
1330 {"MUX_VX0", "AMic1", "PDM_UL1"},
1331 {"MUX_VX0", "VX Left", "Capture Mixer"},
1332 {"MUX_VX0", "VX Right", "Capture Mixer"},
1333
1334 /* MUX_VX1 - ROUTE_UL - Chan 20 */
1335 {"MUX_VX1", "DMic0L", "DMIC0"},
1336 {"MUX_VX1", "DMic0R", "DMIC0"},
1337 {"MUX_VX1", "DMic1L", "DMIC1"},
1338 {"MUX_VX1", "DMic1R", "DMIC1"},
1339 {"MUX_VX1", "DMic2L", "DMIC2"},
1340 {"MUX_VX1", "DMic2R", "DMIC2"},
1341 {"MUX_VX1", "BT Left", "BT_VX_UL"},
1342 {"MUX_VX1", "BT Right", "BT_VX_UL"},
1343 {"MUX_VX1", "MMExt Left", "MM_EXT_UL"},
1344 {"MUX_VX1", "MMExt Right", "MM_EXT_UL"},
1345 {"MUX_VX1", "AMic0", "PDM_UL1"},
1346 {"MUX_VX1", "AMic1", "PDM_UL1"},
1347 {"MUX_VX1", "VX Left", "Capture Mixer"},
1348 {"MUX_VX1", "VX Right", "Capture Mixer"},
1349
1350 /* Headset (DL1) playback path */
1351 {"DL1 Mixer", "Tones", "TONES_DL"},
1352 {"DL1 Mixer", "Voice", "VX DL VMixer"},
1353 {"DL1 Mixer", "Capture", "DL1 Capture VMixer"},
1354 {"DL1 Capture VMixer", NULL, "MUX_UL10"},
1355 {"DL1 Capture VMixer", NULL, "MUX_UL11"},
1356 {"DL1 Mixer", "Multimedia", "MM_DL VMixer"},
1357 {"MM_DL VMixer", NULL, "MM_DL"},
1358 {"MM_DL VMixer", NULL, "MM_DL_LP"},
1359
1360 /* Sidetone Mixer */
1361 {"Sidetone Mixer", "Playback", "DL1 Mixer"},
1362 {"Sidetone Mixer", "Capture", "Sidetone Capture VMixer"},
1363 {"Sidetone Capture VMixer", NULL, "MUX_VX0"},
1364 {"Sidetone Capture VMixer", NULL, "MUX_VX1"},
1365
1366 /* Playback Output selection after DL1 Gain */
1367 {"DL1 BT_VX", "Switch", "Sidetone Mixer"},
1368 {"DL1 MM_EXT", "Switch", "Sidetone Mixer"},
1369 {"DL1 PDM", "Switch", "Sidetone Mixer"},
1370 {"PDM_DL1", NULL, "DL1 PDM"},
1371 {"BT_VX_DL", NULL, "DL1 BT_VX"},
1372 {"MM_EXT_DL", NULL, "DL1 MM_EXT"},
1373
1374 /* Handsfree (DL2) playback path */
1375 {"DL2 Mixer", "Tones", "TONES_DL"},
1376 {"DL2 Mixer", "Voice", "VX DL VMixer"},
1377 {"DL2 Mixer", "Capture", "DL2 Capture VMixer"},
1378 {"DL2 Capture VMixer", NULL, "MUX_UL10"},
1379 {"DL2 Capture VMixer", NULL, "MUX_UL11"},
1380 {"DL2 Mixer", "Multimedia", "MM_DL VMixer"},
1381 {"MM_DL VMixer", NULL, "MM_DL"},
1382 {"MM_DL VMixer", NULL, "MM_DL_LP"},
1383 {"PDM_DL2", NULL, "DL2 Mixer"},
1384
1385 /* VxREC Mixer */
1386 {"Capture Mixer", "Tones", "TONES_DL"},
1387 {"Capture Mixer", "Voice Playback", "VX DL VMixer"},
1388 {"Capture Mixer", "Voice Capture", "VX UL VMixer"},
1389 {"Capture Mixer", "Media Playback", "MM_DL VMixer"},
1390 {"MM_DL VMixer", NULL, "MM_DL"},
1391 {"MM_DL VMixer", NULL, "MM_DL_LP"},
1392
1393 /* Audio UL mixer */
1394 {"Voice Capture Mixer", "Tones Playback", "TONES_DL"},
1395 {"Voice Capture Mixer", "Media Playback", "MM_DL VMixer"},
1396 {"MM_DL VMixer", NULL, "MM_DL"},
1397 {"MM_DL VMixer", NULL, "MM_DL_LP"},
1398 {"Voice Capture Mixer", "Capture", "Voice Capture VMixer"},
1399 {"Voice Capture VMixer", NULL, "MUX_VX0"},
1400 {"Voice Capture VMixer", NULL, "MUX_VX1"},
1401
1402 /* BT */
1403 {"VX UL VMixer", NULL, "Voice Capture Mixer"},
1404
1405 /* Vibra */
1406 {"PDM_VIB", NULL, "VIB_DL"},
1407
1408 /* VX and MODEM */
1409 {"VX_UL", NULL, "VX UL VMixer"},
1410 {"MODEM_UL", NULL, "VX UL VMixer"},
1411 {"VX DL VMixer", NULL, "VX_DL"},
1412 {"VX DL VMixer", NULL, "MODEM_DL"},
1413
1414 /* Backend Enablement - TODO: maybe re-work*/
1415 {"BE_OUT", NULL, "PDM_DL1"},
1416 {"BE_OUT", NULL, "PDM_DL2"},
1417 {"BE_OUT", NULL, "PDM_VIB"},
1418 {"BE_OUT", NULL, "MM_EXT_DL"},
1419 {"BE_OUT", NULL, "BT_VX_DL"},
1420 {"PDM_UL1", NULL, "BE_IN"},
1421 {"BT_VX_UL", NULL, "BE_IN"},
1422 {"MM_EXT_UL", NULL, "BE_IN"},
1423 {"DMIC0", NULL, "BE_IN"},
1424 {"DMIC1", NULL, "BE_IN"},
1425 {"DMIC2", NULL, "BE_IN"},
1426};
1427
1428#ifdef CONFIG_DEBUG_FS
1429
1430static int abe_dbg_get_dma_pos(struct abe_data *abe)
1431{
1432 return omap_get_dma_dst_pos(abe->dma_ch) - abe->dbg_buffer_addr;
1433}
1434
1435static void abe_dbg_dma_irq(int ch, u16 stat, void *data)
1436{
1437}
1438
1439static int abe_dbg_start_dma(struct abe_data *abe, int circular)
1440{
1441 struct omap_dma_channel_params dma_params;
1442 int err;
1443
1444 /* TODO: start the DMA in either :-
1445 *
1446 * 1) circular buffer mode where the DMA will restart when it get to
1447 * the end of the buffer.
1448 * 2) default mode, where DMA stops at the end of the buffer.
1449 */
1450
1451 abe->dma_req = OMAP44XX_DMA_ABE_REQ_7;
1452 err = omap_request_dma(abe->dma_req, "ABE debug",
1453 abe_dbg_dma_irq, abe, &abe->dma_ch);
1454 if (abe->dbg_circular) {
1455 /*
1456 * Link channel with itself so DMA doesn't need any
1457 * reprogramming while looping the buffer
1458 */
1459 omap_dma_link_lch(abe->dma_ch, abe->dma_ch);
1460 }
1461
1462 memset(&dma_params, 0, sizeof(dma_params));
1463 dma_params.data_type = OMAP_DMA_DATA_TYPE_S32;
1464 dma_params.trigger = abe->dma_req;
1465 dma_params.sync_mode = OMAP_DMA_SYNC_FRAME;
1466 dma_params.src_amode = OMAP_DMA_AMODE_DOUBLE_IDX;
1467 dma_params.dst_amode = OMAP_DMA_AMODE_POST_INC;
1468 dma_params.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
1469 dma_params.src_start = D_DEBUG_FIFO_ADDR + ABE_DMEM_BASE_ADDRESS_L3;
1470 dma_params.dst_start = abe->dbg_buffer_addr;
1471 dma_params.src_port = OMAP_DMA_PORT_MPUI;
1472 dma_params.src_ei = 1;
1473 dma_params.src_fi = 1 - abe->dbg_elem_bytes;
1474
1475 dma_params.elem_count = abe->dbg_elem_bytes >> 2; /* 128 bytes shifted into words */
1476 dma_params.frame_count = abe->dbg_buffer_bytes / abe->dbg_elem_bytes;
1477 omap_set_dma_params(abe->dma_ch, &dma_params);
1478
1479 omap_enable_dma_irq(abe->dma_ch, OMAP_DMA_FRAME_IRQ);
1480 omap_set_dma_src_burst_mode(abe->dma_ch, OMAP_DMA_DATA_BURST_16);
1481 omap_set_dma_dest_burst_mode(abe->dma_ch, OMAP_DMA_DATA_BURST_16);
1482
1483 abe->dbg_reader_offset = 0;
1484
1485 pm_runtime_get_sync(abe->dev);
1486 omap_start_dma(abe->dma_ch);
1487 return 0;
1488}
1489
1490static void abe_dbg_stop_dma(struct abe_data *abe)
1491{
1492 while (omap_get_dma_active_status(abe->dma_ch))
1493 omap_stop_dma(abe->dma_ch);
1494
1495 if (abe->dbg_circular)
1496 omap_dma_unlink_lch(abe->dma_ch, abe->dma_ch);
1497 omap_free_dma(abe->dma_ch);
1498 pm_runtime_put_sync(abe->dev);
1499}
1500
1501static int abe_open_data(struct inode *inode, struct file *file)
1502{
1503 struct abe_data *abe = inode->i_private;
1504
1505 abe->dbg_elem_bytes = 128; /* size of debug data per tick */
1506
1507 if (abe->dbg_format1)
1508 abe->dbg_elem_bytes += ABE_DBG_FLAG1_SIZE;
1509 if (abe->dbg_format2)
1510 abe->dbg_elem_bytes += ABE_DBG_FLAG2_SIZE;
1511 if (abe->dbg_format3)
1512 abe->dbg_elem_bytes += ABE_DBG_FLAG3_SIZE;
1513
1514 abe->dbg_buffer_bytes = abe->dbg_elem_bytes * 4 *
1515 abe->dbg_buffer_msecs;
1516
1517 abe->dbg_buffer = dma_alloc_writecombine(abe->dev,
1518 abe->dbg_buffer_bytes, &abe->dbg_buffer_addr, GFP_KERNEL);
1519 if (abe->dbg_buffer == NULL)
1520 return -ENOMEM;
1521
1522 file->private_data = inode->i_private;
1523 abe->dbg_complete = 0;
1524 abe_dbg_start_dma(abe, abe->dbg_circular);
1525
1526 return 0;
1527}
1528
1529static int abe_release_data(struct inode *inode, struct file *file)
1530{
1531 struct abe_data *abe = inode->i_private;
1532
1533 abe_dbg_stop_dma(abe);
1534
1535 dma_free_writecombine(abe->dev, abe->dbg_buffer_bytes,
1536 abe->dbg_buffer, abe->dbg_buffer_addr);
1537 return 0;
1538}
1539
1540static ssize_t abe_copy_to_user(struct abe_data *abe, char __user *user_buf,
1541 size_t count)
1542{
1543 /* check for reader buffer wrap */
1544 if (abe->dbg_reader_offset + count > abe->dbg_buffer_bytes) {
1545 int size = abe->dbg_buffer_bytes - abe->dbg_reader_offset;
1546
1547 /* wrap */
1548 if (copy_to_user(user_buf,
1549 abe->dbg_buffer + abe->dbg_reader_offset, size))
1550 return -EFAULT;
1551
1552 /* need to just return if non circular */
1553 if (!abe->dbg_circular) {
1554 abe->dbg_complete = 1;
1555 return count;
1556 }
1557
1558 if (copy_to_user(user_buf,
1559 abe->dbg_buffer, count - size))
1560 return -EFAULT;
1561 abe->dbg_reader_offset = count - size;
1562 return count;
1563 } else {
1564 /* no wrap */
1565 if (copy_to_user(user_buf,
1566 abe->dbg_buffer + abe->dbg_reader_offset, count))
1567 return -EFAULT;
1568 abe->dbg_reader_offset += count;
1569
1570 if (!abe->dbg_circular &&
1571 abe->dbg_reader_offset == abe->dbg_buffer_bytes)
1572 abe->dbg_complete = 1;
1573
1574 return count;
1575 }
1576}
1577
1578static ssize_t abe_read_data(struct file *file, char __user *user_buf,
1579 size_t count, loff_t *ppos)
1580{
1581 ssize_t ret = 0;
1582 struct abe_data *abe = file->private_data;
1583 DECLARE_WAITQUEUE(wait, current);
1584 int dma_offset, bytes;
1585
1586 add_wait_queue(&abe->wait, &wait);
1587 do {
1588 set_current_state(TASK_INTERRUPTIBLE);
1589 /* TODO: Check if really needed. Or adjust sleep delay
1590 * If not delay trace is not working */
1591 msleep_interruptible(1);
1592 dma_offset = abe_dbg_get_dma_pos(abe);
1593
1594 /* is DMA finished ? */
1595 if (abe->dbg_complete)
1596 break;
1597
1598 /* get maximum amount of debug bytes we can read */
1599 if (dma_offset >= abe->dbg_reader_offset) {
1600 /* dma ptr is ahead of reader */
1601 bytes = dma_offset - abe->dbg_reader_offset;
1602 } else {
1603 /* dma ptr is behind reader */
1604 bytes = dma_offset + abe->dbg_buffer_bytes -
1605 abe->dbg_reader_offset;
1606 }
1607
1608 if (count > bytes)
1609 count = bytes;
1610
1611 if (count > 0) {
1612 ret = abe_copy_to_user(abe, user_buf, count);
1613 break;
1614 }
1615
1616 if (file->f_flags & O_NONBLOCK) {
1617 ret = -EAGAIN;
1618 break;
1619 }
1620
1621 if (signal_pending(current)) {
1622 ret = -ERESTARTSYS;
1623 break;
1624 }
1625
1626 schedule();
1627
1628 } while (1);
1629
1630 __set_current_state(TASK_RUNNING);
1631 remove_wait_queue(&abe->wait, &wait);
1632
1633 return ret;
1634}
1635
1636static const struct file_operations abe_data_fops = {
1637 .open = abe_open_data,
1638 .read = abe_read_data,
1639 .release = abe_release_data,
1640};
1641
1642static void abe_init_debugfs(struct abe_data *abe)
1643{
1644 abe->debugfs_root = debugfs_create_dir("omap4-abe", NULL);
1645 if (!abe->debugfs_root) {
1646 printk(KERN_WARNING "ABE: Failed to create debugfs directory\n");
1647 return;
1648 }
1649
1650 abe->debugfs_fmt1 = debugfs_create_bool("format1", 0644,
1651 abe->debugfs_root,
1652 &abe->dbg_format1);
1653 if (!abe->debugfs_fmt1)
1654 printk(KERN_WARNING "ABE: Failed to create format1 debugfs file\n");
1655
1656 abe->debugfs_fmt2 = debugfs_create_bool("format2", 0644,
1657 abe->debugfs_root,
1658 &abe->dbg_format2);
1659 if (!abe->debugfs_fmt2)
1660 printk(KERN_WARNING "ABE: Failed to create format2 debugfs file\n");
1661
1662 abe->debugfs_fmt3 = debugfs_create_bool("format3", 0644,
1663 abe->debugfs_root,
1664 &abe->dbg_format3);
1665 if (!abe->debugfs_fmt3)
1666 printk(KERN_WARNING "ABE: Failed to create format3 debugfs file\n");
1667
1668 abe->debugfs_elem_bytes = debugfs_create_u32("element_bytes", 0604,
1669 abe->debugfs_root,
1670 &abe->dbg_elem_bytes);
1671 if (!abe->debugfs_elem_bytes)
1672 printk(KERN_WARNING "ABE: Failed to create element size debugfs file\n");
1673
1674 abe->debugfs_size = debugfs_create_u32("msecs", 0644,
1675 abe->debugfs_root,
1676 &abe->dbg_buffer_msecs);
1677 if (!abe->debugfs_size)
1678 printk(KERN_WARNING "ABE: Failed to create buffer size debugfs file\n");
1679
1680 abe->debugfs_circ = debugfs_create_bool("circular", 0644,
1681 abe->debugfs_root,
1682 &abe->dbg_circular);
1683 if (!abe->debugfs_size)
1684 printk(KERN_WARNING "ABE: Failed to create circular mode debugfs file\n");
1685
1686 abe->debugfs_data = debugfs_create_file("debug", 0644,
1687 abe->debugfs_root,
1688 abe, &abe_data_fops);
1689 if (!abe->debugfs_data)
1690 printk(KERN_WARNING "ABE: Failed to create data debugfs file\n");
1691
1692 abe->debugfs_opp_level = debugfs_create_u32("opp_level", 0604,
1693 abe->debugfs_root,
1694 &abe->opp);
1695 if (!abe->debugfs_opp_level)
1696 printk(KERN_WARNING "ABE: Failed to create OPP level debugfs file\n");
1697
1698 abe->dbg_buffer_msecs = 500;
1699 init_waitqueue_head(&abe->wait);
1700}
1701
1702static void abe_cleanup_debugfs(struct abe_data *abe)
1703{
1704 debugfs_remove_recursive(abe->debugfs_root);
1705}
1706
1707#else
1708
1709static inline void abe_init_debugfs(struct abe_data *abe)
1710{
1711}
1712
1713static inline void abe_cleanup_debugfs(struct abe_data *abe)
1714{
1715}
1716#endif
1717
1718static const struct snd_pcm_hardware omap_abe_hardware = {
1719 .info = SNDRV_PCM_INFO_MMAP |
1720 SNDRV_PCM_INFO_MMAP_VALID |
1721 SNDRV_PCM_INFO_INTERLEAVED |
1722 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1723 SNDRV_PCM_INFO_PAUSE |
1724 SNDRV_PCM_INFO_RESUME,
1725 .formats = SNDRV_PCM_FMTBIT_S16_LE |
1726 SNDRV_PCM_FMTBIT_S32_LE,
1727 .period_bytes_min = 4 * 1024,
1728 .period_bytes_max = 24 * 1024,
1729 .periods_min = 2,
1730 .periods_max = 2,
1731 .buffer_bytes_max = 24 * 1024 * 2,
1732};
1733
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001734
1735static int abe_set_opp_mode(struct abe_data *abe)
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001736{
1737 int i, opp = 0;
1738
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001739 /* now calculate OPP level based upon DAPM widget status */
1740 for (i = 0; i < ABE_NUM_WIDGETS; i++) {
1741 if (abe->widget_opp[ABE_WIDGET(i)]) {
1742 dev_dbg(abe->dev, "OPP: id %d = %d%%\n", i,
1743 abe->widget_opp[ABE_WIDGET(i)] * 25);
1744 opp |= abe->widget_opp[ABE_WIDGET(i)];
1745 }
1746 }
1747 opp = (1 << (fls(opp) - 1)) * 25;
1748
1749 if (abe->opp > opp) {
1750 /* Decrease OPP mode - no need of OPP100% */
1751 switch (opp) {
1752 case 25:
1753 abe_set_opp_processing(ABE_OPP25);
1754 udelay(250);
1755 omap_device_set_rate(abe->dev, abe->dev, 49150000);
1756 break;
1757 case 50:
1758 default:
1759 abe_set_opp_processing(ABE_OPP50);
1760 udelay(250);
1761 omap_device_set_rate(abe->dev, abe->dev, 98300000);
1762 break;
1763 }
1764 } else if (abe->opp < opp) {
1765 /* Increase OPP mode */
1766 switch (opp) {
1767 case 25:
1768 omap_device_set_rate(abe->dev, abe->dev, 49000000);
1769 abe_set_opp_processing(ABE_OPP25);
1770 break;
1771 case 50:
1772 omap_device_set_rate(abe->dev, abe->dev, 98300000);
1773 abe_set_opp_processing(ABE_OPP50);
1774 break;
1775 case 100:
1776 default:
1777 omap_device_set_rate(abe->dev, abe->dev, 196600000);
1778 abe_set_opp_processing(ABE_OPP100);
1779 break;
1780 }
1781 }
1782 abe->opp = opp;
1783 dev_dbg(abe->dev, "new OPP level is %d\n", opp);
1784
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001785 return 0;
1786}
1787
1788static int aess_set_runtime_opp_level(struct abe_data *abe)
1789{
1790 mutex_lock(&abe->opp_mutex);
1791
1792 pm_runtime_get_sync(abe->dev);
1793 abe_set_opp_mode(abe);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001794 pm_runtime_put_sync(abe->dev);
1795
1796 mutex_unlock(&abe->opp_mutex);
1797
1798 return 0;
1799}
1800
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001801static int aess_save_context(struct abe_data *abe)
1802{
1803 struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
1804
1805 /* TODO: Find a better way to save/retore gains after OFF mode */
1806
1807 abe_mute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
1808 abe_mute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
1809 abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
1810 abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
1811 abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
1812 abe_mute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
1813 abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
1814 abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
1815 abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
1816 abe_mute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
1817 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
1818 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
1819 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
1820 abe_mute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
1821 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
1822 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
1823 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
1824 abe_mute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
1825 abe_mute_gain(MIXECHO, MIX_ECHO_DL1);
1826 abe_mute_gain(MIXECHO, MIX_ECHO_DL2);
1827 abe_mute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
1828 abe_mute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
1829 abe_mute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
1830 abe_mute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
1831 abe_mute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
1832 abe_mute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
1833 abe_mute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
1834 abe_mute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
1835
1836 if (pdata->get_context_loss_count)
1837 abe->loss_count = pdata->get_context_loss_count(abe->dev);
1838
1839 return 0;
1840}
1841
1842static int aess_restore_context(struct abe_data *abe)
1843{
1844 struct omap4_abe_dsp_pdata *pdata = abe->abe_pdata;
1845 int loss_count = 0;
1846
1847 omap_device_set_rate(&abe->dev, &abe->dev, 98000000);
1848
1849 if (pdata->get_context_loss_count)
1850 loss_count = pdata->get_context_loss_count(abe->dev);
1851
1852 if (loss_count != the_abe->loss_count)
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05001853 abe_reload_fw(abe->firmware);
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001854
1855 /* TODO: Find a better way to save/retore gains after dor OFF mode */
1856 abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_UP_MIXER);
1857 abe_unmute_gain(MIXSDT, MIX_SDT_INPUT_DL1_MIXER);
1858 abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_MM_DL);
1859 abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_TONES);
1860 abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_UPLINK);
1861 abe_unmute_gain(MIXAUDUL, MIX_AUDUL_INPUT_VX_DL);
1862 abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_TONES);
1863 abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_DL);
1864 abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_MM_DL);
1865 abe_unmute_gain(MIXVXREC, MIX_VXREC_INPUT_VX_UL);
1866 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_DL);
1867 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_MM_UL2);
1868 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_VX_DL);
1869 abe_unmute_gain(MIXDL1, MIX_DL1_INPUT_TONES);
1870 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_TONES);
1871 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_VX_DL);
1872 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_DL);
1873 abe_unmute_gain(MIXDL2, MIX_DL2_INPUT_MM_UL2);
1874 abe_unmute_gain(MIXECHO, MIX_ECHO_DL1);
1875 abe_unmute_gain(MIXECHO, MIX_ECHO_DL2);
1876 abe_unmute_gain(GAINS_DMIC1, GAIN_LEFT_OFFSET);
1877 abe_unmute_gain(GAINS_DMIC1, GAIN_RIGHT_OFFSET);
1878 abe_unmute_gain(GAINS_DMIC2, GAIN_LEFT_OFFSET);
1879 abe_unmute_gain(GAINS_DMIC2, GAIN_RIGHT_OFFSET);
1880 abe_unmute_gain(GAINS_DMIC3, GAIN_LEFT_OFFSET);
1881 abe_unmute_gain(GAINS_DMIC3, GAIN_RIGHT_OFFSET);
1882 abe_unmute_gain(GAINS_AMIC, GAIN_LEFT_OFFSET);
1883 abe_unmute_gain(GAINS_AMIC, GAIN_RIGHT_OFFSET);
1884/*
1885 abe_dsp_set_equalizer(EQ1, abe->dl1_equ_profile);
1886 abe_dsp_set_equalizer(EQ2L, abe->dl20_equ_profile);
1887 abe_dsp_set_equalizer(EQ2R, abe->dl21_equ_profile);
1888 abe_dsp_set_equalizer(EQAMIC, abe->amic_equ_profile);
1889 abe_dsp_set_equalizer(EQDMIC, abe->dmic_equ_profile);
1890 abe_dsp_set_equalizer(EQSDT, abe->sdt_equ_profile);
1891*/
1892 abe_set_router_configuration(UPROUTE, 0, (u32 *)abe->router);
1893
1894 return 0;
1895}
1896
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001897static int aess_open(struct snd_pcm_substream *substream)
1898{
1899 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1900 struct snd_soc_platform *platform = rtd->platform;
1901 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
1902 struct snd_soc_dai *dai = rtd->cpu_dai;
1903 int ret = 0;
1904
1905 mutex_lock(&abe->mutex);
1906
1907 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
1908
1909 pm_runtime_get_sync(abe->dev);
1910
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001911 if (!abe->active++) {
1912 abe->opp = 0;
1913 aess_restore_context(abe);
1914 abe_set_opp_mode(abe);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001915 abe_wakeup();
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02001916 }
Liam Girdwooda8d99da2011-02-03 15:28:19 +00001917
1918 switch (dai->id) {
1919 case ABE_FRONTEND_DAI_MODEM:
1920 break;
1921 case ABE_FRONTEND_DAI_LP_MEDIA:
1922 snd_soc_set_runtime_hwparams(substream, &omap_abe_hardware);
1923 ret = snd_pcm_hw_constraint_step(substream->runtime, 0,
1924 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 1024);
1925 break;
1926 default:
1927 break;
1928 }
1929
1930 mutex_unlock(&abe->mutex);
1931 return ret;
1932}
1933
1934static int aess_hw_params(struct snd_pcm_substream *substream,
1935 struct snd_pcm_hw_params *params)
1936{
1937 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1938 struct snd_pcm_runtime *runtime = substream->runtime;
1939 struct snd_soc_platform *platform = rtd->platform;
1940 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
1941 struct snd_soc_dai *dai = rtd->cpu_dai;
1942 abe_data_format_t format;
1943 size_t period_size;
1944 u32 dst;
1945
1946 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
1947
1948 if (dai->id != ABE_FRONTEND_DAI_LP_MEDIA)
1949 return 0;
1950
1951 /*Storing substream pointer for irq*/
1952 abe->ping_pong_substream = substream;
1953
1954 format.f = params_rate(params);
1955 if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE)
1956 format.samp_format = STEREO_MSB;
1957 else
1958 format.samp_format = STEREO_16_16;
1959
1960 if (format.f == 44100)
1961 abe_write_event_generator(EVENT_44100);
1962
1963 period_size = params_period_bytes(params);
1964
1965 /*Adding ping pong buffer subroutine*/
1966 abe_plug_subroutine(&abe_irq_pingpong_player_id,
1967 (abe_subroutine2) abe_irq_pingpong_subroutine,
1968 SUB_1_PARAM, (u32 *)abe);
1969
1970 /* Connect a Ping-Pong cache-flush protocol to MM_DL port */
1971 abe_connect_irq_ping_pong_port(MM_DL_PORT, &format,
1972 abe_irq_pingpong_player_id,
1973 period_size, &dst,
1974 PING_PONG_WITH_MCU_IRQ);
1975
1976 /* Memory mapping for hw params */
1977 runtime->dma_area = abe->io_base[0] + dst;
1978 runtime->dma_addr = 0;
1979 runtime->dma_bytes = period_size * 2;
1980
1981 /* Need to set the first buffer in order to get interrupt */
1982 abe_set_ping_pong_buffer(MM_DL_PORT, period_size);
1983 abe->first_irq = 1;
1984
1985 return 0;
1986}
1987
1988static int aess_prepare(struct snd_pcm_substream *substream)
1989{
1990 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1991 struct snd_soc_platform *platform = rtd->platform;
1992 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
1993 struct snd_soc_dai *dai = rtd->cpu_dai;
1994
1995 mutex_lock(&abe->mutex);
1996 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
1997 aess_set_runtime_opp_level(abe);
1998 mutex_unlock(&abe->mutex);
1999 return 0;
2000}
2001
2002static int aess_close(struct snd_pcm_substream *substream)
2003{
2004 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2005 struct snd_soc_platform *platform = rtd->platform;
2006 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
2007 struct snd_soc_dai *dai = rtd->cpu_dai;
2008
2009 mutex_lock(&abe->mutex);
2010 aess_set_runtime_opp_level(abe);
2011
2012 dev_dbg(dai->dev, "%s: %s\n", __func__, dai->name);
2013
2014 if (!--abe->active) {
2015 abe_disable_irq();
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02002016 aess_save_context(abe);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002017 abe_dsp_shutdown();
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002018 }
2019
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02002020 pm_runtime_put_sync(abe->dev);
2021
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002022 mutex_unlock(&abe->mutex);
2023 return 0;
2024}
2025
2026static int aess_mmap(struct snd_pcm_substream *substream,
2027 struct vm_area_struct *vma)
2028{
2029 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2030 struct snd_soc_dai *dai = rtd->cpu_dai;
2031 int offset, size, err;
2032
2033 if (dai->id != ABE_FRONTEND_DAI_LP_MEDIA)
2034 return -EINVAL;
2035
2036 vma->vm_flags |= VM_IO | VM_RESERVED;
2037 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
2038 size = vma->vm_end - vma->vm_start;
2039 offset = vma->vm_pgoff << PAGE_SHIFT;
2040
2041 err = io_remap_pfn_range(vma, vma->vm_start,
2042 (ABE_DMEM_BASE_ADDRESS_MPU +
2043 ABE_DMEM_BASE_OFFSET_PING_PONG + offset) >> PAGE_SHIFT,
2044 size, vma->vm_page_prot);
2045
2046 if (err)
2047 return -EAGAIN;
2048
2049 return 0;
2050}
2051
2052static snd_pcm_uframes_t aess_pointer(struct snd_pcm_substream *substream)
2053{
2054 snd_pcm_uframes_t offset;
2055 u32 pingpong;
2056
2057 abe_read_offset_from_ping_buffer(MM_DL_PORT, &pingpong);
2058 offset = (snd_pcm_uframes_t)pingpong;
2059
2060 return offset;
2061}
2062
2063static struct snd_pcm_ops omap_aess_pcm_ops = {
2064 .open = aess_open,
2065 .hw_params = aess_hw_params,
2066 .prepare = aess_prepare,
2067 .close = aess_close,
2068 .pointer = aess_pointer,
2069 .mmap = aess_mmap,
2070};
2071
2072#if CONFIG_PM
2073static int aess_suspend(struct device *dev)
2074{
2075 struct abe_data *abe = dev_get_drvdata(dev);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002076
2077 pm_runtime_get_sync(abe->dev);
2078
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02002079 aess_save_context(abe);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002080
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002081 pm_runtime_put_sync(abe->dev);
2082
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002083 return 0;
2084}
2085
2086static int aess_resume(struct device *dev)
2087{
2088 struct abe_data *abe = dev_get_drvdata(dev);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002089
2090 pm_runtime_get_sync(abe->dev);
2091
Sebastien Guiriecb2f30fb2011-07-04 14:36:34 +02002092 aess_restore_context(abe);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002093
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002094 pm_runtime_put_sync(abe->dev);
2095
2096 return 0;
2097}
2098
2099#else
2100#define aess_suspend NULL
2101#define aess_resume NULL
2102#endif
2103
2104static const struct dev_pm_ops aess_pm_ops = {
2105 .suspend = aess_suspend,
2106 .resume = aess_resume,
2107};
2108
2109static int aess_stream_event(struct snd_soc_dapm_context *dapm)
2110{
2111 struct snd_soc_platform *platform = dapm->platform;
2112 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
2113
2114 pm_runtime_get_sync(abe->dev);
2115
2116 if (abe->active)
2117 aess_set_runtime_opp_level(abe);
2118
2119 pm_runtime_put_sync(abe->dev);
2120
2121 return 0;
2122}
2123
2124static int abe_add_widgets(struct snd_soc_platform *platform)
2125{
2126 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
2127 struct fw_header *hdr = &abe->hdr;
2128 int i, j;
2129
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002130 /* create equalizer controls */
2131 for (i = 0; i < hdr->num_equ; i++) {
2132 struct soc_enum *equalizer_enum = &abe->equalizer_enum[i];
2133 struct snd_kcontrol_new *equalizer_control =
2134 &abe->equalizer_control[i];
2135
2136 equalizer_enum->reg = i;
2137 equalizer_enum->max = abe->equ_texts[i].count;
2138 for (j = 0; j < abe->equ_texts[i].count; j++)
2139 equalizer_enum->dtexts[j] = abe->equ_texts[i].texts[j];
2140
2141 equalizer_control->name = abe->equ_texts[i].name;
2142 equalizer_control->private_value = (unsigned long)equalizer_enum;
2143 equalizer_control->get = abe_get_equalizer;
2144 equalizer_control->put = abe_put_equalizer;
2145 equalizer_control->info = snd_soc_info_enum_ext1;
2146 equalizer_control->iface = SNDRV_CTL_ELEM_IFACE_MIXER;
2147
2148 dev_dbg(platform->dev, "added EQU mixer: %s profiles %d\n",
2149 abe->equ_texts[i].name, abe->equ_texts[i].count);
2150
2151 for (j = 0; j < abe->equ_texts[i].count; j++)
2152 dev_dbg(platform->dev, " %s\n", equalizer_enum->dtexts[j]);
2153 }
2154
2155 snd_soc_add_platform_controls(platform, abe->equalizer_control,
2156 hdr->num_equ);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002157
2158 snd_soc_add_platform_controls(platform, abe_controls,
2159 ARRAY_SIZE(abe_controls));
2160
2161 snd_soc_dapm_new_controls(&platform->dapm, abe_dapm_widgets,
2162 ARRAY_SIZE(abe_dapm_widgets));
2163
2164 snd_soc_dapm_add_routes(&platform->dapm, intercon, ARRAY_SIZE(intercon));
2165
2166 snd_soc_dapm_new_widgets(&platform->dapm);
2167
2168 return 0;
2169}
2170
2171static int abe_probe(struct snd_soc_platform *platform)
2172{
2173 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002174 u8 *fw_data;
2175 int i, offset = 0;
2176 int ret = 0;
2177#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002178 const struct firmware *fw;
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002179#endif
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002180
2181 abe->platform = platform;
2182
2183 pm_runtime_enable(abe->dev);
2184
2185#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
2186 /* request firmware & coefficients */
2187 ret = request_firmware(&fw, "omap4_abe", platform->dev);
2188 if (ret != 0) {
2189 dev_err(abe->dev, "Failed to load firmware: %d\n", ret);
2190 return ret;
2191 }
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002192 fw_data = fw->data;
2193#else
2194 fw_data = (u8 *)abe_get_default_fw();
2195#endif
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002196
2197 /* get firmware and coefficients header info */
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002198 memcpy(&abe->hdr, fw_data, sizeof(struct fw_header));
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002199 if (abe->hdr.firmware_size > ABE_MAX_FW_SIZE) {
2200 dev_err(abe->dev, "Firmware too large at %d bytes: %d\n",
2201 abe->hdr.firmware_size, ret);
2202 ret = -EINVAL;
2203 goto err_fw;
2204 }
2205 dev_dbg(abe->dev, "ABE firmware size %d bytes\n", abe->hdr.firmware_size);
2206
2207 if (abe->hdr.coeff_size > ABE_MAX_COEFF_SIZE) {
2208 dev_err(abe->dev, "Coefficients too large at %d bytes: %d\n",
2209 abe->hdr.coeff_size, ret);
2210 ret = -EINVAL;
2211 goto err_fw;
2212 }
2213 dev_dbg(abe->dev, "ABE coefficients size %d bytes\n", abe->hdr.coeff_size);
2214
2215 /* get coefficient EQU mixer strings */
2216 if (abe->hdr.num_equ >= ABE_MAX_EQU) {
2217 dev_err(abe->dev, "Too many equalizers got %d\n", abe->hdr.num_equ);
2218 ret = -EINVAL;
2219 goto err_fw;
2220 }
2221 abe->equ_texts = kzalloc(abe->hdr.num_equ * sizeof(struct coeff_config),
2222 GFP_KERNEL);
2223 if (abe->equ_texts == NULL) {
2224 ret = -ENOMEM;
2225 goto err_fw;
2226 }
2227 offset = sizeof(struct fw_header);
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002228 memcpy(abe->equ_texts, fw_data + offset,
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002229 abe->hdr.num_equ * sizeof(struct coeff_config));
2230
2231 /* get coefficients from firmware */
2232 abe->equ[0] = kmalloc(abe->hdr.coeff_size, GFP_KERNEL);
2233 if (abe->equ[0] == NULL) {
2234 ret = -ENOMEM;
2235 goto err_equ;
2236 }
2237 offset += abe->hdr.num_equ * sizeof(struct coeff_config);
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002238 memcpy(abe->equ[0], fw_data + offset, abe->hdr.coeff_size);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002239
2240 /* allocate coefficient mixer texts */
2241 dev_dbg(abe->dev, "loaded %d equalizers\n", abe->hdr.num_equ);
2242 for (i = 0; i < abe->hdr.num_equ; i++) {
2243 dev_dbg(abe->dev, "equ %d: %s profiles %d\n", i,
2244 abe->equ_texts[i].name, abe->equ_texts[i].count);
2245 if (abe->equ_texts[i].count >= ABE_MAX_PROFILES) {
2246 dev_err(abe->dev, "Too many profiles got %d for equ %d\n",
2247 abe->equ_texts[i].count, i);
2248 ret = -EINVAL;
2249 goto err_texts;
2250 }
2251 abe->equalizer_enum[i].dtexts =
2252 kzalloc(abe->equ_texts[i].count * sizeof(char *), GFP_KERNEL);
2253 if (abe->equalizer_enum[i].dtexts == NULL) {
2254 ret = -ENOMEM;
2255 goto err_texts;
2256 }
2257 }
2258
2259 /* initialise coefficient equalizers */
2260 for (i = 1; i < abe->hdr.num_equ; i++) {
2261 abe->equ[i] = abe->equ[i - 1] +
Sebastien Guiriec2c25e322011-07-13 02:54:44 -05002262 abe->equ_texts[i - 1].count * abe->equ_texts[i - 1].coeff;
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002263 }
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002264
2265 /* store ABE firmware for later context restore */
2266 abe->firmware = kzalloc(abe->hdr.firmware_size, GFP_KERNEL);
2267 memcpy(abe->firmware,
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002268 fw_data + sizeof(struct fw_header) + abe->hdr.coeff_size,
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002269 abe->hdr.firmware_size);
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002270
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002271 ret = request_irq(abe->irq, abe_irq_handler, 0, "ABE", (void *)abe);
2272 if (ret) {
2273 dev_err(platform->dev, "request for ABE IRQ %d failed %d\n",
2274 abe->irq, ret);
2275 goto err_texts;
2276 }
2277
2278 /* aess_clk has to be enabled to access hal register.
2279 * Disable the clk after it has been used.
2280 */
2281 pm_runtime_get_sync(abe->dev);
2282
2283 abe_init_mem(abe->io_base);
2284
2285 abe_reset_hal();
2286
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002287 abe_load_fw(abe->firmware);
2288
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002289 /* Config OPP 100 for now */
2290 abe_set_opp_processing(ABE_OPP100);
2291
2292 /* "tick" of the audio engine */
2293 abe_write_event_generator(EVENT_TIMER);
2294 /* Stop the engine */
2295 abe_stop_event_generator();
2296 abe_disable_irq();
2297
2298 pm_runtime_put_sync(abe->dev);
2299 abe_add_widgets(platform);
2300
2301#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
2302 release_firmware(fw);
2303#endif
2304 return ret;
2305
2306err_texts:
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002307 kfree(abe->firmware);
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002308 for (i = 0; i < abe->hdr.num_equ; i++)
2309 kfree(abe->equalizer_enum[i].texts);
2310 kfree(abe->equ[0]);
2311err_equ:
2312 kfree(abe->equ_texts);
2313err_fw:
Misael Lopez Cruz54365dc2011-07-13 03:25:37 -05002314#if defined(CONFIG_SND_OMAP_SOC_ABE_DSP_MODULE)
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002315 release_firmware(fw);
2316#endif
2317 return ret;
2318}
2319
2320static int abe_remove(struct snd_soc_platform *platform)
2321{
2322 struct abe_data *abe = snd_soc_platform_get_drvdata(platform);
2323 int i;
2324
2325 free_irq(abe->irq, (void *)abe);
2326
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002327 for (i = 0; i < abe->hdr.num_equ; i++)
2328 kfree(abe->equalizer_enum[i].texts);
2329
2330 kfree(abe->equ[0]);
2331 kfree(abe->equ_texts);
Misael Lopez Cruz7c8913a2011-07-12 07:04:43 -05002332 kfree(abe->firmware);
2333
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002334 pm_runtime_disable(abe->dev);
2335
2336 return 0;
2337}
2338
2339static struct snd_soc_platform_driver omap_aess_platform = {
2340 .ops = &omap_aess_pcm_ops,
2341 .probe = abe_probe,
2342 .remove = abe_remove,
2343 .read = abe_dsp_read,
2344 .write = abe_dsp_write,
2345 .stream_event = aess_stream_event,
2346};
2347
2348static int __devinit abe_engine_probe(struct platform_device *pdev)
2349{
2350 struct resource *res;
2351 struct omap4_abe_dsp_pdata *pdata = pdev->dev.platform_data;
2352 struct abe_data *abe;
Misael Lopez Cruz5ae9cf52011-07-12 05:17:16 -05002353 int ret = -EINVAL, i;
Liam Girdwooda8d99da2011-02-03 15:28:19 +00002354
2355 abe = kzalloc(sizeof(struct abe_data), GFP_KERNEL);
2356 if (abe == NULL)
2357 return -ENOMEM;
2358 dev_set_drvdata(&pdev->dev, abe);
2359 the_abe = abe;
2360
2361 /* ZERO_labelID should really be 0 */
2362 for (i = 0; i < ABE_ROUTES_UL + 2; i++)
2363 abe->router[i] = ZERO_labelID;
2364
2365 for (i = 0; i < 5; i++) {
2366 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
2367 abe_memory_bank[i]);
2368 if (res == NULL) {
2369 dev_err(&pdev->dev, "no resource %s\n",
2370 abe_memory_bank[i]);
2371 goto err;
2372 }
2373 abe->io_base[i] = ioremap(res->start, resource_size(res));
2374 if (!abe->io_base[i]) {
2375 ret = -ENOMEM;
2376 goto err;
2377 }
2378 }
2379
2380 abe->irq = platform_get_irq(pdev, 0);
2381 if (abe->irq < 0) {
2382 ret = abe->irq;
2383 goto err;
2384 }
2385
2386 abe->abe_pdata = pdata;
2387 abe->dev = &pdev->dev;
2388 mutex_init(&abe->mutex);
2389 mutex_init(&abe->opp_mutex);
2390
2391 ret = snd_soc_register_platform(abe->dev,
2392 &omap_aess_platform);
2393 if (ret < 0)
2394 return ret;
2395
2396 abe_init_debugfs(abe);
2397 return ret;
2398
2399err:
2400 for (--i; i >= 0; i--)
2401 iounmap(abe->io_base[i]);
2402 kfree(abe);
2403 return ret;
2404}
2405
2406static int __devexit abe_engine_remove(struct platform_device *pdev)
2407{
2408 struct abe_data *abe = dev_get_drvdata(&pdev->dev);
2409 int i;
2410
2411 abe_cleanup_debugfs(abe);
2412 snd_soc_unregister_platform(&pdev->dev);
2413 for (i = 0; i < 5; i++)
2414 iounmap(abe->io_base[i]);
2415 kfree(abe);
2416 return 0;
2417}
2418
2419static struct platform_driver omap_aess_driver = {
2420 .driver = {
2421 .name = "aess",
2422 .owner = THIS_MODULE,
2423 .pm = &aess_pm_ops,
2424 },
2425 .probe = abe_engine_probe,
2426 .remove = __devexit_p(abe_engine_remove),
2427};
2428
2429static int __init abe_engine_init(void)
2430{
2431 return platform_driver_register(&omap_aess_driver);
2432}
2433module_init(abe_engine_init);
2434
2435static void __exit abe_engine_exit(void)
2436{
2437 platform_driver_unregister(&omap_aess_driver);
2438}
2439module_exit(abe_engine_exit);
2440
2441MODULE_DESCRIPTION("ASoC OMAP4 ABE");
2442MODULE_AUTHOR("Liam Girdwood <lrg@ti.com>");
2443MODULE_LICENSE("GPL");