Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
[platform/kernel/linux-starfive.git] / sound / soc / intel / keembay / kmb_platform.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 //
3 // Copyright (C) 2020 Intel Corporation.
4 //
5 // Intel KeemBay Platform driver.
6 //
7
8 #include <linux/clk.h>
9 #include <linux/io.h>
10 #include <linux/module.h>
11 #include <sound/pcm.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include "kmb_platform.h"
15
16 #define PERIODS_MIN             2
17 #define PERIODS_MAX             48
18 #define PERIOD_BYTES_MIN        4096
19 #define BUFFER_BYTES_MAX        (PERIODS_MAX * PERIOD_BYTES_MIN)
20 #define TDM_OPERATION           1
21 #define I2S_OPERATION           0
22 #define DATA_WIDTH_CONFIG_BIT   6
23 #define TDM_CHANNEL_CONFIG_BIT  3
24
25 static const struct snd_pcm_hardware kmb_pcm_hardware = {
26         .info = SNDRV_PCM_INFO_INTERLEAVED |
27                 SNDRV_PCM_INFO_MMAP |
28                 SNDRV_PCM_INFO_MMAP_VALID |
29                 SNDRV_PCM_INFO_BATCH |
30                 SNDRV_PCM_INFO_BLOCK_TRANSFER,
31         .rates = SNDRV_PCM_RATE_8000 |
32                  SNDRV_PCM_RATE_16000 |
33                  SNDRV_PCM_RATE_48000,
34         .rate_min = 8000,
35         .rate_max = 48000,
36         .formats = SNDRV_PCM_FMTBIT_S16_LE |
37                    SNDRV_PCM_FMTBIT_S24_LE |
38                    SNDRV_PCM_FMTBIT_S32_LE,
39         .channels_min = 2,
40         .channels_max = 2,
41         .buffer_bytes_max = BUFFER_BYTES_MAX,
42         .period_bytes_min = PERIOD_BYTES_MIN,
43         .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
44         .periods_min = PERIODS_MIN,
45         .periods_max = PERIODS_MAX,
46         .fifo_size = 16,
47 };
48
49 static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s,
50                                   struct snd_pcm_runtime *runtime,
51                                   unsigned int tx_ptr, bool *period_elapsed)
52 {
53         unsigned int period_pos = tx_ptr % runtime->period_size;
54         void __iomem *i2s_base = kmb_i2s->i2s_base;
55         void *buf = runtime->dma_area;
56         int i;
57
58         /* KMB i2s uses two separate L/R FIFO */
59         for (i = 0; i < kmb_i2s->fifo_th; i++) {
60                 if (kmb_i2s->config.data_width == 16) {
61                         writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
62                         writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
63                 } else {
64                         writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0));
65                         writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0));
66                 }
67
68                 period_pos++;
69
70                 if (++tx_ptr >= runtime->buffer_size)
71                         tx_ptr = 0;
72         }
73
74         *period_elapsed = period_pos >= runtime->period_size;
75
76         return tx_ptr;
77 }
78
79 static unsigned int kmb_pcm_rx_fn(struct kmb_i2s_info *kmb_i2s,
80                                   struct snd_pcm_runtime *runtime,
81                                   unsigned int rx_ptr, bool *period_elapsed)
82 {
83         unsigned int period_pos = rx_ptr % runtime->period_size;
84         void __iomem *i2s_base = kmb_i2s->i2s_base;
85         void *buf = runtime->dma_area;
86         int i;
87
88         /* KMB i2s uses two separate L/R FIFO */
89         for (i = 0; i < kmb_i2s->fifo_th; i++) {
90                 if (kmb_i2s->config.data_width == 16) {
91                         ((u16(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0));
92                         ((u16(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0));
93                 } else {
94                         ((u32(*)[2])buf)[rx_ptr][0] = readl(i2s_base + LRBR_LTHR(0));
95                         ((u32(*)[2])buf)[rx_ptr][1] = readl(i2s_base + RRBR_RTHR(0));
96                 }
97
98                 period_pos++;
99
100                 if (++rx_ptr >= runtime->buffer_size)
101                         rx_ptr = 0;
102         }
103
104         *period_elapsed = period_pos >= runtime->period_size;
105
106         return rx_ptr;
107 }
108
109 static inline void kmb_i2s_disable_channels(struct kmb_i2s_info *kmb_i2s,
110                                             u32 stream)
111 {
112         u32 i;
113
114         /* Disable all channels regardless of configuration*/
115         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
116                 for (i = 0; i < MAX_ISR; i++)
117                         writel(0, kmb_i2s->i2s_base + TER(i));
118         } else {
119                 for (i = 0; i < MAX_ISR; i++)
120                         writel(0, kmb_i2s->i2s_base + RER(i));
121         }
122 }
123
124 static inline void kmb_i2s_clear_irqs(struct kmb_i2s_info *kmb_i2s, u32 stream)
125 {
126         struct i2s_clk_config_data *config = &kmb_i2s->config;
127         u32 i;
128
129         if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
130                 for (i = 0; i < config->chan_nr / 2; i++)
131                         readl(kmb_i2s->i2s_base + TOR(i));
132         } else {
133                 for (i = 0; i < config->chan_nr / 2; i++)
134                         readl(kmb_i2s->i2s_base + ROR(i));
135         }
136 }
137
138 static inline void kmb_i2s_irq_trigger(struct kmb_i2s_info *kmb_i2s,
139                                        u32 stream, int chan_nr, bool trigger)
140 {
141         u32 i, irq;
142         u32 flag;
143
144         if (stream == SNDRV_PCM_STREAM_PLAYBACK)
145                 flag = TX_INT_FLAG;
146         else
147                 flag = RX_INT_FLAG;
148
149         for (i = 0; i < chan_nr / 2; i++) {
150                 irq = readl(kmb_i2s->i2s_base + IMR(i));
151
152                 if (trigger)
153                         irq = irq & ~flag;
154                 else
155                         irq = irq | flag;
156
157                 writel(irq, kmb_i2s->i2s_base + IMR(i));
158         }
159 }
160
161 static void kmb_pcm_operation(struct kmb_i2s_info *kmb_i2s, bool playback)
162 {
163         struct snd_pcm_substream *substream;
164         bool period_elapsed;
165         unsigned int new_ptr;
166         unsigned int ptr;
167
168         if (playback)
169                 substream = kmb_i2s->tx_substream;
170         else
171                 substream = kmb_i2s->rx_substream;
172
173         if (!substream || !snd_pcm_running(substream))
174                 return;
175
176         if (playback) {
177                 ptr = kmb_i2s->tx_ptr;
178                 new_ptr = kmb_pcm_tx_fn(kmb_i2s, substream->runtime,
179                                         ptr, &period_elapsed);
180                 cmpxchg(&kmb_i2s->tx_ptr, ptr, new_ptr);
181         } else {
182                 ptr = kmb_i2s->rx_ptr;
183                 new_ptr = kmb_pcm_rx_fn(kmb_i2s, substream->runtime,
184                                         ptr, &period_elapsed);
185                 cmpxchg(&kmb_i2s->rx_ptr, ptr, new_ptr);
186         }
187
188         if (period_elapsed)
189                 snd_pcm_period_elapsed(substream);
190 }
191
192 static int kmb_pcm_open(struct snd_soc_component *component,
193                         struct snd_pcm_substream *substream)
194 {
195         struct snd_pcm_runtime *runtime = substream->runtime;
196         struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
197         struct kmb_i2s_info *kmb_i2s;
198
199         kmb_i2s = snd_soc_dai_get_drvdata(asoc_rtd_to_cpu(rtd, 0));
200         snd_soc_set_runtime_hwparams(substream, &kmb_pcm_hardware);
201         snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
202         runtime->private_data = kmb_i2s;
203
204         return 0;
205 }
206
207 static int kmb_pcm_trigger(struct snd_soc_component *component,
208                            struct snd_pcm_substream *substream, int cmd)
209 {
210         struct snd_pcm_runtime *runtime = substream->runtime;
211         struct kmb_i2s_info *kmb_i2s = runtime->private_data;
212
213         switch (cmd) {
214         case SNDRV_PCM_TRIGGER_START:
215                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
216                         kmb_i2s->tx_ptr = 0;
217                         kmb_i2s->tx_substream = substream;
218                 } else {
219                         kmb_i2s->rx_ptr = 0;
220                         kmb_i2s->rx_substream = substream;
221                 }
222                 break;
223         case SNDRV_PCM_TRIGGER_STOP:
224                 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
225                         kmb_i2s->tx_substream = NULL;
226                 else
227                         kmb_i2s->rx_substream = NULL;
228                 break;
229         default:
230                 return -EINVAL;
231         }
232
233         return 0;
234 }
235
236 static irqreturn_t kmb_i2s_irq_handler(int irq, void *dev_id)
237 {
238         struct kmb_i2s_info *kmb_i2s = dev_id;
239         struct i2s_clk_config_data *config = &kmb_i2s->config;
240         irqreturn_t ret = IRQ_NONE;
241         u32 isr[4];
242         int i;
243
244         for (i = 0; i < config->chan_nr / 2; i++)
245                 isr[i] = readl(kmb_i2s->i2s_base + ISR(i));
246
247         kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
248         kmb_i2s_clear_irqs(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);
249
250         for (i = 0; i < config->chan_nr / 2; i++) {
251                 /*
252                  * Check if TX fifo is empty. If empty fill FIFO with samples
253                  */
254                 if ((isr[i] & ISR_TXFE)) {
255                         kmb_pcm_operation(kmb_i2s, true);
256                         ret = IRQ_HANDLED;
257                 }
258                 /*
259                  * Data available. Retrieve samples from FIFO
260                  */
261                 if ((isr[i] & ISR_RXDA)) {
262                         kmb_pcm_operation(kmb_i2s, false);
263                         ret = IRQ_HANDLED;
264                 }
265                 /* Error Handling: TX */
266                 if (isr[i] & ISR_TXFO) {
267                         dev_dbg(kmb_i2s->dev, "TX overrun (ch_id=%d)\n", i);
268                         ret = IRQ_HANDLED;
269                 }
270                 /* Error Handling: RX */
271                 if (isr[i] & ISR_RXFO) {
272                         dev_dbg(kmb_i2s->dev, "RX overrun (ch_id=%d)\n", i);
273                         ret = IRQ_HANDLED;
274                 }
275         }
276
277         return ret;
278 }
279
280 static int kmb_platform_pcm_new(struct snd_soc_component *component,
281                                 struct snd_soc_pcm_runtime *soc_runtime)
282 {
283         size_t size = kmb_pcm_hardware.buffer_bytes_max;
284         /* Use SNDRV_DMA_TYPE_CONTINUOUS as KMB doesn't use PCI sg buffer */
285         snd_pcm_set_managed_buffer_all(soc_runtime->pcm,
286                                        SNDRV_DMA_TYPE_CONTINUOUS,
287                                        NULL, size, size);
288         return 0;
289 }
290
291 static snd_pcm_uframes_t kmb_pcm_pointer(struct snd_soc_component *component,
292                                          struct snd_pcm_substream *substream)
293 {
294         struct snd_pcm_runtime *runtime = substream->runtime;
295         struct kmb_i2s_info *kmb_i2s = runtime->private_data;
296         snd_pcm_uframes_t pos;
297
298         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
299                 pos = kmb_i2s->tx_ptr;
300         else
301                 pos = kmb_i2s->rx_ptr;
302
303         return pos < runtime->buffer_size ? pos : 0;
304 }
305
306 static const struct snd_soc_component_driver kmb_component = {
307         .name           = "kmb",
308         .pcm_construct  = kmb_platform_pcm_new,
309         .open           = kmb_pcm_open,
310         .trigger        = kmb_pcm_trigger,
311         .pointer        = kmb_pcm_pointer,
312 };
313
314 static void kmb_i2s_start(struct kmb_i2s_info *kmb_i2s,
315                           struct snd_pcm_substream *substream)
316 {
317         struct i2s_clk_config_data *config = &kmb_i2s->config;
318
319         /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
320         writel(1, kmb_i2s->i2s_base + IER);
321
322         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
323                 writel(1, kmb_i2s->i2s_base + ITER);
324         else
325                 writel(1, kmb_i2s->i2s_base + IRER);
326
327         kmb_i2s_irq_trigger(kmb_i2s, substream->stream, config->chan_nr, true);
328
329         if (kmb_i2s->master)
330                 writel(1, kmb_i2s->i2s_base + CER);
331         else
332                 writel(0, kmb_i2s->i2s_base + CER);
333 }
334
335 static void kmb_i2s_stop(struct kmb_i2s_info *kmb_i2s,
336                          struct snd_pcm_substream *substream)
337 {
338         /* I2S Programming sequence in Keem_Bay_VPU_DB_v1.1 */
339         kmb_i2s_clear_irqs(kmb_i2s, substream->stream);
340
341         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
342                 writel(0, kmb_i2s->i2s_base + ITER);
343         else
344                 writel(0, kmb_i2s->i2s_base + IRER);
345
346         kmb_i2s_irq_trigger(kmb_i2s, substream->stream, 8, false);
347
348         if (!kmb_i2s->active) {
349                 writel(0, kmb_i2s->i2s_base + CER);
350                 writel(0, kmb_i2s->i2s_base + IER);
351         }
352 }
353
354 static void kmb_disable_clk(void *clk)
355 {
356         clk_disable_unprepare(clk);
357 }
358
359 static int kmb_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
360 {
361         struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
362         int ret;
363
364         switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
365         case SND_SOC_DAIFMT_CBM_CFM:
366                 kmb_i2s->master = false;
367                 ret = 0;
368                 break;
369         case SND_SOC_DAIFMT_CBS_CFS:
370                 writel(MASTER_MODE, kmb_i2s->pss_base + I2S_GEN_CFG_0);
371
372                 ret = clk_prepare_enable(kmb_i2s->clk_i2s);
373                 if (ret < 0)
374                         return ret;
375
376                 ret = devm_add_action_or_reset(kmb_i2s->dev, kmb_disable_clk,
377                                                kmb_i2s->clk_i2s);
378                 if (ret)
379                         return ret;
380
381                 kmb_i2s->master = true;
382                 break;
383         default:
384                 return -EINVAL;
385         }
386
387         return ret;
388 }
389
390 static int kmb_dai_trigger(struct snd_pcm_substream *substream,
391                            int cmd, struct snd_soc_dai *cpu_dai)
392 {
393         struct kmb_i2s_info *kmb_i2s  = snd_soc_dai_get_drvdata(cpu_dai);
394
395         switch (cmd) {
396         case SNDRV_PCM_TRIGGER_START:
397                 /* Keep track of i2s activity before turn off
398                  * the i2s interface
399                  */
400                 kmb_i2s->active++;
401                 kmb_i2s_start(kmb_i2s, substream);
402                 break;
403         case SNDRV_PCM_TRIGGER_STOP:
404                 kmb_i2s->active--;
405                 kmb_i2s_stop(kmb_i2s, substream);
406                 break;
407         default:
408                 return  -EINVAL;
409         }
410
411         return 0;
412 }
413
414 static void kmb_i2s_config(struct kmb_i2s_info *kmb_i2s, int stream)
415 {
416         struct i2s_clk_config_data *config = &kmb_i2s->config;
417         u32 ch_reg;
418
419         kmb_i2s_disable_channels(kmb_i2s, stream);
420
421         for (ch_reg = 0; ch_reg < config->chan_nr / 2; ch_reg++) {
422                 if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
423                         writel(kmb_i2s->xfer_resolution,
424                                kmb_i2s->i2s_base + TCR(ch_reg));
425
426                         writel(kmb_i2s->fifo_th - 1,
427                                kmb_i2s->i2s_base + TFCR(ch_reg));
428
429                         writel(1, kmb_i2s->i2s_base + TER(ch_reg));
430                 } else {
431                         writel(kmb_i2s->xfer_resolution,
432                                kmb_i2s->i2s_base + RCR(ch_reg));
433
434                         writel(kmb_i2s->fifo_th - 1,
435                                kmb_i2s->i2s_base + RFCR(ch_reg));
436
437                         writel(1, kmb_i2s->i2s_base + RER(ch_reg));
438                 }
439         }
440 }
441
442 static int kmb_dai_hw_params(struct snd_pcm_substream *substream,
443                              struct snd_pcm_hw_params *hw_params,
444                              struct snd_soc_dai *cpu_dai)
445 {
446         struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
447         struct i2s_clk_config_data *config = &kmb_i2s->config;
448         u32 register_val, write_val;
449         int ret;
450
451         switch (params_format(hw_params)) {
452         case SNDRV_PCM_FORMAT_S16_LE:
453                 config->data_width = 16;
454                 kmb_i2s->ccr = 0x00;
455                 kmb_i2s->xfer_resolution = 0x02;
456                 break;
457         case SNDRV_PCM_FORMAT_S24_LE:
458                 config->data_width = 24;
459                 kmb_i2s->ccr = 0x08;
460                 kmb_i2s->xfer_resolution = 0x04;
461                 break;
462         case SNDRV_PCM_FORMAT_S32_LE:
463                 config->data_width = 32;
464                 kmb_i2s->ccr = 0x10;
465                 kmb_i2s->xfer_resolution = 0x05;
466                 break;
467         default:
468                 dev_err(kmb_i2s->dev, "kmb: unsupported PCM fmt");
469                 return -EINVAL;
470         }
471
472         config->chan_nr = params_channels(hw_params);
473
474         switch (config->chan_nr) {
475         /* TODO: This switch case will handle up to TDM8 in the near future */
476         case TWO_CHANNEL_SUPPORT:
477                 write_val = ((config->chan_nr / 2) << TDM_CHANNEL_CONFIG_BIT) |
478                                 (config->data_width << DATA_WIDTH_CONFIG_BIT) |
479                                 MASTER_MODE | I2S_OPERATION;
480
481                 writel(write_val, kmb_i2s->pss_base + I2S_GEN_CFG_0);
482
483                 register_val = readl(kmb_i2s->pss_base + I2S_GEN_CFG_0);
484                 dev_dbg(kmb_i2s->dev, "pss register = 0x%X", register_val);
485                 break;
486         default:
487                 dev_dbg(kmb_i2s->dev, "channel not supported\n");
488                 return -EINVAL;
489         }
490
491         kmb_i2s_config(kmb_i2s, substream->stream);
492
493         writel(kmb_i2s->ccr, kmb_i2s->i2s_base + CCR);
494
495         config->sample_rate = params_rate(hw_params);
496
497         if (kmb_i2s->master) {
498                 /* Only 2 ch supported in Master mode */
499                 u32 bitclk = config->sample_rate * config->data_width * 2;
500
501                 ret = clk_set_rate(kmb_i2s->clk_i2s, bitclk);
502                 if (ret) {
503                         dev_err(kmb_i2s->dev,
504                                 "Can't set I2S clock rate: %d\n", ret);
505                         return ret;
506                 }
507         }
508
509         return 0;
510 }
511
512 static int kmb_dai_prepare(struct snd_pcm_substream *substream,
513                            struct snd_soc_dai *cpu_dai)
514 {
515         struct kmb_i2s_info *kmb_i2s = snd_soc_dai_get_drvdata(cpu_dai);
516
517         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
518                 writel(1, kmb_i2s->i2s_base + TXFFR);
519         else
520                 writel(1, kmb_i2s->i2s_base + RXFFR);
521
522         return 0;
523 }
524
525 static struct snd_soc_dai_ops kmb_dai_ops = {
526         .trigger        = kmb_dai_trigger,
527         .hw_params      = kmb_dai_hw_params,
528         .prepare        = kmb_dai_prepare,
529         .set_fmt        = kmb_set_dai_fmt,
530 };
531
532 static struct snd_soc_dai_driver intel_kmb_platform_dai[] = {
533         {
534                 .name = "kmb-plat-dai",
535                 .playback = {
536                         .channels_min = 2,
537                         .channels_max = 2,
538                         .rates = SNDRV_PCM_RATE_8000 |
539                                  SNDRV_PCM_RATE_16000 |
540                                  SNDRV_PCM_RATE_48000,
541                         .rate_min = 8000,
542                         .rate_max = 48000,
543                         .formats = (SNDRV_PCM_FMTBIT_S32_LE |
544                                     SNDRV_PCM_FMTBIT_S24_LE |
545                                     SNDRV_PCM_FMTBIT_S16_LE),
546                 },
547                 .capture = {
548                         .channels_min = 2,
549                         .channels_max = 2,
550                         /*
551                          * .channels_max will be overwritten
552                          * if provided by Device Tree
553                          */
554                         .rates = SNDRV_PCM_RATE_8000 |
555                                  SNDRV_PCM_RATE_16000 |
556                                  SNDRV_PCM_RATE_48000,
557                         .rate_min = 8000,
558                         .rate_max = 48000,
559                         .formats = (SNDRV_PCM_FMTBIT_S32_LE |
560                                     SNDRV_PCM_FMTBIT_S24_LE |
561                                     SNDRV_PCM_FMTBIT_S16_LE),
562                 },
563                 .ops = &kmb_dai_ops,
564         },
565 };
566
567 static int kmb_plat_dai_probe(struct platform_device *pdev)
568 {
569         struct snd_soc_dai_driver *kmb_i2s_dai;
570         struct device *dev = &pdev->dev;
571         struct kmb_i2s_info *kmb_i2s;
572         int ret, irq;
573         u32 comp1_reg;
574
575         kmb_i2s = devm_kzalloc(dev, sizeof(*kmb_i2s), GFP_KERNEL);
576         if (!kmb_i2s)
577                 return -ENOMEM;
578
579         kmb_i2s_dai = devm_kzalloc(dev, sizeof(*kmb_i2s_dai), GFP_KERNEL);
580         if (!kmb_i2s_dai)
581                 return -ENOMEM;
582
583         kmb_i2s_dai->ops = &kmb_dai_ops;
584
585         /* Prepare the related clocks */
586         kmb_i2s->clk_apb = devm_clk_get(dev, "apb_clk");
587         if (IS_ERR(kmb_i2s->clk_apb)) {
588                 dev_err(dev, "Failed to get apb clock\n");
589                 return PTR_ERR(kmb_i2s->clk_apb);
590         }
591
592         ret = clk_prepare_enable(kmb_i2s->clk_apb);
593         if (ret < 0)
594                 return ret;
595
596         ret = devm_add_action_or_reset(dev, kmb_disable_clk, kmb_i2s->clk_apb);
597         if (ret) {
598                 dev_err(dev, "Failed to add clk_apb reset action\n");
599                 return ret;
600         }
601
602         kmb_i2s->clk_i2s = devm_clk_get(dev, "osc");
603         if (IS_ERR(kmb_i2s->clk_i2s)) {
604                 dev_err(dev, "Failed to get osc clock\n");
605                 return PTR_ERR(kmb_i2s->clk_i2s);
606         }
607
608         kmb_i2s->i2s_base = devm_platform_ioremap_resource(pdev, 0);
609         if (IS_ERR(kmb_i2s->i2s_base))
610                 return PTR_ERR(kmb_i2s->i2s_base);
611
612         kmb_i2s->pss_base = devm_platform_ioremap_resource(pdev, 1);
613         if (IS_ERR(kmb_i2s->pss_base))
614                 return PTR_ERR(kmb_i2s->pss_base);
615
616         kmb_i2s->dev = &pdev->dev;
617
618         irq = platform_get_irq_optional(pdev, 0);
619         if (irq > 0) {
620                 ret = devm_request_irq(dev, irq, kmb_i2s_irq_handler, 0,
621                                        pdev->name, kmb_i2s);
622                 if (ret < 0) {
623                         dev_err(dev, "failed to request irq\n");
624                         return ret;
625                 }
626         }
627
628         comp1_reg = readl(kmb_i2s->i2s_base + I2S_COMP_PARAM_1);
629
630         kmb_i2s->fifo_th = (1 << COMP1_FIFO_DEPTH(comp1_reg)) / 2;
631
632         ret = devm_snd_soc_register_component(dev, &kmb_component,
633                                               intel_kmb_platform_dai,
634                                 ARRAY_SIZE(intel_kmb_platform_dai));
635         if (ret) {
636                 dev_err(dev, "not able to register dai\n");
637                 return ret;
638         }
639
640         /* To ensure none of the channels are enabled at boot up */
641         kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_PLAYBACK);
642         kmb_i2s_disable_channels(kmb_i2s, SNDRV_PCM_STREAM_CAPTURE);
643
644         dev_set_drvdata(dev, kmb_i2s);
645
646         return ret;
647 }
648
649 static const struct of_device_id kmb_plat_of_match[] = {
650         { .compatible = "intel,keembay-i2s", },
651         {}
652 };
653
654 static struct platform_driver kmb_plat_dai_driver = {
655         .driver         = {
656                 .name           = "kmb-plat-dai",
657                 .of_match_table = kmb_plat_of_match,
658         },
659         .probe          = kmb_plat_dai_probe,
660 };
661
662 module_platform_driver(kmb_plat_dai_driver);
663
664 MODULE_DESCRIPTION("ASoC Intel KeemBay Platform driver");
665 MODULE_AUTHOR("Sia Jee Heng <jee.heng.sia@intel.com>");
666 MODULE_AUTHOR("Sit, Michael Wei Hong <michael.wei.hong.sit@intel.com>");
667 MODULE_LICENSE("GPL v2");
668 MODULE_ALIAS("platform:kmb_platform");