1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2017 ZTE Ltd
7 * Author: Baoyou Xie <baoyou.xie@linaro.org>
10 #include <linux/clk.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>
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
28 #define FIFO_CTRL_TX_RST BIT(0)
29 #define FIFO_CTRL_RX_RST BIT(0)
30 #define DEAGULT_FIFO_THRES GENMASK(4, 2)
32 #define FIFO_CTRL_TX_DMA_EN BIT(1)
33 #define FIFO_CTRL_RX_DMA_EN BIT(1)
35 #define TX_FIFO_RST_MASK BIT(0)
36 #define RX_FIFO_RST_MASK BIT(0)
38 #define FIFOCTRL_TX_FIFO_RST BIT(0)
39 #define FIFOCTRL_RX_FIFO_RST BIT(0)
41 #define TXTH_MASK GENMASK(5, 2)
42 #define RXTH_MASK GENMASK(5, 2)
44 #define FIFOCTRL_THRESHOLD(x) ((x) << 2)
46 #define TIMING_MS_MASK BIT(1)
48 * 00: 8 clk cycles every timeslot
49 * 01: 16 clk cycles every timeslot
50 * 10: 32 clk cycles every timeslot
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
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)
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
69 #define INT_DISABLE_ALL 0
70 #define INT_STATUS_MASK GENMASK(6, 0)
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
;
83 static inline u32
zx_tdm_readl(struct zx_tdm_info
*tdm
, u16 reg
)
85 return readl_relaxed(tdm
->regbase
+ reg
);
88 static inline void zx_tdm_writel(struct zx_tdm_info
*tdm
, u16 reg
, u32 val
)
90 writel_relaxed(val
, tdm
->regbase
+ reg
);
93 static void zx_tdm_tx_en(struct zx_tdm_info
*tdm
, bool on
)
97 val
= zx_tdm_readl(tdm
, REG_PROCESS_CTRL
);
99 val
|= PROCESS_TX_EN
| PROCESS_TDM_EN
;
101 val
&= ~(PROCESS_TX_EN
| PROCESS_TDM_EN
);
102 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, val
);
105 static void zx_tdm_rx_en(struct zx_tdm_info
*tdm
, bool on
)
109 val
= zx_tdm_readl(tdm
, REG_PROCESS_CTRL
);
111 val
|= PROCESS_RX_EN
| PROCESS_TDM_EN
;
113 val
&= ~(PROCESS_RX_EN
| PROCESS_TDM_EN
);
114 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, val
);
117 static void zx_tdm_tx_dma_en(struct zx_tdm_info
*tdm
, bool on
)
121 val
= zx_tdm_readl(tdm
, REG_TX_FIFO_CTRL
);
122 val
|= FIFO_CTRL_TX_RST
| DEAGULT_FIFO_THRES
;
124 val
|= FIFO_CTRL_TX_DMA_EN
;
126 val
&= ~FIFO_CTRL_TX_DMA_EN
;
127 zx_tdm_writel(tdm
, REG_TX_FIFO_CTRL
, val
);
130 static void zx_tdm_rx_dma_en(struct zx_tdm_info
*tdm
, bool on
)
134 val
= zx_tdm_readl(tdm
, REG_RX_FIFO_CTRL
);
135 val
|= FIFO_CTRL_RX_RST
| DEAGULT_FIFO_THRES
;
137 val
|= FIFO_CTRL_RX_DMA_EN
;
139 val
&= ~FIFO_CTRL_RX_DMA_EN
;
140 zx_tdm_writel(tdm
, REG_RX_FIFO_CTRL
, val
);
143 #define ZX_TDM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
145 #define ZX_TDM_FMTBIT \
146 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_MU_LAW | \
147 SNDRV_PCM_FMTBIT_A_LAW)
149 static int zx_tdm_dai_probe(struct snd_soc_dai
*dai
)
151 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
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
);
163 static int zx_tdm_set_fmt(struct snd_soc_dai
*cpu_dai
, unsigned int fmt
)
165 struct zx_tdm_info
*tdm
= snd_soc_dai_get_drvdata(cpu_dai
);
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
;
172 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
173 case SND_SOC_DAIFMT_CBM_CFM
:
175 val
|= TIMING_MASTER_MODE
;
177 case SND_SOC_DAIFMT_CBS_CFS
:
179 val
&= ~TIMING_MASTER_MODE
;
182 dev_err(cpu_dai
->dev
, "Unknown master/slave format\n");
187 zx_tdm_writel(tdm
, REG_TIMING_CTRL
, val
);
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
)
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;
204 dma_data
= snd_soc_dai_get_dma_data(socdai
, substream
);
205 dma_data
->addr_width
= ch_num
>> 3;
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
:
214 dev_err(socdai
->dev
, "Unknown data format\n");
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
);
224 ret
= clk_set_rate(tdm
->dai_wclk
,
225 params_rate(params
) * TIMING_WIDTH_FACTOR
* ch_num
);
230 static int zx_tdm_trigger(struct snd_pcm_substream
*substream
, int cmd
,
231 struct snd_soc_dai
*dai
)
233 int capture
= (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
);
234 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
239 case SNDRV_PCM_TRIGGER_START
:
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
);
245 zx_tdm_rx_dma_en(zx_tdm
, true);
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
);
251 zx_tdm_tx_dma_en(zx_tdm
, true);
254 case SNDRV_PCM_TRIGGER_RESUME
:
255 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
257 zx_tdm_rx_en(zx_tdm
, true);
259 zx_tdm_tx_en(zx_tdm
, true);
261 case SNDRV_PCM_TRIGGER_STOP
:
263 zx_tdm_rx_dma_en(zx_tdm
, false);
265 zx_tdm_tx_dma_en(zx_tdm
, false);
267 case SNDRV_PCM_TRIGGER_SUSPEND
:
268 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
270 zx_tdm_rx_en(zx_tdm
, false);
272 zx_tdm_tx_en(zx_tdm
, false);
282 static int zx_tdm_startup(struct snd_pcm_substream
*substream
,
283 struct snd_soc_dai
*dai
)
285 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
288 ret
= clk_prepare_enable(zx_tdm
->dai_wclk
);
292 ret
= clk_prepare_enable(zx_tdm
->dai_pclk
);
294 clk_disable_unprepare(zx_tdm
->dai_wclk
);
301 static void zx_tdm_shutdown(struct snd_pcm_substream
*substream
,
302 struct snd_soc_dai
*dai
)
304 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
306 clk_disable_unprepare(zx_tdm
->dai_pclk
);
307 clk_disable_unprepare(zx_tdm
->dai_wclk
);
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
,
318 static const struct snd_soc_component_driver zx_tdm_component
= {
322 static void zx_tdm_init_state(struct zx_tdm_info
*tdm
)
326 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, PROCESS_DISABLE_ALL
);
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
);
334 zx_tdm_writel(tdm
, REG_INT_EN
, INT_DISABLE_ALL
);
336 * write INT_STATUS register to clear it.
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
);
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
);
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
);
353 static struct snd_soc_dai_driver zx_tdm_dai
= {
354 .name
= "zx-tdm-dai",
356 .probe
= zx_tdm_dai_probe
,
360 .rates
= ZX_TDM_RATES
,
361 .formats
= ZX_TDM_FMTBIT
,
366 .rates
= ZX_TDM_RATES
,
367 .formats
= ZX_TDM_FMTBIT
,
369 .ops
= &zx_tdm_dai_ops
,
372 static int zx_tdm_probe(struct platform_device
*pdev
)
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
;
383 zx_tdm
= devm_kzalloc(&pdev
->dev
, sizeof(*zx_tdm
), GFP_KERNEL
);
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
);
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
);
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
);
407 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
408 "zte,tdm-dma-sysctrl", 2, 0, &out_args
);
410 dev_err(&pdev
->dev
, "Fail to get zte,tdm-dma-sysctrl\n");
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
);
422 regmap_update_bits(regmap_sysctrl
, dma_reg_offset
, dma_mask
, dma_mask
);
423 of_node_put(out_args
.np
);
425 zx_tdm_init_state(zx_tdm
);
426 platform_set_drvdata(pdev
, zx_tdm
);
428 ret
= devm_snd_soc_register_component(&pdev
->dev
, &zx_tdm_component
,
431 dev_err(&pdev
->dev
, "Register DAI failed: %d\n", ret
);
435 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
437 dev_err(&pdev
->dev
, "Register platform PCM failed: %d\n", ret
);
442 static const struct of_device_id zx_tdm_dt_ids
[] = {
443 { .compatible
= "zte,zx296718-tdm", },
446 MODULE_DEVICE_TABLE(of
, zx_tdm_dt_ids
);
448 static struct platform_driver tdm_driver
= {
449 .probe
= zx_tdm_probe
,
452 .of_match_table
= zx_tdm_dt_ids
,
455 module_platform_driver(tdm_driver
);
457 MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
458 MODULE_DESCRIPTION("ZTE TDM DAI driver");
459 MODULE_LICENSE("GPL v2");