]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - sound/soc/samsung/i2s.c
ASoC: dmaengine: Remove unused SND_DMAENGINE_PCM_FLAG_CUSTOM_CHANNEL_NAME flag
[mirror_ubuntu-hirsute-kernel.git] / sound / soc / samsung / i2s.c
CommitLineData
c1b2db4d
SN
1// SPDX-License-Identifier: GPL-2.0
2//
3// ALSA SoC Audio Layer - Samsung I2S Controller driver
4//
5// Copyright (c) 2010 Samsung Electronics Co. Ltd.
6// Jaswinder Singh <jassisinghbrar@gmail.com>
1c7ac018 7
074b89bb 8#include <dt-bindings/sound/samsung-i2s.h>
1c7ac018
JB
9#include <linux/delay.h>
10#include <linux/slab.h>
11#include <linux/clk.h>
074b89bb 12#include <linux/clk-provider.h>
1c7ac018 13#include <linux/io.h>
da155d5b 14#include <linux/module.h>
40476f61 15#include <linux/of.h>
2f7b5d14 16#include <linux/of_device.h>
40476f61 17#include <linux/of_gpio.h>
c5cf4dbc 18#include <linux/pm_runtime.h>
1c7ac018 19
1c7ac018 20#include <sound/soc.h>
0378b6ac 21#include <sound/pcm_params.h>
1c7ac018 22
436d42c6 23#include <linux/platform_data/asoc-s3c.h>
1c7ac018
JB
24
25#include "dma.h"
61100f40 26#include "idma.h"
1c7ac018 27#include "i2s.h"
172a453d 28#include "i2s-regs.h"
1c7ac018
JB
29
30#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
31
a404b72d
SN
32#define SAMSUNG_I2S_ID_PRIMARY 1
33#define SAMSUNG_I2S_ID_SECONDARY 2
34
a5a56871
PV
35struct samsung_i2s_variant_regs {
36 unsigned int bfs_off;
37 unsigned int rfs_off;
38 unsigned int sdf_off;
39 unsigned int txr_off;
40 unsigned int rclksrc_off;
41 unsigned int mss_off;
42 unsigned int cdclkcon_off;
43 unsigned int lrp_off;
44 unsigned int bfs_mask;
45 unsigned int rfs_mask;
46 unsigned int ftx0cnt_off;
47};
48
40476f61 49struct samsung_i2s_dai_data {
7da493e9 50 u32 quirks;
4720c2fe 51 unsigned int pcm_rates;
a5a56871 52 const struct samsung_i2s_variant_regs *i2s_variant_regs;
40476f61
PV
53};
54
1c7ac018
JB
55struct i2s_dai {
56 /* Platform device for this DAI */
57 struct platform_device *pdev;
e2e16fa6 58
9f9f8a5b 59 /* Frame clock */
1c7ac018
JB
60 unsigned frmclk;
61 /*
9f9f8a5b 62 * Specifically requested RCLK, BCLK by machine driver.
1c7ac018
JB
63 * 0 indicates CPU driver is free to choose any value.
64 */
65 unsigned rfs, bfs;
1c7ac018
JB
66 /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */
67 struct i2s_dai *pri_dai;
68 /* Pointer to the Secondary_Fifo if it has one, NULL otherwise */
69 struct i2s_dai *sec_dai;
9f9f8a5b
SN
70
71#define DAI_OPENED (1 << 0) /* DAI is opened */
72#define DAI_MANAGER (1 << 1) /* DAI is the manager */
1c7ac018 73 unsigned mode;
a404b72d 74
1c7ac018 75 /* Driver for this DAI */
a404b72d
SN
76 struct snd_soc_dai_driver *drv;
77
1c7ac018 78 /* DMA parameters */
69e7a69a
SN
79 struct snd_dmaengine_dai_dma_data dma_playback;
80 struct snd_dmaengine_dai_dma_data dma_capture;
81 struct snd_dmaengine_dai_dma_data idma_playback;
9bdca822 82 dma_filter_fn filter;
f3670536 83
89d2e831 84 struct samsung_i2s_priv *priv;
1c7ac018
JB
85};
86
a404b72d
SN
87struct samsung_i2s_priv {
88 struct platform_device *pdev;
7196c64c 89 struct platform_device *pdev_sec;
a404b72d 90
e2e16fa6
SN
91 /* Memory mapped SFR region */
92 void __iomem *addr;
93
a404b72d 94 /* Spinlock protecting access to the device's registers */
9d7939c9 95 spinlock_t lock;
a404b72d 96
9f9f8a5b 97 /* Lock for cross interface checks */
defc67c6
SN
98 spinlock_t pcm_lock;
99
a404b72d
SN
100 /* CPU DAIs and their corresponding drivers */
101 struct i2s_dai *dai;
102 struct snd_soc_dai_driver *dai_drv;
103 int num_dais;
89d2e831 104
b5d015e6
SN
105 /* The I2S controller's core clock */
106 struct clk *clk;
107
3b0fa51f
SN
108 /* Clock for generating I2S signals */
109 struct clk *op_clk;
110
111 /* Rate of RCLK source clock */
112 unsigned long rclk_srcrate;
113
81bcbf2c
SN
114 /* Cache of selected I2S registers for system suspend */
115 u32 suspend_i2smod;
116 u32 suspend_i2scon;
117 u32 suspend_i2spsr;
118
5bfaeddc 119 const struct samsung_i2s_variant_regs *variant_regs;
5944170f 120 u32 quirks;
5bfaeddc 121
89d2e831
SN
122 /* The clock provider's data */
123 struct clk *clk_table[3];
124 struct clk_onecell_data clk_data;
a404b72d
SN
125};
126
a404b72d 127/* Returns true if this is the 'overlay' stereo DAI */
1c7ac018
JB
128static inline bool is_secondary(struct i2s_dai *i2s)
129{
a404b72d 130 return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY;
1c7ac018
JB
131}
132
133/* If operating in SoC-Slave mode */
134static inline bool is_slave(struct i2s_dai *i2s)
135{
e2e16fa6
SN
136 struct samsung_i2s_priv *priv = i2s->priv;
137
138 u32 mod = readl(priv->addr + I2SMOD);
5bfaeddc 139 return (mod & (1 << priv->variant_regs->mss_off)) ? true : false;
1c7ac018
JB
140}
141
142/* If this interface of the controller is transmitting data */
143static inline bool tx_active(struct i2s_dai *i2s)
144{
145 u32 active;
146
147 if (!i2s)
148 return false;
149
e2e16fa6 150 active = readl(i2s->priv->addr + I2SCON);
1c7ac018
JB
151
152 if (is_secondary(i2s))
153 active &= CON_TXSDMA_ACTIVE;
154 else
155 active &= CON_TXDMA_ACTIVE;
156
157 return active ? true : false;
158}
159
dcd60fc3
SN
160/* Return pointer to the other DAI */
161static inline struct i2s_dai *get_other_dai(struct i2s_dai *i2s)
162{
163 return i2s->pri_dai ? : i2s->sec_dai;
164}
165
1c7ac018
JB
166/* If the other interface of the controller is transmitting data */
167static inline bool other_tx_active(struct i2s_dai *i2s)
168{
dcd60fc3 169 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
170
171 return tx_active(other);
172}
173
174/* If any interface of the controller is transmitting data */
175static inline bool any_tx_active(struct i2s_dai *i2s)
176{
177 return tx_active(i2s) || other_tx_active(i2s);
178}
179
180/* If this interface of the controller is receiving data */
181static inline bool rx_active(struct i2s_dai *i2s)
182{
183 u32 active;
184
185 if (!i2s)
186 return false;
187
e2e16fa6 188 active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE;
1c7ac018
JB
189
190 return active ? true : false;
191}
192
193/* If the other interface of the controller is receiving data */
194static inline bool other_rx_active(struct i2s_dai *i2s)
195{
dcd60fc3 196 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
197
198 return rx_active(other);
199}
200
201/* If any interface of the controller is receiving data */
202static inline bool any_rx_active(struct i2s_dai *i2s)
203{
204 return rx_active(i2s) || other_rx_active(i2s);
205}
206
207/* If the other DAI is transmitting or receiving data */
208static inline bool other_active(struct i2s_dai *i2s)
209{
210 return other_rx_active(i2s) || other_tx_active(i2s);
211}
212
213/* If this DAI is transmitting or receiving data */
214static inline bool this_active(struct i2s_dai *i2s)
215{
216 return tx_active(i2s) || rx_active(i2s);
217}
218
219/* If the controller is active anyway */
220static inline bool any_active(struct i2s_dai *i2s)
221{
222 return this_active(i2s) || other_active(i2s);
223}
224
225static inline struct i2s_dai *to_info(struct snd_soc_dai *dai)
226{
a404b72d
SN
227 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
228
229 return &priv->dai[dai->id - 1];
1c7ac018
JB
230}
231
232static inline bool is_opened(struct i2s_dai *i2s)
233{
234 if (i2s && (i2s->mode & DAI_OPENED))
235 return true;
236 else
237 return false;
238}
239
240static inline bool is_manager(struct i2s_dai *i2s)
241{
242 if (is_opened(i2s) && (i2s->mode & DAI_MANAGER))
243 return true;
244 else
245 return false;
246}
247
248/* Read RCLK of I2S (in multiples of LRCLK) */
249static inline unsigned get_rfs(struct i2s_dai *i2s)
250{
e2e16fa6 251 struct samsung_i2s_priv *priv = i2s->priv;
4ca0c0d4 252 u32 rfs;
e2e16fa6 253
5bfaeddc
SN
254 rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off;
255 rfs &= priv->variant_regs->rfs_mask;
1c7ac018
JB
256
257 switch (rfs) {
a5a56871
PV
258 case 7: return 192;
259 case 6: return 96;
260 case 5: return 128;
261 case 4: return 64;
1c7ac018
JB
262 case 3: return 768;
263 case 2: return 384;
264 case 1: return 512;
265 default: return 256;
266 }
267}
268
269/* Write RCLK of I2S (in multiples of LRCLK) */
270static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
271{
e2e16fa6
SN
272 struct samsung_i2s_priv *priv = i2s->priv;
273 u32 mod = readl(priv->addr + I2SMOD);
5bfaeddc 274 int rfs_shift = priv->variant_regs->rfs_off;
1c7ac018 275
5bfaeddc 276 mod &= ~(priv->variant_regs->rfs_mask << rfs_shift);
1c7ac018
JB
277
278 switch (rfs) {
a5a56871
PV
279 case 192:
280 mod |= (EXYNOS7_MOD_RCLK_192FS << rfs_shift);
281 break;
282 case 96:
283 mod |= (EXYNOS7_MOD_RCLK_96FS << rfs_shift);
284 break;
285 case 128:
286 mod |= (EXYNOS7_MOD_RCLK_128FS << rfs_shift);
287 break;
288 case 64:
289 mod |= (EXYNOS7_MOD_RCLK_64FS << rfs_shift);
290 break;
1c7ac018 291 case 768:
b60be4aa 292 mod |= (MOD_RCLK_768FS << rfs_shift);
1c7ac018
JB
293 break;
294 case 512:
b60be4aa 295 mod |= (MOD_RCLK_512FS << rfs_shift);
1c7ac018
JB
296 break;
297 case 384:
b60be4aa 298 mod |= (MOD_RCLK_384FS << rfs_shift);
1c7ac018
JB
299 break;
300 default:
b60be4aa 301 mod |= (MOD_RCLK_256FS << rfs_shift);
1c7ac018
JB
302 break;
303 }
304
e2e16fa6 305 writel(mod, priv->addr + I2SMOD);
1c7ac018
JB
306}
307
9f9f8a5b 308/* Read bit-clock of I2S (in multiples of LRCLK) */
1c7ac018
JB
309static inline unsigned get_bfs(struct i2s_dai *i2s)
310{
e2e16fa6 311 struct samsung_i2s_priv *priv = i2s->priv;
4ca0c0d4 312 u32 bfs;
e2e16fa6 313
5bfaeddc
SN
314 bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off;
315 bfs &= priv->variant_regs->bfs_mask;
1c7ac018
JB
316
317 switch (bfs) {
4ca0c0d4
PV
318 case 8: return 256;
319 case 7: return 192;
320 case 6: return 128;
321 case 5: return 96;
322 case 4: return 64;
1c7ac018
JB
323 case 3: return 24;
324 case 2: return 16;
325 case 1: return 48;
326 default: return 32;
327 }
328}
329
9f9f8a5b 330/* Write bit-clock of I2S (in multiples of LRCLK) */
1c7ac018
JB
331static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
332{
e2e16fa6
SN
333 struct samsung_i2s_priv *priv = i2s->priv;
334 u32 mod = readl(priv->addr + I2SMOD);
5944170f 335 int tdm = priv->quirks & QUIRK_SUPPORTS_TDM;
5bfaeddc 336 int bfs_shift = priv->variant_regs->bfs_off;
4ca0c0d4
PV
337
338 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */
339 if (!tdm && bfs > 48) {
340 dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n");
341 return;
342 }
1c7ac018 343
5bfaeddc 344 mod &= ~(priv->variant_regs->bfs_mask << bfs_shift);
a5a56871 345
1c7ac018
JB
346 switch (bfs) {
347 case 48:
b60be4aa 348 mod |= (MOD_BCLK_48FS << bfs_shift);
1c7ac018
JB
349 break;
350 case 32:
b60be4aa 351 mod |= (MOD_BCLK_32FS << bfs_shift);
1c7ac018
JB
352 break;
353 case 24:
b60be4aa 354 mod |= (MOD_BCLK_24FS << bfs_shift);
1c7ac018
JB
355 break;
356 case 16:
b60be4aa 357 mod |= (MOD_BCLK_16FS << bfs_shift);
1c7ac018 358 break;
4ca0c0d4
PV
359 case 64:
360 mod |= (EXYNOS5420_MOD_BCLK_64FS << bfs_shift);
361 break;
362 case 96:
363 mod |= (EXYNOS5420_MOD_BCLK_96FS << bfs_shift);
364 break;
365 case 128:
366 mod |= (EXYNOS5420_MOD_BCLK_128FS << bfs_shift);
367 break;
368 case 192:
369 mod |= (EXYNOS5420_MOD_BCLK_192FS << bfs_shift);
370 break;
371 case 256:
372 mod |= (EXYNOS5420_MOD_BCLK_256FS << bfs_shift);
1c7ac018
JB
373 break;
374 default:
375 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");
376 return;
377 }
378
e2e16fa6 379 writel(mod, priv->addr + I2SMOD);
1c7ac018
JB
380}
381
9f9f8a5b 382/* Sample size */
1c7ac018
JB
383static inline int get_blc(struct i2s_dai *i2s)
384{
e2e16fa6 385 int blc = readl(i2s->priv->addr + I2SMOD);
1c7ac018
JB
386
387 blc = (blc >> 13) & 0x3;
388
389 switch (blc) {
390 case 2: return 24;
391 case 1: return 8;
392 default: return 16;
393 }
394}
395
9f9f8a5b 396/* TX channel control */
1c7ac018
JB
397static void i2s_txctrl(struct i2s_dai *i2s, int on)
398{
e2e16fa6
SN
399 struct samsung_i2s_priv *priv = i2s->priv;
400 void __iomem *addr = priv->addr;
5bfaeddc 401 int txr_off = priv->variant_regs->txr_off;
1c7ac018 402 u32 con = readl(addr + I2SCON);
a5a56871 403 u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
1c7ac018
JB
404
405 if (on) {
406 con |= CON_ACTIVE;
407 con &= ~CON_TXCH_PAUSE;
408
409 if (is_secondary(i2s)) {
410 con |= CON_TXSDMA_ACTIVE;
411 con &= ~CON_TXSDMA_PAUSE;
412 } else {
413 con |= CON_TXDMA_ACTIVE;
414 con &= ~CON_TXDMA_PAUSE;
415 }
416
417 if (any_rx_active(i2s))
a5a56871 418 mod |= 2 << txr_off;
1c7ac018 419 else
a5a56871 420 mod |= 0 << txr_off;
1c7ac018
JB
421 } else {
422 if (is_secondary(i2s)) {
423 con |= CON_TXSDMA_PAUSE;
424 con &= ~CON_TXSDMA_ACTIVE;
425 } else {
426 con |= CON_TXDMA_PAUSE;
427 con &= ~CON_TXDMA_ACTIVE;
428 }
429
430 if (other_tx_active(i2s)) {
431 writel(con, addr + I2SCON);
432 return;
433 }
434
435 con |= CON_TXCH_PAUSE;
436
437 if (any_rx_active(i2s))
a5a56871 438 mod |= 1 << txr_off;
1c7ac018
JB
439 else
440 con &= ~CON_ACTIVE;
441 }
442
443 writel(mod, addr + I2SMOD);
444 writel(con, addr + I2SCON);
445}
446
447/* RX Channel Control */
448static void i2s_rxctrl(struct i2s_dai *i2s, int on)
449{
e2e16fa6
SN
450 struct samsung_i2s_priv *priv = i2s->priv;
451 void __iomem *addr = priv->addr;
5bfaeddc 452 int txr_off = priv->variant_regs->txr_off;
1c7ac018 453 u32 con = readl(addr + I2SCON);
a5a56871 454 u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
1c7ac018
JB
455
456 if (on) {
457 con |= CON_RXDMA_ACTIVE | CON_ACTIVE;
458 con &= ~(CON_RXDMA_PAUSE | CON_RXCH_PAUSE);
459
460 if (any_tx_active(i2s))
a5a56871 461 mod |= 2 << txr_off;
1c7ac018 462 else
a5a56871 463 mod |= 1 << txr_off;
1c7ac018
JB
464 } else {
465 con |= CON_RXDMA_PAUSE | CON_RXCH_PAUSE;
466 con &= ~CON_RXDMA_ACTIVE;
467
468 if (any_tx_active(i2s))
a5a56871 469 mod |= 0 << txr_off;
1c7ac018
JB
470 else
471 con &= ~CON_ACTIVE;
472 }
473
474 writel(mod, addr + I2SMOD);
475 writel(con, addr + I2SCON);
476}
477
478/* Flush FIFO of an interface */
479static inline void i2s_fifo(struct i2s_dai *i2s, u32 flush)
480{
481 void __iomem *fic;
482 u32 val;
483
484 if (!i2s)
485 return;
486
487 if (is_secondary(i2s))
e2e16fa6 488 fic = i2s->priv->addr + I2SFICS;
1c7ac018 489 else
e2e16fa6 490 fic = i2s->priv->addr + I2SFIC;
1c7ac018
JB
491
492 /* Flush the FIFO */
493 writel(readl(fic) | flush, fic);
494
495 /* Be patient */
496 val = msecs_to_loops(1) / 1000; /* 1 usec */
497 while (--val)
498 cpu_relax();
499
500 writel(readl(fic) & ~flush, fic);
501}
502
3b0fa51f
SN
503static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,
504 int dir)
1c7ac018 505{
3b0fa51f 506 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 507 struct i2s_dai *i2s = to_info(dai);
dcd60fc3 508 struct i2s_dai *other = get_other_dai(i2s);
5bfaeddc 509 const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs;
a5a56871
PV
510 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
511 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
ce8bcdbb 512 u32 mod, mask, val = 0;
316fa9e0 513 unsigned long flags;
dc938ddb
MS
514 int ret = 0;
515
516 pm_runtime_get_sync(dai->dev);
ce8bcdbb 517
9d7939c9 518 spin_lock_irqsave(&priv->lock, flags);
e2e16fa6 519 mod = readl(priv->addr + I2SMOD);
9d7939c9 520 spin_unlock_irqrestore(&priv->lock, flags);
1c7ac018
JB
521
522 switch (clk_id) {
c86d50f9 523 case SAMSUNG_I2S_OPCLK:
ce8bcdbb 524 mask = MOD_OPCLK_MASK;
45ae70e8 525 val = (dir << MOD_OPCLK_SHIFT) & MOD_OPCLK_MASK;
c86d50f9 526 break;
1c7ac018 527 case SAMSUNG_I2S_CDCLK:
ce8bcdbb 528 mask = 1 << i2s_regs->cdclkcon_off;
1c7ac018
JB
529 /* Shouldn't matter in GATING(CLOCK_IN) mode */
530 if (dir == SND_SOC_CLOCK_IN)
531 rfs = 0;
532
133c2681 533 if ((rfs && other && other->rfs && (other->rfs != rfs)) ||
1c7ac018
JB
534 (any_active(i2s) &&
535 (((dir == SND_SOC_CLOCK_IN)
a5a56871 536 && !(mod & cdcon_mask)) ||
1c7ac018 537 ((dir == SND_SOC_CLOCK_OUT)
a5a56871 538 && (mod & cdcon_mask))))) {
1c7ac018
JB
539 dev_err(&i2s->pdev->dev,
540 "%s:%d Other DAI busy\n", __func__, __LINE__);
dc938ddb
MS
541 ret = -EAGAIN;
542 goto err;
1c7ac018
JB
543 }
544
545 if (dir == SND_SOC_CLOCK_IN)
ce8bcdbb 546 val = 1 << i2s_regs->cdclkcon_off;
1c7ac018
JB
547
548 i2s->rfs = rfs;
549 break;
550
551 case SAMSUNG_I2S_RCLKSRC_0: /* clock corrsponding to IISMOD[10] := 0 */
552 case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */
ce8bcdbb
SN
553 mask = 1 << i2s_regs->rclksrc_off;
554
5944170f 555 if ((priv->quirks & QUIRK_NO_MUXPSR)
1c7ac018
JB
556 || (clk_id == SAMSUNG_I2S_RCLKSRC_0))
557 clk_id = 0;
558 else
559 clk_id = 1;
560
561 if (!any_active(i2s)) {
3b0fa51f 562 if (priv->op_clk && !IS_ERR(priv->op_clk)) {
a5a56871
PV
563 if ((clk_id && !(mod & rsrc_mask)) ||
564 (!clk_id && (mod & rsrc_mask))) {
3b0fa51f
SN
565 clk_disable_unprepare(priv->op_clk);
566 clk_put(priv->op_clk);
1c7ac018 567 } else {
3b0fa51f
SN
568 priv->rclk_srcrate =
569 clk_get_rate(priv->op_clk);
dc938ddb 570 goto done;
1c7ac018
JB
571 }
572 }
573
1974a042 574 if (clk_id)
3b0fa51f 575 priv->op_clk = clk_get(&i2s->pdev->dev,
1974a042
PV
576 "i2s_opclk1");
577 else
3b0fa51f 578 priv->op_clk = clk_get(&i2s->pdev->dev,
1974a042 579 "i2s_opclk0");
a6aba536 580
3b0fa51f
SN
581 if (WARN_ON(IS_ERR(priv->op_clk))) {
582 ret = PTR_ERR(priv->op_clk);
583 priv->op_clk = NULL;
dc938ddb
MS
584 goto err;
585 }
a6aba536 586
3b0fa51f 587 ret = clk_prepare_enable(priv->op_clk);
6431a7e3 588 if (ret) {
3b0fa51f
SN
589 clk_put(priv->op_clk);
590 priv->op_clk = NULL;
f5c97c7b 591 goto err;
6431a7e3 592 }
3b0fa51f 593 priv->rclk_srcrate = clk_get_rate(priv->op_clk);
1c7ac018 594
a5a56871
PV
595 } else if ((!clk_id && (mod & rsrc_mask))
596 || (clk_id && !(mod & rsrc_mask))) {
1c7ac018
JB
597 dev_err(&i2s->pdev->dev,
598 "%s:%d Other DAI busy\n", __func__, __LINE__);
dc938ddb
MS
599 ret = -EAGAIN;
600 goto err;
1c7ac018
JB
601 } else {
602 /* Call can't be on the active DAI */
dc938ddb 603 goto done;
1c7ac018
JB
604 }
605
ce8bcdbb
SN
606 if (clk_id == 1)
607 val = 1 << i2s_regs->rclksrc_off;
b2de1d20 608 break;
1c7ac018
JB
609 default:
610 dev_err(&i2s->pdev->dev, "We don't serve that!\n");
dc938ddb
MS
611 ret = -EINVAL;
612 goto err;
1c7ac018
JB
613 }
614
9d7939c9 615 spin_lock_irqsave(&priv->lock, flags);
e2e16fa6 616 mod = readl(priv->addr + I2SMOD);
ce8bcdbb 617 mod = (mod & ~mask) | val;
e2e16fa6 618 writel(mod, priv->addr + I2SMOD);
9d7939c9 619 spin_unlock_irqrestore(&priv->lock, flags);
dc938ddb
MS
620done:
621 pm_runtime_put(dai->dev);
1c7ac018
JB
622
623 return 0;
dc938ddb
MS
624err:
625 pm_runtime_put(dai->dev);
626 return ret;
1c7ac018
JB
627}
628
89d2e831 629static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
1c7ac018 630{
89d2e831 631 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 632 struct i2s_dai *i2s = to_info(dai);
a5a56871 633 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
ce8bcdbb 634 u32 mod, tmp = 0;
316fa9e0 635 unsigned long flags;
1c7ac018 636
5bfaeddc
SN
637 lrp_shift = priv->variant_regs->lrp_off;
638 sdf_shift = priv->variant_regs->sdf_off;
639 mod_slave = 1 << priv->variant_regs->mss_off;
4ca0c0d4 640
b60be4aa
PV
641 sdf_mask = MOD_SDF_MASK << sdf_shift;
642 lrp_rlow = MOD_LR_RLOW << lrp_shift;
643
1c7ac018
JB
644 /* Format is priority */
645 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
646 case SND_SOC_DAIFMT_RIGHT_J:
b60be4aa
PV
647 tmp |= lrp_rlow;
648 tmp |= (MOD_SDF_MSB << sdf_shift);
1c7ac018
JB
649 break;
650 case SND_SOC_DAIFMT_LEFT_J:
b60be4aa
PV
651 tmp |= lrp_rlow;
652 tmp |= (MOD_SDF_LSB << sdf_shift);
1c7ac018
JB
653 break;
654 case SND_SOC_DAIFMT_I2S:
b60be4aa 655 tmp |= (MOD_SDF_IIS << sdf_shift);
1c7ac018
JB
656 break;
657 default:
658 dev_err(&i2s->pdev->dev, "Format not supported\n");
659 return -EINVAL;
660 }
661
662 /*
663 * INV flag is relative to the FORMAT flag - if set it simply
664 * flips the polarity specified by the Standard
665 */
666 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
667 case SND_SOC_DAIFMT_NB_NF:
668 break;
669 case SND_SOC_DAIFMT_NB_IF:
b60be4aa
PV
670 if (tmp & lrp_rlow)
671 tmp &= ~lrp_rlow;
1c7ac018 672 else
b60be4aa 673 tmp |= lrp_rlow;
1c7ac018
JB
674 break;
675 default:
676 dev_err(&i2s->pdev->dev, "Polarity not supported\n");
677 return -EINVAL;
678 }
679
680 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
681 case SND_SOC_DAIFMT_CBM_CFM:
a5a56871 682 tmp |= mod_slave;
1c7ac018
JB
683 break;
684 case SND_SOC_DAIFMT_CBS_CFS:
647d04f8
SN
685 /*
686 * Set default source clock in Master mode, only when the
687 * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any
688 * clock configuration assigned in DT is not overwritten.
689 */
3b0fa51f 690 if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL)
1c7ac018
JB
691 i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,
692 0, SND_SOC_CLOCK_IN);
693 break;
694 default:
695 dev_err(&i2s->pdev->dev, "master/slave format not supported\n");
696 return -EINVAL;
697 }
698
dc938ddb 699 pm_runtime_get_sync(dai->dev);
9d7939c9 700 spin_lock_irqsave(&priv->lock, flags);
e2e16fa6 701 mod = readl(priv->addr + I2SMOD);
b60be4aa
PV
702 /*
703 * Don't change the I2S mode if any controller is active on this
704 * channel.
705 */
1c7ac018 706 if (any_active(i2s) &&
a5a56871 707 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
9d7939c9 708 spin_unlock_irqrestore(&priv->lock, flags);
dc938ddb 709 pm_runtime_put(dai->dev);
1c7ac018
JB
710 dev_err(&i2s->pdev->dev,
711 "%s:%d Other DAI busy\n", __func__, __LINE__);
712 return -EAGAIN;
713 }
714
a5a56871 715 mod &= ~(sdf_mask | lrp_rlow | mod_slave);
1c7ac018 716 mod |= tmp;
e2e16fa6 717 writel(mod, priv->addr + I2SMOD);
9d7939c9 718 spin_unlock_irqrestore(&priv->lock, flags);
dc938ddb 719 pm_runtime_put(dai->dev);
1c7ac018
JB
720
721 return 0;
722}
723
724static int i2s_hw_params(struct snd_pcm_substream *substream,
725 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
726{
89d2e831 727 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 728 struct i2s_dai *i2s = to_info(dai);
ce8bcdbb 729 u32 mod, mask = 0, val = 0;
860b454c 730 struct clk *rclksrc;
316fa9e0 731 unsigned long flags;
1c7ac018 732
dc938ddb
MS
733 WARN_ON(!pm_runtime_active(dai->dev));
734
1c7ac018 735 if (!is_secondary(i2s))
ce8bcdbb 736 mask |= (MOD_DC2_EN | MOD_DC1_EN);
1c7ac018
JB
737
738 switch (params_channels(params)) {
739 case 6:
ce8bcdbb 740 val |= MOD_DC2_EN;
9f9f8a5b 741 /* Fall through */
1c7ac018 742 case 4:
ce8bcdbb 743 val |= MOD_DC1_EN;
1c7ac018
JB
744 break;
745 case 2:
588fb705 746 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
69e7a69a 747 i2s->dma_playback.addr_width = 4;
588fb705 748 else
69e7a69a 749 i2s->dma_capture.addr_width = 4;
588fb705
SP
750 break;
751 case 1:
752 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
69e7a69a 753 i2s->dma_playback.addr_width = 2;
588fb705 754 else
69e7a69a 755 i2s->dma_capture.addr_width = 2;
588fb705 756
1c7ac018
JB
757 break;
758 default:
759 dev_err(&i2s->pdev->dev, "%d channels not supported\n",
760 params_channels(params));
761 return -EINVAL;
762 }
763
764 if (is_secondary(i2s))
ce8bcdbb 765 mask |= MOD_BLCS_MASK;
1c7ac018 766 else
ce8bcdbb 767 mask |= MOD_BLCP_MASK;
1c7ac018
JB
768
769 if (is_manager(i2s))
ce8bcdbb 770 mask |= MOD_BLC_MASK;
1c7ac018 771
88ce1465
TB
772 switch (params_width(params)) {
773 case 8:
1c7ac018 774 if (is_secondary(i2s))
ce8bcdbb 775 val |= MOD_BLCS_8BIT;
1c7ac018 776 else
ce8bcdbb 777 val |= MOD_BLCP_8BIT;
1c7ac018 778 if (is_manager(i2s))
ce8bcdbb 779 val |= MOD_BLC_8BIT;
1c7ac018 780 break;
88ce1465 781 case 16:
1c7ac018 782 if (is_secondary(i2s))
ce8bcdbb 783 val |= MOD_BLCS_16BIT;
1c7ac018 784 else
ce8bcdbb 785 val |= MOD_BLCP_16BIT;
1c7ac018 786 if (is_manager(i2s))
ce8bcdbb 787 val |= MOD_BLC_16BIT;
1c7ac018 788 break;
88ce1465 789 case 24:
1c7ac018 790 if (is_secondary(i2s))
ce8bcdbb 791 val |= MOD_BLCS_24BIT;
1c7ac018 792 else
ce8bcdbb 793 val |= MOD_BLCP_24BIT;
1c7ac018 794 if (is_manager(i2s))
ce8bcdbb 795 val |= MOD_BLC_24BIT;
1c7ac018
JB
796 break;
797 default:
798 dev_err(&i2s->pdev->dev, "Format(%d) not supported\n",
799 params_format(params));
800 return -EINVAL;
801 }
ce8bcdbb 802
9d7939c9 803 spin_lock_irqsave(&priv->lock, flags);
e2e16fa6 804 mod = readl(priv->addr + I2SMOD);
ce8bcdbb 805 mod = (mod & ~mask) | val;
e2e16fa6 806 writel(mod, priv->addr + I2SMOD);
9d7939c9 807 spin_unlock_irqrestore(&priv->lock, flags);
1c7ac018 808
69e7a69a 809 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
d37bdf73 810
1c7ac018
JB
811 i2s->frmclk = params_rate(params);
812
89d2e831 813 rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC];
860b454c 814 if (rclksrc && !IS_ERR(rclksrc))
3b0fa51f 815 priv->rclk_srcrate = clk_get_rate(rclksrc);
860b454c 816
1c7ac018
JB
817 return 0;
818}
819
9f9f8a5b 820/* We set constraints on the substream according to the version of I2S */
1c7ac018
JB
821static int i2s_startup(struct snd_pcm_substream *substream,
822 struct snd_soc_dai *dai)
823{
5944170f 824 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 825 struct i2s_dai *i2s = to_info(dai);
dcd60fc3 826 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
827 unsigned long flags;
828
dc938ddb
MS
829 pm_runtime_get_sync(dai->dev);
830
defc67c6 831 spin_lock_irqsave(&priv->pcm_lock, flags);
1c7ac018
JB
832
833 i2s->mode |= DAI_OPENED;
834
835 if (is_manager(other))
836 i2s->mode &= ~DAI_MANAGER;
837 else
838 i2s->mode |= DAI_MANAGER;
839
5944170f 840 if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR))
e2e16fa6 841 writel(CON_RSTCLR, i2s->priv->addr + I2SCON);
2d77828d 842
defc67c6 843 spin_unlock_irqrestore(&priv->pcm_lock, flags);
1c7ac018
JB
844
845 return 0;
846}
847
848static void i2s_shutdown(struct snd_pcm_substream *substream,
849 struct snd_soc_dai *dai)
850{
defc67c6 851 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 852 struct i2s_dai *i2s = to_info(dai);
dcd60fc3 853 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
854 unsigned long flags;
855
defc67c6 856 spin_lock_irqsave(&priv->pcm_lock, flags);
1c7ac018
JB
857
858 i2s->mode &= ~DAI_OPENED;
859 i2s->mode &= ~DAI_MANAGER;
860
074b89bb 861 if (is_opened(other))
1c7ac018 862 other->mode |= DAI_MANAGER;
074b89bb 863
1c7ac018
JB
864 /* Reset any constraint on RFS and BFS */
865 i2s->rfs = 0;
866 i2s->bfs = 0;
867
defc67c6 868 spin_unlock_irqrestore(&priv->pcm_lock, flags);
dc938ddb
MS
869
870 pm_runtime_put(dai->dev);
1c7ac018
JB
871}
872
873static int config_setup(struct i2s_dai *i2s)
874{
3b0fa51f 875 struct samsung_i2s_priv *priv = i2s->priv;
dcd60fc3 876 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
877 unsigned rfs, bfs, blc;
878 u32 psr;
879
880 blc = get_blc(i2s);
881
882 bfs = i2s->bfs;
883
884 if (!bfs && other)
885 bfs = other->bfs;
886
887 /* Select least possible multiple(2) if no constraint set */
888 if (!bfs)
889 bfs = blc * 2;
890
891 rfs = i2s->rfs;
892
893 if (!rfs && other)
894 rfs = other->rfs;
895
896 if ((rfs == 256 || rfs == 512) && (blc == 24)) {
897 dev_err(&i2s->pdev->dev,
898 "%d-RFS not supported for 24-blc\n", rfs);
899 return -EINVAL;
900 }
901
902 if (!rfs) {
903 if (bfs == 16 || bfs == 32)
904 rfs = 256;
905 else
906 rfs = 384;
907 }
908
909 /* If already setup and running */
910 if (any_active(i2s) && (get_rfs(i2s) != rfs || get_bfs(i2s) != bfs)) {
911 dev_err(&i2s->pdev->dev,
912 "%s:%d Other DAI busy\n", __func__, __LINE__);
913 return -EAGAIN;
914 }
915
1c7ac018
JB
916 set_bfs(i2s, bfs);
917 set_rfs(i2s, rfs);
918
77010010
PV
919 /* Don't bother with PSR in Slave mode */
920 if (is_slave(i2s))
921 return 0;
922
5944170f 923 if (!(priv->quirks & QUIRK_NO_MUXPSR)) {
3b0fa51f 924 psr = priv->rclk_srcrate / i2s->frmclk / rfs;
e2e16fa6 925 writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR);
1c7ac018
JB
926 dev_dbg(&i2s->pdev->dev,
927 "RCLK_SRC=%luHz PSR=%u, RCLK=%dfs, BCLK=%dfs\n",
3b0fa51f 928 priv->rclk_srcrate, psr, rfs, bfs);
1c7ac018
JB
929 }
930
931 return 0;
932}
933
934static int i2s_trigger(struct snd_pcm_substream *substream,
935 int cmd, struct snd_soc_dai *dai)
936{
9d7939c9 937 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018
JB
938 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
939 struct snd_soc_pcm_runtime *rtd = substream->private_data;
940 struct i2s_dai *i2s = to_info(rtd->cpu_dai);
941 unsigned long flags;
942
943 switch (cmd) {
944 case SNDRV_PCM_TRIGGER_START:
945 case SNDRV_PCM_TRIGGER_RESUME:
946 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
dc938ddb 947 pm_runtime_get_sync(dai->dev);
9d7939c9 948 spin_lock_irqsave(&priv->lock, flags);
1c7ac018 949
1c7ac018 950 if (config_setup(i2s)) {
9d7939c9 951 spin_unlock_irqrestore(&priv->lock, flags);
1c7ac018
JB
952 return -EINVAL;
953 }
954
955 if (capture)
956 i2s_rxctrl(i2s, 1);
957 else
958 i2s_txctrl(i2s, 1);
959
9d7939c9 960 spin_unlock_irqrestore(&priv->lock, flags);
1c7ac018
JB
961 break;
962 case SNDRV_PCM_TRIGGER_STOP:
963 case SNDRV_PCM_TRIGGER_SUSPEND:
964 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
9d7939c9 965 spin_lock_irqsave(&priv->lock, flags);
1c7ac018 966
c90887fe 967 if (capture) {
1c7ac018 968 i2s_rxctrl(i2s, 0);
775bc971 969 i2s_fifo(i2s, FIC_RXFLUSH);
c90887fe
JB
970 } else {
971 i2s_txctrl(i2s, 0);
775bc971 972 i2s_fifo(i2s, FIC_TXFLUSH);
c90887fe 973 }
775bc971 974
9d7939c9 975 spin_unlock_irqrestore(&priv->lock, flags);
dc938ddb 976 pm_runtime_put(dai->dev);
1c7ac018
JB
977 break;
978 }
979
980 return 0;
981}
982
983static int i2s_set_clkdiv(struct snd_soc_dai *dai,
984 int div_id, int div)
985{
986 struct i2s_dai *i2s = to_info(dai);
dcd60fc3 987 struct i2s_dai *other = get_other_dai(i2s);
1c7ac018
JB
988
989 switch (div_id) {
990 case SAMSUNG_I2S_DIV_BCLK:
dc938ddb 991 pm_runtime_get_sync(dai->dev);
1c7ac018
JB
992 if ((any_active(i2s) && div && (get_bfs(i2s) != div))
993 || (other && other->bfs && (other->bfs != div))) {
dc938ddb 994 pm_runtime_put(dai->dev);
1c7ac018
JB
995 dev_err(&i2s->pdev->dev,
996 "%s:%d Other DAI busy\n", __func__, __LINE__);
997 return -EAGAIN;
998 }
999 i2s->bfs = div;
dc938ddb 1000 pm_runtime_put(dai->dev);
1c7ac018
JB
1001 break;
1002 default:
1003 dev_err(&i2s->pdev->dev,
1004 "Invalid clock divider(%d)\n", div_id);
1005 return -EINVAL;
1006 }
1007
1008 return 0;
1009}
1010
1011static snd_pcm_sframes_t
1012i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
1013{
e2e16fa6 1014 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 1015 struct i2s_dai *i2s = to_info(dai);
e2e16fa6 1016 u32 reg = readl(priv->addr + I2SFIC);
1c7ac018
JB
1017 snd_pcm_sframes_t delay;
1018
dc938ddb
MS
1019 WARN_ON(!pm_runtime_active(dai->dev));
1020
1c7ac018
JB
1021 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
1022 delay = FIC_RXCOUNT(reg);
1023 else if (is_secondary(i2s))
e2e16fa6 1024 delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS));
1c7ac018 1025 else
5bfaeddc 1026 delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f;
1c7ac018
JB
1027
1028 return delay;
1029}
1030
1031#ifdef CONFIG_PM
1032static int i2s_suspend(struct snd_soc_dai *dai)
1033{
e7e52dfc 1034 return pm_runtime_force_suspend(dai->dev);
1c7ac018
JB
1035}
1036
1037static int i2s_resume(struct snd_soc_dai *dai)
1038{
e7e52dfc 1039 return pm_runtime_force_resume(dai->dev);
1c7ac018
JB
1040}
1041#else
1042#define i2s_suspend NULL
1043#define i2s_resume NULL
1044#endif
1045
1046static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
1047{
e2e16fa6 1048 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1c7ac018 1049 struct i2s_dai *i2s = to_info(dai);
dcd60fc3 1050 struct i2s_dai *other = get_other_dai(i2s);
ce8bcdbb 1051 unsigned long flags;
1c7ac018 1052
dc938ddb
MS
1053 pm_runtime_get_sync(dai->dev);
1054
9f9f8a5b
SN
1055 if (is_secondary(i2s)) {
1056 /* If this is probe on the secondary DAI */
eb540d39 1057 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL);
872c26bd 1058 } else {
69e7a69a 1059 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback,
eb540d39 1060 &i2s->dma_capture);
511e3033 1061
5944170f 1062 if (priv->quirks & QUIRK_NEED_RSTCLR)
e2e16fa6 1063 writel(CON_RSTCLR, priv->addr + I2SCON);
1c7ac018 1064
5944170f 1065 if (priv->quirks & QUIRK_SUPPORTS_IDMA)
e2e16fa6 1066 idma_reg_addr_init(priv->addr,
eb540d39 1067 other->idma_playback.addr);
872c26bd 1068 }
61100f40 1069
1c7ac018
JB
1070 /* Reset any constraint on RFS and BFS */
1071 i2s->rfs = 0;
1072 i2s->bfs = 0;
ce8bcdbb 1073
9d7939c9 1074 spin_lock_irqsave(&priv->lock, flags);
1c7ac018
JB
1075 i2s_txctrl(i2s, 0);
1076 i2s_rxctrl(i2s, 0);
1077 i2s_fifo(i2s, FIC_TXFLUSH);
1078 i2s_fifo(other, FIC_TXFLUSH);
1079 i2s_fifo(i2s, FIC_RXFLUSH);
9d7939c9 1080 spin_unlock_irqrestore(&priv->lock, flags);
1c7ac018
JB
1081
1082 /* Gate CDCLK by default */
1083 if (!is_opened(other))
1084 i2s_set_sysclk(dai, SAMSUNG_I2S_CDCLK,
1085 0, SND_SOC_CLOCK_IN);
dc938ddb 1086 pm_runtime_put(dai->dev);
1c7ac018
JB
1087
1088 return 0;
1089}
1090
1091static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
1092{
e2e16fa6 1093 struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
a404b72d 1094 struct i2s_dai *i2s = to_info(dai);
5faf071d 1095 unsigned long flags;
1c7ac018 1096
dc938ddb
MS
1097 pm_runtime_get_sync(dai->dev);
1098
c92f1d0e 1099 if (!is_secondary(i2s)) {
5944170f 1100 if (priv->quirks & QUIRK_NEED_RSTCLR) {
9d7939c9 1101 spin_lock_irqsave(&priv->lock, flags);
e2e16fa6 1102 writel(0, priv->addr + I2SCON);
9d7939c9 1103 spin_unlock_irqrestore(&priv->lock, flags);
ce8bcdbb 1104 }
1c7ac018
JB
1105 }
1106
dc938ddb
MS
1107 pm_runtime_put(dai->dev);
1108
1c7ac018
JB
1109 return 0;
1110}
1111
85e7652d 1112static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
1c7ac018
JB
1113 .trigger = i2s_trigger,
1114 .hw_params = i2s_hw_params,
1115 .set_fmt = i2s_set_fmt,
1116 .set_clkdiv = i2s_set_clkdiv,
1117 .set_sysclk = i2s_set_sysclk,
1118 .startup = i2s_startup,
1119 .shutdown = i2s_shutdown,
1120 .delay = i2s_delay,
1121};
1122
64aba9bc
SN
1123static const struct snd_soc_dapm_widget samsung_i2s_widgets[] = {
1124 /* Backend DAI */
1125 SND_SOC_DAPM_AIF_OUT("Mixer DAI TX", NULL, 0, SND_SOC_NOPM, 0, 0),
1126 SND_SOC_DAPM_AIF_IN("Mixer DAI RX", NULL, 0, SND_SOC_NOPM, 0, 0),
1127
1128 /* Playback Mixer */
1129 SND_SOC_DAPM_MIXER("Playback Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
1130};
1131
1132static const struct snd_soc_dapm_route samsung_i2s_dapm_routes[] = {
1133 { "Playback Mixer", NULL, "Primary" },
1134 { "Playback Mixer", NULL, "Secondary" },
1135
1136 { "Mixer DAI TX", NULL, "Playback Mixer" },
1137 { "Playback Mixer", NULL, "Mixer DAI RX" },
1138};
1139
4b828535 1140static const struct snd_soc_component_driver samsung_i2s_component = {
64aba9bc
SN
1141 .name = "samsung-i2s",
1142
1143 .dapm_widgets = samsung_i2s_widgets,
1144 .num_dapm_widgets = ARRAY_SIZE(samsung_i2s_widgets),
1145
1146 .dapm_routes = samsung_i2s_dapm_routes,
1147 .num_dapm_routes = ARRAY_SIZE(samsung_i2s_dapm_routes),
4b828535
KM
1148};
1149
c5ba6192
SN
1150#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
1151 SNDRV_PCM_FMTBIT_S24_LE)
1c7ac018 1152
a404b72d
SN
1153static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
1154 const struct samsung_i2s_dai_data *i2s_dai_data,
1155 int num_dais)
1c7ac018 1156{
a404b72d 1157 static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" };
64aba9bc 1158 static const char *stream_names[] = { "Primary", "Secondary" };
a404b72d
SN
1159 struct snd_soc_dai_driver *dai_drv;
1160 struct i2s_dai *dai;
1161 int i;
1162
1163 priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais,
1164 sizeof(*dai), GFP_KERNEL);
1165 if (!priv->dai)
1166 return -ENOMEM;
1167
1168 priv->dai_drv = devm_kcalloc(&priv->pdev->dev, num_dais,
1169 sizeof(*dai_drv), GFP_KERNEL);
1170 if (!priv->dai_drv)
1171 return -ENOMEM;
1172
1173 for (i = 0; i < num_dais; i++) {
1174 dai_drv = &priv->dai_drv[i];
1175
1176 dai_drv->probe = samsung_i2s_dai_probe;
1177 dai_drv->remove = samsung_i2s_dai_remove;
1178 dai_drv->suspend = i2s_suspend;
1179 dai_drv->resume = i2s_resume;
1180
1181 dai_drv->symmetric_rates = 1;
1182 dai_drv->ops = &samsung_i2s_dai_ops;
1183
1184 dai_drv->playback.channels_min = 1;
1185 dai_drv->playback.channels_max = 2;
1186 dai_drv->playback.rates = i2s_dai_data->pcm_rates;
1187 dai_drv->playback.formats = SAMSUNG_I2S_FMTS;
64aba9bc 1188 dai_drv->playback.stream_name = stream_names[i];
a404b72d
SN
1189
1190 dai_drv->id = i + 1;
1191 dai_drv->name = dai_names[i];
1192
1193 priv->dai[i].drv = &priv->dai_drv[i];
1194 priv->dai[i].pdev = priv->pdev;
c6f9b1eb 1195 }
a404b72d
SN
1196
1197 /* Initialize capture only for the primary DAI */
1198 dai_drv = &priv->dai_drv[SAMSUNG_I2S_ID_PRIMARY - 1];
1199
1200 dai_drv->capture.channels_min = 1;
1201 dai_drv->capture.channels_max = 2;
1202 dai_drv->capture.rates = i2s_dai_data->pcm_rates;
1203 dai_drv->capture.formats = SAMSUNG_I2S_FMTS;
1204
1205 return 0;
1c7ac018
JB
1206}
1207
641d334b 1208#ifdef CONFIG_PM
5b1d3c34
C
1209static int i2s_runtime_suspend(struct device *dev)
1210{
b5d015e6 1211 struct samsung_i2s_priv *priv = dev_get_drvdata(dev);
5b1d3c34 1212
e2e16fa6
SN
1213 priv->suspend_i2smod = readl(priv->addr + I2SMOD);
1214 priv->suspend_i2scon = readl(priv->addr + I2SCON);
1215 priv->suspend_i2spsr = readl(priv->addr + I2SPSR);
e7e52dfc 1216
3b0fa51f
SN
1217 if (priv->op_clk)
1218 clk_disable_unprepare(priv->op_clk);
b5d015e6 1219 clk_disable_unprepare(priv->clk);
5b1d3c34
C
1220
1221 return 0;
1222}
1223
1224static int i2s_runtime_resume(struct device *dev)
1225{
b5d015e6 1226 struct samsung_i2s_priv *priv = dev_get_drvdata(dev);
f5c97c7b 1227 int ret;
5b1d3c34 1228
b5d015e6 1229 ret = clk_prepare_enable(priv->clk);
f5c97c7b
AY
1230 if (ret)
1231 return ret;
1232
3b0fa51f
SN
1233 if (priv->op_clk) {
1234 ret = clk_prepare_enable(priv->op_clk);
f5c97c7b 1235 if (ret) {
b5d015e6 1236 clk_disable_unprepare(priv->clk);
f5c97c7b
AY
1237 return ret;
1238 }
1239 }
5b1d3c34 1240
e2e16fa6
SN
1241 writel(priv->suspend_i2scon, priv->addr + I2SCON);
1242 writel(priv->suspend_i2smod, priv->addr + I2SMOD);
1243 writel(priv->suspend_i2spsr, priv->addr + I2SPSR);
5b1d3c34
C
1244
1245 return 0;
1246}
641d334b 1247#endif /* CONFIG_PM */
5b1d3c34 1248
89d2e831 1249static void i2s_unregister_clocks(struct samsung_i2s_priv *priv)
074b89bb
SN
1250{
1251 int i;
1252
89d2e831
SN
1253 for (i = 0; i < priv->clk_data.clk_num; i++) {
1254 if (!IS_ERR(priv->clk_table[i]))
1255 clk_unregister(priv->clk_table[i]);
074b89bb
SN
1256 }
1257}
1258
89d2e831 1259static void i2s_unregister_clock_provider(struct samsung_i2s_priv *priv)
074b89bb 1260{
89d2e831
SN
1261 of_clk_del_provider(priv->pdev->dev.of_node);
1262 i2s_unregister_clocks(priv);
074b89bb
SN
1263}
1264
89d2e831
SN
1265
1266static int i2s_register_clock_provider(struct samsung_i2s_priv *priv)
074b89bb 1267{
a404b72d 1268
aa274c5c 1269 const char * const i2s_clk_desc[] = { "cdclk", "rclk_src", "prescaler" };
074b89bb
SN
1270 const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" };
1271 const char *p_names[2] = { NULL };
89d2e831 1272 struct device *dev = &priv->pdev->dev;
5bfaeddc 1273 const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs;
aa274c5c 1274 const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)];
074b89bb
SN
1275 struct clk *rclksrc;
1276 int ret, i;
1277
1278 /* Register the clock provider only if it's expected in the DTB */
1279 if (!of_find_property(dev->of_node, "#clock-cells", NULL))
1280 return 0;
1281
1282 /* Get the RCLKSRC mux clock parent clock names */
1283 for (i = 0; i < ARRAY_SIZE(p_names); i++) {
1284 rclksrc = clk_get(dev, clk_name[i]);
1285 if (IS_ERR(rclksrc))
1286 continue;
1287 p_names[i] = __clk_get_name(rclksrc);
1288 clk_put(rclksrc);
1289 }
1290
aa274c5c
SN
1291 for (i = 0; i < ARRAY_SIZE(i2s_clk_desc); i++) {
1292 i2s_clk_name[i] = devm_kasprintf(dev, GFP_KERNEL, "%s_%s",
1293 dev_name(dev), i2s_clk_desc[i]);
1294 if (!i2s_clk_name[i])
1295 return -ENOMEM;
1296 }
1297
5944170f 1298 if (!(priv->quirks & QUIRK_NO_MUXPSR)) {
074b89bb 1299 /* Activate the prescaler */
e2e16fa6
SN
1300 u32 val = readl(priv->addr + I2SPSR);
1301 writel(val | PSR_PSREN, priv->addr + I2SPSR);
074b89bb 1302
89d2e831 1303 priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,
aa274c5c
SN
1304 i2s_clk_name[CLK_I2S_RCLK_SRC], p_names,
1305 ARRAY_SIZE(p_names),
074b89bb 1306 CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
e2e16fa6 1307 priv->addr + I2SMOD, reg_info->rclksrc_off,
9d7939c9 1308 1, 0, &priv->lock);
074b89bb 1309
89d2e831 1310 priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,
aa274c5c
SN
1311 i2s_clk_name[CLK_I2S_RCLK_PSR],
1312 i2s_clk_name[CLK_I2S_RCLK_SRC],
074b89bb 1313 CLK_SET_RATE_PARENT,
9d7939c9 1314 priv->addr + I2SPSR, 8, 6, 0, &priv->lock);
074b89bb 1315
aa274c5c 1316 p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR];
89d2e831 1317 priv->clk_data.clk_num = 2;
074b89bb 1318 }
074b89bb 1319
89d2e831 1320 priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev,
aa274c5c
SN
1321 i2s_clk_name[CLK_I2S_CDCLK], p_names[0],
1322 CLK_SET_RATE_PARENT,
e2e16fa6 1323 priv->addr + I2SMOD, reg_info->cdclkcon_off,
9d7939c9 1324 CLK_GATE_SET_TO_DISABLE, &priv->lock);
074b89bb 1325
89d2e831
SN
1326 priv->clk_data.clk_num += 1;
1327 priv->clk_data.clks = priv->clk_table;
074b89bb
SN
1328
1329 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
89d2e831 1330 &priv->clk_data);
074b89bb
SN
1331 if (ret < 0) {
1332 dev_err(dev, "failed to add clock provider: %d\n", ret);
89d2e831 1333 i2s_unregister_clocks(priv);
074b89bb
SN
1334 }
1335
1336 return ret;
1337}
1338
7196c64c
SN
1339/* Create platform device for the secondary PCM */
1340static int i2s_create_secondary_device(struct samsung_i2s_priv *priv)
1341{
1342 struct platform_device *pdev;
1343 int ret;
1344
1345 pdev = platform_device_register_simple("samsung-i2s-sec", -1, NULL, 0);
1346 if (!pdev)
1347 return -ENOMEM;
1348
1349 ret = device_attach(&pdev->dev);
1350 if (ret < 0) {
1351 dev_info(&pdev->dev, "device_attach() failed\n");
1352 return ret;
1353 }
1354
1355 priv->pdev_sec = pdev;
1356
1357 return 0;
1358}
1359
1360static void i2s_delete_secondary_device(struct samsung_i2s_priv *priv)
1361{
1362 if (priv->pdev_sec) {
1363 platform_device_del(priv->pdev_sec);
1364 priv->pdev_sec = NULL;
1365 }
1366}
fdca21ad 1367static int samsung_i2s_probe(struct platform_device *pdev)
1c7ac018 1368{
1c7ac018 1369 struct i2s_dai *pri_dai, *sec_dai = NULL;
40476f61 1370 struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;
1c7ac018 1371 struct resource *res;
40476f61
PV
1372 u32 regs_base, quirks = 0, idma_addr = 0;
1373 struct device_node *np = pdev->dev.of_node;
7da493e9 1374 const struct samsung_i2s_dai_data *i2s_dai_data;
a404b72d
SN
1375 int num_dais, ret;
1376 struct samsung_i2s_priv *priv;
1c7ac018 1377
2f7b5d14
SN
1378 if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
1379 i2s_dai_data = of_device_get_match_data(&pdev->dev);
1380 else
1381 i2s_dai_data = (struct samsung_i2s_dai_data *)
1382 platform_get_device_id(pdev)->driver_data;
7c62eebb 1383
7196c64c
SN
1384 /* Nothing to do if it is the secondary device probe */
1385 if (!i2s_dai_data)
1386 return 0;
1387
a404b72d
SN
1388 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1389 if (!priv)
40476f61 1390 return -ENOMEM;
1c7ac018 1391
a404b72d 1392 quirks = np ? i2s_dai_data->quirks : i2s_pdata->type.quirks;
a404b72d
SN
1393 num_dais = (quirks & QUIRK_SEC_DAI) ? 2 : 1;
1394 priv->pdev = pdev;
5944170f
SN
1395 priv->variant_regs = i2s_dai_data->i2s_variant_regs;
1396 priv->quirks = quirks;
a404b72d
SN
1397
1398 ret = i2s_alloc_dais(priv, i2s_dai_data, num_dais);
1399 if (ret < 0)
1400 return ret;
1401
1402 pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1];
1403
9d7939c9 1404 spin_lock_init(&priv->lock);
defc67c6 1405 spin_lock_init(&priv->pcm_lock);
f3670536 1406
40476f61 1407 if (!np) {
40476f61
PV
1408 if (i2s_pdata == NULL) {
1409 dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n");
1410 return -EINVAL;
1411 }
1412
69e7a69a
SN
1413 pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback;
1414 pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture;
9bdca822 1415 pri_dai->filter = i2s_pdata->dma_filter;
b9a1a743 1416
409c69be 1417 idma_addr = i2s_pdata->type.idma_addr;
40476f61 1418 } else {
40476f61
PV
1419 if (of_property_read_u32(np, "samsung,idma-addr",
1420 &idma_addr)) {
b0759736
PV
1421 if (quirks & QUIRK_SUPPORTS_IDMA) {
1422 dev_info(&pdev->dev, "idma address is not"\
40476f61 1423 "specified");
40476f61
PV
1424 }
1425 }
1426 }
1c7ac018
JB
1427
1428 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
e2e16fa6
SN
1429 priv->addr = devm_ioremap_resource(&pdev->dev, res);
1430 if (IS_ERR(priv->addr))
1431 return PTR_ERR(priv->addr);
1c7ac018 1432
1c7ac018
JB
1433 regs_base = res->start;
1434
b5d015e6
SN
1435 priv->clk = devm_clk_get(&pdev->dev, "iis");
1436 if (IS_ERR(priv->clk)) {
0ec2ba80 1437 dev_err(&pdev->dev, "Failed to get iis clock\n");
b5d015e6 1438 return PTR_ERR(priv->clk);
0ec2ba80 1439 }
c92f1d0e 1440
b5d015e6 1441 ret = clk_prepare_enable(priv->clk);
c92f1d0e
SN
1442 if (ret != 0) {
1443 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
1444 return ret;
1445 }
69e7a69a
SN
1446 pri_dai->dma_playback.addr = regs_base + I2STXD;
1447 pri_dai->dma_capture.addr = regs_base + I2SRXD;
b8ab0ccc
SN
1448 pri_dai->dma_playback.chan_name = "tx";
1449 pri_dai->dma_capture.chan_name = "rx";
69e7a69a
SN
1450 pri_dai->dma_playback.addr_width = 4;
1451 pri_dai->dma_capture.addr_width = 4;
89d2e831 1452 pri_dai->priv = priv;
1c7ac018
JB
1453
1454 if (quirks & QUIRK_PRI_6CHAN)
a404b72d 1455 pri_dai->drv->playback.channels_max = 6;
1c7ac018 1456
73f5dfc6 1457 ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter,
0f928c19 1458 "tx", "rx", NULL);
73f5dfc6
MS
1459 if (ret < 0)
1460 goto err_disable_clk;
1461
1c7ac018 1462 if (quirks & QUIRK_SEC_DAI) {
a404b72d 1463 sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1];
7e5d8706 1464
69e7a69a 1465 sec_dai->dma_playback.addr = regs_base + I2STXDS;
b8ab0ccc 1466 sec_dai->dma_playback.chan_name = "tx-sec";
40476f61 1467
9bdca822 1468 if (!np) {
69e7a69a 1469 sec_dai->dma_playback.filter_data = i2s_pdata->dma_play_sec;
9bdca822
AB
1470 sec_dai->filter = i2s_pdata->dma_filter;
1471 }
40476f61 1472
69e7a69a 1473 sec_dai->dma_playback.addr_width = 4;
69e7a69a 1474 sec_dai->idma_playback.addr = idma_addr;
1c7ac018 1475 sec_dai->pri_dai = pri_dai;
89d2e831 1476 sec_dai->priv = priv;
1c7ac018 1477 pri_dai->sec_dai = sec_dai;
be2c92eb 1478
7196c64c
SN
1479 ret = i2s_create_secondary_device(priv);
1480 if (ret < 0)
1481 goto err_disable_clk;
1482
1483 ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev,
1484 sec_dai->filter, "tx-sec", NULL,
1485 &pdev->dev);
be2c92eb
MS
1486 if (ret < 0)
1487 goto err_disable_clk;
1488
1c7ac018
JB
1489 }
1490
0429ffef
MB
1491 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
1492 dev_err(&pdev->dev, "Unable to configure gpio\n");
fd61576f
WY
1493 ret = -EINVAL;
1494 goto err_disable_clk;
1c7ac018
JB
1495 }
1496
a404b72d
SN
1497 dev_set_drvdata(&pdev->dev, priv);
1498
1499 ret = devm_snd_soc_register_component(&pdev->dev,
1500 &samsung_i2s_component,
1501 priv->dai_drv, num_dais);
1502 if (ret < 0)
1503 goto err_disable_clk;
1c7ac018 1504
dc938ddb 1505 pm_runtime_set_active(&pdev->dev);
c5cf4dbc
MB
1506 pm_runtime_enable(&pdev->dev);
1507
89d2e831 1508 ret = i2s_register_clock_provider(priv);
48279c53
SN
1509 if (ret < 0)
1510 goto err_disable_pm;
1511
3b0fa51f 1512 priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]);
48279c53
SN
1513
1514 return 0;
a08485d8 1515
48279c53 1516err_disable_pm:
2b960386 1517 pm_runtime_disable(&pdev->dev);
fd61576f 1518err_disable_clk:
b5d015e6 1519 clk_disable_unprepare(priv->clk);
7196c64c 1520 i2s_delete_secondary_device(priv);
2b960386 1521 return ret;
1c7ac018
JB
1522}
1523
fdca21ad 1524static int samsung_i2s_remove(struct platform_device *pdev)
1c7ac018 1525{
a404b72d 1526 struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev);
1c7ac018 1527
7196c64c
SN
1528 /* The secondary device has no driver data assigned */
1529 if (!priv)
1530 return 0;
1531
dc938ddb 1532 pm_runtime_get_sync(&pdev->dev);
be2c92eb 1533 pm_runtime_disable(&pdev->dev);
c92f1d0e 1534
89d2e831 1535 i2s_unregister_clock_provider(priv);
b5d015e6 1536 clk_disable_unprepare(priv->clk);
dc938ddb 1537 pm_runtime_put_noidle(&pdev->dev);
7196c64c 1538 i2s_delete_secondary_device(priv);
1c7ac018 1539
1c7ac018
JB
1540 return 0;
1541}
1542
a5a56871
PV
1543static const struct samsung_i2s_variant_regs i2sv3_regs = {
1544 .bfs_off = 1,
1545 .rfs_off = 3,
1546 .sdf_off = 5,
1547 .txr_off = 8,
1548 .rclksrc_off = 10,
1549 .mss_off = 11,
1550 .cdclkcon_off = 12,
1551 .lrp_off = 7,
1552 .bfs_mask = 0x3,
1553 .rfs_mask = 0x3,
1554 .ftx0cnt_off = 8,
1555};
1556
1557static const struct samsung_i2s_variant_regs i2sv6_regs = {
1558 .bfs_off = 0,
1559 .rfs_off = 4,
1560 .sdf_off = 6,
1561 .txr_off = 8,
1562 .rclksrc_off = 10,
1563 .mss_off = 11,
1564 .cdclkcon_off = 12,
1565 .lrp_off = 15,
1566 .bfs_mask = 0xf,
1567 .rfs_mask = 0x3,
1568 .ftx0cnt_off = 8,
1569};
1570
1571static const struct samsung_i2s_variant_regs i2sv7_regs = {
1572 .bfs_off = 0,
1573 .rfs_off = 4,
1574 .sdf_off = 7,
1575 .txr_off = 9,
1576 .rclksrc_off = 11,
1577 .mss_off = 12,
1578 .cdclkcon_off = 22,
1579 .lrp_off = 15,
1580 .bfs_mask = 0xf,
1581 .rfs_mask = 0x7,
1582 .ftx0cnt_off = 0,
1583};
1584
1585static const struct samsung_i2s_variant_regs i2sv5_i2s1_regs = {
1586 .bfs_off = 0,
1587 .rfs_off = 3,
1588 .sdf_off = 6,
1589 .txr_off = 8,
1590 .rclksrc_off = 10,
1591 .mss_off = 11,
1592 .cdclkcon_off = 12,
1593 .lrp_off = 15,
1594 .bfs_mask = 0x7,
1595 .rfs_mask = 0x7,
1596 .ftx0cnt_off = 8,
1597};
1598
7da493e9 1599static const struct samsung_i2s_dai_data i2sv3_dai_type = {
7da493e9 1600 .quirks = QUIRK_NO_MUXPSR,
4720c2fe 1601 .pcm_rates = SNDRV_PCM_RATE_8000_96000,
a5a56871 1602 .i2s_variant_regs = &i2sv3_regs,
7da493e9
PV
1603};
1604
1605static const struct samsung_i2s_dai_data i2sv5_dai_type = {
b0759736
PV
1606 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
1607 QUIRK_SUPPORTS_IDMA,
4720c2fe 1608 .pcm_rates = SNDRV_PCM_RATE_8000_96000,
a5a56871 1609 .i2s_variant_regs = &i2sv3_regs,
7da493e9
PV
1610};
1611
4ca0c0d4 1612static const struct samsung_i2s_dai_data i2sv6_dai_type = {
4ca0c0d4 1613 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
b0759736 1614 QUIRK_SUPPORTS_TDM | QUIRK_SUPPORTS_IDMA,
4720c2fe 1615 .pcm_rates = SNDRV_PCM_RATE_8000_96000,
a5a56871
PV
1616 .i2s_variant_regs = &i2sv6_regs,
1617};
1618
1619static const struct samsung_i2s_dai_data i2sv7_dai_type = {
a5a56871
PV
1620 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
1621 QUIRK_SUPPORTS_TDM,
4720c2fe 1622 .pcm_rates = SNDRV_PCM_RATE_8000_192000,
a5a56871
PV
1623 .i2s_variant_regs = &i2sv7_regs,
1624};
1625
1626static const struct samsung_i2s_dai_data i2sv5_dai_type_i2s1 = {
a5a56871 1627 .quirks = QUIRK_PRI_6CHAN | QUIRK_NEED_RSTCLR,
4720c2fe 1628 .pcm_rates = SNDRV_PCM_RATE_8000_96000,
a5a56871 1629 .i2s_variant_regs = &i2sv5_i2s1_regs,
4ca0c0d4
PV
1630};
1631
eb8ca0fa 1632static const struct platform_device_id samsung_i2s_driver_ids[] = {
7c62eebb
PV
1633 {
1634 .name = "samsung-i2s",
3f024980 1635 .driver_data = (kernel_ulong_t)&i2sv3_dai_type,
7196c64c
SN
1636 }, {
1637 .name = "samsung-i2s-sec",
7c62eebb
PV
1638 },
1639 {},
1640};
2af19558 1641MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids);
7c62eebb 1642
40476f61 1643#ifdef CONFIG_OF
40476f61 1644static const struct of_device_id exynos_i2s_match[] = {
7da493e9
PV
1645 {
1646 .compatible = "samsung,s3c6410-i2s",
1647 .data = &i2sv3_dai_type,
1648 }, {
1649 .compatible = "samsung,s5pv210-i2s",
1650 .data = &i2sv5_dai_type,
4ca0c0d4
PV
1651 }, {
1652 .compatible = "samsung,exynos5420-i2s",
1653 .data = &i2sv6_dai_type,
a5a56871
PV
1654 }, {
1655 .compatible = "samsung,exynos7-i2s",
1656 .data = &i2sv7_dai_type,
1657 }, {
1658 .compatible = "samsung,exynos7-i2s1",
1659 .data = &i2sv5_dai_type_i2s1,
40476f61
PV
1660 },
1661 {},
1662};
1663MODULE_DEVICE_TABLE(of, exynos_i2s_match);
1664#endif
1665
5b1d3c34
C
1666static const struct dev_pm_ops samsung_i2s_pm = {
1667 SET_RUNTIME_PM_OPS(i2s_runtime_suspend,
1668 i2s_runtime_resume, NULL)
e7e52dfc
MS
1669 SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
1670 pm_runtime_force_resume)
5b1d3c34
C
1671};
1672
1c7ac018
JB
1673static struct platform_driver samsung_i2s_driver = {
1674 .probe = samsung_i2s_probe,
fdca21ad 1675 .remove = samsung_i2s_remove,
7c62eebb 1676 .id_table = samsung_i2s_driver_ids,
1c7ac018
JB
1677 .driver = {
1678 .name = "samsung-i2s",
40476f61 1679 .of_match_table = of_match_ptr(exynos_i2s_match),
5b1d3c34 1680 .pm = &samsung_i2s_pm,
1c7ac018
JB
1681 },
1682};
1683
e00c3f55 1684module_platform_driver(samsung_i2s_driver);
1c7ac018
JB
1685
1686/* Module information */
df8ad335 1687MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
1c7ac018
JB
1688MODULE_DESCRIPTION("Samsung I2S Interface");
1689MODULE_ALIAS("platform:samsung-i2s");
1690MODULE_LICENSE("GPL");