4 * Copyright (C) 2017 ZTE Ltd
6 * Author: Baoyou Xie <baoyou.xie@linaro.org>
8 * License terms: GNU General Public License (GPL) version 2
11 #include <linux/clk.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <sound/dmaengine_pcm.h>
16 #include <sound/pcm_params.h>
17 #include <sound/soc.h>
18 #include <sound/soc-dai.h>
20 #define REG_TIMING_CTRL 0x04
21 #define REG_TX_FIFO_CTRL 0x0C
22 #define REG_RX_FIFO_CTRL 0x10
23 #define REG_INT_EN 0x1C
24 #define REG_INT_STATUS 0x20
25 #define REG_DATABUF 0x24
26 #define REG_TS_MASK0 0x44
27 #define REG_PROCESS_CTRL 0x54
29 #define FIFO_CTRL_TX_RST BIT(0)
30 #define FIFO_CTRL_RX_RST BIT(0)
31 #define DEAGULT_FIFO_THRES GENMASK(4, 2)
33 #define FIFO_CTRL_TX_DMA_EN BIT(1)
34 #define FIFO_CTRL_RX_DMA_EN BIT(1)
36 #define TX_FIFO_RST_MASK BIT(0)
37 #define RX_FIFO_RST_MASK BIT(0)
39 #define FIFOCTRL_TX_FIFO_RST BIT(0)
40 #define FIFOCTRL_RX_FIFO_RST BIT(0)
42 #define TXTH_MASK GENMASK(5, 2)
43 #define RXTH_MASK GENMASK(5, 2)
45 #define FIFOCTRL_THRESHOLD(x) ((x) << 2)
47 #define TIMING_MS_MASK BIT(1)
49 * 00: 8 clk cycles every timeslot
50 * 01: 16 clk cycles every timeslot
51 * 10: 32 clk cycles every timeslot
53 #define TIMING_SYNC_WIDTH_MASK GENMASK(6, 5)
54 #define TIMING_WIDTH_SHIFT 5
55 #define TIMING_DEFAULT_WIDTH 0
56 #define TIMING_TS_WIDTH(x) ((x) << TIMING_WIDTH_SHIFT)
57 #define TIMING_WIDTH_FACTOR 8
59 #define TIMING_MASTER_MODE BIT(21)
60 #define TIMING_LSB_FIRST BIT(20)
61 #define TIMING_TS_NUM(x) (((x) - 1) << 7)
62 #define TIMING_CLK_SEL_MASK GENMASK(2, 0)
63 #define TIMING_CLK_SEL_DEF BIT(2)
65 #define PROCESS_TX_EN BIT(0)
66 #define PROCESS_RX_EN BIT(1)
67 #define PROCESS_TDM_EN BIT(2)
68 #define PROCESS_DISABLE_ALL 0
70 #define INT_DISABLE_ALL 0
71 #define INT_STATUS_MASK GENMASK(6, 0)
74 struct snd_dmaengine_dai_dma_data dma_playback
;
75 struct snd_dmaengine_dai_dma_data dma_capture
;
76 resource_size_t phy_addr
;
77 void __iomem
*regbase
;
84 static inline u32
zx_tdm_readl(struct zx_tdm_info
*tdm
, u16 reg
)
86 return readl_relaxed(tdm
->regbase
+ reg
);
89 static inline void zx_tdm_writel(struct zx_tdm_info
*tdm
, u16 reg
, u32 val
)
91 writel_relaxed(val
, tdm
->regbase
+ reg
);
94 static void zx_tdm_tx_en(struct zx_tdm_info
*tdm
, bool on
)
98 val
= zx_tdm_readl(tdm
, REG_PROCESS_CTRL
);
100 val
|= PROCESS_TX_EN
| PROCESS_TDM_EN
;
102 val
&= ~(PROCESS_TX_EN
| PROCESS_TDM_EN
);
103 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, val
);
106 static void zx_tdm_rx_en(struct zx_tdm_info
*tdm
, bool on
)
110 val
= zx_tdm_readl(tdm
, REG_PROCESS_CTRL
);
112 val
|= PROCESS_RX_EN
| PROCESS_TDM_EN
;
114 val
&= ~(PROCESS_RX_EN
| PROCESS_TDM_EN
);
115 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, val
);
118 static void zx_tdm_tx_dma_en(struct zx_tdm_info
*tdm
, bool on
)
122 val
= zx_tdm_readl(tdm
, REG_TX_FIFO_CTRL
);
123 val
|= FIFO_CTRL_TX_RST
| DEAGULT_FIFO_THRES
;
125 val
|= FIFO_CTRL_TX_DMA_EN
;
127 val
&= ~FIFO_CTRL_TX_DMA_EN
;
128 zx_tdm_writel(tdm
, REG_TX_FIFO_CTRL
, val
);
131 static void zx_tdm_rx_dma_en(struct zx_tdm_info
*tdm
, bool on
)
135 val
= zx_tdm_readl(tdm
, REG_RX_FIFO_CTRL
);
136 val
|= FIFO_CTRL_RX_RST
| DEAGULT_FIFO_THRES
;
138 val
|= FIFO_CTRL_RX_DMA_EN
;
140 val
&= ~FIFO_CTRL_RX_DMA_EN
;
141 zx_tdm_writel(tdm
, REG_RX_FIFO_CTRL
, val
);
144 #define ZX_TDM_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
146 #define ZX_TDM_FMTBIT \
147 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_MU_LAW | \
148 SNDRV_PCM_FORMAT_A_LAW)
150 static int zx_tdm_dai_probe(struct snd_soc_dai
*dai
)
152 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
154 snd_soc_dai_set_drvdata(dai
, zx_tdm
);
155 zx_tdm
->dma_playback
.addr
= zx_tdm
->phy_addr
+ REG_DATABUF
;
156 zx_tdm
->dma_playback
.maxburst
= 16;
157 zx_tdm
->dma_capture
.addr
= zx_tdm
->phy_addr
+ REG_DATABUF
;
158 zx_tdm
->dma_capture
.maxburst
= 16;
159 snd_soc_dai_init_dma_data(dai
, &zx_tdm
->dma_playback
,
160 &zx_tdm
->dma_capture
);
164 static int zx_tdm_set_fmt(struct snd_soc_dai
*cpu_dai
, unsigned int fmt
)
166 struct zx_tdm_info
*tdm
= snd_soc_dai_get_drvdata(cpu_dai
);
169 val
= zx_tdm_readl(tdm
, REG_TIMING_CTRL
);
170 val
&= ~(TIMING_SYNC_WIDTH_MASK
| TIMING_MS_MASK
);
171 val
|= TIMING_DEFAULT_WIDTH
<< TIMING_WIDTH_SHIFT
;
173 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
174 case SND_SOC_DAIFMT_CBM_CFM
:
176 val
|= TIMING_MASTER_MODE
;
178 case SND_SOC_DAIFMT_CBS_CFS
:
180 val
&= ~TIMING_MASTER_MODE
;
183 dev_err(cpu_dai
->dev
, "Unknown master/slave format\n");
188 zx_tdm_writel(tdm
, REG_TIMING_CTRL
, val
);
193 static int zx_tdm_hw_params(struct snd_pcm_substream
*substream
,
194 struct snd_pcm_hw_params
*params
,
195 struct snd_soc_dai
*socdai
)
197 struct zx_tdm_info
*tdm
= snd_soc_dai_get_drvdata(socdai
);
198 struct snd_dmaengine_dai_dma_data
*dma_data
;
199 unsigned int ts_width
= TIMING_DEFAULT_WIDTH
;
200 unsigned int ch_num
= 32;
201 unsigned int mask
= 0;
202 unsigned int ret
= 0;
205 dma_data
= snd_soc_dai_get_dma_data(socdai
, substream
);
206 dma_data
->addr_width
= ch_num
>> 3;
208 switch (params_format(params
)) {
209 case SNDRV_PCM_FORMAT_MU_LAW
:
210 case SNDRV_PCM_FORMAT_A_LAW
:
211 case SNDRV_PCM_FORMAT_S16_LE
:
216 dev_err(socdai
->dev
, "Unknown data format\n");
220 val
= zx_tdm_readl(tdm
, REG_TIMING_CTRL
);
221 val
|= TIMING_TS_WIDTH(ts_width
) | TIMING_TS_NUM(1);
222 zx_tdm_writel(tdm
, REG_TIMING_CTRL
, val
);
223 zx_tdm_writel(tdm
, REG_TS_MASK0
, mask
);
226 ret
= clk_set_rate(tdm
->dai_wclk
,
227 params_rate(params
) * TIMING_WIDTH_FACTOR
* ch_num
);
232 static int zx_tdm_trigger(struct snd_pcm_substream
*substream
, int cmd
,
233 struct snd_soc_dai
*dai
)
235 int capture
= (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
);
236 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
241 case SNDRV_PCM_TRIGGER_START
:
243 val
= zx_tdm_readl(zx_tdm
, REG_RX_FIFO_CTRL
);
244 val
|= FIFOCTRL_RX_FIFO_RST
;
245 zx_tdm_writel(zx_tdm
, REG_RX_FIFO_CTRL
, val
);
247 zx_tdm_rx_dma_en(zx_tdm
, true);
249 val
= zx_tdm_readl(zx_tdm
, REG_TX_FIFO_CTRL
);
250 val
|= FIFOCTRL_TX_FIFO_RST
;
251 zx_tdm_writel(zx_tdm
, REG_TX_FIFO_CTRL
, val
);
253 zx_tdm_tx_dma_en(zx_tdm
, true);
256 case SNDRV_PCM_TRIGGER_RESUME
:
257 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
259 zx_tdm_rx_en(zx_tdm
, true);
261 zx_tdm_tx_en(zx_tdm
, true);
263 case SNDRV_PCM_TRIGGER_STOP
:
265 zx_tdm_rx_dma_en(zx_tdm
, false);
267 zx_tdm_tx_dma_en(zx_tdm
, false);
269 case SNDRV_PCM_TRIGGER_SUSPEND
:
270 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
272 zx_tdm_rx_en(zx_tdm
, false);
274 zx_tdm_tx_en(zx_tdm
, false);
284 static int zx_tdm_startup(struct snd_pcm_substream
*substream
,
285 struct snd_soc_dai
*dai
)
287 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
290 ret
= clk_prepare_enable(zx_tdm
->dai_wclk
);
294 ret
= clk_prepare_enable(zx_tdm
->dai_pclk
);
296 clk_disable_unprepare(zx_tdm
->dai_wclk
);
303 static void zx_tdm_shutdown(struct snd_pcm_substream
*substream
,
304 struct snd_soc_dai
*dai
)
306 struct zx_tdm_info
*zx_tdm
= dev_get_drvdata(dai
->dev
);
308 clk_disable_unprepare(zx_tdm
->dai_pclk
);
309 clk_disable_unprepare(zx_tdm
->dai_wclk
);
312 static const struct snd_soc_dai_ops zx_tdm_dai_ops
= {
313 .trigger
= zx_tdm_trigger
,
314 .hw_params
= zx_tdm_hw_params
,
315 .set_fmt
= zx_tdm_set_fmt
,
316 .startup
= zx_tdm_startup
,
317 .shutdown
= zx_tdm_shutdown
,
320 static const struct snd_soc_component_driver zx_tdm_component
= {
324 static void zx_tdm_init_state(struct zx_tdm_info
*tdm
)
328 zx_tdm_writel(tdm
, REG_PROCESS_CTRL
, PROCESS_DISABLE_ALL
);
330 val
= zx_tdm_readl(tdm
, REG_TIMING_CTRL
);
331 val
|= TIMING_LSB_FIRST
;
332 val
&= ~TIMING_CLK_SEL_MASK
;
333 val
|= TIMING_CLK_SEL_DEF
;
334 zx_tdm_writel(tdm
, REG_TIMING_CTRL
, val
);
336 zx_tdm_writel(tdm
, REG_INT_EN
, INT_DISABLE_ALL
);
338 * write INT_STATUS register to clear it.
340 zx_tdm_writel(tdm
, REG_INT_STATUS
, INT_STATUS_MASK
);
341 zx_tdm_writel(tdm
, REG_RX_FIFO_CTRL
, FIFOCTRL_RX_FIFO_RST
);
342 zx_tdm_writel(tdm
, REG_TX_FIFO_CTRL
, FIFOCTRL_TX_FIFO_RST
);
344 val
= zx_tdm_readl(tdm
, REG_RX_FIFO_CTRL
);
345 val
&= ~(RXTH_MASK
| RX_FIFO_RST_MASK
);
346 val
|= FIFOCTRL_THRESHOLD(8);
347 zx_tdm_writel(tdm
, REG_RX_FIFO_CTRL
, val
);
349 val
= zx_tdm_readl(tdm
, REG_TX_FIFO_CTRL
);
350 val
&= ~(TXTH_MASK
| TX_FIFO_RST_MASK
);
351 val
|= FIFOCTRL_THRESHOLD(8);
352 zx_tdm_writel(tdm
, REG_TX_FIFO_CTRL
, val
);
355 static struct snd_soc_dai_driver zx_tdm_dai
= {
356 .name
= "zx-tdm-dai",
358 .probe
= zx_tdm_dai_probe
,
362 .rates
= ZX_TDM_RATES
,
363 .formats
= ZX_TDM_FMTBIT
,
368 .rates
= ZX_TDM_RATES
,
369 .formats
= ZX_TDM_FMTBIT
,
371 .ops
= &zx_tdm_dai_ops
,
374 static int zx_tdm_probe(struct platform_device
*pdev
)
376 struct device
*dev
= &pdev
->dev
;
377 struct of_phandle_args out_args
;
378 unsigned int dma_reg_offset
;
379 struct zx_tdm_info
*zx_tdm
;
380 unsigned int dma_mask
;
381 struct resource
*res
;
382 struct regmap
*regmap_sysctrl
;
385 zx_tdm
= devm_kzalloc(&pdev
->dev
, sizeof(*zx_tdm
), GFP_KERNEL
);
391 zx_tdm
->dai_wclk
= devm_clk_get(&pdev
->dev
, "wclk");
392 if (IS_ERR(zx_tdm
->dai_wclk
)) {
393 dev_err(&pdev
->dev
, "Fail to get wclk\n");
394 return PTR_ERR(zx_tdm
->dai_wclk
);
397 zx_tdm
->dai_pclk
= devm_clk_get(&pdev
->dev
, "pclk");
398 if (IS_ERR(zx_tdm
->dai_pclk
)) {
399 dev_err(&pdev
->dev
, "Fail to get pclk\n");
400 return PTR_ERR(zx_tdm
->dai_pclk
);
403 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
404 zx_tdm
->phy_addr
= res
->start
;
405 zx_tdm
->regbase
= devm_ioremap_resource(&pdev
->dev
, res
);
406 if (IS_ERR(zx_tdm
->regbase
))
407 return PTR_ERR(zx_tdm
->regbase
);
409 ret
= of_parse_phandle_with_fixed_args(pdev
->dev
.of_node
,
410 "zte,tdm-dma-sysctrl", 2, 0, &out_args
);
412 dev_err(&pdev
->dev
, "Fail to get zte,tdm-dma-sysctrl\n");
416 dma_reg_offset
= out_args
.args
[0];
417 dma_mask
= out_args
.args
[1];
418 regmap_sysctrl
= syscon_node_to_regmap(out_args
.np
);
419 if (IS_ERR(regmap_sysctrl
)) {
420 of_node_put(out_args
.np
);
421 return PTR_ERR(regmap_sysctrl
);
424 regmap_update_bits(regmap_sysctrl
, dma_reg_offset
, dma_mask
, dma_mask
);
425 of_node_put(out_args
.np
);
427 zx_tdm_init_state(zx_tdm
);
428 platform_set_drvdata(pdev
, zx_tdm
);
430 ret
= devm_snd_soc_register_component(&pdev
->dev
, &zx_tdm_component
,
433 dev_err(&pdev
->dev
, "Register DAI failed: %d\n", ret
);
437 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
439 dev_err(&pdev
->dev
, "Register platform PCM failed: %d\n", ret
);
444 static const struct of_device_id zx_tdm_dt_ids
[] = {
445 { .compatible
= "zte,zx296718-tdm", },
448 MODULE_DEVICE_TABLE(of
, zx_tdm_dt_ids
);
450 static struct platform_driver tdm_driver
= {
451 .probe
= zx_tdm_probe
,
454 .of_match_table
= zx_tdm_dt_ids
,
457 module_platform_driver(tdm_driver
);
459 MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
460 MODULE_DESCRIPTION("ZTE TDM DAI driver");
461 MODULE_LICENSE("GPL v2");