hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/sound/soc/samsung/i2s.c
....@@ -1,14 +1,9 @@
1
-/* sound/soc/samsung/i2s.c
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>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License version 2 as
10
- * published by the Free Software Foundation.
11
- */
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>
127
138 #include <dt-bindings/sound/samsung-i2s.h>
149 #include <linux/delay.h>
....@@ -34,6 +29,9 @@
3429
3530 #define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
3631
32
+#define SAMSUNG_I2S_ID_PRIMARY 1
33
+#define SAMSUNG_I2S_ID_SECONDARY 2
34
+
3735 struct samsung_i2s_variant_regs {
3836 unsigned int bfs_off;
3937 unsigned int rfs_off;
....@@ -57,64 +55,82 @@
5755 struct i2s_dai {
5856 /* Platform device for this DAI */
5957 struct platform_device *pdev;
60
- /* Memory mapped SFR region */
61
- void __iomem *addr;
62
- /* Rate of RCLK source clock */
63
- unsigned long rclk_srcrate;
64
- /* Frame Clock */
58
+
59
+ /* Frame clock */
6560 unsigned frmclk;
6661 /*
67
- * Specifically requested RCLK,BCLK by MACHINE Driver.
62
+ * Specifically requested RCLK, BCLK by machine driver.
6863 * 0 indicates CPU driver is free to choose any value.
6964 */
7065 unsigned rfs, bfs;
71
- /* I2S Controller's core clock */
72
- struct clk *clk;
73
- /* Clock for generating I2S signals */
74
- struct clk *op_clk;
7566 /* Pointer to the Primary_Fifo if this is Sec_Fifo, NULL otherwise */
7667 struct i2s_dai *pri_dai;
7768 /* Pointer to the Secondary_Fifo if it has one, NULL otherwise */
7869 struct i2s_dai *sec_dai;
79
-#define DAI_OPENED (1 << 0) /* Dai is opened */
80
-#define DAI_MANAGER (1 << 1) /* Dai is the manager */
70
+
71
+#define DAI_OPENED (1 << 0) /* DAI is opened */
72
+#define DAI_MANAGER (1 << 1) /* DAI is the manager */
8173 unsigned mode;
74
+
8275 /* Driver for this DAI */
83
- struct snd_soc_dai_driver i2s_dai_drv;
76
+ struct snd_soc_dai_driver *drv;
77
+
8478 /* DMA parameters */
8579 struct snd_dmaengine_dai_dma_data dma_playback;
8680 struct snd_dmaengine_dai_dma_data dma_capture;
8781 struct snd_dmaengine_dai_dma_data idma_playback;
8882 dma_filter_fn filter;
89
- u32 quirks;
90
- u32 suspend_i2smod;
91
- u32 suspend_i2scon;
92
- u32 suspend_i2spsr;
93
- const struct samsung_i2s_variant_regs *variant_regs;
9483
95
- /* Spinlock protecting access to the device's registers */
96
- spinlock_t spinlock;
97
- spinlock_t *lock;
98
-
99
- /* Below fields are only valid if this is the primary FIFO */
100
- struct clk *clk_table[3];
101
- struct clk_onecell_data clk_data;
84
+ struct samsung_i2s_priv *priv;
10285 };
10386
104
-/* Lock for cross i/f checks */
105
-static DEFINE_SPINLOCK(lock);
87
+struct samsung_i2s_priv {
88
+ struct platform_device *pdev;
89
+ struct platform_device *pdev_sec;
10690
107
-/* If this is the 'overlay' stereo DAI */
91
+ /* Lock for cross interface checks */
92
+ spinlock_t pcm_lock;
93
+
94
+ /* CPU DAIs and their corresponding drivers */
95
+ struct i2s_dai *dai;
96
+ struct snd_soc_dai_driver *dai_drv;
97
+ int num_dais;
98
+
99
+ /* The I2S controller's core clock */
100
+ struct clk *clk;
101
+
102
+ /* Clock for generating I2S signals */
103
+ struct clk *op_clk;
104
+
105
+ /* Rate of RCLK source clock */
106
+ unsigned long rclk_srcrate;
107
+
108
+ /* Cache of selected I2S registers for system suspend */
109
+ u32 suspend_i2smod;
110
+ u32 suspend_i2scon;
111
+ u32 suspend_i2spsr;
112
+
113
+ const struct samsung_i2s_variant_regs *variant_regs;
114
+ u32 quirks;
115
+
116
+ /* The clock provider's data */
117
+ struct clk *clk_table[3];
118
+ struct clk_onecell_data clk_data;
119
+
120
+ /* Spinlock protecting member fields below */
121
+ spinlock_t lock;
122
+
123
+ /* Memory mapped SFR region */
124
+ void __iomem *addr;
125
+
126
+ /* A flag indicating the I2S slave mode operation */
127
+ bool slave_mode;
128
+};
129
+
130
+/* Returns true if this is the 'overlay' stereo DAI */
108131 static inline bool is_secondary(struct i2s_dai *i2s)
109132 {
110
- return i2s->pri_dai ? true : false;
111
-}
112
-
113
-/* If operating in SoC-Slave mode */
114
-static inline bool is_slave(struct i2s_dai *i2s)
115
-{
116
- u32 mod = readl(i2s->addr + I2SMOD);
117
- return (mod & (1 << i2s->variant_regs->mss_off)) ? true : false;
133
+ return i2s->drv->id == SAMSUNG_I2S_ID_SECONDARY;
118134 }
119135
120136 /* If this interface of the controller is transmitting data */
....@@ -125,7 +141,7 @@
125141 if (!i2s)
126142 return false;
127143
128
- active = readl(i2s->addr + I2SCON);
144
+ active = readl(i2s->priv->addr + I2SCON);
129145
130146 if (is_secondary(i2s))
131147 active &= CON_TXSDMA_ACTIVE;
....@@ -163,7 +179,7 @@
163179 if (!i2s)
164180 return false;
165181
166
- active = readl(i2s->addr + I2SCON) & CON_RXDMA_ACTIVE;
182
+ active = readl(i2s->priv->addr + I2SCON) & CON_RXDMA_ACTIVE;
167183
168184 return active ? true : false;
169185 }
....@@ -202,7 +218,9 @@
202218
203219 static inline struct i2s_dai *to_info(struct snd_soc_dai *dai)
204220 {
205
- return snd_soc_dai_get_drvdata(dai);
221
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
222
+
223
+ return &priv->dai[dai->id - 1];
206224 }
207225
208226 static inline bool is_opened(struct i2s_dai *i2s)
....@@ -224,9 +242,11 @@
224242 /* Read RCLK of I2S (in multiples of LRCLK) */
225243 static inline unsigned get_rfs(struct i2s_dai *i2s)
226244 {
245
+ struct samsung_i2s_priv *priv = i2s->priv;
227246 u32 rfs;
228
- rfs = readl(i2s->addr + I2SMOD) >> i2s->variant_regs->rfs_off;
229
- rfs &= i2s->variant_regs->rfs_mask;
247
+
248
+ rfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->rfs_off;
249
+ rfs &= priv->variant_regs->rfs_mask;
230250
231251 switch (rfs) {
232252 case 7: return 192;
....@@ -243,10 +263,11 @@
243263 /* Write RCLK of I2S (in multiples of LRCLK) */
244264 static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
245265 {
246
- u32 mod = readl(i2s->addr + I2SMOD);
247
- int rfs_shift = i2s->variant_regs->rfs_off;
266
+ struct samsung_i2s_priv *priv = i2s->priv;
267
+ u32 mod = readl(priv->addr + I2SMOD);
268
+ int rfs_shift = priv->variant_regs->rfs_off;
248269
249
- mod &= ~(i2s->variant_regs->rfs_mask << rfs_shift);
270
+ mod &= ~(priv->variant_regs->rfs_mask << rfs_shift);
250271
251272 switch (rfs) {
252273 case 192:
....@@ -275,15 +296,17 @@
275296 break;
276297 }
277298
278
- writel(mod, i2s->addr + I2SMOD);
299
+ writel(mod, priv->addr + I2SMOD);
279300 }
280301
281
-/* Read Bit-Clock of I2S (in multiples of LRCLK) */
302
+/* Read bit-clock of I2S (in multiples of LRCLK) */
282303 static inline unsigned get_bfs(struct i2s_dai *i2s)
283304 {
305
+ struct samsung_i2s_priv *priv = i2s->priv;
284306 u32 bfs;
285
- bfs = readl(i2s->addr + I2SMOD) >> i2s->variant_regs->bfs_off;
286
- bfs &= i2s->variant_regs->bfs_mask;
307
+
308
+ bfs = readl(priv->addr + I2SMOD) >> priv->variant_regs->bfs_off;
309
+ bfs &= priv->variant_regs->bfs_mask;
287310
288311 switch (bfs) {
289312 case 8: return 256;
....@@ -298,12 +321,13 @@
298321 }
299322 }
300323
301
-/* Write Bit-Clock of I2S (in multiples of LRCLK) */
324
+/* Write bit-clock of I2S (in multiples of LRCLK) */
302325 static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
303326 {
304
- u32 mod = readl(i2s->addr + I2SMOD);
305
- int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM;
306
- int bfs_shift = i2s->variant_regs->bfs_off;
327
+ struct samsung_i2s_priv *priv = i2s->priv;
328
+ u32 mod = readl(priv->addr + I2SMOD);
329
+ int tdm = priv->quirks & QUIRK_SUPPORTS_TDM;
330
+ int bfs_shift = priv->variant_regs->bfs_off;
307331
308332 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */
309333 if (!tdm && bfs > 48) {
....@@ -311,7 +335,7 @@
311335 return;
312336 }
313337
314
- mod &= ~(i2s->variant_regs->bfs_mask << bfs_shift);
338
+ mod &= ~(priv->variant_regs->bfs_mask << bfs_shift);
315339
316340 switch (bfs) {
317341 case 48:
....@@ -346,13 +370,13 @@
346370 return;
347371 }
348372
349
- writel(mod, i2s->addr + I2SMOD);
373
+ writel(mod, priv->addr + I2SMOD);
350374 }
351375
352
-/* Sample-Size */
376
+/* Sample size */
353377 static inline int get_blc(struct i2s_dai *i2s)
354378 {
355
- int blc = readl(i2s->addr + I2SMOD);
379
+ int blc = readl(i2s->priv->addr + I2SMOD);
356380
357381 blc = (blc >> 13) & 0x3;
358382
....@@ -363,11 +387,12 @@
363387 }
364388 }
365389
366
-/* TX Channel Control */
390
+/* TX channel control */
367391 static void i2s_txctrl(struct i2s_dai *i2s, int on)
368392 {
369
- void __iomem *addr = i2s->addr;
370
- int txr_off = i2s->variant_regs->txr_off;
393
+ struct samsung_i2s_priv *priv = i2s->priv;
394
+ void __iomem *addr = priv->addr;
395
+ int txr_off = priv->variant_regs->txr_off;
371396 u32 con = readl(addr + I2SCON);
372397 u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
373398
....@@ -416,8 +441,9 @@
416441 /* RX Channel Control */
417442 static void i2s_rxctrl(struct i2s_dai *i2s, int on)
418443 {
419
- void __iomem *addr = i2s->addr;
420
- int txr_off = i2s->variant_regs->txr_off;
444
+ struct samsung_i2s_priv *priv = i2s->priv;
445
+ void __iomem *addr = priv->addr;
446
+ int txr_off = priv->variant_regs->txr_off;
421447 u32 con = readl(addr + I2SCON);
422448 u32 mod = readl(addr + I2SMOD) & ~(3 << txr_off);
423449
....@@ -453,9 +479,9 @@
453479 return;
454480
455481 if (is_secondary(i2s))
456
- fic = i2s->addr + I2SFICS;
482
+ fic = i2s->priv->addr + I2SFICS;
457483 else
458
- fic = i2s->addr + I2SFIC;
484
+ fic = i2s->priv->addr + I2SFIC;
459485
460486 /* Flush the FIFO */
461487 writel(readl(fic) | flush, fic);
....@@ -468,12 +494,13 @@
468494 writel(readl(fic) & ~flush, fic);
469495 }
470496
471
-static int i2s_set_sysclk(struct snd_soc_dai *dai,
472
- int clk_id, unsigned int rfs, int dir)
497
+static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,
498
+ int dir)
473499 {
500
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
474501 struct i2s_dai *i2s = to_info(dai);
475502 struct i2s_dai *other = get_other_dai(i2s);
476
- const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
503
+ const struct samsung_i2s_variant_regs *i2s_regs = priv->variant_regs;
477504 unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
478505 unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
479506 u32 mod, mask, val = 0;
....@@ -482,9 +509,9 @@
482509
483510 pm_runtime_get_sync(dai->dev);
484511
485
- spin_lock_irqsave(i2s->lock, flags);
486
- mod = readl(i2s->addr + I2SMOD);
487
- spin_unlock_irqrestore(i2s->lock, flags);
512
+ spin_lock_irqsave(&priv->lock, flags);
513
+ mod = readl(priv->addr + I2SMOD);
514
+ spin_unlock_irqrestore(&priv->lock, flags);
488515
489516 switch (clk_id) {
490517 case SAMSUNG_I2S_OPCLK:
....@@ -519,51 +546,46 @@
519546 case SAMSUNG_I2S_RCLKSRC_1: /* clock corrsponding to IISMOD[10] := 1 */
520547 mask = 1 << i2s_regs->rclksrc_off;
521548
522
- if ((i2s->quirks & QUIRK_NO_MUXPSR)
549
+ if ((priv->quirks & QUIRK_NO_MUXPSR)
523550 || (clk_id == SAMSUNG_I2S_RCLKSRC_0))
524551 clk_id = 0;
525552 else
526553 clk_id = 1;
527554
528555 if (!any_active(i2s)) {
529
- if (i2s->op_clk && !IS_ERR(i2s->op_clk)) {
556
+ if (priv->op_clk && !IS_ERR(priv->op_clk)) {
530557 if ((clk_id && !(mod & rsrc_mask)) ||
531558 (!clk_id && (mod & rsrc_mask))) {
532
- clk_disable_unprepare(i2s->op_clk);
533
- clk_put(i2s->op_clk);
559
+ clk_disable_unprepare(priv->op_clk);
560
+ clk_put(priv->op_clk);
534561 } else {
535
- i2s->rclk_srcrate =
536
- clk_get_rate(i2s->op_clk);
562
+ priv->rclk_srcrate =
563
+ clk_get_rate(priv->op_clk);
537564 goto done;
538565 }
539566 }
540567
541568 if (clk_id)
542
- i2s->op_clk = clk_get(&i2s->pdev->dev,
569
+ priv->op_clk = clk_get(&i2s->pdev->dev,
543570 "i2s_opclk1");
544571 else
545
- i2s->op_clk = clk_get(&i2s->pdev->dev,
572
+ priv->op_clk = clk_get(&i2s->pdev->dev,
546573 "i2s_opclk0");
547574
548
- if (WARN_ON(IS_ERR(i2s->op_clk))) {
549
- ret = PTR_ERR(i2s->op_clk);
550
- i2s->op_clk = NULL;
575
+ if (WARN_ON(IS_ERR(priv->op_clk))) {
576
+ ret = PTR_ERR(priv->op_clk);
577
+ priv->op_clk = NULL;
551578 goto err;
552579 }
553580
554
- ret = clk_prepare_enable(i2s->op_clk);
581
+ ret = clk_prepare_enable(priv->op_clk);
555582 if (ret) {
556
- clk_put(i2s->op_clk);
557
- i2s->op_clk = NULL;
583
+ clk_put(priv->op_clk);
584
+ priv->op_clk = NULL;
558585 goto err;
559586 }
560
- i2s->rclk_srcrate = clk_get_rate(i2s->op_clk);
587
+ priv->rclk_srcrate = clk_get_rate(priv->op_clk);
561588
562
- /* Over-ride the other's */
563
- if (other) {
564
- other->op_clk = i2s->op_clk;
565
- other->rclk_srcrate = i2s->rclk_srcrate;
566
- }
567589 } else if ((!clk_id && (mod & rsrc_mask))
568590 || (clk_id && !(mod & rsrc_mask))) {
569591 dev_err(&i2s->pdev->dev,
....@@ -572,8 +594,6 @@
572594 goto err;
573595 } else {
574596 /* Call can't be on the active DAI */
575
- i2s->op_clk = other->op_clk;
576
- i2s->rclk_srcrate = other->rclk_srcrate;
577597 goto done;
578598 }
579599
....@@ -586,11 +606,11 @@
586606 goto err;
587607 }
588608
589
- spin_lock_irqsave(i2s->lock, flags);
590
- mod = readl(i2s->addr + I2SMOD);
609
+ spin_lock_irqsave(&priv->lock, flags);
610
+ mod = readl(priv->addr + I2SMOD);
591611 mod = (mod & ~mask) | val;
592
- writel(mod, i2s->addr + I2SMOD);
593
- spin_unlock_irqrestore(i2s->lock, flags);
612
+ writel(mod, priv->addr + I2SMOD);
613
+ spin_unlock_irqrestore(&priv->lock, flags);
594614 done:
595615 pm_runtime_put(dai->dev);
596616
....@@ -600,18 +620,17 @@
600620 return ret;
601621 }
602622
603
-static int i2s_set_fmt(struct snd_soc_dai *dai,
604
- unsigned int fmt)
623
+static int i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
605624 {
625
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
606626 struct i2s_dai *i2s = to_info(dai);
607
- struct i2s_dai *other = get_other_dai(i2s);
608627 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
609628 u32 mod, tmp = 0;
610629 unsigned long flags;
611630
612
- lrp_shift = i2s->variant_regs->lrp_off;
613
- sdf_shift = i2s->variant_regs->sdf_off;
614
- mod_slave = 1 << i2s->variant_regs->mss_off;
631
+ lrp_shift = priv->variant_regs->lrp_off;
632
+ sdf_shift = priv->variant_regs->sdf_off;
633
+ mod_slave = 1 << priv->variant_regs->mss_off;
615634
616635 sdf_mask = MOD_SDF_MASK << sdf_shift;
617636 lrp_rlow = MOD_LR_RLOW << lrp_shift;
....@@ -662,8 +681,7 @@
662681 * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any
663682 * clock configuration assigned in DT is not overwritten.
664683 */
665
- if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL &&
666
- other->clk_data.clks == NULL)
684
+ if (priv->rclk_srcrate == 0 && priv->clk_data.clks == NULL)
667685 i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,
668686 0, SND_SOC_CLOCK_IN);
669687 break;
....@@ -673,15 +691,15 @@
673691 }
674692
675693 pm_runtime_get_sync(dai->dev);
676
- spin_lock_irqsave(i2s->lock, flags);
677
- mod = readl(i2s->addr + I2SMOD);
694
+ spin_lock_irqsave(&priv->lock, flags);
695
+ mod = readl(priv->addr + I2SMOD);
678696 /*
679697 * Don't change the I2S mode if any controller is active on this
680698 * channel.
681699 */
682700 if (any_active(i2s) &&
683701 ((mod & (sdf_mask | lrp_rlow | mod_slave)) != tmp)) {
684
- spin_unlock_irqrestore(i2s->lock, flags);
702
+ spin_unlock_irqrestore(&priv->lock, flags);
685703 pm_runtime_put(dai->dev);
686704 dev_err(&i2s->pdev->dev,
687705 "%s:%d Other DAI busy\n", __func__, __LINE__);
....@@ -690,8 +708,9 @@
690708
691709 mod &= ~(sdf_mask | lrp_rlow | mod_slave);
692710 mod |= tmp;
693
- writel(mod, i2s->addr + I2SMOD);
694
- spin_unlock_irqrestore(i2s->lock, flags);
711
+ writel(mod, priv->addr + I2SMOD);
712
+ priv->slave_mode = (mod & mod_slave);
713
+ spin_unlock_irqrestore(&priv->lock, flags);
695714 pm_runtime_put(dai->dev);
696715
697716 return 0;
....@@ -700,8 +719,8 @@
700719 static int i2s_hw_params(struct snd_pcm_substream *substream,
701720 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
702721 {
722
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
703723 struct i2s_dai *i2s = to_info(dai);
704
- struct i2s_dai *other = get_other_dai(i2s);
705724 u32 mod, mask = 0, val = 0;
706725 struct clk *rclksrc;
707726 unsigned long flags;
....@@ -714,7 +733,7 @@
714733 switch (params_channels(params)) {
715734 case 6:
716735 val |= MOD_DC2_EN;
717
- /* fall through */
736
+ fallthrough;
718737 case 4:
719738 val |= MOD_DC1_EN;
720739 break;
....@@ -776,37 +795,35 @@
776795 return -EINVAL;
777796 }
778797
779
- spin_lock_irqsave(i2s->lock, flags);
780
- mod = readl(i2s->addr + I2SMOD);
798
+ spin_lock_irqsave(&priv->lock, flags);
799
+ mod = readl(priv->addr + I2SMOD);
781800 mod = (mod & ~mask) | val;
782
- writel(mod, i2s->addr + I2SMOD);
783
- spin_unlock_irqrestore(i2s->lock, flags);
801
+ writel(mod, priv->addr + I2SMOD);
802
+ spin_unlock_irqrestore(&priv->lock, flags);
784803
785804 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
786805
787806 i2s->frmclk = params_rate(params);
788807
789
- rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
790
- if (!rclksrc || IS_ERR(rclksrc))
791
- rclksrc = other->clk_table[CLK_I2S_RCLK_SRC];
792
-
808
+ rclksrc = priv->clk_table[CLK_I2S_RCLK_SRC];
793809 if (rclksrc && !IS_ERR(rclksrc))
794
- i2s->rclk_srcrate = clk_get_rate(rclksrc);
810
+ priv->rclk_srcrate = clk_get_rate(rclksrc);
795811
796812 return 0;
797813 }
798814
799
-/* We set constraints on the substream acc to the version of I2S */
815
+/* We set constraints on the substream according to the version of I2S */
800816 static int i2s_startup(struct snd_pcm_substream *substream,
801817 struct snd_soc_dai *dai)
802818 {
819
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
803820 struct i2s_dai *i2s = to_info(dai);
804821 struct i2s_dai *other = get_other_dai(i2s);
805822 unsigned long flags;
806823
807824 pm_runtime_get_sync(dai->dev);
808825
809
- spin_lock_irqsave(&lock, flags);
826
+ spin_lock_irqsave(&priv->pcm_lock, flags);
810827
811828 i2s->mode |= DAI_OPENED;
812829
....@@ -815,10 +832,10 @@
815832 else
816833 i2s->mode |= DAI_MANAGER;
817834
818
- if (!any_active(i2s) && (i2s->quirks & QUIRK_NEED_RSTCLR))
819
- writel(CON_RSTCLR, i2s->addr + I2SCON);
835
+ if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR))
836
+ writel(CON_RSTCLR, i2s->priv->addr + I2SCON);
820837
821
- spin_unlock_irqrestore(&lock, flags);
838
+ spin_unlock_irqrestore(&priv->pcm_lock, flags);
822839
823840 return 0;
824841 }
....@@ -826,11 +843,12 @@
826843 static void i2s_shutdown(struct snd_pcm_substream *substream,
827844 struct snd_soc_dai *dai)
828845 {
846
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
829847 struct i2s_dai *i2s = to_info(dai);
830848 struct i2s_dai *other = get_other_dai(i2s);
831849 unsigned long flags;
832850
833
- spin_lock_irqsave(&lock, flags);
851
+ spin_lock_irqsave(&priv->pcm_lock, flags);
834852
835853 i2s->mode &= ~DAI_OPENED;
836854 i2s->mode &= ~DAI_MANAGER;
....@@ -842,13 +860,14 @@
842860 i2s->rfs = 0;
843861 i2s->bfs = 0;
844862
845
- spin_unlock_irqrestore(&lock, flags);
863
+ spin_unlock_irqrestore(&priv->pcm_lock, flags);
846864
847865 pm_runtime_put(dai->dev);
848866 }
849867
850868 static int config_setup(struct i2s_dai *i2s)
851869 {
870
+ struct samsung_i2s_priv *priv = i2s->priv;
852871 struct i2s_dai *other = get_other_dai(i2s);
853872 unsigned rfs, bfs, blc;
854873 u32 psr;
....@@ -893,15 +912,15 @@
893912 set_rfs(i2s, rfs);
894913
895914 /* Don't bother with PSR in Slave mode */
896
- if (is_slave(i2s))
915
+ if (priv->slave_mode)
897916 return 0;
898917
899
- if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
900
- psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
901
- writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
918
+ if (!(priv->quirks & QUIRK_NO_MUXPSR)) {
919
+ psr = priv->rclk_srcrate / i2s->frmclk / rfs;
920
+ writel(((psr - 1) << 8) | PSR_PSREN, priv->addr + I2SPSR);
902921 dev_dbg(&i2s->pdev->dev,
903922 "RCLK_SRC=%luHz PSR=%u, RCLK=%dfs, BCLK=%dfs\n",
904
- i2s->rclk_srcrate, psr, rfs, bfs);
923
+ priv->rclk_srcrate, psr, rfs, bfs);
905924 }
906925
907926 return 0;
....@@ -910,9 +929,10 @@
910929 static int i2s_trigger(struct snd_pcm_substream *substream,
911930 int cmd, struct snd_soc_dai *dai)
912931 {
932
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
913933 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
914
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
915
- struct i2s_dai *i2s = to_info(rtd->cpu_dai);
934
+ struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
935
+ struct i2s_dai *i2s = to_info(asoc_rtd_to_cpu(rtd, 0));
916936 unsigned long flags;
917937
918938 switch (cmd) {
....@@ -920,10 +940,10 @@
920940 case SNDRV_PCM_TRIGGER_RESUME:
921941 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
922942 pm_runtime_get_sync(dai->dev);
923
- spin_lock_irqsave(i2s->lock, flags);
943
+ spin_lock_irqsave(&priv->lock, flags);
924944
925945 if (config_setup(i2s)) {
926
- spin_unlock_irqrestore(i2s->lock, flags);
946
+ spin_unlock_irqrestore(&priv->lock, flags);
927947 return -EINVAL;
928948 }
929949
....@@ -932,12 +952,12 @@
932952 else
933953 i2s_txctrl(i2s, 1);
934954
935
- spin_unlock_irqrestore(i2s->lock, flags);
955
+ spin_unlock_irqrestore(&priv->lock, flags);
936956 break;
937957 case SNDRV_PCM_TRIGGER_STOP:
938958 case SNDRV_PCM_TRIGGER_SUSPEND:
939959 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
940
- spin_lock_irqsave(i2s->lock, flags);
960
+ spin_lock_irqsave(&priv->lock, flags);
941961
942962 if (capture) {
943963 i2s_rxctrl(i2s, 0);
....@@ -947,7 +967,7 @@
947967 i2s_fifo(i2s, FIC_TXFLUSH);
948968 }
949969
950
- spin_unlock_irqrestore(i2s->lock, flags);
970
+ spin_unlock_irqrestore(&priv->lock, flags);
951971 pm_runtime_put(dai->dev);
952972 break;
953973 }
....@@ -986,32 +1006,32 @@
9861006 static snd_pcm_sframes_t
9871007 i2s_delay(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
9881008 {
1009
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
9891010 struct i2s_dai *i2s = to_info(dai);
990
- u32 reg = readl(i2s->addr + I2SFIC);
1011
+ u32 reg = readl(priv->addr + I2SFIC);
9911012 snd_pcm_sframes_t delay;
992
- const struct samsung_i2s_variant_regs *i2s_regs = i2s->variant_regs;
9931013
9941014 WARN_ON(!pm_runtime_active(dai->dev));
9951015
9961016 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
9971017 delay = FIC_RXCOUNT(reg);
9981018 else if (is_secondary(i2s))
999
- delay = FICS_TXCOUNT(readl(i2s->addr + I2SFICS));
1019
+ delay = FICS_TXCOUNT(readl(priv->addr + I2SFICS));
10001020 else
1001
- delay = (reg >> i2s_regs->ftx0cnt_off) & 0x7f;
1021
+ delay = (reg >> priv->variant_regs->ftx0cnt_off) & 0x7f;
10021022
10031023 return delay;
10041024 }
10051025
10061026 #ifdef CONFIG_PM
1007
-static int i2s_suspend(struct snd_soc_dai *dai)
1027
+static int i2s_suspend(struct snd_soc_component *component)
10081028 {
1009
- return pm_runtime_force_suspend(dai->dev);
1029
+ return pm_runtime_force_suspend(component->dev);
10101030 }
10111031
1012
-static int i2s_resume(struct snd_soc_dai *dai)
1032
+static int i2s_resume(struct snd_soc_component *component)
10131033 {
1014
- return pm_runtime_force_resume(dai->dev);
1034
+ return pm_runtime_force_resume(component->dev);
10151035 }
10161036 #else
10171037 #define i2s_suspend NULL
....@@ -1020,39 +1040,39 @@
10201040
10211041 static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
10221042 {
1043
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
10231044 struct i2s_dai *i2s = to_info(dai);
10241045 struct i2s_dai *other = get_other_dai(i2s);
10251046 unsigned long flags;
10261047
10271048 pm_runtime_get_sync(dai->dev);
10281049
1029
- if (is_secondary(i2s)) { /* If this is probe on the secondary DAI */
1030
- snd_soc_dai_init_dma_data(dai, &other->sec_dai->dma_playback,
1031
- NULL);
1050
+ if (is_secondary(i2s)) {
1051
+ /* If this is probe on the secondary DAI */
1052
+ snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, NULL);
10321053 } else {
10331054 snd_soc_dai_init_dma_data(dai, &i2s->dma_playback,
1034
- &i2s->dma_capture);
1055
+ &i2s->dma_capture);
10351056
1036
- if (i2s->quirks & QUIRK_NEED_RSTCLR)
1037
- writel(CON_RSTCLR, i2s->addr + I2SCON);
1057
+ if (priv->quirks & QUIRK_NEED_RSTCLR)
1058
+ writel(CON_RSTCLR, priv->addr + I2SCON);
10381059
1039
- if (i2s->quirks & QUIRK_SUPPORTS_IDMA)
1040
- idma_reg_addr_init(i2s->addr,
1041
- i2s->sec_dai->idma_playback.addr);
1060
+ if (priv->quirks & QUIRK_SUPPORTS_IDMA)
1061
+ idma_reg_addr_init(priv->addr,
1062
+ other->idma_playback.addr);
10421063 }
10431064
10441065 /* Reset any constraint on RFS and BFS */
10451066 i2s->rfs = 0;
10461067 i2s->bfs = 0;
1047
- i2s->rclk_srcrate = 0;
10481068
1049
- spin_lock_irqsave(i2s->lock, flags);
1069
+ spin_lock_irqsave(&priv->lock, flags);
10501070 i2s_txctrl(i2s, 0);
10511071 i2s_rxctrl(i2s, 0);
10521072 i2s_fifo(i2s, FIC_TXFLUSH);
10531073 i2s_fifo(other, FIC_TXFLUSH);
10541074 i2s_fifo(i2s, FIC_RXFLUSH);
1055
- spin_unlock_irqrestore(i2s->lock, flags);
1075
+ spin_unlock_irqrestore(&priv->lock, flags);
10561076
10571077 /* Gate CDCLK by default */
10581078 if (!is_opened(other))
....@@ -1065,16 +1085,17 @@
10651085
10661086 static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
10671087 {
1068
- struct i2s_dai *i2s = snd_soc_dai_get_drvdata(dai);
1088
+ struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
1089
+ struct i2s_dai *i2s = to_info(dai);
10691090 unsigned long flags;
10701091
10711092 pm_runtime_get_sync(dai->dev);
10721093
10731094 if (!is_secondary(i2s)) {
1074
- if (i2s->quirks & QUIRK_NEED_RSTCLR) {
1075
- spin_lock_irqsave(i2s->lock, flags);
1076
- writel(0, i2s->addr + I2SCON);
1077
- spin_unlock_irqrestore(i2s->lock, flags);
1095
+ if (priv->quirks & QUIRK_NEED_RSTCLR) {
1096
+ spin_lock_irqsave(&priv->lock, flags);
1097
+ writel(0, priv->addr + I2SCON);
1098
+ spin_unlock_irqrestore(&priv->lock, flags);
10781099 }
10791100 }
10801101
....@@ -1094,118 +1115,160 @@
10941115 .delay = i2s_delay,
10951116 };
10961117
1097
-static const struct snd_soc_component_driver samsung_i2s_component = {
1098
- .name = "samsung-i2s",
1118
+static const struct snd_soc_dapm_widget samsung_i2s_widgets[] = {
1119
+ /* Backend DAI */
1120
+ SND_SOC_DAPM_AIF_OUT("Mixer DAI TX", NULL, 0, SND_SOC_NOPM, 0, 0),
1121
+ SND_SOC_DAPM_AIF_IN("Mixer DAI RX", NULL, 0, SND_SOC_NOPM, 0, 0),
1122
+
1123
+ /* Playback Mixer */
1124
+ SND_SOC_DAPM_MIXER("Playback Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
10991125 };
11001126
1101
-#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | \
1102
- SNDRV_PCM_FMTBIT_S16_LE | \
1103
- SNDRV_PCM_FMTBIT_S24_LE)
1127
+static const struct snd_soc_dapm_route samsung_i2s_dapm_routes[] = {
1128
+ { "Playback Mixer", NULL, "Primary Playback" },
1129
+ { "Playback Mixer", NULL, "Secondary Playback" },
11041130
1105
-static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev,
1106
- const struct samsung_i2s_dai_data *i2s_dai_data,
1107
- bool sec)
1131
+ { "Mixer DAI TX", NULL, "Playback Mixer" },
1132
+ { "Primary Capture", NULL, "Mixer DAI RX" },
1133
+};
1134
+
1135
+static const struct snd_soc_component_driver samsung_i2s_component = {
1136
+ .name = "samsung-i2s",
1137
+
1138
+ .dapm_widgets = samsung_i2s_widgets,
1139
+ .num_dapm_widgets = ARRAY_SIZE(samsung_i2s_widgets),
1140
+
1141
+ .dapm_routes = samsung_i2s_dapm_routes,
1142
+ .num_dapm_routes = ARRAY_SIZE(samsung_i2s_dapm_routes),
1143
+
1144
+ .suspend = i2s_suspend,
1145
+ .resume = i2s_resume,
1146
+};
1147
+
1148
+#define SAMSUNG_I2S_FMTS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
1149
+ SNDRV_PCM_FMTBIT_S24_LE)
1150
+
1151
+static int i2s_alloc_dais(struct samsung_i2s_priv *priv,
1152
+ const struct samsung_i2s_dai_data *i2s_dai_data,
1153
+ int num_dais)
11081154 {
1109
- struct i2s_dai *i2s;
1155
+ static const char *dai_names[] = { "samsung-i2s", "samsung-i2s-sec" };
1156
+ static const char *stream_names[] = { "Primary Playback",
1157
+ "Secondary Playback" };
1158
+ struct snd_soc_dai_driver *dai_drv;
1159
+ struct i2s_dai *dai;
1160
+ int i;
11101161
1111
- i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
1112
- if (i2s == NULL)
1113
- return NULL;
1162
+ priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais,
1163
+ sizeof(*dai), GFP_KERNEL);
1164
+ if (!priv->dai)
1165
+ return -ENOMEM;
11141166
1115
- i2s->pdev = pdev;
1116
- i2s->pri_dai = NULL;
1117
- i2s->sec_dai = NULL;
1118
- i2s->i2s_dai_drv.id = 1;
1119
- i2s->i2s_dai_drv.symmetric_rates = 1;
1120
- i2s->i2s_dai_drv.probe = samsung_i2s_dai_probe;
1121
- i2s->i2s_dai_drv.remove = samsung_i2s_dai_remove;
1122
- i2s->i2s_dai_drv.ops = &samsung_i2s_dai_ops;
1123
- i2s->i2s_dai_drv.suspend = i2s_suspend;
1124
- i2s->i2s_dai_drv.resume = i2s_resume;
1125
- i2s->i2s_dai_drv.playback.channels_min = 1;
1126
- i2s->i2s_dai_drv.playback.channels_max = 2;
1127
- i2s->i2s_dai_drv.playback.rates = i2s_dai_data->pcm_rates;
1128
- i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
1167
+ priv->dai_drv = devm_kcalloc(&priv->pdev->dev, num_dais,
1168
+ sizeof(*dai_drv), GFP_KERNEL);
1169
+ if (!priv->dai_drv)
1170
+ return -ENOMEM;
11291171
1130
- if (!sec) {
1131
- i2s->i2s_dai_drv.name = SAMSUNG_I2S_DAI;
1132
- i2s->i2s_dai_drv.capture.channels_min = 1;
1133
- i2s->i2s_dai_drv.capture.channels_max = 2;
1134
- i2s->i2s_dai_drv.capture.rates = i2s_dai_data->pcm_rates;
1135
- i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
1136
- } else {
1137
- i2s->i2s_dai_drv.name = SAMSUNG_I2S_DAI_SEC;
1172
+ for (i = 0; i < num_dais; i++) {
1173
+ dai_drv = &priv->dai_drv[i];
1174
+
1175
+ dai_drv->probe = samsung_i2s_dai_probe;
1176
+ dai_drv->remove = samsung_i2s_dai_remove;
1177
+
1178
+ dai_drv->symmetric_rates = 1;
1179
+ dai_drv->ops = &samsung_i2s_dai_ops;
1180
+
1181
+ dai_drv->playback.channels_min = 1;
1182
+ dai_drv->playback.channels_max = 2;
1183
+ dai_drv->playback.rates = i2s_dai_data->pcm_rates;
1184
+ dai_drv->playback.formats = SAMSUNG_I2S_FMTS;
1185
+ dai_drv->playback.stream_name = stream_names[i];
1186
+
1187
+ dai_drv->id = i + 1;
1188
+ dai_drv->name = dai_names[i];
1189
+
1190
+ priv->dai[i].drv = &priv->dai_drv[i];
1191
+ priv->dai[i].pdev = priv->pdev;
11381192 }
1139
- return i2s;
1193
+
1194
+ /* Initialize capture only for the primary DAI */
1195
+ dai_drv = &priv->dai_drv[SAMSUNG_I2S_ID_PRIMARY - 1];
1196
+
1197
+ dai_drv->capture.channels_min = 1;
1198
+ dai_drv->capture.channels_max = 2;
1199
+ dai_drv->capture.rates = i2s_dai_data->pcm_rates;
1200
+ dai_drv->capture.formats = SAMSUNG_I2S_FMTS;
1201
+ dai_drv->capture.stream_name = "Primary Capture";
1202
+
1203
+ return 0;
11401204 }
11411205
11421206 #ifdef CONFIG_PM
11431207 static int i2s_runtime_suspend(struct device *dev)
11441208 {
1145
- struct i2s_dai *i2s = dev_get_drvdata(dev);
1209
+ struct samsung_i2s_priv *priv = dev_get_drvdata(dev);
11461210
1147
- i2s->suspend_i2smod = readl(i2s->addr + I2SMOD);
1148
- i2s->suspend_i2scon = readl(i2s->addr + I2SCON);
1149
- i2s->suspend_i2spsr = readl(i2s->addr + I2SPSR);
1211
+ priv->suspend_i2smod = readl(priv->addr + I2SMOD);
1212
+ priv->suspend_i2scon = readl(priv->addr + I2SCON);
1213
+ priv->suspend_i2spsr = readl(priv->addr + I2SPSR);
11501214
1151
- if (i2s->op_clk)
1152
- clk_disable_unprepare(i2s->op_clk);
1153
- clk_disable_unprepare(i2s->clk);
1215
+ if (priv->op_clk)
1216
+ clk_disable_unprepare(priv->op_clk);
1217
+ clk_disable_unprepare(priv->clk);
11541218
11551219 return 0;
11561220 }
11571221
11581222 static int i2s_runtime_resume(struct device *dev)
11591223 {
1160
- struct i2s_dai *i2s = dev_get_drvdata(dev);
1224
+ struct samsung_i2s_priv *priv = dev_get_drvdata(dev);
11611225 int ret;
11621226
1163
- ret = clk_prepare_enable(i2s->clk);
1227
+ ret = clk_prepare_enable(priv->clk);
11641228 if (ret)
11651229 return ret;
11661230
1167
- if (i2s->op_clk) {
1168
- ret = clk_prepare_enable(i2s->op_clk);
1231
+ if (priv->op_clk) {
1232
+ ret = clk_prepare_enable(priv->op_clk);
11691233 if (ret) {
1170
- clk_disable_unprepare(i2s->clk);
1234
+ clk_disable_unprepare(priv->clk);
11711235 return ret;
11721236 }
11731237 }
11741238
1175
- writel(i2s->suspend_i2scon, i2s->addr + I2SCON);
1176
- writel(i2s->suspend_i2smod, i2s->addr + I2SMOD);
1177
- writel(i2s->suspend_i2spsr, i2s->addr + I2SPSR);
1239
+ writel(priv->suspend_i2scon, priv->addr + I2SCON);
1240
+ writel(priv->suspend_i2smod, priv->addr + I2SMOD);
1241
+ writel(priv->suspend_i2spsr, priv->addr + I2SPSR);
11781242
11791243 return 0;
11801244 }
11811245 #endif /* CONFIG_PM */
11821246
1183
-static void i2s_unregister_clocks(struct i2s_dai *i2s)
1247
+static void i2s_unregister_clocks(struct samsung_i2s_priv *priv)
11841248 {
11851249 int i;
11861250
1187
- for (i = 0; i < i2s->clk_data.clk_num; i++) {
1188
- if (!IS_ERR(i2s->clk_table[i]))
1189
- clk_unregister(i2s->clk_table[i]);
1251
+ for (i = 0; i < priv->clk_data.clk_num; i++) {
1252
+ if (!IS_ERR(priv->clk_table[i]))
1253
+ clk_unregister(priv->clk_table[i]);
11901254 }
11911255 }
11921256
1193
-static void i2s_unregister_clock_provider(struct platform_device *pdev)
1257
+static void i2s_unregister_clock_provider(struct samsung_i2s_priv *priv)
11941258 {
1195
- struct i2s_dai *i2s = dev_get_drvdata(&pdev->dev);
1196
-
1197
- of_clk_del_provider(pdev->dev.of_node);
1198
- i2s_unregister_clocks(i2s);
1259
+ of_clk_del_provider(priv->pdev->dev.of_node);
1260
+ i2s_unregister_clocks(priv);
11991261 }
12001262
1201
-static int i2s_register_clock_provider(struct platform_device *pdev)
1263
+
1264
+static int i2s_register_clock_provider(struct samsung_i2s_priv *priv)
12021265 {
1266
+
12031267 const char * const i2s_clk_desc[] = { "cdclk", "rclk_src", "prescaler" };
12041268 const char *clk_name[2] = { "i2s_opclk0", "i2s_opclk1" };
12051269 const char *p_names[2] = { NULL };
1206
- struct device *dev = &pdev->dev;
1207
- struct i2s_dai *i2s = dev_get_drvdata(dev);
1208
- const struct samsung_i2s_variant_regs *reg_info = i2s->variant_regs;
1270
+ struct device *dev = &priv->pdev->dev;
1271
+ const struct samsung_i2s_variant_regs *reg_info = priv->variant_regs;
12091272 const char *i2s_clk_name[ARRAY_SIZE(i2s_clk_desc)];
12101273 struct clk *rclksrc;
12111274 int ret, i;
....@@ -1230,110 +1293,170 @@
12301293 return -ENOMEM;
12311294 }
12321295
1233
- if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
1296
+ if (!(priv->quirks & QUIRK_NO_MUXPSR)) {
12341297 /* Activate the prescaler */
1235
- u32 val = readl(i2s->addr + I2SPSR);
1236
- writel(val | PSR_PSREN, i2s->addr + I2SPSR);
1298
+ u32 val = readl(priv->addr + I2SPSR);
1299
+ writel(val | PSR_PSREN, priv->addr + I2SPSR);
12371300
1238
- i2s->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,
1301
+ priv->clk_table[CLK_I2S_RCLK_SRC] = clk_register_mux(dev,
12391302 i2s_clk_name[CLK_I2S_RCLK_SRC], p_names,
12401303 ARRAY_SIZE(p_names),
12411304 CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
1242
- i2s->addr + I2SMOD, reg_info->rclksrc_off,
1243
- 1, 0, i2s->lock);
1305
+ priv->addr + I2SMOD, reg_info->rclksrc_off,
1306
+ 1, 0, &priv->lock);
12441307
1245
- i2s->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,
1308
+ priv->clk_table[CLK_I2S_RCLK_PSR] = clk_register_divider(dev,
12461309 i2s_clk_name[CLK_I2S_RCLK_PSR],
12471310 i2s_clk_name[CLK_I2S_RCLK_SRC],
12481311 CLK_SET_RATE_PARENT,
1249
- i2s->addr + I2SPSR, 8, 6, 0, i2s->lock);
1312
+ priv->addr + I2SPSR, 8, 6, 0, &priv->lock);
12501313
12511314 p_names[0] = i2s_clk_name[CLK_I2S_RCLK_PSR];
1252
- i2s->clk_data.clk_num = 2;
1315
+ priv->clk_data.clk_num = 2;
12531316 }
12541317
1255
- i2s->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev,
1318
+ priv->clk_table[CLK_I2S_CDCLK] = clk_register_gate(dev,
12561319 i2s_clk_name[CLK_I2S_CDCLK], p_names[0],
12571320 CLK_SET_RATE_PARENT,
1258
- i2s->addr + I2SMOD, reg_info->cdclkcon_off,
1259
- CLK_GATE_SET_TO_DISABLE, i2s->lock);
1321
+ priv->addr + I2SMOD, reg_info->cdclkcon_off,
1322
+ CLK_GATE_SET_TO_DISABLE, &priv->lock);
12601323
1261
- i2s->clk_data.clk_num += 1;
1262
- i2s->clk_data.clks = i2s->clk_table;
1324
+ priv->clk_data.clk_num += 1;
1325
+ priv->clk_data.clks = priv->clk_table;
12631326
12641327 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
1265
- &i2s->clk_data);
1328
+ &priv->clk_data);
12661329 if (ret < 0) {
12671330 dev_err(dev, "failed to add clock provider: %d\n", ret);
1268
- i2s_unregister_clocks(i2s);
1331
+ i2s_unregister_clocks(priv);
12691332 }
12701333
12711334 return ret;
1335
+}
1336
+
1337
+/* Create platform device for the secondary PCM */
1338
+static int i2s_create_secondary_device(struct samsung_i2s_priv *priv)
1339
+{
1340
+ struct platform_device *pdev_sec;
1341
+ const char *devname;
1342
+ int ret;
1343
+
1344
+ devname = devm_kasprintf(&priv->pdev->dev, GFP_KERNEL, "%s-sec",
1345
+ dev_name(&priv->pdev->dev));
1346
+ if (!devname)
1347
+ return -ENOMEM;
1348
+
1349
+ pdev_sec = platform_device_alloc(devname, -1);
1350
+ if (!pdev_sec)
1351
+ return -ENOMEM;
1352
+
1353
+ pdev_sec->driver_override = kstrdup("samsung-i2s", GFP_KERNEL);
1354
+
1355
+ ret = platform_device_add(pdev_sec);
1356
+ if (ret < 0) {
1357
+ platform_device_put(pdev_sec);
1358
+ return ret;
1359
+ }
1360
+
1361
+ ret = device_attach(&pdev_sec->dev);
1362
+ if (ret <= 0) {
1363
+ platform_device_unregister(priv->pdev_sec);
1364
+ dev_info(&pdev_sec->dev, "device_attach() failed\n");
1365
+ return ret;
1366
+ }
1367
+
1368
+ priv->pdev_sec = pdev_sec;
1369
+
1370
+ return 0;
1371
+}
1372
+
1373
+static void i2s_delete_secondary_device(struct samsung_i2s_priv *priv)
1374
+{
1375
+ platform_device_unregister(priv->pdev_sec);
1376
+ priv->pdev_sec = NULL;
12721377 }
12731378
12741379 static int samsung_i2s_probe(struct platform_device *pdev)
12751380 {
12761381 struct i2s_dai *pri_dai, *sec_dai = NULL;
12771382 struct s3c_audio_pdata *i2s_pdata = pdev->dev.platform_data;
1278
- struct resource *res;
1279
- u32 regs_base, quirks = 0, idma_addr = 0;
1383
+ u32 regs_base, idma_addr = 0;
12801384 struct device_node *np = pdev->dev.of_node;
12811385 const struct samsung_i2s_dai_data *i2s_dai_data;
1282
- int ret;
1386
+ const struct platform_device_id *id;
1387
+ struct samsung_i2s_priv *priv;
1388
+ struct resource *res;
1389
+ int num_dais, ret;
12831390
1284
- if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
1391
+ if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
12851392 i2s_dai_data = of_device_get_match_data(&pdev->dev);
1286
- else
1287
- i2s_dai_data = (struct samsung_i2s_dai_data *)
1288
- platform_get_device_id(pdev)->driver_data;
1393
+ } else {
1394
+ id = platform_get_device_id(pdev);
12891395
1290
- pri_dai = i2s_alloc_dai(pdev, i2s_dai_data, false);
1291
- if (!pri_dai) {
1292
- dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
1293
- return -ENOMEM;
1396
+ /* Nothing to do if it is the secondary device probe */
1397
+ if (!id)
1398
+ return 0;
1399
+
1400
+ i2s_dai_data = (struct samsung_i2s_dai_data *)id->driver_data;
12941401 }
12951402
1296
- spin_lock_init(&pri_dai->spinlock);
1297
- pri_dai->lock = &pri_dai->spinlock;
1403
+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
1404
+ if (!priv)
1405
+ return -ENOMEM;
12981406
1299
- if (!np) {
1300
- if (i2s_pdata == NULL) {
1301
- dev_err(&pdev->dev, "Can't work without s3c_audio_pdata\n");
1407
+ if (np) {
1408
+ priv->quirks = i2s_dai_data->quirks;
1409
+ } else {
1410
+ if (!i2s_pdata) {
1411
+ dev_err(&pdev->dev, "Missing platform data\n");
13021412 return -EINVAL;
13031413 }
1414
+ priv->quirks = i2s_pdata->type.quirks;
1415
+ }
13041416
1417
+ num_dais = (priv->quirks & QUIRK_SEC_DAI) ? 2 : 1;
1418
+ priv->pdev = pdev;
1419
+ priv->variant_regs = i2s_dai_data->i2s_variant_regs;
1420
+
1421
+ ret = i2s_alloc_dais(priv, i2s_dai_data, num_dais);
1422
+ if (ret < 0)
1423
+ return ret;
1424
+
1425
+ pri_dai = &priv->dai[SAMSUNG_I2S_ID_PRIMARY - 1];
1426
+
1427
+ spin_lock_init(&priv->lock);
1428
+ spin_lock_init(&priv->pcm_lock);
1429
+
1430
+ if (!np) {
13051431 pri_dai->dma_playback.filter_data = i2s_pdata->dma_playback;
13061432 pri_dai->dma_capture.filter_data = i2s_pdata->dma_capture;
13071433 pri_dai->filter = i2s_pdata->dma_filter;
13081434
1309
- quirks = i2s_pdata->type.quirks;
13101435 idma_addr = i2s_pdata->type.idma_addr;
13111436 } else {
1312
- quirks = i2s_dai_data->quirks;
13131437 if (of_property_read_u32(np, "samsung,idma-addr",
13141438 &idma_addr)) {
1315
- if (quirks & QUIRK_SUPPORTS_IDMA) {
1439
+ if (priv->quirks & QUIRK_SUPPORTS_IDMA) {
13161440 dev_info(&pdev->dev, "idma address is not"\
13171441 "specified");
13181442 }
13191443 }
13201444 }
1321
- quirks &= ~(QUIRK_SEC_DAI | QUIRK_SUPPORTS_IDMA);
13221445
13231446 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1324
- pri_dai->addr = devm_ioremap_resource(&pdev->dev, res);
1325
- if (IS_ERR(pri_dai->addr))
1326
- return PTR_ERR(pri_dai->addr);
1447
+ priv->addr = devm_ioremap_resource(&pdev->dev, res);
1448
+ if (IS_ERR(priv->addr))
1449
+ return PTR_ERR(priv->addr);
13271450
13281451 regs_base = res->start;
13291452
1330
- pri_dai->clk = devm_clk_get(&pdev->dev, "iis");
1331
- if (IS_ERR(pri_dai->clk)) {
1453
+ priv->clk = devm_clk_get(&pdev->dev, "iis");
1454
+ if (IS_ERR(priv->clk)) {
13321455 dev_err(&pdev->dev, "Failed to get iis clock\n");
1333
- return PTR_ERR(pri_dai->clk);
1456
+ return PTR_ERR(priv->clk);
13341457 }
13351458
1336
- ret = clk_prepare_enable(pri_dai->clk);
1459
+ ret = clk_prepare_enable(priv->clk);
13371460 if (ret != 0) {
13381461 dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
13391462 return ret;
....@@ -1344,33 +1467,19 @@
13441467 pri_dai->dma_capture.chan_name = "rx";
13451468 pri_dai->dma_playback.addr_width = 4;
13461469 pri_dai->dma_capture.addr_width = 4;
1347
- pri_dai->quirks = quirks;
1348
- pri_dai->variant_regs = i2s_dai_data->i2s_variant_regs;
1470
+ pri_dai->priv = priv;
13491471
1350
- if (quirks & QUIRK_PRI_6CHAN)
1351
- pri_dai->i2s_dai_drv.playback.channels_max = 6;
1472
+ if (priv->quirks & QUIRK_PRI_6CHAN)
1473
+ pri_dai->drv->playback.channels_max = 6;
13521474
13531475 ret = samsung_asoc_dma_platform_register(&pdev->dev, pri_dai->filter,
1354
- NULL, NULL);
1476
+ "tx", "rx", NULL);
13551477 if (ret < 0)
13561478 goto err_disable_clk;
13571479
1358
- ret = devm_snd_soc_register_component(&pdev->dev,
1359
- &samsung_i2s_component,
1360
- &pri_dai->i2s_dai_drv, 1);
1361
- if (ret < 0)
1362
- goto err_disable_clk;
1480
+ if (priv->quirks & QUIRK_SEC_DAI) {
1481
+ sec_dai = &priv->dai[SAMSUNG_I2S_ID_SECONDARY - 1];
13631482
1364
- if (quirks & QUIRK_SEC_DAI) {
1365
- sec_dai = i2s_alloc_dai(pdev, i2s_dai_data, true);
1366
- if (!sec_dai) {
1367
- dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
1368
- ret = -ENOMEM;
1369
- goto err_disable_clk;
1370
- }
1371
-
1372
- sec_dai->lock = &pri_dai->spinlock;
1373
- sec_dai->variant_regs = pri_dai->variant_regs;
13741483 sec_dai->dma_playback.addr = regs_base + I2STXDS;
13751484 sec_dai->dma_playback.chan_name = "tx-sec";
13761485
....@@ -1380,62 +1489,72 @@
13801489 }
13811490
13821491 sec_dai->dma_playback.addr_width = 4;
1383
- sec_dai->addr = pri_dai->addr;
1384
- sec_dai->clk = pri_dai->clk;
1385
- sec_dai->quirks = quirks;
13861492 sec_dai->idma_playback.addr = idma_addr;
13871493 sec_dai->pri_dai = pri_dai;
1494
+ sec_dai->priv = priv;
13881495 pri_dai->sec_dai = sec_dai;
13891496
1390
- ret = samsung_asoc_dma_platform_register(&pdev->dev,
1391
- sec_dai->filter, "tx-sec", NULL);
1497
+ ret = i2s_create_secondary_device(priv);
13921498 if (ret < 0)
13931499 goto err_disable_clk;
13941500
1395
- ret = devm_snd_soc_register_component(&pdev->dev,
1396
- &samsung_i2s_component,
1397
- &sec_dai->i2s_dai_drv, 1);
1501
+ ret = samsung_asoc_dma_platform_register(&priv->pdev_sec->dev,
1502
+ sec_dai->filter, "tx-sec", NULL,
1503
+ &pdev->dev);
13981504 if (ret < 0)
1399
- goto err_disable_clk;
1505
+ goto err_del_sec;
1506
+
14001507 }
14011508
14021509 if (i2s_pdata && i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
14031510 dev_err(&pdev->dev, "Unable to configure gpio\n");
14041511 ret = -EINVAL;
1405
- goto err_disable_clk;
1512
+ goto err_del_sec;
14061513 }
14071514
1408
- dev_set_drvdata(&pdev->dev, pri_dai);
1515
+ dev_set_drvdata(&pdev->dev, priv);
1516
+
1517
+ ret = devm_snd_soc_register_component(&pdev->dev,
1518
+ &samsung_i2s_component,
1519
+ priv->dai_drv, num_dais);
1520
+ if (ret < 0)
1521
+ goto err_del_sec;
14091522
14101523 pm_runtime_set_active(&pdev->dev);
14111524 pm_runtime_enable(&pdev->dev);
14121525
1413
- ret = i2s_register_clock_provider(pdev);
1526
+ ret = i2s_register_clock_provider(priv);
14141527 if (ret < 0)
14151528 goto err_disable_pm;
14161529
1417
- pri_dai->op_clk = clk_get_parent(pri_dai->clk_table[CLK_I2S_RCLK_SRC]);
1530
+ priv->op_clk = clk_get_parent(priv->clk_table[CLK_I2S_RCLK_SRC]);
14181531
14191532 return 0;
14201533
14211534 err_disable_pm:
14221535 pm_runtime_disable(&pdev->dev);
1536
+err_del_sec:
1537
+ i2s_delete_secondary_device(priv);
14231538 err_disable_clk:
1424
- clk_disable_unprepare(pri_dai->clk);
1539
+ clk_disable_unprepare(priv->clk);
14251540 return ret;
14261541 }
14271542
14281543 static int samsung_i2s_remove(struct platform_device *pdev)
14291544 {
1430
- struct i2s_dai *pri_dai;
1545
+ struct samsung_i2s_priv *priv = dev_get_drvdata(&pdev->dev);
14311546
1432
- pri_dai = dev_get_drvdata(&pdev->dev);
1547
+ /* The secondary device has no driver data assigned */
1548
+ if (!priv)
1549
+ return 0;
14331550
14341551 pm_runtime_get_sync(&pdev->dev);
14351552 pm_runtime_disable(&pdev->dev);
14361553
1437
- i2s_unregister_clock_provider(pdev);
1438
- clk_disable_unprepare(pri_dai->clk);
1554
+ i2s_unregister_clock_provider(priv);
1555
+ i2s_delete_secondary_device(priv);
1556
+ clk_disable_unprepare(priv->clk);
1557
+
14391558 pm_runtime_put_noidle(&pdev->dev);
14401559
14411560 return 0;