1 // SPDX-License-Identifier: GPL-2.0 2 // 3 // test-component.c -- Test Audio Component driver 4 // 5 // Copyright (C) 2020 Renesas Electronics Corporation 6 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 7 8 #include <linux/slab.h> 9 #include <linux/of.h> 10 #include <linux/of_graph.h> 11 #include <linux/module.h> 12 #include <linux/workqueue.h> 13 #include <sound/pcm.h> 14 #include <sound/soc.h> 15 16 #define TEST_NAME_LEN 32 17 struct test_dai_name { 18 char name[TEST_NAME_LEN]; 19 char name_playback[TEST_NAME_LEN]; 20 char name_capture[TEST_NAME_LEN]; 21 }; 22 23 struct test_priv { 24 struct device *dev; 25 struct snd_pcm_substream *substream; 26 struct delayed_work dwork; 27 struct snd_soc_component_driver *component_driver; 28 struct snd_soc_dai_driver *dai_driver; 29 struct test_dai_name *name; 30 }; 31 32 struct test_adata { 33 u32 is_cpu:1; 34 u32 cmp_v:1; 35 u32 dai_v:1; 36 }; 37 38 #define mile_stone(d) dev_info((d)->dev, "%s() : %s", __func__, (d)->driver->name) 39 #define mile_stone_x(dev) dev_info(dev, "%s()", __func__) 40 41 static int test_dai_set_sysclk(struct snd_soc_dai *dai, 42 int clk_id, unsigned int freq, int dir) 43 { 44 mile_stone(dai); 45 46 return 0; 47 } 48 49 static int test_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, 50 unsigned int freq_in, unsigned int freq_out) 51 { 52 mile_stone(dai); 53 54 return 0; 55 } 56 57 static int test_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) 58 { 59 mile_stone(dai); 60 61 return 0; 62 } 63 64 static int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 65 { 66 unsigned int format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 67 unsigned int clock = fmt & SND_SOC_DAIFMT_CLOCK_MASK; 68 unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK; 69 unsigned int master = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; 70 char *str; 71 72 dev_info(dai->dev, "name : %s", dai->name); 73 74 str = "unknown"; 75 switch (format) { 76 case SND_SOC_DAIFMT_I2S: 77 str = "i2s"; 78 break; 79 case SND_SOC_DAIFMT_RIGHT_J: 80 str = "right_j"; 81 break; 82 case SND_SOC_DAIFMT_LEFT_J: 83 str = "left_j"; 84 break; 85 case SND_SOC_DAIFMT_DSP_A: 86 str = "dsp_a"; 87 break; 88 case SND_SOC_DAIFMT_DSP_B: 89 str = "dsp_b"; 90 break; 91 case SND_SOC_DAIFMT_AC97: 92 str = "ac97"; 93 break; 94 case SND_SOC_DAIFMT_PDM: 95 str = "pdm"; 96 break; 97 } 98 dev_info(dai->dev, "format : %s", str); 99 100 if (clock == SND_SOC_DAIFMT_CONT) 101 str = "continuous"; 102 else 103 str = "gated"; 104 dev_info(dai->dev, "clock : %s", str); 105 106 str = "unknown"; 107 switch (master) { 108 case SND_SOC_DAIFMT_BP_FP: 109 str = "clk provider, frame provider"; 110 break; 111 case SND_SOC_DAIFMT_BC_FP: 112 str = "clk consumer, frame provider"; 113 break; 114 case SND_SOC_DAIFMT_BP_FC: 115 str = "clk provider, frame consumer"; 116 break; 117 case SND_SOC_DAIFMT_BC_FC: 118 str = "clk consumer, frame consumer"; 119 break; 120 } 121 dev_info(dai->dev, "clock : codec is %s", str); 122 123 str = "unknown"; 124 switch (inv) { 125 case SND_SOC_DAIFMT_NB_NF: 126 str = "normal bit, normal frame"; 127 break; 128 case SND_SOC_DAIFMT_NB_IF: 129 str = "normal bit, invert frame"; 130 break; 131 case SND_SOC_DAIFMT_IB_NF: 132 str = "invert bit, normal frame"; 133 break; 134 case SND_SOC_DAIFMT_IB_IF: 135 str = "invert bit, invert frame"; 136 break; 137 } 138 dev_info(dai->dev, "signal : %s", str); 139 140 return 0; 141 } 142 143 static int test_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream) 144 { 145 mile_stone(dai); 146 147 return 0; 148 } 149 150 static int test_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 151 { 152 mile_stone(dai); 153 154 return 0; 155 } 156 157 static void test_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 158 { 159 mile_stone(dai); 160 } 161 162 static int test_dai_hw_params(struct snd_pcm_substream *substream, 163 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 164 { 165 mile_stone(dai); 166 167 return 0; 168 } 169 170 static int test_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 171 { 172 mile_stone(dai); 173 174 return 0; 175 } 176 177 static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) 178 { 179 mile_stone(dai); 180 181 return 0; 182 } 183 184 static const u64 test_dai_formats = 185 /* 186 * Select below from Sound Card, not auto 187 * SND_SOC_POSSIBLE_DAIFMT_BP_FP 188 * SND_SOC_POSSIBLE_DAIFMT_BC_FP 189 * SND_SOC_POSSIBLE_DAIFMT_BP_FC 190 * SND_SOC_POSSIBLE_DAIFMT_BC_FC 191 */ 192 SND_SOC_POSSIBLE_DAIFMT_I2S | 193 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | 194 SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 195 SND_SOC_POSSIBLE_DAIFMT_DSP_A | 196 SND_SOC_POSSIBLE_DAIFMT_DSP_B | 197 SND_SOC_POSSIBLE_DAIFMT_AC97 | 198 SND_SOC_POSSIBLE_DAIFMT_PDM | 199 SND_SOC_POSSIBLE_DAIFMT_NB_NF | 200 SND_SOC_POSSIBLE_DAIFMT_NB_IF | 201 SND_SOC_POSSIBLE_DAIFMT_IB_NF | 202 SND_SOC_POSSIBLE_DAIFMT_IB_IF; 203 204 static const struct snd_soc_dai_ops test_ops = { 205 .set_fmt = test_dai_set_fmt, 206 .startup = test_dai_startup, 207 .shutdown = test_dai_shutdown, 208 .auto_selectable_formats = &test_dai_formats, 209 .num_auto_selectable_formats = 1, 210 }; 211 212 static const struct snd_soc_dai_ops test_verbose_ops = { 213 .set_sysclk = test_dai_set_sysclk, 214 .set_pll = test_dai_set_pll, 215 .set_clkdiv = test_dai_set_clkdiv, 216 .set_fmt = test_dai_set_fmt, 217 .mute_stream = test_dai_mute_stream, 218 .startup = test_dai_startup, 219 .shutdown = test_dai_shutdown, 220 .hw_params = test_dai_hw_params, 221 .hw_free = test_dai_hw_free, 222 .trigger = test_dai_trigger, 223 .auto_selectable_formats = &test_dai_formats, 224 .num_auto_selectable_formats = 1, 225 }; 226 227 #define STUB_RATES SNDRV_PCM_RATE_8000_384000 228 #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 229 SNDRV_PCM_FMTBIT_U8 | \ 230 SNDRV_PCM_FMTBIT_S16_LE | \ 231 SNDRV_PCM_FMTBIT_U16_LE | \ 232 SNDRV_PCM_FMTBIT_S24_LE | \ 233 SNDRV_PCM_FMTBIT_S24_3LE | \ 234 SNDRV_PCM_FMTBIT_U24_LE | \ 235 SNDRV_PCM_FMTBIT_S32_LE | \ 236 SNDRV_PCM_FMTBIT_U32_LE) 237 238 static int test_component_probe(struct snd_soc_component *component) 239 { 240 mile_stone(component); 241 242 return 0; 243 } 244 245 static void test_component_remove(struct snd_soc_component *component) 246 { 247 mile_stone(component); 248 } 249 250 static int test_component_suspend(struct snd_soc_component *component) 251 { 252 mile_stone(component); 253 254 return 0; 255 } 256 257 static int test_component_resume(struct snd_soc_component *component) 258 { 259 mile_stone(component); 260 261 return 0; 262 } 263 264 #define PREALLOC_BUFFER (32 * 1024) 265 static int test_component_pcm_construct(struct snd_soc_component *component, 266 struct snd_soc_pcm_runtime *rtd) 267 { 268 mile_stone(component); 269 270 snd_pcm_set_managed_buffer_all( 271 rtd->pcm, 272 SNDRV_DMA_TYPE_DEV, 273 rtd->card->snd_card->dev, 274 PREALLOC_BUFFER, PREALLOC_BUFFER); 275 276 return 0; 277 } 278 279 static void test_component_pcm_destruct(struct snd_soc_component *component, 280 struct snd_pcm *pcm) 281 { 282 mile_stone(component); 283 } 284 285 static int test_component_set_sysclk(struct snd_soc_component *component, 286 int clk_id, int source, unsigned int freq, int dir) 287 { 288 mile_stone(component); 289 290 return 0; 291 } 292 293 static int test_component_set_pll(struct snd_soc_component *component, int pll_id, 294 int source, unsigned int freq_in, unsigned int freq_out) 295 { 296 mile_stone(component); 297 298 return 0; 299 } 300 301 static int test_component_set_jack(struct snd_soc_component *component, 302 struct snd_soc_jack *jack, void *data) 303 { 304 mile_stone(component); 305 306 return 0; 307 } 308 309 static void test_component_seq_notifier(struct snd_soc_component *component, 310 enum snd_soc_dapm_type type, int subseq) 311 { 312 mile_stone(component); 313 } 314 315 static int test_component_stream_event(struct snd_soc_component *component, int event) 316 { 317 mile_stone(component); 318 319 return 0; 320 } 321 322 static int test_component_set_bias_level(struct snd_soc_component *component, 323 enum snd_soc_bias_level level) 324 { 325 mile_stone(component); 326 327 return 0; 328 } 329 330 static const struct snd_pcm_hardware test_component_hardware = { 331 /* Random values to keep userspace happy when checking constraints */ 332 .info = SNDRV_PCM_INFO_INTERLEAVED | 333 SNDRV_PCM_INFO_MMAP | 334 SNDRV_PCM_INFO_MMAP_VALID, 335 .buffer_bytes_max = 32 * 1024, 336 .period_bytes_min = 32, 337 .period_bytes_max = 8192, 338 .periods_min = 1, 339 .periods_max = 128, 340 .fifo_size = 256, 341 }; 342 343 static int test_component_open(struct snd_soc_component *component, 344 struct snd_pcm_substream *substream) 345 { 346 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); 347 348 mile_stone(component); 349 350 /* BE's dont need dummy params */ 351 if (!rtd->dai_link->no_pcm) 352 snd_soc_set_runtime_hwparams(substream, &test_component_hardware); 353 354 return 0; 355 } 356 357 static int test_component_close(struct snd_soc_component *component, 358 struct snd_pcm_substream *substream) 359 { 360 mile_stone(component); 361 362 return 0; 363 } 364 365 static int test_component_ioctl(struct snd_soc_component *component, 366 struct snd_pcm_substream *substream, 367 unsigned int cmd, void *arg) 368 { 369 mile_stone(component); 370 371 return 0; 372 } 373 374 static int test_component_hw_params(struct snd_soc_component *component, 375 struct snd_pcm_substream *substream, 376 struct snd_pcm_hw_params *params) 377 { 378 mile_stone(component); 379 380 return 0; 381 } 382 383 static int test_component_hw_free(struct snd_soc_component *component, 384 struct snd_pcm_substream *substream) 385 { 386 mile_stone(component); 387 388 return 0; 389 } 390 391 static int test_component_prepare(struct snd_soc_component *component, 392 struct snd_pcm_substream *substream) 393 { 394 mile_stone(component); 395 396 return 0; 397 } 398 399 static void test_component_timer_stop(struct test_priv *priv) 400 { 401 cancel_delayed_work(&priv->dwork); 402 } 403 404 static void test_component_timer_start(struct test_priv *priv) 405 { 406 schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10)); 407 } 408 409 static void test_component_dwork(struct work_struct *work) 410 { 411 struct test_priv *priv = container_of(work, struct test_priv, dwork.work); 412 413 if (priv->substream) 414 snd_pcm_period_elapsed(priv->substream); 415 416 test_component_timer_start(priv); 417 } 418 419 static int test_component_trigger(struct snd_soc_component *component, 420 struct snd_pcm_substream *substream, int cmd) 421 { 422 struct test_priv *priv = dev_get_drvdata(component->dev); 423 424 mile_stone(component); 425 426 switch (cmd) { 427 case SNDRV_PCM_TRIGGER_START: 428 test_component_timer_start(priv); 429 priv->substream = substream; /* set substream later */ 430 break; 431 case SNDRV_PCM_TRIGGER_STOP: 432 priv->substream = NULL; 433 test_component_timer_stop(priv); 434 } 435 436 return 0; 437 } 438 439 static int test_component_sync_stop(struct snd_soc_component *component, 440 struct snd_pcm_substream *substream) 441 { 442 mile_stone(component); 443 444 return 0; 445 } 446 447 static snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component, 448 struct snd_pcm_substream *substream) 449 { 450 struct snd_pcm_runtime *runtime = substream->runtime; 451 static int pointer; 452 453 if (!runtime) 454 return 0; 455 456 pointer += 10; 457 if (pointer > PREALLOC_BUFFER) 458 pointer = 0; 459 460 /* mile_stone(component); */ 461 462 return bytes_to_frames(runtime, pointer); 463 } 464 465 static int test_component_get_time_info(struct snd_soc_component *component, 466 struct snd_pcm_substream *substream, 467 struct timespec64 *system_ts, 468 struct timespec64 *audio_ts, 469 struct snd_pcm_audio_tstamp_config *audio_tstamp_config, 470 struct snd_pcm_audio_tstamp_report *audio_tstamp_report) 471 { 472 mile_stone(component); 473 474 return 0; 475 } 476 477 static int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 478 struct snd_pcm_hw_params *params) 479 { 480 mile_stone_x(rtd->dev); 481 482 return 0; 483 } 484 485 /* CPU */ 486 static const struct test_adata test_cpu = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, }; 487 static const struct test_adata test_cpu_vv = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, }; 488 static const struct test_adata test_cpu_nv = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, }; 489 static const struct test_adata test_cpu_vn = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, }; 490 /* Codec */ 491 static const struct test_adata test_codec = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, }; 492 static const struct test_adata test_codec_vv = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, }; 493 static const struct test_adata test_codec_nv = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, }; 494 static const struct test_adata test_codec_vn = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, }; 495 496 static const struct of_device_id test_of_match[] = { 497 { .compatible = "test-cpu", .data = (void *)&test_cpu, }, 498 { .compatible = "test-cpu-verbose", .data = (void *)&test_cpu_vv, }, 499 { .compatible = "test-cpu-verbose-dai", .data = (void *)&test_cpu_nv, }, 500 { .compatible = "test-cpu-verbose-component", .data = (void *)&test_cpu_vn, }, 501 { .compatible = "test-codec", .data = (void *)&test_codec, }, 502 { .compatible = "test-codec-verbose", .data = (void *)&test_codec_vv, }, 503 { .compatible = "test-codec-verbose-dai", .data = (void *)&test_codec_nv, }, 504 { .compatible = "test-codec-verbose-component", .data = (void *)&test_codec_vn, }, 505 {}, 506 }; 507 MODULE_DEVICE_TABLE(of, test_of_match); 508 509 static const struct snd_soc_dapm_widget widgets[] = { 510 /* 511 * FIXME 512 * 513 * Just IN/OUT is OK for now, 514 * but need to be updated ? 515 */ 516 SND_SOC_DAPM_INPUT("IN"), 517 SND_SOC_DAPM_OUTPUT("OUT"), 518 }; 519 520 static int test_driver_probe(struct platform_device *pdev) 521 { 522 struct device *dev = &pdev->dev; 523 struct device_node *node = dev->of_node; 524 struct device_node *ep; 525 const struct test_adata *adata = of_device_get_match_data(&pdev->dev); 526 struct snd_soc_component_driver *cdriv; 527 struct snd_soc_dai_driver *ddriv; 528 struct test_dai_name *dname; 529 struct test_priv *priv; 530 int num, ret, i; 531 532 num = of_graph_get_endpoint_count(node); 533 if (!num) { 534 dev_err(dev, "no port exits\n"); 535 return -EINVAL; 536 } 537 538 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 539 cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); 540 ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); 541 dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); 542 if (!priv || !cdriv || !ddriv || !dname || !adata) 543 return -EINVAL; 544 545 priv->dev = dev; 546 priv->component_driver = cdriv; 547 priv->dai_driver = ddriv; 548 priv->name = dname; 549 550 INIT_DELAYED_WORK(&priv->dwork, test_component_dwork); 551 dev_set_drvdata(dev, priv); 552 553 if (adata->is_cpu) { 554 cdriv->name = "test_cpu"; 555 cdriv->pcm_construct = test_component_pcm_construct; 556 cdriv->pointer = test_component_pointer; 557 cdriv->trigger = test_component_trigger; 558 cdriv->legacy_dai_naming = 1; 559 } else { 560 cdriv->name = "test_codec"; 561 cdriv->idle_bias_on = 1; 562 cdriv->endianness = 1; 563 } 564 565 cdriv->open = test_component_open; 566 cdriv->dapm_widgets = widgets; 567 cdriv->num_dapm_widgets = ARRAY_SIZE(widgets); 568 569 if (adata->cmp_v) { 570 cdriv->probe = test_component_probe; 571 cdriv->remove = test_component_remove; 572 cdriv->suspend = test_component_suspend; 573 cdriv->resume = test_component_resume; 574 cdriv->set_sysclk = test_component_set_sysclk; 575 cdriv->set_pll = test_component_set_pll; 576 cdriv->set_jack = test_component_set_jack; 577 cdriv->seq_notifier = test_component_seq_notifier; 578 cdriv->stream_event = test_component_stream_event; 579 cdriv->set_bias_level = test_component_set_bias_level; 580 cdriv->close = test_component_close; 581 cdriv->ioctl = test_component_ioctl; 582 cdriv->hw_params = test_component_hw_params; 583 cdriv->hw_free = test_component_hw_free; 584 cdriv->prepare = test_component_prepare; 585 cdriv->sync_stop = test_component_sync_stop; 586 cdriv->get_time_info = test_component_get_time_info; 587 cdriv->be_hw_params_fixup = test_component_be_hw_params_fixup; 588 589 if (adata->is_cpu) 590 cdriv->pcm_destruct = test_component_pcm_destruct; 591 } 592 593 i = 0; 594 for_each_endpoint_of_node(node, ep) { 595 snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i); 596 ddriv[i].name = dname[i].name; 597 598 snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i); 599 ddriv[i].playback.stream_name = dname[i].name_playback; 600 ddriv[i].playback.channels_min = 1; 601 ddriv[i].playback.channels_max = 384; 602 ddriv[i].playback.rates = STUB_RATES; 603 ddriv[i].playback.formats = STUB_FORMATS; 604 605 snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i); 606 ddriv[i].capture.stream_name = dname[i].name_capture; 607 ddriv[i].capture.channels_min = 1; 608 ddriv[i].capture.channels_max = 384; 609 ddriv[i].capture.rates = STUB_RATES; 610 ddriv[i].capture.formats = STUB_FORMATS; 611 612 if (adata->dai_v) 613 ddriv[i].ops = &test_verbose_ops; 614 else 615 ddriv[i].ops = &test_ops; 616 617 i++; 618 } 619 620 ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num); 621 if (ret < 0) 622 return ret; 623 624 mile_stone_x(dev); 625 626 return 0; 627 } 628 629 static void test_driver_remove(struct platform_device *pdev) 630 { 631 mile_stone_x(&pdev->dev); 632 } 633 634 static struct platform_driver test_driver = { 635 .driver = { 636 .name = "test-component", 637 .of_match_table = test_of_match, 638 }, 639 .probe = test_driver_probe, 640 .remove = test_driver_remove, 641 }; 642 module_platform_driver(test_driver); 643 644 MODULE_ALIAS("platform:asoc-test-component"); 645 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 646 MODULE_DESCRIPTION("ASoC Test Component"); 647 MODULE_LICENSE("GPL v2"); 648