asoc:tegra: Support setting bit clock
[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/32bit always*/
680         if ((chid == dam_ch_in0) &&
681                 ((client_channels != 1) || (client_bits != 32)))
682                 return -EINVAL;
683 #else
684         /*ch0 takes input as mono/16bit always*/
685         if ((chid == dam_ch_in0) &&
686                 ((client_channels != 1) || (client_bits != 16)))
687                 return -EINVAL;
688 #endif
689
690         value |= TEGRA30_CIF_MONOCONV_COPY;
691         value |= TEGRA30_CIF_STEREOCONV_CH0;
692         value |= (audio_channels-1)  << TEGRA30_AUDIO_CHANNELS_SHIFT;
693         value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
694         value |= (client_channels-1)  << TEGRA30_CLIENT_CHANNELS_SHIFT;
695         value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
696
697         switch (chid) {
698         case dam_ch_out:
699                 value |= TEGRA30_CIF_DIRECTION_TX;
700                 reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
701                 break;
702         case dam_ch_in0:
703                 value |= TEGRA30_CIF_DIRECTION_RX;
704                 reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
705                 break;
706         case dam_ch_in1:
707                 value |= TEGRA30_CIF_DIRECTION_RX;
708                 reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
709                 break;
710         default:
711                 return -EINVAL;
712         }
713
714         tegra30_dam_writel(dams_cont_info[ifc], value, reg);
715
716         return 0;
717 }
718
719 #ifndef CONFIG_ARCH_TEGRA_3x_SOC
720 void tegra30_dam_write_coeff_ram(int ifc, int fsin, int fsout)
721 {
722         u32 val;
723         int i, *coefRam = NULL;
724
725         if (ifc >= TEGRA30_NR_DAM_IFC)
726                 return;
727
728         tegra30_dam_writel(dams_cont_info[ifc], 0x00002000,
729                         TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
730
731         switch(fsin) {
732                 case TEGRA30_AUDIO_SAMPLERATE_8000:
733                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
734                                 coefRam = coefRam8To48;
735                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
736                                 coefRam = coefRam8To44;
737                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
738                                 coefRam = coefRam8To16;
739                         break;
740
741                 case TEGRA30_AUDIO_SAMPLERATE_16000:
742                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
743                                 coefRam = coefRam16To48;
744                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
745                                 coefRam = coefRam16To44;
746                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
747                                 coefRam = coefRam16To8;
748                         break;
749
750                 case TEGRA30_AUDIO_SAMPLERATE_44100:
751                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
752                                 coefRam = coefRam44To8;
753                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
754                                 coefRam = coefRam44To16;
755                         break;
756
757                 case TEGRA30_AUDIO_SAMPLERATE_48000:
758                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
759                                 coefRam = coefRam48To8;
760                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
761                                 coefRam = coefRam48To16;
762                         break;
763
764                 default:
765                         break;
766         }
767
768         tegra30_dam_writel(dams_cont_info[ifc], 0x00005000,
769                         TEGRA30_DAM_AUDIORAMCTL_DAM_CTRL_0);
770
771         for (i = 0; i < 64; i++) {
772                 val = coefRam[i];\r
773                 tegra30_dam_writel(dams_cont_info[ifc], val,
774                                 TEGRA30_DAM_AUDIORAMCTL_DAM_DATA_0);
775         }
776 }
777
778 void tegra30_dam_set_farrow_param(int ifc, int fsin, int fsout)
779 {
780         u32 val = TEGRA30_FARROW_PARAM_RESET;
781
782         if (ifc >= TEGRA30_NR_DAM_IFC)
783                 return;
784
785         switch(fsin) {
786                 case TEGRA30_AUDIO_SAMPLERATE_8000:
787                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
788                                 val = TEGRA30_FARROW_PARAM_1;
789                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
790                                 val = TEGRA30_FARROW_PARAM_2;
791                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
792                                 val = TEGRA30_FARROW_PARAM_1;
793                         break;
794
795                 case TEGRA30_AUDIO_SAMPLERATE_16000:
796                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
797                                 val = TEGRA30_FARROW_PARAM_1;
798                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
799                                 val = TEGRA30_FARROW_PARAM_2;
800                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
801                                 val = TEGRA30_FARROW_PARAM_1;
802                         break;
803
804                 case TEGRA30_AUDIO_SAMPLERATE_44100:
805                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
806                                 val = TEGRA30_FARROW_PARAM_3;
807                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
808                                 val = TEGRA30_FARROW_PARAM_3;
809                         break;
810
811                 case TEGRA30_AUDIO_SAMPLERATE_48000:
812                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
813                                 val = TEGRA30_FARROW_PARAM_1;
814                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
815                                 val = TEGRA30_FARROW_PARAM_1;
816                         break;
817
818                 default:
819                         break;
820         }
821
822         tegra30_dam_writel(dams_cont_info[ifc], val,
823                         TEGRA30_DAM_FARROW_PARAM_0);
824 }
825
826 void tegra30_dam_set_biquad_fixed_coef(int ifc)
827 {
828         u32 val = TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0_VAL;
829
830         if (ifc >= TEGRA30_NR_DAM_IFC)
831                 return;
832
833         tegra30_dam_writel(dams_cont_info[ifc], val,
834                         TEGRA30_DAM_CH0_BIQUAD_FIXED_COEF_0);
835 }
836
837 void tegra30_dam_enable_coeff_ram(int ifc)
838 {
839         u32 val;
840
841         if (ifc >= TEGRA30_NR_DAM_IFC)
842                 return;
843
844         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
845         val |= TEGRA30_DAM_CH0_CTRL_COEFF_RAM_ENABLE;
846
847         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
848 }
849
850 void tegra30_dam_set_filter_stages(int ifc, int fsin, int fsout)
851 {
852         u32 val;
853         int filt_stages = 0;
854
855         if (ifc >= TEGRA30_NR_DAM_IFC)
856                 return;
857
858         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CH0_CTRL);
859
860         switch(fsin) {
861                 case TEGRA30_AUDIO_SAMPLERATE_8000:
862                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
863                                 filt_stages = 1;
864                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
865                                 filt_stages = 2;
866                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
867                                 filt_stages = 0;
868                         break;
869
870                 case TEGRA30_AUDIO_SAMPLERATE_16000:
871                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_48000)
872                                 filt_stages = 0;
873                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_44100)
874                                 filt_stages = 3;
875                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
876                                 filt_stages = 0;
877                         break;
878
879                 case TEGRA30_AUDIO_SAMPLERATE_44100:
880                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
881                                 filt_stages = 2;
882                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
883                                 filt_stages = 2;
884                         break;
885
886                 case TEGRA30_AUDIO_SAMPLERATE_48000:
887                         if (fsout == TEGRA30_AUDIO_SAMPLERATE_8000)
888                                 filt_stages = 1;
889                         else if (fsout == TEGRA30_AUDIO_SAMPLERATE_16000)
890                                 filt_stages = 0;
891                         break;
892
893                 default:
894                         break;
895         }
896
897         val |= filt_stages << TEGRA30_DAM_CH0_CTRL_FILT_STAGES_SHIFT;
898
899         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CH0_CTRL);
900 }
901
902 void tegra30_dam_enable_stereo_mixing(int ifc)
903 {
904         u32 val;
905
906         if (ifc >= TEGRA30_NR_DAM_IFC)
907                 return;
908
909         val = tegra30_dam_readl(dams_cont_info[ifc], TEGRA30_DAM_CTRL);
910         val |= TEGRA30_DAM_CTRL_STEREO_MIXING_ENABLE;
911
912         tegra30_dam_writel(dams_cont_info[ifc], val, TEGRA30_DAM_CTRL);
913 }
914 #endif
915
916 void tegra30_dam_enable(int ifc, int on, int chid)
917 {
918         u32 old_val, val, enreg;
919         u32 old_val_dam, val_dam;
920         int dcnt = 10;
921         struct tegra30_dam_context *dam = dams_cont_info[ifc];
922
923         if (ifc >= TEGRA30_NR_DAM_IFC)
924                 return;
925
926         if (chid == dam_ch_in0)
927                 enreg = TEGRA30_DAM_CH0_CTRL;
928         else
929                 enreg = TEGRA30_DAM_CH1_CTRL;
930
931         old_val = val = tegra30_dam_readl(dam, enreg);
932
933         if (on) {
934                 if (!dam->ch_enable_refcnt[chid]++)
935                         val |= TEGRA30_DAM_CH0_CTRL_EN;
936         } else if (dam->ch_enable_refcnt[chid]) {
937                 dam->ch_enable_refcnt[chid]--;
938                 if (!dam->ch_enable_refcnt[chid])
939                         val &= ~TEGRA30_DAM_CH0_CTRL_EN;
940         }
941
942         old_val_dam = val_dam = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
943
944         if (dam->ch_enable_refcnt[dam_ch_in0] ||
945                 dam->ch_enable_refcnt[dam_ch_in1])
946                 val_dam |= TEGRA30_DAM_CTRL_DAM_EN;
947         else
948                 val_dam &= ~TEGRA30_DAM_CTRL_DAM_EN;
949
950         if (val != old_val) {
951                 tegra30_dam_writel(dam, val, enreg);
952
953                 if (!on) {
954                         if (chid == dam_ch_in0) {
955                                 while (!tegra30_ahub_dam_ch0_is_empty(ifc)
956                                         && dcnt--)
957                                         udelay(100);
958
959                                 dcnt = 10;
960                         }
961                         else {
962                                 while (!tegra30_ahub_dam_ch1_is_empty(ifc)
963                                         && dcnt--)
964                                         udelay(100);
965
966                                 dcnt = 10;
967                         }
968                 }
969         }
970
971         if (old_val_dam != val_dam) {
972                 tegra30_dam_writel(dam, val_dam, TEGRA30_DAM_CTRL);
973                 if (!on) {
974                         while (!tegra30_ahub_dam_tx_is_empty(ifc) && dcnt--)
975                                 udelay(100);
976
977                         dcnt = 10;
978                 }
979         }
980 }
981
982 void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
983 {
984         u32 val;
985
986         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
987         val &= ~TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK;
988         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
989         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
990 }
991
992 void tegra30_dam_ch1_set_datasync(struct tegra30_dam_context *dam, int datasync)
993 {
994         u32 val;
995
996         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL);
997         val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK;
998         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
999         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH1_CTRL);
1000 }
1001
1002 void tegra30_dam_enable_clip_counter(struct tegra30_dam_context *dam, int on)
1003 {
1004         u32 val;
1005
1006         val = tegra30_dam_readl(dam, TEGRA30_DAM_CLIP);
1007         val &= ~TEGRA30_DAM_CLIP_COUNTER_ENABLE;
1008         val |= on ?  TEGRA30_DAM_CLIP_COUNTER_ENABLE : 0;
1009         tegra30_dam_writel(dam, val, TEGRA30_DAM_CLIP);
1010 }
1011
1012 static int __devinit tegra30_dam_probe(struct platform_device *pdev)
1013 {
1014         struct resource *res,  *region;
1015         struct tegra30_dam_context *dam;
1016         int ret = 0;
1017 #ifdef CONFIG_PM
1018         int i;
1019 #endif
1020         int clkm_rate;
1021
1022         if ((pdev->id < 0) ||
1023                 (pdev->id >= TEGRA30_NR_DAM_IFC)) {
1024                 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
1025                 return -EINVAL;
1026         }
1027
1028         dams_cont_info[pdev->id] = devm_kzalloc(&pdev->dev,
1029                                         sizeof(struct tegra30_dam_context),
1030                                         GFP_KERNEL);
1031         if (!dams_cont_info[pdev->id]) {
1032                 dev_err(&pdev->dev, "Can't allocate dam context\n");
1033                 ret = -ENOMEM;
1034                 goto exit;
1035         }
1036         dam = dams_cont_info[pdev->id];
1037
1038         dam->dam_clk = clk_get(&pdev->dev, NULL);
1039         if (IS_ERR(dam->dam_clk)) {
1040                 dev_err(&pdev->dev, "Can't retrieve dam clock\n");
1041                 ret = PTR_ERR(dam->dam_clk);
1042                 goto err_free;
1043         }
1044         clkm_rate = clk_get_rate(clk_get_parent(dam->dam_clk));
1045         while (clkm_rate > 13000000)
1046                 clkm_rate >>= 1;
1047
1048         clk_set_rate(dam->dam_clk,clkm_rate);
1049
1050         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1051         if (!res) {
1052                 dev_err(&pdev->dev, "No memory 0 resource\n");
1053                 ret = -ENODEV;
1054                 goto err_clk_put_dam;
1055         }
1056
1057         region = devm_request_mem_region(&pdev->dev, res->start,
1058                         resource_size(res), pdev->name);
1059         if (!region) {
1060                 dev_err(&pdev->dev, "Memory region 0 already claimed\n");
1061                 ret = -EBUSY;
1062                 goto err_clk_put_dam;
1063         }
1064
1065         dam->damregs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
1066         if (!dam->damregs) {
1067                 dev_err(&pdev->dev, "ioremap 0 failed\n");
1068                 ret = -ENOMEM;
1069                 goto err_clk_put_dam;
1070         }
1071
1072 #ifdef CONFIG_PM
1073         /* cache the POR values of DAM regs*/
1074         tegra30_dam_enable_clock(pdev->id);
1075
1076         for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
1077                 if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
1078                         (i == TEGRA30_DAM_CTRL_RSVD_10))
1079                         continue;
1080
1081                         dam->reg_cache[i] =
1082                                 tegra30_dam_readl(dam, i << 2);
1083         }
1084
1085         tegra30_dam_disable_clock(pdev->id);
1086 #endif
1087
1088         platform_set_drvdata(pdev, dam);
1089
1090         tegra30_dam_debug_add(dam, pdev->id);
1091
1092         return 0;
1093
1094 err_clk_put_dam:
1095         clk_put(dam->dam_clk);
1096 err_free:
1097         dams_cont_info[pdev->id] = NULL;
1098 exit:
1099         return ret;
1100 }
1101
1102 static int __devexit tegra30_dam_remove(struct platform_device *pdev)
1103 {
1104         struct tegra30_dam_context *dam;
1105
1106         dam = platform_get_drvdata(pdev);
1107         clk_put(dam->dam_clk);
1108         tegra30_dam_debug_remove(dam);
1109         dams_cont_info[pdev->id] = NULL;
1110
1111         return 0;
1112 }
1113
1114 static struct platform_driver tegra30_dam_driver = {
1115         .probe = tegra30_dam_probe,
1116         .remove = __devexit_p(tegra30_dam_remove),
1117         .driver = {
1118                 .name = DRV_NAME,
1119                 .owner = THIS_MODULE,
1120         },
1121 };
1122
1123 static int __init tegra30_dam_modinit(void)
1124 {
1125         return platform_driver_register(&tegra30_dam_driver);
1126 }
1127 module_init(tegra30_dam_modinit);
1128
1129 static void __exit tegra30_dam_modexit(void)
1130 {
1131         platform_driver_unregister(&tegra30_dam_driver);
1132 }
1133 module_exit(tegra30_dam_modexit);
1134
1135 MODULE_AUTHOR("Nikesh Oswal <noswal@nvidia.com>");
1136 MODULE_DESCRIPTION("Tegra 30 DAM driver");
1137 MODULE_LICENSE("GPL");
1138 MODULE_ALIAS("platform:" DRV_NAME);