Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ux500_msp_dai.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) ST-Ericsson SA 2012
3  *
4  * Author: Ola Lilja <[email protected]>,
5  * Roger Nilsson <[email protected]>
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>
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 {
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;
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 =
76  break;
77 
78  case 16000:
79  prot_desc->frame_period =
81  break;
82 
83  case 44100:
84  prot_desc->frame_period =
86  break;
87 
88  case 48000:
89  prot_desc->frame_period =
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 
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) {
179  break;
180 
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) {
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 
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;
237  prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
238  prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
241 
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;
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;
273  prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
274  prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
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;
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 ?
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 &
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 
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 
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:
494  1, 2);
495  break;
496 
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 
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 |
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) {
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) {
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 {
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  if (!drvdata)
764  return -ENOMEM;
765 
766  drvdata->fmt = 0;
767  drvdata->slots = 1;
768  drvdata->tx_mask = 0x01;
769  drvdata->rx_mask = 0x01;
770  drvdata->slot_width = 16;
771  drvdata->master_clk = MSP_INPUT_FREQ_APB;
772 
773  drvdata->reg_vape = devm_regulator_get(&pdev->dev, "v-ape");
774  if (IS_ERR(drvdata->reg_vape)) {
775  ret = (int)PTR_ERR(drvdata->reg_vape);
776  dev_err(&pdev->dev,
777  "%s: ERROR: Failed to get Vape supply (%d)!\n",
778  __func__, ret);
779  return ret;
780  }
781  prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, (char *)pdev->name, 50);
782 
783  drvdata->clk = clk_get(&pdev->dev, NULL);
784  if (IS_ERR(drvdata->clk)) {
785  ret = (int)PTR_ERR(drvdata->clk);
786  dev_err(&pdev->dev, "%s: ERROR: clk_get failed (%d)!\n",
787  __func__, ret);
788  goto err_clk;
789  }
790 
791  ret = ux500_msp_i2s_init_msp(pdev, &drvdata->msp,
792  pdev->dev.platform_data);
793  if (!drvdata->msp) {
794  dev_err(&pdev->dev,
795  "%s: ERROR: Failed to init MSP-struct (%d)!",
796  __func__, ret);
797  goto err_init_msp;
798  }
799  dev_set_drvdata(&pdev->dev, drvdata);
800 
801  ret = snd_soc_register_dai(&pdev->dev,
802  &ux500_msp_dai_drv[drvdata->msp->id]);
803  if (ret < 0) {
804  dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
805  __func__, drvdata->msp->id);
806  goto err_init_msp;
807  }
808 
809  return 0;
810 
811 err_init_msp:
812  clk_put(drvdata->clk);
813 
814 err_clk:
815  devm_regulator_put(drvdata->reg_vape);
816 
817  return ret;
818 }
819 
820 static int __devexit ux500_msp_drv_remove(struct platform_device *pdev)
821 {
822  struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(&pdev->dev);
823 
824  snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(ux500_msp_dai_drv));
825 
826  devm_regulator_put(drvdata->reg_vape);
827  prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, "ux500_msp_i2s");
828 
829  clk_put(drvdata->clk);
830 
831  ux500_msp_i2s_cleanup_msp(pdev, drvdata->msp);
832 
833  return 0;
834 }
835 
836 static const struct of_device_id ux500_msp_i2s_match[] = {
837  { .compatible = "stericsson,ux500-msp-i2s", },
838  {},
839 };
840 
841 static struct platform_driver msp_i2s_driver = {
842  .driver = {
843  .name = "ux500-msp-i2s",
844  .owner = THIS_MODULE,
845  .of_match_table = ux500_msp_i2s_match,
846  },
847  .probe = ux500_msp_drv_probe,
848  .remove = ux500_msp_drv_remove,
849 };
850 module_platform_driver(msp_i2s_driver);
851 
852 MODULE_LICENSE("GPL v2");