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