2 * SiRF USP in I2S/DSP mode
4 * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
6 * Licensed under GPLv2 or later.
8 #include <linux/module.h>
11 #include <linux/clk.h>
12 #include <linux/pm_runtime.h>
13 #include <sound/soc.h>
14 #include <sound/pcm_params.h>
15 #include <sound/dmaengine_pcm.h>
20 struct regmap
*regmap
;
25 struct snd_dmaengine_dai_dma_data playback_dma_data
;
26 struct snd_dmaengine_dai_dma_data capture_dma_data
;
29 static void sirf_usp_tx_enable(struct sirf_usp
*usp
)
31 regmap_update_bits(usp
->regmap
, USP_TX_FIFO_OP
,
32 USP_TX_FIFO_RESET
, USP_TX_FIFO_RESET
);
33 regmap_write(usp
->regmap
, USP_TX_FIFO_OP
, 0);
35 regmap_update_bits(usp
->regmap
, USP_TX_FIFO_OP
,
36 USP_TX_FIFO_START
, USP_TX_FIFO_START
);
38 regmap_update_bits(usp
->regmap
, USP_TX_RX_ENABLE
,
39 USP_TX_ENA
, USP_TX_ENA
);
42 static void sirf_usp_tx_disable(struct sirf_usp
*usp
)
44 regmap_update_bits(usp
->regmap
, USP_TX_RX_ENABLE
,
45 USP_TX_ENA
, ~USP_TX_ENA
);
47 regmap_write(usp
->regmap
, USP_TX_FIFO_OP
, 0);
50 static void sirf_usp_rx_enable(struct sirf_usp
*usp
)
52 regmap_update_bits(usp
->regmap
, USP_RX_FIFO_OP
,
53 USP_RX_FIFO_RESET
, USP_RX_FIFO_RESET
);
54 regmap_write(usp
->regmap
, USP_RX_FIFO_OP
, 0);
56 regmap_update_bits(usp
->regmap
, USP_RX_FIFO_OP
,
57 USP_RX_FIFO_START
, USP_RX_FIFO_START
);
59 regmap_update_bits(usp
->regmap
, USP_TX_RX_ENABLE
,
60 USP_RX_ENA
, USP_RX_ENA
);
63 static void sirf_usp_rx_disable(struct sirf_usp
*usp
)
65 regmap_update_bits(usp
->regmap
, USP_TX_RX_ENABLE
,
66 USP_RX_ENA
, ~USP_RX_ENA
);
68 regmap_write(usp
->regmap
, USP_RX_FIFO_OP
, 0);
71 static int sirf_usp_pcm_dai_probe(struct snd_soc_dai
*dai
)
73 struct sirf_usp
*usp
= snd_soc_dai_get_drvdata(dai
);
74 snd_soc_dai_init_dma_data(dai
, &usp
->playback_dma_data
,
75 &usp
->capture_dma_data
);
79 static int sirf_usp_pcm_set_dai_fmt(struct snd_soc_dai
*dai
,
82 struct sirf_usp
*usp
= snd_soc_dai_get_drvdata(dai
);
84 /* set master/slave audio interface */
85 switch (fmt
& SND_SOC_DAIFMT_MASTER_MASK
) {
86 case SND_SOC_DAIFMT_CBM_CFM
:
89 dev_err(dai
->dev
, "Only CBM and CFM supported\n");
93 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
94 case SND_SOC_DAIFMT_I2S
:
95 case SND_SOC_DAIFMT_DSP_A
:
96 usp
->daifmt_format
= (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
);
99 dev_err(dai
->dev
, "Only I2S and DSP_A format supported\n");
106 static void sirf_usp_i2s_init(struct sirf_usp
*usp
)
108 /* Configure RISC mode */
109 regmap_update_bits(usp
->regmap
, USP_RISC_DSP_MODE
,
110 USP_RISC_DSP_SEL
, ~USP_RISC_DSP_SEL
);
113 * Configure DMA IO Length register
114 * Set no limit, USP can receive data continuously until it is diabled
116 regmap_write(usp
->regmap
, USP_TX_DMA_IO_LEN
, 0);
117 regmap_write(usp
->regmap
, USP_RX_DMA_IO_LEN
, 0);
119 /* Configure Mode2 register */
120 regmap_write(usp
->regmap
, USP_MODE2
, (1 << USP_RXD_DELAY_LEN_OFFSET
) |
121 (0 << USP_TXD_DELAY_LEN_OFFSET
) |
122 USP_TFS_CLK_SLAVE_MODE
| USP_RFS_CLK_SLAVE_MODE
);
124 /* Configure Mode1 register */
125 regmap_write(usp
->regmap
, USP_MODE1
,
126 USP_SYNC_MODE
| USP_EN
| USP_TXD_ACT_EDGE_FALLING
|
127 USP_RFS_ACT_LEVEL_LOGIC1
| USP_TFS_ACT_LEVEL_LOGIC1
|
128 USP_TX_UFLOW_REPEAT_ZERO
| USP_CLOCK_MODE_SLAVE
);
130 /* Configure RX DMA IO Control register */
131 regmap_write(usp
->regmap
, USP_RX_DMA_IO_CTRL
, 0);
133 /* Congiure RX FIFO Control register */
134 regmap_write(usp
->regmap
, USP_RX_FIFO_CTRL
,
135 (USP_RX_FIFO_THRESHOLD
<< USP_RX_FIFO_THD_OFFSET
) |
136 (USP_TX_RX_FIFO_WIDTH_DWORD
<< USP_RX_FIFO_WIDTH_OFFSET
));
138 /* Congiure RX FIFO Level Check register */
139 regmap_write(usp
->regmap
, USP_RX_FIFO_LEVEL_CHK
,
140 RX_FIFO_SC(0x04) | RX_FIFO_LC(0x0E) | RX_FIFO_HC(0x1B));
142 /* Configure TX DMA IO Control register*/
143 regmap_write(usp
->regmap
, USP_TX_DMA_IO_CTRL
, 0);
145 /* Configure TX FIFO Control register */
146 regmap_write(usp
->regmap
, USP_TX_FIFO_CTRL
,
147 (USP_TX_FIFO_THRESHOLD
<< USP_TX_FIFO_THD_OFFSET
) |
148 (USP_TX_RX_FIFO_WIDTH_DWORD
<< USP_TX_FIFO_WIDTH_OFFSET
));
149 /* Congiure TX FIFO Level Check register */
150 regmap_write(usp
->regmap
, USP_TX_FIFO_LEVEL_CHK
,
151 TX_FIFO_SC(0x1B) | TX_FIFO_LC(0x0E) | TX_FIFO_HC(0x04));
154 static int sirf_usp_pcm_hw_params(struct snd_pcm_substream
*substream
,
155 struct snd_pcm_hw_params
*params
, struct snd_soc_dai
*dai
)
157 struct sirf_usp
*usp
= snd_soc_dai_get_drvdata(dai
);
158 u32 data_len
, frame_len
, shifter_len
;
160 switch (params_format(params
)) {
161 case SNDRV_PCM_FORMAT_S16_LE
:
165 case SNDRV_PCM_FORMAT_S24_LE
:
169 case SNDRV_PCM_FORMAT_S24_3LE
:
174 dev_err(dai
->dev
, "Format unsupported\n");
178 shifter_len
= data_len
;
180 switch (usp
->daifmt_format
) {
181 case SND_SOC_DAIFMT_I2S
:
182 regmap_update_bits(usp
->regmap
, USP_RX_FRAME_CTRL
,
183 USP_I2S_SYNC_CHG
, USP_I2S_SYNC_CHG
);
185 case SND_SOC_DAIFMT_DSP_A
:
186 regmap_update_bits(usp
->regmap
, USP_RX_FRAME_CTRL
,
187 USP_I2S_SYNC_CHG
, 0);
188 frame_len
= data_len
* params_channels(params
);
189 data_len
= frame_len
;
192 dev_err(dai
->dev
, "Only support I2S and DSP_A mode\n");
196 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
197 regmap_update_bits(usp
->regmap
, USP_TX_FRAME_CTRL
,
198 USP_TXC_DATA_LEN_MASK
| USP_TXC_FRAME_LEN_MASK
199 | USP_TXC_SHIFTER_LEN_MASK
| USP_TXC_SLAVE_CLK_SAMPLE
,
200 ((data_len
- 1) << USP_TXC_DATA_LEN_OFFSET
)
201 | ((frame_len
- 1) << USP_TXC_FRAME_LEN_OFFSET
)
202 | ((shifter_len
- 1) << USP_TXC_SHIFTER_LEN_OFFSET
)
203 | USP_TXC_SLAVE_CLK_SAMPLE
);
205 regmap_update_bits(usp
->regmap
, USP_RX_FRAME_CTRL
,
206 USP_RXC_DATA_LEN_MASK
| USP_RXC_FRAME_LEN_MASK
207 | USP_RXC_SHIFTER_LEN_MASK
| USP_SINGLE_SYNC_MODE
,
208 ((data_len
- 1) << USP_RXC_DATA_LEN_OFFSET
)
209 | ((frame_len
- 1) << USP_RXC_FRAME_LEN_OFFSET
)
210 | ((shifter_len
- 1) << USP_RXC_SHIFTER_LEN_OFFSET
)
211 | USP_SINGLE_SYNC_MODE
);
216 static int sirf_usp_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
,
217 struct snd_soc_dai
*dai
)
219 struct sirf_usp
*usp
= snd_soc_dai_get_drvdata(dai
);
222 case SNDRV_PCM_TRIGGER_START
:
223 case SNDRV_PCM_TRIGGER_RESUME
:
224 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
225 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
226 sirf_usp_tx_enable(usp
);
228 sirf_usp_rx_enable(usp
);
230 case SNDRV_PCM_TRIGGER_STOP
:
231 case SNDRV_PCM_TRIGGER_SUSPEND
:
232 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
233 if (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
)
234 sirf_usp_tx_disable(usp
);
236 sirf_usp_rx_disable(usp
);
243 static const struct snd_soc_dai_ops sirf_usp_pcm_dai_ops
= {
244 .trigger
= sirf_usp_pcm_trigger
,
245 .set_fmt
= sirf_usp_pcm_set_dai_fmt
,
246 .hw_params
= sirf_usp_pcm_hw_params
,
249 static struct snd_soc_dai_driver sirf_usp_pcm_dai
= {
250 .probe
= sirf_usp_pcm_dai_probe
,
251 .name
= "sirf-usp-pcm",
254 .stream_name
= "SiRF USP PCM Playback",
257 .rates
= SNDRV_PCM_RATE_8000_192000
,
258 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE
|
259 SNDRV_PCM_FMTBIT_S24_3LE
,
262 .stream_name
= "SiRF USP PCM Capture",
265 .rates
= SNDRV_PCM_RATE_8000_192000
,
266 .formats
= SNDRV_PCM_FMTBIT_S16_LE
| SNDRV_PCM_FMTBIT_S24_LE
|
267 SNDRV_PCM_FMTBIT_S24_3LE
,
269 .ops
= &sirf_usp_pcm_dai_ops
,
272 static int sirf_usp_pcm_runtime_suspend(struct device
*dev
)
274 struct sirf_usp
*usp
= dev_get_drvdata(dev
);
275 clk_disable_unprepare(usp
->clk
);
279 static int sirf_usp_pcm_runtime_resume(struct device
*dev
)
281 struct sirf_usp
*usp
= dev_get_drvdata(dev
);
283 ret
= clk_prepare_enable(usp
->clk
);
285 dev_err(dev
, "clk_enable failed: %d\n", ret
);
288 sirf_usp_i2s_init(usp
);
292 #ifdef CONFIG_PM_SLEEP
293 static int sirf_usp_pcm_suspend(struct device
*dev
)
295 struct sirf_usp
*usp
= dev_get_drvdata(dev
);
297 if (!pm_runtime_status_suspended(dev
)) {
298 regmap_read(usp
->regmap
, USP_MODE1
, &usp
->mode1_reg
);
299 regmap_read(usp
->regmap
, USP_MODE2
, &usp
->mode2_reg
);
300 sirf_usp_pcm_runtime_suspend(dev
);
305 static int sirf_usp_pcm_resume(struct device
*dev
)
307 struct sirf_usp
*usp
= dev_get_drvdata(dev
);
310 if (!pm_runtime_status_suspended(dev
)) {
311 ret
= sirf_usp_pcm_runtime_resume(dev
);
314 regmap_write(usp
->regmap
, USP_MODE1
, usp
->mode1_reg
);
315 regmap_write(usp
->regmap
, USP_MODE2
, usp
->mode2_reg
);
321 static const struct snd_soc_component_driver sirf_usp_component
= {
325 static const struct regmap_config sirf_usp_regmap_config
= {
329 .max_register
= USP_RX_FIFO_DATA
,
330 .cache_type
= REGCACHE_NONE
,
333 static int sirf_usp_pcm_probe(struct platform_device
*pdev
)
336 struct sirf_usp
*usp
;
338 struct resource
*mem_res
;
340 usp
= devm_kzalloc(&pdev
->dev
, sizeof(struct sirf_usp
),
345 platform_set_drvdata(pdev
, usp
);
347 mem_res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
348 base
= devm_ioremap(&pdev
->dev
, mem_res
->start
,
349 resource_size(mem_res
));
352 usp
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, base
,
353 &sirf_usp_regmap_config
);
354 if (IS_ERR(usp
->regmap
))
355 return PTR_ERR(usp
->regmap
);
357 usp
->clk
= devm_clk_get(&pdev
->dev
, NULL
);
358 if (IS_ERR(usp
->clk
)) {
359 dev_err(&pdev
->dev
, "Get clock failed.\n");
360 return PTR_ERR(usp
->clk
);
363 pm_runtime_enable(&pdev
->dev
);
364 if (!pm_runtime_enabled(&pdev
->dev
)) {
365 ret
= sirf_usp_pcm_runtime_resume(&pdev
->dev
);
370 ret
= devm_snd_soc_register_component(&pdev
->dev
, &sirf_usp_component
,
371 &sirf_usp_pcm_dai
, 1);
373 dev_err(&pdev
->dev
, "Register Audio SoC dai failed.\n");
376 return devm_snd_dmaengine_pcm_register(&pdev
->dev
, NULL
, 0);
379 static int sirf_usp_pcm_remove(struct platform_device
*pdev
)
381 if (!pm_runtime_enabled(&pdev
->dev
))
382 sirf_usp_pcm_runtime_suspend(&pdev
->dev
);
384 pm_runtime_disable(&pdev
->dev
);
388 static const struct of_device_id sirf_usp_pcm_of_match
[] = {
389 { .compatible
= "sirf,prima2-usp-pcm", },
392 MODULE_DEVICE_TABLE(of
, sirf_usp_pcm_of_match
);
394 static const struct dev_pm_ops sirf_usp_pcm_pm_ops
= {
395 SET_RUNTIME_PM_OPS(sirf_usp_pcm_runtime_suspend
,
396 sirf_usp_pcm_runtime_resume
, NULL
)
397 SET_SYSTEM_SLEEP_PM_OPS(sirf_usp_pcm_suspend
, sirf_usp_pcm_resume
)
400 static struct platform_driver sirf_usp_pcm_driver
= {
402 .name
= "sirf-usp-pcm",
403 .owner
= THIS_MODULE
,
404 .of_match_table
= sirf_usp_pcm_of_match
,
405 .pm
= &sirf_usp_pcm_pm_ops
,
407 .probe
= sirf_usp_pcm_probe
,
408 .remove
= sirf_usp_pcm_remove
,
411 module_platform_driver(sirf_usp_pcm_driver
);
413 MODULE_DESCRIPTION("SiRF SoC USP PCM bus driver");
414 MODULE_AUTHOR("RongJun Ying <Rongjun.Ying@csr.com>");
415 MODULE_LICENSE("GPL v2");