1/*
2 * Copyright (C) 2015 Linaro
3 *
4 * Author: Jun Nie <jun.nie@linaro.org>
5 *
6 * License terms: GNU General Public License (GPL) version 2
7 */
8
9#include <linux/clk.h>
10#include <linux/device.h>
11#include <linux/dmaengine.h>
12#include <linux/init.h>
13#include <linux/io.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/of_address.h>
17#include <sound/asoundef.h>
18#include <sound/core.h>
19#include <sound/dmaengine_pcm.h>
20#include <sound/initval.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/soc.h>
24#include <sound/soc-dai.h>
25
26#define ZX_CTRL				0x04
27#define ZX_FIFOCTRL			0x08
28#define ZX_INT_STATUS			0x10
29#define ZX_INT_MASK			0x14
30#define ZX_DATA				0x18
31#define ZX_VALID_BIT			0x1c
32#define ZX_CH_STA_1			0x20
33#define ZX_CH_STA_2			0x24
34#define ZX_CH_STA_3			0x28
35#define ZX_CH_STA_4			0x2c
36#define ZX_CH_STA_5			0x30
37#define ZX_CH_STA_6			0x34
38
39#define ZX_CTRL_MODA_16			(0 << 6)
40#define ZX_CTRL_MODA_18			BIT(6)
41#define ZX_CTRL_MODA_20			(2 << 6)
42#define ZX_CTRL_MODA_24			(3 << 6)
43#define ZX_CTRL_MODA_MASK		(3 << 6)
44
45#define ZX_CTRL_ENB			BIT(4)
46#define ZX_CTRL_DNB			(0 << 4)
47#define ZX_CTRL_ENB_MASK		BIT(4)
48
49#define ZX_CTRL_TX_OPEN			BIT(0)
50#define ZX_CTRL_TX_CLOSE		(0 << 0)
51#define ZX_CTRL_TX_MASK			BIT(0)
52
53#define ZX_CTRL_OPEN			(ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
54#define ZX_CTRL_CLOSE			(ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
55
56#define ZX_CTRL_DOUBLE_TRACK		(0 << 8)
57#define ZX_CTRL_LEFT_TRACK		BIT(8)
58#define ZX_CTRL_RIGHT_TRACK		(2 << 8)
59#define ZX_CTRL_TRACK_MASK		(3 << 8)
60
61#define ZX_FIFOCTRL_TXTH_MASK		(0x1f << 8)
62#define ZX_FIFOCTRL_TXTH(x)		(x << 8)
63#define ZX_FIFOCTRL_TX_DMA_EN		BIT(2)
64#define ZX_FIFOCTRL_TX_DMA_DIS		(0 << 2)
65#define ZX_FIFOCTRL_TX_DMA_EN_MASK	BIT(2)
66#define ZX_FIFOCTRL_TX_FIFO_RST		BIT(0)
67#define ZX_FIFOCTRL_TX_FIFO_RST_MASK	BIT(0)
68
69#define ZX_VALID_DOUBLE_TRACK		(0 << 0)
70#define ZX_VALID_LEFT_TRACK		BIT(1)
71#define ZX_VALID_RIGHT_TRACK		(2 << 0)
72#define ZX_VALID_TRACK_MASK		(3 << 0)
73
74#define ZX_SPDIF_CLK_RAT		(4 * 32)
75
76struct zx_spdif_info {
77	struct snd_dmaengine_dai_dma_data	dma_data;
78	struct clk				*dai_clk;
79	void __iomem				*reg_base;
80	resource_size_t				mapbase;
81};
82
83static int zx_spdif_dai_probe(struct snd_soc_dai *dai)
84{
85	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
86
87	snd_soc_dai_set_drvdata(dai, zx_spdif);
88	zx_spdif->dma_data.addr = zx_spdif->mapbase + ZX_DATA;
89	zx_spdif->dma_data.maxburst = 8;
90	snd_soc_dai_init_dma_data(dai, &zx_spdif->dma_data, NULL);
91	return 0;
92}
93
94static int zx_spdif_chanstats(void __iomem *base, unsigned int rate)
95{
96	u32 cstas1;
97
98	switch (rate) {
99	case 22050:
100		cstas1 = IEC958_AES3_CON_FS_22050;
101		break;
102	case 24000:
103		cstas1 = IEC958_AES3_CON_FS_24000;
104		break;
105	case 32000:
106		cstas1 = IEC958_AES3_CON_FS_32000;
107		break;
108	case 44100:
109		cstas1 = IEC958_AES3_CON_FS_44100;
110		break;
111	case 48000:
112		cstas1 = IEC958_AES3_CON_FS_48000;
113		break;
114	case 88200:
115		cstas1 = IEC958_AES3_CON_FS_88200;
116		break;
117	case 96000:
118		cstas1 = IEC958_AES3_CON_FS_96000;
119		break;
120	case 176400:
121		cstas1 = IEC958_AES3_CON_FS_176400;
122		break;
123	case 192000:
124		cstas1 = IEC958_AES3_CON_FS_192000;
125		break;
126	default:
127		return -EINVAL;
128	}
129	cstas1 = cstas1 << 24;
130	cstas1 |= IEC958_AES0_CON_NOT_COPYRIGHT;
131
132	writel_relaxed(cstas1, base + ZX_CH_STA_1);
133	return 0;
134}
135
136static int zx_spdif_hw_params(struct snd_pcm_substream *substream,
137			      struct snd_pcm_hw_params *params,
138			      struct snd_soc_dai *socdai)
139{
140	struct zx_spdif_info *zx_spdif = dev_get_drvdata(socdai->dev);
141	struct zx_spdif_info *spdif = snd_soc_dai_get_drvdata(socdai);
142	struct snd_dmaengine_dai_dma_data *dma_data = &zx_spdif->dma_data;
143	u32 val, ch_num, rate;
144	int ret;
145
146	dma_data = snd_soc_dai_get_dma_data(socdai, substream);
147	dma_data->addr_width = params_width(params) >> 3;
148
149	val = readl_relaxed(zx_spdif->reg_base + ZX_CTRL);
150	val &= ~ZX_CTRL_MODA_MASK;
151	switch (params_format(params)) {
152	case SNDRV_PCM_FORMAT_S16_LE:
153		val |= ZX_CTRL_MODA_16;
154		break;
155
156	case SNDRV_PCM_FORMAT_S18_3LE:
157		val |= ZX_CTRL_MODA_18;
158		break;
159
160	case SNDRV_PCM_FORMAT_S20_3LE:
161		val |= ZX_CTRL_MODA_20;
162		break;
163
164	case SNDRV_PCM_FORMAT_S24_LE:
165		val |= ZX_CTRL_MODA_24;
166		break;
167	default:
168		dev_err(socdai->dev, "Format not support!\n");
169		return -EINVAL;
170	}
171
172	ch_num = params_channels(params);
173	if (ch_num == 2)
174		val |= ZX_CTRL_DOUBLE_TRACK;
175	else
176		val |= ZX_CTRL_LEFT_TRACK;
177	writel_relaxed(val, zx_spdif->reg_base + ZX_CTRL);
178
179	val = readl_relaxed(zx_spdif->reg_base + ZX_VALID_BIT);
180	val &= ~ZX_VALID_TRACK_MASK;
181	if (ch_num == 2)
182		val |= ZX_VALID_DOUBLE_TRACK;
183	else
184		val |= ZX_VALID_RIGHT_TRACK;
185	writel_relaxed(val, zx_spdif->reg_base + ZX_VALID_BIT);
186
187	rate = params_rate(params);
188	ret = zx_spdif_chanstats(zx_spdif->reg_base, rate);
189	if (ret)
190		return ret;
191	return clk_set_rate(spdif->dai_clk, rate * ch_num * ZX_SPDIF_CLK_RAT);
192}
193
194static void zx_spdif_cfg_tx(void __iomem *base, int on)
195{
196	u32 val;
197
198	val = readl_relaxed(base + ZX_CTRL);
199	val &= ~(ZX_CTRL_ENB_MASK | ZX_CTRL_TX_MASK);
200	val |= on ? ZX_CTRL_OPEN : ZX_CTRL_CLOSE;
201	writel_relaxed(val, base + ZX_CTRL);
202
203	val = readl_relaxed(base + ZX_FIFOCTRL);
204	val &= ~ZX_FIFOCTRL_TX_DMA_EN_MASK;
205	if (on)
206		val |= ZX_FIFOCTRL_TX_DMA_EN;
207	writel_relaxed(val, base + ZX_FIFOCTRL);
208}
209
210static int zx_spdif_trigger(struct snd_pcm_substream *substream, int cmd,
211			    struct snd_soc_dai *dai)
212{
213	u32 val;
214	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
215	int  ret = 0;
216
217	switch (cmd) {
218	case SNDRV_PCM_TRIGGER_START:
219		val = readl_relaxed(zx_spdif->reg_base + ZX_FIFOCTRL);
220		val |= ZX_FIFOCTRL_TX_FIFO_RST;
221		writel_relaxed(val, zx_spdif->reg_base + ZX_FIFOCTRL);
222	/* fall thru */
223	case SNDRV_PCM_TRIGGER_RESUME:
224	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
225		zx_spdif_cfg_tx(zx_spdif->reg_base, true);
226		break;
227
228	case SNDRV_PCM_TRIGGER_STOP:
229	case SNDRV_PCM_TRIGGER_SUSPEND:
230	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
231		zx_spdif_cfg_tx(zx_spdif->reg_base, false);
232		break;
233
234	default:
235		ret = -EINVAL;
236		break;
237	}
238
239	return ret;
240}
241
242static int zx_spdif_startup(struct snd_pcm_substream *substream,
243			    struct snd_soc_dai *dai)
244{
245	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
246
247	return clk_prepare_enable(zx_spdif->dai_clk);
248}
249
250static void zx_spdif_shutdown(struct snd_pcm_substream *substream,
251			      struct snd_soc_dai *dai)
252{
253	struct zx_spdif_info *zx_spdif = dev_get_drvdata(dai->dev);
254
255	clk_disable_unprepare(zx_spdif->dai_clk);
256}
257
258#define ZX_RATES \
259	(SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
260	SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
261	SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
262
263#define ZX_FORMAT \
264	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
265	| SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
266
267static struct snd_soc_dai_ops zx_spdif_dai_ops = {
268	.trigger	= zx_spdif_trigger,
269	.startup	= zx_spdif_startup,
270	.shutdown	= zx_spdif_shutdown,
271	.hw_params	= zx_spdif_hw_params,
272};
273
274static struct snd_soc_dai_driver zx_spdif_dai = {
275	.name = "spdif",
276	.id = 0,
277	.probe = zx_spdif_dai_probe,
278	.playback = {
279		.channels_min = 1,
280		.channels_max = 2,
281		.rates = ZX_RATES,
282		.formats = ZX_FORMAT,
283	},
284	.ops = &zx_spdif_dai_ops,
285};
286
287static const struct snd_soc_component_driver zx_spdif_component = {
288	.name	= "spdif",
289};
290
291static void zx_spdif_dev_init(void __iomem *base)
292{
293	u32 val;
294
295	writel_relaxed(0, base + ZX_CTRL);
296	writel_relaxed(0, base + ZX_INT_MASK);
297	writel_relaxed(0xf, base + ZX_INT_STATUS);
298	writel_relaxed(0x1, base + ZX_FIFOCTRL);
299
300	val = readl_relaxed(base + ZX_FIFOCTRL);
301	val &= ~(ZX_FIFOCTRL_TXTH_MASK | ZX_FIFOCTRL_TX_FIFO_RST_MASK);
302	val |= ZX_FIFOCTRL_TXTH(8);
303	writel_relaxed(val, base + ZX_FIFOCTRL);
304}
305
306static int zx_spdif_probe(struct platform_device *pdev)
307{
308	struct resource *res;
309	struct zx_spdif_info *zx_spdif;
310	int ret;
311
312	zx_spdif = devm_kzalloc(&pdev->dev, sizeof(*zx_spdif), GFP_KERNEL);
313	if (!zx_spdif)
314		return -ENOMEM;
315
316	zx_spdif->dai_clk = devm_clk_get(&pdev->dev, "tx");
317	if (IS_ERR(zx_spdif->dai_clk)) {
318		dev_err(&pdev->dev, "Fail to get clk\n");
319		return PTR_ERR(zx_spdif->dai_clk);
320	}
321
322	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
323	zx_spdif->mapbase = res->start;
324	zx_spdif->reg_base = devm_ioremap_resource(&pdev->dev, res);
325	if (IS_ERR(zx_spdif->reg_base)) {
326		dev_err(&pdev->dev, "ioremap failed!\n");
327		return PTR_ERR(zx_spdif->reg_base);
328	}
329
330	zx_spdif_dev_init(zx_spdif->reg_base);
331	platform_set_drvdata(pdev, zx_spdif);
332
333	ret = devm_snd_soc_register_component(&pdev->dev, &zx_spdif_component,
334					 &zx_spdif_dai, 1);
335	if (ret) {
336		dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
337		return ret;
338	}
339
340	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
341	if (ret)
342		dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
343
344	return ret;
345}
346
347static const struct of_device_id zx_spdif_dt_ids[] = {
348	{ .compatible = "zte,zx296702-spdif", },
349	{}
350};
351MODULE_DEVICE_TABLE(of, zx_spdif_dt_ids);
352
353static struct platform_driver spdif_driver = {
354	.probe = zx_spdif_probe,
355	.driver = {
356		.name = "zx-spdif",
357		.of_match_table = zx_spdif_dt_ids,
358	},
359};
360
361module_platform_driver(spdif_driver);
362
363MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
364MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
365MODULE_LICENSE("GPL");
366