2 * Copyright (C) 2015 Linaro
4 * Author: Jun Nie <jun.nie@linaro.org>
6 * License terms: GNU General Public License (GPL) version 2
10 #include <linux/device.h>
11 #include <linux/dmaengine.h>
12 #include <linux/init.h>
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/of_address.h>
17 #include <sound/asoundef.h>
18 #include <sound/core.h>
19 #include <sound/dmaengine_pcm.h>
20 #include <sound/initval.h>
21 #include <sound/pcm.h>
22 #include <sound/pcm_params.h>
23 #include <sound/soc.h>
24 #include <sound/soc-dai.h>
27 #define ZX_FIFOCTRL 0x08
28 #define ZX_INT_STATUS 0x10
29 #define ZX_INT_MASK 0x14
31 #define ZX_VALID_BIT 0x1c
32 #define ZX_CH_STA_1 0x20
33 #define ZX_CH_STA_2 0x24
34 #define ZX_CH_STA_3 0x28
35 #define ZX_CH_STA_4 0x2c
36 #define ZX_CH_STA_5 0x30
37 #define ZX_CH_STA_6 0x34
39 #define ZX_CTRL_MODA_16 (0 << 6)
40 #define ZX_CTRL_MODA_18 BIT(6)
41 #define ZX_CTRL_MODA_20 (2 << 6)
42 #define ZX_CTRL_MODA_24 (3 << 6)
43 #define ZX_CTRL_MODA_MASK (3 << 6)
45 #define ZX_CTRL_ENB BIT(4)
46 #define ZX_CTRL_DNB (0 << 4)
47 #define ZX_CTRL_ENB_MASK BIT(4)
49 #define ZX_CTRL_TX_OPEN BIT(0)
50 #define ZX_CTRL_TX_CLOSE (0 << 0)
51 #define ZX_CTRL_TX_MASK BIT(0)
53 #define ZX_CTRL_OPEN (ZX_CTRL_TX_OPEN | ZX_CTRL_ENB)
54 #define ZX_CTRL_CLOSE (ZX_CTRL_TX_CLOSE | ZX_CTRL_DNB)
56 #define ZX_CTRL_DOUBLE_TRACK (0 << 8)
57 #define ZX_CTRL_LEFT_TRACK BIT(8)
58 #define ZX_CTRL_RIGHT_TRACK (2 << 8)
59 #define ZX_CTRL_TRACK_MASK (3 << 8)
61 #define ZX_FIFOCTRL_TXTH_MASK (0x1f << 8)
62 #define ZX_FIFOCTRL_TXTH(x) (x << 8)
63 #define ZX_FIFOCTRL_TX_DMA_EN BIT(2)
64 #define ZX_FIFOCTRL_TX_DMA_DIS (0 << 2)
65 #define ZX_FIFOCTRL_TX_DMA_EN_MASK BIT(2)
66 #define ZX_FIFOCTRL_TX_FIFO_RST BIT(0)
67 #define ZX_FIFOCTRL_TX_FIFO_RST_MASK BIT(0)
69 #define ZX_VALID_DOUBLE_TRACK (0 << 0)
70 #define ZX_VALID_LEFT_TRACK BIT(1)
71 #define ZX_VALID_RIGHT_TRACK (2 << 0)
72 #define ZX_VALID_TRACK_MASK (3 << 0)
74 #define ZX_SPDIF_CLK_RAT (4 * 32)
76 struct zx_spdif_info
{
77 struct snd_dmaengine_dai_dma_data dma_data
;
79 void __iomem
*reg_base
;
80 resource_size_t mapbase
;
83 static int zx_spdif_dai_probe(struct snd_soc_dai
*dai
)
85 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
87 snd_soc_dai_set_drvdata(dai
, zx_spdif
);
88 zx_spdif
->dma_data
.addr
= zx_spdif
->mapbase
+ ZX_DATA
;
89 zx_spdif
->dma_data
.maxburst
= 8;
90 snd_soc_dai_init_dma_data(dai
, &zx_spdif
->dma_data
, NULL
);
94 static int zx_spdif_chanstats(void __iomem
*base
, unsigned int rate
)
100 cstas1
= IEC958_AES3_CON_FS_22050
;
103 cstas1
= IEC958_AES3_CON_FS_24000
;
106 cstas1
= IEC958_AES3_CON_FS_32000
;
109 cstas1
= IEC958_AES3_CON_FS_44100
;
112 cstas1
= IEC958_AES3_CON_FS_48000
;
115 cstas1
= IEC958_AES3_CON_FS_88200
;
118 cstas1
= IEC958_AES3_CON_FS_96000
;
121 cstas1
= IEC958_AES3_CON_FS_176400
;
124 cstas1
= IEC958_AES3_CON_FS_192000
;
129 cstas1
= cstas1
<< 24;
130 cstas1
|= IEC958_AES0_CON_NOT_COPYRIGHT
;
132 writel_relaxed(cstas1
, base
+ ZX_CH_STA_1
);
136 static int zx_spdif_hw_params(struct snd_pcm_substream
*substream
,
137 struct snd_pcm_hw_params
*params
,
138 struct snd_soc_dai
*socdai
)
140 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(socdai
->dev
);
141 struct zx_spdif_info
*spdif
= snd_soc_dai_get_drvdata(socdai
);
142 struct snd_dmaengine_dai_dma_data
*dma_data
= &zx_spdif
->dma_data
;
143 u32 val
, ch_num
, rate
;
146 dma_data
= snd_soc_dai_get_dma_data(socdai
, substream
);
147 dma_data
->addr_width
= params_width(params
) >> 3;
149 val
= readl_relaxed(zx_spdif
->reg_base
+ ZX_CTRL
);
150 val
&= ~ZX_CTRL_MODA_MASK
;
151 switch (params_format(params
)) {
152 case SNDRV_PCM_FORMAT_S16_LE
:
153 val
|= ZX_CTRL_MODA_16
;
156 case SNDRV_PCM_FORMAT_S18_3LE
:
157 val
|= ZX_CTRL_MODA_18
;
160 case SNDRV_PCM_FORMAT_S20_3LE
:
161 val
|= ZX_CTRL_MODA_20
;
164 case SNDRV_PCM_FORMAT_S24_LE
:
165 val
|= ZX_CTRL_MODA_24
;
168 dev_err(socdai
->dev
, "Format not support!\n");
172 ch_num
= params_channels(params
);
174 val
|= ZX_CTRL_DOUBLE_TRACK
;
176 val
|= ZX_CTRL_LEFT_TRACK
;
177 writel_relaxed(val
, zx_spdif
->reg_base
+ ZX_CTRL
);
179 val
= readl_relaxed(zx_spdif
->reg_base
+ ZX_VALID_BIT
);
180 val
&= ~ZX_VALID_TRACK_MASK
;
182 val
|= ZX_VALID_DOUBLE_TRACK
;
184 val
|= ZX_VALID_RIGHT_TRACK
;
185 writel_relaxed(val
, zx_spdif
->reg_base
+ ZX_VALID_BIT
);
187 rate
= params_rate(params
);
188 ret
= zx_spdif_chanstats(zx_spdif
->reg_base
, rate
);
191 ret
= clk_set_rate(spdif
->dai_clk
, rate
* ch_num
* ZX_SPDIF_CLK_RAT
);
198 static void zx_spdif_cfg_tx(void __iomem
*base
, int on
)
202 val
= readl_relaxed(base
+ ZX_CTRL
);
203 val
&= ~(ZX_CTRL_ENB_MASK
| ZX_CTRL_TX_MASK
);
204 val
|= on
? ZX_CTRL_OPEN
: ZX_CTRL_CLOSE
;
205 writel_relaxed(val
, base
+ ZX_CTRL
);
207 val
= readl_relaxed(base
+ ZX_FIFOCTRL
);
208 val
&= ~ZX_FIFOCTRL_TX_DMA_EN_MASK
;
210 val
|= ZX_FIFOCTRL_TX_DMA_EN
;
211 writel_relaxed(val
, base
+ ZX_FIFOCTRL
);
214 static int zx_spdif_trigger(struct snd_pcm_substream
*substream
, int cmd
,
215 struct snd_soc_dai
*dai
)
218 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
222 case SNDRV_PCM_TRIGGER_START
:
223 val
= readl_relaxed(zx_spdif
->reg_base
+ ZX_FIFOCTRL
);
224 val
|= ZX_FIFOCTRL_TX_FIFO_RST
;
225 writel_relaxed(val
, zx_spdif
->reg_base
+ ZX_FIFOCTRL
);
227 case SNDRV_PCM_TRIGGER_RESUME
:
228 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
229 zx_spdif_cfg_tx(zx_spdif
->reg_base
, true);
232 case SNDRV_PCM_TRIGGER_STOP
:
233 case SNDRV_PCM_TRIGGER_SUSPEND
:
234 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
235 zx_spdif_cfg_tx(zx_spdif
->reg_base
, false);
246 static int zx_spdif_startup(struct snd_pcm_substream
*substream
,
247 struct snd_soc_dai
*dai
)
249 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
251 return clk_prepare_enable(zx_spdif
->dai_clk
);
254 static void zx_spdif_shutdown(struct snd_pcm_substream
*substream
,
255 struct snd_soc_dai
*dai
)
257 struct zx_spdif_info
*zx_spdif
= dev_get_drvdata(dai
->dev
);
259 clk_disable_unprepare(zx_spdif
->dai_clk
);
263 (SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
264 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |\
265 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000)
268 (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE \
269 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE)
271 static struct snd_soc_dai_ops zx_spdif_dai_ops
= {
272 .trigger
= zx_spdif_trigger
,
273 .startup
= zx_spdif_startup
,
274 .shutdown
= zx_spdif_shutdown
,
275 .hw_params
= zx_spdif_hw_params
,
278 static struct snd_soc_dai_driver zx_spdif_dai
= {
281 .probe
= zx_spdif_dai_probe
,
286 .formats
= ZX_FORMAT
,
288 .ops
= &zx_spdif_dai_ops
,
291 static const struct snd_soc_component_driver zx_spdif_component
= {
295 static void zx_spdif_dev_init(void __iomem
*base
)
299 writel_relaxed(0, base
+ ZX_CTRL
);
300 writel_relaxed(0, base
+ ZX_INT_MASK
);
301 writel_relaxed(0xf, base
+ ZX_INT_STATUS
);
302 writel_relaxed(0x1, base
+ ZX_FIFOCTRL
);
304 val
= readl_relaxed(base
+ ZX_FIFOCTRL
);
305 val
&= ~(ZX_FIFOCTRL_TXTH_MASK
| ZX_FIFOCTRL_TX_FIFO_RST_MASK
);
306 val
|= ZX_FIFOCTRL_TXTH(8);
307 writel_relaxed(val
, base
+ ZX_FIFOCTRL
);
310 static int zx_spdif_probe(struct platform_device
*pdev
)
312 struct resource
*res
;
313 struct zx_spdif_info
*zx_spdif
;
316 zx_spdif
= devm_kzalloc(sizeof(*zx_spdif
), GFP_KERNEL
);
320 zx_spdif
->dai_clk
= devm_clk_get(&pdev
->dev
, "tx");
321 if (IS_ERR(zx_spdif
->dai_clk
)) {
322 dev_err(&pdev
->dev
, "Fail to get clk\n");
323 return PTR_ERR(zx_spdif
->dai_clk
);
326 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
327 zx_spdif
->mapbase
= res
->start
;
328 zx_spdif
->reg_base
= devm_ioremap_resource(&pdev
->dev
, res
);
329 if (!zx_spdif
->reg_base
) {
330 dev_err(&pdev
->dev
, "ioremap failed!\n");
334 zx_spdif_dev_init(zx_spdif
->reg_base
);
335 platform_set_drvdata(pdev
, zx_spdif
);
337 ret
= devm_snd_soc_register_component(&pdev
->dev
, &zx_spdif_component
,
340 dev_err(&pdev
->dev
, "Register DAI failed: %d\n", ret
);
344 ret
= devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
346 dev_err(&pdev
->dev
, "Register platform PCM failed: %d\n", ret
);
351 static const struct of_device_id zx_spdif_dt_ids
[] = {
352 { .compatible
= "zte,zx296702-spdif", },
355 MODULE_DEVICE_TABLE(of
, zx_spdif_dt_ids
);
357 static struct platform_driver spdif_driver
= {
358 .probe
= zx_spdif_probe
,
361 .owner
= THIS_MODULE
,
362 .of_match_table
= zx_spdif_dt_ids
,
366 module_platform_driver(spdif_driver
);
368 MODULE_AUTHOR("Jun Nie <jun.nie@linaro.org>");
369 MODULE_DESCRIPTION("ZTE SPDIF SoC DAI");
370 MODULE_LICENSE("GPL");