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