]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/ux500/ux500_msp_dai.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[karo-tx-linux.git] / sound / soc / ux500 / ux500_msp_dai.c
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/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
32 static 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
65 static 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
129 static 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
173 static 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
229 static 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
267 static 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
302 static 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
384 static 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
408 static 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
442 static 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
479 static 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
521 static 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
562 static 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
603 static 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
625 static 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
640 static 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
656 static 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
669 static 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
752 static 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
808 err_init_msp:
809         clk_put(drvdata->clk);
810
811 err_clk:
812         devm_regulator_put(drvdata->reg_vape);
813
814         return ret;
815 }
816
817 static 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
833 static 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 };
841 module_platform_driver(msp_i2s_driver);
842
843 MODULE_LICENSE("GPL v2");