]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/rockchip/rockchip_i2s.c
870a6645c7824d0c8f9f70d927595375ee4104b2
[karo-tx-linux.git] / sound / soc / rockchip / rockchip_i2s.c
1 /* sound/soc/rockchip/rockchip_i2s.c
2  *
3  * ALSA SoC Audio Layer - Rockchip I2S Controller driver
4  *
5  * Copyright (c) 2014 Rockchip Electronics Co. Ltd.
6  * Author: Jianqun <jay.xu@rock-chips.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11  */
12
13 #include <linux/module.h>
14 #include <linux/delay.h>
15 #include <linux/of_gpio.h>
16 #include <linux/clk.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/regmap.h>
19 #include <sound/pcm_params.h>
20 #include <sound/dmaengine_pcm.h>
21
22 #include "rockchip_i2s.h"
23
24 #define DRV_NAME "rockchip-i2s"
25
26 struct rk_i2s_dev {
27         struct device *dev;
28
29         struct clk *hclk;
30         struct clk *mclk;
31
32         struct snd_dmaengine_dai_dma_data capture_dma_data;
33         struct snd_dmaengine_dai_dma_data playback_dma_data;
34
35         struct regmap *regmap;
36
37 /*
38  * Used to indicate the tx/rx status.
39  * I2S controller hopes to start the tx and rx together,
40  * also to stop them when they are both try to stop.
41 */
42         bool tx_start;
43         bool rx_start;
44 };
45
46 static int i2s_runtime_suspend(struct device *dev)
47 {
48         struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
49
50         clk_disable_unprepare(i2s->mclk);
51
52         return 0;
53 }
54
55 static int i2s_runtime_resume(struct device *dev)
56 {
57         struct rk_i2s_dev *i2s = dev_get_drvdata(dev);
58         int ret;
59
60         ret = clk_prepare_enable(i2s->mclk);
61         if (ret) {
62                 dev_err(i2s->dev, "clock enable failed %d\n", ret);
63                 return ret;
64         }
65
66         return 0;
67 }
68
69 static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
70 {
71         return snd_soc_dai_get_drvdata(dai);
72 }
73
74 static void rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
75 {
76         unsigned int val = 0;
77         int retry = 10;
78
79         if (on) {
80                 regmap_update_bits(i2s->regmap, I2S_DMACR,
81                                    I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_ENABLE);
82
83                 regmap_update_bits(i2s->regmap, I2S_XFER,
84                                    I2S_XFER_TXS_START | I2S_XFER_RXS_START,
85                                    I2S_XFER_TXS_START | I2S_XFER_RXS_START);
86
87                 i2s->tx_start = true;
88         } else {
89                 i2s->tx_start = false;
90
91                 regmap_update_bits(i2s->regmap, I2S_DMACR,
92                                    I2S_DMACR_TDE_ENABLE, I2S_DMACR_TDE_DISABLE);
93
94                 if (!i2s->rx_start) {
95                         regmap_update_bits(i2s->regmap, I2S_XFER,
96                                            I2S_XFER_TXS_START |
97                                            I2S_XFER_RXS_START,
98                                            I2S_XFER_TXS_STOP |
99                                            I2S_XFER_RXS_STOP);
100
101                         regmap_update_bits(i2s->regmap, I2S_CLR,
102                                            I2S_CLR_TXC | I2S_CLR_RXC,
103                                            I2S_CLR_TXC | I2S_CLR_RXC);
104
105                         regmap_read(i2s->regmap, I2S_CLR, &val);
106
107                         /* Should wait for clear operation to finish */
108                         while (val) {
109                                 regmap_read(i2s->regmap, I2S_CLR, &val);
110                                 retry--;
111                                 if (!retry)
112                                         dev_warn(i2s->dev, "fail to clear\n");
113                         }
114                 }
115         }
116 }
117
118 static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
119 {
120         unsigned int val = 0;
121         int retry = 10;
122
123         if (on) {
124                 regmap_update_bits(i2s->regmap, I2S_DMACR,
125                                    I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
126
127                 regmap_update_bits(i2s->regmap, I2S_XFER,
128                                    I2S_XFER_TXS_START | I2S_XFER_RXS_START,
129                                    I2S_XFER_TXS_START | I2S_XFER_RXS_START);
130
131                 i2s->rx_start = true;
132         } else {
133                 i2s->rx_start = false;
134
135                 regmap_update_bits(i2s->regmap, I2S_DMACR,
136                                    I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
137
138                 if (!i2s->tx_start) {
139                         regmap_update_bits(i2s->regmap, I2S_XFER,
140                                            I2S_XFER_TXS_START |
141                                            I2S_XFER_RXS_START,
142                                            I2S_XFER_TXS_STOP |
143                                            I2S_XFER_RXS_STOP);
144
145                         regmap_update_bits(i2s->regmap, I2S_CLR,
146                                            I2S_CLR_TXC | I2S_CLR_RXC,
147                                            I2S_CLR_TXC | I2S_CLR_RXC);
148
149                         regmap_read(i2s->regmap, I2S_CLR, &val);
150
151                         /* Should wait for clear operation to finish */
152                         while (val) {
153                                 regmap_read(i2s->regmap, I2S_CLR, &val);
154                                 retry--;
155                                 if (!retry)
156                                         dev_warn(i2s->dev, "fail to clear\n");
157                         }
158                 }
159         }
160 }
161
162 static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
163                                 unsigned int fmt)
164 {
165         struct rk_i2s_dev *i2s = to_info(cpu_dai);
166         unsigned int mask = 0, val = 0;
167
168         mask = I2S_CKR_MSS_MASK;
169         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
170         case SND_SOC_DAIFMT_CBS_CFS:
171                 /* Set source clock in Master mode */
172                 val = I2S_CKR_MSS_MASTER;
173                 break;
174         case SND_SOC_DAIFMT_CBM_CFM:
175                 val = I2S_CKR_MSS_SLAVE;
176                 break;
177         default:
178                 return -EINVAL;
179         }
180
181         regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
182
183         mask = I2S_TXCR_IBM_MASK;
184         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
185         case SND_SOC_DAIFMT_RIGHT_J:
186                 val = I2S_TXCR_IBM_RSJM;
187                 break;
188         case SND_SOC_DAIFMT_LEFT_J:
189                 val = I2S_TXCR_IBM_LSJM;
190                 break;
191         case SND_SOC_DAIFMT_I2S:
192                 val = I2S_TXCR_IBM_NORMAL;
193                 break;
194         default:
195                 return -EINVAL;
196         }
197
198         regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
199
200         mask = I2S_RXCR_IBM_MASK;
201         switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
202         case SND_SOC_DAIFMT_RIGHT_J:
203                 val = I2S_RXCR_IBM_RSJM;
204                 break;
205         case SND_SOC_DAIFMT_LEFT_J:
206                 val = I2S_RXCR_IBM_LSJM;
207                 break;
208         case SND_SOC_DAIFMT_I2S:
209                 val = I2S_RXCR_IBM_NORMAL;
210                 break;
211         default:
212                 return -EINVAL;
213         }
214
215         regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
216
217         return 0;
218 }
219
220 static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
221                                   struct snd_pcm_hw_params *params,
222                                   struct snd_soc_dai *dai)
223 {
224         struct rk_i2s_dev *i2s = to_info(dai);
225         unsigned int val = 0;
226
227         switch (params_format(params)) {
228         case SNDRV_PCM_FORMAT_S8:
229                 val |= I2S_TXCR_VDW(8);
230                 break;
231         case SNDRV_PCM_FORMAT_S16_LE:
232                 val |= I2S_TXCR_VDW(16);
233                 break;
234         case SNDRV_PCM_FORMAT_S20_3LE:
235                 val |= I2S_TXCR_VDW(20);
236                 break;
237         case SNDRV_PCM_FORMAT_S24_LE:
238                 val |= I2S_TXCR_VDW(24);
239                 break;
240         default:
241                 return -EINVAL;
242         }
243
244         regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val);
245         regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val);
246
247         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
248                 dai->playback_dma_data = &i2s->playback_dma_data;
249                 regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
250                                    I2S_DMACR_TDL(1) | I2S_DMACR_TDE_ENABLE);
251         } else {
252                 dai->capture_dma_data = &i2s->capture_dma_data;
253                 regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
254                                    I2S_DMACR_RDL(1) | I2S_DMACR_RDE_ENABLE);
255         }
256
257         return 0;
258 }
259
260 static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
261                                 int cmd, struct snd_soc_dai *dai)
262 {
263         struct rk_i2s_dev *i2s = to_info(dai);
264         int ret = 0;
265
266         switch (cmd) {
267         case SNDRV_PCM_TRIGGER_START:
268         case SNDRV_PCM_TRIGGER_RESUME:
269         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
270                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
271                         rockchip_snd_rxctrl(i2s, 1);
272                 else
273                         rockchip_snd_txctrl(i2s, 1);
274                 break;
275         case SNDRV_PCM_TRIGGER_SUSPEND:
276         case SNDRV_PCM_TRIGGER_STOP:
277         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
278                 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
279                         rockchip_snd_rxctrl(i2s, 0);
280                 else
281                         rockchip_snd_txctrl(i2s, 0);
282                 break;
283         default:
284                 ret = -EINVAL;
285                 break;
286         }
287
288         return ret;
289 }
290
291 static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
292                                    unsigned int freq, int dir)
293 {
294         struct rk_i2s_dev *i2s = to_info(cpu_dai);
295         int ret;
296
297         ret = clk_set_rate(i2s->mclk, freq);
298         if (ret)
299                 dev_err(i2s->dev, "Fail to set mclk %d\n", ret);
300
301         return ret;
302 }
303
304 static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
305         .hw_params = rockchip_i2s_hw_params,
306         .set_sysclk = rockchip_i2s_set_sysclk,
307         .set_fmt = rockchip_i2s_set_fmt,
308         .trigger = rockchip_i2s_trigger,
309 };
310
311 static struct snd_soc_dai_driver rockchip_i2s_dai = {
312         .playback = {
313                 .channels_min = 2,
314                 .channels_max = 8,
315                 .rates = SNDRV_PCM_RATE_8000_192000,
316                 .formats = (SNDRV_PCM_FMTBIT_S8 |
317                             SNDRV_PCM_FMTBIT_S16_LE |
318                             SNDRV_PCM_FMTBIT_S20_3LE |
319                             SNDRV_PCM_FMTBIT_S24_LE),
320         },
321         .capture = {
322                 .channels_min = 2,
323                 .channels_max = 2,
324                 .rates = SNDRV_PCM_RATE_8000_192000,
325                 .formats = (SNDRV_PCM_FMTBIT_S8 |
326                             SNDRV_PCM_FMTBIT_S16_LE |
327                             SNDRV_PCM_FMTBIT_S20_3LE |
328                             SNDRV_PCM_FMTBIT_S24_LE),
329         },
330         .ops = &rockchip_i2s_dai_ops,
331 };
332
333 static const struct snd_soc_component_driver rockchip_i2s_component = {
334         .name = DRV_NAME,
335 };
336
337 static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)
338 {
339         switch (reg) {
340         case I2S_TXCR:
341         case I2S_RXCR:
342         case I2S_CKR:
343         case I2S_DMACR:
344         case I2S_INTCR:
345         case I2S_XFER:
346         case I2S_CLR:
347         case I2S_TXDR:
348                 return true;
349         default:
350                 return false;
351         }
352 }
353
354 static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
355 {
356         switch (reg) {
357         case I2S_TXCR:
358         case I2S_RXCR:
359         case I2S_CKR:
360         case I2S_DMACR:
361         case I2S_INTCR:
362         case I2S_XFER:
363         case I2S_CLR:
364         case I2S_RXDR:
365                 return true;
366         default:
367                 return false;
368         }
369 }
370
371 static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
372 {
373         switch (reg) {
374         case I2S_FIFOLR:
375         case I2S_INTSR:
376                 return true;
377         default:
378                 return false;
379         }
380 }
381
382 static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
383 {
384         switch (reg) {
385         case I2S_FIFOLR:
386                 return true;
387         default:
388                 return false;
389         }
390 }
391
392 static const struct regmap_config rockchip_i2s_regmap_config = {
393         .reg_bits = 32,
394         .reg_stride = 4,
395         .val_bits = 32,
396         .max_register = I2S_RXDR,
397         .writeable_reg = rockchip_i2s_wr_reg,
398         .readable_reg = rockchip_i2s_rd_reg,
399         .volatile_reg = rockchip_i2s_volatile_reg,
400         .precious_reg = rockchip_i2s_precious_reg,
401         .cache_type = REGCACHE_FLAT,
402 };
403
404 static int rockchip_i2s_probe(struct platform_device *pdev)
405 {
406         struct rk_i2s_dev *i2s;
407         struct resource *res;
408         void __iomem *regs;
409         int ret;
410
411         i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
412         if (!i2s) {
413                 dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
414                 return -ENOMEM;
415         }
416
417         /* try to prepare related clocks */
418         i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
419         if (IS_ERR(i2s->hclk)) {
420                 dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
421                 return PTR_ERR(i2s->hclk);
422         }
423
424         i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
425         if (IS_ERR(i2s->mclk)) {
426                 dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
427                 return PTR_ERR(i2s->mclk);
428         }
429
430         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
431         regs = devm_ioremap_resource(&pdev->dev, res);
432         if (IS_ERR(regs))
433                 return PTR_ERR(regs);
434
435         i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
436                                             &rockchip_i2s_regmap_config);
437         if (IS_ERR(i2s->regmap)) {
438                 dev_err(&pdev->dev,
439                         "Failed to initialise managed register map\n");
440                 return PTR_ERR(i2s->regmap);
441         }
442
443         i2s->playback_dma_data.addr = res->start + I2S_TXDR;
444         i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
445         i2s->playback_dma_data.maxburst = 16;
446
447         i2s->capture_dma_data.addr = res->start + I2S_RXDR;
448         i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
449         i2s->capture_dma_data.maxburst = 16;
450
451         i2s->dev = &pdev->dev;
452         dev_set_drvdata(&pdev->dev, i2s);
453
454         pm_runtime_enable(&pdev->dev);
455         if (!pm_runtime_enabled(&pdev->dev)) {
456                 ret = i2s_runtime_resume(&pdev->dev);
457                 if (ret)
458                         goto err_pm_disable;
459         }
460
461         ret = devm_snd_soc_register_component(&pdev->dev,
462                                               &rockchip_i2s_component,
463                                               &rockchip_i2s_dai, 1);
464         if (ret) {
465                 dev_err(&pdev->dev, "Could not register DAI\n");
466                 goto err_suspend;
467         }
468
469         ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
470         if (ret) {
471                 dev_err(&pdev->dev, "Could not register PCM\n");
472                 goto err_pcm_register;
473         }
474
475         return 0;
476
477 err_pcm_register:
478         snd_dmaengine_pcm_unregister(&pdev->dev);
479 err_suspend:
480         if (!pm_runtime_status_suspended(&pdev->dev))
481                 i2s_runtime_suspend(&pdev->dev);
482 err_pm_disable:
483         pm_runtime_disable(&pdev->dev);
484
485         return ret;
486 }
487
488 static int rockchip_i2s_remove(struct platform_device *pdev)
489 {
490         struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
491
492         pm_runtime_disable(&pdev->dev);
493         if (!pm_runtime_status_suspended(&pdev->dev))
494                 i2s_runtime_suspend(&pdev->dev);
495
496         clk_disable_unprepare(i2s->mclk);
497         clk_disable_unprepare(i2s->hclk);
498         snd_dmaengine_pcm_unregister(&pdev->dev);
499         snd_soc_unregister_component(&pdev->dev);
500
501         return 0;
502 }
503
504 static const struct of_device_id rockchip_i2s_match[] = {
505         { .compatible = "rockchip,rk3066-i2s", },
506         {},
507 };
508
509 static const struct dev_pm_ops rockchip_i2s_pm_ops = {
510         SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
511                            NULL)
512 };
513
514 static struct platform_driver rockchip_i2s_driver = {
515         .probe = rockchip_i2s_probe,
516         .remove = rockchip_i2s_remove,
517         .driver = {
518                 .name = DRV_NAME,
519                 .owner = THIS_MODULE,
520                 .of_match_table = of_match_ptr(rockchip_i2s_match),
521                 .pm = &rockchip_i2s_pm_ops,
522         },
523 };
524 module_platform_driver(rockchip_i2s_driver);
525
526 MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
527 MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
528 MODULE_LICENSE("GPL v2");
529 MODULE_ALIAS("platform:" DRV_NAME);
530 MODULE_DEVICE_TABLE(of, rockchip_i2s_match);