aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/ux500
diff options
context:
space:
mode:
authorOla Lilja <ola.o.lilja@stericsson.com>2012-05-08 09:57:18 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-05-09 07:52:59 -0400
commit3592b7f69a5438812381ff0aacdea1725ffa1c1c (patch)
treeb24451a32b623d2d1ce71031bdc9033195129fec /sound/soc/ux500
parent41a41eaca48946a69bb0a1f6e053b9e4f1458e15 (diff)
ASoC: Ux500: Add MSP I2S-driver
Add driver for running I2S with the MSP-block. Signed-off-by: Ola Lilja <ola.o.lilja@stericsson.com> [Fixed trailing whitespace -- broonie] Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/ux500')
-rw-r--r--sound/soc/ux500/Kconfig15
-rw-r--r--sound/soc/ux500/Makefile4
-rw-r--r--sound/soc/ux500/ux500_msp_dai.c843
-rw-r--r--sound/soc/ux500/ux500_msp_dai.h79
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.c742
-rw-r--r--sound/soc/ux500/ux500_msp_i2s.h553
6 files changed, 2236 insertions, 0 deletions
diff --git a/sound/soc/ux500/Kconfig b/sound/soc/ux500/Kconfig
new file mode 100644
index 000000000000..ac852347c5dc
--- /dev/null
+++ b/sound/soc/ux500/Kconfig
@@ -0,0 +1,15 @@
1#
2# Ux500 SoC audio configuration
3#
4menuconfig SND_SOC_UX500
5 tristate "SoC Audio support for Ux500 platform"
6 depends on SND_SOC
7 help
8 Say Y if you want to enable ASoC-support for
9 any of the Ux500 platforms (e.g. U8500).
10
11config SND_SOC_UX500_PLAT_MSP_I2S
12 tristate "Platform - MSP (I2S)"
13 depends on SND_SOC_UX500
14 help
15 Say Y if you want to enable the Ux500 MSP I2S-driver.
diff --git a/sound/soc/ux500/Makefile b/sound/soc/ux500/Makefile
new file mode 100644
index 000000000000..19974c5a2ea1
--- /dev/null
+++ b/sound/soc/ux500/Makefile
@@ -0,0 +1,4 @@
1# Ux500 Platform Support
2
3snd-soc-ux500-plat-msp-i2s-objs := ux500_msp_dai.o ux500_msp_i2s.o
4obj-$(CONFIG_SND_SOC_UX500_PLAT_MSP_I2S) += snd-soc-ux500-plat-msp-i2s.o
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c
new file mode 100644
index 000000000000..93c6c40e724c
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_dai.c
@@ -0,0 +1,843 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
6 * for ST-Ericsson.
7 *
8 * License terms:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/slab.h>
17#include <linux/bitops.h>
18#include <linux/platform_device.h>
19#include <linux/clk.h>
20#include <linux/regulator/consumer.h>
21#include <linux/mfd/dbx500-prcmu.h>
22
23#include <mach/hardware.h>
24#include <mach/board-mop500-msp.h>
25
26#include <sound/soc.h>
27#include <sound/soc-dai.h>
28
29#include "ux500_msp_i2s.h"
30#include "ux500_msp_dai.h"
31
32static int setup_pcm_multichan(struct snd_soc_dai *dai,
33 struct ux500_msp_config *msp_config)
34{
35 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
36 struct msp_multichannel_config *multi =
37 &msp_config->multichannel_config;
38
39 if (drvdata->slots > 1) {
40 msp_config->multichannel_configured = 1;
41
42 multi->tx_multichannel_enable = true;
43 multi->rx_multichannel_enable = true;
44 multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED;
45
46 multi->tx_channel_0_enable = drvdata->tx_mask;
47 multi->tx_channel_1_enable = 0;
48 multi->tx_channel_2_enable = 0;
49 multi->tx_channel_3_enable = 0;
50
51 multi->rx_channel_0_enable = drvdata->rx_mask;
52 multi->rx_channel_1_enable = 0;
53 multi->rx_channel_2_enable = 0;
54 multi->rx_channel_3_enable = 0;
55
56 dev_dbg(dai->dev,
57 "%s: Multichannel enabled. Slots: %d, TX: %u, RX: %u\n",
58 __func__, drvdata->slots, multi->tx_channel_0_enable,
59 multi->rx_channel_0_enable);
60 }
61
62 return 0;
63}
64
65static int setup_frameper(struct snd_soc_dai *dai, unsigned int rate,
66 struct msp_protdesc *prot_desc)
67{
68 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
69
70 switch (drvdata->slots) {
71 case 1:
72 switch (rate) {
73 case 8000:
74 prot_desc->frame_period =
75 FRAME_PER_SINGLE_SLOT_8_KHZ;
76 break;
77
78 case 16000:
79 prot_desc->frame_period =
80 FRAME_PER_SINGLE_SLOT_16_KHZ;
81 break;
82
83 case 44100:
84 prot_desc->frame_period =
85 FRAME_PER_SINGLE_SLOT_44_1_KHZ;
86 break;
87
88 case 48000:
89 prot_desc->frame_period =
90 FRAME_PER_SINGLE_SLOT_48_KHZ;
91 break;
92
93 default:
94 dev_err(dai->dev,
95 "%s: Error: Unsupported sample-rate (freq = %d)!\n",
96 __func__, rate);
97 return -EINVAL;
98 }
99 break;
100
101 case 2:
102 prot_desc->frame_period = FRAME_PER_2_SLOTS;
103 break;
104
105 case 8:
106 prot_desc->frame_period = FRAME_PER_8_SLOTS;
107 break;
108
109 case 16:
110 prot_desc->frame_period = FRAME_PER_16_SLOTS;
111 break;
112 default:
113 dev_err(dai->dev,
114 "%s: Error: Unsupported slot-count (slots = %d)!\n",
115 __func__, drvdata->slots);
116 return -EINVAL;
117 }
118
119 prot_desc->clocks_per_frame =
120 prot_desc->frame_period+1;
121
122 dev_dbg(dai->dev, "%s: Clocks per frame: %u\n",
123 __func__,
124 prot_desc->clocks_per_frame);
125
126 return 0;
127}
128
129static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
130 struct msp_protdesc *prot_desc)
131{
132 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
133
134 u32 frame_length = MSP_FRAME_LEN_1;
135 prot_desc->frame_width = 0;
136
137 switch (drvdata->slots) {
138 case 1:
139 frame_length = MSP_FRAME_LEN_1;
140 break;
141
142 case 2:
143 frame_length = MSP_FRAME_LEN_2;
144 break;
145
146 case 8:
147 frame_length = MSP_FRAME_LEN_8;
148 break;
149
150 case 16:
151 frame_length = MSP_FRAME_LEN_16;
152 break;
153 default:
154 dev_err(dai->dev,
155 "%s: Error: Unsupported slot-count (slots = %d)!\n",
156 __func__, drvdata->slots);
157 return -EINVAL;
158 }
159
160 prot_desc->tx_frame_len_1 = frame_length;
161 prot_desc->rx_frame_len_1 = frame_length;
162 prot_desc->tx_frame_len_2 = frame_length;
163 prot_desc->rx_frame_len_2 = frame_length;
164
165 prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
166 prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
167 prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
168 prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
169
170 return setup_frameper(dai, rate, prot_desc);
171}
172
173static int setup_clocking(struct snd_soc_dai *dai,
174 unsigned int fmt,
175 struct ux500_msp_config *msp_config)
176{
177 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
178 case SND_SOC_DAIFMT_NB_NF:
179 break;
180
181 case SND_SOC_DAIFMT_NB_IF:
182 msp_config->tx_fsync_pol ^= 1 << TFSPOL_SHIFT;
183 msp_config->rx_fsync_pol ^= 1 << RFSPOL_SHIFT;
184
185 break;
186
187 default:
188 dev_err(dai->dev,
189 "%s: Error: Unsopported inversion (fmt = 0x%x)!\n",
190 __func__, fmt);
191
192 return -EINVAL;
193 }
194
195 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
196 case SND_SOC_DAIFMT_CBM_CFM:
197 dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
198
199 msp_config->iodelay = 0x20;
200 msp_config->rx_fsync_sel = 0;
201 msp_config->tx_fsync_sel = 1 << TFSSEL_SHIFT;
202 msp_config->tx_clk_sel = 0;
203 msp_config->rx_clk_sel = 0;
204 msp_config->srg_clk_sel = 0x2 << SCKSEL_SHIFT;
205
206 break;
207
208 case SND_SOC_DAIFMT_CBS_CFS:
209 dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
210
211 msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
212 msp_config->tx_fsync_sel = TX_SYNC_SRG_PROG;
213 msp_config->rx_clk_sel = RX_CLK_SEL_SRG;
214 msp_config->rx_fsync_sel = RX_SYNC_SRG;
215 msp_config->srg_clk_sel = 1 << SCKSEL_SHIFT;
216
217 break;
218
219 default:
220 dev_err(dai->dev, "%s: Error: Unsopported master (fmt = 0x%x)!\n",
221 __func__, fmt);
222
223 return -EINVAL;
224 }
225
226 return 0;
227}
228
229static int setup_pcm_protdesc(struct snd_soc_dai *dai,
230 unsigned int fmt,
231 struct msp_protdesc *prot_desc)
232{
233 prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
234 prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
235 prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
236 prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
237 prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
238 prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
239 prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_HI);
240 prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_HI << RFSPOL_SHIFT;
241
242 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
243 dev_dbg(dai->dev, "%s: DSP_A.\n", __func__);
244 prot_desc->rx_clk_pol = MSP_RISING_EDGE;
245 prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
246
247 prot_desc->rx_data_delay = MSP_DELAY_1;
248 prot_desc->tx_data_delay = MSP_DELAY_1;
249 } else {
250 dev_dbg(dai->dev, "%s: DSP_B.\n", __func__);
251 prot_desc->rx_clk_pol = MSP_FALLING_EDGE;
252 prot_desc->tx_clk_pol = MSP_RISING_EDGE;
253
254 prot_desc->rx_data_delay = MSP_DELAY_0;
255 prot_desc->tx_data_delay = MSP_DELAY_0;
256 }
257
258 prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
259 prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
260 prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
261 prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
262 prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
263
264 return 0;
265}
266
267static int setup_i2s_protdesc(struct msp_protdesc *prot_desc)
268{
269 prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
270 prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
271 prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
272 prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
273 prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
274 prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
275 prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_LO);
276 prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_LO << RFSPOL_SHIFT;
277
278 prot_desc->rx_frame_len_1 = MSP_FRAME_LEN_1;
279 prot_desc->rx_frame_len_2 = MSP_FRAME_LEN_1;
280 prot_desc->tx_frame_len_1 = MSP_FRAME_LEN_1;
281 prot_desc->tx_frame_len_2 = MSP_FRAME_LEN_1;
282 prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
283 prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
284 prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
285 prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
286
287 prot_desc->rx_clk_pol = MSP_RISING_EDGE;
288 prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
289
290 prot_desc->rx_data_delay = MSP_DELAY_0;
291 prot_desc->tx_data_delay = MSP_DELAY_0;
292
293 prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
294 prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
295 prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
296 prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
297 prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
298
299 return 0;
300}
301
302static int setup_msp_config(struct snd_pcm_substream *substream,
303 struct snd_soc_dai *dai,
304 struct ux500_msp_config *msp_config)
305{
306 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
307 struct msp_protdesc *prot_desc = &msp_config->protdesc;
308 struct snd_pcm_runtime *runtime = substream->runtime;
309 unsigned int fmt = drvdata->fmt;
310 int ret;
311
312 memset(msp_config, 0, sizeof(*msp_config));
313
314 msp_config->f_inputclk = drvdata->master_clk;
315
316 msp_config->tx_fifo_config = TX_FIFO_ENABLE;
317 msp_config->rx_fifo_config = RX_FIFO_ENABLE;
318 msp_config->def_elem_len = 1;
319 msp_config->direction = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
320 MSP_DIR_TX : MSP_DIR_RX;
321 msp_config->data_size = MSP_DATA_BITS_32;
322 msp_config->frame_freq = runtime->rate;
323
324 dev_dbg(dai->dev, "%s: f_inputclk = %u, frame_freq = %u.\n",
325 __func__, msp_config->f_inputclk, msp_config->frame_freq);
326 /* To avoid division by zero */
327 prot_desc->clocks_per_frame = 1;
328
329 dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
330 runtime->rate, runtime->channels);
331 switch (fmt &
332 (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
333 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
334 dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
335
336 msp_config->default_protdesc = 1;
337 msp_config->protocol = MSP_I2S_PROTOCOL;
338 break;
339
340 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
341 dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
342
343 msp_config->data_size = MSP_DATA_BITS_16;
344 msp_config->protocol = MSP_I2S_PROTOCOL;
345
346 ret = setup_i2s_protdesc(prot_desc);
347 if (ret < 0)
348 return ret;
349
350 break;
351
352 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
353 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
354 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
355 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
356 dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
357
358 msp_config->data_size = MSP_DATA_BITS_16;
359 msp_config->protocol = MSP_PCM_PROTOCOL;
360
361 ret = setup_pcm_protdesc(dai, fmt, prot_desc);
362 if (ret < 0)
363 return ret;
364
365 ret = setup_pcm_multichan(dai, msp_config);
366 if (ret < 0)
367 return ret;
368
369 ret = setup_pcm_framing(dai, runtime->rate, prot_desc);
370 if (ret < 0)
371 return ret;
372
373 break;
374
375 default:
376 dev_err(dai->dev, "%s: Error: Unsopported format (%d)!\n",
377 __func__, fmt);
378 return -EINVAL;
379 }
380
381 return setup_clocking(dai, fmt, msp_config);
382}
383
384static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
385 struct snd_soc_dai *dai)
386{
387 int ret = 0;
388 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
389
390 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
391 snd_pcm_stream_str(substream));
392
393 /* Enable regulator */
394 ret = regulator_enable(drvdata->reg_vape);
395 if (ret != 0) {
396 dev_err(drvdata->msp->dev,
397 "%s: Failed to enable regulator!\n", __func__);
398 return ret;
399 }
400
401 /* Enable clock */
402 dev_dbg(dai->dev, "%s: Enabling MSP-clock.\n", __func__);
403 clk_enable(drvdata->clk);
404
405 return 0;
406}
407
408static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
409 struct snd_soc_dai *dai)
410{
411 int ret;
412 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
413 bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
414
415 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
416 snd_pcm_stream_str(substream));
417
418 if (drvdata->vape_opp_constraint == 1) {
419 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
420 "ux500_msp_i2s", 50);
421 drvdata->vape_opp_constraint = 0;
422 }
423
424 if (ux500_msp_i2s_close(drvdata->msp,
425 is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
426 dev_err(dai->dev,
427 "%s: Error: MSP %d (%s): Unable to close i2s.\n",
428 __func__, dai->id, snd_pcm_stream_str(substream));
429 }
430
431 /* Disable clock */
432 clk_disable(drvdata->clk);
433
434 /* Disable regulator */
435 ret = regulator_disable(drvdata->reg_vape);
436 if (ret < 0)
437 dev_err(dai->dev,
438 "%s: ERROR: Failed to disable regulator (%d)!\n",
439 __func__, ret);
440}
441
442static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
443 struct snd_soc_dai *dai)
444{
445 int ret = 0;
446 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
447 struct snd_pcm_runtime *runtime = substream->runtime;
448 struct ux500_msp_config msp_config;
449
450 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
451 dai->id, snd_pcm_stream_str(substream), runtime->rate);
452
453 setup_msp_config(substream, dai, &msp_config);
454
455 ret = ux500_msp_i2s_open(drvdata->msp, &msp_config);
456 if (ret < 0) {
457 dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
458 __func__, ret);
459 return ret;
460 }
461
462 /* Set OPP-level */
463 if ((drvdata->fmt & SND_SOC_DAIFMT_MASTER_MASK) &&
464 (drvdata->msp->f_bitclk > 19200000)) {
465 /* If the bit-clock is higher than 19.2MHz, Vape should be
466 * run in 100% OPP. Only when bit-clock is used (MSP master) */
467 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
468 "ux500-msp-i2s", 100);
469 drvdata->vape_opp_constraint = 1;
470 } else {
471 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
472 "ux500-msp-i2s", 50);
473 drvdata->vape_opp_constraint = 0;
474 }
475
476 return ret;
477}
478
479static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
480 struct snd_pcm_hw_params *params,
481 struct snd_soc_dai *dai)
482{
483 unsigned int mask, slots_active;
484 struct snd_pcm_runtime *runtime = substream->runtime;
485 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
486
487 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
488 __func__, dai->id, snd_pcm_stream_str(substream));
489
490 switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
491 case SND_SOC_DAIFMT_I2S:
492 snd_pcm_hw_constraint_minmax(runtime,
493 SNDRV_PCM_HW_PARAM_CHANNELS,
494 1, 2);
495 break;
496
497 case SND_SOC_DAIFMT_DSP_B:
498 case SND_SOC_DAIFMT_DSP_A:
499 mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
500 drvdata->tx_mask :
501 drvdata->rx_mask;
502
503 slots_active = hweight32(mask);
504 dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
505
506 snd_pcm_hw_constraint_minmax(runtime,
507 SNDRV_PCM_HW_PARAM_CHANNELS,
508 slots_active, slots_active);
509 break;
510
511 default:
512 dev_err(dai->dev,
513 "%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
514 __func__, drvdata->fmt);
515 return -EINVAL;
516 }
517
518 return 0;
519}
520
521static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
522 unsigned int fmt)
523{
524 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
525
526 dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
527
528 switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
529 SND_SOC_DAIFMT_MASTER_MASK)) {
530 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
531 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
532 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBS_CFS:
533 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_CBM_CFM:
534 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
535 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
536 break;
537
538 default:
539 dev_err(dai->dev,
540 "%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
541 __func__, drvdata->fmt);
542 return -EINVAL;
543 }
544
545 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
546 case SND_SOC_DAIFMT_NB_NF:
547 case SND_SOC_DAIFMT_NB_IF:
548 case SND_SOC_DAIFMT_IB_IF:
549 break;
550
551 default:
552 dev_err(dai->dev,
553 "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
554 __func__, drvdata->fmt);
555 return -EINVAL;
556 }
557
558 drvdata->fmt = fmt;
559 return 0;
560}
561
562static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
563 unsigned int tx_mask,
564 unsigned int rx_mask,
565 int slots, int slot_width)
566{
567 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
568 unsigned int cap;
569
570 switch (slots) {
571 case 1:
572 cap = 0x01;
573 break;
574 case 2:
575 cap = 0x03;
576 break;
577 case 8:
578 cap = 0xFF;
579 break;
580 case 16:
581 cap = 0xFFFF;
582 break;
583 default:
584 dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
585 __func__, slots);
586 return -EINVAL;
587 }
588 drvdata->slots = slots;
589
590 if (!(slot_width == 16)) {
591 dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
592 __func__, slot_width);
593 return -EINVAL;
594 }
595 drvdata->slot_width = slot_width;
596
597 drvdata->tx_mask = tx_mask & cap;
598 drvdata->rx_mask = rx_mask & cap;
599
600 return 0;
601}
602
603static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
604 int clk_id, unsigned int freq, int dir)
605{
606 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
607
608 dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
609 __func__, dai->id, clk_id, freq);
610
611 switch (clk_id) {
612 case UX500_MSP_MASTER_CLOCK:
613 drvdata->master_clk = freq;
614 break;
615
616 default:
617 dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
618 __func__, dai->id, clk_id);
619 return -EINVAL;
620 }
621
622 return 0;
623}
624
625static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
626 int cmd, struct snd_soc_dai *dai)
627{
628 int ret = 0;
629 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
630
631 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
632 __func__, dai->id, snd_pcm_stream_str(substream),
633 (int)drvdata->msp->id, cmd);
634
635 ret = ux500_msp_i2s_trigger(drvdata->msp, cmd, substream->stream);
636
637 return ret;
638}
639
640static int ux500_msp_dai_probe(struct snd_soc_dai *dai)
641{
642 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dai->dev);
643
644 drvdata->playback_dma_data.dma_cfg = drvdata->msp->dma_cfg_tx;
645 drvdata->capture_dma_data.dma_cfg = drvdata->msp->dma_cfg_rx;
646
647 dai->playback_dma_data = &drvdata->playback_dma_data;
648 dai->capture_dma_data = &drvdata->capture_dma_data;
649
650 drvdata->playback_dma_data.data_size = drvdata->slot_width;
651 drvdata->capture_dma_data.data_size = drvdata->slot_width;
652
653 return 0;
654}
655
656static struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
657 {
658 .set_sysclk = ux500_msp_dai_set_dai_sysclk,
659 .set_fmt = ux500_msp_dai_set_dai_fmt,
660 .set_tdm_slot = ux500_msp_dai_set_tdm_slot,
661 .startup = ux500_msp_dai_startup,
662 .shutdown = ux500_msp_dai_shutdown,
663 .prepare = ux500_msp_dai_prepare,
664 .trigger = ux500_msp_dai_trigger,
665 .hw_params = ux500_msp_dai_hw_params,
666 }
667};
668
669static struct snd_soc_dai_driver ux500_msp_dai_drv[UX500_NBR_OF_DAI] = {
670 {
671 .name = "ux500-msp-i2s.0",
672 .probe = ux500_msp_dai_probe,
673 .id = 0,
674 .suspend = NULL,
675 .resume = NULL,
676 .playback = {
677 .channels_min = UX500_MSP_MIN_CHANNELS,
678 .channels_max = UX500_MSP_MAX_CHANNELS,
679 .rates = UX500_I2S_RATES,
680 .formats = UX500_I2S_FORMATS,
681 },
682 .capture = {
683 .channels_min = UX500_MSP_MIN_CHANNELS,
684 .channels_max = UX500_MSP_MAX_CHANNELS,
685 .rates = UX500_I2S_RATES,
686 .formats = UX500_I2S_FORMATS,
687 },
688 .ops = ux500_msp_dai_ops,
689 },
690 {
691 .name = "ux500-msp-i2s.1",
692 .probe = ux500_msp_dai_probe,
693 .id = 1,
694 .suspend = NULL,
695 .resume = NULL,
696 .playback = {
697 .channels_min = UX500_MSP_MIN_CHANNELS,
698 .channels_max = UX500_MSP_MAX_CHANNELS,
699 .rates = UX500_I2S_RATES,
700 .formats = UX500_I2S_FORMATS,
701 },
702 .capture = {
703 .channels_min = UX500_MSP_MIN_CHANNELS,
704 .channels_max = UX500_MSP_MAX_CHANNELS,
705 .rates = UX500_I2S_RATES,
706 .formats = UX500_I2S_FORMATS,
707 },
708 .ops = ux500_msp_dai_ops,
709 },
710 {
711 .name = "ux500-msp-i2s.2",
712 .id = 2,
713 .probe = ux500_msp_dai_probe,
714 .suspend = NULL,
715 .resume = NULL,
716 .playback = {
717 .channels_min = UX500_MSP_MIN_CHANNELS,
718 .channels_max = UX500_MSP_MAX_CHANNELS,
719 .rates = UX500_I2S_RATES,
720 .formats = UX500_I2S_FORMATS,
721 },
722 .capture = {
723 .channels_min = UX500_MSP_MIN_CHANNELS,
724 .channels_max = UX500_MSP_MAX_CHANNELS,
725 .rates = UX500_I2S_RATES,
726 .formats = UX500_I2S_FORMATS,
727 },
728 .ops = ux500_msp_dai_ops,
729 },
730 {
731 .name = "ux500-msp-i2s.3",
732 .probe = ux500_msp_dai_probe,
733 .id = 3,
734 .suspend = NULL,
735 .resume = NULL,
736 .playback = {
737 .channels_min = UX500_MSP_MIN_CHANNELS,
738 .channels_max = UX500_MSP_MAX_CHANNELS,
739 .rates = UX500_I2S_RATES,
740 .formats = UX500_I2S_FORMATS,
741 },
742 .capture = {
743 .channels_min = UX500_MSP_MIN_CHANNELS,
744 .channels_max = UX500_MSP_MAX_CHANNELS,
745 .rates = UX500_I2S_RATES,
746 .formats = UX500_I2S_FORMATS,
747 },
748 .ops = ux500_msp_dai_ops,
749 },
750};
751
752static int __devinit ux500_msp_drv_probe(struct platform_device *pdev)
753{
754 struct ux500_msp_i2s_drvdata *drvdata;
755 int ret = 0;
756
757 dev_dbg(&pdev->dev, "%s: Enter (pdev->name = %s).\n", __func__,
758 pdev->name);
759
760 drvdata = devm_kzalloc(&pdev->dev,
761 sizeof(struct ux500_msp_i2s_drvdata),
762 GFP_KERNEL);
763 drvdata->fmt = 0;
764 drvdata->slots = 1;
765 drvdata->tx_mask = 0x01;
766 drvdata->rx_mask = 0x01;
767 drvdata->slot_width = 16;
768 drvdata->master_clk = MSP_INPUT_FREQ_APB;
769
770 drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
771 if (IS_ERR(drvdata->reg_vape)) {
772 ret = (int)PTR_ERR(drvdata->reg_vape);
773 dev_err(&pdev->dev,
774 "%s: ERROR: Failed to get Vape supply (%d)!\n",
775 __func__, ret);
776 return ret;
777 }
778 prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
779
780 drvdata->clk = clk_get(&pdev->dev, NULL);
781 if (IS_ERR(drvdata->clk)) {
782 ret = (int)PTR_ERR(drvdata->clk);
783 dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
784 __func__, ret);
785 goto err_clk;
786 }
787
788 ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
789 pdev->dev.platform_data);
790 if (!drvdata->msp) {
791 dev_err(&pdev->dev,
792 "%s: ERROR: Failed to init MSP-struct (%d)!",
793 __func__, ret);
794 goto err_init_msp;
795 }
796 dev_set_drvdata(&pdev->dev, drvdata);
797
798 ret = snd_soc_register_dai(&pdev->dev,
799 &ux500_msp_dai_drv[drvdata->msp->id]);
800 if (ret < 0) {
801 dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
802 __func__, drvdata->msp->id);
803 goto err_init_msp;
804 }
805
806 return 0;
807
808err_init_msp:
809 clk_put(drvdata->clk);
810
811err_clk:
812 devm_regulator_put(drvdata->reg_vape);
813
814 return ret;
815}
816
817static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
818{
819 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
820
821 snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
822
823 devm_regulator_put(drvdata->reg_vape);
824 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
825
826 clk_put(drvdata->clk);
827
828 ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
829
830 return 0;
831}
832
833static struct platform_driver msp_i2s_driver = {
834 .driver = {
835 .name = "ux500-msp-i2s",
836 .owner = THIS_MODULE,
837 },
838 .probe = ux500_msp_drv_probe,
839 .remove = ux500_msp_drv_remove,
840};
841module_platform_driver(msp_i2s_driver);
842
843MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_msp_dai.h b/sound/soc/ux500/ux500_msp_dai.h
new file mode 100644
index 000000000000..98202a34a5dd
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_dai.h
@@ -0,0 +1,79 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
6 * for ST-Ericsson.
7 *
8 * License terms:
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as published
12 * by the Free Software Foundation.
13 */
14
15#ifndef UX500_msp_dai_H
16#define UX500_msp_dai_H
17
18#include <linux/types.h>
19#include <linux/spinlock.h>
20
21#include "ux500_msp_i2s.h"
22
23#define UX500_NBR_OF_DAI 4
24
25#define UX500_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 | \
26 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
27
28#define UX500_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
29
30#define FRAME_PER_SINGLE_SLOT_8_KHZ 31
31#define FRAME_PER_SINGLE_SLOT_16_KHZ 124
32#define FRAME_PER_SINGLE_SLOT_44_1_KHZ 63
33#define FRAME_PER_SINGLE_SLOT_48_KHZ 49
34#define FRAME_PER_2_SLOTS 31
35#define FRAME_PER_8_SLOTS 138
36#define FRAME_PER_16_SLOTS 277
37
38#ifndef CONFIG_SND_SOC_UX500_AB5500
39#define UX500_MSP_INTERNAL_CLOCK_FREQ 40000000
40#define UX500_MSP1_INTERNAL_CLOCK_FREQ UX500_MSP_INTERNAL_CLOCK_FREQ
41#else
42#define UX500_MSP_INTERNAL_CLOCK_FREQ 13000000
43#define UX500_MSP1_INTERNAL_CLOCK_FREQ (UX500_MSP_INTERNAL_CLOCK_FREQ * 2)
44#endif
45
46#define UX500_MSP_MIN_CHANNELS 1
47#define UX500_MSP_MAX_CHANNELS 8
48
49#define PLAYBACK_CONFIGURED 1
50#define CAPTURE_CONFIGURED 2
51
52enum ux500_msp_clock_id {
53 UX500_MSP_MASTER_CLOCK,
54};
55
56struct ux500_msp_i2s_drvdata {
57 struct ux500_msp *msp;
58 struct regulator *reg_vape;
59 struct ux500_msp_dma_params playback_dma_data;
60 struct ux500_msp_dma_params capture_dma_data;
61 unsigned int fmt;
62 unsigned int tx_mask;
63 unsigned int rx_mask;
64 int slots;
65 int slot_width;
66 u8 configured;
67 int data_delay;
68
69 /* Clocks */
70 unsigned int master_clk;
71 struct clk *clk;
72
73 /* Regulators */
74 int vape_opp_constraint;
75};
76
77int ux500_msp_dai_set_data_delay(struct snd_soc_dai *dai, int delay);
78
79#endif
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c
new file mode 100644
index 000000000000..496dec10c96e
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_i2s.c
@@ -0,0 +1,742 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * Roger Nilsson <roger.xr.nilsson@stericsson.com>,
6 * Sandeep Kaushik <sandeep.kaushik@st.com>
7 * for ST-Ericsson.
8 *
9 * License terms:
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as published
13 * by the Free Software Foundation.
14 */
15
16#include <linux/module.h>
17#include <linux/platform_device.h>
18#include <linux/delay.h>
19#include <linux/slab.h>
20
21#include <mach/hardware.h>
22#include <mach/board-mop500-msp.h>
23
24#include <sound/soc.h>
25
26#include "ux500_msp_i2s.h"
27
28 /* Protocol desciptors */
29static const struct msp_protdesc prot_descs[] = {
30 { /* I2S */
31 MSP_SINGLE_PHASE,
32 MSP_SINGLE_PHASE,
33 MSP_PHASE2_START_MODE_IMEDIATE,
34 MSP_PHASE2_START_MODE_IMEDIATE,
35 MSP_BTF_MS_BIT_FIRST,
36 MSP_BTF_MS_BIT_FIRST,
37 MSP_FRAME_LEN_1,
38 MSP_FRAME_LEN_1,
39 MSP_FRAME_LEN_1,
40 MSP_FRAME_LEN_1,
41 MSP_ELEM_LEN_32,
42 MSP_ELEM_LEN_32,
43 MSP_ELEM_LEN_32,
44 MSP_ELEM_LEN_32,
45 MSP_DELAY_1,
46 MSP_DELAY_1,
47 MSP_RISING_EDGE,
48 MSP_FALLING_EDGE,
49 MSP_FSYNC_POL_ACT_LO,
50 MSP_FSYNC_POL_ACT_LO,
51 MSP_SWAP_NONE,
52 MSP_SWAP_NONE,
53 MSP_COMPRESS_MODE_LINEAR,
54 MSP_EXPAND_MODE_LINEAR,
55 MSP_FSYNC_IGNORE,
56 31,
57 15,
58 32,
59 }, { /* PCM */
60 MSP_DUAL_PHASE,
61 MSP_DUAL_PHASE,
62 MSP_PHASE2_START_MODE_FSYNC,
63 MSP_PHASE2_START_MODE_FSYNC,
64 MSP_BTF_MS_BIT_FIRST,
65 MSP_BTF_MS_BIT_FIRST,
66 MSP_FRAME_LEN_1,
67 MSP_FRAME_LEN_1,
68 MSP_FRAME_LEN_1,
69 MSP_FRAME_LEN_1,
70 MSP_ELEM_LEN_16,
71 MSP_ELEM_LEN_16,
72 MSP_ELEM_LEN_16,
73 MSP_ELEM_LEN_16,
74 MSP_DELAY_0,
75 MSP_DELAY_0,
76 MSP_RISING_EDGE,
77 MSP_FALLING_EDGE,
78 MSP_FSYNC_POL_ACT_HI,
79 MSP_FSYNC_POL_ACT_HI,
80 MSP_SWAP_NONE,
81 MSP_SWAP_NONE,
82 MSP_COMPRESS_MODE_LINEAR,
83 MSP_EXPAND_MODE_LINEAR,
84 MSP_FSYNC_IGNORE,
85 255,
86 0,
87 256,
88 }, { /* Companded PCM */
89 MSP_SINGLE_PHASE,
90 MSP_SINGLE_PHASE,
91 MSP_PHASE2_START_MODE_FSYNC,
92 MSP_PHASE2_START_MODE_FSYNC,
93 MSP_BTF_MS_BIT_FIRST,
94 MSP_BTF_MS_BIT_FIRST,
95 MSP_FRAME_LEN_1,
96 MSP_FRAME_LEN_1,
97 MSP_FRAME_LEN_1,
98 MSP_FRAME_LEN_1,
99 MSP_ELEM_LEN_8,
100 MSP_ELEM_LEN_8,
101 MSP_ELEM_LEN_8,
102 MSP_ELEM_LEN_8,
103 MSP_DELAY_0,
104 MSP_DELAY_0,
105 MSP_RISING_EDGE,
106 MSP_RISING_EDGE,
107 MSP_FSYNC_POL_ACT_HI,
108 MSP_FSYNC_POL_ACT_HI,
109 MSP_SWAP_NONE,
110 MSP_SWAP_NONE,
111 MSP_COMPRESS_MODE_LINEAR,
112 MSP_EXPAND_MODE_LINEAR,
113 MSP_FSYNC_IGNORE,
114 255,
115 0,
116 256,
117 },
118};
119
120static void set_prot_desc_tx(struct ux500_msp *msp,
121 struct msp_protdesc *protdesc,
122 enum msp_data_size data_size)
123{
124 u32 temp_reg = 0;
125
126 temp_reg |= MSP_P2_ENABLE_BIT(protdesc->tx_phase_mode);
127 temp_reg |= MSP_P2_START_MODE_BIT(protdesc->tx_phase2_start_mode);
128 temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->tx_frame_len_1);
129 temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->tx_frame_len_2);
130 if (msp->def_elem_len) {
131 temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->tx_elem_len_1);
132 temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->tx_elem_len_2);
133 } else {
134 temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);
135 temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);
136 }
137 temp_reg |= MSP_DATA_DELAY_BITS(protdesc->tx_data_delay);
138 temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->tx_byte_order);
139 temp_reg |= MSP_FSYNC_POL(protdesc->tx_fsync_pol);
140 temp_reg |= MSP_DATA_WORD_SWAP(protdesc->tx_half_word_swap);
141 temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->compression_mode);
142 temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);
143
144 writel(temp_reg, msp->registers + MSP_TCF);
145}
146
147static void set_prot_desc_rx(struct ux500_msp *msp,
148 struct msp_protdesc *protdesc,
149 enum msp_data_size data_size)
150{
151 u32 temp_reg = 0;
152
153 temp_reg |= MSP_P2_ENABLE_BIT(protdesc->rx_phase_mode);
154 temp_reg |= MSP_P2_START_MODE_BIT(protdesc->rx_phase2_start_mode);
155 temp_reg |= MSP_P1_FRAME_LEN_BITS(protdesc->rx_frame_len_1);
156 temp_reg |= MSP_P2_FRAME_LEN_BITS(protdesc->rx_frame_len_2);
157 if (msp->def_elem_len) {
158 temp_reg |= MSP_P1_ELEM_LEN_BITS(protdesc->rx_elem_len_1);
159 temp_reg |= MSP_P2_ELEM_LEN_BITS(protdesc->rx_elem_len_2);
160 } else {
161 temp_reg |= MSP_P1_ELEM_LEN_BITS(data_size);
162 temp_reg |= MSP_P2_ELEM_LEN_BITS(data_size);
163 }
164
165 temp_reg |= MSP_DATA_DELAY_BITS(protdesc->rx_data_delay);
166 temp_reg |= MSP_SET_ENDIANNES_BIT(protdesc->rx_byte_order);
167 temp_reg |= MSP_FSYNC_POL(protdesc->rx_fsync_pol);
168 temp_reg |= MSP_DATA_WORD_SWAP(protdesc->rx_half_word_swap);
169 temp_reg |= MSP_SET_COMPANDING_MODE(protdesc->expansion_mode);
170 temp_reg |= MSP_SET_FSYNC_IGNORE(protdesc->frame_sync_ignore);
171
172 writel(temp_reg, msp->registers + MSP_RCF);
173}
174
175static int configure_protocol(struct ux500_msp *msp,
176 struct ux500_msp_config *config)
177{
178 struct msp_protdesc *protdesc;
179 enum msp_data_size data_size;
180 u32 temp_reg = 0;
181
182 data_size = config->data_size;
183 msp->def_elem_len = config->def_elem_len;
184 if (config->default_protdesc == 1) {
185 if (config->protocol >= MSP_INVALID_PROTOCOL) {
186 dev_err(msp->dev, "%s: ERROR: Invalid protocol!\n",
187 __func__);
188 return -EINVAL;
189 }
190 protdesc =
191 (struct msp_protdesc *)&prot_descs[config->protocol];
192 } else {
193 protdesc = (struct msp_protdesc *)&config->protdesc;
194 }
195
196 if (data_size < MSP_DATA_BITS_DEFAULT || data_size > MSP_DATA_BITS_32) {
197 dev_err(msp->dev,
198 "%s: ERROR: Invalid data-size requested (data_size = %d)!\n",
199 __func__, data_size);
200 return -EINVAL;
201 }
202
203 if (config->direction & MSP_DIR_TX)
204 set_prot_desc_tx(msp, protdesc, data_size);
205 if (config->direction & MSP_DIR_RX)
206 set_prot_desc_rx(msp, protdesc, data_size);
207
208 /* The code below should not be separated. */
209 temp_reg = readl(msp->registers + MSP_GCR) & ~TX_CLK_POL_RISING;
210 temp_reg |= MSP_TX_CLKPOL_BIT(~protdesc->tx_clk_pol);
211 writel(temp_reg, msp->registers + MSP_GCR);
212 temp_reg = readl(msp->registers + MSP_GCR) & ~RX_CLK_POL_RISING;
213 temp_reg |= MSP_RX_CLKPOL_BIT(protdesc->rx_clk_pol);
214 writel(temp_reg, msp->registers + MSP_GCR);
215
216 return 0;
217}
218
219static int setup_bitclk(struct ux500_msp *msp, struct ux500_msp_config *config)
220{
221 u32 reg_val_GCR;
222 u32 frame_per = 0;
223 u32 sck_div = 0;
224 u32 frame_width = 0;
225 u32 temp_reg = 0;
226 struct msp_protdesc *protdesc = NULL;
227
228 reg_val_GCR = readl(msp->registers + MSP_GCR);
229 writel(reg_val_GCR & ~SRG_ENABLE, msp->registers + MSP_GCR);
230
231 if (config->default_protdesc)
232 protdesc =
233 (struct msp_protdesc *)&prot_descs[config->protocol];
234 else
235 protdesc = (struct msp_protdesc *)&config->protdesc;
236
237 switch (config->protocol) {
238 case MSP_PCM_PROTOCOL:
239 case MSP_PCM_COMPAND_PROTOCOL:
240 frame_width = protdesc->frame_width;
241 sck_div = config->f_inputclk / (config->frame_freq *
242 (protdesc->clocks_per_frame));
243 frame_per = protdesc->frame_period;
244 break;
245 case MSP_I2S_PROTOCOL:
246 frame_width = protdesc->frame_width;
247 sck_div = config->f_inputclk / (config->frame_freq *
248 (protdesc->clocks_per_frame));
249 frame_per = protdesc->frame_period;
250 break;
251 default:
252 dev_err(msp->dev, "%s: ERROR: Unknown protocol (%d)!\n",
253 __func__,
254 config->protocol);
255 return -EINVAL;
256 }
257
258 temp_reg = (sck_div - 1) & SCK_DIV_MASK;
259 temp_reg |= FRAME_WIDTH_BITS(frame_width);
260 temp_reg |= FRAME_PERIOD_BITS(frame_per);
261 writel(temp_reg, msp->registers + MSP_SRG);
262
263 msp->f_bitclk = (config->f_inputclk)/(sck_div + 1);
264
265 /* Enable bit-clock */
266 udelay(100);
267 reg_val_GCR = readl(msp->registers + MSP_GCR);
268 writel(reg_val_GCR | SRG_ENABLE, msp->registers + MSP_GCR);
269 udelay(100);
270
271 return 0;
272}
273
274static int configure_multichannel(struct ux500_msp *msp,
275 struct ux500_msp_config *config)
276{
277 struct msp_protdesc *protdesc;
278 struct msp_multichannel_config *mcfg;
279 u32 reg_val_MCR;
280
281 if (config->default_protdesc == 1) {
282 if (config->protocol >= MSP_INVALID_PROTOCOL) {
283 dev_err(msp->dev,
284 "%s: ERROR: Invalid protocol (%d)!\n",
285 __func__, config->protocol);
286 return -EINVAL;
287 }
288 protdesc = (struct msp_protdesc *)
289 &prot_descs[config->protocol];
290 } else {
291 protdesc = (struct msp_protdesc *)&config->protdesc;
292 }
293
294 mcfg = &config->multichannel_config;
295 if (mcfg->tx_multichannel_enable) {
296 if (protdesc->tx_phase_mode == MSP_SINGLE_PHASE) {
297 reg_val_MCR = readl(msp->registers + MSP_MCR);
298 writel(reg_val_MCR | (mcfg->tx_multichannel_enable ?
299 1 << TMCEN_BIT : 0),
300 msp->registers + MSP_MCR);
301 writel(mcfg->tx_channel_0_enable,
302 msp->registers + MSP_TCE0);
303 writel(mcfg->tx_channel_1_enable,
304 msp->registers + MSP_TCE1);
305 writel(mcfg->tx_channel_2_enable,
306 msp->registers + MSP_TCE2);
307 writel(mcfg->tx_channel_3_enable,
308 msp->registers + MSP_TCE3);
309 } else {
310 dev_err(msp->dev,
311 "%s: ERROR: Only single-phase supported (TX-mode: %d)!\n",
312 __func__, protdesc->tx_phase_mode);
313 return -EINVAL;
314 }
315 }
316 if (mcfg->rx_multichannel_enable) {
317 if (protdesc->rx_phase_mode == MSP_SINGLE_PHASE) {
318 reg_val_MCR = readl(msp->registers + MSP_MCR);
319 writel(reg_val_MCR | (mcfg->rx_multichannel_enable ?
320 1 << RMCEN_BIT : 0),
321 msp->registers + MSP_MCR);
322 writel(mcfg->rx_channel_0_enable,
323 msp->registers + MSP_RCE0);
324 writel(mcfg->rx_channel_1_enable,
325 msp->registers + MSP_RCE1);
326 writel(mcfg->rx_channel_2_enable,
327 msp->registers + MSP_RCE2);
328 writel(mcfg->rx_channel_3_enable,
329 msp->registers + MSP_RCE3);
330 } else {
331 dev_err(msp->dev,
332 "%s: ERROR: Only single-phase supported (RX-mode: %d)!\n",
333 __func__, protdesc->rx_phase_mode);
334 return -EINVAL;
335 }
336 if (mcfg->rx_comparison_enable_mode) {
337 reg_val_MCR = readl(msp->registers + MSP_MCR);
338 writel(reg_val_MCR |
339 (mcfg->rx_comparison_enable_mode << RCMPM_BIT),
340 msp->registers + MSP_MCR);
341
342 writel(mcfg->comparison_mask,
343 msp->registers + MSP_RCM);
344 writel(mcfg->comparison_value,
345 msp->registers + MSP_RCV);
346
347 }
348 }
349
350 return 0;
351}
352
353static int enable_msp(struct ux500_msp *msp, struct ux500_msp_config *config)
354{
355 int status = 0;
356 u32 reg_val_DMACR, reg_val_GCR;
357
358 /* Check msp state whether in RUN or CONFIGURED Mode */
359 if ((msp->msp_state == MSP_STATE_IDLE) && (msp->plat_init)) {
360 status = msp->plat_init();
361 if (status) {
362 dev_err(msp->dev, "%s: ERROR: Failed to init MSP (%d)!\n",
363 __func__, status);
364 return status;
365 }
366 }
367
368 /* Configure msp with protocol dependent settings */
369 configure_protocol(msp, config);
370 setup_bitclk(msp, config);
371 if (config->multichannel_configured == 1) {
372 status = configure_multichannel(msp, config);
373 if (status)
374 dev_warn(msp->dev,
375 "%s: WARN: configure_multichannel failed (%d)!\n",
376 __func__, status);
377 }
378
379 /* Make sure the correct DMA-directions are configured */
380 if ((config->direction & MSP_DIR_RX) && (!msp->dma_cfg_rx)) {
381 dev_err(msp->dev, "%s: ERROR: MSP RX-mode is not configured!",
382 __func__);
383 return -EINVAL;
384 }
385 if ((config->direction == MSP_DIR_TX) && (!msp->dma_cfg_tx)) {
386 dev_err(msp->dev, "%s: ERROR: MSP TX-mode is not configured!",
387 __func__);
388 return -EINVAL;
389 }
390
391 reg_val_DMACR = readl(msp->registers + MSP_DMACR);
392 if (config->direction & MSP_DIR_RX)
393 reg_val_DMACR |= RX_DMA_ENABLE;
394 if (config->direction & MSP_DIR_TX)
395 reg_val_DMACR |= TX_DMA_ENABLE;
396 writel(reg_val_DMACR, msp->registers + MSP_DMACR);
397
398 writel(config->iodelay, msp->registers + MSP_IODLY);
399
400 /* Enable frame generation logic */
401 reg_val_GCR = readl(msp->registers + MSP_GCR);
402 writel(reg_val_GCR | FRAME_GEN_ENABLE, msp->registers + MSP_GCR);
403
404 return status;
405}
406
407static void flush_fifo_rx(struct ux500_msp *msp)
408{
409 u32 reg_val_DR, reg_val_GCR, reg_val_FLR;
410 u32 limit = 32;
411
412 reg_val_GCR = readl(msp->registers + MSP_GCR);
413 writel(reg_val_GCR | RX_ENABLE, msp->registers + MSP_GCR);
414
415 reg_val_FLR = readl(msp->registers + MSP_FLR);
416 while (!(reg_val_FLR & RX_FIFO_EMPTY) && limit--) {
417 reg_val_DR = readl(msp->registers + MSP_DR);
418 reg_val_FLR = readl(msp->registers + MSP_FLR);
419 }
420
421 writel(reg_val_GCR, msp->registers + MSP_GCR);
422}
423
424static void flush_fifo_tx(struct ux500_msp *msp)
425{
426 u32 reg_val_TSTDR, reg_val_GCR, reg_val_FLR;
427 u32 limit = 32;
428
429 reg_val_GCR = readl(msp->registers + MSP_GCR);
430 writel(reg_val_GCR | TX_ENABLE, msp->registers + MSP_GCR);
431 writel(MSP_ITCR_ITEN | MSP_ITCR_TESTFIFO, msp->registers + MSP_ITCR);
432
433 reg_val_FLR = readl(msp->registers + MSP_FLR);
434 while (!(reg_val_FLR & TX_FIFO_EMPTY) && limit--) {
435 reg_val_TSTDR = readl(msp->registers + MSP_TSTDR);
436 reg_val_FLR = readl(msp->registers + MSP_FLR);
437 }
438 writel(0x0, msp->registers + MSP_ITCR);
439 writel(reg_val_GCR, msp->registers + MSP_GCR);
440}
441
442int ux500_msp_i2s_open(struct ux500_msp *msp,
443 struct ux500_msp_config *config)
444{
445 u32 old_reg, new_reg, mask;
446 int res;
447 unsigned int tx_sel, rx_sel, tx_busy, rx_busy;
448
449 if (in_interrupt()) {
450 dev_err(msp->dev,
451 "%s: ERROR: Open called in interrupt context!\n",
452 __func__);
453 return -1;
454 }
455
456 tx_sel = (config->direction & MSP_DIR_TX) > 0;
457 rx_sel = (config->direction & MSP_DIR_RX) > 0;
458 if (!tx_sel && !rx_sel) {
459 dev_err(msp->dev, "%s: Error: No direction selected!\n",
460 __func__);
461 return -EINVAL;
462 }
463
464 tx_busy = (msp->dir_busy & MSP_DIR_TX) > 0;
465 rx_busy = (msp->dir_busy & MSP_DIR_RX) > 0;
466 if (tx_busy && tx_sel) {
467 dev_err(msp->dev, "%s: Error: TX is in use!\n", __func__);
468 return -EBUSY;
469 }
470 if (rx_busy && rx_sel) {
471 dev_err(msp->dev, "%s: Error: RX is in use!\n", __func__);
472 return -EBUSY;
473 }
474
475 msp->dir_busy |= (tx_sel ? MSP_DIR_TX : 0) | (rx_sel ? MSP_DIR_RX : 0);
476
477 /* First do the global config register */
478 mask = RX_CLK_SEL_MASK | TX_CLK_SEL_MASK | RX_FSYNC_MASK |
479 TX_FSYNC_MASK | RX_SYNC_SEL_MASK | TX_SYNC_SEL_MASK |
480 RX_FIFO_ENABLE_MASK | TX_FIFO_ENABLE_MASK | SRG_CLK_SEL_MASK |
481 LOOPBACK_MASK | TX_EXTRA_DELAY_MASK;
482
483 new_reg = (config->tx_clk_sel | config->rx_clk_sel |
484 config->rx_fsync_pol | config->tx_fsync_pol |
485 config->rx_fsync_sel | config->tx_fsync_sel |
486 config->rx_fifo_config | config->tx_fifo_config |
487 config->srg_clk_sel | config->loopback_enable |
488 config->tx_data_enable);
489
490 old_reg = readl(msp->registers + MSP_GCR);
491 old_reg &= ~mask;
492 new_reg |= old_reg;
493 writel(new_reg, msp->registers + MSP_GCR);
494
495 res = enable_msp(msp, config);
496 if (res < 0) {
497 dev_err(msp->dev, "%s: ERROR: enable_msp failed (%d)!\n",
498 __func__, res);
499 return -EBUSY;
500 }
501 if (config->loopback_enable & 0x80)
502 msp->loopback_enable = 1;
503
504 /* Flush FIFOs */
505 flush_fifo_tx(msp);
506 flush_fifo_rx(msp);
507
508 msp->msp_state = MSP_STATE_CONFIGURED;
509 return 0;
510}
511
512static void disable_msp_rx(struct ux500_msp *msp)
513{
514 u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;
515
516 reg_val_GCR = readl(msp->registers + MSP_GCR);
517 writel(reg_val_GCR & ~RX_ENABLE, msp->registers + MSP_GCR);
518 reg_val_DMACR = readl(msp->registers + MSP_DMACR);
519 writel(reg_val_DMACR & ~RX_DMA_ENABLE, msp->registers + MSP_DMACR);
520 reg_val_IMSC = readl(msp->registers + MSP_IMSC);
521 writel(reg_val_IMSC &
522 ~(RX_SERVICE_INT | RX_OVERRUN_ERROR_INT),
523 msp->registers + MSP_IMSC);
524
525 msp->dir_busy &= ~MSP_DIR_RX;
526}
527
528static void disable_msp_tx(struct ux500_msp *msp)
529{
530 u32 reg_val_GCR, reg_val_DMACR, reg_val_IMSC;
531
532 reg_val_GCR = readl(msp->registers + MSP_GCR);
533 writel(reg_val_GCR & ~TX_ENABLE, msp->registers + MSP_GCR);
534 reg_val_DMACR = readl(msp->registers + MSP_DMACR);
535 writel(reg_val_DMACR & ~TX_DMA_ENABLE, msp->registers + MSP_DMACR);
536 reg_val_IMSC = readl(msp->registers + MSP_IMSC);
537 writel(reg_val_IMSC &
538 ~(TX_SERVICE_INT | TX_UNDERRUN_ERR_INT),
539 msp->registers + MSP_IMSC);
540
541 msp->dir_busy &= ~MSP_DIR_TX;
542}
543
544static int disable_msp(struct ux500_msp *msp, unsigned int dir)
545{
546 u32 reg_val_GCR;
547 int status = 0;
548 unsigned int disable_tx, disable_rx;
549
550 reg_val_GCR = readl(msp->registers + MSP_GCR);
551 disable_tx = dir & MSP_DIR_TX;
552 disable_rx = dir & MSP_DIR_TX;
553 if (disable_tx && disable_rx) {
554 reg_val_GCR = readl(msp->registers + MSP_GCR);
555 writel(reg_val_GCR | LOOPBACK_MASK,
556 msp->registers + MSP_GCR);
557
558 /* Flush TX-FIFO */
559 flush_fifo_tx(msp);
560
561 /* Disable TX-channel */
562 writel((readl(msp->registers + MSP_GCR) &
563 (~TX_ENABLE)), msp->registers + MSP_GCR);
564
565 /* Flush RX-FIFO */
566 flush_fifo_rx(msp);
567
568 /* Disable Loopback and Receive channel */
569 writel((readl(msp->registers + MSP_GCR) &
570 (~(RX_ENABLE | LOOPBACK_MASK))),
571 msp->registers + MSP_GCR);
572
573 disable_msp_tx(msp);
574 disable_msp_rx(msp);
575 } else if (disable_tx)
576 disable_msp_tx(msp);
577 else if (disable_rx)
578 disable_msp_rx(msp);
579
580 return status;
581}
582
583int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd, int direction)
584{
585 u32 reg_val_GCR, enable_bit;
586
587 if (msp->msp_state == MSP_STATE_IDLE) {
588 dev_err(msp->dev, "%s: ERROR: MSP is not configured!\n",
589 __func__);
590 return -EINVAL;
591 }
592
593 switch (cmd) {
594 case SNDRV_PCM_TRIGGER_START:
595 case SNDRV_PCM_TRIGGER_RESUME:
596 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
597 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
598 enable_bit = TX_ENABLE;
599 else
600 enable_bit = RX_ENABLE;
601 reg_val_GCR = readl(msp->registers + MSP_GCR);
602 writel(reg_val_GCR | enable_bit, msp->registers + MSP_GCR);
603 break;
604
605 case SNDRV_PCM_TRIGGER_STOP:
606 case SNDRV_PCM_TRIGGER_SUSPEND:
607 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
608 if (direction == SNDRV_PCM_STREAM_PLAYBACK)
609 disable_msp_tx(msp);
610 else
611 disable_msp_rx(msp);
612 break;
613 default:
614 return -EINVAL;
615 break;
616 }
617
618 return 0;
619}
620
621int ux500_msp_i2s_close(struct ux500_msp *msp, unsigned int dir)
622{
623 int status = 0;
624
625 dev_dbg(msp->dev, "%s: Enter (dir = 0x%01x).\n", __func__, dir);
626
627 status = disable_msp(msp, dir);
628 if (msp->dir_busy == 0) {
629 /* disable sample rate and frame generators */
630 msp->msp_state = MSP_STATE_IDLE;
631 writel((readl(msp->registers + MSP_GCR) &
632 (~(FRAME_GEN_ENABLE | SRG_ENABLE))),
633 msp->registers + MSP_GCR);
634 if (msp->plat_exit)
635 status = msp->plat_exit();
636 if (status)
637 dev_warn(msp->dev,
638 "%s: WARN: ux500_msp_i2s_exit failed (%d)!\n",
639 __func__, status);
640 writel(0, msp->registers + MSP_GCR);
641 writel(0, msp->registers + MSP_TCF);
642 writel(0, msp->registers + MSP_RCF);
643 writel(0, msp->registers + MSP_DMACR);
644 writel(0, msp->registers + MSP_SRG);
645 writel(0, msp->registers + MSP_MCR);
646 writel(0, msp->registers + MSP_RCM);
647 writel(0, msp->registers + MSP_RCV);
648 writel(0, msp->registers + MSP_TCE0);
649 writel(0, msp->registers + MSP_TCE1);
650 writel(0, msp->registers + MSP_TCE2);
651 writel(0, msp->registers + MSP_TCE3);
652 writel(0, msp->registers + MSP_RCE0);
653 writel(0, msp->registers + MSP_RCE1);
654 writel(0, msp->registers + MSP_RCE2);
655 writel(0, msp->registers + MSP_RCE3);
656 }
657
658 return status;
659
660}
661
662int ux500_msp_i2s_init_msp(struct platform_device *pdev,
663 struct ux500_msp **msp_p,
664 struct msp_i2s_platform_data *platform_data)
665{
666 int ret = 0;
667 struct resource *res = NULL;
668 struct i2s_controller *i2s_cont;
669 struct ux500_msp *msp;
670
671 dev_dbg(&pdev->dev, "%s: Enter (name: %s, id: %d).\n", __func__,
672 pdev->name, platform_data->id);
673
674 *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL);
675 msp = *msp_p;
676
677 msp->id = platform_data->id;
678 msp->dev = &pdev->dev;
679 msp->plat_init = platform_data->msp_i2s_init;
680 msp->plat_exit = platform_data->msp_i2s_exit;
681 msp->dma_cfg_rx = platform_data->msp_i2s_dma_rx;
682 msp->dma_cfg_tx = platform_data->msp_i2s_dma_tx;
683
684 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
685 if (res == NULL) {
686 dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",
687 __func__);
688 ret = -ENOMEM;
689 goto err_res;
690 }
691
692 msp->registers = ioremap(res->start, (res->end - res->start + 1));
693 if (msp->registers == NULL) {
694 dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__);
695 ret = -ENOMEM;
696 goto err_res;
697 }
698
699 msp->msp_state = MSP_STATE_IDLE;
700 msp->loopback_enable = 0;
701
702 /* I2S-controller is allocated and added in I2S controller class. */
703 i2s_cont = devm_kzalloc(&pdev->dev, sizeof(*i2s_cont), GFP_KERNEL);
704 if (!i2s_cont) {
705 dev_err(&pdev->dev,
706 "%s: ERROR: Failed to allocate I2S-controller!\n",
707 __func__);
708 goto err_i2s_cont;
709 }
710 i2s_cont->dev.parent = &pdev->dev;
711 i2s_cont->data = (void *)msp;
712 i2s_cont->id = (s16)msp->id;
713 snprintf(i2s_cont->name, sizeof(i2s_cont->name), "ux500-msp-i2s.%04x",
714 msp->id);
715 dev_dbg(&pdev->dev, "I2S device-name: '%s'\n", i2s_cont->name);
716 msp->i2s_cont = i2s_cont;
717
718 return 0;
719
720err_i2s_cont:
721 iounmap(msp->registers);
722
723err_res:
724 devm_kfree(&pdev->dev, msp);
725
726 return ret;
727}
728
729void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
730 struct ux500_msp *msp)
731{
732 dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
733
734 device_unregister(&msp->i2s_cont->dev);
735 devm_kfree(&pdev->dev, msp->i2s_cont);
736
737 iounmap(msp->registers);
738
739 devm_kfree(&pdev->dev, msp);
740}
741
742MODULE_LICENSE("GPLv2");
diff --git a/sound/soc/ux500/ux500_msp_i2s.h b/sound/soc/ux500/ux500_msp_i2s.h
new file mode 100644
index 000000000000..7f71b4a0d4bc
--- /dev/null
+++ b/sound/soc/ux500/ux500_msp_i2s.h
@@ -0,0 +1,553 @@
1/*
2 * Copyright (C) ST-Ericsson SA 2012
3 *
4 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
5 * for ST-Ericsson.
6 *
7 * License terms:
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as published
11 * by the Free Software Foundation.
12 */
13
14
15#ifndef UX500_MSP_I2S_H
16#define UX500_MSP_I2S_H
17
18#include <linux/platform_device.h>
19
20#include <mach/board-mop500-msp.h>
21
22#define MSP_INPUT_FREQ_APB 48000000
23
24/*** Stereo mode. Used for APB data accesses as 16 bits accesses (mono),
25 * 32 bits accesses (stereo).
26 ***/
27enum msp_stereo_mode {
28 MSP_MONO,
29 MSP_STEREO
30};
31
32/* Direction (Transmit/Receive mode) */
33enum msp_direction {
34 MSP_TX = 1,
35 MSP_RX = 2
36};
37
38/* Transmit and receive configuration register */
39#define MSP_BIG_ENDIAN 0x00000000
40#define MSP_LITTLE_ENDIAN 0x00001000
41#define MSP_UNEXPECTED_FS_ABORT 0x00000000
42#define MSP_UNEXPECTED_FS_IGNORE 0x00008000
43#define MSP_NON_MODE_BIT_MASK 0x00009000
44
45/* Global configuration register */
46#define RX_ENABLE 0x00000001
47#define RX_FIFO_ENABLE 0x00000002
48#define RX_SYNC_SRG 0x00000010
49#define RX_CLK_POL_RISING 0x00000020
50#define RX_CLK_SEL_SRG 0x00000040
51#define TX_ENABLE 0x00000100
52#define TX_FIFO_ENABLE 0x00000200
53#define TX_SYNC_SRG_PROG 0x00001800
54#define TX_SYNC_SRG_AUTO 0x00001000
55#define TX_CLK_POL_RISING 0x00002000
56#define TX_CLK_SEL_SRG 0x00004000
57#define TX_EXTRA_DELAY_ENABLE 0x00008000
58#define SRG_ENABLE 0x00010000
59#define FRAME_GEN_ENABLE 0x00100000
60#define SRG_CLK_SEL_APB 0x00000000
61#define RX_FIFO_SYNC_HI 0x00000000
62#define TX_FIFO_SYNC_HI 0x00000000
63#define SPI_CLK_MODE_NORMAL 0x00000000
64
65#define MSP_FRAME_SIZE_AUTO -1
66
67#define MSP_DR 0x00
68#define MSP_GCR 0x04
69#define MSP_TCF 0x08
70#define MSP_RCF 0x0c
71#define MSP_SRG 0x10
72#define MSP_FLR 0x14
73#define MSP_DMACR 0x18
74
75#define MSP_IMSC 0x20
76#define MSP_RIS 0x24
77#define MSP_MIS 0x28
78#define MSP_ICR 0x2c
79#define MSP_MCR 0x30
80#define MSP_RCV 0x34
81#define MSP_RCM 0x38
82
83#define MSP_TCE0 0x40
84#define MSP_TCE1 0x44
85#define MSP_TCE2 0x48
86#define MSP_TCE3 0x4c
87
88#define MSP_RCE0 0x60
89#define MSP_RCE1 0x64
90#define MSP_RCE2 0x68
91#define MSP_RCE3 0x6c
92#define MSP_IODLY 0x70
93
94#define MSP_ITCR 0x80
95#define MSP_ITIP 0x84
96#define MSP_ITOP 0x88
97#define MSP_TSTDR 0x8c
98
99#define MSP_PID0 0xfe0
100#define MSP_PID1 0xfe4
101#define MSP_PID2 0xfe8
102#define MSP_PID3 0xfec
103
104#define MSP_CID0 0xff0
105#define MSP_CID1 0xff4
106#define MSP_CID2 0xff8
107#define MSP_CID3 0xffc
108
109/* Protocol dependant parameters list */
110#define RX_ENABLE_MASK BIT(0)
111#define RX_FIFO_ENABLE_MASK BIT(1)
112#define RX_FSYNC_MASK BIT(2)
113#define DIRECT_COMPANDING_MASK BIT(3)
114#define RX_SYNC_SEL_MASK BIT(4)
115#define RX_CLK_POL_MASK BIT(5)
116#define RX_CLK_SEL_MASK BIT(6)
117#define LOOPBACK_MASK BIT(7)
118#define TX_ENABLE_MASK BIT(8)
119#define TX_FIFO_ENABLE_MASK BIT(9)
120#define TX_FSYNC_MASK BIT(10)
121#define TX_MSP_TDR_TSR BIT(11)
122#define TX_SYNC_SEL_MASK (BIT(12) | BIT(11))
123#define TX_CLK_POL_MASK BIT(13)
124#define TX_CLK_SEL_MASK BIT(14)
125#define TX_EXTRA_DELAY_MASK BIT(15)
126#define SRG_ENABLE_MASK BIT(16)
127#define SRG_CLK_POL_MASK BIT(17)
128#define SRG_CLK_SEL_MASK (BIT(19) | BIT(18))
129#define FRAME_GEN_EN_MASK BIT(20)
130#define SPI_CLK_MODE_MASK (BIT(22) | BIT(21))
131#define SPI_BURST_MODE_MASK BIT(23)
132
133#define RXEN_SHIFT 0
134#define RFFEN_SHIFT 1
135#define RFSPOL_SHIFT 2
136#define DCM_SHIFT 3
137#define RFSSEL_SHIFT 4
138#define RCKPOL_SHIFT 5
139#define RCKSEL_SHIFT 6
140#define LBM_SHIFT 7
141#define TXEN_SHIFT 8
142#define TFFEN_SHIFT 9
143#define TFSPOL_SHIFT 10
144#define TFSSEL_SHIFT 11
145#define TCKPOL_SHIFT 13
146#define TCKSEL_SHIFT 14
147#define TXDDL_SHIFT 15
148#define SGEN_SHIFT 16
149#define SCKPOL_SHIFT 17
150#define SCKSEL_SHIFT 18
151#define FGEN_SHIFT 20
152#define SPICKM_SHIFT 21
153#define TBSWAP_SHIFT 28
154
155#define RCKPOL_MASK BIT(0)
156#define TCKPOL_MASK BIT(0)
157#define SPICKM_MASK (BIT(1) | BIT(0))
158#define MSP_RX_CLKPOL_BIT(n) ((n & RCKPOL_MASK) << RCKPOL_SHIFT)
159#define MSP_TX_CLKPOL_BIT(n) ((n & TCKPOL_MASK) << TCKPOL_SHIFT)
160
161#define P1ELEN_SHIFT 0
162#define P1FLEN_SHIFT 3
163#define DTYP_SHIFT 10
164#define ENDN_SHIFT 12
165#define DDLY_SHIFT 13
166#define FSIG_SHIFT 15
167#define P2ELEN_SHIFT 16
168#define P2FLEN_SHIFT 19
169#define P2SM_SHIFT 26
170#define P2EN_SHIFT 27
171#define FSYNC_SHIFT 15
172
173#define P1ELEN_MASK 0x00000007
174#define P2ELEN_MASK 0x00070000
175#define P1FLEN_MASK 0x00000378
176#define P2FLEN_MASK 0x03780000
177#define DDLY_MASK 0x00003000
178#define DTYP_MASK 0x00000600
179#define P2SM_MASK 0x04000000
180#define P2EN_MASK 0x08000000
181#define ENDN_MASK 0x00001000
182#define TFSPOL_MASK 0x00000400
183#define TBSWAP_MASK 0x30000000
184#define COMPANDING_MODE_MASK 0x00000c00
185#define FSYNC_MASK 0x00008000
186
187#define MSP_P1_ELEM_LEN_BITS(n) (n & P1ELEN_MASK)
188#define MSP_P2_ELEM_LEN_BITS(n) (((n) << P2ELEN_SHIFT) & P2ELEN_MASK)
189#define MSP_P1_FRAME_LEN_BITS(n) (((n) << P1FLEN_SHIFT) & P1FLEN_MASK)
190#define MSP_P2_FRAME_LEN_BITS(n) (((n) << P2FLEN_SHIFT) & P2FLEN_MASK)
191#define MSP_DATA_DELAY_BITS(n) (((n) << DDLY_SHIFT) & DDLY_MASK)
192#define MSP_DATA_TYPE_BITS(n) (((n) << DTYP_SHIFT) & DTYP_MASK)
193#define MSP_P2_START_MODE_BIT(n) ((n << P2SM_SHIFT) & P2SM_MASK)
194#define MSP_P2_ENABLE_BIT(n) ((n << P2EN_SHIFT) & P2EN_MASK)
195#define MSP_SET_ENDIANNES_BIT(n) ((n << ENDN_SHIFT) & ENDN_MASK)
196#define MSP_FSYNC_POL(n) ((n << TFSPOL_SHIFT) & TFSPOL_MASK)
197#define MSP_DATA_WORD_SWAP(n) ((n << TBSWAP_SHIFT) & TBSWAP_MASK)
198#define MSP_SET_COMPANDING_MODE(n) ((n << DTYP_SHIFT) & \
199 COMPANDING_MODE_MASK)
200#define MSP_SET_FSYNC_IGNORE(n) ((n << FSYNC_SHIFT) & FSYNC_MASK)
201
202/* Flag register */
203#define RX_BUSY BIT(0)
204#define RX_FIFO_EMPTY BIT(1)
205#define RX_FIFO_FULL BIT(2)
206#define TX_BUSY BIT(3)
207#define TX_FIFO_EMPTY BIT(4)
208#define TX_FIFO_FULL BIT(5)
209
210#define RBUSY_SHIFT 0
211#define RFE_SHIFT 1
212#define RFU_SHIFT 2
213#define TBUSY_SHIFT 3
214#define TFE_SHIFT 4
215#define TFU_SHIFT 5
216
217/* Multichannel control register */
218#define RMCEN_SHIFT 0
219#define RMCSF_SHIFT 1
220#define RCMPM_SHIFT 3
221#define TMCEN_SHIFT 5
222#define TNCSF_SHIFT 6
223
224/* Sample rate generator register */
225#define SCKDIV_SHIFT 0
226#define FRWID_SHIFT 10
227#define FRPER_SHIFT 16
228
229#define SCK_DIV_MASK 0x0000003FF
230#define FRAME_WIDTH_BITS(n) (((n) << FRWID_SHIFT) & 0x0000FC00)
231#define FRAME_PERIOD_BITS(n) (((n) << FRPER_SHIFT) & 0x1FFF0000)
232
233/* DMA controller register */
234#define RX_DMA_ENABLE BIT(0)
235#define TX_DMA_ENABLE BIT(1)
236
237#define RDMAE_SHIFT 0
238#define TDMAE_SHIFT 1
239
240/* Interrupt Register */
241#define RX_SERVICE_INT BIT(0)
242#define RX_OVERRUN_ERROR_INT BIT(1)
243#define RX_FSYNC_ERR_INT BIT(2)
244#define RX_FSYNC_INT BIT(3)
245#define TX_SERVICE_INT BIT(4)
246#define TX_UNDERRUN_ERR_INT BIT(5)
247#define TX_FSYNC_ERR_INT BIT(6)
248#define TX_FSYNC_INT BIT(7)
249#define ALL_INT 0x000000ff
250
251/* MSP test control register */
252#define MSP_ITCR_ITEN BIT(0)
253#define MSP_ITCR_TESTFIFO BIT(1)
254
255#define RMCEN_BIT 0
256#define RMCSF_BIT 1
257#define RCMPM_BIT 3
258#define TMCEN_BIT 5
259#define TNCSF_BIT 6
260
261/* Single or dual phase mode */
262enum msp_phase_mode {
263 MSP_SINGLE_PHASE,
264 MSP_DUAL_PHASE
265};
266
267/* Frame length */
268enum msp_frame_length {
269 MSP_FRAME_LEN_1 = 0,
270 MSP_FRAME_LEN_2 = 1,
271 MSP_FRAME_LEN_4 = 3,
272 MSP_FRAME_LEN_8 = 7,
273 MSP_FRAME_LEN_12 = 11,
274 MSP_FRAME_LEN_16 = 15,
275 MSP_FRAME_LEN_20 = 19,
276 MSP_FRAME_LEN_32 = 31,
277 MSP_FRAME_LEN_48 = 47,
278 MSP_FRAME_LEN_64 = 63
279};
280
281/* Element length */
282enum msp_elem_length {
283 MSP_ELEM_LEN_8 = 0,
284 MSP_ELEM_LEN_10 = 1,
285 MSP_ELEM_LEN_12 = 2,
286 MSP_ELEM_LEN_14 = 3,
287 MSP_ELEM_LEN_16 = 4,
288 MSP_ELEM_LEN_20 = 5,
289 MSP_ELEM_LEN_24 = 6,
290 MSP_ELEM_LEN_32 = 7
291};
292
293enum msp_data_xfer_width {
294 MSP_DATA_TRANSFER_WIDTH_BYTE,
295 MSP_DATA_TRANSFER_WIDTH_HALFWORD,
296 MSP_DATA_TRANSFER_WIDTH_WORD
297};
298
299enum msp_frame_sync {
300 MSP_FSYNC_UNIGNORE = 0,
301 MSP_FSYNC_IGNORE = 1,
302};
303
304enum msp_phase2_start_mode {
305 MSP_PHASE2_START_MODE_IMEDIATE,
306 MSP_PHASE2_START_MODE_FSYNC
307};
308
309enum msp_btf {
310 MSP_BTF_MS_BIT_FIRST = 0,
311 MSP_BTF_LS_BIT_FIRST = 1
312};
313
314enum msp_fsync_pol {
315 MSP_FSYNC_POL_ACT_HI = 0,
316 MSP_FSYNC_POL_ACT_LO = 1
317};
318
319/* Data delay (in bit clock cycles) */
320enum msp_delay {
321 MSP_DELAY_0 = 0,
322 MSP_DELAY_1 = 1,
323 MSP_DELAY_2 = 2,
324 MSP_DELAY_3 = 3
325};
326
327/* Configurations of clocks (transmit, receive or sample rate generator) */
328enum msp_edge {
329 MSP_FALLING_EDGE = 0,
330 MSP_RISING_EDGE = 1,
331};
332
333enum msp_hws {
334 MSP_SWAP_NONE = 0,
335 MSP_SWAP_BYTE_PER_WORD = 1,
336 MSP_SWAP_BYTE_PER_HALF_WORD = 2,
337 MSP_SWAP_HALF_WORD_PER_WORD = 3
338};
339
340enum msp_compress_mode {
341 MSP_COMPRESS_MODE_LINEAR = 0,
342 MSP_COMPRESS_MODE_MU_LAW = 2,
343 MSP_COMPRESS_MODE_A_LAW = 3
344};
345
346enum msp_spi_burst_mode {
347 MSP_SPI_BURST_MODE_DISABLE = 0,
348 MSP_SPI_BURST_MODE_ENABLE = 1
349};
350
351enum msp_expand_mode {
352 MSP_EXPAND_MODE_LINEAR = 0,
353 MSP_EXPAND_MODE_LINEAR_SIGNED = 1,
354 MSP_EXPAND_MODE_MU_LAW = 2,
355 MSP_EXPAND_MODE_A_LAW = 3
356};
357
358#define MSP_FRAME_PERIOD_IN_MONO_MODE 256
359#define MSP_FRAME_PERIOD_IN_STEREO_MODE 32
360#define MSP_FRAME_WIDTH_IN_STEREO_MODE 16
361
362enum msp_protocol {
363 MSP_I2S_PROTOCOL,
364 MSP_PCM_PROTOCOL,
365 MSP_PCM_COMPAND_PROTOCOL,
366 MSP_INVALID_PROTOCOL
367};
368
369/*
370 * No of registers to backup during
371 * suspend resume
372 */
373#define MAX_MSP_BACKUP_REGS 36
374
375enum enum_i2s_controller {
376 MSP_0_I2S_CONTROLLER = 0,
377 MSP_1_I2S_CONTROLLER,
378 MSP_2_I2S_CONTROLLER,
379 MSP_3_I2S_CONTROLLER,
380};
381
382enum i2s_direction_t {
383 MSP_DIR_TX = 0x01,
384 MSP_DIR_RX = 0x02,
385};
386
387enum msp_data_size {
388 MSP_DATA_BITS_DEFAULT = -1,
389 MSP_DATA_BITS_8 = 0x00,
390 MSP_DATA_BITS_10,
391 MSP_DATA_BITS_12,
392 MSP_DATA_BITS_14,
393 MSP_DATA_BITS_16,
394 MSP_DATA_BITS_20,
395 MSP_DATA_BITS_24,
396 MSP_DATA_BITS_32,
397};
398
399enum msp_state {
400 MSP_STATE_IDLE = 0,
401 MSP_STATE_CONFIGURED = 1,
402 MSP_STATE_RUNNING = 2,
403};
404
405enum msp_rx_comparison_enable_mode {
406 MSP_COMPARISON_DISABLED = 0,
407 MSP_COMPARISON_NONEQUAL_ENABLED = 2,
408 MSP_COMPARISON_EQUAL_ENABLED = 3
409};
410
411struct msp_multichannel_config {
412 bool rx_multichannel_enable;
413 bool tx_multichannel_enable;
414 enum msp_rx_comparison_enable_mode rx_comparison_enable_mode;
415 u8 padding;
416 u32 comparison_value;
417 u32 comparison_mask;
418 u32 rx_channel_0_enable;
419 u32 rx_channel_1_enable;
420 u32 rx_channel_2_enable;
421 u32 rx_channel_3_enable;
422 u32 tx_channel_0_enable;
423 u32 tx_channel_1_enable;
424 u32 tx_channel_2_enable;
425 u32 tx_channel_3_enable;
426};
427
428struct msp_protdesc {
429 u32 rx_phase_mode;
430 u32 tx_phase_mode;
431 u32 rx_phase2_start_mode;
432 u32 tx_phase2_start_mode;
433 u32 rx_byte_order;
434 u32 tx_byte_order;
435 u32 rx_frame_len_1;
436 u32 rx_frame_len_2;
437 u32 tx_frame_len_1;
438 u32 tx_frame_len_2;
439 u32 rx_elem_len_1;
440 u32 rx_elem_len_2;
441 u32 tx_elem_len_1;
442 u32 tx_elem_len_2;
443 u32 rx_data_delay;
444 u32 tx_data_delay;
445 u32 rx_clk_pol;
446 u32 tx_clk_pol;
447 u32 rx_fsync_pol;
448 u32 tx_fsync_pol;
449 u32 rx_half_word_swap;
450 u32 tx_half_word_swap;
451 u32 compression_mode;
452 u32 expansion_mode;
453 u32 frame_sync_ignore;
454 u32 frame_period;
455 u32 frame_width;
456 u32 clocks_per_frame;
457};
458
459struct i2s_message {
460 enum i2s_direction_t i2s_direction;
461 void *txdata;
462 void *rxdata;
463 size_t txbytes;
464 size_t rxbytes;
465 int dma_flag;
466 int tx_offset;
467 int rx_offset;
468 bool cyclic_dma;
469 dma_addr_t buf_addr;
470 size_t buf_len;
471 size_t period_len;
472};
473
474struct i2s_controller {
475 struct module *owner;
476 unsigned int id;
477 unsigned int class;
478 const struct i2s_algorithm *algo; /* the algorithm to access the bus */
479 void *data;
480 struct mutex bus_lock;
481 struct device dev; /* the controller device */
482 char name[48];
483};
484
485struct ux500_msp_config {
486 unsigned int f_inputclk;
487 unsigned int rx_clk_sel;
488 unsigned int tx_clk_sel;
489 unsigned int srg_clk_sel;
490 unsigned int rx_fsync_pol;
491 unsigned int tx_fsync_pol;
492 unsigned int rx_fsync_sel;
493 unsigned int tx_fsync_sel;
494 unsigned int rx_fifo_config;
495 unsigned int tx_fifo_config;
496 unsigned int spi_clk_mode;
497 unsigned int spi_burst_mode;
498 unsigned int loopback_enable;
499 unsigned int tx_data_enable;
500 unsigned int default_protdesc;
501 struct msp_protdesc protdesc;
502 int multichannel_configured;
503 struct msp_multichannel_config multichannel_config;
504 unsigned int direction;
505 unsigned int protocol;
506 unsigned int frame_freq;
507 unsigned int frame_size;
508 enum msp_data_size data_size;
509 unsigned int def_elem_len;
510 unsigned int iodelay;
511 void (*handler) (void *data);
512 void *tx_callback_data;
513 void *rx_callback_data;
514};
515
516struct ux500_msp {
517 enum enum_i2s_controller id;
518 void __iomem *registers;
519 struct device *dev;
520 struct i2s_controller *i2s_cont;
521 struct stedma40_chan_cfg *dma_cfg_rx;
522 struct stedma40_chan_cfg *dma_cfg_tx;
523 struct dma_chan *tx_pipeid;
524 struct dma_chan *rx_pipeid;
525 enum msp_state msp_state;
526 int (*transfer) (struct ux500_msp *msp, struct i2s_message *message);
527 int (*plat_init) (void);
528 int (*plat_exit) (void);
529 struct timer_list notify_timer;
530 int def_elem_len;
531 unsigned int dir_busy;
532 int loopback_enable;
533 u32 backup_regs[MAX_MSP_BACKUP_REGS];
534 unsigned int f_bitclk;
535};
536
537struct ux500_msp_dma_params {
538 unsigned int data_size;
539 struct stedma40_chan_cfg *dma_cfg;
540};
541
542int ux500_msp_i2s_init_msp(struct platform_device *pdev,
543 struct ux500_msp **msp_p,
544 struct msp_i2s_platform_data *platform_data);
545void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
546 struct ux500_msp *msp);
547int ux500_msp_i2s_open(struct ux500_msp *msp, struct ux500_msp_config *config);
548int ux500_msp_i2s_close(struct ux500_msp *msp,
549 unsigned int dir);
550int ux500_msp_i2s_trigger(struct ux500_msp *msp, int cmd,
551 int direction);
552
553#endif