• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ZTE's TDM driver
4  *
5  * Copyright (C) 2017 ZTE Ltd
6  *
7  * Author: Baoyou Xie <baoyou.xie@linaro.org>
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/io.h>
12 #include <linux/mfd/syscon.h>
13 #include <linux/module.h>
14 #include <sound/dmaengine_pcm.h>
15 #include <sound/pcm_params.h>
16 #include <sound/soc.h>
17 #include <sound/soc-dai.h>
18 
19 #define	REG_TIMING_CTRL		0x04
20 #define	REG_TX_FIFO_CTRL	0x0C
21 #define	REG_RX_FIFO_CTRL	0x10
22 #define REG_INT_EN		0x1C
23 #define REG_INT_STATUS		0x20
24 #define REG_DATABUF		0x24
25 #define REG_TS_MASK0		0x44
26 #define REG_PROCESS_CTRL	0x54
27 
28 #define FIFO_CTRL_TX_RST	BIT(0)
29 #define FIFO_CTRL_RX_RST	BIT(0)
30 #define DEAGULT_FIFO_THRES	GENMASK(4, 2)
31 
32 #define FIFO_CTRL_TX_DMA_EN	BIT(1)
33 #define FIFO_CTRL_RX_DMA_EN	BIT(1)
34 
35 #define TX_FIFO_RST_MASK	BIT(0)
36 #define RX_FIFO_RST_MASK	BIT(0)
37 
38 #define FIFOCTRL_TX_FIFO_RST	BIT(0)
39 #define FIFOCTRL_RX_FIFO_RST	BIT(0)
40 
41 #define TXTH_MASK		GENMASK(5, 2)
42 #define RXTH_MASK		GENMASK(5, 2)
43 
44 #define FIFOCTRL_THRESHOLD(x)	((x) << 2)
45 
46 #define TIMING_MS_MASK		BIT(1)
47 /*
48  * 00: 8 clk cycles every timeslot
49  * 01: 16 clk cycles every timeslot
50  * 10: 32 clk cycles every timeslot
51  */
52 #define TIMING_SYNC_WIDTH_MASK	GENMASK(6, 5)
53 #define TIMING_WIDTH_SHIFT      5
54 #define TIMING_DEFAULT_WIDTH    0
55 #define TIMING_TS_WIDTH(x)	((x) << TIMING_WIDTH_SHIFT)
56 #define TIMING_WIDTH_FACTOR     8
57 
58 #define TIMING_MASTER_MODE	BIT(21)
59 #define TIMING_LSB_FIRST	BIT(20)
60 #define TIMING_TS_NUM(x)	(((x) - 1) << 7)
61 #define TIMING_CLK_SEL_MASK	GENMASK(2, 0)
62 #define TIMING_CLK_SEL_DEF	BIT(2)
63 
64 #define PROCESS_TX_EN		BIT(0)
65 #define PROCESS_RX_EN		BIT(1)
66 #define PROCESS_TDM_EN		BIT(2)
67 #define PROCESS_DISABLE_ALL	0
68 
69 #define INT_DISABLE_ALL		0
70 #define INT_STATUS_MASK		GENMASK(6, 0)
71 
72 struct zx_tdm_info {
73 	struct snd_dmaengine_dai_dma_data	dma_playback;
74 	struct snd_dmaengine_dai_dma_data	dma_capture;
75 	resource_size_t				phy_addr;
76 	void __iomem				*regbase;
77 	struct clk				*dai_wclk;
78 	struct clk				*dai_pclk;
79 	int					master;
80 	struct device				*dev;
81 };
82 
zx_tdm_readl(struct zx_tdm_info * tdm,u16 reg)83 static inline u32 zx_tdm_readl(struct zx_tdm_info *tdm, u16 reg)
84 {
85 	return readl_relaxed(tdm->regbase + reg);
86 }
87 
zx_tdm_writel(struct zx_tdm_info * tdm,u16 reg,u32 val)88 static inline void zx_tdm_writel(struct zx_tdm_info *tdm, u16 reg, u32 val)
89 {
90 	writel_relaxed(val, tdm->regbase + reg);
91 }
92 
zx_tdm_tx_en(struct zx_tdm_info * tdm,bool on)93 static void zx_tdm_tx_en(struct zx_tdm_info *tdm, bool on)
94 {
95 	unsigned long val;
96 
97 	val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
98 	if (on)
99 		val |= PROCESS_TX_EN | PROCESS_TDM_EN;
100 	else
101 		val &= ~(PROCESS_TX_EN | PROCESS_TDM_EN);
102 	zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
103 }
104 
zx_tdm_rx_en(struct zx_tdm_info * tdm,bool on)105 static void zx_tdm_rx_en(struct zx_tdm_info *tdm, bool on)
106 {
107 	unsigned long val;
108 
109 	val = zx_tdm_readl(tdm, REG_PROCESS_CTRL);
110 	if (on)
111 		val |= PROCESS_RX_EN | PROCESS_TDM_EN;
112 	else
113 		val &= ~(PROCESS_RX_EN | PROCESS_TDM_EN);
114 	zx_tdm_writel(tdm, REG_PROCESS_CTRL, val);
115 }
116 
zx_tdm_tx_dma_en(struct zx_tdm_info * tdm,bool on)117 static void zx_tdm_tx_dma_en(struct zx_tdm_info *tdm, bool on)
118 {
119 	unsigned long val;
120 
121 	val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
122 	val |= FIFO_CTRL_TX_RST | DEAGULT_FIFO_THRES;
123 	if (on)
124 		val |= FIFO_CTRL_TX_DMA_EN;
125 	else
126 		val &= ~FIFO_CTRL_TX_DMA_EN;
127 	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
128 }
129 
zx_tdm_rx_dma_en(struct zx_tdm_info * tdm,bool on)130 static void zx_tdm_rx_dma_en(struct zx_tdm_info *tdm, bool on)
131 {
132 	unsigned long val;
133 
134 	val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
135 	val |= FIFO_CTRL_RX_RST | DEAGULT_FIFO_THRES;
136 	if (on)
137 		val |= FIFO_CTRL_RX_DMA_EN;
138 	else
139 		val &= ~FIFO_CTRL_RX_DMA_EN;
140 	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
141 }
142 
143 #define ZX_TDM_RATES	(SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
144 
145 #define ZX_TDM_FMTBIT \
146 	(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \
147 	SNDRV_PCM_FMTBIT_A_LAW)
148 
zx_tdm_dai_probe(struct snd_soc_dai * dai)149 static int zx_tdm_dai_probe(struct snd_soc_dai *dai)
150 {
151 	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
152 
153 	snd_soc_dai_set_drvdata(dai, zx_tdm);
154 	zx_tdm->dma_playback.addr = zx_tdm->phy_addr + REG_DATABUF;
155 	zx_tdm->dma_playback.maxburst = 16;
156 	zx_tdm->dma_capture.addr = zx_tdm->phy_addr + REG_DATABUF;
157 	zx_tdm->dma_capture.maxburst = 16;
158 	snd_soc_dai_init_dma_data(dai, &zx_tdm->dma_playback,
159 				  &zx_tdm->dma_capture);
160 	return 0;
161 }
162 
zx_tdm_set_fmt(struct snd_soc_dai * cpu_dai,unsigned int fmt)163 static int zx_tdm_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
164 {
165 	struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(cpu_dai);
166 	unsigned long val;
167 
168 	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
169 	val &= ~(TIMING_SYNC_WIDTH_MASK | TIMING_MS_MASK);
170 	val |= TIMING_DEFAULT_WIDTH << TIMING_WIDTH_SHIFT;
171 
172 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
173 	case SND_SOC_DAIFMT_CBM_CFM:
174 		tdm->master = 1;
175 		val |= TIMING_MASTER_MODE;
176 		break;
177 	case SND_SOC_DAIFMT_CBS_CFS:
178 		tdm->master = 0;
179 		val &= ~TIMING_MASTER_MODE;
180 		break;
181 	default:
182 		dev_err(cpu_dai->dev, "Unknown master/slave format\n");
183 		return -EINVAL;
184 	}
185 
186 
187 	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
188 
189 	return 0;
190 }
191 
zx_tdm_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * socdai)192 static int zx_tdm_hw_params(struct snd_pcm_substream *substream,
193 			    struct snd_pcm_hw_params *params,
194 			    struct snd_soc_dai *socdai)
195 {
196 	struct zx_tdm_info *tdm = snd_soc_dai_get_drvdata(socdai);
197 	struct snd_dmaengine_dai_dma_data *dma_data;
198 	unsigned int ts_width = TIMING_DEFAULT_WIDTH;
199 	unsigned int ch_num = 32;
200 	unsigned int mask = 0;
201 	unsigned int ret = 0;
202 	unsigned long val;
203 
204 	dma_data = snd_soc_dai_get_dma_data(socdai, substream);
205 	dma_data->addr_width = ch_num >> 3;
206 
207 	switch (params_format(params)) {
208 	case SNDRV_PCM_FORMAT_MU_LAW:
209 	case SNDRV_PCM_FORMAT_A_LAW:
210 	case SNDRV_PCM_FORMAT_S16_LE:
211 		ts_width = 1;
212 		break;
213 	default:
214 		dev_err(socdai->dev, "Unknown data format\n");
215 		return -EINVAL;
216 	}
217 
218 	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
219 	val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1);
220 	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
221 	zx_tdm_writel(tdm, REG_TS_MASK0, mask);
222 
223 	if (tdm->master)
224 		ret = clk_set_rate(tdm->dai_wclk,
225 			params_rate(params) * TIMING_WIDTH_FACTOR * ch_num);
226 
227 	return ret;
228 }
229 
zx_tdm_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)230 static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
231 			  struct snd_soc_dai *dai)
232 {
233 	int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
234 	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
235 	unsigned int val;
236 	int ret = 0;
237 
238 	switch (cmd) {
239 	case SNDRV_PCM_TRIGGER_START:
240 		if (capture) {
241 			val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL);
242 			val |= FIFOCTRL_RX_FIFO_RST;
243 			zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val);
244 
245 			zx_tdm_rx_dma_en(zx_tdm, true);
246 		} else {
247 			val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL);
248 			val |= FIFOCTRL_TX_FIFO_RST;
249 			zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val);
250 
251 			zx_tdm_tx_dma_en(zx_tdm, true);
252 		}
253 		break;
254 	case SNDRV_PCM_TRIGGER_RESUME:
255 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
256 		if (capture)
257 			zx_tdm_rx_en(zx_tdm, true);
258 		else
259 			zx_tdm_tx_en(zx_tdm, true);
260 		break;
261 	case SNDRV_PCM_TRIGGER_STOP:
262 		if (capture)
263 			zx_tdm_rx_dma_en(zx_tdm, false);
264 		else
265 			zx_tdm_tx_dma_en(zx_tdm, false);
266 		break;
267 	case SNDRV_PCM_TRIGGER_SUSPEND:
268 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
269 		if (capture)
270 			zx_tdm_rx_en(zx_tdm, false);
271 		else
272 			zx_tdm_tx_en(zx_tdm, false);
273 		break;
274 	default:
275 		ret = -EINVAL;
276 		break;
277 	}
278 
279 	return ret;
280 }
281 
zx_tdm_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)282 static int zx_tdm_startup(struct snd_pcm_substream *substream,
283 			  struct snd_soc_dai *dai)
284 {
285 	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
286 	int ret;
287 
288 	ret = clk_prepare_enable(zx_tdm->dai_wclk);
289 	if (ret)
290 		return ret;
291 
292 	ret = clk_prepare_enable(zx_tdm->dai_pclk);
293 	if (ret) {
294 		clk_disable_unprepare(zx_tdm->dai_wclk);
295 		return ret;
296 	}
297 
298 	return 0;
299 }
300 
zx_tdm_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)301 static void zx_tdm_shutdown(struct snd_pcm_substream *substream,
302 			    struct snd_soc_dai *dai)
303 {
304 	struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
305 
306 	clk_disable_unprepare(zx_tdm->dai_pclk);
307 	clk_disable_unprepare(zx_tdm->dai_wclk);
308 }
309 
310 static const struct snd_soc_dai_ops zx_tdm_dai_ops = {
311 	.trigger	= zx_tdm_trigger,
312 	.hw_params	= zx_tdm_hw_params,
313 	.set_fmt	= zx_tdm_set_fmt,
314 	.startup	= zx_tdm_startup,
315 	.shutdown	= zx_tdm_shutdown,
316 };
317 
318 static const struct snd_soc_component_driver zx_tdm_component = {
319 	.name			= "zx-tdm",
320 };
321 
zx_tdm_init_state(struct zx_tdm_info * tdm)322 static void zx_tdm_init_state(struct zx_tdm_info *tdm)
323 {
324 	unsigned int val;
325 
326 	zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL);
327 
328 	val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
329 	val |= TIMING_LSB_FIRST;
330 	val &= ~TIMING_CLK_SEL_MASK;
331 	val |= TIMING_CLK_SEL_DEF;
332 	zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
333 
334 	zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL);
335 	/*
336 	 * write INT_STATUS register to clear it.
337 	 */
338 	zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK);
339 	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST);
340 	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST);
341 
342 	val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
343 	val &= ~(RXTH_MASK | RX_FIFO_RST_MASK);
344 	val |= FIFOCTRL_THRESHOLD(8);
345 	zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
346 
347 	val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
348 	val &= ~(TXTH_MASK | TX_FIFO_RST_MASK);
349 	val |= FIFOCTRL_THRESHOLD(8);
350 	zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
351 }
352 
353 static struct snd_soc_dai_driver zx_tdm_dai = {
354 	.name	= "zx-tdm-dai",
355 	.id	= 0,
356 	.probe	= zx_tdm_dai_probe,
357 	.playback   = {
358 		.channels_min	= 1,
359 		.channels_max	= 4,
360 		.rates		= ZX_TDM_RATES,
361 		.formats	= ZX_TDM_FMTBIT,
362 	},
363 	.capture = {
364 		.channels_min	= 1,
365 		.channels_max	= 4,
366 		.rates		= ZX_TDM_RATES,
367 		.formats	= ZX_TDM_FMTBIT,
368 	},
369 	.ops	= &zx_tdm_dai_ops,
370 };
371 
zx_tdm_probe(struct platform_device * pdev)372 static int zx_tdm_probe(struct platform_device *pdev)
373 {
374 	struct device *dev = &pdev->dev;
375 	struct of_phandle_args out_args;
376 	unsigned int dma_reg_offset;
377 	struct zx_tdm_info *zx_tdm;
378 	unsigned int dma_mask;
379 	struct resource *res;
380 	struct regmap *regmap_sysctrl;
381 	int ret;
382 
383 	zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
384 	if (!zx_tdm)
385 		return -ENOMEM;
386 
387 	zx_tdm->dev = dev;
388 
389 	zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
390 	if (IS_ERR(zx_tdm->dai_wclk)) {
391 		dev_err(&pdev->dev, "Fail to get wclk\n");
392 		return PTR_ERR(zx_tdm->dai_wclk);
393 	}
394 
395 	zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
396 	if (IS_ERR(zx_tdm->dai_pclk)) {
397 		dev_err(&pdev->dev, "Fail to get pclk\n");
398 		return PTR_ERR(zx_tdm->dai_pclk);
399 	}
400 
401 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
402 	zx_tdm->phy_addr = res->start;
403 	zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
404 	if (IS_ERR(zx_tdm->regbase))
405 		return PTR_ERR(zx_tdm->regbase);
406 
407 	ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
408 				"zte,tdm-dma-sysctrl", 2, 0, &out_args);
409 	if (ret) {
410 		dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
411 		return ret;
412 	}
413 
414 	dma_reg_offset = out_args.args[0];
415 	dma_mask = out_args.args[1];
416 	regmap_sysctrl = syscon_node_to_regmap(out_args.np);
417 	if (IS_ERR(regmap_sysctrl)) {
418 		of_node_put(out_args.np);
419 		return PTR_ERR(regmap_sysctrl);
420 	}
421 
422 	regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
423 	of_node_put(out_args.np);
424 
425 	zx_tdm_init_state(zx_tdm);
426 	platform_set_drvdata(pdev, zx_tdm);
427 
428 	ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
429 						&zx_tdm_dai, 1);
430 	if (ret) {
431 		dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
432 		return ret;
433 	}
434 
435 	ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
436 	if (ret)
437 		dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
438 
439 	return ret;
440 }
441 
442 static const struct of_device_id zx_tdm_dt_ids[] = {
443 	{ .compatible = "zte,zx296718-tdm", },
444 	{}
445 };
446 MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
447 
448 static struct platform_driver tdm_driver = {
449 	.probe = zx_tdm_probe,
450 	.driver = {
451 		.name = "zx-tdm",
452 		.of_match_table = zx_tdm_dt_ids,
453 	},
454 };
455 module_platform_driver(tdm_driver);
456 
457 MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
458 MODULE_DESCRIPTION("ZTE TDM DAI driver");
459 MODULE_LICENSE("GPL v2");
460