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
test_dai_set_sysclk(struct snd_soc_dai * dai,int clk_id,unsigned int freq,int dir)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
test_dai_set_pll(struct snd_soc_dai * dai,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)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
test_dai_set_clkdiv(struct snd_soc_dai * dai,int div_id,int div)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
test_dai_set_fmt(struct snd_soc_dai * dai,unsigned int fmt)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
test_dai_set_tdm_slot(struct snd_soc_dai * dai,unsigned int tx_mask,unsigned int rx_mask,int slots,int slot_width)143 static int test_dai_set_tdm_slot(struct snd_soc_dai *dai,
144 unsigned int tx_mask, unsigned int rx_mask,
145 int slots, int slot_width)
146 {
147 dev_info(dai->dev, "set tdm slot: tx_mask=0x%08X, rx_mask=0x%08X, slots=%d, slot_width=%d\n",
148 tx_mask, rx_mask, slots, slot_width);
149 return 0;
150 }
151
test_dai_mute_stream(struct snd_soc_dai * dai,int mute,int stream)152 static int test_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
153 {
154 mile_stone(dai);
155
156 return 0;
157 }
158
test_dai_startup(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)159 static int test_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
160 {
161 mile_stone(dai);
162
163 return 0;
164 }
165
test_dai_shutdown(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)166 static void test_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
167 {
168 mile_stone(dai);
169 }
170
test_dai_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)171 static int test_dai_hw_params(struct snd_pcm_substream *substream,
172 struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
173 {
174 mile_stone(dai);
175
176 return 0;
177 }
178
test_dai_hw_free(struct snd_pcm_substream * substream,struct snd_soc_dai * dai)179 static int test_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
180 {
181 mile_stone(dai);
182
183 return 0;
184 }
185
test_dai_trigger(struct snd_pcm_substream * substream,int cmd,struct snd_soc_dai * dai)186 static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
187 {
188 mile_stone(dai);
189
190 return 0;
191 }
192
193 static const u64 test_dai_formats =
194 /*
195 * Select below from Sound Card, not auto
196 * SND_SOC_POSSIBLE_DAIFMT_BP_FP
197 * SND_SOC_POSSIBLE_DAIFMT_BC_FP
198 * SND_SOC_POSSIBLE_DAIFMT_BP_FC
199 * SND_SOC_POSSIBLE_DAIFMT_BC_FC
200 */
201 SND_SOC_POSSIBLE_DAIFMT_I2S |
202 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
203 SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
204 SND_SOC_POSSIBLE_DAIFMT_DSP_A |
205 SND_SOC_POSSIBLE_DAIFMT_DSP_B |
206 SND_SOC_POSSIBLE_DAIFMT_AC97 |
207 SND_SOC_POSSIBLE_DAIFMT_PDM |
208 SND_SOC_POSSIBLE_DAIFMT_NB_NF |
209 SND_SOC_POSSIBLE_DAIFMT_NB_IF |
210 SND_SOC_POSSIBLE_DAIFMT_IB_NF |
211 SND_SOC_POSSIBLE_DAIFMT_IB_IF;
212
213 static const struct snd_soc_dai_ops test_ops = {
214 .set_fmt = test_dai_set_fmt,
215 .set_tdm_slot = test_dai_set_tdm_slot,
216 .startup = test_dai_startup,
217 .shutdown = test_dai_shutdown,
218 .auto_selectable_formats = &test_dai_formats,
219 .num_auto_selectable_formats = 1,
220 };
221
222 static const struct snd_soc_dai_ops test_verbose_ops = {
223 .set_sysclk = test_dai_set_sysclk,
224 .set_pll = test_dai_set_pll,
225 .set_clkdiv = test_dai_set_clkdiv,
226 .set_fmt = test_dai_set_fmt,
227 .set_tdm_slot = test_dai_set_tdm_slot,
228 .mute_stream = test_dai_mute_stream,
229 .startup = test_dai_startup,
230 .shutdown = test_dai_shutdown,
231 .hw_params = test_dai_hw_params,
232 .hw_free = test_dai_hw_free,
233 .trigger = test_dai_trigger,
234 .auto_selectable_formats = &test_dai_formats,
235 .num_auto_selectable_formats = 1,
236 };
237
238 #define STUB_RATES SNDRV_PCM_RATE_CONTINUOUS
239 #define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
240 SNDRV_PCM_FMTBIT_U8 | \
241 SNDRV_PCM_FMTBIT_S16_LE | \
242 SNDRV_PCM_FMTBIT_U16_LE | \
243 SNDRV_PCM_FMTBIT_S24_LE | \
244 SNDRV_PCM_FMTBIT_S24_3LE | \
245 SNDRV_PCM_FMTBIT_U24_LE | \
246 SNDRV_PCM_FMTBIT_S32_LE | \
247 SNDRV_PCM_FMTBIT_U32_LE)
248
test_component_probe(struct snd_soc_component * component)249 static int test_component_probe(struct snd_soc_component *component)
250 {
251 mile_stone(component);
252
253 return 0;
254 }
255
test_component_remove(struct snd_soc_component * component)256 static void test_component_remove(struct snd_soc_component *component)
257 {
258 mile_stone(component);
259 }
260
test_component_suspend(struct snd_soc_component * component)261 static int test_component_suspend(struct snd_soc_component *component)
262 {
263 mile_stone(component);
264
265 return 0;
266 }
267
test_component_resume(struct snd_soc_component * component)268 static int test_component_resume(struct snd_soc_component *component)
269 {
270 mile_stone(component);
271
272 return 0;
273 }
274
275 #define PREALLOC_BUFFER (32 * 1024)
test_component_pcm_construct(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)276 static int test_component_pcm_construct(struct snd_soc_component *component,
277 struct snd_soc_pcm_runtime *rtd)
278 {
279 mile_stone(component);
280
281 snd_pcm_set_managed_buffer_all(
282 rtd->pcm,
283 SNDRV_DMA_TYPE_DEV,
284 rtd->card->snd_card->dev,
285 PREALLOC_BUFFER, PREALLOC_BUFFER);
286
287 return 0;
288 }
289
test_component_pcm_destruct(struct snd_soc_component * component,struct snd_pcm * pcm)290 static void test_component_pcm_destruct(struct snd_soc_component *component,
291 struct snd_pcm *pcm)
292 {
293 mile_stone(component);
294 }
295
test_component_set_sysclk(struct snd_soc_component * component,int clk_id,int source,unsigned int freq,int dir)296 static int test_component_set_sysclk(struct snd_soc_component *component,
297 int clk_id, int source, unsigned int freq, int dir)
298 {
299 mile_stone(component);
300
301 return 0;
302 }
303
test_component_set_pll(struct snd_soc_component * component,int pll_id,int source,unsigned int freq_in,unsigned int freq_out)304 static int test_component_set_pll(struct snd_soc_component *component, int pll_id,
305 int source, unsigned int freq_in, unsigned int freq_out)
306 {
307 mile_stone(component);
308
309 return 0;
310 }
311
test_component_set_jack(struct snd_soc_component * component,struct snd_soc_jack * jack,void * data)312 static int test_component_set_jack(struct snd_soc_component *component,
313 struct snd_soc_jack *jack, void *data)
314 {
315 mile_stone(component);
316
317 return 0;
318 }
319
test_component_seq_notifier(struct snd_soc_component * component,enum snd_soc_dapm_type type,int subseq)320 static void test_component_seq_notifier(struct snd_soc_component *component,
321 enum snd_soc_dapm_type type, int subseq)
322 {
323 mile_stone(component);
324 }
325
test_component_stream_event(struct snd_soc_component * component,int event)326 static int test_component_stream_event(struct snd_soc_component *component, int event)
327 {
328 mile_stone(component);
329
330 return 0;
331 }
332
test_component_set_bias_level(struct snd_soc_component * component,enum snd_soc_bias_level level)333 static int test_component_set_bias_level(struct snd_soc_component *component,
334 enum snd_soc_bias_level level)
335 {
336 mile_stone(component);
337
338 return 0;
339 }
340
341 static const struct snd_pcm_hardware test_component_hardware = {
342 /* Random values to keep userspace happy when checking constraints */
343 .info = SNDRV_PCM_INFO_INTERLEAVED |
344 SNDRV_PCM_INFO_MMAP |
345 SNDRV_PCM_INFO_MMAP_VALID,
346 .buffer_bytes_max = 32 * 1024,
347 .period_bytes_min = 32,
348 .period_bytes_max = 8192,
349 .periods_min = 1,
350 .periods_max = 128,
351 .fifo_size = 256,
352 };
353
test_component_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)354 static int test_component_open(struct snd_soc_component *component,
355 struct snd_pcm_substream *substream)
356 {
357 struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
358
359 mile_stone(component);
360
361 /* BE's dont need dummy params */
362 if (!rtd->dai_link->no_pcm)
363 snd_soc_set_runtime_hwparams(substream, &test_component_hardware);
364
365 return 0;
366 }
367
test_component_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)368 static int test_component_close(struct snd_soc_component *component,
369 struct snd_pcm_substream *substream)
370 {
371 mile_stone(component);
372
373 return 0;
374 }
375
test_component_ioctl(struct snd_soc_component * component,struct snd_pcm_substream * substream,unsigned int cmd,void * arg)376 static int test_component_ioctl(struct snd_soc_component *component,
377 struct snd_pcm_substream *substream,
378 unsigned int cmd, void *arg)
379 {
380 mile_stone(component);
381
382 return 0;
383 }
384
test_component_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)385 static int test_component_hw_params(struct snd_soc_component *component,
386 struct snd_pcm_substream *substream,
387 struct snd_pcm_hw_params *params)
388 {
389 mile_stone(component);
390
391 return 0;
392 }
393
test_component_hw_free(struct snd_soc_component * component,struct snd_pcm_substream * substream)394 static int test_component_hw_free(struct snd_soc_component *component,
395 struct snd_pcm_substream *substream)
396 {
397 mile_stone(component);
398
399 return 0;
400 }
401
test_component_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)402 static int test_component_prepare(struct snd_soc_component *component,
403 struct snd_pcm_substream *substream)
404 {
405 mile_stone(component);
406
407 return 0;
408 }
409
test_component_timer_stop(struct test_priv * priv)410 static void test_component_timer_stop(struct test_priv *priv)
411 {
412 cancel_delayed_work(&priv->dwork);
413 }
414
test_component_timer_start(struct test_priv * priv)415 static void test_component_timer_start(struct test_priv *priv)
416 {
417 schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10));
418 }
419
test_component_dwork(struct work_struct * work)420 static void test_component_dwork(struct work_struct *work)
421 {
422 struct test_priv *priv = container_of(work, struct test_priv, dwork.work);
423
424 if (priv->substream)
425 snd_pcm_period_elapsed(priv->substream);
426
427 test_component_timer_start(priv);
428 }
429
test_component_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)430 static int test_component_trigger(struct snd_soc_component *component,
431 struct snd_pcm_substream *substream, int cmd)
432 {
433 struct test_priv *priv = dev_get_drvdata(component->dev);
434
435 mile_stone(component);
436
437 switch (cmd) {
438 case SNDRV_PCM_TRIGGER_START:
439 test_component_timer_start(priv);
440 priv->substream = substream; /* set substream later */
441 break;
442 case SNDRV_PCM_TRIGGER_STOP:
443 priv->substream = NULL;
444 test_component_timer_stop(priv);
445 }
446
447 return 0;
448 }
449
test_component_sync_stop(struct snd_soc_component * component,struct snd_pcm_substream * substream)450 static int test_component_sync_stop(struct snd_soc_component *component,
451 struct snd_pcm_substream *substream)
452 {
453 mile_stone(component);
454
455 return 0;
456 }
457
test_component_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)458 static snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component,
459 struct snd_pcm_substream *substream)
460 {
461 struct snd_pcm_runtime *runtime = substream->runtime;
462 static int pointer;
463
464 if (!runtime)
465 return 0;
466
467 pointer += 10;
468 if (pointer > PREALLOC_BUFFER)
469 pointer = 0;
470
471 /* mile_stone(component); */
472
473 return bytes_to_frames(runtime, pointer);
474 }
475
test_component_get_time_info(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct timespec64 * system_ts,struct timespec64 * audio_ts,struct snd_pcm_audio_tstamp_config * audio_tstamp_config,struct snd_pcm_audio_tstamp_report * audio_tstamp_report)476 static int test_component_get_time_info(struct snd_soc_component *component,
477 struct snd_pcm_substream *substream,
478 struct timespec64 *system_ts,
479 struct timespec64 *audio_ts,
480 struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
481 struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
482 {
483 mile_stone(component);
484
485 return 0;
486 }
487
test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime * rtd,struct snd_pcm_hw_params * params)488 static int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
489 struct snd_pcm_hw_params *params)
490 {
491 mile_stone_x(rtd->dev);
492
493 return 0;
494 }
495
496 /* CPU */
497 static const struct test_adata test_cpu = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, };
498 static const struct test_adata test_cpu_vv = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, };
499 static const struct test_adata test_cpu_nv = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, };
500 static const struct test_adata test_cpu_vn = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, };
501 /* Codec */
502 static const struct test_adata test_codec = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, };
503 static const struct test_adata test_codec_vv = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, };
504 static const struct test_adata test_codec_nv = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, };
505 static const struct test_adata test_codec_vn = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, };
506
507 static const struct of_device_id test_of_match[] = {
508 { .compatible = "test-cpu", .data = (void *)&test_cpu, },
509 { .compatible = "test-cpu-verbose", .data = (void *)&test_cpu_vv, },
510 { .compatible = "test-cpu-verbose-dai", .data = (void *)&test_cpu_nv, },
511 { .compatible = "test-cpu-verbose-component", .data = (void *)&test_cpu_vn, },
512 { .compatible = "test-codec", .data = (void *)&test_codec, },
513 { .compatible = "test-codec-verbose", .data = (void *)&test_codec_vv, },
514 { .compatible = "test-codec-verbose-dai", .data = (void *)&test_codec_nv, },
515 { .compatible = "test-codec-verbose-component", .data = (void *)&test_codec_vn, },
516 {},
517 };
518 MODULE_DEVICE_TABLE(of, test_of_match);
519
520 static const struct snd_soc_dapm_widget widgets[] = {
521 /*
522 * FIXME
523 *
524 * Just IN/OUT is OK for now,
525 * but need to be updated ?
526 */
527 SND_SOC_DAPM_INPUT("IN"),
528 SND_SOC_DAPM_OUTPUT("OUT"),
529 };
530
test_driver_probe(struct platform_device * pdev)531 static int test_driver_probe(struct platform_device *pdev)
532 {
533 struct device *dev = &pdev->dev;
534 struct device_node *node = dev->of_node;
535 const struct test_adata *adata = of_device_get_match_data(&pdev->dev);
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 || !adata)
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 cdriv->legacy_dai_naming = 1;
569 } else {
570 cdriv->name = "test_codec";
571 cdriv->idle_bias_on = 1;
572 cdriv->endianness = 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_of_graph_port(node, port) {
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
test_driver_remove(struct platform_device * pdev)639 static void test_driver_remove(struct platform_device *pdev)
640 {
641 mile_stone_x(&pdev->dev);
642 }
643
644 static struct platform_driver test_driver = {
645 .driver = {
646 .name = "test-component",
647 .of_match_table = test_of_match,
648 },
649 .probe = test_driver_probe,
650 .remove = test_driver_remove,
651 };
652 module_platform_driver(test_driver);
653
654 MODULE_ALIAS("platform:asoc-test-component");
655 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
656 MODULE_DESCRIPTION("ASoC Test Component");
657 MODULE_LICENSE("GPL v2");
658