Version:  2.0.40 2.2.26 2.4.37 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7

Linux/sound/soc/dwc/designware_i2s.c

  1 /*
  2  * ALSA SoC Synopsys I2S Audio Layer
  3  *
  4  * sound/soc/dwc/designware_i2s.c
  5  *
  6  * Copyright (C) 2010 ST Microelectronics
  7  * Rajeev Kumar <rajeevkumar.linux@gmail.com>
  8  *
  9  * This file is licensed under the terms of the GNU General Public
 10  * License version 2. This program is licensed "as is" without any
 11  * warranty of any kind, whether express or implied.
 12  */
 13 
 14 #include <linux/clk.h>
 15 #include <linux/device.h>
 16 #include <linux/init.h>
 17 #include <linux/io.h>
 18 #include <linux/interrupt.h>
 19 #include <linux/module.h>
 20 #include <linux/slab.h>
 21 #include <linux/pm_runtime.h>
 22 #include <sound/designware_i2s.h>
 23 #include <sound/pcm.h>
 24 #include <sound/pcm_params.h>
 25 #include <sound/soc.h>
 26 #include <sound/dmaengine_pcm.h>
 27 
 28 /* common register for all channel */
 29 #define IER             0x000
 30 #define IRER            0x004
 31 #define ITER            0x008
 32 #define CER             0x00C
 33 #define CCR             0x010
 34 #define RXFFR           0x014
 35 #define TXFFR           0x018
 36 
 37 /* I2STxRxRegisters for all channels */
 38 #define LRBR_LTHR(x)    (0x40 * x + 0x020)
 39 #define RRBR_RTHR(x)    (0x40 * x + 0x024)
 40 #define RER(x)          (0x40 * x + 0x028)
 41 #define TER(x)          (0x40 * x + 0x02C)
 42 #define RCR(x)          (0x40 * x + 0x030)
 43 #define TCR(x)          (0x40 * x + 0x034)
 44 #define ISR(x)          (0x40 * x + 0x038)
 45 #define IMR(x)          (0x40 * x + 0x03C)
 46 #define ROR(x)          (0x40 * x + 0x040)
 47 #define TOR(x)          (0x40 * x + 0x044)
 48 #define RFCR(x)         (0x40 * x + 0x048)
 49 #define TFCR(x)         (0x40 * x + 0x04C)
 50 #define RFF(x)          (0x40 * x + 0x050)
 51 #define TFF(x)          (0x40 * x + 0x054)
 52 
 53 /* I2SCOMPRegisters */
 54 #define I2S_COMP_PARAM_2        0x01F0
 55 #define I2S_COMP_PARAM_1        0x01F4
 56 #define I2S_COMP_VERSION        0x01F8
 57 #define I2S_COMP_TYPE           0x01FC
 58 
 59 /*
 60  * Component parameter register fields - define the I2S block's
 61  * configuration.
 62  */
 63 #define COMP1_TX_WORDSIZE_3(r)  (((r) & GENMASK(27, 25)) >> 25)
 64 #define COMP1_TX_WORDSIZE_2(r)  (((r) & GENMASK(24, 22)) >> 22)
 65 #define COMP1_TX_WORDSIZE_1(r)  (((r) & GENMASK(21, 19)) >> 19)
 66 #define COMP1_TX_WORDSIZE_0(r)  (((r) & GENMASK(18, 16)) >> 16)
 67 #define COMP1_TX_CHANNELS(r)    (((r) & GENMASK(10, 9)) >> 9)
 68 #define COMP1_RX_CHANNELS(r)    (((r) & GENMASK(8, 7)) >> 7)
 69 #define COMP1_RX_ENABLED(r)     (((r) & BIT(6)) >> 6)
 70 #define COMP1_TX_ENABLED(r)     (((r) & BIT(5)) >> 5)
 71 #define COMP1_MODE_EN(r)        (((r) & BIT(4)) >> 4)
 72 #define COMP1_FIFO_DEPTH_GLOBAL(r)      (((r) & GENMASK(3, 2)) >> 2)
 73 #define COMP1_APB_DATA_WIDTH(r) (((r) & GENMASK(1, 0)) >> 0)
 74 
 75 #define COMP2_RX_WORDSIZE_3(r)  (((r) & GENMASK(12, 10)) >> 10)
 76 #define COMP2_RX_WORDSIZE_2(r)  (((r) & GENMASK(9, 7)) >> 7)
 77 #define COMP2_RX_WORDSIZE_1(r)  (((r) & GENMASK(5, 3)) >> 3)
 78 #define COMP2_RX_WORDSIZE_0(r)  (((r) & GENMASK(2, 0)) >> 0)
 79 
 80 /* Number of entries in WORDSIZE and DATA_WIDTH parameter registers */
 81 #define COMP_MAX_WORDSIZE       (1 << 3)
 82 #define COMP_MAX_DATA_WIDTH     (1 << 2)
 83 
 84 #define MAX_CHANNEL_NUM         8
 85 #define MIN_CHANNEL_NUM         2
 86 
 87 union dw_i2s_snd_dma_data {
 88         struct i2s_dma_data pd;
 89         struct snd_dmaengine_dai_dma_data dt;
 90 };
 91 
 92 struct dw_i2s_dev {
 93         void __iomem *i2s_base;
 94         struct clk *clk;
 95         int active;
 96         unsigned int capability;
 97         unsigned int quirks;
 98         unsigned int i2s_reg_comp1;
 99         unsigned int i2s_reg_comp2;
100         struct device *dev;
101         u32 ccr;
102         u32 xfer_resolution;
103         u32 fifo_th;
104 
105         /* data related to DMA transfers b/w i2s and DMAC */
106         union dw_i2s_snd_dma_data play_dma_data;
107         union dw_i2s_snd_dma_data capture_dma_data;
108         struct i2s_clk_config_data config;
109         int (*i2s_clk_cfg)(struct i2s_clk_config_data *config);
110 };
111 
112 static inline void i2s_write_reg(void __iomem *io_base, int reg, u32 val)
113 {
114         writel(val, io_base + reg);
115 }
116 
117 static inline u32 i2s_read_reg(void __iomem *io_base, int reg)
118 {
119         return readl(io_base + reg);
120 }
121 
122 static inline void i2s_disable_channels(struct dw_i2s_dev *dev, u32 stream)
123 {
124         u32 i = 0;
125 
126         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
127                 for (i = 0; i < 4; i++)
128                         i2s_write_reg(dev->i2s_base, TER(i), 0);
129         } else {
130                 for (i = 0; i < 4; i++)
131                         i2s_write_reg(dev->i2s_base, RER(i), 0);
132         }
133 }
134 
135 static inline void i2s_clear_irqs(struct dw_i2s_dev *dev, u32 stream)
136 {
137         u32 i = 0;
138 
139         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
140                 for (i = 0; i < 4; i++)
141                         i2s_read_reg(dev->i2s_base, TOR(i));
142         } else {
143                 for (i = 0; i < 4; i++)
144                         i2s_read_reg(dev->i2s_base, ROR(i));
145         }
146 }
147 
148 static void i2s_start(struct dw_i2s_dev *dev,
149                       struct snd_pcm_substream *substream)
150 {
151         struct i2s_clk_config_data *config = &dev->config;
152         u32 i, irq;
153         i2s_write_reg(dev->i2s_base, IER, 1);
154 
155         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
156                 for (i = 0; i < (config->chan_nr / 2); i++) {
157                         irq = i2s_read_reg(dev->i2s_base, IMR(i));
158                         i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x30);
159                 }
160                 i2s_write_reg(dev->i2s_base, ITER, 1);
161         } else {
162                 for (i = 0; i < (config->chan_nr / 2); i++) {
163                         irq = i2s_read_reg(dev->i2s_base, IMR(i));
164                         i2s_write_reg(dev->i2s_base, IMR(i), irq & ~0x03);
165                 }
166                 i2s_write_reg(dev->i2s_base, IRER, 1);
167         }
168 
169         i2s_write_reg(dev->i2s_base, CER, 1);
170 }
171 
172 static void i2s_stop(struct dw_i2s_dev *dev,
173                 struct snd_pcm_substream *substream)
174 {
175         u32 i = 0, irq;
176 
177         i2s_clear_irqs(dev, substream->stream);
178         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
179                 i2s_write_reg(dev->i2s_base, ITER, 0);
180 
181                 for (i = 0; i < 4; i++) {
182                         irq = i2s_read_reg(dev->i2s_base, IMR(i));
183                         i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x30);
184                 }
185         } else {
186                 i2s_write_reg(dev->i2s_base, IRER, 0);
187 
188                 for (i = 0; i < 4; i++) {
189                         irq = i2s_read_reg(dev->i2s_base, IMR(i));
190                         i2s_write_reg(dev->i2s_base, IMR(i), irq | 0x03);
191                 }
192         }
193 
194         if (!dev->active) {
195                 i2s_write_reg(dev->i2s_base, CER, 0);
196                 i2s_write_reg(dev->i2s_base, IER, 0);
197         }
198 }
199 
200 static int dw_i2s_startup(struct snd_pcm_substream *substream,
201                 struct snd_soc_dai *cpu_dai)
202 {
203         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
204         union dw_i2s_snd_dma_data *dma_data = NULL;
205 
206         if (!(dev->capability & DWC_I2S_RECORD) &&
207                         (substream->stream == SNDRV_PCM_STREAM_CAPTURE))
208                 return -EINVAL;
209 
210         if (!(dev->capability & DWC_I2S_PLAY) &&
211                         (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
212                 return -EINVAL;
213 
214         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
215                 dma_data = &dev->play_dma_data;
216         else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
217                 dma_data = &dev->capture_dma_data;
218 
219         snd_soc_dai_set_dma_data(cpu_dai, substream, (void *)dma_data);
220 
221         return 0;
222 }
223 
224 static void dw_i2s_config(struct dw_i2s_dev *dev, int stream)
225 {
226         u32 ch_reg, irq;
227         struct i2s_clk_config_data *config = &dev->config;
228 
229 
230         i2s_disable_channels(dev, stream);
231 
232         for (ch_reg = 0; ch_reg < (config->chan_nr / 2); ch_reg++) {
233                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
234                         i2s_write_reg(dev->i2s_base, TCR(ch_reg),
235                                       dev->xfer_resolution);
236                         i2s_write_reg(dev->i2s_base, TFCR(ch_reg),
237                                       dev->fifo_th - 1);
238                         irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
239                         i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x30);
240                         i2s_write_reg(dev->i2s_base, TER(ch_reg), 1);
241                 } else {
242                         i2s_write_reg(dev->i2s_base, RCR(ch_reg),
243                                       dev->xfer_resolution);
244                         i2s_write_reg(dev->i2s_base, RFCR(ch_reg),
245                                       dev->fifo_th - 1);
246                         irq = i2s_read_reg(dev->i2s_base, IMR(ch_reg));
247                         i2s_write_reg(dev->i2s_base, IMR(ch_reg), irq & ~0x03);
248                         i2s_write_reg(dev->i2s_base, RER(ch_reg), 1);
249                 }
250 
251         }
252 }
253 
254 static int dw_i2s_hw_params(struct snd_pcm_substream *substream,
255                 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
256 {
257         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
258         struct i2s_clk_config_data *config = &dev->config;
259         int ret;
260 
261         switch (params_format(params)) {
262         case SNDRV_PCM_FORMAT_S16_LE:
263                 config->data_width = 16;
264                 dev->ccr = 0x00;
265                 dev->xfer_resolution = 0x02;
266                 break;
267 
268         case SNDRV_PCM_FORMAT_S24_LE:
269                 config->data_width = 24;
270                 dev->ccr = 0x08;
271                 dev->xfer_resolution = 0x04;
272                 break;
273 
274         case SNDRV_PCM_FORMAT_S32_LE:
275                 config->data_width = 32;
276                 dev->ccr = 0x10;
277                 dev->xfer_resolution = 0x05;
278                 break;
279 
280         default:
281                 dev_err(dev->dev, "designware-i2s: unsuppted PCM fmt");
282                 return -EINVAL;
283         }
284 
285         config->chan_nr = params_channels(params);
286 
287         switch (config->chan_nr) {
288         case EIGHT_CHANNEL_SUPPORT:
289         case SIX_CHANNEL_SUPPORT:
290         case FOUR_CHANNEL_SUPPORT:
291         case TWO_CHANNEL_SUPPORT:
292                 break;
293         default:
294                 dev_err(dev->dev, "channel not supported\n");
295                 return -EINVAL;
296         }
297 
298         dw_i2s_config(dev, substream->stream);
299 
300         i2s_write_reg(dev->i2s_base, CCR, dev->ccr);
301 
302         config->sample_rate = params_rate(params);
303 
304         if (dev->capability & DW_I2S_MASTER) {
305                 if (dev->i2s_clk_cfg) {
306                         ret = dev->i2s_clk_cfg(config);
307                         if (ret < 0) {
308                                 dev_err(dev->dev, "runtime audio clk config fail\n");
309                                 return ret;
310                         }
311                 } else {
312                         u32 bitclk = config->sample_rate *
313                                         config->data_width * 2;
314 
315                         ret = clk_set_rate(dev->clk, bitclk);
316                         if (ret) {
317                                 dev_err(dev->dev, "Can't set I2S clock rate: %d\n",
318                                         ret);
319                                 return ret;
320                         }
321                 }
322         }
323         return 0;
324 }
325 
326 static void dw_i2s_shutdown(struct snd_pcm_substream *substream,
327                 struct snd_soc_dai *dai)
328 {
329         snd_soc_dai_set_dma_data(dai, substream, NULL);
330 }
331 
332 static int dw_i2s_prepare(struct snd_pcm_substream *substream,
333                           struct snd_soc_dai *dai)
334 {
335         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
336 
337         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
338                 i2s_write_reg(dev->i2s_base, TXFFR, 1);
339         else
340                 i2s_write_reg(dev->i2s_base, RXFFR, 1);
341 
342         return 0;
343 }
344 
345 static int dw_i2s_trigger(struct snd_pcm_substream *substream,
346                 int cmd, struct snd_soc_dai *dai)
347 {
348         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
349         int ret = 0;
350 
351         switch (cmd) {
352         case SNDRV_PCM_TRIGGER_START:
353         case SNDRV_PCM_TRIGGER_RESUME:
354         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
355                 dev->active++;
356                 i2s_start(dev, substream);
357                 break;
358 
359         case SNDRV_PCM_TRIGGER_STOP:
360         case SNDRV_PCM_TRIGGER_SUSPEND:
361         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
362                 dev->active--;
363                 i2s_stop(dev, substream);
364                 break;
365         default:
366                 ret = -EINVAL;
367                 break;
368         }
369         return ret;
370 }
371 
372 static int dw_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
373 {
374         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
375         int ret = 0;
376 
377         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
378         case SND_SOC_DAIFMT_CBM_CFM:
379                 if (dev->capability & DW_I2S_SLAVE)
380                         ret = 0;
381                 else
382                         ret = -EINVAL;
383                 break;
384         case SND_SOC_DAIFMT_CBS_CFS:
385                 if (dev->capability & DW_I2S_MASTER)
386                         ret = 0;
387                 else
388                         ret = -EINVAL;
389                 break;
390         case SND_SOC_DAIFMT_CBM_CFS:
391         case SND_SOC_DAIFMT_CBS_CFM:
392                 ret = -EINVAL;
393                 break;
394         default:
395                 dev_dbg(dev->dev, "dwc : Invalid master/slave format\n");
396                 ret = -EINVAL;
397                 break;
398         }
399         return ret;
400 }
401 
402 static struct snd_soc_dai_ops dw_i2s_dai_ops = {
403         .startup        = dw_i2s_startup,
404         .shutdown       = dw_i2s_shutdown,
405         .hw_params      = dw_i2s_hw_params,
406         .prepare        = dw_i2s_prepare,
407         .trigger        = dw_i2s_trigger,
408         .set_fmt        = dw_i2s_set_fmt,
409 };
410 
411 static const struct snd_soc_component_driver dw_i2s_component = {
412         .name           = "dw-i2s",
413 };
414 
415 #ifdef CONFIG_PM
416 static int dw_i2s_runtime_suspend(struct device *dev)
417 {
418         struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
419 
420         if (dw_dev->capability & DW_I2S_MASTER)
421                 clk_disable(dw_dev->clk);
422         return 0;
423 }
424 
425 static int dw_i2s_runtime_resume(struct device *dev)
426 {
427         struct dw_i2s_dev *dw_dev = dev_get_drvdata(dev);
428 
429         if (dw_dev->capability & DW_I2S_MASTER)
430                 clk_enable(dw_dev->clk);
431         return 0;
432 }
433 
434 static int dw_i2s_suspend(struct snd_soc_dai *dai)
435 {
436         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
437 
438         if (dev->capability & DW_I2S_MASTER)
439                 clk_disable(dev->clk);
440         return 0;
441 }
442 
443 static int dw_i2s_resume(struct snd_soc_dai *dai)
444 {
445         struct dw_i2s_dev *dev = snd_soc_dai_get_drvdata(dai);
446 
447         if (dev->capability & DW_I2S_MASTER)
448                 clk_enable(dev->clk);
449 
450         if (dai->playback_active)
451                 dw_i2s_config(dev, SNDRV_PCM_STREAM_PLAYBACK);
452         if (dai->capture_active)
453                 dw_i2s_config(dev, SNDRV_PCM_STREAM_CAPTURE);
454         return 0;
455 }
456 
457 #else
458 #define dw_i2s_suspend  NULL
459 #define dw_i2s_resume   NULL
460 #endif
461 
462 /*
463  * The following tables allow a direct lookup of various parameters
464  * defined in the I2S block's configuration in terms of sound system
465  * parameters.  Each table is sized to the number of entries possible
466  * according to the number of configuration bits describing an I2S
467  * block parameter.
468  */
469 
470 /* Maximum bit resolution of a channel - not uniformly spaced */
471 static const u32 fifo_width[COMP_MAX_WORDSIZE] = {
472         12, 16, 20, 24, 32, 0, 0, 0
473 };
474 
475 /* Width of (DMA) bus */
476 static const u32 bus_widths[COMP_MAX_DATA_WIDTH] = {
477         DMA_SLAVE_BUSWIDTH_1_BYTE,
478         DMA_SLAVE_BUSWIDTH_2_BYTES,
479         DMA_SLAVE_BUSWIDTH_4_BYTES,
480         DMA_SLAVE_BUSWIDTH_UNDEFINED
481 };
482 
483 /* PCM format to support channel resolution */
484 static const u32 formats[COMP_MAX_WORDSIZE] = {
485         SNDRV_PCM_FMTBIT_S16_LE,
486         SNDRV_PCM_FMTBIT_S16_LE,
487         SNDRV_PCM_FMTBIT_S24_LE,
488         SNDRV_PCM_FMTBIT_S24_LE,
489         SNDRV_PCM_FMTBIT_S32_LE,
490         0,
491         0,
492         0
493 };
494 
495 static int dw_configure_dai(struct dw_i2s_dev *dev,
496                                    struct snd_soc_dai_driver *dw_i2s_dai,
497                                    unsigned int rates)
498 {
499         /*
500          * Read component parameter registers to extract
501          * the I2S block's configuration.
502          */
503         u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
504         u32 comp2 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp2);
505         u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
506         u32 idx;
507 
508         if (dev->capability & DWC_I2S_RECORD &&
509                         dev->quirks & DW_I2S_QUIRK_COMP_PARAM1)
510                 comp1 = comp1 & ~BIT(5);
511 
512         if (COMP1_TX_ENABLED(comp1)) {
513                 dev_dbg(dev->dev, " designware: play supported\n");
514                 idx = COMP1_TX_WORDSIZE_0(comp1);
515                 if (WARN_ON(idx >= ARRAY_SIZE(formats)))
516                         return -EINVAL;
517                 dw_i2s_dai->playback.channels_min = MIN_CHANNEL_NUM;
518                 dw_i2s_dai->playback.channels_max =
519                                 1 << (COMP1_TX_CHANNELS(comp1) + 1);
520                 dw_i2s_dai->playback.formats = formats[idx];
521                 dw_i2s_dai->playback.rates = rates;
522         }
523 
524         if (COMP1_RX_ENABLED(comp1)) {
525                 dev_dbg(dev->dev, "designware: record supported\n");
526                 idx = COMP2_RX_WORDSIZE_0(comp2);
527                 if (WARN_ON(idx >= ARRAY_SIZE(formats)))
528                         return -EINVAL;
529                 dw_i2s_dai->capture.channels_min = MIN_CHANNEL_NUM;
530                 dw_i2s_dai->capture.channels_max =
531                                 1 << (COMP1_RX_CHANNELS(comp1) + 1);
532                 dw_i2s_dai->capture.formats = formats[idx];
533                 dw_i2s_dai->capture.rates = rates;
534         }
535 
536         if (COMP1_MODE_EN(comp1)) {
537                 dev_dbg(dev->dev, "designware: i2s master mode supported\n");
538                 dev->capability |= DW_I2S_MASTER;
539         } else {
540                 dev_dbg(dev->dev, "designware: i2s slave mode supported\n");
541                 dev->capability |= DW_I2S_SLAVE;
542         }
543 
544         dev->fifo_th = fifo_depth / 2;
545         return 0;
546 }
547 
548 static int dw_configure_dai_by_pd(struct dw_i2s_dev *dev,
549                                    struct snd_soc_dai_driver *dw_i2s_dai,
550                                    struct resource *res,
551                                    const struct i2s_platform_data *pdata)
552 {
553         u32 comp1 = i2s_read_reg(dev->i2s_base, dev->i2s_reg_comp1);
554         u32 idx = COMP1_APB_DATA_WIDTH(comp1);
555         int ret;
556 
557         if (WARN_ON(idx >= ARRAY_SIZE(bus_widths)))
558                 return -EINVAL;
559 
560         ret = dw_configure_dai(dev, dw_i2s_dai, pdata->snd_rates);
561         if (ret < 0)
562                 return ret;
563 
564         /* Set DMA slaves info */
565         dev->play_dma_data.pd.data = pdata->play_dma_data;
566         dev->capture_dma_data.pd.data = pdata->capture_dma_data;
567         dev->play_dma_data.pd.addr = res->start + I2S_TXDMA;
568         dev->capture_dma_data.pd.addr = res->start + I2S_RXDMA;
569         dev->play_dma_data.pd.max_burst = 16;
570         dev->capture_dma_data.pd.max_burst = 16;
571         dev->play_dma_data.pd.addr_width = bus_widths[idx];
572         dev->capture_dma_data.pd.addr_width = bus_widths[idx];
573         dev->play_dma_data.pd.filter = pdata->filter;
574         dev->capture_dma_data.pd.filter = pdata->filter;
575 
576         return 0;
577 }
578 
579 static int dw_configure_dai_by_dt(struct dw_i2s_dev *dev,
580                                    struct snd_soc_dai_driver *dw_i2s_dai,
581                                    struct resource *res)
582 {
583         u32 comp1 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_1);
584         u32 comp2 = i2s_read_reg(dev->i2s_base, I2S_COMP_PARAM_2);
585         u32 fifo_depth = 1 << (1 + COMP1_FIFO_DEPTH_GLOBAL(comp1));
586         u32 idx = COMP1_APB_DATA_WIDTH(comp1);
587         u32 idx2;
588         int ret;
589 
590         if (WARN_ON(idx >= ARRAY_SIZE(bus_widths)))
591                 return -EINVAL;
592 
593         ret = dw_configure_dai(dev, dw_i2s_dai, SNDRV_PCM_RATE_8000_192000);
594         if (ret < 0)
595                 return ret;
596 
597         if (COMP1_TX_ENABLED(comp1)) {
598                 idx2 = COMP1_TX_WORDSIZE_0(comp1);
599 
600                 dev->capability |= DWC_I2S_PLAY;
601                 dev->play_dma_data.dt.addr = res->start + I2S_TXDMA;
602                 dev->play_dma_data.dt.addr_width = bus_widths[idx];
603                 dev->play_dma_data.dt.chan_name = "TX";
604                 dev->play_dma_data.dt.fifo_size = fifo_depth *
605                         (fifo_width[idx2]) >> 8;
606                 dev->play_dma_data.dt.maxburst = 16;
607         }
608         if (COMP1_RX_ENABLED(comp1)) {
609                 idx2 = COMP2_RX_WORDSIZE_0(comp2);
610 
611                 dev->capability |= DWC_I2S_RECORD;
612                 dev->capture_dma_data.dt.addr = res->start + I2S_RXDMA;
613                 dev->capture_dma_data.dt.addr_width = bus_widths[idx];
614                 dev->capture_dma_data.dt.chan_name = "RX";
615                 dev->capture_dma_data.dt.fifo_size = fifo_depth *
616                         (fifo_width[idx2] >> 8);
617                 dev->capture_dma_data.dt.maxburst = 16;
618         }
619 
620         return 0;
621 
622 }
623 
624 static int dw_i2s_probe(struct platform_device *pdev)
625 {
626         const struct i2s_platform_data *pdata = pdev->dev.platform_data;
627         struct dw_i2s_dev *dev;
628         struct resource *res;
629         int ret;
630         struct snd_soc_dai_driver *dw_i2s_dai;
631         const char *clk_id;
632 
633         dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
634         if (!dev) {
635                 dev_warn(&pdev->dev, "kzalloc fail\n");
636                 return -ENOMEM;
637         }
638 
639         dw_i2s_dai = devm_kzalloc(&pdev->dev, sizeof(*dw_i2s_dai), GFP_KERNEL);
640         if (!dw_i2s_dai)
641                 return -ENOMEM;
642 
643         dw_i2s_dai->ops = &dw_i2s_dai_ops;
644         dw_i2s_dai->suspend = dw_i2s_suspend;
645         dw_i2s_dai->resume = dw_i2s_resume;
646 
647         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
648         dev->i2s_base = devm_ioremap_resource(&pdev->dev, res);
649         if (IS_ERR(dev->i2s_base))
650                 return PTR_ERR(dev->i2s_base);
651 
652         dev->dev = &pdev->dev;
653 
654         dev->i2s_reg_comp1 = I2S_COMP_PARAM_1;
655         dev->i2s_reg_comp2 = I2S_COMP_PARAM_2;
656         if (pdata) {
657                 dev->capability = pdata->cap;
658                 clk_id = NULL;
659                 dev->quirks = pdata->quirks;
660                 if (dev->quirks & DW_I2S_QUIRK_COMP_REG_OFFSET) {
661                         dev->i2s_reg_comp1 = pdata->i2s_reg_comp1;
662                         dev->i2s_reg_comp2 = pdata->i2s_reg_comp2;
663                 }
664                 ret = dw_configure_dai_by_pd(dev, dw_i2s_dai, res, pdata);
665         } else {
666                 clk_id = "i2sclk";
667                 ret = dw_configure_dai_by_dt(dev, dw_i2s_dai, res);
668         }
669         if (ret < 0)
670                 return ret;
671 
672         if (dev->capability & DW_I2S_MASTER) {
673                 if (pdata) {
674                         dev->i2s_clk_cfg = pdata->i2s_clk_cfg;
675                         if (!dev->i2s_clk_cfg) {
676                                 dev_err(&pdev->dev, "no clock configure method\n");
677                                 return -ENODEV;
678                         }
679                 }
680                 dev->clk = devm_clk_get(&pdev->dev, clk_id);
681 
682                 if (IS_ERR(dev->clk))
683                         return PTR_ERR(dev->clk);
684 
685                 ret = clk_prepare_enable(dev->clk);
686                 if (ret < 0)
687                         return ret;
688         }
689 
690         dev_set_drvdata(&pdev->dev, dev);
691         ret = devm_snd_soc_register_component(&pdev->dev, &dw_i2s_component,
692                                          dw_i2s_dai, 1);
693         if (ret != 0) {
694                 dev_err(&pdev->dev, "not able to register dai\n");
695                 goto err_clk_disable;
696         }
697 
698         if (!pdata) {
699                 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
700                 if (ret) {
701                         dev_err(&pdev->dev,
702                                 "Could not register PCM: %d\n", ret);
703                         goto err_clk_disable;
704                 }
705         }
706         pm_runtime_enable(&pdev->dev);
707         return 0;
708 
709 err_clk_disable:
710         if (dev->capability & DW_I2S_MASTER)
711                 clk_disable_unprepare(dev->clk);
712         return ret;
713 }
714 
715 static int dw_i2s_remove(struct platform_device *pdev)
716 {
717         struct dw_i2s_dev *dev = dev_get_drvdata(&pdev->dev);
718 
719         if (dev->capability & DW_I2S_MASTER)
720                 clk_disable_unprepare(dev->clk);
721 
722         pm_runtime_disable(&pdev->dev);
723         return 0;
724 }
725 
726 #ifdef CONFIG_OF
727 static const struct of_device_id dw_i2s_of_match[] = {
728         { .compatible = "snps,designware-i2s",   },
729         {},
730 };
731 
732 MODULE_DEVICE_TABLE(of, dw_i2s_of_match);
733 #endif
734 
735 static const struct dev_pm_ops dwc_pm_ops = {
736         SET_RUNTIME_PM_OPS(dw_i2s_runtime_suspend, dw_i2s_runtime_resume, NULL)
737 };
738 
739 static struct platform_driver dw_i2s_driver = {
740         .probe          = dw_i2s_probe,
741         .remove         = dw_i2s_remove,
742         .driver         = {
743                 .name   = "designware-i2s",
744                 .of_match_table = of_match_ptr(dw_i2s_of_match),
745                 .pm = &dwc_pm_ops,
746         },
747 };
748 
749 module_platform_driver(dw_i2s_driver);
750 
751 MODULE_AUTHOR("Rajeev Kumar <rajeevkumar.linux@gmail.com>");
752 MODULE_DESCRIPTION("DESIGNWARE I2S SoC Interface");
753 MODULE_LICENSE("GPL");
754 MODULE_ALIAS("platform:designware_i2s");
755 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us