faa65afb6951a10c1fc0fee29452d243654ad7ac
[firefly-linux-kernel-4.4.55.git] / sound / soc / fsl / fsl_sai.c
1 /*
2  * Freescale ALSA SoC Digital Audio Interface (SAI) driver.
3  *
4  * Copyright 2012-2013 Freescale Semiconductor, Inc.
5  *
6  * This program is free software, you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation, either version 2 of the License, or(at your
9  * option) any later version.
10  *
11  */
12
13 #include <linux/clk.h>
14 #include <linux/delay.h>
15 #include <linux/dmaengine.h>
16 #include <linux/module.h>
17 #include <linux/of_address.h>
18 #include <linux/regmap.h>
19 #include <linux/slab.h>
20 #include <sound/core.h>
21 #include <sound/dmaengine_pcm.h>
22 #include <sound/pcm_params.h>
23
24 #include "fsl_sai.h"
25
26 static int fsl_sai_set_dai_sysclk_tr(struct snd_soc_dai *cpu_dai,
27                 int clk_id, unsigned int freq, int fsl_dir)
28 {
29         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
30         u32 val_cr2, reg_cr2;
31
32         if (fsl_dir == FSL_FMT_TRANSMITTER)
33                 reg_cr2 = FSL_SAI_TCR2;
34         else
35                 reg_cr2 = FSL_SAI_RCR2;
36
37         regmap_read(sai->regmap, reg_cr2, &val_cr2);
38
39         val_cr2 &= ~FSL_SAI_CR2_MSEL_MASK;
40
41         switch (clk_id) {
42         case FSL_SAI_CLK_BUS:
43                 val_cr2 |= FSL_SAI_CR2_MSEL_BUS;
44                 break;
45         case FSL_SAI_CLK_MAST1:
46                 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK1;
47                 break;
48         case FSL_SAI_CLK_MAST2:
49                 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK2;
50                 break;
51         case FSL_SAI_CLK_MAST3:
52                 val_cr2 |= FSL_SAI_CR2_MSEL_MCLK3;
53                 break;
54         default:
55                 return -EINVAL;
56         }
57
58         regmap_write(sai->regmap, reg_cr2, val_cr2);
59
60         return 0;
61 }
62
63 static int fsl_sai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
64                 int clk_id, unsigned int freq, int dir)
65 {
66         int ret;
67
68         if (dir == SND_SOC_CLOCK_IN)
69                 return 0;
70
71         ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
72                                         FSL_FMT_TRANSMITTER);
73         if (ret) {
74                 dev_err(cpu_dai->dev, "Cannot set tx sysclk: %d\n", ret);
75                 return ret;
76         }
77
78         ret = fsl_sai_set_dai_sysclk_tr(cpu_dai, clk_id, freq,
79                                         FSL_FMT_RECEIVER);
80         if (ret)
81                 dev_err(cpu_dai->dev, "Cannot set rx sysclk: %d\n", ret);
82
83         return ret;
84 }
85
86 static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
87                                 unsigned int fmt, int fsl_dir)
88 {
89         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
90         u32 val_cr2, val_cr4, reg_cr2, reg_cr4;
91
92         if (fsl_dir == FSL_FMT_TRANSMITTER) {
93                 reg_cr2 = FSL_SAI_TCR2;
94                 reg_cr4 = FSL_SAI_TCR4;
95         } else {
96                 reg_cr2 = FSL_SAI_RCR2;
97                 reg_cr4 = FSL_SAI_RCR4;
98         }
99
100         regmap_read(sai->regmap, reg_cr2, &val_cr2);
101         regmap_read(sai->regmap, reg_cr4, &val_cr4);
102
103         if (sai->big_endian_data)
104                 val_cr4 &= ~FSL_SAI_CR4_MF;
105         else
106                 val_cr4 |= FSL_SAI_CR4_MF;
107
108         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
109         case SND_SOC_DAIFMT_I2S:
110                 val_cr4 |= FSL_SAI_CR4_FSE;
111                 break;
112         default:
113                 return -EINVAL;
114         }
115
116         switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
117         case SND_SOC_DAIFMT_IB_IF:
118                 val_cr4 |= FSL_SAI_CR4_FSP;
119                 val_cr2 &= ~FSL_SAI_CR2_BCP;
120                 break;
121         case SND_SOC_DAIFMT_IB_NF:
122                 val_cr4 &= ~FSL_SAI_CR4_FSP;
123                 val_cr2 &= ~FSL_SAI_CR2_BCP;
124                 break;
125         case SND_SOC_DAIFMT_NB_IF:
126                 val_cr4 |= FSL_SAI_CR4_FSP;
127                 val_cr2 |= FSL_SAI_CR2_BCP;
128                 break;
129         case SND_SOC_DAIFMT_NB_NF:
130                 val_cr4 &= ~FSL_SAI_CR4_FSP;
131                 val_cr2 |= FSL_SAI_CR2_BCP;
132                 break;
133         default:
134                 return -EINVAL;
135         }
136
137         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
138         case SND_SOC_DAIFMT_CBS_CFS:
139                 val_cr2 |= FSL_SAI_CR2_BCD_MSTR;
140                 val_cr4 |= FSL_SAI_CR4_FSD_MSTR;
141                 break;
142         case SND_SOC_DAIFMT_CBM_CFM:
143                 val_cr2 &= ~FSL_SAI_CR2_BCD_MSTR;
144                 val_cr4 &= ~FSL_SAI_CR4_FSD_MSTR;
145                 break;
146         default:
147                 return -EINVAL;
148         }
149
150         regmap_write(sai->regmap, reg_cr2, val_cr2);
151         regmap_write(sai->regmap, reg_cr4, val_cr4);
152
153         return 0;
154 }
155
156 static int fsl_sai_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
157 {
158         int ret;
159
160         ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_TRANSMITTER);
161         if (ret) {
162                 dev_err(cpu_dai->dev, "Cannot set tx format: %d\n", ret);
163                 return ret;
164         }
165
166         ret = fsl_sai_set_dai_fmt_tr(cpu_dai, fmt, FSL_FMT_RECEIVER);
167         if (ret)
168                 dev_err(cpu_dai->dev, "Cannot set rx format: %d\n", ret);
169
170         return ret;
171 }
172
173 static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
174                 struct snd_pcm_hw_params *params,
175                 struct snd_soc_dai *cpu_dai)
176 {
177         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
178         u32 val_cr4, val_cr5, val_mr, reg_cr4, reg_cr5, reg_mr;
179         unsigned int channels = params_channels(params);
180         u32 word_width = snd_pcm_format_width(params_format(params));
181
182         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
183                 reg_cr4 = FSL_SAI_TCR4;
184                 reg_cr5 = FSL_SAI_TCR5;
185                 reg_mr = FSL_SAI_TMR;
186         } else {
187                 reg_cr4 = FSL_SAI_RCR4;
188                 reg_cr5 = FSL_SAI_RCR5;
189                 reg_mr = FSL_SAI_RMR;
190         }
191
192         regmap_read(sai->regmap, reg_cr4, &val_cr4);
193         regmap_read(sai->regmap, reg_cr4, &val_cr5);
194
195         val_cr4 &= ~FSL_SAI_CR4_SYWD_MASK;
196         val_cr4 &= ~FSL_SAI_CR4_FRSZ_MASK;
197
198         val_cr5 &= ~FSL_SAI_CR5_WNW_MASK;
199         val_cr5 &= ~FSL_SAI_CR5_W0W_MASK;
200         val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
201
202         val_cr4 |= FSL_SAI_CR4_SYWD(word_width);
203         val_cr5 |= FSL_SAI_CR5_WNW(word_width);
204         val_cr5 |= FSL_SAI_CR5_W0W(word_width);
205
206         val_cr5 &= ~FSL_SAI_CR5_FBT_MASK;
207         if (sai->big_endian_data)
208                 val_cr5 |= FSL_SAI_CR5_FBT(0);
209         else
210                 val_cr5 |= FSL_SAI_CR5_FBT(word_width - 1);
211
212         val_cr4 |= FSL_SAI_CR4_FRSZ(channels);
213         val_mr = ~0UL - ((1 << channels) - 1);
214
215         regmap_write(sai->regmap, reg_cr4, val_cr4);
216         regmap_write(sai->regmap, reg_cr5, val_cr5);
217         regmap_write(sai->regmap, reg_mr, val_mr);
218
219         return 0;
220 }
221
222 static int fsl_sai_trigger(struct snd_pcm_substream *substream, int cmd,
223                 struct snd_soc_dai *cpu_dai)
224 {
225         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
226         u32 tcsr, rcsr;
227
228         regmap_update_bits(sai->regmap, FSL_SAI_TCR2, FSL_SAI_CR2_SYNC,
229                            ~FSL_SAI_CR2_SYNC);
230         regmap_update_bits(sai->regmap, FSL_SAI_RCR2, FSL_SAI_CR2_SYNC,
231                            FSL_SAI_CR2_SYNC);
232
233         regmap_read(sai->regmap, FSL_SAI_TCSR, &tcsr);
234         regmap_read(sai->regmap, FSL_SAI_RCSR, &rcsr);
235
236         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
237                 tcsr |= FSL_SAI_CSR_FRDE;
238                 rcsr &= ~FSL_SAI_CSR_FRDE;
239         } else {
240                 rcsr |= FSL_SAI_CSR_FRDE;
241                 tcsr &= ~FSL_SAI_CSR_FRDE;
242         }
243
244         switch (cmd) {
245         case SNDRV_PCM_TRIGGER_START:
246         case SNDRV_PCM_TRIGGER_RESUME:
247         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
248                 tcsr |= FSL_SAI_CSR_TERE;
249                 rcsr |= FSL_SAI_CSR_TERE;
250
251                 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
252                 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
253                 break;
254         case SNDRV_PCM_TRIGGER_STOP:
255         case SNDRV_PCM_TRIGGER_SUSPEND:
256         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
257                 if (!(cpu_dai->playback_active || cpu_dai->capture_active)) {
258                         tcsr &= ~FSL_SAI_CSR_TERE;
259                         rcsr &= ~FSL_SAI_CSR_TERE;
260                 }
261
262                 regmap_write(sai->regmap, FSL_SAI_TCSR, tcsr);
263                 regmap_write(sai->regmap, FSL_SAI_RCSR, rcsr);
264                 break;
265         default:
266                 return -EINVAL;
267         }
268
269         return 0;
270 }
271
272 static int fsl_sai_startup(struct snd_pcm_substream *substream,
273                 struct snd_soc_dai *cpu_dai)
274 {
275         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
276         u32 reg;
277
278         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
279                 reg = FSL_SAI_TCR3;
280         else
281                 reg = FSL_SAI_RCR3;
282
283         regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
284                            FSL_SAI_CR3_TRCE);
285
286         return 0;
287 }
288
289 static void fsl_sai_shutdown(struct snd_pcm_substream *substream,
290                 struct snd_soc_dai *cpu_dai)
291 {
292         struct fsl_sai *sai = snd_soc_dai_get_drvdata(cpu_dai);
293         u32 reg;
294
295         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
296                 reg = FSL_SAI_TCR3;
297         else
298                 reg = FSL_SAI_RCR3;
299
300         regmap_update_bits(sai->regmap, reg, FSL_SAI_CR3_TRCE,
301                            ~FSL_SAI_CR3_TRCE);
302 }
303
304 static const struct snd_soc_dai_ops fsl_sai_pcm_dai_ops = {
305         .set_sysclk     = fsl_sai_set_dai_sysclk,
306         .set_fmt        = fsl_sai_set_dai_fmt,
307         .hw_params      = fsl_sai_hw_params,
308         .trigger        = fsl_sai_trigger,
309         .startup        = fsl_sai_startup,
310         .shutdown       = fsl_sai_shutdown,
311 };
312
313 static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai)
314 {
315         struct fsl_sai *sai = dev_get_drvdata(cpu_dai->dev);
316
317         regmap_update_bits(sai->regmap, FSL_SAI_TCSR, 0xffffffff, 0x0);
318         regmap_update_bits(sai->regmap, FSL_SAI_RCSR, 0xffffffff, 0x0);
319         regmap_update_bits(sai->regmap, FSL_SAI_TCR1, FSL_SAI_CR1_RFW_MASK,
320                            FSL_SAI_MAXBURST_TX * 2);
321         regmap_update_bits(sai->regmap, FSL_SAI_RCR1, FSL_SAI_CR1_RFW_MASK,
322                            FSL_SAI_MAXBURST_RX - 1);
323
324         snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx,
325                                 &sai->dma_params_rx);
326
327         snd_soc_dai_set_drvdata(cpu_dai, sai);
328
329         return 0;
330 }
331
332 static struct snd_soc_dai_driver fsl_sai_dai = {
333         .probe = fsl_sai_dai_probe,
334         .playback = {
335                 .channels_min = 1,
336                 .channels_max = 2,
337                 .rates = SNDRV_PCM_RATE_8000_96000,
338                 .formats = FSL_SAI_FORMATS,
339         },
340         .capture = {
341                 .channels_min = 1,
342                 .channels_max = 2,
343                 .rates = SNDRV_PCM_RATE_8000_96000,
344                 .formats = FSL_SAI_FORMATS,
345         },
346         .ops = &fsl_sai_pcm_dai_ops,
347 };
348
349 static const struct snd_soc_component_driver fsl_component = {
350         .name           = "fsl-sai",
351 };
352
353 static bool fsl_sai_readable_reg(struct device *dev, unsigned int reg)
354 {
355         switch (reg) {
356         case FSL_SAI_TCSR:
357         case FSL_SAI_TCR1:
358         case FSL_SAI_TCR2:
359         case FSL_SAI_TCR3:
360         case FSL_SAI_TCR4:
361         case FSL_SAI_TCR5:
362         case FSL_SAI_TFR:
363         case FSL_SAI_TMR:
364         case FSL_SAI_RCSR:
365         case FSL_SAI_RCR1:
366         case FSL_SAI_RCR2:
367         case FSL_SAI_RCR3:
368         case FSL_SAI_RCR4:
369         case FSL_SAI_RCR5:
370         case FSL_SAI_RDR:
371         case FSL_SAI_RFR:
372         case FSL_SAI_RMR:
373                 return true;
374         default:
375                 return false;
376         }
377 }
378
379 static bool fsl_sai_volatile_reg(struct device *dev, unsigned int reg)
380 {
381         switch (reg) {
382         case FSL_SAI_TFR:
383         case FSL_SAI_RFR:
384         case FSL_SAI_TDR:
385         case FSL_SAI_RDR:
386                 return true;
387         default:
388                 return false;
389         }
390
391 }
392
393 static bool fsl_sai_writeable_reg(struct device *dev, unsigned int reg)
394 {
395         switch (reg) {
396         case FSL_SAI_TCSR:
397         case FSL_SAI_TCR1:
398         case FSL_SAI_TCR2:
399         case FSL_SAI_TCR3:
400         case FSL_SAI_TCR4:
401         case FSL_SAI_TCR5:
402         case FSL_SAI_TDR:
403         case FSL_SAI_TMR:
404         case FSL_SAI_RCSR:
405         case FSL_SAI_RCR1:
406         case FSL_SAI_RCR2:
407         case FSL_SAI_RCR3:
408         case FSL_SAI_RCR4:
409         case FSL_SAI_RCR5:
410         case FSL_SAI_RMR:
411                 return true;
412         default:
413                 return false;
414         }
415 }
416
417 static struct regmap_config fsl_sai_regmap_config = {
418         .reg_bits = 32,
419         .reg_stride = 4,
420         .val_bits = 32,
421
422         .max_register = FSL_SAI_RMR,
423         .readable_reg = fsl_sai_readable_reg,
424         .volatile_reg = fsl_sai_volatile_reg,
425         .writeable_reg = fsl_sai_writeable_reg,
426 };
427
428 static int fsl_sai_probe(struct platform_device *pdev)
429 {
430         struct device_node *np = pdev->dev.of_node;
431         struct fsl_sai *sai;
432         struct resource *res;
433         void __iomem *base;
434         int ret;
435
436         sai = devm_kzalloc(&pdev->dev, sizeof(*sai), GFP_KERNEL);
437         if (!sai)
438                 return -ENOMEM;
439
440         sai->big_endian_regs = of_property_read_bool(np, "big-endian-regs");
441         if (sai->big_endian_regs)
442                 fsl_sai_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG;
443
444         sai->big_endian_data = of_property_read_bool(np, "big-endian-data");
445
446         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
447         base = devm_ioremap_resource(&pdev->dev, res);
448         if (IS_ERR(base))
449                 return PTR_ERR(base);
450
451         sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev,
452                         "sai", base, &fsl_sai_regmap_config);
453         if (IS_ERR(sai->regmap)) {
454                 dev_err(&pdev->dev, "regmap init failed\n");
455                 return PTR_ERR(sai->regmap);
456         }
457
458         sai->dma_params_rx.addr = res->start + FSL_SAI_RDR;
459         sai->dma_params_tx.addr = res->start + FSL_SAI_TDR;
460         sai->dma_params_rx.maxburst = FSL_SAI_MAXBURST_RX;
461         sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX;
462
463         platform_set_drvdata(pdev, sai);
464
465         ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component,
466                         &fsl_sai_dai, 1);
467         if (ret)
468                 return ret;
469
470         return devm_snd_dmaengine_pcm_register(&pdev->dev, NULL,
471                         SND_DMAENGINE_PCM_FLAG_NO_RESIDUE);
472 }
473
474 static const struct of_device_id fsl_sai_ids[] = {
475         { .compatible = "fsl,vf610-sai", },
476         { /* sentinel */ }
477 };
478
479 static struct platform_driver fsl_sai_driver = {
480         .probe = fsl_sai_probe,
481         .driver = {
482                 .name = "fsl-sai",
483                 .owner = THIS_MODULE,
484                 .of_match_table = fsl_sai_ids,
485         },
486 };
487 module_platform_driver(fsl_sai_driver);
488
489 MODULE_DESCRIPTION("Freescale Soc SAI Interface");
490 MODULE_AUTHOR("Xiubo Li, <Li.Xiubo@freescale.com>");
491 MODULE_ALIAS("platform:fsl-sai");
492 MODULE_LICENSE("GPL");