asoc: tegra: Add PCM driver for TDM mode
[linux-2.6.git] / sound / soc / tegra / tegra30_spdif.c
1 /*
2  * tegra30_spdif.c - Tegra30 SPDIF driver
3  *
4  * Author: Sumit Bhattacharya <sumitb@nvidia.com>
5  * Copyright (C) 2011 - NVIDIA, Inc.
6  *
7  * Based on code copyright/by:
8  *
9  * Copyright (c) 2009-2011, NVIDIA Corporation.
10  * Scott Peterson <speterson@nvidia.com>
11  *
12  * Copyright (C) 2010 Google, Inc.
13  * Iliyan Malchev <malchev@google.com>
14  *
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * version 2 as published by the Free Software Foundation.
18  *
19  * This program is distributed in the hope that it will be useful, but
20  * WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27  * 02110-1301 USA
28  *
29  */
30
31 #include <linux/clk.h>
32 #include <linux/module.h>
33 #include <linux/debugfs.h>
34 #include <linux/device.h>
35 #include <linux/platform_device.h>
36 #include <linux/seq_file.h>
37 #include <linux/slab.h>
38 #include <linux/io.h>
39 #include <mach/iomap.h>
40 #include <mach/hdmi-audio.h>
41 #include <sound/core.h>
42 #include <sound/pcm.h>
43 #include <sound/pcm_params.h>
44 #include <sound/soc.h>
45
46 #include "tegra30_spdif.h"
47
48 #define DRV_NAME "tegra30-spdif"
49
50 static inline void tegra30_spdif_write(struct tegra30_spdif *spdif,
51                                                 u32 reg, u32 val)
52 {
53         __raw_writel(val, spdif->regs + reg);
54 }
55
56 static inline u32 tegra30_spdif_read(struct tegra30_spdif *spdif, u32 reg)
57 {
58         return __raw_readl(spdif->regs + reg);
59 }
60
61 static void tegra30_spdif_enable_clocks(struct tegra30_spdif *spdif)
62 {
63         clk_enable(spdif->clk_spdif_out);
64         tegra30_ahub_enable_clocks();
65 }
66
67 static void tegra30_spdif_disable_clocks(struct tegra30_spdif *spdif)
68 {
69         tegra30_ahub_disable_clocks();
70         clk_disable(spdif->clk_spdif_out);
71 }
72
73 #ifdef CONFIG_DEBUG_FS
74 static int tegra30_spdif_show(struct seq_file *s, void *unused)
75 {
76 #define REG(r) { r, #r }
77         static const struct {
78                 int offset;
79                 const char *name;
80         } regs[] = {
81                 REG(TEGRA30_SPDIF_CTRL),
82                 REG(TEGRA30_SPDIF_STROBE_CTRL),
83                 REG(TEGRA30_SPDIF_CIF_TXD_CTRL),
84                 REG(TEGRA30_SPDIF_CIF_RXD_CTRL),
85                 REG(TEGRA30_SPDIF_CIF_TXU_CTRL),
86                 REG(TEGRA30_SPDIF_CIF_RXU_CTRL),
87                 REG(TEGRA30_SPDIF_CH_STA_RX_A),
88                 REG(TEGRA30_SPDIF_CH_STA_RX_B),
89                 REG(TEGRA30_SPDIF_CH_STA_RX_C),
90                 REG(TEGRA30_SPDIF_CH_STA_RX_D),
91                 REG(TEGRA30_SPDIF_CH_STA_RX_E),
92                 REG(TEGRA30_SPDIF_CH_STA_RX_F),
93                 REG(TEGRA30_SPDIF_CH_STA_TX_A),
94                 REG(TEGRA30_SPDIF_CH_STA_TX_B),
95                 REG(TEGRA30_SPDIF_CH_STA_TX_C),
96                 REG(TEGRA30_SPDIF_CH_STA_TX_D),
97                 REG(TEGRA30_SPDIF_CH_STA_TX_E),
98                 REG(TEGRA30_SPDIF_CH_STA_TX_F),
99                 REG(TEGRA30_SPDIF_FLOWCTL_CTRL),
100                 REG(TEGRA30_SPDIF_TX_STEP),
101                 REG(TEGRA30_SPDIF_FLOW_STATUS),
102                 REG(TEGRA30_SPDIF_FLOW_TOTAL),
103                 REG(TEGRA30_SPDIF_FLOW_OVER),
104                 REG(TEGRA30_SPDIF_FLOW_UNDER),
105                 REG(TEGRA30_SPDIF_LCOEF_1_4_0),
106                 REG(TEGRA30_SPDIF_LCOEF_1_4_1),
107                 REG(TEGRA30_SPDIF_LCOEF_1_4_2),
108                 REG(TEGRA30_SPDIF_LCOEF_1_4_3),
109                 REG(TEGRA30_SPDIF_LCOEF_1_4_4),
110                 REG(TEGRA30_SPDIF_LCOEF_1_4_5),
111                 REG(TEGRA30_SPDIF_LCOEF_2_4_0),
112                 REG(TEGRA30_SPDIF_LCOEF_2_4_1),
113                 REG(TEGRA30_SPDIF_LCOEF_2_4_2),
114         };
115 #undef REG
116
117         struct tegra30_spdif *spdif = s->private;
118         int i;
119
120         tegra30_spdif_enable_clocks(spdif);
121
122         for (i = 0; i < ARRAY_SIZE(regs); i++) {
123                 u32 val = tegra30_spdif_read(spdif, regs[i].offset);
124                 seq_printf(s, "%s = %08x\n", regs[i].name, val);
125         }
126
127         tegra30_spdif_disable_clocks(spdif);
128
129         return 0;
130 }
131
132 static int tegra30_spdif_debug_open(struct inode *inode, struct file *file)
133 {
134         return single_open(file, tegra30_spdif_show, inode->i_private);
135 }
136
137 static const struct file_operations tegra30_spdif_debug_fops = {
138         .open    = tegra30_spdif_debug_open,
139         .read    = seq_read,
140         .llseek  = seq_lseek,
141         .release = single_release,
142 };
143
144 static void tegra30_spdif_debug_add(struct tegra30_spdif *spdif)
145 {
146         char name[] = DRV_NAME;
147
148         spdif->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
149                                         spdif, &tegra30_spdif_debug_fops);
150 }
151
152 static void tegra30_spdif_debug_remove(struct tegra30_spdif *spdif)
153 {
154         if (spdif->debug)
155                 debugfs_remove(spdif->debug);
156 }
157 #else
158 static inline void tegra30_spdif_debug_add(struct tegra30_spdif *spdif)
159 {
160 }
161
162 static inline void tegra30_spdif_debug_remove(struct tegra30_spdif *spdif)
163 {
164 }
165 #endif
166
167 int tegra30_spdif_startup(struct snd_pcm_substream *substream,
168                         struct snd_soc_dai *dai)
169 {
170         struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
171         int ret = 0;
172
173         tegra30_spdif_enable_clocks(spdif);
174
175         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
176                 ret = tegra30_ahub_allocate_tx_fifo(&spdif->txcif,
177                                         &spdif->playback_dma_data.addr,
178                                         &spdif->playback_dma_data.req_sel);
179                 spdif->playback_dma_data.wrap = 4;
180                 spdif->playback_dma_data.width = 32;
181                 tegra30_ahub_set_rx_cif_source(TEGRA30_AHUB_RXCIF_SPDIF_RX0,
182                                                spdif->txcif);
183         }
184
185         tegra30_spdif_disable_clocks(spdif);
186
187         return ret;
188 }
189
190 void tegra30_spdif_shutdown(struct snd_pcm_substream *substream,
191                         struct snd_soc_dai *dai)
192 {
193         struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
194
195         tegra30_spdif_enable_clocks(spdif);
196
197         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
198                 tegra30_ahub_unset_rx_cif_source(TEGRA30_AHUB_RXCIF_SPDIF_RX0);
199                 tegra30_ahub_free_tx_fifo(spdif->txcif);
200         }
201
202         tegra30_spdif_disable_clocks(spdif);
203 }
204
205 static int tegra30_spdif_hw_params(struct snd_pcm_substream *substream,
206                                 struct snd_pcm_hw_params *params,
207                                 struct snd_soc_dai *dai)
208 {
209         struct device *dev = substream->pcm->card->dev;
210         struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
211         int ret, srate, spdifclock;
212
213         if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK) {
214                 dev_err(dev, "spdif capture is not supported\n");
215                 return -EINVAL;
216         }
217
218         spdif->reg_ctrl &= ~TEGRA30_SPDIF_CTRL_BIT_MODE_MASK;
219         switch (params_format(params)) {
220         case SNDRV_PCM_FORMAT_S16_LE:
221                 spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_PACK_ENABLE;
222                 spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_BIT_MODE_16BIT;
223                 break;
224         default:
225                 return -EINVAL;
226         }
227
228         srate = params_rate(params);
229         spdif->reg_ch_sta_a &= ~TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_MASK;
230         spdif->reg_ch_sta_b &= ~TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_MASK;
231         switch (srate) {
232         case 32000:
233                 spdifclock = 4096000;
234                 spdif->reg_ch_sta_a |=
235                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_32000;
236                 spdif->reg_ch_sta_b |=
237                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_32000;
238                 break;
239         case 44100:
240                 spdifclock = 5644800;
241                 spdif->reg_ch_sta_a |=
242                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_44100;
243                 spdif->reg_ch_sta_b |=
244                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_44100;
245                 break;
246         case 48000:
247                 spdifclock = 6144000;
248                 spdif->reg_ch_sta_a |=
249                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_48000;
250                 spdif->reg_ch_sta_b |=
251                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_48000;
252                 break;
253         case 88200:
254                 spdifclock = 11289600;
255                 spdif->reg_ch_sta_a |=
256                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_88200;
257                 spdif->reg_ch_sta_b |=
258                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_88200;
259                 break;
260         case 96000:
261                 spdifclock = 12288000;
262                 spdif->reg_ch_sta_a |=
263                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_96000;
264                 spdif->reg_ch_sta_b |=
265                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_96000;
266                 break;
267         case 176400:
268                 spdifclock = 22579200;
269                 spdif->reg_ch_sta_a |=
270                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_176400;
271                 spdif->reg_ch_sta_b |=
272                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_176400;
273                 break;
274         case 192000:
275                 spdifclock = 24576000;
276                 spdif->reg_ch_sta_a |=
277                         TEGRA30_SPDIF_CH_STA_TX_A_SAMP_FREQ_192000;
278                 spdif->reg_ch_sta_b |=
279                         TEGRA30_SPDIF_CH_STA_TX_B_ORIG_SAMP_FREQ_192000;
280                 break;
281         default:
282                 return -EINVAL;
283         }
284
285         ret = clk_set_rate(spdif->clk_spdif_out, spdifclock);
286         if (ret) {
287                 dev_err(dev, "Can't set SPDIF clock rate: %d\n", ret);
288                 return ret;
289         }
290
291         tegra30_spdif_enable_clocks(spdif);
292
293         tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_A,
294                                                 spdif->reg_ch_sta_a);
295         tegra30_spdif_write(spdif, TEGRA30_SPDIF_CH_STA_TX_B,
296                                                 spdif->reg_ch_sta_b);
297
298         tegra30_spdif_disable_clocks(spdif);
299
300         ret = tegra_hdmi_setup_audio_freq_source(srate, SPDIF);
301         if (ret) {
302                 dev_err(dev, "Can't set HDMI audio freq source: %d\n", ret);
303                 return ret;
304         }
305
306         return 0;
307 }
308
309 static void tegra30_spdif_start_playback(struct tegra30_spdif *spdif)
310 {
311         tegra30_ahub_enable_tx_fifo(spdif->txcif);
312         spdif->reg_ctrl |= TEGRA30_SPDIF_CTRL_TX_EN_ENABLE |
313                                 TEGRA30_SPDIF_CTRL_TC_EN_ENABLE;
314         tegra30_spdif_write(spdif, TEGRA30_SPDIF_CTRL, spdif->reg_ctrl);
315 }
316
317 static void tegra30_spdif_stop_playback(struct tegra30_spdif *spdif)
318 {
319         tegra30_ahub_disable_tx_fifo(spdif->txcif);
320         spdif->reg_ctrl &= ~(TEGRA30_SPDIF_CTRL_TX_EN_ENABLE |
321                                 TEGRA30_SPDIF_CTRL_TC_EN_ENABLE);
322         tegra30_spdif_write(spdif, TEGRA30_SPDIF_CTRL, spdif->reg_ctrl);
323 }
324
325 static int tegra30_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
326                                 struct snd_soc_dai *dai)
327 {
328         struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
329
330         switch (cmd) {
331         case SNDRV_PCM_TRIGGER_START:
332         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
333         case SNDRV_PCM_TRIGGER_RESUME:
334                 tegra30_spdif_enable_clocks(spdif);
335                 tegra30_spdif_start_playback(spdif);
336                 break;
337         case SNDRV_PCM_TRIGGER_STOP:
338         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
339         case SNDRV_PCM_TRIGGER_SUSPEND:
340                 tegra30_spdif_stop_playback(spdif);
341                 tegra30_spdif_disable_clocks(spdif);
342                 break;
343         default:
344                 return -EINVAL;
345         }
346
347         return 0;
348 }
349
350 static int tegra30_spdif_probe(struct snd_soc_dai *dai)
351 {
352         struct tegra30_spdif *spdif = snd_soc_dai_get_drvdata(dai);
353
354         dai->playback_dma_data = &spdif->playback_dma_data;
355         dai->capture_dma_data = NULL;
356
357         return 0;
358 }
359
360 static struct snd_soc_dai_ops tegra30_spdif_dai_ops = {
361         .startup        = tegra30_spdif_startup,
362         .shutdown       = tegra30_spdif_shutdown,
363         .hw_params      = tegra30_spdif_hw_params,
364         .trigger        = tegra30_spdif_trigger,
365 };
366
367 struct snd_soc_dai_driver tegra30_spdif_dai = {
368         .name = DRV_NAME,
369         .probe = tegra30_spdif_probe,
370         .playback = {
371                 .channels_min = 2,
372                 .channels_max = 2,
373                 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
374                                 SNDRV_PCM_RATE_48000,
375                 .formats = SNDRV_PCM_FMTBIT_S16_LE,
376         },
377         .ops = &tegra30_spdif_dai_ops,
378 };
379
380 static __devinit int tegra30_spdif_platform_probe(struct platform_device *pdev)
381 {
382         struct tegra30_spdif *spdif;
383         struct resource *mem, *memregion;
384         int ret;
385         u32 reg_val;
386
387         spdif = kzalloc(sizeof(struct tegra30_spdif), GFP_KERNEL);
388         if (!spdif) {
389                 dev_err(&pdev->dev, "Can't allocate tegra30_spdif\n");
390                 ret = -ENOMEM;
391                 goto exit;
392         }
393         dev_set_drvdata(&pdev->dev, spdif);
394
395         spdif->clk_spdif_out = clk_get(&pdev->dev, "spdif_out");
396         if (IS_ERR(spdif->clk_spdif_out)) {
397                 dev_err(&pdev->dev, "Can't retrieve spdif clock\n");
398                 ret = PTR_ERR(spdif->clk_spdif_out);
399                 goto err_free;
400         }
401
402         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
403         if (!mem) {
404                 dev_err(&pdev->dev, "No memory resource\n");
405                 ret = -ENODEV;
406                 goto err_clk_put_spdif;
407         }
408
409         memregion = request_mem_region(mem->start, resource_size(mem),
410                                         DRV_NAME);
411         if (!memregion) {
412                 dev_err(&pdev->dev, "Memory region already claimed\n");
413                 ret = -EBUSY;
414                 goto err_clk_put_spdif;
415         }
416
417         spdif->regs = ioremap(mem->start, resource_size(mem));
418         if (!spdif->regs) {
419                 dev_err(&pdev->dev, "ioremap failed\n");
420                 ret = -ENOMEM;
421                 goto err_release;
422         }
423
424         tegra30_spdif_enable_clocks(spdif);
425
426         reg_val = TEGRA30_SPDIF_CIF_TXD_CTRL_DIRECTION_RXCIF |
427                 TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_BIT16 |
428                 TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_BIT16 |
429                 TEGRA30_SPDIF_CIF_TXD_CTRL_AUDIO_CH2 |
430                 TEGRA30_SPDIF_CIF_TXD_CTRL_CLIENT_CH2 |
431                 (3 << TEGRA30_SPDIF_CIF_TXD_CTRL_FIFO_TH_SHIFT);
432
433         tegra30_spdif_write(spdif, TEGRA30_SPDIF_CIF_TXD_CTRL, reg_val);
434
435         tegra30_spdif_disable_clocks(spdif);
436
437         ret = snd_soc_register_dai(&pdev->dev, &tegra30_spdif_dai);
438         if (ret) {
439                 dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
440                 ret = -ENOMEM;
441                 goto err_unmap;
442         }
443
444         tegra30_spdif_debug_add(spdif);
445
446         return 0;
447
448 err_unmap:
449         iounmap(spdif->regs);
450 err_release:
451         release_mem_region(mem->start, resource_size(mem));
452 err_clk_put_spdif:
453         clk_put(spdif->clk_spdif_out);
454 err_free:
455         kfree(spdif);
456 exit:
457         return ret;
458 }
459
460 static int __devexit tegra30_spdif_platform_remove(struct platform_device *pdev)
461 {
462         struct tegra30_spdif *spdif = dev_get_drvdata(&pdev->dev);
463         struct resource *res;
464
465         snd_soc_unregister_dai(&pdev->dev);
466
467         tegra30_spdif_debug_remove(spdif);
468
469         iounmap(spdif->regs);
470
471         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
472         release_mem_region(res->start, resource_size(res));
473
474         clk_put(spdif->clk_spdif_out);
475
476         kfree(spdif);
477
478         return 0;
479 }
480
481 static struct platform_driver tegra30_spdif_driver = {
482         .driver = {
483                 .name = DRV_NAME,
484                 .owner = THIS_MODULE,
485         },
486         .probe = tegra30_spdif_platform_probe,
487         .remove = __devexit_p(tegra30_spdif_platform_remove),
488 };
489
490 static int __init snd_tegra30_spdif_init(void)
491 {
492         return platform_driver_register(&tegra30_spdif_driver);
493 }
494 module_init(snd_tegra30_spdif_init);
495
496 static void __exit snd_tegra30_spdif_exit(void)
497 {
498         platform_driver_unregister(&tegra30_spdif_driver);
499 }
500 module_exit(snd_tegra30_spdif_exit);
501
502 MODULE_AUTHOR("Sumit Bhattacharya <sumitb@nvidia.com>");
503 MODULE_DESCRIPTION("Tegra30 SPDIF ASoC driver");
504 MODULE_LICENSE("GPL");
505 MODULE_ALIAS("platform:" DRV_NAME);