2 * ALSA SoC Synopsys I2S Audio Layer
4 * sound/soc/spear/designware_i2s.c
6 * Copyright (C) 2010 ST Microelectronics
7 * Rajeev Kumar <rajeev-dlh.kumar@st.com>
9 * This file is licensed under the terms of the GNU General Public
10 * License version 2. This program is licensed "as is" without any
11 * warranty of any kind, whether express or implied.
14 #include <linux/clk.h>
15 #include <linux/device.h>
16 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/module.h>
20 #include <linux/slab.h>
21 #include <sound/designware_i2s.h>
22 #include <sound/pcm.h>
23 #include <sound/pcm_params.h>
24 #include <sound/soc.h>
26 /* common register for all channel */
35 /* I2STxRxRegisters for all channels */
36 #define LRBR_LTHR(x) (0x40 * x + 0x020)
37 #define RRBR_RTHR(x) (0x40 * x + 0x024)
38 #define RER(x) (0x40 * x + 0x028)
39 #define TER(x) (0x40 * x + 0x02C)
40 #define RCR(x) (0x40 * x + 0x030)
41 #define TCR(x) (0x40 * x + 0x034)
42 #define ISR(x) (0x40 * x + 0x038)
43 #define IMR(x) (0x40 * x + 0x03C)
44 #define ROR(x) (0x40 * x + 0x040)
45 #define TOR(x) (0x40 * x + 0x044)
46 #define RFCR(x) (0x40 * x + 0x048)
47 #define TFCR(x) (0x40 * x + 0x04C)
48 #define RFF(x) (0x40 * x + 0x050)
49 #define TFF(x) (0x40 * x + 0x054)
51 /* I2SCOMPRegisters */
52 #define I2S_COMP_PARAM_2 0x01F0
53 #define I2S_COMP_PARAM_1 0x01F4
54 #define I2S_COMP_VERSION 0x01F8
55 #define I2S_COMP_TYPE 0x01FC
57 #define MAX_CHANNEL_NUM 8
58 #define MIN_CHANNEL_NUM 2
61 void __iomem
*i2s_base
;
64 unsigned int capability
;
67 /* data related to DMA transfers b/w i2s and DMAC */
68 struct i2s_dma_data play_dma_data
;
69 struct i2s_dma_data capture_dma_data
;
70 struct i2s_clk_config_data config
;
71 int (*i2s_clk_cfg
)(struct i2s_clk_config_data
*config
);
74 static inline void i2s_write_reg(void *io_base
, int reg
, u32 val
)
76 writel(val
, io_base
+ reg
);
79 static inline u32
i2s_read_reg(void *io_base
, int reg
)
81 return readl(io_base
+ reg
);
84 static inline void i2s_disable_channels(struct dw_i2s_dev
*dev
, u32 stream
)
88 if (stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
89 for (i
= 0; i
< 4; i
++)
90 i2s_write_reg(dev
->i2s_base
, TER(i
), 0);
92 for (i
= 0; i
< 4; i
++)
93 i2s_write_reg(dev
->i2s_base
, RER(i
), 0);
97 static inline void i2s_clear_irqs(struct dw_i2s_dev
*dev
, u32 stream
)
101 if (stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
102 for (i
= 0; i
< 4; i
++)
103 i2s_write_reg(dev
->i2s_base
, TOR(i
), 0);
105 for (i
= 0; i
< 4; i
++)
106 i2s_write_reg(dev
->i2s_base
, ROR(i
), 0);
110 void i2s_start(struct dw_i2s_dev
*dev
, struct snd_pcm_substream
*substream
)
113 i2s_write_reg(dev
->i2s_base
, IER
, 1);
115 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
116 i2s_write_reg(dev
->i2s_base
, ITER
, 1);
118 i2s_write_reg(dev
->i2s_base
, IRER
, 1);
120 i2s_write_reg(dev
->i2s_base
, CER
, 1);
123 static void i2s_stop(struct dw_i2s_dev
*dev
,
124 struct snd_pcm_substream
*substream
)
128 i2s_clear_irqs(dev
, substream
->stream
);
129 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
130 i2s_write_reg(dev
->i2s_base
, ITER
, 0);
132 for (i
= 0; i
< 4; i
++) {
133 irq
= i2s_read_reg(dev
->i2s_base
, IMR(i
));
134 i2s_write_reg(dev
->i2s_base
, IMR(i
), irq
| 0x30);
137 i2s_write_reg(dev
->i2s_base
, IRER
, 0);
139 for (i
= 0; i
< 4; i
++) {
140 irq
= i2s_read_reg(dev
->i2s_base
, IMR(i
));
141 i2s_write_reg(dev
->i2s_base
, IMR(i
), irq
| 0x03);
146 i2s_write_reg(dev
->i2s_base
, CER
, 0);
147 i2s_write_reg(dev
->i2s_base
, IER
, 0);
151 static int dw_i2s_startup(struct snd_pcm_substream
*substream
,
152 struct snd_soc_dai
*cpu_dai
)
154 struct dw_i2s_dev
*dev
= snd_soc_dai_get_drvdata(cpu_dai
);
155 struct i2s_dma_data
*dma_data
= NULL
;
157 if (!(dev
->capability
& DWC_I2S_RECORD
) &&
158 (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
))
161 if (!(dev
->capability
& DWC_I2S_PLAY
) &&
162 (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
))
165 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
166 dma_data
= &dev
->play_dma_data
;
167 else if (substream
->stream
== SNDRV_PCM_STREAM_CAPTURE
)
168 dma_data
= &dev
->capture_dma_data
;
170 snd_soc_dai_set_dma_data(cpu_dai
, substream
, (void *)dma_data
);
175 static int dw_i2s_hw_params(struct snd_pcm_substream
*substream
,
176 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
178 struct dw_i2s_dev
*dev
= snd_soc_dai_get_drvdata(dai
);
179 struct i2s_clk_config_data
*config
= &dev
->config
;
180 u32 ccr
, xfer_resolution
, ch_reg
, irq
;
183 switch (params_format(params
)) {
184 case SNDRV_PCM_FORMAT_S16_LE
:
185 config
->data_width
= 16;
187 xfer_resolution
= 0x02;
190 case SNDRV_PCM_FORMAT_S24_LE
:
191 config
->data_width
= 24;
193 xfer_resolution
= 0x04;
196 case SNDRV_PCM_FORMAT_S32_LE
:
197 config
->data_width
= 32;
199 xfer_resolution
= 0x05;
203 dev_err(dev
->dev
, "designware-i2s: unsuppted PCM fmt");
207 config
->chan_nr
= params_channels(params
);
209 switch (config
->chan_nr
) {
210 case EIGHT_CHANNEL_SUPPORT
:
212 case SIX_CHANNEL_SUPPORT
:
214 case FOUR_CHANNEL_SUPPORT
:
216 case TWO_CHANNEL_SUPPORT
:
220 dev_err(dev
->dev
, "channel not supported\n");
223 i2s_disable_channels(dev
, substream
->stream
);
225 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
) {
226 i2s_write_reg(dev
->i2s_base
, TCR(ch_reg
), xfer_resolution
);
227 i2s_write_reg(dev
->i2s_base
, TFCR(ch_reg
), 0x02);
228 irq
= i2s_read_reg(dev
->i2s_base
, IMR(ch_reg
));
229 i2s_write_reg(dev
->i2s_base
, IMR(ch_reg
), irq
& ~0x30);
230 i2s_write_reg(dev
->i2s_base
, TER(ch_reg
), 1);
232 i2s_write_reg(dev
->i2s_base
, RCR(ch_reg
), xfer_resolution
);
233 i2s_write_reg(dev
->i2s_base
, RFCR(ch_reg
), 0x07);
234 irq
= i2s_read_reg(dev
->i2s_base
, IMR(ch_reg
));
235 i2s_write_reg(dev
->i2s_base
, IMR(ch_reg
), irq
& ~0x03);
236 i2s_write_reg(dev
->i2s_base
, RER(ch_reg
), 1);
239 i2s_write_reg(dev
->i2s_base
, CCR
, ccr
);
241 config
->sample_rate
= params_rate(params
);
243 if (!dev
->i2s_clk_cfg
)
246 ret
= dev
->i2s_clk_cfg(config
);
248 dev_err(dev
->dev
, "runtime audio clk config fail\n");
255 static void dw_i2s_shutdown(struct snd_pcm_substream
*substream
,
256 struct snd_soc_dai
*dai
)
258 snd_soc_dai_set_dma_data(dai
, substream
, NULL
);
261 static int dw_i2s_trigger(struct snd_pcm_substream
*substream
,
262 int cmd
, struct snd_soc_dai
*dai
)
264 struct dw_i2s_dev
*dev
= snd_soc_dai_get_drvdata(dai
);
268 case SNDRV_PCM_TRIGGER_START
:
269 case SNDRV_PCM_TRIGGER_RESUME
:
270 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
272 i2s_start(dev
, substream
);
275 case SNDRV_PCM_TRIGGER_STOP
:
276 case SNDRV_PCM_TRIGGER_SUSPEND
:
277 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
279 i2s_stop(dev
, substream
);
288 static struct snd_soc_dai_ops dw_i2s_dai_ops
= {
289 .startup
= dw_i2s_startup
,
290 .shutdown
= dw_i2s_shutdown
,
291 .hw_params
= dw_i2s_hw_params
,
292 .trigger
= dw_i2s_trigger
,
297 static int dw_i2s_suspend(struct snd_soc_dai
*dai
)
299 struct dw_i2s_dev
*dev
= snd_soc_dai_get_drvdata(dai
);
301 clk_disable(dev
->clk
);
305 static int dw_i2s_resume(struct snd_soc_dai
*dai
)
307 struct dw_i2s_dev
*dev
= snd_soc_dai_get_drvdata(dai
);
309 clk_enable(dev
->clk
);
314 #define dw_i2s_suspend NULL
315 #define dw_i2s_resume NULL
318 static int dw_i2s_probe(struct platform_device
*pdev
)
320 const struct i2s_platform_data
*pdata
= pdev
->dev
.platform_data
;
321 struct dw_i2s_dev
*dev
;
322 struct resource
*res
;
325 struct snd_soc_dai_driver
*dw_i2s_dai
;
328 dev_err(&pdev
->dev
, "Invalid platform data\n");
332 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
334 dev_err(&pdev
->dev
, "no i2s resource defined\n");
338 if (!devm_request_mem_region(&pdev
->dev
, res
->start
,
339 resource_size(res
), pdev
->name
)) {
340 dev_err(&pdev
->dev
, "i2s region already claimed\n");
344 dev
= devm_kzalloc(&pdev
->dev
, sizeof(*dev
), GFP_KERNEL
);
346 dev_warn(&pdev
->dev
, "kzalloc fail\n");
350 dev
->i2s_base
= devm_ioremap(&pdev
->dev
, res
->start
,
352 if (!dev
->i2s_base
) {
353 dev_err(&pdev
->dev
, "ioremap fail for i2s_region\n");
358 dev
->capability
= cap
;
359 dev
->i2s_clk_cfg
= pdata
->i2s_clk_cfg
;
361 /* Set DMA slaves info */
363 dev
->play_dma_data
.data
= pdata
->play_dma_data
;
364 dev
->capture_dma_data
.data
= pdata
->capture_dma_data
;
365 dev
->play_dma_data
.addr
= res
->start
+ I2S_TXDMA
;
366 dev
->capture_dma_data
.addr
= res
->start
+ I2S_RXDMA
;
367 dev
->play_dma_data
.max_burst
= 16;
368 dev
->capture_dma_data
.max_burst
= 16;
369 dev
->play_dma_data
.addr_width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
370 dev
->capture_dma_data
.addr_width
= DMA_SLAVE_BUSWIDTH_2_BYTES
;
371 dev
->play_dma_data
.filter
= pdata
->filter
;
372 dev
->capture_dma_data
.filter
= pdata
->filter
;
374 dev
->clk
= clk_get(&pdev
->dev
, NULL
);
375 if (IS_ERR(dev
->clk
))
376 return PTR_ERR(dev
->clk
);
378 ret
= clk_enable(dev
->clk
);
382 dw_i2s_dai
= devm_kzalloc(&pdev
->dev
, sizeof(*dw_i2s_dai
), GFP_KERNEL
);
384 dev_err(&pdev
->dev
, "mem allocation failed for dai driver\n");
386 goto err_clk_disable
;
389 if (cap
& DWC_I2S_PLAY
) {
390 dev_dbg(&pdev
->dev
, " SPEAr: play supported\n");
391 dw_i2s_dai
->playback
.channels_min
= MIN_CHANNEL_NUM
;
392 dw_i2s_dai
->playback
.channels_max
= pdata
->channel
;
393 dw_i2s_dai
->playback
.formats
= pdata
->snd_fmts
;
394 dw_i2s_dai
->playback
.rates
= pdata
->snd_rates
;
397 if (cap
& DWC_I2S_RECORD
) {
398 dev_dbg(&pdev
->dev
, "SPEAr: record supported\n");
399 dw_i2s_dai
->capture
.channels_min
= MIN_CHANNEL_NUM
;
400 dw_i2s_dai
->capture
.channels_max
= pdata
->channel
;
401 dw_i2s_dai
->capture
.formats
= pdata
->snd_fmts
;
402 dw_i2s_dai
->capture
.rates
= pdata
->snd_rates
;
405 dw_i2s_dai
->ops
= &dw_i2s_dai_ops
;
406 dw_i2s_dai
->suspend
= dw_i2s_suspend
;
407 dw_i2s_dai
->resume
= dw_i2s_resume
;
409 dev
->dev
= &pdev
->dev
;
410 dev_set_drvdata(&pdev
->dev
, dev
);
411 ret
= snd_soc_register_dai(&pdev
->dev
, dw_i2s_dai
);
413 dev_err(&pdev
->dev
, "not able to register dai\n");
414 goto err_set_drvdata
;
420 dev_set_drvdata(&pdev
->dev
, NULL
);
422 clk_disable(dev
->clk
);
428 static int dw_i2s_remove(struct platform_device
*pdev
)
430 struct dw_i2s_dev
*dev
= dev_get_drvdata(&pdev
->dev
);
432 snd_soc_unregister_dai(&pdev
->dev
);
433 dev_set_drvdata(&pdev
->dev
, NULL
);
440 static struct platform_driver dw_i2s_driver
= {
441 .probe
= dw_i2s_probe
,
442 .remove
= dw_i2s_remove
,
444 .name
= "designware-i2s",
445 .owner
= THIS_MODULE
,
449 module_platform_driver(dw_i2s_driver
);
451 MODULE_AUTHOR("Rajeev Kumar <rajeev-dlh.kumar@st.com>");
452 MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface");
453 MODULE_LICENSE("GPL");
454 MODULE_ALIAS("platform:designware_i2s");