1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (C) ST-Ericsson SA 2012
4 *
5 * Author: Ola Lilja <ola.o.lilja@stericsson.com>,
6 * Roger Nilsson <roger.xr.nilsson@stericsson.com>
7 * for ST-Ericsson.
8 */
9
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/bitops.h>
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <linux/of.h>
16#include <linux/regulator/consumer.h>
17#include <linux/mfd/dbx500-prcmu.h>
18
19#include <sound/soc.h>
20#include <sound/soc-dai.h>
21#include <sound/dmaengine_pcm.h>
22
23#include "ux500_msp_i2s.h"
24#include "ux500_msp_dai.h"
25#include "ux500_pcm.h"
26
27static int setup_pcm_multichan(struct snd_soc_dai *dai,
28 struct ux500_msp_config *msp_config)
29{
30 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
31 struct msp_multichannel_config *multi =
32 &msp_config->multichannel_config;
33
34 if (drvdata->slots > 1) {
35 msp_config->multichannel_configured = 1;
36
37 multi->tx_multichannel_enable = true;
38 multi->rx_multichannel_enable = true;
39 multi->rx_comparison_enable_mode = MSP_COMPARISON_DISABLED;
40
41 multi->tx_channel_0_enable = drvdata->tx_mask;
42 multi->tx_channel_1_enable = 0;
43 multi->tx_channel_2_enable = 0;
44 multi->tx_channel_3_enable = 0;
45
46 multi->rx_channel_0_enable = drvdata->rx_mask;
47 multi->rx_channel_1_enable = 0;
48 multi->rx_channel_2_enable = 0;
49 multi->rx_channel_3_enable = 0;
50
51 dev_dbg(dai->dev,
52 "%s: Multichannel enabled. Slots: %d, TX: %u, RX: %u\n",
53 __func__, drvdata->slots, multi->tx_channel_0_enable,
54 multi->rx_channel_0_enable);
55 }
56
57 return 0;
58}
59
60static int setup_frameper(struct snd_soc_dai *dai, unsigned int rate,
61 struct msp_protdesc *prot_desc)
62{
63 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
64
65 switch (drvdata->slots) {
66 case 1:
67 switch (rate) {
68 case 8000:
69 prot_desc->frame_period =
70 FRAME_PER_SINGLE_SLOT_8_KHZ;
71 break;
72
73 case 16000:
74 prot_desc->frame_period =
75 FRAME_PER_SINGLE_SLOT_16_KHZ;
76 break;
77
78 case 44100:
79 prot_desc->frame_period =
80 FRAME_PER_SINGLE_SLOT_44_1_KHZ;
81 break;
82
83 case 48000:
84 prot_desc->frame_period =
85 FRAME_PER_SINGLE_SLOT_48_KHZ;
86 break;
87
88 default:
89 dev_err(dai->dev,
90 "%s: Error: Unsupported sample-rate (freq = %d)!\n",
91 __func__, rate);
92 return -EINVAL;
93 }
94 break;
95
96 case 2:
97 prot_desc->frame_period = FRAME_PER_2_SLOTS;
98 break;
99
100 case 8:
101 prot_desc->frame_period = FRAME_PER_8_SLOTS;
102 break;
103
104 case 16:
105 prot_desc->frame_period = FRAME_PER_16_SLOTS;
106 break;
107 default:
108 dev_err(dai->dev,
109 "%s: Error: Unsupported slot-count (slots = %d)!\n",
110 __func__, drvdata->slots);
111 return -EINVAL;
112 }
113
114 prot_desc->clocks_per_frame =
115 prot_desc->frame_period+1;
116
117 dev_dbg(dai->dev, "%s: Clocks per frame: %u\n",
118 __func__,
119 prot_desc->clocks_per_frame);
120
121 return 0;
122}
123
124static int setup_pcm_framing(struct snd_soc_dai *dai, unsigned int rate,
125 struct msp_protdesc *prot_desc)
126{
127 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
128
129 u32 frame_length = MSP_FRAME_LEN_1;
130
131 prot_desc->frame_width = 0;
132
133 switch (drvdata->slots) {
134 case 1:
135 frame_length = MSP_FRAME_LEN_1;
136 break;
137
138 case 2:
139 frame_length = MSP_FRAME_LEN_2;
140 break;
141
142 case 8:
143 frame_length = MSP_FRAME_LEN_8;
144 break;
145
146 case 16:
147 frame_length = MSP_FRAME_LEN_16;
148 break;
149 default:
150 dev_err(dai->dev,
151 "%s: Error: Unsupported slot-count (slots = %d)!\n",
152 __func__, drvdata->slots);
153 return -EINVAL;
154 }
155
156 prot_desc->tx_frame_len_1 = frame_length;
157 prot_desc->rx_frame_len_1 = frame_length;
158 prot_desc->tx_frame_len_2 = frame_length;
159 prot_desc->rx_frame_len_2 = frame_length;
160
161 prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
162 prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
163 prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
164 prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
165
166 return setup_frameper(dai, rate, prot_desc);
167}
168
169static int setup_clocking(struct snd_soc_dai *dai,
170 unsigned int fmt,
171 struct ux500_msp_config *msp_config)
172{
173 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
174 case SND_SOC_DAIFMT_NB_NF:
175 break;
176
177 case SND_SOC_DAIFMT_NB_IF:
178 msp_config->tx_fsync_pol ^= 1 << TFSPOL_SHIFT;
179 msp_config->rx_fsync_pol ^= 1 << RFSPOL_SHIFT;
180
181 break;
182
183 default:
184 dev_err(dai->dev,
185 "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
186 __func__, fmt);
187
188 return -EINVAL;
189 }
190
191 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
192 case SND_SOC_DAIFMT_BC_FC:
193 dev_dbg(dai->dev, "%s: Codec is master.\n", __func__);
194
195 msp_config->iodelay = 0x20;
196 msp_config->rx_fsync_sel = 0;
197 msp_config->tx_fsync_sel = 1 << TFSSEL_SHIFT;
198 msp_config->tx_clk_sel = 0;
199 msp_config->rx_clk_sel = 0;
200 msp_config->srg_clk_sel = 0x2 << SCKSEL_SHIFT;
201
202 break;
203
204 case SND_SOC_DAIFMT_BP_FP:
205 dev_dbg(dai->dev, "%s: Codec is slave.\n", __func__);
206
207 msp_config->tx_clk_sel = TX_CLK_SEL_SRG;
208 msp_config->tx_fsync_sel = TX_SYNC_SRG_PROG;
209 msp_config->rx_clk_sel = RX_CLK_SEL_SRG;
210 msp_config->rx_fsync_sel = RX_SYNC_SRG;
211 msp_config->srg_clk_sel = 1 << SCKSEL_SHIFT;
212
213 break;
214
215 default:
216 dev_err(dai->dev, "%s: Error: Unsupported master (fmt = 0x%x)!\n",
217 __func__, fmt);
218
219 return -EINVAL;
220 }
221
222 return 0;
223}
224
225static int setup_pcm_protdesc(struct snd_soc_dai *dai,
226 unsigned int fmt,
227 struct msp_protdesc *prot_desc)
228{
229 prot_desc->rx_phase_mode = MSP_SINGLE_PHASE;
230 prot_desc->tx_phase_mode = MSP_SINGLE_PHASE;
231 prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
232 prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_IMEDIATE;
233 prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
234 prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
235 prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_HI);
236 prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_HI << RFSPOL_SHIFT;
237
238 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_DSP_A) {
239 dev_dbg(dai->dev, "%s: DSP_A.\n", __func__);
240 prot_desc->rx_clk_pol = MSP_RISING_EDGE;
241 prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
242
243 prot_desc->rx_data_delay = MSP_DELAY_1;
244 prot_desc->tx_data_delay = MSP_DELAY_1;
245 } else {
246 dev_dbg(dai->dev, "%s: DSP_B.\n", __func__);
247 prot_desc->rx_clk_pol = MSP_FALLING_EDGE;
248 prot_desc->tx_clk_pol = MSP_RISING_EDGE;
249
250 prot_desc->rx_data_delay = MSP_DELAY_0;
251 prot_desc->tx_data_delay = MSP_DELAY_0;
252 }
253
254 prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
255 prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
256 prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
257 prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
258 prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
259
260 return 0;
261}
262
263static int setup_i2s_protdesc(struct msp_protdesc *prot_desc)
264{
265 prot_desc->rx_phase_mode = MSP_DUAL_PHASE;
266 prot_desc->tx_phase_mode = MSP_DUAL_PHASE;
267 prot_desc->rx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
268 prot_desc->tx_phase2_start_mode = MSP_PHASE2_START_MODE_FSYNC;
269 prot_desc->rx_byte_order = MSP_BTF_MS_BIT_FIRST;
270 prot_desc->tx_byte_order = MSP_BTF_MS_BIT_FIRST;
271 prot_desc->tx_fsync_pol = MSP_FSYNC_POL(MSP_FSYNC_POL_ACT_LO);
272 prot_desc->rx_fsync_pol = MSP_FSYNC_POL_ACT_LO << RFSPOL_SHIFT;
273
274 prot_desc->rx_frame_len_1 = MSP_FRAME_LEN_1;
275 prot_desc->rx_frame_len_2 = MSP_FRAME_LEN_1;
276 prot_desc->tx_frame_len_1 = MSP_FRAME_LEN_1;
277 prot_desc->tx_frame_len_2 = MSP_FRAME_LEN_1;
278 prot_desc->rx_elem_len_1 = MSP_ELEM_LEN_16;
279 prot_desc->rx_elem_len_2 = MSP_ELEM_LEN_16;
280 prot_desc->tx_elem_len_1 = MSP_ELEM_LEN_16;
281 prot_desc->tx_elem_len_2 = MSP_ELEM_LEN_16;
282
283 prot_desc->rx_clk_pol = MSP_RISING_EDGE;
284 prot_desc->tx_clk_pol = MSP_FALLING_EDGE;
285
286 prot_desc->rx_data_delay = MSP_DELAY_0;
287 prot_desc->tx_data_delay = MSP_DELAY_0;
288
289 prot_desc->tx_half_word_swap = MSP_SWAP_NONE;
290 prot_desc->rx_half_word_swap = MSP_SWAP_NONE;
291 prot_desc->compression_mode = MSP_COMPRESS_MODE_LINEAR;
292 prot_desc->expansion_mode = MSP_EXPAND_MODE_LINEAR;
293 prot_desc->frame_sync_ignore = MSP_FSYNC_IGNORE;
294
295 return 0;
296}
297
298static int setup_msp_config(struct snd_pcm_substream *substream,
299 struct snd_soc_dai *dai,
300 struct ux500_msp_config *msp_config)
301{
302 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
303 struct msp_protdesc *prot_desc = &msp_config->protdesc;
304 struct snd_pcm_runtime *runtime = substream->runtime;
305 unsigned int fmt = drvdata->fmt;
306 int ret;
307
308 memset(msp_config, 0, sizeof(*msp_config));
309
310 msp_config->f_inputclk = drvdata->master_clk;
311
312 msp_config->tx_fifo_config = TX_FIFO_ENABLE;
313 msp_config->rx_fifo_config = RX_FIFO_ENABLE;
314 msp_config->def_elem_len = 1;
315 msp_config->direction = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
316 MSP_DIR_TX : MSP_DIR_RX;
317 msp_config->data_size = MSP_DATA_BITS_32;
318 msp_config->frame_freq = runtime->rate;
319
320 dev_dbg(dai->dev, "%s: f_inputclk = %u, frame_freq = %u.\n",
321 __func__, msp_config->f_inputclk, msp_config->frame_freq);
322 /* To avoid division by zero */
323 prot_desc->clocks_per_frame = 1;
324
325 dev_dbg(dai->dev, "%s: rate: %u, channels: %d.\n", __func__,
326 runtime->rate, runtime->channels);
327 switch (fmt &
328 (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) {
329 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP:
330 dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
331
332 msp_config->default_protdesc = 1;
333 msp_config->protocol = MSP_I2S_PROTOCOL;
334 break;
335
336 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC:
337 dev_dbg(dai->dev, "%s: SND_SOC_DAIFMT_I2S.\n", __func__);
338
339 msp_config->data_size = MSP_DATA_BITS_16;
340 msp_config->protocol = MSP_I2S_PROTOCOL;
341
342 ret = setup_i2s_protdesc(prot_desc);
343 if (ret < 0)
344 return ret;
345
346 break;
347
348 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP:
349 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC:
350 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP:
351 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC:
352 dev_dbg(dai->dev, "%s: PCM format.\n", __func__);
353
354 msp_config->data_size = MSP_DATA_BITS_16;
355 msp_config->protocol = MSP_PCM_PROTOCOL;
356
357 ret = setup_pcm_protdesc(dai, fmt, prot_desc);
358 if (ret < 0)
359 return ret;
360
361 ret = setup_pcm_multichan(dai, msp_config);
362 if (ret < 0)
363 return ret;
364
365 ret = setup_pcm_framing(dai, rate: runtime->rate, prot_desc);
366 if (ret < 0)
367 return ret;
368
369 break;
370
371 default:
372 dev_err(dai->dev, "%s: Error: Unsupported format (%d)!\n",
373 __func__, fmt);
374 return -EINVAL;
375 }
376
377 return setup_clocking(dai, fmt, msp_config);
378}
379
380static int ux500_msp_dai_startup(struct snd_pcm_substream *substream,
381 struct snd_soc_dai *dai)
382{
383 int ret = 0;
384 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
385
386 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
387 snd_pcm_stream_str(substream));
388
389 /* Enable regulator */
390 ret = regulator_enable(regulator: drvdata->reg_vape);
391 if (ret != 0) {
392 dev_err(drvdata->msp->dev,
393 "%s: Failed to enable regulator!\n", __func__);
394 return ret;
395 }
396
397 /* Prepare and enable clocks */
398 dev_dbg(dai->dev, "%s: Enabling MSP-clocks.\n", __func__);
399 ret = clk_prepare_enable(clk: drvdata->pclk);
400 if (ret) {
401 dev_err(drvdata->msp->dev,
402 "%s: Failed to prepare/enable pclk!\n", __func__);
403 goto err_pclk;
404 }
405
406 ret = clk_prepare_enable(clk: drvdata->clk);
407 if (ret) {
408 dev_err(drvdata->msp->dev,
409 "%s: Failed to prepare/enable clk!\n", __func__);
410 goto err_clk;
411 }
412
413 return ret;
414err_clk:
415 clk_disable_unprepare(clk: drvdata->pclk);
416err_pclk:
417 regulator_disable(regulator: drvdata->reg_vape);
418 return ret;
419}
420
421static void ux500_msp_dai_shutdown(struct snd_pcm_substream *substream,
422 struct snd_soc_dai *dai)
423{
424 int ret;
425 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
426 bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
427
428 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n", __func__, dai->id,
429 snd_pcm_stream_str(substream));
430
431 if (drvdata->vape_opp_constraint == 1) {
432 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
433 name: "ux500_msp_i2s", new_value: 50);
434 drvdata->vape_opp_constraint = 0;
435 }
436
437 if (ux500_msp_i2s_close(msp: drvdata->msp,
438 dir: is_playback ? MSP_DIR_TX : MSP_DIR_RX)) {
439 dev_err(dai->dev,
440 "%s: Error: MSP %d (%s): Unable to close i2s.\n",
441 __func__, dai->id, snd_pcm_stream_str(substream));
442 }
443
444 /* Disable and unprepare clocks */
445 clk_disable_unprepare(clk: drvdata->clk);
446 clk_disable_unprepare(clk: drvdata->pclk);
447
448 /* Disable regulator */
449 ret = regulator_disable(regulator: drvdata->reg_vape);
450 if (ret < 0)
451 dev_err(dai->dev,
452 "%s: ERROR: Failed to disable regulator (%d)!\n",
453 __func__, ret);
454}
455
456static int ux500_msp_dai_prepare(struct snd_pcm_substream *substream,
457 struct snd_soc_dai *dai)
458{
459 int ret = 0;
460 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
461 struct snd_pcm_runtime *runtime = substream->runtime;
462 struct ux500_msp_config msp_config;
463
464 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (rate = %d).\n", __func__,
465 dai->id, snd_pcm_stream_str(substream), runtime->rate);
466
467 setup_msp_config(substream, dai, msp_config: &msp_config);
468
469 ret = ux500_msp_i2s_open(msp: drvdata->msp, config: &msp_config);
470 if (ret < 0) {
471 dev_err(dai->dev, "%s: Error: msp_setup failed (ret = %d)!\n",
472 __func__, ret);
473 return ret;
474 }
475
476 /* Set OPP-level */
477 if ((drvdata->fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) &&
478 (drvdata->msp->f_bitclk > 19200000)) {
479 /* If the bit-clock is higher than 19.2MHz, Vape should be
480 * run in 100% OPP. Only when bit-clock is used (MSP master)
481 */
482 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
483 name: "ux500-msp-i2s", new_value: 100);
484 drvdata->vape_opp_constraint = 1;
485 } else {
486 prcmu_qos_update_requirement(PRCMU_QOS_APE_OPP,
487 name: "ux500-msp-i2s", new_value: 50);
488 drvdata->vape_opp_constraint = 0;
489 }
490
491 return ret;
492}
493
494static int ux500_msp_dai_hw_params(struct snd_pcm_substream *substream,
495 struct snd_pcm_hw_params *params,
496 struct snd_soc_dai *dai)
497{
498 unsigned int mask, slots_active;
499 struct snd_pcm_runtime *runtime = substream->runtime;
500 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
501
502 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter.\n",
503 __func__, dai->id, snd_pcm_stream_str(substream));
504
505 switch (drvdata->fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
506 case SND_SOC_DAIFMT_I2S:
507 snd_pcm_hw_constraint_minmax(runtime,
508 SNDRV_PCM_HW_PARAM_CHANNELS,
509 min: 1, max: 2);
510 break;
511
512 case SND_SOC_DAIFMT_DSP_B:
513 case SND_SOC_DAIFMT_DSP_A:
514 mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
515 drvdata->tx_mask :
516 drvdata->rx_mask;
517
518 slots_active = hweight32(mask);
519 dev_dbg(dai->dev, "TDM-slots active: %d", slots_active);
520
521 snd_pcm_hw_constraint_single(runtime,
522 SNDRV_PCM_HW_PARAM_CHANNELS,
523 val: slots_active);
524 break;
525
526 default:
527 dev_err(dai->dev,
528 "%s: Error: Unsupported protocol (fmt = 0x%x)!\n",
529 __func__, drvdata->fmt);
530 return -EINVAL;
531 }
532
533 return 0;
534}
535
536static int ux500_msp_dai_set_dai_fmt(struct snd_soc_dai *dai,
537 unsigned int fmt)
538{
539 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
540
541 dev_dbg(dai->dev, "%s: MSP %d: Enter.\n", __func__, dai->id);
542
543 switch (fmt & (SND_SOC_DAIFMT_FORMAT_MASK |
544 SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK)) {
545 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BP_FP:
546 case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_BC_FC:
547 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BP_FP:
548 case SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_BC_FC:
549 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BP_FP:
550 case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_BC_FC:
551 break;
552
553 default:
554 dev_err(dai->dev,
555 "%s: Error: Unsupported protocol/master (fmt = 0x%x)!\n",
556 __func__, drvdata->fmt);
557 return -EINVAL;
558 }
559
560 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
561 case SND_SOC_DAIFMT_NB_NF:
562 case SND_SOC_DAIFMT_NB_IF:
563 case SND_SOC_DAIFMT_IB_IF:
564 break;
565
566 default:
567 dev_err(dai->dev,
568 "%s: Error: Unsupported inversion (fmt = 0x%x)!\n",
569 __func__, drvdata->fmt);
570 return -EINVAL;
571 }
572
573 drvdata->fmt = fmt;
574 return 0;
575}
576
577static int ux500_msp_dai_set_tdm_slot(struct snd_soc_dai *dai,
578 unsigned int tx_mask,
579 unsigned int rx_mask,
580 int slots, int slot_width)
581{
582 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
583 unsigned int cap;
584
585 switch (slots) {
586 case 1:
587 cap = 0x01;
588 break;
589 case 2:
590 cap = 0x03;
591 break;
592 case 8:
593 cap = 0xFF;
594 break;
595 case 16:
596 cap = 0xFFFF;
597 break;
598 default:
599 dev_err(dai->dev, "%s: Error: Unsupported slot-count (%d)!\n",
600 __func__, slots);
601 return -EINVAL;
602 }
603 drvdata->slots = slots;
604
605 if (!(slot_width == 16)) {
606 dev_err(dai->dev, "%s: Error: Unsupported slot-width (%d)!\n",
607 __func__, slot_width);
608 return -EINVAL;
609 }
610 drvdata->slot_width = slot_width;
611
612 drvdata->tx_mask = tx_mask & cap;
613 drvdata->rx_mask = rx_mask & cap;
614
615 return 0;
616}
617
618static int ux500_msp_dai_set_dai_sysclk(struct snd_soc_dai *dai,
619 int clk_id, unsigned int freq, int dir)
620{
621 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
622
623 dev_dbg(dai->dev, "%s: MSP %d: Enter. clk-id: %d, freq: %u.\n",
624 __func__, dai->id, clk_id, freq);
625
626 switch (clk_id) {
627 case UX500_MSP_MASTER_CLOCK:
628 drvdata->master_clk = freq;
629 break;
630
631 default:
632 dev_err(dai->dev, "%s: MSP %d: Invalid clk-id (%d)!\n",
633 __func__, dai->id, clk_id);
634 return -EINVAL;
635 }
636
637 return 0;
638}
639
640static int ux500_msp_dai_trigger(struct snd_pcm_substream *substream,
641 int cmd, struct snd_soc_dai *dai)
642{
643 int ret = 0;
644 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
645
646 dev_dbg(dai->dev, "%s: MSP %d (%s): Enter (msp->id = %d, cmd = %d).\n",
647 __func__, dai->id, snd_pcm_stream_str(substream),
648 (int)drvdata->msp->id, cmd);
649
650 ret = ux500_msp_i2s_trigger(msp: drvdata->msp, cmd, direction: substream->stream);
651
652 return ret;
653}
654
655static int ux500_msp_dai_of_probe(struct snd_soc_dai *dai)
656{
657 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: dai->dev);
658 struct snd_dmaengine_dai_dma_data *playback_dma_data;
659 struct snd_dmaengine_dai_dma_data *capture_dma_data;
660
661 playback_dma_data = devm_kzalloc(dev: dai->dev,
662 size: sizeof(*playback_dma_data),
663 GFP_KERNEL);
664 if (!playback_dma_data)
665 return -ENOMEM;
666
667 capture_dma_data = devm_kzalloc(dev: dai->dev,
668 size: sizeof(*capture_dma_data),
669 GFP_KERNEL);
670 if (!capture_dma_data)
671 return -ENOMEM;
672
673 playback_dma_data->addr = drvdata->msp->tx_rx_addr;
674 capture_dma_data->addr = drvdata->msp->tx_rx_addr;
675
676 playback_dma_data->maxburst = 4;
677 capture_dma_data->maxburst = 4;
678
679 snd_soc_dai_init_dma_data(dai, playback: playback_dma_data, capture: capture_dma_data);
680
681 return 0;
682}
683
684static const struct snd_soc_dai_ops ux500_msp_dai_ops[] = {
685 {
686 .probe = ux500_msp_dai_of_probe,
687 .set_sysclk = ux500_msp_dai_set_dai_sysclk,
688 .set_fmt = ux500_msp_dai_set_dai_fmt,
689 .set_tdm_slot = ux500_msp_dai_set_tdm_slot,
690 .startup = ux500_msp_dai_startup,
691 .shutdown = ux500_msp_dai_shutdown,
692 .prepare = ux500_msp_dai_prepare,
693 .trigger = ux500_msp_dai_trigger,
694 .hw_params = ux500_msp_dai_hw_params,
695 }
696};
697
698static struct snd_soc_dai_driver ux500_msp_dai_drv = {
699 .playback.channels_min = UX500_MSP_MIN_CHANNELS,
700 .playback.channels_max = UX500_MSP_MAX_CHANNELS,
701 .playback.rates = UX500_I2S_RATES,
702 .playback.formats = UX500_I2S_FORMATS,
703 .capture.channels_min = UX500_MSP_MIN_CHANNELS,
704 .capture.channels_max = UX500_MSP_MAX_CHANNELS,
705 .capture.rates = UX500_I2S_RATES,
706 .capture.formats = UX500_I2S_FORMATS,
707 .ops = ux500_msp_dai_ops,
708};
709
710static const struct snd_soc_component_driver ux500_msp_component = {
711 .name = "ux500-msp",
712 .legacy_dai_naming = 1,
713};
714
715
716static int ux500_msp_drv_probe(struct platform_device *pdev)
717{
718 struct ux500_msp_i2s_drvdata *drvdata;
719 int ret = 0;
720
721 drvdata = devm_kzalloc(dev: &pdev->dev,
722 size: sizeof(struct ux500_msp_i2s_drvdata),
723 GFP_KERNEL);
724 if (!drvdata)
725 return -ENOMEM;
726
727 drvdata->fmt = 0;
728 drvdata->slots = 1;
729 drvdata->tx_mask = 0x01;
730 drvdata->rx_mask = 0x01;
731 drvdata->slot_width = 16;
732 drvdata->master_clk = MSP_INPUT_FREQ_APB;
733
734 drvdata->reg_vape = devm_regulator_get(dev: &pdev->dev, id: "v-ape");
735 if (IS_ERR(ptr: drvdata->reg_vape)) {
736 ret = (int)PTR_ERR(ptr: drvdata->reg_vape);
737 dev_err(&pdev->dev,
738 "%s: ERROR: Failed to get Vape supply (%d)!\n",
739 __func__, ret);
740 return ret;
741 }
742 prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, name: (char *)pdev->name, value: 50);
743
744 drvdata->pclk = devm_clk_get(dev: &pdev->dev, id: "apb_pclk");
745 if (IS_ERR(ptr: drvdata->pclk)) {
746 ret = (int)PTR_ERR(ptr: drvdata->pclk);
747 dev_err(&pdev->dev,
748 "%s: ERROR: devm_clk_get of pclk failed (%d)!\n",
749 __func__, ret);
750 return ret;
751 }
752
753 drvdata->clk = devm_clk_get(dev: &pdev->dev, NULL);
754 if (IS_ERR(ptr: drvdata->clk)) {
755 ret = (int)PTR_ERR(ptr: drvdata->clk);
756 dev_err(&pdev->dev,
757 "%s: ERROR: devm_clk_get failed (%d)!\n",
758 __func__, ret);
759 return ret;
760 }
761
762 ret = ux500_msp_i2s_init_msp(pdev, msp_p: &drvdata->msp);
763 if (!drvdata->msp) {
764 dev_err(&pdev->dev,
765 "%s: ERROR: Failed to init MSP-struct (%d)!",
766 __func__, ret);
767 return ret;
768 }
769 dev_set_drvdata(dev: &pdev->dev, data: drvdata);
770
771 ret = snd_soc_register_component(dev: &pdev->dev, component_driver: &ux500_msp_component,
772 dai_drv: &ux500_msp_dai_drv, num_dai: 1);
773 if (ret < 0) {
774 dev_err(&pdev->dev, "Error: %s: Failed to register MSP%d!\n",
775 __func__, drvdata->msp->id);
776 return ret;
777 }
778
779 ret = ux500_pcm_register_platform(pdev);
780 if (ret < 0) {
781 dev_err(&pdev->dev,
782 "Error: %s: Failed to register PCM platform device!\n",
783 __func__);
784 goto err_reg_plat;
785 }
786
787 return 0;
788
789err_reg_plat:
790 snd_soc_unregister_component(dev: &pdev->dev);
791 return ret;
792}
793
794static void ux500_msp_drv_remove(struct platform_device *pdev)
795{
796 struct ux500_msp_i2s_drvdata *drvdata = dev_get_drvdata(dev: &pdev->dev);
797
798 ux500_pcm_unregister_platform(pdev);
799
800 snd_soc_unregister_component(dev: &pdev->dev);
801
802 prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, name: "ux500_msp_i2s");
803
804 ux500_msp_i2s_cleanup_msp(pdev, msp: drvdata->msp);
805}
806
807static const struct of_device_id ux500_msp_i2s_match[] = {
808 { .compatible = "stericsson,ux500-msp-i2s", },
809 {},
810};
811MODULE_DEVICE_TABLE(of, ux500_msp_i2s_match);
812
813static struct platform_driver msp_i2s_driver = {
814 .driver = {
815 .name = "ux500-msp-i2s",
816 .of_match_table = ux500_msp_i2s_match,
817 },
818 .probe = ux500_msp_drv_probe,
819 .remove_new = ux500_msp_drv_remove,
820};
821module_platform_driver(msp_i2s_driver);
822
823MODULE_LICENSE("GPL v2");
824

source code of linux/sound/soc/ux500/ux500_msp_dai.c