asoc: tegra: add power management functionality in t30 drivers
[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  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * version 2 as published by the Free Software Foundation.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19  * 02110-1301 USA
20  *
21  */
22
23 #include <linux/clk.h>
24 #include <linux/module.h>
25 #include <linux/debugfs.h>
26 #include <linux/device.h>
27 #include <linux/platform_device.h>
28 #include <linux/seq_file.h>
29 #include <linux/slab.h>
30 #include <linux/io.h>
31 #include <sound/soc.h>
32 #include "tegra30_dam.h"
33 #include "tegra30_ahub.h"
34
35 #define DRV_NAME "tegra30-dam"
36
37 static struct tegra30_dam_context       *dams_cont_info[TEGRA30_NR_DAM_IFC];
38
39 enum {
40         dam_ch_in0 = 0x0,
41         dam_ch_in1,
42         dam_ch_out,
43         dam_ch_maxnum
44 } tegra30_dam_chtype;
45
46 struct tegra30_dam_src_step_table  step_table[] = {
47         { 8000, 44100, 80 },
48         { 8000, 48000, 0 },
49         { 16000, 44100, 160 },
50         { 16000, 48000, 1 },
51         { 44100, 8000, 441 },
52         { 48000, 8000, 0 },
53         { 44100, 16000, 441 },
54         { 48000, 16000, 0 },
55 };
56
57 static void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
58                 int fsout);
59 static void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam,
60                 int fsin);
61 static int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
62                 int insample, int outsample);
63 static void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step);
64
65 static inline void tegra30_dam_writel(struct tegra30_dam_context *dam,
66                         u32 val, u32 reg)
67 {
68 #ifdef CONFIG_PM
69         dam->reg_cache[reg >> 2] = val;
70 #endif
71         __raw_writel(val, dam->damregs + reg);
72 }
73
74 static inline u32 tegra30_dam_readl(struct tegra30_dam_context *dam, u32 reg)
75 {
76         u32 val = __raw_readl(dam->damregs + reg);
77
78         return val;
79 }
80
81 #ifdef CONFIG_PM
82 int tegra30_dam_resume(int ifc)
83 {
84         int i = 0;
85         struct tegra30_dam_context *dam;
86
87         if (ifc >= TEGRA30_NR_DAM_IFC)
88                 return -EINVAL;
89
90         dam = dams_cont_info[ifc];
91
92         if (dam->in_use) {
93                 tegra30_dam_enable_clock(ifc);
94
95                 for (i = 0; i <= TEGRA30_DAM_CTRL_REGINDEX; i++) {
96                         if ((i == TEGRA30_DAM_CTRL_RSVD_6) ||
97                                 (i == TEGRA30_DAM_CTRL_RSVD_10))
98                                 continue;
99
100                         tegra30_dam_writel(dam, dam->reg_cache[i],
101                                                 (i << 2));
102                 }
103
104                 tegra30_dam_disable_clock(ifc);
105         }
106
107         return 0;
108 }
109 #endif
110
111 void tegra30_dam_disable_clock(int ifc)
112 {
113         struct tegra30_dam_context *dam;
114
115         if (ifc >= TEGRA30_NR_DAM_IFC)
116                 return -EINVAL;
117
118         dam =  dams_cont_info[ifc];
119         clk_disable(dam->dam_clk);
120         tegra30_ahub_disable_clocks();
121 }
122
123 int tegra30_dam_enable_clock(int ifc)
124 {
125         struct tegra30_dam_context *dam;
126
127         if (ifc >= TEGRA30_NR_DAM_IFC)
128                 return -EINVAL;
129
130         dam =  dams_cont_info[ifc];
131         tegra30_ahub_enable_clocks();
132         clk_enable(dam->dam_clk);
133
134         return 0;
135 }
136
137 #ifdef CONFIG_DEBUG_FS
138 static int tegra30_dam_show(struct seq_file *s, void *unused)
139 {
140 #define REG(r) { r, #r }
141         static const struct {
142                 int offset;
143                 const char *name;
144         } regs[] = {
145                 REG(TEGRA30_DAM_CTRL),
146                 REG(TEGRA30_DAM_CLIP),
147                 REG(TEGRA30_DAM_CLIP_THRESHOLD),
148                 REG(TEGRA30_DAM_AUDIOCIF_OUT_CTRL),
149                 REG(TEGRA30_DAM_CH0_CTRL),
150                 REG(TEGRA30_DAM_CH0_CONV),
151                 REG(TEGRA30_DAM_AUDIOCIF_CH0_CTRL),
152                 REG(TEGRA30_DAM_CH1_CTRL),
153                 REG(TEGRA30_DAM_CH1_CONV),
154                 REG(TEGRA30_DAM_AUDIOCIF_CH1_CTRL),
155         };
156 #undef REG
157
158         struct tegra30_dam_context *dam = s->private;
159         int i;
160
161         clk_enable(dam->dam_clk);
162
163         for (i = 0; i < ARRAY_SIZE(regs); i++) {
164                 u32 val = tegra30_dam_readl(dam, regs[i].offset);
165                 seq_printf(s, "%s = %08x\n", regs[i].name, val);
166         }
167
168         clk_disable(dam->dam_clk);
169
170         return 0;
171 }
172
173 static int tegra30_dam_debug_open(struct inode *inode, struct file *file)
174 {
175         return single_open(file, tegra30_dam_show, inode->i_private);
176 }
177
178 static const struct file_operations tegra30_dam_debug_fops = {
179         .open    = tegra30_dam_debug_open,
180         .read    = seq_read,
181         .llseek  = seq_lseek,
182         .release = single_release,
183 };
184
185 static void tegra30_dam_debug_add(struct tegra30_dam_context *dam, int id)
186 {
187         char name[] = DRV_NAME ".0";
188
189         snprintf(name, sizeof(name), DRV_NAME".%1d", id);
190         dam->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
191                         dam, &tegra30_dam_debug_fops);
192 }
193
194 static void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
195 {
196         if (dam->debug)
197                 debugfs_remove(dam->debug);
198 }
199 #else
200 static inline void tegra30_dam_debug_add(struct tegra30_dam_context *dam,
201                                                 int id)
202 {
203 }
204
205 static inline void tegra30_dam_debug_remove(struct tegra30_dam_context *dam)
206 {
207 }
208 #endif
209
210 int tegra30_dam_allocate_controller()
211 {
212         int i = 0;
213         struct tegra30_dam_context *dam = NULL;
214
215         for (i = 0; i < TEGRA30_NR_DAM_IFC; i++) {
216
217                 dam =  dams_cont_info[i];
218
219                 if (!dam->in_use) {
220                         dam->in_use = true;
221                         return i;
222                 }
223         }
224
225         return -ENOENT;
226 }
227
228 int tegra30_dam_allocate_channel(int ifc, int chid)
229 {
230         int i = 0;
231         struct tegra30_dam_context *dam = NULL;
232
233         if (ifc >= TEGRA30_NR_DAM_IFC)
234                 return -EINVAL;
235
236         dam =  dams_cont_info[ifc];
237
238         if (!dam->ch_alloc[chid]) {
239                 dam->ch_alloc[chid] = true;
240                 return 0;
241         }
242
243         return -ENOENT;
244 }
245
246 int tegra30_dam_free_channel(int ifc, int chid)
247 {
248         int i = 0;
249         struct tegra30_dam_context *dam = NULL;
250
251         if (ifc >= TEGRA30_NR_DAM_IFC)
252                 return -EINVAL;
253
254         dam =  dams_cont_info[ifc];
255
256         if (dam->ch_alloc[chid]) {
257                 dam->ch_alloc[chid] = false;
258                 return 0;
259         }
260
261         return -EINVAL;
262 }
263
264 int tegra30_dam_free_controller(int ifc)
265 {
266         struct tegra30_dam_context *dam = NULL;
267
268         if (ifc >= TEGRA30_NR_DAM_IFC)
269                 return -EINVAL;
270
271         dam =  dams_cont_info[ifc];
272
273         if (!dam->ch_alloc[dam_ch_in0] &&
274                 !dam->ch_alloc[dam_ch_in1]) {
275                 dam->in_use = false;
276                 return 0;
277         }
278
279         return -EINVAL;
280 }
281
282 void tegra30_dam_set_samplerate(int ifc, int chid, int samplerate)
283 {
284         struct tegra30_dam_context *dam = dams_cont_info[ifc];
285
286         if (ifc >= TEGRA30_NR_DAM_IFC)
287                 return -EINVAL;
288
289         switch (chid) {
290         case dam_ch_in0:
291                 tegra30_dam_set_input_samplerate(dam, samplerate);
292                 dam->ch_insamplerate[dam_ch_in0] = samplerate;
293                 tegra30_dam_set_step_reset(dam, samplerate, dam->outsamplerate);
294                 break;
295         case dam_ch_in1:
296                 if (samplerate != dam->outsamplerate)
297                         return -EINVAL;
298                 dam->ch_insamplerate[dam_ch_in1] = samplerate;
299                 break;
300         case dam_ch_out:
301                 tegra30_dam_set_output_samplerate(dam, samplerate);
302                 dam->outsamplerate = samplerate;
303                 break;
304         default:
305                 break;
306         }
307 }
308
309 void tegra30_dam_set_output_samplerate(struct tegra30_dam_context *dam,
310                                         int fsout)
311 {
312         u32 val;
313
314         val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
315         val &= ~TEGRA30_DAM_CTRL_FSOUT_MASK;
316
317         switch (fsout) {
318         case TEGRA30_AUDIO_SAMPLERATE_8000:
319                 val |= TEGRA30_DAM_CTRL_FSOUT_FS8;
320                 break;
321         case TEGRA30_AUDIO_SAMPLERATE_16000:
322                 val |= TEGRA30_DAM_CTRL_FSOUT_FS16;
323                 break;
324         case TEGRA30_AUDIO_SAMPLERATE_44100:
325                 val |= TEGRA30_DAM_CTRL_FSOUT_FS44;
326                 break;
327         case TEGRA30_AUDIO_SAMPLERATE_48000:
328                 val |= TEGRA30_DAM_CTRL_FSOUT_FS48;
329                 break;
330         default:
331                 break;
332         }
333
334         tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
335 }
336
337 void tegra30_dam_set_input_samplerate(struct tegra30_dam_context *dam, int fsin)
338 {
339         u32 val;
340
341         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
342         val &= ~TEGRA30_DAM_CH0_CTRL_FSIN_MASK;
343
344         switch (fsin) {
345         case TEGRA30_AUDIO_SAMPLERATE_8000:
346                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS8;
347                 break;
348         case TEGRA30_AUDIO_SAMPLERATE_16000:
349                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS16;
350                 break;
351         case TEGRA30_AUDIO_SAMPLERATE_44100:
352                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS44;
353                 break;
354         case TEGRA30_AUDIO_SAMPLERATE_48000:
355                 val |= TEGRA30_DAM_CH0_CTRL_FSIN_FS48;
356                 break;
357         default:
358                 break;
359         }
360
361         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
362 }
363
364 int tegra30_dam_set_step_reset(struct tegra30_dam_context *dam,
365                 int insample, int outsample)
366 {
367         int step_reset = 0;
368         int i = 0;
369
370         for (i = 0; i < ARRAY_SIZE(step_table); i++) {
371                 if ((insample == step_table[i].insample) &&
372                         (outsample == step_table[i].outsample))
373                         step_reset = step_table[i].stepreset;
374         }
375
376         tegra30_dam_ch0_set_step(dam, step_reset);
377
378         return 0;
379 }
380
381 void tegra30_dam_ch0_set_step(struct tegra30_dam_context *dam, int step)
382 {
383         u32 val;
384
385         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
386         val &= ~TEGRA30_DAM_CH0_CTRL_STEP_MASK;
387         val |= step << TEGRA30_DAM_CH0_CTRL_STEP_SHIFT;
388         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
389 }
390
391 int tegra30_dam_set_gain(int ifc, int chid, int gain)
392 {
393
394         if (ifc >= TEGRA30_NR_DAM_IFC)
395                 return -EINVAL;
396
397         switch (chid) {
398         case dam_ch_in0:
399                 tegra30_dam_writel(dams_cont_info[ifc], gain,
400                         TEGRA30_DAM_CH0_CONV);
401                 break;
402         case dam_ch_in1:
403                 tegra30_dam_writel(dams_cont_info[ifc], gain,
404                         TEGRA30_DAM_CH1_CONV);
405                 break;
406         default:
407                 break;
408         }
409
410         return 0;
411 }
412
413 int tegra30_dam_set_acif(int ifc, int chid, unsigned int audio_channels,
414         unsigned int audio_bits, unsigned int client_channels,
415         unsigned int client_bits)
416 {
417         unsigned int reg;
418         unsigned int value = 0;
419
420         if (ifc >= TEGRA30_NR_DAM_IFC)
421                 return -EINVAL;
422
423         /*ch0 takes input as mono/16bit always*/
424         if ((chid == dam_ch_in0) &&
425                 ((client_channels != 1) || (client_bits != 16)))
426                 return -EINVAL;
427
428         value |= TEGRA30_CIF_MONOCONV_COPY;
429         value |= TEGRA30_CIF_STEREOCONV_CH0;
430         value |= (audio_channels-1)  << TEGRA30_AUDIO_CHANNELS_SHIFT;
431         value |= (((audio_bits>>2)-1)<<TEGRA30_AUDIO_BITS_SHIFT);
432         value |= (client_channels-1)  << TEGRA30_CLIENT_CHANNELS_SHIFT;
433         value |= (((client_bits>>2)-1)<<TEGRA30_CLIENT_BITS_SHIFT);
434
435         switch (chid) {
436         case dam_ch_out:
437                 value |= TEGRA30_CIF_DIRECTION_TX;
438                 reg = TEGRA30_DAM_AUDIOCIF_OUT_CTRL;
439                 break;
440         case dam_ch_in0:
441                 value |= TEGRA30_CIF_DIRECTION_RX;
442                 reg = TEGRA30_DAM_AUDIOCIF_CH0_CTRL;
443                 break;
444         case dam_ch_in1:
445                 value |= TEGRA30_CIF_DIRECTION_RX;
446                 reg = TEGRA30_DAM_AUDIOCIF_CH1_CTRL;
447                 break;
448         }
449
450         tegra30_dam_writel(dams_cont_info[ifc], value, reg);
451
452         return 0;
453 }
454
455 void tegra30_dam_enable(int ifc, int on, int chid)
456 {
457         u32 old_val, val, enreg;
458         struct tegra30_dam_context *dam = dams_cont_info[ifc];
459
460         if (ifc >= TEGRA30_NR_DAM_IFC)
461                 return -EINVAL;
462
463         if (chid == dam_ch_in0)
464                 enreg = TEGRA30_DAM_CH0_CTRL;
465         else
466                 enreg = TEGRA30_DAM_CH1_CTRL;
467
468         old_val = val = tegra30_dam_readl(dam, enreg);
469
470         if (on) {
471                 if (!dam->ch_enable_refcnt[chid]++)
472                         val |= TEGRA30_DAM_CH0_CTRL_EN;
473         } else if (dam->ch_enable_refcnt[chid]) {
474                 dam->ch_enable_refcnt[chid]--;
475                 if (!dam->ch_enable_refcnt[chid])
476                         val &= ~TEGRA30_DAM_CH0_CTRL_EN;
477         }
478
479         if (val != old_val)
480                 tegra30_dam_writel(dam, val, enreg);
481
482         old_val = val = tegra30_dam_readl(dam, TEGRA30_DAM_CTRL);
483
484         if (dam->ch_enable_refcnt[dam_ch_in0] ||
485                 dam->ch_enable_refcnt[dam_ch_in1])
486                 val |= TEGRA30_DAM_CTRL_DAM_EN;
487         else
488                 val &= ~TEGRA30_DAM_CTRL_DAM_EN;
489
490         if (old_val != val)
491                 tegra30_dam_writel(dam, val, TEGRA30_DAM_CTRL);
492 }
493
494 void tegra30_dam_ch0_set_datasync(struct tegra30_dam_context *dam, int datasync)
495 {
496         u32 val;
497
498         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH0_CTRL);
499         val &= ~TEGRA30_DAM_CH0_CTRL_DATA_SYNC_MASK;
500         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
501         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH0_CTRL);
502 }
503
504 void tegra30_dam_ch1_set_datasync(struct tegra30_dam_context *dam, int datasync)
505 {
506         u32 val;
507
508         val = tegra30_dam_readl(dam, TEGRA30_DAM_CH1_CTRL);
509         val &= ~TEGRA30_DAM_CH1_CTRL_DATA_SYNC_MASK;
510         val |= datasync << TEGRA30_DAM_DATA_SYNC_SHIFT;
511         tegra30_dam_writel(dam, val, TEGRA30_DAM_CH1_CTRL);
512 }
513
514 void tegra30_dam_enable_clip_counter(struct tegra30_dam_context *dam, int on)
515 {
516         u32 val;
517
518         val = tegra30_dam_readl(dam, TEGRA30_DAM_CLIP);
519         val &= ~TEGRA30_DAM_CLIP_COUNTER_ENABLE;
520         val |= on ?  TEGRA30_DAM_CLIP_COUNTER_ENABLE : 0;
521         tegra30_dam_writel(dam, val, TEGRA30_DAM_CLIP);
522 }
523
524 static int __devinit tegra30_dam_probe(struct platform_device *pdev)
525 {
526         struct resource *res,  *region;
527         struct tegra30_dam_context *dam;
528         int ret = 0;
529
530         if ((pdev->id < 0) ||
531                 (pdev->id >= TEGRA30_NR_DAM_IFC)) {
532                 dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
533                 return -EINVAL;
534         }
535
536         dams_cont_info[pdev->id] = devm_kzalloc(&pdev->dev,
537                                         sizeof(struct tegra30_dam_context),
538                                         GFP_KERNEL);
539         if (!dams_cont_info[pdev->id]) {
540                 dev_err(&pdev->dev, "Can't allocate dam context\n");
541                 ret = -ENOMEM;
542                 goto exit;
543         }
544         dam = dams_cont_info[pdev->id];
545
546         dam->dam_clk = clk_get(&pdev->dev, NULL);
547         if (IS_ERR(dam->dam_clk)) {
548                 dev_err(&pdev->dev, "Can't retrieve dam clock\n");
549                 ret = PTR_ERR(dam->dam_clk);
550                 goto err_free;
551         }
552
553         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
554         if (!res) {
555                 dev_err(&pdev->dev, "No memory 0 resource\n");
556                 ret = -ENODEV;
557                 goto err_clk_put_dam;
558         }
559
560         region = devm_request_mem_region(&pdev->dev, res->start,
561                         resource_size(res), pdev->name);
562         if (!region) {
563                 dev_err(&pdev->dev, "Memory region 0 already claimed\n");
564                 ret = -EBUSY;
565                 goto err_clk_put_dam;
566         }
567
568         dam->damregs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
569         if (!dam->damregs) {
570                 dev_err(&pdev->dev, "ioremap 0 failed\n");
571                 ret = -ENOMEM;
572                 goto err_clk_put_dam;
573         }
574
575         platform_set_drvdata(pdev, dam);
576
577         tegra30_dam_debug_add(dam, pdev->id);
578
579         return 0;
580
581 err_clk_put_dam:
582         clk_put(dam->dam_clk);
583 err_free:
584         dams_cont_info[pdev->id] = NULL;
585 exit:
586         return ret;
587 }
588
589 static int __devexit tegra30_dam_remove(struct platform_device *pdev)
590 {
591         struct tegra30_dam_context *dam;
592
593         dam = platform_get_drvdata(pdev);
594         clk_put(dam->dam_clk);
595         tegra30_dam_debug_remove(dam);
596         dams_cont_info[pdev->id] = NULL;
597
598         return 0;
599 }
600
601 static struct platform_driver tegra30_dam_driver = {
602         .probe = tegra30_dam_probe,
603         .remove = __devexit_p(tegra30_dam_remove),
604         .driver = {
605                 .name = DRV_NAME,
606                 .owner = THIS_MODULE,
607         },
608 };
609
610 static int __init tegra30_dam_modinit(void)
611 {
612         return platform_driver_register(&tegra30_dam_driver);
613 }
614 module_init(tegra30_dam_modinit);
615
616 static void __exit tegra30_dam_modexit(void)
617 {
618         platform_driver_unregister(&tegra30_dam_driver);
619 }
620 module_exit(tegra30_dam_modexit);
621
622 MODULE_AUTHOR("Nikesh Oswal <noswal@nvidia.com>");
623 MODULE_DESCRIPTION("Tegra 30 DAM driver");
624 MODULE_LICENSE("GPL");
625 MODULE_ALIAS("platform:" DRV_NAME);