Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ASoC: test-component: add Test Component for Sound debug/test

We already have dummy-codec, dummy-platform.
But its issues are
1) we don't have dummy-cpu,
2) we can't select it via DeviceTree
3) It do nothing

Sometimes we want to have Dummy Sound Component for debugging,
for testing, for learning Framework behavior, etc, etc...
This patch adds Test-Component driver for it.

User can select CPU Component by using "test-cpu" compatible,
and can select Codec Component by using "test-codec" compatible.

It doesn't support Platform so far, but is easy to add.

We can verbose print to know its progress if user selected
xxx-verbose compatible driver.

for example,
test-cpu : silent Component, silent DAI
test-cpu-verbose-component : verbose Component, silent DAI
test-cpu-verbose-dai : silent Component, verbose DAI
test-cpu-verbose : verbose Component, verbose DAI

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Link: https://lore.kernel.org/r/877dein8rx.wl-kuninori.morimoto.gx@renesas.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Kuninori Morimoto and committed by
Mark Brown
d293abc0 5dd7e163

+667
+6
sound/soc/generic/Kconfig
··· 17 17 This option enables generic simple sound card support 18 18 with OF-graph DT bindings. 19 19 It also support DPCM of multi CPU single Codec ststem. 20 + 21 + config SND_TEST_COMPONENT 22 + tristate "ASoC Test component sound support" 23 + depends on OF 24 + help 25 + This option enables test component sound driver support.
+2
sound/soc/generic/Makefile
··· 2 2 snd-soc-simple-card-utils-objs := simple-card-utils.o 3 3 snd-soc-simple-card-objs := simple-card.o 4 4 snd-soc-audio-graph-card-objs := audio-graph-card.o 5 + snd-soc-test-component-objs := test-component.o 5 6 6 7 obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o 7 8 obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o 8 9 obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o 10 + obj-$(CONFIG_SND_TEST_COMPONENT) += snd-soc-test-component.o
+659
sound/soc/generic/test-component.c
··· 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_device.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_MASTER_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_CBP_CFP: 109 + str = "clk provider, frame provider"; 110 + break; 111 + case SND_SOC_DAIFMT_CBC_CFP: 112 + str = "clk consumer, frame provider"; 113 + break; 114 + case SND_SOC_DAIFMT_CBP_CFC: 115 + str = "clk provider, frame consumer"; 116 + break; 117 + case SND_SOC_DAIFMT_CBC_CFC: 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 int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, 185 + int cmd, struct snd_soc_dai *dai) 186 + { 187 + mile_stone(dai); 188 + 189 + return 0; 190 + } 191 + 192 + static u64 test_dai_formats = 193 + /* 194 + * Select below from Sound Card, not auto 195 + * SND_SOC_POSSIBLE_DAIFMT_CBP_CFP 196 + * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP 197 + * SND_SOC_POSSIBLE_DAIFMT_CBP_CFC 198 + * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC 199 + */ 200 + SND_SOC_POSSIBLE_DAIFMT_I2S | 201 + SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | 202 + SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 203 + SND_SOC_POSSIBLE_DAIFMT_DSP_A | 204 + SND_SOC_POSSIBLE_DAIFMT_DSP_B | 205 + SND_SOC_POSSIBLE_DAIFMT_AC97 | 206 + SND_SOC_POSSIBLE_DAIFMT_PDM | 207 + SND_SOC_POSSIBLE_DAIFMT_NB_NF | 208 + SND_SOC_POSSIBLE_DAIFMT_NB_IF | 209 + SND_SOC_POSSIBLE_DAIFMT_IB_NF | 210 + SND_SOC_POSSIBLE_DAIFMT_IB_IF; 211 + 212 + static const struct snd_soc_dai_ops test_ops = { 213 + .set_fmt = test_dai_set_fmt, 214 + .startup = test_dai_startup, 215 + .shutdown = test_dai_shutdown, 216 + .auto_selectable_formats = &test_dai_formats, 217 + .num_auto_selectable_formats = 1, 218 + }; 219 + 220 + static const struct snd_soc_dai_ops test_verbose_ops = { 221 + .set_sysclk = test_dai_set_sysclk, 222 + .set_pll = test_dai_set_pll, 223 + .set_clkdiv = test_dai_set_clkdiv, 224 + .set_fmt = test_dai_set_fmt, 225 + .mute_stream = test_dai_mute_stream, 226 + .startup = test_dai_startup, 227 + .shutdown = test_dai_shutdown, 228 + .hw_params = test_dai_hw_params, 229 + .hw_free = test_dai_hw_free, 230 + .trigger = test_dai_trigger, 231 + .bespoke_trigger = test_dai_bespoke_trigger, 232 + .auto_selectable_formats = &test_dai_formats, 233 + .num_auto_selectable_formats = 1, 234 + }; 235 + 236 + #define STUB_RATES SNDRV_PCM_RATE_8000_384000 237 + #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 238 + SNDRV_PCM_FMTBIT_U8 | \ 239 + SNDRV_PCM_FMTBIT_S16_LE | \ 240 + SNDRV_PCM_FMTBIT_U16_LE | \ 241 + SNDRV_PCM_FMTBIT_S24_LE | \ 242 + SNDRV_PCM_FMTBIT_S24_3LE | \ 243 + SNDRV_PCM_FMTBIT_U24_LE | \ 244 + SNDRV_PCM_FMTBIT_S32_LE | \ 245 + SNDRV_PCM_FMTBIT_U32_LE) 246 + 247 + static int test_component_probe(struct snd_soc_component *component) 248 + { 249 + mile_stone(component); 250 + 251 + return 0; 252 + } 253 + 254 + static void test_component_remove(struct snd_soc_component *component) 255 + { 256 + mile_stone(component); 257 + } 258 + 259 + static int test_component_suspend(struct snd_soc_component *component) 260 + { 261 + mile_stone(component); 262 + 263 + return 0; 264 + } 265 + 266 + static int test_component_resume(struct snd_soc_component *component) 267 + { 268 + mile_stone(component); 269 + 270 + return 0; 271 + } 272 + 273 + #define PREALLOC_BUFFER (32 * 1024) 274 + static int test_component_pcm_construct(struct snd_soc_component *component, 275 + struct snd_soc_pcm_runtime *rtd) 276 + { 277 + mile_stone(component); 278 + 279 + snd_pcm_set_managed_buffer_all( 280 + rtd->pcm, 281 + SNDRV_DMA_TYPE_DEV, 282 + rtd->card->snd_card->dev, 283 + PREALLOC_BUFFER, PREALLOC_BUFFER); 284 + 285 + return 0; 286 + } 287 + 288 + static void test_component_pcm_destruct(struct snd_soc_component *component, 289 + struct snd_pcm *pcm) 290 + { 291 + mile_stone(component); 292 + } 293 + 294 + static int test_component_set_sysclk(struct snd_soc_component *component, 295 + int clk_id, int source, unsigned int freq, int dir) 296 + { 297 + mile_stone(component); 298 + 299 + return 0; 300 + } 301 + 302 + static int test_component_set_pll(struct snd_soc_component *component, int pll_id, 303 + int source, unsigned int freq_in, unsigned int freq_out) 304 + { 305 + mile_stone(component); 306 + 307 + return 0; 308 + } 309 + 310 + static int test_component_set_jack(struct snd_soc_component *component, 311 + struct snd_soc_jack *jack, void *data) 312 + { 313 + mile_stone(component); 314 + 315 + return 0; 316 + } 317 + 318 + static void test_component_seq_notifier(struct snd_soc_component *component, 319 + enum snd_soc_dapm_type type, int subseq) 320 + { 321 + mile_stone(component); 322 + } 323 + 324 + static int test_component_stream_event(struct snd_soc_component *component, int event) 325 + { 326 + mile_stone(component); 327 + 328 + return 0; 329 + } 330 + 331 + static int test_component_set_bias_level(struct snd_soc_component *component, 332 + enum snd_soc_bias_level level) 333 + { 334 + mile_stone(component); 335 + 336 + return 0; 337 + } 338 + 339 + static const struct snd_pcm_hardware test_component_hardware = { 340 + /* Random values to keep userspace happy when checking constraints */ 341 + .info = SNDRV_PCM_INFO_INTERLEAVED | 342 + SNDRV_PCM_INFO_MMAP | 343 + SNDRV_PCM_INFO_MMAP_VALID, 344 + .buffer_bytes_max = 32 * 1024, 345 + .period_bytes_min = 32, 346 + .period_bytes_max = 8192, 347 + .periods_min = 1, 348 + .periods_max = 128, 349 + .fifo_size = 256, 350 + }; 351 + 352 + static int test_component_open(struct snd_soc_component *component, 353 + struct snd_pcm_substream *substream) 354 + { 355 + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 356 + 357 + mile_stone(component); 358 + 359 + /* BE's dont need dummy params */ 360 + if (!rtd->dai_link->no_pcm) 361 + snd_soc_set_runtime_hwparams(substream, &test_component_hardware); 362 + 363 + return 0; 364 + } 365 + 366 + static int test_component_close(struct snd_soc_component *component, 367 + struct snd_pcm_substream *substream) 368 + { 369 + mile_stone(component); 370 + 371 + return 0; 372 + } 373 + 374 + static int test_component_ioctl(struct snd_soc_component *component, 375 + struct snd_pcm_substream *substream, 376 + unsigned int cmd, void *arg) 377 + { 378 + mile_stone(component); 379 + 380 + return 0; 381 + } 382 + 383 + static int test_component_hw_params(struct snd_soc_component *component, 384 + struct snd_pcm_substream *substream, 385 + struct snd_pcm_hw_params *params) 386 + { 387 + mile_stone(component); 388 + 389 + return 0; 390 + } 391 + 392 + static int test_component_hw_free(struct snd_soc_component *component, 393 + struct snd_pcm_substream *substream) 394 + { 395 + mile_stone(component); 396 + 397 + return 0; 398 + } 399 + 400 + static int test_component_prepare(struct snd_soc_component *component, 401 + struct snd_pcm_substream *substream) 402 + { 403 + mile_stone(component); 404 + 405 + return 0; 406 + } 407 + 408 + static void test_component_timer_stop(struct test_priv *priv) 409 + { 410 + cancel_delayed_work(&priv->dwork); 411 + } 412 + 413 + static void test_component_timer_start(struct test_priv *priv) 414 + { 415 + schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10)); 416 + } 417 + 418 + static void test_component_dwork(struct work_struct *work) 419 + { 420 + struct test_priv *priv = container_of(work, struct test_priv, dwork.work); 421 + 422 + if (priv->substream) 423 + snd_pcm_period_elapsed(priv->substream); 424 + 425 + test_component_timer_start(priv); 426 + } 427 + 428 + static int test_component_trigger(struct snd_soc_component *component, 429 + struct snd_pcm_substream *substream, int cmd) 430 + { 431 + struct test_priv *priv = dev_get_drvdata(component->dev); 432 + 433 + mile_stone(component); 434 + 435 + switch (cmd) { 436 + case SNDRV_PCM_TRIGGER_START: 437 + test_component_timer_start(priv); 438 + priv->substream = substream; /* set substream later */ 439 + break; 440 + case SNDRV_PCM_TRIGGER_STOP: 441 + priv->substream = NULL; 442 + test_component_timer_stop(priv); 443 + } 444 + 445 + return 0; 446 + } 447 + 448 + static int test_component_sync_stop(struct snd_soc_component *component, 449 + struct snd_pcm_substream *substream) 450 + { 451 + mile_stone(component); 452 + 453 + return 0; 454 + } 455 + 456 + static snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component, 457 + struct snd_pcm_substream *substream) 458 + { 459 + struct snd_pcm_runtime *runtime = substream->runtime; 460 + static int pointer; 461 + 462 + if (!runtime) 463 + return 0; 464 + 465 + pointer += 10; 466 + if (pointer > PREALLOC_BUFFER) 467 + pointer = 0; 468 + 469 + /* mile_stone(component); */ 470 + 471 + return bytes_to_frames(runtime, pointer); 472 + } 473 + 474 + static int test_component_get_time_info(struct snd_soc_component *component, 475 + struct snd_pcm_substream *substream, 476 + struct timespec64 *system_ts, 477 + struct timespec64 *audio_ts, 478 + struct snd_pcm_audio_tstamp_config *audio_tstamp_config, 479 + struct snd_pcm_audio_tstamp_report *audio_tstamp_report) 480 + { 481 + mile_stone(component); 482 + 483 + return 0; 484 + } 485 + 486 + static int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 487 + struct snd_pcm_hw_params *params) 488 + { 489 + mile_stone_x(rtd->dev); 490 + 491 + return 0; 492 + } 493 + 494 + /* CPU */ 495 + static const struct test_adata test_cpu = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, }; 496 + static const struct test_adata test_cpu_vv = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, }; 497 + static const struct test_adata test_cpu_nv = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, }; 498 + static const struct test_adata test_cpu_vn = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, }; 499 + /* Codec */ 500 + static const struct test_adata test_codec = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, }; 501 + static const struct test_adata test_codec_vv = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, }; 502 + static const struct test_adata test_codec_nv = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, }; 503 + static const struct test_adata test_codec_vn = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, }; 504 + 505 + static const struct of_device_id test_of_match[] = { 506 + { .compatible = "test-cpu", .data = (void *)&test_cpu, }, 507 + { .compatible = "test-cpu-verbose", .data = (void *)&test_cpu_vv, }, 508 + { .compatible = "test-cpu-verbose-dai", .data = (void *)&test_cpu_nv, }, 509 + { .compatible = "test-cpu-verbose-component", .data = (void *)&test_cpu_vn, }, 510 + { .compatible = "test-codec", .data = (void *)&test_codec, }, 511 + { .compatible = "test-codec-verbose", .data = (void *)&test_codec_vv, }, 512 + { .compatible = "test-codec-verbose-dai", .data = (void *)&test_codec_nv, }, 513 + { .compatible = "test-codec-verbose-component", .data = (void *)&test_codec_vn, }, 514 + {}, 515 + }; 516 + MODULE_DEVICE_TABLE(of, test_of_match); 517 + 518 + static const struct snd_soc_dapm_widget widgets[] = { 519 + /* 520 + * FIXME 521 + * 522 + * Just IN/OUT is OK for now, 523 + * but need to be updated ? 524 + */ 525 + SND_SOC_DAPM_INPUT("IN"), 526 + SND_SOC_DAPM_OUTPUT("OUT"), 527 + }; 528 + 529 + static int test_driver_probe(struct platform_device *pdev) 530 + { 531 + struct device *dev = &pdev->dev; 532 + struct device_node *node = dev->of_node; 533 + struct device_node *ep; 534 + const struct of_device_id *of_id = of_match_device(test_of_match, &pdev->dev); 535 + const struct test_adata *adata = of_id->data; 536 + struct snd_soc_component_driver *cdriv; 537 + struct snd_soc_dai_driver *ddriv; 538 + struct test_dai_name *dname; 539 + struct test_priv *priv; 540 + int num, ret, i; 541 + 542 + num = of_graph_get_endpoint_count(node); 543 + if (!num) { 544 + dev_err(dev, "no port exits\n"); 545 + return -EINVAL; 546 + } 547 + 548 + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 549 + cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); 550 + ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); 551 + dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); 552 + if (!priv || !cdriv || !ddriv || !dname) 553 + return -EINVAL; 554 + 555 + priv->dev = dev; 556 + priv->component_driver = cdriv; 557 + priv->dai_driver = ddriv; 558 + priv->name = dname; 559 + 560 + INIT_DELAYED_WORK(&priv->dwork, test_component_dwork); 561 + dev_set_drvdata(dev, priv); 562 + 563 + if (adata->is_cpu) { 564 + cdriv->name = "test_cpu"; 565 + cdriv->pcm_construct = test_component_pcm_construct; 566 + cdriv->pointer = test_component_pointer; 567 + cdriv->trigger = test_component_trigger; 568 + } else { 569 + cdriv->name = "test_codec"; 570 + cdriv->idle_bias_on = 1; 571 + cdriv->endianness = 1; 572 + cdriv->non_legacy_dai_naming = 1; 573 + } 574 + 575 + cdriv->open = test_component_open; 576 + cdriv->dapm_widgets = widgets; 577 + cdriv->num_dapm_widgets = ARRAY_SIZE(widgets); 578 + 579 + if (adata->cmp_v) { 580 + cdriv->probe = test_component_probe; 581 + cdriv->remove = test_component_remove; 582 + cdriv->suspend = test_component_suspend; 583 + cdriv->resume = test_component_resume; 584 + cdriv->set_sysclk = test_component_set_sysclk; 585 + cdriv->set_pll = test_component_set_pll; 586 + cdriv->set_jack = test_component_set_jack; 587 + cdriv->seq_notifier = test_component_seq_notifier; 588 + cdriv->stream_event = test_component_stream_event; 589 + cdriv->set_bias_level = test_component_set_bias_level; 590 + cdriv->close = test_component_close; 591 + cdriv->ioctl = test_component_ioctl; 592 + cdriv->hw_params = test_component_hw_params; 593 + cdriv->hw_free = test_component_hw_free; 594 + cdriv->prepare = test_component_prepare; 595 + cdriv->sync_stop = test_component_sync_stop; 596 + cdriv->get_time_info = test_component_get_time_info; 597 + cdriv->be_hw_params_fixup = test_component_be_hw_params_fixup; 598 + 599 + if (adata->is_cpu) 600 + cdriv->pcm_destruct = test_component_pcm_destruct; 601 + } 602 + 603 + i = 0; 604 + for_each_endpoint_of_node(node, ep) { 605 + snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i); 606 + ddriv[i].name = dname[i].name; 607 + 608 + snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i); 609 + ddriv[i].playback.stream_name = dname[i].name_playback; 610 + ddriv[i].playback.channels_min = 1; 611 + ddriv[i].playback.channels_max = 384; 612 + ddriv[i].playback.rates = STUB_RATES; 613 + ddriv[i].playback.formats = STUB_FORMATS; 614 + 615 + snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i); 616 + ddriv[i].capture.stream_name = dname[i].name_capture; 617 + ddriv[i].capture.channels_min = 1; 618 + ddriv[i].capture.channels_max = 384; 619 + ddriv[i].capture.rates = STUB_RATES; 620 + ddriv[i].capture.formats = STUB_FORMATS; 621 + 622 + if (adata->dai_v) 623 + ddriv[i].ops = &test_verbose_ops; 624 + else 625 + ddriv[i].ops = &test_ops; 626 + 627 + i++; 628 + } 629 + 630 + ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num); 631 + if (ret < 0) 632 + return ret; 633 + 634 + mile_stone_x(dev); 635 + 636 + return 0; 637 + } 638 + 639 + static int test_driver_remove(struct platform_device *pdev) 640 + { 641 + mile_stone_x(&pdev->dev); 642 + 643 + return 0; 644 + } 645 + 646 + static struct platform_driver test_driver = { 647 + .driver = { 648 + .name = "test-component", 649 + .of_match_table = test_of_match, 650 + }, 651 + .probe = test_driver_probe, 652 + .remove = test_driver_remove, 653 + }; 654 + module_platform_driver(test_driver); 655 + 656 + MODULE_ALIAS("platform:asoc-test-component"); 657 + MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 658 + MODULE_DESCRIPTION("ASoC Test Component"); 659 + MODULE_LICENSE("GPL v2");