1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2015 Linaro
5 * Author: Jun Nie <jun.nie@linaro.org>
9 #include <linux/device.h>
10 #include <linux/dmaengine.h>
11 #include <linux/init.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>
26 #define ZX_FIFOCTRL 0x08
27 #define ZX_INT_STATUS 0x10
28 #define ZX_INT_MASK 0x14
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
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)
44 #define ZX_CTRL_ENB BIT(4)
45 #define ZX_CTRL_DNB (0 << 4)
46 #define ZX_CTRL_ENB_MASK BIT(4)
48 #define ZX_CTRL_TX_OPEN BIT(0)
49 #define ZX_CTRL_TX_CLOSE (0 << 0)
50 #define ZX_CTRL_TX_MASK BIT(0)
52 #define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
53 #define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
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)
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)
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)
73 #define ZX_SPDIF_CLK_RAT (2 * 32)
75 struct zx_spdif_info
{
76 struct snd_dmaengine_dai_dma_data dma_data
;
78 void __iomem
*reg_base
;
79 resource_size_t mapbase
;
82 static int zx_spdif_dai_probe(struct snd_soc_dai
*dai
)
84 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
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
);
93 static int zx_spdif_chanstats(void __iomem
*base
, unsigned int rate
)
99 cstas1
= IEC958_AES3_CON_FS_22050
;
102 cstas1
= IEC958_AES3_CON_FS_24000
;
105 cstas1
= IEC958_AES3_CON_FS_32000
;
108 cstas1
= IEC958_AES3_CON_FS_44100
;
111 cstas1
= IEC958_AES3_CON_FS_48000
;
114 cstas1
= IEC958_AES3_CON_FS_88200
;
117 cstas1
= IEC958_AES3_CON_FS_96000
;
120 cstas1
= IEC958_AES3_CON_FS_176400
;
123 cstas1
= IEC958_AES3_CON_FS_192000
;
128 cstas1
= cstas1
<< 24;
129 cstas1
|= IEC958_AES0_CON_NOT_COPYRIGHT
;
131 writel_relaxed(cstas1
, base
+ ZX_CH_STA_1
);
135 static int zx_spdif_hw_params(struct snd_pcm_substream
*substream
,
136 struct snd_pcm_hw_params
*params
,
137 struct snd_soc_dai
*socdai
)
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
;
146 dma_data
->addr_width
= params_width(params
) >> 3;
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
;
155 case SNDRV_PCM_FORMAT_S18_3LE
:
156 val
|= ZX_CTRL_MODA_18
;
159 case SNDRV_PCM_FORMAT_S20_3LE
:
160 val
|= ZX_CTRL_MODA_20
;
163 case SNDRV_PCM_FORMAT_S24_LE
:
164 val
|= ZX_CTRL_MODA_24
;
167 dev_err(socdai
->dev
, "Format not support!\n");
171 ch_num
= params_channels(params
);
173 val
|= ZX_CTRL_DOUBLE_TRACK
;
175 val
|= ZX_CTRL_LEFT_TRACK
;
176 writel_relaxed(val
, zx_spdif
->reg_base
+ ZX_CTRL
);
178 val
= readl_relaxed(zx_spdif
->reg_base
+ ZX_VALID_BIT
);
179 val
&= ~ZX_VALID_TRACK_MASK
;
181 val
|= ZX_VALID_DOUBLE_TRACK
;
183 val
|= ZX_VALID_RIGHT_TRACK
;
184 writel_relaxed(val
, zx_spdif
->reg_base
+ ZX_VALID_BIT
);
186 rate
= params_rate(params
);
187 ret
= zx_spdif_chanstats(zx_spdif
->reg_base
, rate
);
190 return clk_set_rate(spdif
->dai_clk
, rate
* ch_num
* ZX_SPDIF_CLK_RAT
);
193 static void zx_spdif_cfg_tx(void __iomem
*base
, int on
)
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
);
202 val
= readl_relaxed(base
+ ZX_FIFOCTRL
);
203 val
&= ~ZX_FIFOCTRL_TX_DMA_EN_MASK
;
205 val
|= ZX_FIFOCTRL_TX_DMA_EN
;
206 writel_relaxed(val
, base
+ ZX_FIFOCTRL
);
209 static int zx_spdif_trigger(struct snd_pcm_substream
*substream
, int cmd
,
210 struct snd_soc_dai
*dai
)
213 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
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
);
222 case SNDRV_PCM_TRIGGER_RESUME
:
223 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
224 zx_spdif_cfg_tx(zx_spdif
->reg_base
, true);
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);
241 static int zx_spdif_startup(struct snd_pcm_substream
*substream
,
242 struct snd_soc_dai
*dai
)
244 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
246 return clk_prepare_enable(zx_spdif
->dai_clk
);
249 static void zx_spdif_shutdown(struct snd_pcm_substream
*substream
,
250 struct snd_soc_dai
*dai
)
252 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
254 clk_disable_unprepare(zx_spdif
->dai_clk
);
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)
263 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
264 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
266 static 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
,
273 static struct snd_soc_dai_driver zx_spdif_dai
= {
276 .probe
= zx_spdif_dai_probe
,
281 .formats
= ZX_FORMAT
,
283 .ops
= &zx_spdif_dai_ops
,
286 static const struct snd_soc_component_driver zx_spdif_component
= {
290 static void zx_spdif_dev_init(void __iomem
*base
)
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
);
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
);
305 static int zx_spdif_probe(struct platform_device
*pdev
)
307 struct resource
*res
;
308 struct zx_spdif_info
*zx_spdif
;
311 zx_spdif
= devm_kzalloc(&pdev
->dev
, sizeof(*zx_spdif
), GFP_KERNEL
);
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
);
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
);
328 zx_spdif_dev_init(zx_spdif
->reg_base
);
329 platform_set_drvdata(pdev
, zx_spdif
);
331 ret
= devm_snd_soc_register_component(&pdev
->dev
, &zx_spdif_component
,
334 dev_err(&pdev
->dev
, "Register DAI failed: %d\n", ret
);
338 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
340 dev_err(&pdev
->dev
, "Register platform PCM failed: %d\n", ret
);
345 static const struct of_device_id zx_spdif_dt_ids
[] = {
346 { .compatible
= "zte,zx296702-spdif", },
349 MODULE_DEVICE_TABLE(of
, zx_spdif_dt_ids
);
351 static struct platform_driver spdif_driver
= {
352 .probe
= zx_spdif_probe
,
355 .of_match_table
= zx_spdif_dt_ids
,
359 module_platform_driver(spdif_driver
);
361 MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
362 MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
363 MODULE_LICENSE("GPL");