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
26struct 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
46static 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
55static 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
69static inline struct rk_i2s_dev *to_info(struct snd_soc_dai *dai)
70{
71	return snd_soc_dai_get_drvdata(dai);
72}
73
74static 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					break;
114				}
115			}
116		}
117	}
118}
119
120static void rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
121{
122	unsigned int val = 0;
123	int retry = 10;
124
125	if (on) {
126		regmap_update_bits(i2s->regmap, I2S_DMACR,
127				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_ENABLE);
128
129		regmap_update_bits(i2s->regmap, I2S_XFER,
130				   I2S_XFER_TXS_START | I2S_XFER_RXS_START,
131				   I2S_XFER_TXS_START | I2S_XFER_RXS_START);
132
133		i2s->rx_start = true;
134	} else {
135		i2s->rx_start = false;
136
137		regmap_update_bits(i2s->regmap, I2S_DMACR,
138				   I2S_DMACR_RDE_ENABLE, I2S_DMACR_RDE_DISABLE);
139
140		if (!i2s->tx_start) {
141			regmap_update_bits(i2s->regmap, I2S_XFER,
142					   I2S_XFER_TXS_START |
143					   I2S_XFER_RXS_START,
144					   I2S_XFER_TXS_STOP |
145					   I2S_XFER_RXS_STOP);
146
147			regmap_update_bits(i2s->regmap, I2S_CLR,
148					   I2S_CLR_TXC | I2S_CLR_RXC,
149					   I2S_CLR_TXC | I2S_CLR_RXC);
150
151			regmap_read(i2s->regmap, I2S_CLR, &val);
152
153			/* Should wait for clear operation to finish */
154			while (val) {
155				regmap_read(i2s->regmap, I2S_CLR, &val);
156				retry--;
157				if (!retry) {
158					dev_warn(i2s->dev, "fail to clear\n");
159					break;
160				}
161			}
162		}
163	}
164}
165
166static int rockchip_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
167				unsigned int fmt)
168{
169	struct rk_i2s_dev *i2s = to_info(cpu_dai);
170	unsigned int mask = 0, val = 0;
171
172	mask = I2S_CKR_MSS_MASK;
173	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
174	case SND_SOC_DAIFMT_CBS_CFS:
175		/* Set source clock in Master mode */
176		val = I2S_CKR_MSS_MASTER;
177		break;
178	case SND_SOC_DAIFMT_CBM_CFM:
179		val = I2S_CKR_MSS_SLAVE;
180		break;
181	default:
182		return -EINVAL;
183	}
184
185	regmap_update_bits(i2s->regmap, I2S_CKR, mask, val);
186
187	mask = I2S_TXCR_IBM_MASK;
188	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
189	case SND_SOC_DAIFMT_RIGHT_J:
190		val = I2S_TXCR_IBM_RSJM;
191		break;
192	case SND_SOC_DAIFMT_LEFT_J:
193		val = I2S_TXCR_IBM_LSJM;
194		break;
195	case SND_SOC_DAIFMT_I2S:
196		val = I2S_TXCR_IBM_NORMAL;
197		break;
198	default:
199		return -EINVAL;
200	}
201
202	regmap_update_bits(i2s->regmap, I2S_TXCR, mask, val);
203
204	mask = I2S_RXCR_IBM_MASK;
205	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
206	case SND_SOC_DAIFMT_RIGHT_J:
207		val = I2S_RXCR_IBM_RSJM;
208		break;
209	case SND_SOC_DAIFMT_LEFT_J:
210		val = I2S_RXCR_IBM_LSJM;
211		break;
212	case SND_SOC_DAIFMT_I2S:
213		val = I2S_RXCR_IBM_NORMAL;
214		break;
215	default:
216		return -EINVAL;
217	}
218
219	regmap_update_bits(i2s->regmap, I2S_RXCR, mask, val);
220
221	return 0;
222}
223
224static int rockchip_i2s_hw_params(struct snd_pcm_substream *substream,
225				  struct snd_pcm_hw_params *params,
226				  struct snd_soc_dai *dai)
227{
228	struct rk_i2s_dev *i2s = to_info(dai);
229	unsigned int val = 0;
230
231	switch (params_format(params)) {
232	case SNDRV_PCM_FORMAT_S8:
233		val |= I2S_TXCR_VDW(8);
234		break;
235	case SNDRV_PCM_FORMAT_S16_LE:
236		val |= I2S_TXCR_VDW(16);
237		break;
238	case SNDRV_PCM_FORMAT_S20_3LE:
239		val |= I2S_TXCR_VDW(20);
240		break;
241	case SNDRV_PCM_FORMAT_S24_LE:
242		val |= I2S_TXCR_VDW(24);
243		break;
244	default:
245		return -EINVAL;
246	}
247
248	regmap_update_bits(i2s->regmap, I2S_TXCR, I2S_TXCR_VDW_MASK, val);
249	regmap_update_bits(i2s->regmap, I2S_RXCR, I2S_RXCR_VDW_MASK, val);
250	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_TDL_MASK,
251			   I2S_DMACR_TDL(16));
252	regmap_update_bits(i2s->regmap, I2S_DMACR, I2S_DMACR_RDL_MASK,
253			   I2S_DMACR_RDL(16));
254
255	return 0;
256}
257
258static int rockchip_i2s_trigger(struct snd_pcm_substream *substream,
259				int cmd, struct snd_soc_dai *dai)
260{
261	struct rk_i2s_dev *i2s = to_info(dai);
262	int ret = 0;
263
264	switch (cmd) {
265	case SNDRV_PCM_TRIGGER_START:
266	case SNDRV_PCM_TRIGGER_RESUME:
267	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
268		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
269			rockchip_snd_rxctrl(i2s, 1);
270		else
271			rockchip_snd_txctrl(i2s, 1);
272		break;
273	case SNDRV_PCM_TRIGGER_SUSPEND:
274	case SNDRV_PCM_TRIGGER_STOP:
275	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
276		if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
277			rockchip_snd_rxctrl(i2s, 0);
278		else
279			rockchip_snd_txctrl(i2s, 0);
280		break;
281	default:
282		ret = -EINVAL;
283		break;
284	}
285
286	return ret;
287}
288
289static int rockchip_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
290				   unsigned int freq, int dir)
291{
292	struct rk_i2s_dev *i2s = to_info(cpu_dai);
293	int ret;
294
295	ret = clk_set_rate(i2s->mclk, freq);
296	if (ret)
297		dev_err(i2s->dev, "Fail to set mclk %d\n", ret);
298
299	return ret;
300}
301
302static int rockchip_i2s_dai_probe(struct snd_soc_dai *dai)
303{
304	struct rk_i2s_dev *i2s = snd_soc_dai_get_drvdata(dai);
305
306	dai->capture_dma_data = &i2s->capture_dma_data;
307	dai->playback_dma_data = &i2s->playback_dma_data;
308
309	return 0;
310}
311
312static const struct snd_soc_dai_ops rockchip_i2s_dai_ops = {
313	.hw_params = rockchip_i2s_hw_params,
314	.set_sysclk = rockchip_i2s_set_sysclk,
315	.set_fmt = rockchip_i2s_set_fmt,
316	.trigger = rockchip_i2s_trigger,
317};
318
319static struct snd_soc_dai_driver rockchip_i2s_dai = {
320	.probe = rockchip_i2s_dai_probe,
321	.playback = {
322		.stream_name = "Playback",
323		.channels_min = 2,
324		.channels_max = 8,
325		.rates = SNDRV_PCM_RATE_8000_192000,
326		.formats = (SNDRV_PCM_FMTBIT_S8 |
327			    SNDRV_PCM_FMTBIT_S16_LE |
328			    SNDRV_PCM_FMTBIT_S20_3LE |
329			    SNDRV_PCM_FMTBIT_S24_LE),
330	},
331	.capture = {
332		.stream_name = "Capture",
333		.channels_min = 2,
334		.channels_max = 2,
335		.rates = SNDRV_PCM_RATE_8000_192000,
336		.formats = (SNDRV_PCM_FMTBIT_S8 |
337			    SNDRV_PCM_FMTBIT_S16_LE |
338			    SNDRV_PCM_FMTBIT_S20_3LE |
339			    SNDRV_PCM_FMTBIT_S24_LE),
340	},
341	.ops = &rockchip_i2s_dai_ops,
342	.symmetric_rates = 1,
343};
344
345static const struct snd_soc_component_driver rockchip_i2s_component = {
346	.name = DRV_NAME,
347};
348
349static bool rockchip_i2s_wr_reg(struct device *dev, unsigned int reg)
350{
351	switch (reg) {
352	case I2S_TXCR:
353	case I2S_RXCR:
354	case I2S_CKR:
355	case I2S_DMACR:
356	case I2S_INTCR:
357	case I2S_XFER:
358	case I2S_CLR:
359	case I2S_TXDR:
360		return true;
361	default:
362		return false;
363	}
364}
365
366static bool rockchip_i2s_rd_reg(struct device *dev, unsigned int reg)
367{
368	switch (reg) {
369	case I2S_TXCR:
370	case I2S_RXCR:
371	case I2S_CKR:
372	case I2S_DMACR:
373	case I2S_INTCR:
374	case I2S_XFER:
375	case I2S_CLR:
376	case I2S_RXDR:
377	case I2S_FIFOLR:
378	case I2S_INTSR:
379		return true;
380	default:
381		return false;
382	}
383}
384
385static bool rockchip_i2s_volatile_reg(struct device *dev, unsigned int reg)
386{
387	switch (reg) {
388	case I2S_INTSR:
389	case I2S_CLR:
390		return true;
391	default:
392		return false;
393	}
394}
395
396static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
397{
398	switch (reg) {
399	default:
400		return false;
401	}
402}
403
404static const struct regmap_config rockchip_i2s_regmap_config = {
405	.reg_bits = 32,
406	.reg_stride = 4,
407	.val_bits = 32,
408	.max_register = I2S_RXDR,
409	.writeable_reg = rockchip_i2s_wr_reg,
410	.readable_reg = rockchip_i2s_rd_reg,
411	.volatile_reg = rockchip_i2s_volatile_reg,
412	.precious_reg = rockchip_i2s_precious_reg,
413	.cache_type = REGCACHE_FLAT,
414};
415
416static int rockchip_i2s_probe(struct platform_device *pdev)
417{
418	struct rk_i2s_dev *i2s;
419	struct resource *res;
420	void __iomem *regs;
421	int ret;
422
423	i2s = devm_kzalloc(&pdev->dev, sizeof(*i2s), GFP_KERNEL);
424	if (!i2s) {
425		dev_err(&pdev->dev, "Can't allocate rk_i2s_dev\n");
426		return -ENOMEM;
427	}
428
429	/* try to prepare related clocks */
430	i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
431	if (IS_ERR(i2s->hclk)) {
432		dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
433		return PTR_ERR(i2s->hclk);
434	}
435	ret = clk_prepare_enable(i2s->hclk);
436	if (ret) {
437		dev_err(i2s->dev, "hclock enable failed %d\n", ret);
438		return ret;
439	}
440
441	i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
442	if (IS_ERR(i2s->mclk)) {
443		dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
444		return PTR_ERR(i2s->mclk);
445	}
446
447	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
448	regs = devm_ioremap_resource(&pdev->dev, res);
449	if (IS_ERR(regs))
450		return PTR_ERR(regs);
451
452	i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
453					    &rockchip_i2s_regmap_config);
454	if (IS_ERR(i2s->regmap)) {
455		dev_err(&pdev->dev,
456			"Failed to initialise managed register map\n");
457		return PTR_ERR(i2s->regmap);
458	}
459
460	i2s->playback_dma_data.addr = res->start + I2S_TXDR;
461	i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
462	i2s->playback_dma_data.maxburst = 4;
463
464	i2s->capture_dma_data.addr = res->start + I2S_RXDR;
465	i2s->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
466	i2s->capture_dma_data.maxburst = 4;
467
468	i2s->dev = &pdev->dev;
469	dev_set_drvdata(&pdev->dev, i2s);
470
471	pm_runtime_enable(&pdev->dev);
472	if (!pm_runtime_enabled(&pdev->dev)) {
473		ret = i2s_runtime_resume(&pdev->dev);
474		if (ret)
475			goto err_pm_disable;
476	}
477
478	ret = devm_snd_soc_register_component(&pdev->dev,
479					      &rockchip_i2s_component,
480					      &rockchip_i2s_dai, 1);
481	if (ret) {
482		dev_err(&pdev->dev, "Could not register DAI\n");
483		goto err_suspend;
484	}
485
486	ret = snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
487	if (ret) {
488		dev_err(&pdev->dev, "Could not register PCM\n");
489		goto err_pcm_register;
490	}
491
492	return 0;
493
494err_pcm_register:
495	snd_dmaengine_pcm_unregister(&pdev->dev);
496err_suspend:
497	if (!pm_runtime_status_suspended(&pdev->dev))
498		i2s_runtime_suspend(&pdev->dev);
499err_pm_disable:
500	pm_runtime_disable(&pdev->dev);
501
502	return ret;
503}
504
505static int rockchip_i2s_remove(struct platform_device *pdev)
506{
507	struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
508
509	pm_runtime_disable(&pdev->dev);
510	if (!pm_runtime_status_suspended(&pdev->dev))
511		i2s_runtime_suspend(&pdev->dev);
512
513	clk_disable_unprepare(i2s->mclk);
514	clk_disable_unprepare(i2s->hclk);
515	snd_dmaengine_pcm_unregister(&pdev->dev);
516	snd_soc_unregister_component(&pdev->dev);
517
518	return 0;
519}
520
521static const struct of_device_id rockchip_i2s_match[] = {
522	{ .compatible = "rockchip,rk3066-i2s", },
523	{},
524};
525
526static const struct dev_pm_ops rockchip_i2s_pm_ops = {
527	SET_RUNTIME_PM_OPS(i2s_runtime_suspend, i2s_runtime_resume,
528			   NULL)
529};
530
531static struct platform_driver rockchip_i2s_driver = {
532	.probe = rockchip_i2s_probe,
533	.remove = rockchip_i2s_remove,
534	.driver = {
535		.name = DRV_NAME,
536		.of_match_table = of_match_ptr(rockchip_i2s_match),
537		.pm = &rockchip_i2s_pm_ops,
538	},
539};
540module_platform_driver(rockchip_i2s_driver);
541
542MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
543MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
544MODULE_LICENSE("GPL v2");
545MODULE_ALIAS("platform:" DRV_NAME);
546MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
547