1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // Xilinx ASoC audio formatter support 4 // 5 // Copyright (C) 2018 Xilinx, Inc. 6 // 7 // Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com> 8 9 #include <linux/clk.h> 10 #include <linux/io.h> 11 #include <linux/module.h> 12 #include <linux/of_address.h> 13 #include <linux/of_irq.h> 14 #include <linux/sizes.h> 15 16 #include <sound/asoundef.h> 17 #include <sound/soc.h> 18 #include <sound/pcm_params.h> 19 20 #define DRV_NAME "xlnx_formatter_pcm" 21 22 #define XLNX_S2MM_OFFSET 0 23 #define XLNX_MM2S_OFFSET 0x100 24 25 #define XLNX_AUD_CORE_CONFIG 0x4 26 #define XLNX_AUD_CTRL 0x10 27 #define XLNX_AUD_STS 0x14 28 29 #define AUD_CTRL_RESET_MASK BIT(1) 30 #define AUD_CFG_MM2S_MASK BIT(15) 31 #define AUD_CFG_S2MM_MASK BIT(31) 32 33 #define XLNX_AUD_FS_MULTIPLIER 0x18 34 #define XLNX_AUD_PERIOD_CONFIG 0x1C 35 #define XLNX_AUD_BUFF_ADDR_LSB 0x20 36 #define XLNX_AUD_BUFF_ADDR_MSB 0x24 37 #define XLNX_AUD_XFER_COUNT 0x28 38 #define XLNX_AUD_CH_STS_START 0x2C 39 #define XLNX_BYTES_PER_CH 0x44 40 #define XLNX_AUD_ALIGN_BYTES 64 41 42 #define AUD_STS_IOC_IRQ_MASK BIT(31) 43 #define AUD_STS_CH_STS_MASK BIT(29) 44 #define AUD_CTRL_IOC_IRQ_MASK BIT(13) 45 #define AUD_CTRL_TOUT_IRQ_MASK BIT(14) 46 #define AUD_CTRL_DMA_EN_MASK BIT(0) 47 48 #define CFG_MM2S_CH_MASK GENMASK(11, 8) 49 #define CFG_MM2S_CH_SHIFT 8 50 #define CFG_MM2S_XFER_MASK GENMASK(14, 13) 51 #define CFG_MM2S_XFER_SHIFT 13 52 #define CFG_MM2S_PKG_MASK BIT(12) 53 54 #define CFG_S2MM_CH_MASK GENMASK(27, 24) 55 #define CFG_S2MM_CH_SHIFT 24 56 #define CFG_S2MM_XFER_MASK GENMASK(30, 29) 57 #define CFG_S2MM_XFER_SHIFT 29 58 #define CFG_S2MM_PKG_MASK BIT(28) 59 60 #define AUD_CTRL_DATA_WIDTH_SHIFT 16 61 #define AUD_CTRL_ACTIVE_CH_SHIFT 19 62 #define PERIOD_CFG_PERIODS_SHIFT 16 63 64 #define PERIODS_MIN 2 65 #define PERIODS_MAX 6 66 #define PERIOD_BYTES_MIN 192 67 #define PERIOD_BYTES_MAX (50 * 1024) 68 #define XLNX_PARAM_UNKNOWN 0 69 70 enum bit_depth { 71 BIT_DEPTH_8, 72 BIT_DEPTH_16, 73 BIT_DEPTH_20, 74 BIT_DEPTH_24, 75 BIT_DEPTH_32, 76 }; 77 78 struct xlnx_pcm_drv_data { 79 void __iomem *mmio; 80 bool s2mm_presence; 81 bool mm2s_presence; 82 int s2mm_irq; 83 int mm2s_irq; 84 struct snd_pcm_substream *play_stream; 85 struct snd_pcm_substream *capture_stream; 86 struct clk *axi_clk; 87 unsigned int sysclk; 88 }; 89 90 /* 91 * struct xlnx_pcm_stream_param - stream configuration 92 * @mmio: base address offset 93 * @interleaved: audio channels arrangement in buffer 94 * @xfer_mode: data formatting mode during transfer 95 * @ch_limit: Maximum channels supported 96 * @buffer_size: stream ring buffer size 97 */ 98 struct xlnx_pcm_stream_param { 99 void __iomem *mmio; 100 bool interleaved; 101 u32 xfer_mode; 102 u32 ch_limit; 103 u64 buffer_size; 104 }; 105 106 static const struct snd_pcm_hardware xlnx_pcm_hardware = { 107 .info = SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 108 SNDRV_PCM_INFO_BATCH | SNDRV_PCM_INFO_PAUSE | 109 SNDRV_PCM_INFO_RESUME, 110 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | 111 SNDRV_PCM_FMTBIT_S24_LE, 112 .channels_min = 2, 113 .channels_max = 2, 114 .rates = SNDRV_PCM_RATE_8000_192000, 115 .rate_min = 8000, 116 .rate_max = 192000, 117 .buffer_bytes_max = PERIODS_MAX * PERIOD_BYTES_MAX, 118 .period_bytes_min = PERIOD_BYTES_MIN, 119 .period_bytes_max = PERIOD_BYTES_MAX, 120 .periods_min = PERIODS_MIN, 121 .periods_max = PERIODS_MAX, 122 }; 123 124 enum { 125 AES_TO_AES, 126 AES_TO_PCM, 127 PCM_TO_PCM, 128 PCM_TO_AES 129 }; 130 131 static void xlnx_parse_aes_params(u32 chsts_reg1_val, u32 chsts_reg2_val, 132 struct device *dev) 133 { 134 u32 padded, srate, bit_depth, status[2]; 135 136 if (chsts_reg1_val & IEC958_AES0_PROFESSIONAL) { 137 status[0] = chsts_reg1_val & 0xff; 138 status[1] = (chsts_reg1_val >> 16) & 0xff; 139 140 switch (status[0] & IEC958_AES0_PRO_FS) { 141 case IEC958_AES0_PRO_FS_44100: 142 srate = 44100; 143 break; 144 case IEC958_AES0_PRO_FS_48000: 145 srate = 48000; 146 break; 147 case IEC958_AES0_PRO_FS_32000: 148 srate = 32000; 149 break; 150 case IEC958_AES0_PRO_FS_NOTID: 151 default: 152 srate = XLNX_PARAM_UNKNOWN; 153 break; 154 } 155 156 switch (status[1] & IEC958_AES2_PRO_SBITS) { 157 case IEC958_AES2_PRO_WORDLEN_NOTID: 158 case IEC958_AES2_PRO_SBITS_20: 159 padded = 0; 160 break; 161 case IEC958_AES2_PRO_SBITS_24: 162 padded = 4; 163 break; 164 default: 165 bit_depth = XLNX_PARAM_UNKNOWN; 166 goto log_params; 167 } 168 169 switch (status[1] & IEC958_AES2_PRO_WORDLEN) { 170 case IEC958_AES2_PRO_WORDLEN_20_16: 171 bit_depth = 16 + padded; 172 break; 173 case IEC958_AES2_PRO_WORDLEN_22_18: 174 bit_depth = 18 + padded; 175 break; 176 case IEC958_AES2_PRO_WORDLEN_23_19: 177 bit_depth = 19 + padded; 178 break; 179 case IEC958_AES2_PRO_WORDLEN_24_20: 180 bit_depth = 20 + padded; 181 break; 182 case IEC958_AES2_PRO_WORDLEN_NOTID: 183 default: 184 bit_depth = XLNX_PARAM_UNKNOWN; 185 break; 186 } 187 188 } else { 189 status[0] = (chsts_reg1_val >> 24) & 0xff; 190 status[1] = chsts_reg2_val & 0xff; 191 192 switch (status[0] & IEC958_AES3_CON_FS) { 193 case IEC958_AES3_CON_FS_44100: 194 srate = 44100; 195 break; 196 case IEC958_AES3_CON_FS_48000: 197 srate = 48000; 198 break; 199 case IEC958_AES3_CON_FS_32000: 200 srate = 32000; 201 break; 202 default: 203 srate = XLNX_PARAM_UNKNOWN; 204 break; 205 } 206 207 if (status[1] & IEC958_AES4_CON_MAX_WORDLEN_24) 208 padded = 4; 209 else 210 padded = 0; 211 212 switch (status[1] & IEC958_AES4_CON_WORDLEN) { 213 case IEC958_AES4_CON_WORDLEN_20_16: 214 bit_depth = 16 + padded; 215 break; 216 case IEC958_AES4_CON_WORDLEN_22_18: 217 bit_depth = 18 + padded; 218 break; 219 case IEC958_AES4_CON_WORDLEN_23_19: 220 bit_depth = 19 + padded; 221 break; 222 case IEC958_AES4_CON_WORDLEN_24_20: 223 bit_depth = 20 + padded; 224 break; 225 case IEC958_AES4_CON_WORDLEN_21_17: 226 bit_depth = 17 + padded; 227 break; 228 case IEC958_AES4_CON_WORDLEN_NOTID: 229 default: 230 bit_depth = XLNX_PARAM_UNKNOWN; 231 break; 232 } 233 } 234 235 log_params: 236 if (srate != XLNX_PARAM_UNKNOWN) 237 dev_info(dev, "sample rate = %d\n", srate); 238 else 239 dev_info(dev, "sample rate = unknown\n"); 240 241 if (bit_depth != XLNX_PARAM_UNKNOWN) 242 dev_info(dev, "bit_depth = %d\n", bit_depth); 243 else 244 dev_info(dev, "bit_depth = unknown\n"); 245 } 246 247 static int xlnx_formatter_pcm_reset(void __iomem *mmio_base) 248 { 249 u32 val, retries = 0; 250 251 val = readl(mmio_base + XLNX_AUD_CTRL); 252 val |= AUD_CTRL_RESET_MASK; 253 writel(val, mmio_base + XLNX_AUD_CTRL); 254 255 val = readl(mmio_base + XLNX_AUD_CTRL); 256 /* Poll for maximum timeout of approximately 100ms (1 * 100)*/ 257 while ((val & AUD_CTRL_RESET_MASK) && (retries < 100)) { 258 mdelay(1); 259 retries++; 260 val = readl(mmio_base + XLNX_AUD_CTRL); 261 } 262 if (val & AUD_CTRL_RESET_MASK) 263 return -ENODEV; 264 265 return 0; 266 } 267 268 static void xlnx_formatter_disable_irqs(void __iomem *mmio_base, int stream) 269 { 270 u32 val; 271 272 val = readl(mmio_base + XLNX_AUD_CTRL); 273 val &= ~AUD_CTRL_IOC_IRQ_MASK; 274 if (stream == SNDRV_PCM_STREAM_CAPTURE) 275 val &= ~AUD_CTRL_TOUT_IRQ_MASK; 276 277 writel(val, mmio_base + XLNX_AUD_CTRL); 278 } 279 280 static irqreturn_t xlnx_mm2s_irq_handler(int irq, void *arg) 281 { 282 u32 val; 283 void __iomem *reg; 284 struct xlnx_pcm_drv_data *adata = arg; 285 286 reg = adata->mmio + XLNX_MM2S_OFFSET + XLNX_AUD_STS; 287 val = readl(reg); 288 if (val & AUD_STS_IOC_IRQ_MASK) { 289 writel(val & AUD_STS_IOC_IRQ_MASK, reg); 290 if (adata->play_stream) 291 snd_pcm_period_elapsed(adata->play_stream); 292 return IRQ_HANDLED; 293 } 294 295 return IRQ_NONE; 296 } 297 298 static irqreturn_t xlnx_s2mm_irq_handler(int irq, void *arg) 299 { 300 u32 val; 301 void __iomem *reg; 302 struct xlnx_pcm_drv_data *adata = arg; 303 304 reg = adata->mmio + XLNX_S2MM_OFFSET + XLNX_AUD_STS; 305 val = readl(reg); 306 if (val & AUD_STS_IOC_IRQ_MASK) { 307 writel(val & AUD_STS_IOC_IRQ_MASK, reg); 308 if (adata->capture_stream) 309 snd_pcm_period_elapsed(adata->capture_stream); 310 return IRQ_HANDLED; 311 } 312 313 return IRQ_NONE; 314 } 315 316 static int xlnx_formatter_set_sysclk(struct snd_soc_component *component, 317 int clk_id, int source, unsigned int freq, int dir) 318 { 319 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev); 320 321 adata->sysclk = freq; 322 return 0; 323 } 324 325 static int xlnx_formatter_pcm_open(struct snd_soc_component *component, 326 struct snd_pcm_substream *substream) 327 { 328 int err; 329 u32 val, data_format_mode; 330 u32 ch_count_mask, ch_count_shift, data_xfer_mode, data_xfer_shift; 331 struct xlnx_pcm_stream_param *stream_data; 332 struct snd_pcm_runtime *runtime = substream->runtime; 333 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev); 334 335 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 336 !adata->mm2s_presence) 337 return -ENODEV; 338 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && 339 !adata->s2mm_presence) 340 return -ENODEV; 341 342 stream_data = kzalloc_obj(*stream_data); 343 if (!stream_data) 344 return -ENOMEM; 345 346 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 347 ch_count_mask = CFG_MM2S_CH_MASK; 348 ch_count_shift = CFG_MM2S_CH_SHIFT; 349 data_xfer_mode = CFG_MM2S_XFER_MASK; 350 data_xfer_shift = CFG_MM2S_XFER_SHIFT; 351 data_format_mode = CFG_MM2S_PKG_MASK; 352 stream_data->mmio = adata->mmio + XLNX_MM2S_OFFSET; 353 adata->play_stream = substream; 354 355 } else { 356 ch_count_mask = CFG_S2MM_CH_MASK; 357 ch_count_shift = CFG_S2MM_CH_SHIFT; 358 data_xfer_mode = CFG_S2MM_XFER_MASK; 359 data_xfer_shift = CFG_S2MM_XFER_SHIFT; 360 data_format_mode = CFG_S2MM_PKG_MASK; 361 stream_data->mmio = adata->mmio + XLNX_S2MM_OFFSET; 362 adata->capture_stream = substream; 363 } 364 365 val = readl(adata->mmio + XLNX_AUD_CORE_CONFIG); 366 367 if (!(val & data_format_mode)) 368 stream_data->interleaved = true; 369 370 stream_data->xfer_mode = (val & data_xfer_mode) >> data_xfer_shift; 371 stream_data->ch_limit = (val & ch_count_mask) >> ch_count_shift; 372 dev_info(component->dev, 373 "stream %d : format = %d mode = %d ch_limit = %d\n", 374 substream->stream, stream_data->interleaved, 375 stream_data->xfer_mode, stream_data->ch_limit); 376 377 snd_soc_set_runtime_hwparams(substream, &xlnx_pcm_hardware); 378 runtime->private_data = stream_data; 379 380 /* Resize the period bytes as divisible by 64 */ 381 err = snd_pcm_hw_constraint_step(runtime, 0, 382 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 383 XLNX_AUD_ALIGN_BYTES); 384 if (err) { 385 dev_err(component->dev, 386 "Unable to set constraint on period bytes\n"); 387 return err; 388 } 389 390 /* Resize the buffer bytes as divisible by 64 */ 391 err = snd_pcm_hw_constraint_step(runtime, 0, 392 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 393 XLNX_AUD_ALIGN_BYTES); 394 if (err) { 395 dev_err(component->dev, 396 "Unable to set constraint on buffer bytes\n"); 397 return err; 398 } 399 400 /* Set periods as integer multiple */ 401 err = snd_pcm_hw_constraint_integer(runtime, 402 SNDRV_PCM_HW_PARAM_PERIODS); 403 if (err < 0) { 404 dev_err(component->dev, 405 "Unable to set constraint on periods to be integer\n"); 406 return err; 407 } 408 409 /* enable DMA IOC irq */ 410 val = readl(stream_data->mmio + XLNX_AUD_CTRL); 411 val |= AUD_CTRL_IOC_IRQ_MASK; 412 writel(val, stream_data->mmio + XLNX_AUD_CTRL); 413 414 return 0; 415 } 416 417 static int xlnx_formatter_pcm_close(struct snd_soc_component *component, 418 struct snd_pcm_substream *substream) 419 { 420 int ret; 421 struct xlnx_pcm_stream_param *stream_data = 422 substream->runtime->private_data; 423 424 ret = xlnx_formatter_pcm_reset(stream_data->mmio); 425 if (ret) { 426 dev_err(component->dev, "audio formatter reset failed\n"); 427 goto err_reset; 428 } 429 xlnx_formatter_disable_irqs(stream_data->mmio, substream->stream); 430 431 err_reset: 432 kfree(stream_data); 433 return 0; 434 } 435 436 static snd_pcm_uframes_t 437 xlnx_formatter_pcm_pointer(struct snd_soc_component *component, 438 struct snd_pcm_substream *substream) 439 { 440 u32 pos; 441 struct snd_pcm_runtime *runtime = substream->runtime; 442 struct xlnx_pcm_stream_param *stream_data = runtime->private_data; 443 444 pos = readl(stream_data->mmio + XLNX_AUD_XFER_COUNT); 445 446 if (pos >= stream_data->buffer_size) 447 pos = 0; 448 449 return bytes_to_frames(runtime, pos); 450 } 451 452 static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component, 453 struct snd_pcm_substream *substream, 454 struct snd_pcm_hw_params *params) 455 { 456 u32 low, high, active_ch, val, bytes_per_ch, bits_per_sample; 457 u32 aes_reg1_val, aes_reg2_val; 458 u64 size; 459 struct snd_pcm_runtime *runtime = substream->runtime; 460 struct xlnx_pcm_stream_param *stream_data = runtime->private_data; 461 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(component->dev); 462 463 active_ch = params_channels(params); 464 if (active_ch > stream_data->ch_limit) 465 return -EINVAL; 466 467 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && 468 adata->sysclk) { 469 unsigned int mclk_fs = adata->sysclk / params_rate(params); 470 471 if (adata->sysclk % params_rate(params) != 0) { 472 dev_warn(component->dev, "sysclk %u not divisible by rate %u\n", 473 adata->sysclk, params_rate(params)); 474 return -EINVAL; 475 } 476 477 writel(mclk_fs, stream_data->mmio + XLNX_AUD_FS_MULTIPLIER); 478 } 479 480 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE && 481 stream_data->xfer_mode == AES_TO_PCM) { 482 val = readl(stream_data->mmio + XLNX_AUD_STS); 483 if (val & AUD_STS_CH_STS_MASK) { 484 aes_reg1_val = readl(stream_data->mmio + 485 XLNX_AUD_CH_STS_START); 486 aes_reg2_val = readl(stream_data->mmio + 487 XLNX_AUD_CH_STS_START + 0x4); 488 489 xlnx_parse_aes_params(aes_reg1_val, aes_reg2_val, 490 component->dev); 491 } 492 } 493 494 size = params_buffer_bytes(params); 495 496 stream_data->buffer_size = size; 497 498 low = lower_32_bits(runtime->dma_addr); 499 high = upper_32_bits(runtime->dma_addr); 500 writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB); 501 writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB); 502 503 val = readl(stream_data->mmio + XLNX_AUD_CTRL); 504 bits_per_sample = params_width(params); 505 switch (bits_per_sample) { 506 case 8: 507 val |= (BIT_DEPTH_8 << AUD_CTRL_DATA_WIDTH_SHIFT); 508 break; 509 case 16: 510 val |= (BIT_DEPTH_16 << AUD_CTRL_DATA_WIDTH_SHIFT); 511 break; 512 case 20: 513 val |= (BIT_DEPTH_20 << AUD_CTRL_DATA_WIDTH_SHIFT); 514 break; 515 case 24: 516 val |= (BIT_DEPTH_24 << AUD_CTRL_DATA_WIDTH_SHIFT); 517 break; 518 case 32: 519 val |= (BIT_DEPTH_32 << AUD_CTRL_DATA_WIDTH_SHIFT); 520 break; 521 default: 522 return -EINVAL; 523 } 524 525 val |= active_ch << AUD_CTRL_ACTIVE_CH_SHIFT; 526 writel(val, stream_data->mmio + XLNX_AUD_CTRL); 527 528 val = (params_periods(params) << PERIOD_CFG_PERIODS_SHIFT) 529 | params_period_bytes(params); 530 writel(val, stream_data->mmio + XLNX_AUD_PERIOD_CONFIG); 531 bytes_per_ch = DIV_ROUND_UP(params_period_bytes(params), active_ch); 532 writel(bytes_per_ch, stream_data->mmio + XLNX_BYTES_PER_CH); 533 534 return 0; 535 } 536 537 static int xlnx_formatter_pcm_trigger(struct snd_soc_component *component, 538 struct snd_pcm_substream *substream, 539 int cmd) 540 { 541 u32 val; 542 struct xlnx_pcm_stream_param *stream_data = 543 substream->runtime->private_data; 544 545 switch (cmd) { 546 case SNDRV_PCM_TRIGGER_START: 547 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 548 case SNDRV_PCM_TRIGGER_RESUME: 549 val = readl(stream_data->mmio + XLNX_AUD_CTRL); 550 val |= AUD_CTRL_DMA_EN_MASK; 551 writel(val, stream_data->mmio + XLNX_AUD_CTRL); 552 break; 553 case SNDRV_PCM_TRIGGER_STOP: 554 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 555 case SNDRV_PCM_TRIGGER_SUSPEND: 556 val = readl(stream_data->mmio + XLNX_AUD_CTRL); 557 val &= ~AUD_CTRL_DMA_EN_MASK; 558 writel(val, stream_data->mmio + XLNX_AUD_CTRL); 559 break; 560 } 561 562 return 0; 563 } 564 565 static int xlnx_formatter_pcm_new(struct snd_soc_component *component, 566 struct snd_soc_pcm_runtime *rtd) 567 { 568 snd_pcm_set_managed_buffer_all(rtd->pcm, 569 SNDRV_DMA_TYPE_DEV, component->dev, 570 xlnx_pcm_hardware.buffer_bytes_max, 571 xlnx_pcm_hardware.buffer_bytes_max); 572 return 0; 573 } 574 575 static const struct snd_soc_component_driver xlnx_asoc_component = { 576 .name = DRV_NAME, 577 .set_sysclk = xlnx_formatter_set_sysclk, 578 .open = xlnx_formatter_pcm_open, 579 .close = xlnx_formatter_pcm_close, 580 .hw_params = xlnx_formatter_pcm_hw_params, 581 .trigger = xlnx_formatter_pcm_trigger, 582 .pointer = xlnx_formatter_pcm_pointer, 583 .pcm_new = xlnx_formatter_pcm_new, 584 }; 585 586 static int xlnx_formatter_pcm_probe(struct platform_device *pdev) 587 { 588 int ret; 589 u32 val; 590 struct xlnx_pcm_drv_data *aud_drv_data; 591 struct device *dev = &pdev->dev; 592 593 aud_drv_data = devm_kzalloc(dev, sizeof(*aud_drv_data), GFP_KERNEL); 594 if (!aud_drv_data) 595 return -ENOMEM; 596 597 aud_drv_data->axi_clk = devm_clk_get(dev, "s_axi_lite_aclk"); 598 if (IS_ERR(aud_drv_data->axi_clk)) { 599 ret = PTR_ERR(aud_drv_data->axi_clk); 600 dev_err(dev, "failed to get s_axi_lite_aclk(%d)\n", ret); 601 return ret; 602 } 603 ret = clk_prepare_enable(aud_drv_data->axi_clk); 604 if (ret) { 605 dev_err(dev, 606 "failed to enable s_axi_lite_aclk(%d)\n", ret); 607 return ret; 608 } 609 610 aud_drv_data->mmio = devm_platform_ioremap_resource(pdev, 0); 611 if (IS_ERR(aud_drv_data->mmio)) { 612 dev_err(dev, "audio formatter ioremap failed\n"); 613 ret = PTR_ERR(aud_drv_data->mmio); 614 goto clk_err; 615 } 616 617 val = readl(aud_drv_data->mmio + XLNX_AUD_CORE_CONFIG); 618 if (val & AUD_CFG_MM2S_MASK) { 619 aud_drv_data->mm2s_presence = true; 620 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio + 621 XLNX_MM2S_OFFSET); 622 if (ret) { 623 dev_err(dev, "audio formatter reset failed\n"); 624 goto clk_err; 625 } 626 xlnx_formatter_disable_irqs(aud_drv_data->mmio + 627 XLNX_MM2S_OFFSET, 628 SNDRV_PCM_STREAM_PLAYBACK); 629 630 aud_drv_data->mm2s_irq = platform_get_irq_byname(pdev, 631 "irq_mm2s"); 632 if (aud_drv_data->mm2s_irq < 0) { 633 ret = aud_drv_data->mm2s_irq; 634 goto clk_err; 635 } 636 ret = devm_request_irq(dev, aud_drv_data->mm2s_irq, 637 xlnx_mm2s_irq_handler, 0, 638 "xlnx_formatter_pcm_mm2s_irq", aud_drv_data); 639 if (ret) { 640 dev_err(dev, "xlnx audio mm2s irq request failed\n"); 641 goto clk_err; 642 } 643 } 644 if (val & AUD_CFG_S2MM_MASK) { 645 aud_drv_data->s2mm_presence = true; 646 ret = xlnx_formatter_pcm_reset(aud_drv_data->mmio + 647 XLNX_S2MM_OFFSET); 648 if (ret) { 649 dev_err(dev, "audio formatter reset failed\n"); 650 goto clk_err; 651 } 652 xlnx_formatter_disable_irqs(aud_drv_data->mmio + 653 XLNX_S2MM_OFFSET, 654 SNDRV_PCM_STREAM_CAPTURE); 655 656 aud_drv_data->s2mm_irq = platform_get_irq_byname(pdev, 657 "irq_s2mm"); 658 if (aud_drv_data->s2mm_irq < 0) { 659 ret = aud_drv_data->s2mm_irq; 660 goto clk_err; 661 } 662 ret = devm_request_irq(dev, aud_drv_data->s2mm_irq, 663 xlnx_s2mm_irq_handler, 0, 664 "xlnx_formatter_pcm_s2mm_irq", 665 aud_drv_data); 666 if (ret) { 667 dev_err(dev, "xlnx audio s2mm irq request failed\n"); 668 goto clk_err; 669 } 670 } 671 672 dev_set_drvdata(dev, aud_drv_data); 673 674 ret = devm_snd_soc_register_component(dev, &xlnx_asoc_component, 675 NULL, 0); 676 if (ret) { 677 dev_err(dev, "pcm platform device register failed\n"); 678 goto clk_err; 679 } 680 681 return 0; 682 683 clk_err: 684 clk_disable_unprepare(aud_drv_data->axi_clk); 685 return ret; 686 } 687 688 static void xlnx_formatter_pcm_remove(struct platform_device *pdev) 689 { 690 int ret = 0; 691 struct xlnx_pcm_drv_data *adata = dev_get_drvdata(&pdev->dev); 692 693 if (adata->s2mm_presence) 694 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_S2MM_OFFSET); 695 696 /* Try MM2S reset, even if S2MM reset fails */ 697 if (adata->mm2s_presence) 698 ret = xlnx_formatter_pcm_reset(adata->mmio + XLNX_MM2S_OFFSET); 699 700 if (ret) 701 dev_err(&pdev->dev, "audio formatter reset failed\n"); 702 703 clk_disable_unprepare(adata->axi_clk); 704 } 705 706 static const struct of_device_id xlnx_formatter_pcm_of_match[] = { 707 { .compatible = "xlnx,audio-formatter-1.0"}, 708 {}, 709 }; 710 MODULE_DEVICE_TABLE(of, xlnx_formatter_pcm_of_match); 711 712 static struct platform_driver xlnx_formatter_pcm_driver = { 713 .probe = xlnx_formatter_pcm_probe, 714 .remove = xlnx_formatter_pcm_remove, 715 .driver = { 716 .name = DRV_NAME, 717 .of_match_table = xlnx_formatter_pcm_of_match, 718 }, 719 }; 720 721 module_platform_driver(xlnx_formatter_pcm_driver); 722 723 MODULE_DESCRIPTION("ASoC driver for Xilinx audio formatter"); 724 MODULE_AUTHOR("Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>"); 725 MODULE_LICENSE("GPL v2"); 726