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:
215 dev_err(socdai->dev, "Unknown data format\n");
219 val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
220 val |= TIMING_TS_WIDTH(ts_width) | TIMING_TS_NUM(1);
221 zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
222 zx_tdm_writel(tdm, REG_TS_MASK0, mask);
225 ret = clk_set_rate(tdm->dai_wclk,
226 params_rate(params) * TIMING_WIDTH_FACTOR * ch_num);
231 static int zx_tdm_trigger(struct snd_pcm_substream *substream, int cmd,
232 struct snd_soc_dai *dai)
234 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
235 struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
240 case SNDRV_PCM_TRIGGER_START:
242 val = zx_tdm_readl(zx_tdm, REG_RX_FIFO_CTRL);
243 val |= FIFOCTRL_RX_FIFO_RST;
244 zx_tdm_writel(zx_tdm, REG_RX_FIFO_CTRL, val);
246 zx_tdm_rx_dma_en(zx_tdm, true);
248 val = zx_tdm_readl(zx_tdm, REG_TX_FIFO_CTRL);
249 val |= FIFOCTRL_TX_FIFO_RST;
250 zx_tdm_writel(zx_tdm, REG_TX_FIFO_CTRL, val);
252 zx_tdm_tx_dma_en(zx_tdm, true);
255 case SNDRV_PCM_TRIGGER_RESUME:
256 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
258 zx_tdm_rx_en(zx_tdm, true);
260 zx_tdm_tx_en(zx_tdm, true);
262 case SNDRV_PCM_TRIGGER_STOP:
264 zx_tdm_rx_dma_en(zx_tdm, false);
266 zx_tdm_tx_dma_en(zx_tdm, false);
268 case SNDRV_PCM_TRIGGER_SUSPEND:
269 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
271 zx_tdm_rx_en(zx_tdm, false);
273 zx_tdm_tx_en(zx_tdm, false);
283 static int zx_tdm_startup(struct snd_pcm_substream *substream,
284 struct snd_soc_dai *dai)
286 struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
289 ret = clk_prepare_enable(zx_tdm->dai_wclk);
293 ret = clk_prepare_enable(zx_tdm->dai_pclk);
295 clk_disable_unprepare(zx_tdm->dai_wclk);
302 static void zx_tdm_shutdown(struct snd_pcm_substream *substream,
303 struct snd_soc_dai *dai)
305 struct zx_tdm_info *zx_tdm = dev_get_drvdata(dai->dev);
307 clk_disable_unprepare(zx_tdm->dai_pclk);
308 clk_disable_unprepare(zx_tdm->dai_wclk);
311 static const struct snd_soc_dai_ops zx_tdm_dai_ops = {
312 .trigger = zx_tdm_trigger,
313 .hw_params = zx_tdm_hw_params,
314 .set_fmt = zx_tdm_set_fmt,
315 .startup = zx_tdm_startup,
316 .shutdown = zx_tdm_shutdown,
319 static const struct snd_soc_component_driver zx_tdm_component = {
323 static void zx_tdm_init_state(struct zx_tdm_info *tdm)
327 zx_tdm_writel(tdm, REG_PROCESS_CTRL, PROCESS_DISABLE_ALL);
329 val = zx_tdm_readl(tdm, REG_TIMING_CTRL);
330 val |= TIMING_LSB_FIRST;
331 val &= ~TIMING_CLK_SEL_MASK;
332 val |= TIMING_CLK_SEL_DEF;
333 zx_tdm_writel(tdm, REG_TIMING_CTRL, val);
335 zx_tdm_writel(tdm, REG_INT_EN, INT_DISABLE_ALL);
337 * write INT_STATUS register to clear it.
339 zx_tdm_writel(tdm, REG_INT_STATUS, INT_STATUS_MASK);
340 zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, FIFOCTRL_RX_FIFO_RST);
341 zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, FIFOCTRL_TX_FIFO_RST);
343 val = zx_tdm_readl(tdm, REG_RX_FIFO_CTRL);
344 val &= ~(RXTH_MASK | RX_FIFO_RST_MASK);
345 val |= FIFOCTRL_THRESHOLD(8);
346 zx_tdm_writel(tdm, REG_RX_FIFO_CTRL, val);
348 val = zx_tdm_readl(tdm, REG_TX_FIFO_CTRL);
349 val &= ~(TXTH_MASK | TX_FIFO_RST_MASK);
350 val |= FIFOCTRL_THRESHOLD(8);
351 zx_tdm_writel(tdm, REG_TX_FIFO_CTRL, val);
354 static struct snd_soc_dai_driver zx_tdm_dai = {
355 .name = "zx-tdm-dai",
357 .probe = zx_tdm_dai_probe,
361 .rates = ZX_TDM_RATES,
362 .formats = ZX_TDM_FMTBIT,
367 .rates = ZX_TDM_RATES,
368 .formats = ZX_TDM_FMTBIT,
370 .ops = &zx_tdm_dai_ops,
373 static int zx_tdm_probe(struct platform_device *pdev)
375 struct device *dev = &pdev->dev;
376 struct of_phandle_args out_args;
377 unsigned int dma_reg_offset;
378 struct zx_tdm_info *zx_tdm;
379 unsigned int dma_mask;
380 struct resource *res;
381 struct regmap *regmap_sysctrl;
384 zx_tdm = devm_kzalloc(&pdev->dev, sizeof(*zx_tdm), GFP_KERNEL);
390 zx_tdm->dai_wclk = devm_clk_get(&pdev->dev, "wclk");
391 if (IS_ERR(zx_tdm->dai_wclk)) {
392 dev_err(&pdev->dev, "Fail to get wclk\n");
393 return PTR_ERR(zx_tdm->dai_wclk);
396 zx_tdm->dai_pclk = devm_clk_get(&pdev->dev, "pclk");
397 if (IS_ERR(zx_tdm->dai_pclk)) {
398 dev_err(&pdev->dev, "Fail to get pclk\n");
399 return PTR_ERR(zx_tdm->dai_pclk);
402 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
403 zx_tdm->phy_addr = res->start;
404 zx_tdm->regbase = devm_ioremap_resource(&pdev->dev, res);
405 if (IS_ERR(zx_tdm->regbase))
406 return PTR_ERR(zx_tdm->regbase);
408 ret = of_parse_phandle_with_fixed_args(pdev->dev.of_node,
409 "zte,tdm-dma-sysctrl", 2, 0, &out_args);
411 dev_err(&pdev->dev, "Fail to get zte,tdm-dma-sysctrl\n");
415 dma_reg_offset = out_args.args[0];
416 dma_mask = out_args.args[1];
417 regmap_sysctrl = syscon_node_to_regmap(out_args.np);
418 if (IS_ERR(regmap_sysctrl)) {
419 of_node_put(out_args.np);
420 return PTR_ERR(regmap_sysctrl);
423 regmap_update_bits(regmap_sysctrl, dma_reg_offset, dma_mask, dma_mask);
424 of_node_put(out_args.np);
426 zx_tdm_init_state(zx_tdm);
427 platform_set_drvdata(pdev, zx_tdm);
429 ret = devm_snd_soc_register_component(&pdev->dev, &zx_tdm_component,
432 dev_err(&pdev->dev, "Register DAI failed: %d\n", ret);
436 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
438 dev_err(&pdev->dev, "Register platform PCM failed: %d\n", ret);
443 static const struct of_device_id zx_tdm_dt_ids[] = {
444 { .compatible = "zte,zx296718-tdm", },
447 MODULE_DEVICE_TABLE(of, zx_tdm_dt_ids);
449 static struct platform_driver tdm_driver = {
450 .probe = zx_tdm_probe,
453 .of_match_table = zx_tdm_dt_ids,
456 module_platform_driver(tdm_driver);
458 MODULE_AUTHOR("Baoyou Xie <baoyou.xie@linaro.org>");
459 MODULE_DESCRIPTION("ZTE TDM DAI driver");
460 MODULE_LICENSE("GPL v2");