asoc:tegra: fix dam cif programming
[linux-2.6.git] / sound / soc / tegra / tegra30_dam.c
1 /*
2  * tegra30_dam.c - Tegra 30 DAM driver
3  *
4  * Author: Nikesh Oswal <noswal@nvidia.com>
5  * Copyright (C) 2011 - NVIDIA, Inc.
6  * Copyright (C) 2012, NVIDIA CORPORATION. All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  *
22  */
23
24 #include <linux/clk.h>
25 #include <linux/module.h>
26 #include <linux/debugfs.h>
27 #include <linux/device.h>
28 #include <linux/platform_device.h>
29 #include <linux/seq_file.h>
30 #include <linux/slab.h>
31 #include <linux/delay.h>
32 #include <linux/io.h>
33 #include <sound/soc.h>
34 #include "tegra30_dam.h"
35 #include "tegra30_ahub.h"
36
37 #define DRV_NAME "tegra30-dam"
38
39 static struct tegra30_dam_context       *dams_cont_info[TEGRA30_NR_DAM_IFC];
40
41 enum {
42         dam_ch_in0 = 0x0,
43         dam_ch_in1,
44         dam_ch_out,
45         dam_ch_maxnum
46 } tegra30_dam_chtype;
47
48 struct tegra30_dam_src_step_table  step_table[] = {
49         { 8000, 44100, 80 },
50         { 8000, 48000, 1 },
51         { 16000, 44100, 160 },
52         { 16000, 48000, 1 },
53         { 44100, 8000, 441 },
54         { 48000, 8000, 0 },
55         { 44100, 16000, 441 },
56         { 48000, 16000, 0 },
57 };
58
59 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
60 int coefRam16To44[64] = {
61                                 0x156105, // IIR Filter + interpolation
62                                 0x0000d649,
63                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
64                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
65                                 0x00344928, 0xffcba3e5, 0x006be470,
66                                 0x00137aa7, 0xffe60276, 0x00773410,
67                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
68                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
69                                 0x2,
70                                 0x21a102, // IIR Filter + interplation
71                                 0x00000e00,
72                                 0x00e2e000,0xff6e1a00,0x002aaa00,
73                                 0x00610a00,0xff5dda00,0x003ccc00,
74                                 0x00163a00,0xff3c0400,0x00633200,
75                                 0x3,
76                                 0x2c0204, // Farrow Filter
77                                 0x000aaaab,
78                                 0xffaaaaab,
79                                 0xfffaaaab,
80                                 0x00555555,
81                                 0xff600000,
82                                 0xfff55555,
83                                 0x00155555,
84                                 0x00055555,
85                                 0xffeaaaab,
86                                 0x00200000,
87                                 0x005101, //IIR Filter + Decimator
88                                 8252,
89                                 16067893,-13754014,5906912,
90                                 13037808,-13709975,7317389,
91                                 1,
92                                 0,0,0,0,0,
93                                 0,0,0,0,0,0
94 };
95
96 int coefRam8To48[64] = {
97                                 0x156105, // interpolation + FIlter
98                                 0x0000d649,
99                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
100                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
101                                 0x00344928, 0xffcba3e5, 0x006be470,
102                                 0x00137aa7, 0xffe60276, 0x00773410,
103                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
104                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
105                                 0x2, // ouptut gain
106                                 0x00a102, // filter + interpolation
107                                 0x00000e00,
108                                 0x00e2e000,0xff6e1a00,0x002aaa00,
109                                 0x00610a00,0xff5dda00,0x003ccc00,
110                                 0x00163a00,0xff3c0400,0x00633200,
111                                 0x3,
112                                 0,0,0,0,0,0,
113                                 0,0,0,0,0,0,
114                                 0,0,0,0,0,0,
115                                 0,0,0,0,0,0,
116                                 0,0,0,0,0,0,
117                                 0
118 };
119
120 int coefRam16To48[64] = {
121                                 0x00a105, // interpolation + Filter
122                                 1924,
123                                 13390190,-13855175,5952947,
124                                 1289485,-12761191,6540917,
125                                 -4787304,-11454255,7249439,
126                                 -7239963,-10512732,7776366,
127                                 -8255332,-9999487,8101770,
128                                 -8632155,-9817625,8305531,
129                                 0x3,0,0,
130                                 0,0,0,
131                                 0,0,0,
132                                 0,0,0,
133                                 0,0,0,
134                                 0,0,0,
135                                 0,0,0,
136                                 0,0,0,
137                                 0,0,0,
138                                 0,0,0,
139                                 0,0,0,
140                                 0,0,0,
141                                 0,0,0,
142                                 0,0,0,
143                                 0,0
144 };
145
146 int coefRam44To16[64] = {
147                                 0x126104, // IIR Filter + interp0lation
148                                 2802,
149                                 5762750,-14772125,6628868,
150                                 -9304342,-14504578,7161825,
151                                 -12409641,-14227678,7732611,
152                                 -13291674,-14077653,8099947,
153                                 -13563385,-14061743,8309372,
154                                 2,
155                                 0x1d9204, // Farrwo Filter + Decimation
156                                 0x000aaaab,
157                                 0xffaaaaab,
158                                 0xfffaaaab,
159                                 0x00555555,
160                                 0xff600000,
161                                 0xfff55555,
162                                 0x00155555,
163                                 0x00055555,
164                                 0xffeaaaab,
165                                 0x00200000,
166                                 0x005105, // IIR Filter+decimation
167                                 0x0000d649,
168                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
169                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
170                                 0x00344928, 0xffcba3e5, 0x006be470,
171                                 0x00137aa7, 0xffe60276, 0x00773410,
172                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
173                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
174                                 0x1,
175                                 0,0,0,0,0,
176                                 0,0,0,0,0,
177                                 0,0,0,0
178 };
179
180 int coefRam44To8[64] = {
181                                 0x120104, // IIR Filter
182                                 2802,
183                                 5762750,-14772125,6628868,
184                                 -9304342,-14504578,7161825,
185                                 -12409641,-14227678,7732611,
186                                 -13291674,-14077653,8099947,
187                                 -13563385,-14061743,8309372,
188                                 1,
189                                 0x1d9204, // Farrwo Filter
190                                 0x000aaaab,
191                                 0xffaaaaab,
192                                 0xfffaaaab,
193                                 0x00555555,
194                                 0xff600000,
195                                 0xfff55555,
196                                 0x00155555,
197                                 0x00055555,
198                                 0xffeaaaab,
199                                 0x00200000,
200                                 0x005105, // IIR Filter
201                                 0x0000d649,
202                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
203                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
204                                 0x00344928, 0xffcba3e5, 0x006be470,
205                                 0x00137aa7, 0xffe60276, 0x00773410,
206                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
207                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
208                                 0x1,
209                                 0,0,0,0,0,0,
210                                 0,0,0,0,0,0,
211                                 0,0
212 };
213
214 int coefRam48To16[64] = {
215                                 0x009105, // IIR FIlter + Decimation
216                                 1924,
217                                 13390190,-13855175,5952947,
218                                 1289485,-12761191,6540917,
219                                 -4787304,-11454255,7249439,
220                                 -7239963,-10512732,7776366,
221                                 -8255332,-9999487,8101770,
222                                 -8632155,-9817625,8305531,
223                                 0x1,
224                                 0,0,0,
225                                 0,0,0,0,0,0,0,0,
226                                 0,0,0,0,0,0,0,0,
227                                 0,0,0,0,0,0,0,0,
228                                 0,0,0,0,0,0,0,0,
229                                 0,0,0,0,0,0,0,0
230 };
231
232 int coefRam48To8[64] = {
233                                 0x0c9102,       //IIR Filter + decimation
234                                 0x00000e00,
235                                 0x00e2e000,0xff6e1a00,0x002aaa00,
236                                 0x00610a00,0xff5dda00,0x003ccc00,
237                                 0x00163a00,0xff3c0400,0x00633200,
238                                 0x1,
239                                 0x005105,   //IIR Filter + Decimator
240                                 0x0000d649,
241                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
242                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
243                                 0x00344928, 0xffcba3e5, 0x006be470,
244                                 0x00137aa7, 0xffe60276, 0x00773410,
245                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
246                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
247                                 0x1, // ouptut gain
248                                 0,0,0,0,0,0,
249                                 0,0,0,0,0,0,
250                                 0,0,0,0,0,0,
251                                 0,0,0,0,0,0,
252                                 0,0,0,0,0,0,
253                                 0
254 };
255
256 int coefRam8To44[64] = {
257                                 0x0156105, // IIR filter +interpllation
258                                 0x0000d649,
259                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
260                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
261                                 0x00344928, 0xffcba3e5, 0x006be470,
262                                 0x00137aa7, 0xffe60276, 0x00773410,
263                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
264                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
265                                 0x2, // ouptut gain
266                                 0x21a102, // filter + interp0lation
267                                 0x00000e00,
268                                 0x00e2e000,0xff6e1a00,0x002aaa00,
269                                 0x00610a00,0xff5dda00,0x003ccc00,
270                                 0x00163a00,0xff3c0400,0x00633200,
271                                 0x3,
272                                 0x000204,
273                                 0x000aaaab,
274                                 0xffaaaaab,
275                                 0xfffaaaab,
276                                 0x00555555,
277                                 0xff600000,
278                                 0xfff55555,
279                                 0x00155555,
280                                 0x00055555,
281                                 0xffeaaaab,
282                                 0x00200000,
283                                 0,0,
284                                 0,0,0,0,0,0,
285                                 0,0,0,0,0,0,
286                                 0,0,0,0,0,0
287 };
288
289 int coefRam8To16[64] = {
290                                 0x00006105, // interpolation + IIR Filter
291                                 0x0000d649, // input gain
292                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
293                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
294                                 0x00344928, 0xffcba3e5, 0x006be470,
295                                 0x00137aa7, 0xffe60276, 0x00773410,
296                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
297                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
298                                 0x00000002, // ouptut gain
299 };
300
301 int coefRam16To8[64] = {
302                                 0x00005105,   //IIR Filter + Decimator
303                                 0x0000d649, //input gain
304                                 0x00e87afb, 0xff5f69d0, 0x003df3cf,
305                                 0x007ce488, 0xff99a5c8, 0x0056a6a0,
306                                 0x00344928, 0xffcba3e5, 0x006be470,
307                                 0x00137aa7, 0xffe60276, 0x00773410,
308                                 0x0005fa2a, 0xfff1ac11, 0x007c795b,
309                                 0x00012d36, 0xfff5eca2, 0x007f10ef,
310                                 0x00000001, // ouptut gain
311 };
312 #endif
313
314 static void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
315                 int fsout);
316 static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam,
317                 int fsin);
318 static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
319                 int insample, int outsample);
320 static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step);
321
322 static inline void tegra30_dam_writel(struct tegra30_dam_context *dam,
323                         u32 val, u32 reg)
324 {
325 #ifdef CONFIG_PM
326         dam->reg_cache[reg >> 2] = val;
327 #endif
328         __raw_writel(val, dam->damregs + reg);
329 }
330
331 static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam, u32 reg)
332 {
333         u32 val = __raw_readl(dam->damregs + reg);
334
335         return val;
336 }
337
338 #ifdef CONFIG_PM
339 int tegra30_dam_resume(int ifc)
340 {
341         int i = 0;
342         struct tegra30_dam_context *dam;
343
344         if (ifc >= TEGRA30_NR_DAM_IFC)
345                 return -EINVAL;
346
347         dam = dams_cont_info[ifc];
348
349         if (dam->in_use) {
350                 tegra30_dam_enable_clock(ifc);
351
352                 for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
353                         if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
354                                 (i == TEGRA30_DAM_CTRL_RSVD_10))
355                                 continue;
356
357                         tegra30_dam_writel(dam, dam->reg_cache[i],
358                                                 (i << 2));
359                 }
360
361                 tegra30_dam_disable_clock(ifc);
362         }
363
364         return 0;
365 }
366 #endif
367
368 void tegra30_dam_disable_clock(int ifc)
369 {
370         struct tegra30_dam_context *dam;
371
372         if (ifc >= TEGRA30_NR_DAM_IFC)
373                 return;
374
375         dam =  dams_cont_info[ifc];
376         clk_disable(dam->dam_clk);
377         tegra30_ahub_disable_clocks();
378 }
379
380 int tegra30_dam_enable_clock(int ifc)
381 {
382         struct tegra30_dam_context *dam;
383
384         if (ifc >= TEGRA30_NR_DAM_IFC)
385                 return -EINVAL;
386
387         dam =  dams_cont_info[ifc];
388         tegra30_ahub_enable_clocks();
389         clk_enable(dam->dam_clk);
390
391         return 0;
392 }
393
394 #ifdef CONFIG_DEBUG_FS
395 static int tegra30_dam_show(struct seq_file *s, void *unused)
396 {
397 #define REG(r) { r, #r }
398         static const struct {
399                 int offset;
400                 const char *name;
401         } regs[] = {
402                 REG(TEGRA30_DAM_CTRL),
403                 REG(TEGRA30_DAM_CLIP),
404                 REG(TEGRA30_DAM_CLIP_THRESHOLD),
405                 REG(TEGRA30_DAM_AUDIOCIF_OUT_CTRL),
406                 REG(TEGRA30_DAM_CH0_CTRL),
407                 REG(TEGRA30_DAM_CH0_CONV),
408                 REG(TEGRA30_DAM_AUDIOCIF_CH0_CTRL),
409                 REG(TEGRA30_DAM_CH1_CTRL),
410                 REG(TEGRA30_DAM_CH1_CONV),
411                 REG(TEGRA30_DAM_AUDIOCIF_CH1_CTRL),
412         };
413 #undef REG
414
415         struct tegra30_dam_context *dam = s->private;
416         int i;
417
418         clk_enable(dam->dam_clk);
419
420         for (i = 0; i < ARRAY_SIZE(regs); i++) {
421                 u32 val = tegra30_dam_readl(dam, regs[i].offset);
422                 seq_printf(s, "%s = %08x\n", regs[i].name, val);
423         }
424
425         clk_disable(dam->dam_clk);
426
427         return 0;
428 }
429
430 static int tegra30_dam_debug_open(struct inode *inode, struct file *file)
431 {
432         return single_open(file, tegra30_dam_show, inode->i_private);
433 }
434
435 static const struct file_operations tegra30_dam_debug_fops = {
436         .open    = tegra30_dam_debug_open,
437         .read    = seq_read,
438         .llseek  = seq_lseek,
439         .release = single_release,
440 };
441
442 static void tegra30_dam_debug_add(struct tegra30_dam_context *dam, int id)
443 {
444         char name[] = DRV_NAME ".0";
445
446         snprintf(name, sizeof(name), DRV_NAME".%1d", id);
447         dam->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
448                         dam, &tegra30_dam_debug_fops);
449 }
450
451 static void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
452 {
453         if (dam->debug)
454                 debugfs_remove(dam->debug);
455 }
456 #else
457 static inline void tegra30_dam_debug_add(struct tegra30_dam_context *dam,
458                                                 int id)
459 {
460 }
461
462 static inline void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
463 {
464 }
465 #endif
466
467 int tegra30_dam_allocate_controller()
468 {
469         int i = 0;
470         struct tegra30_dam_context *dam = NULL;
471
472         for (i = 0; i < TEGRA30_NR_DAM_IFC; i++) {
473
474                 dam =  dams_cont_info[i];
475
476                 if (!dam->in_use) {
477                         dam->in_use = true;
478                         return i;
479                 }
480         }
481
482         return -ENOENT;
483 }
484
485 int tegra30_dam_allocate_channel(int ifc, int chid)
486 {
487         struct tegra30_dam_context *dam = NULL;
488
489         if (ifc >= TEGRA30_NR_DAM_IFC)
490                 return -EINVAL;
491
492         dam =  dams_cont_info[ifc];
493
494         if (!dam->ch_alloc[chid]) {
495                 dam->ch_alloc[chid] = true;
496                 return 0;
497         }
498
499         return -ENOENT;
500 }
501
502 int tegra30_dam_free_channel(int ifc, int chid)
503 {
504         struct tegra30_dam_context *dam = NULL;
505
506         if (ifc >= TEGRA30_NR_DAM_IFC)
507                 return -EINVAL;
508
509         dam =  dams_cont_info[ifc];
510
511         if (dam->ch_alloc[chid]) {
512                 dam->ch_alloc[chid] = false;
513                 return 0;
514         }
515
516         return -EINVAL;
517 }
518
519 int tegra30_dam_free_controller(int ifc)
520 {
521         struct tegra30_dam_context *dam = NULL;
522
523         if (ifc >= TEGRA30_NR_DAM_IFC)
524                 return -EINVAL;
525
526         dam =  dams_cont_info[ifc];
527
528         if (!dam->ch_alloc[dam_ch_in0] &&
529                 !dam->ch_alloc[dam_ch_in1]) {
530                 dam->in_use = false;
531                 return 0;
532         }
533
534         return -EINVAL;
535 }
536
537 void tegra30_dam_set_samplerate(int ifc, int chid, int samplerate)
538 {
539         struct tegra30_dam_context *dam = dams_cont_info[ifc];
540
541         if (ifc >= TEGRA30_NR_DAM_IFC)
542                 return;
543
544         switch (chid) {
545         case dam_ch_in0:
546                 tegra30_dam_set_input_samplerate(dam, samplerate);
547                 dam->ch_insamplerate[dam_ch_in0] = samplerate;
548                 tegra30_dam_set_step_reset(dam, samplerate, dam->outsamplerate);
549                 break;
550         case dam_ch_in1:
551                 if (samplerate != dam->outsamplerate)
552                         return;
553                 dam->ch_insamplerate[dam_ch_in1] = samplerate;
554                 break;
555         case dam_ch_out:
556                 tegra30_dam_set_output_samplerate(dam, samplerate);
557                 dam->outsamplerate = samplerate;
558                 break;
559         default:
560                 break;
561         }
562 }
563
564 void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
565                                         int fsout)
566 {
567         u32 val;
568
569         val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
570         val &= ~TEGRA30_DAM_CTRL_FSOUT_MASK;
571
572         switch (fsout) {
573         case TEGRA30_AUDIO_SAMPLERATE_8000:
574                 val |= TEGRA30_DAM_CTRL_FSOUT_FS8;
575                 break;
576         case TEGRA30_AUDIO_SAMPLERATE_16000:
577                 val |= TEGRA30_DAM_CTRL_FSOUT_FS16;
578                 break;
579         case TEGRA30_AUDIO_SAMPLERATE_44100:
580                 val |= TEGRA30_DAM_CTRL_FSOUT_FS44;
581                 break;
582         case TEGRA30_AUDIO_SAMPLERATE_48000:
583                 val |= TEGRA30_DAM_CTRL_FSOUT_FS48;
584                 break;
585         default:
586                 break;
587         }
588
589         tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
590 }
591
592 void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin)
593 {
594         u32 val;
595
596         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
597         val &= ~TEGRA30_DAM_CH0_CTRL_FSIN_MASK;
598
599         switch (fsin) {
600         case TEGRA30_AUDIO_SAMPLERATE_8000:
601                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS8;
602                 break;
603         case TEGRA30_AUDIO_SAMPLERATE_16000:
604                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS16;
605                 break;
606         case TEGRA30_AUDIO_SAMPLERATE_44100:
607                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS44;
608                 break;
609         case TEGRA30_AUDIO_SAMPLERATE_48000:
610                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS48;
611                 break;
612         default:
613                 break;
614         }
615
616         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
617 }
618
619 int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
620                 int insample, int outsample)
621 {
622         int step_reset = 0;
623         int i = 0;
624
625         for (i = 0; i < ARRAY_SIZE(step_table); i++) {
626                 if ((insample == step_table[i].insample) &&
627                         (outsample == step_table[i].outsample))
628                         step_reset = step_table[i].stepreset;
629         }
630
631         tegra30_dam_ch0_set_step(dam, step_reset);
632
633         return 0;
634 }
635
636 void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
637 {
638         u32 val;
639
640         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
641         val &= ~TEGRA30_DAM_CH0_CTRL_STEP_MASK;
642         val |= step << TEGRA30_DAM_CH0_CTRL_STEP_SHIFT;
643         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
644 }
645
646 int tegra30_dam_set_gain(int ifc, int chid, int gain)
647 {
648
649         if (ifc >= TEGRA30_NR_DAM_IFC)
650                 return -EINVAL;
651
652         switch (chid) {
653         case dam_ch_in0:
654                 tegra30_dam_writel(dams_cont_info[ifc], gain,
655                         TEGRA30_DAM_CH0_CONV);
656                 break;
657         case dam_ch_in1:
658                 tegra30_dam_writel(dams_cont_info[ifc], gain,
659                         TEGRA30_DAM_CH1_CONV);
660                 break;
661         default:
662                 break;
663         }
664
665         return 0;
666 }
667
668 int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
669         unsigned int audio_bits, unsigned int client_channels,
670         unsigned int client_bits)
671 {
672         unsigned int reg;
673         unsigned int value = 0;
674
675         if (ifc >= TEGRA30_NR_DAM_IFC)
676                 return -EINVAL;
677
678 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
679         /*ch0 takes input as mono always*/
680         if ((chid == dam_ch_in0) &&
681                 ((client_channels != 1)))
682                 return -EINVAL;
683         /*as per dam spec file chout is fixed to 32 bits*/
684         /*so accept ch0, ch1 and chout as 32bit always*/
685         if (client_bits != 32)
686                 return -EINVAL;
687 #else
688         /*ch0 takes input as mono/16bit always*/
689         if ((chid == dam_ch_in0) &&
690                 ((client_channels != 1) || (client_bits != 16)))
691                 return -EINVAL;
692 #endif
693
694         value |= TEGRA30_CIF_MONOCONV_COPY;
695         value |= TEGRA30_CIF_STEREOCONV_CH0;
696         value |= (audio_channels-1)  << TEGRA30_AUDIO_CHANNELS_SHIFT;
697         value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
698         value |= (client_channels-1)  << TEGRA30_CLIENT_CHANNELS_SHIFT;
699         value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
700
701         switch (chid) {
702         case dam_ch_out:
703                 value |= TEGRA30_CIF_DIRECTION_TX;
704                 reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
705                 break;
706         case dam_ch_in0:
707                 value |= TEGRA30_CIF_DIRECTION_RX;
708                 reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
709                 break;
710         case dam_ch_in1:
711                 value |= TEGRA30_CIF_DIRECTION_RX;
712                 reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
713                 break;
714         default:
715                 return -EINVAL;
716         }
717
718         tegra30_dam_writel(dams_cont_info[ifc], value, reg);
719
720         return 0;
721 }
722
723 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
724 void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout)
725 {
726         u32 val;
727         int i, *coefRam = NULL;
728
729         if (ifc >= TEGRA30_NR_DAM_IFC)
730                 return;
731
732         tegra30_dam_writel(dams_cont_info[ifc], 0x00002000,
733                         TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
734
735         switch(fsin) {
736                 case TEGRA30_AUDIO_SAMPLERATE_8000:
737                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
738                                 coefRam = coefRam8To48;
739                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
740                                 coefRam = coefRam8To44;
741                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
742                                 coefRam = coefRam8To16;
743                         break;
744
745                 case TEGRA30_AUDIO_SAMPLERATE_16000:
746                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
747                                 coefRam = coefRam16To48;
748                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
749                                 coefRam = coefRam16To44;
750                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
751                                 coefRam = coefRam16To8;
752                         break;
753
754                 case TEGRA30_AUDIO_SAMPLERATE_44100:
755                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
756                                 coefRam = coefRam44To8;
757                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
758                                 coefRam = coefRam44To16;
759                         break;
760
761                 case TEGRA30_AUDIO_SAMPLERATE_48000:
762                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
763                                 coefRam = coefRam48To8;
764                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
765                                 coefRam = coefRam48To16;
766                         break;
767
768                 default:
769                         break;
770         }
771
772         tegra30_dam_writel(dams_cont_info[ifc], 0x00005000,
773                         TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
774
775         for (i = 0; i < 64; i++) {
776                 val = coefRam[i];\r
777                 tegra30_dam_writel(dams_cont_info[ifc], val,
778                                 TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0);
779         }
780 }
781
782 void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout)
783 {
784         u32 val = TEGRA30_FARROW_PARAM_RESET;
785
786         if (ifc >= TEGRA30_NR_DAM_IFC)
787                 return;
788
789         switch(fsin) {
790                 case TEGRA30_AUDIO_SAMPLERATE_8000:
791                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
792                                 val = TEGRA30_FARROW_PARAM_1;
793                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
794                                 val = TEGRA30_FARROW_PARAM_2;
795                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
796                                 val = TEGRA30_FARROW_PARAM_1;
797                         break;
798
799                 case TEGRA30_AUDIO_SAMPLERATE_16000:
800                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
801                                 val = TEGRA30_FARROW_PARAM_1;
802                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
803                                 val = TEGRA30_FARROW_PARAM_2;
804                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
805                                 val = TEGRA30_FARROW_PARAM_1;
806                         break;
807
808                 case TEGRA30_AUDIO_SAMPLERATE_44100:
809                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
810                                 val = TEGRA30_FARROW_PARAM_3;
811                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
812                                 val = TEGRA30_FARROW_PARAM_3;
813                         break;
814
815                 case TEGRA30_AUDIO_SAMPLERATE_48000:
816                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
817                                 val = TEGRA30_FARROW_PARAM_1;
818                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
819                                 val = TEGRA30_FARROW_PARAM_1;
820                         break;
821
822                 default:
823                         break;
824         }
825
826         tegra30_dam_writel(dams_cont_info[ifc], val,
827                         TEGRA30_DAM_FARROW_PARAM_0);
828 }
829
830 void tegra30_dam_set_biquad_fixed_coef(int ifc)
831 {
832         u32 val = TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0_VAL;
833
834         if (ifc >= TEGRA30_NR_DAM_IFC)
835                 return;
836
837         tegra30_dam_writel(dams_cont_info[ifc], val,
838                         TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0);
839 }
840
841 void tegra30_dam_enable_coeff_ram(int ifc)
842 {
843         u32 val;
844
845         if (ifc >= TEGRA30_NR_DAM_IFC)
846                 return;
847
848         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
849         val |= TEGRA30_DAM_CH0_CTRL_COEFF_RAM_ENABLE;
850
851         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
852 }
853
854 void tegra30_dam_set_filter_stages(int ifc, int fsin, int fsout)
855 {
856         u32 val;
857         int filt_stages = 0;
858
859         if (ifc >= TEGRA30_NR_DAM_IFC)
860                 return;
861
862         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
863
864         switch(fsin) {
865                 case TEGRA30_AUDIO_SAMPLERATE_8000:
866                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
867                                 filt_stages = 1;
868                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
869                                 filt_stages = 2;
870                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
871                                 filt_stages = 0;
872                         break;
873
874                 case TEGRA30_AUDIO_SAMPLERATE_16000:
875                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
876                                 filt_stages = 0;
877                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
878                                 filt_stages = 3;
879                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
880                                 filt_stages = 0;
881                         break;
882
883                 case TEGRA30_AUDIO_SAMPLERATE_44100:
884                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
885                                 filt_stages = 2;
886                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
887                                 filt_stages = 2;
888                         break;
889
890                 case TEGRA30_AUDIO_SAMPLERATE_48000:
891                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
892                                 filt_stages = 1;
893                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
894                                 filt_stages = 0;
895                         break;
896
897                 default:
898                         break;
899         }
900
901         val |= filt_stages << TEGRA30_DAM_CH0_CTRL_FILT_STAGES_SHIFT;
902
903         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
904 }
905
906 void tegra30_dam_enable_stereo_mixing(int ifc)
907 {
908         u32 val;
909
910         if (ifc >= TEGRA30_NR_DAM_IFC)
911                 return;
912
913         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CTRL);
914         val |= TEGRA30_DAM_CTRL_STEREO_MIXING_ENABLE;
915
916         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CTRL);
917 }
918 #endif
919
920 void tegra30_dam_enable(int ifc, int on, int chid)
921 {
922         u32 old_val, val, enreg;
923         u32 old_val_dam, val_dam;
924         int dcnt = 10;
925         struct tegra30_dam_context *dam = dams_cont_info[ifc];
926
927         if (ifc >= TEGRA30_NR_DAM_IFC)
928                 return;
929
930         if (chid == dam_ch_in0)
931                 enreg = TEGRA30_DAM_CH0_CTRL;
932         else
933                 enreg = TEGRA30_DAM_CH1_CTRL;
934
935         old_val = val = tegra30_dam_readl(dam, enreg);
936
937         if (on) {
938                 if (!dam->ch_enable_refcnt[chid]++)
939                         val |= TEGRA30_DAM_CH0_CTRL_EN;
940         } else if (dam->ch_enable_refcnt[chid]) {
941                 dam->ch_enable_refcnt[chid]--;
942                 if (!dam->ch_enable_refcnt[chid])
943                         val &= ~TEGRA30_DAM_CH0_CTRL_EN;
944         }
945
946         old_val_dam = val_dam = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
947
948         if (dam->ch_enable_refcnt[dam_ch_in0] ||
949                 dam->ch_enable_refcnt[dam_ch_in1])
950                 val_dam |= TEGRA30_DAM_CTRL_DAM_EN;
951         else
952                 val_dam &= ~TEGRA30_DAM_CTRL_DAM_EN;
953
954         if (val != old_val) {
955                 tegra30_dam_writel(dam, val, enreg);
956
957                 if (!on) {
958                         if (chid == dam_ch_in0) {
959                                 while (!tegra30_ahub_dam_ch0_is_empty(ifc)
960                                         && dcnt--)
961                                         udelay(100);
962
963                                 dcnt = 10;
964                         }
965                         else {
966                                 while (!tegra30_ahub_dam_ch1_is_empty(ifc)
967                                         && dcnt--)
968                                         udelay(100);
969
970                                 dcnt = 10;
971                         }
972                 }
973         }
974
975         if (old_val_dam != val_dam) {
976                 tegra30_dam_writel(dam, val_dam, TEGRA30_DAM_CTRL);
977                 if (!on) {
978                         while (!tegra30_ahub_dam_tx_is_empty(ifc) && dcnt--)
979                                 udelay(100);
980
981                         dcnt = 10;
982                 }
983         }
984 }
985
986 void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
987 {
988         u32 val;
989
990         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
991         val &= ~TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK;
992         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
993         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
994 }
995
996 void tegra30_dam_ch1_set_datasync(struct tegra30_dam_context *dam, int datasync)
997 {
998         u32 val;
999
1000         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL);
1001         val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK;
1002         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
1003         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH1_CTRL);
1004 }
1005
1006 void tegra30_dam_enable_clip_counter(struct tegra30_dam_context *dam, int on)
1007 {
1008         u32 val;
1009
1010         val = tegra30_dam_readl(dam, TEGRA30_DAM_CLIP);
1011         val &= ~TEGRA30_DAM_CLIP_COUNTER_ENABLE;
1012         val |= on ?  TEGRA30_DAM_CLIP_COUNTER_ENABLE : 0;
1013         tegra30_dam_writel(dam, val, TEGRA30_DAM_CLIP);
1014 }
1015
1016 static int __devinit tegra30_dam_probe(struct platform_device *pdev)
1017 {
1018         struct resource *res,  *region;
1019         struct tegra30_dam_context *dam;
1020         int ret = 0;
1021 #ifdef CONFIG_PM
1022         int i;
1023 #endif
1024         int clkm_rate;
1025
1026         if ((pdev->id < 0) ||
1027                 (pdev->id >= TEGRA30_NR_DAM_IFC)) {
1028                 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
1029                 return -EINVAL;
1030         }
1031
1032         dams_cont_info[pdev->id] = devm_kzalloc(&pdev->dev,
1033                                         sizeof(struct tegra30_dam_context),
1034                                         GFP_KERNEL);
1035         if (!dams_cont_info[pdev->id]) {
1036                 dev_err(&pdev->dev, "Can't allocate dam context\n");
1037                 ret = -ENOMEM;
1038                 goto exit;
1039         }
1040         dam = dams_cont_info[pdev->id];
1041
1042         dam->dam_clk = clk_get(&pdev->dev, NULL);
1043         if (IS_ERR(dam->dam_clk)) {
1044                 dev_err(&pdev->dev, "Can't retrieve dam clock\n");
1045                 ret = PTR_ERR(dam->dam_clk);
1046                 goto err_free;
1047         }
1048         clkm_rate = clk_get_rate(clk_get_parent(dam->dam_clk));
1049         while (clkm_rate > 13000000)
1050                 clkm_rate >>= 1;
1051
1052         clk_set_rate(dam->dam_clk,clkm_rate);
1053
1054         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1055         if (!res) {
1056                 dev_err(&pdev->dev, "No memory 0 resource\n");
1057                 ret = -ENODEV;
1058                 goto err_clk_put_dam;
1059         }
1060
1061         region = devm_request_mem_region(&pdev->dev, res->start,
1062                         resource_size(res), pdev->name);
1063         if (!region) {
1064                 dev_err(&pdev->dev, "Memory region 0 already claimed\n");
1065                 ret = -EBUSY;
1066                 goto err_clk_put_dam;
1067         }
1068
1069         dam->damregs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
1070         if (!dam->damregs) {
1071                 dev_err(&pdev->dev, "ioremap 0 failed\n");
1072                 ret = -ENOMEM;
1073                 goto err_clk_put_dam;
1074         }
1075
1076 #ifdef CONFIG_PM
1077         /* cache the POR values of DAM regs*/
1078         tegra30_dam_enable_clock(pdev->id);
1079
1080         for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
1081                 if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
1082                         (i == TEGRA30_DAM_CTRL_RSVD_10))
1083                         continue;
1084
1085                         dam->reg_cache[i] =
1086                                 tegra30_dam_readl(dam, i << 2);
1087         }
1088
1089         tegra30_dam_disable_clock(pdev->id);
1090 #endif
1091
1092         platform_set_drvdata(pdev, dam);
1093
1094         tegra30_dam_debug_add(dam, pdev->id);
1095
1096         return 0;
1097
1098 err_clk_put_dam:
1099         clk_put(dam->dam_clk);
1100 err_free:
1101         dams_cont_info[pdev->id] = NULL;
1102 exit:
1103         return ret;
1104 }
1105
1106 static int __devexit tegra30_dam_remove(struct platform_device *pdev)
1107 {
1108         struct tegra30_dam_context *dam;
1109
1110         dam = platform_get_drvdata(pdev);
1111         clk_put(dam->dam_clk);
1112         tegra30_dam_debug_remove(dam);
1113         dams_cont_info[pdev->id] = NULL;
1114
1115         return 0;
1116 }
1117
1118 static struct platform_driver tegra30_dam_driver = {
1119         .probe = tegra30_dam_probe,
1120         .remove = __devexit_p(tegra30_dam_remove),
1121         .driver = {
1122                 .name = DRV_NAME,
1123                 .owner = THIS_MODULE,
1124         },
1125 };
1126
1127 static int __init tegra30_dam_modinit(void)
1128 {
1129         return platform_driver_register(&tegra30_dam_driver);
1130 }
1131 module_init(tegra30_dam_modinit);
1132
1133 static void __exit tegra30_dam_modexit(void)
1134 {
1135         platform_driver_unregister(&tegra30_dam_driver);
1136 }
1137 module_exit(tegra30_dam_modexit);
1138
1139 MODULE_AUTHOR("Nikesh Oswal <noswal@nvidia.com>");
1140 MODULE_DESCRIPTION("Tegra 30 DAM driver");
1141 MODULE_LICENSE("GPL");
1142 MODULE_ALIAS("platform:" DRV_NAME);