Commit | Line | Data |
---|---|---|
d293abc0 KM |
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; | |
d444c8d2 | 69 | unsigned int master = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; |
d293abc0 KM |
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) { | |
d444c8d2 | 108 | case SND_SOC_DAIFMT_BP_FP: |
d293abc0 KM |
109 | str = "clk provider, frame provider"; |
110 | break; | |
d444c8d2 | 111 | case SND_SOC_DAIFMT_BC_FP: |
d293abc0 KM |
112 | str = "clk consumer, frame provider"; |
113 | break; | |
d444c8d2 | 114 | case SND_SOC_DAIFMT_BP_FC: |
d293abc0 KM |
115 | str = "clk provider, frame consumer"; |
116 | break; | |
d444c8d2 | 117 | case SND_SOC_DAIFMT_BC_FC: |
d293abc0 KM |
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 | |
d444c8d2 CK |
195 | * SND_SOC_POSSIBLE_DAIFMT_BP_FP |
196 | * SND_SOC_POSSIBLE_DAIFMT_BC_FP | |
197 | * SND_SOC_POSSIBLE_DAIFMT_BP_FC | |
198 | * SND_SOC_POSSIBLE_DAIFMT_BC_FC | |
d293abc0 KM |
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 = { | |
408c122e | 213 | .set_fmt = test_dai_set_fmt, |
d293abc0 KM |
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, | |
408c122e | 224 | .set_fmt = test_dai_set_fmt, |
d293abc0 KM |
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; | |
befe3045 | 534 | const struct test_adata *adata = of_device_get_match_data(&pdev->dev); |
d293abc0 KM |
535 | struct snd_soc_component_driver *cdriv; |
536 | struct snd_soc_dai_driver *ddriv; | |
537 | struct test_dai_name *dname; | |
538 | struct test_priv *priv; | |
539 | int num, ret, i; | |
540 | ||
541 | num = of_graph_get_endpoint_count(node); | |
542 | if (!num) { | |
543 | dev_err(dev, "no port exits\n"); | |
544 | return -EINVAL; | |
545 | } | |
546 | ||
547 | priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
548 | cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); | |
549 | ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); | |
550 | dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); | |
befe3045 | 551 | if (!priv || !cdriv || !ddriv || !dname || !adata) |
d293abc0 KM |
552 | return -EINVAL; |
553 | ||
554 | priv->dev = dev; | |
555 | priv->component_driver = cdriv; | |
556 | priv->dai_driver = ddriv; | |
557 | priv->name = dname; | |
558 | ||
559 | INIT_DELAYED_WORK(&priv->dwork, test_component_dwork); | |
560 | dev_set_drvdata(dev, priv); | |
561 | ||
562 | if (adata->is_cpu) { | |
563 | cdriv->name = "test_cpu"; | |
564 | cdriv->pcm_construct = test_component_pcm_construct; | |
565 | cdriv->pointer = test_component_pointer; | |
566 | cdriv->trigger = test_component_trigger; | |
d73130ba | 567 | cdriv->legacy_dai_naming = 1; |
d293abc0 KM |
568 | } else { |
569 | cdriv->name = "test_codec"; | |
570 | cdriv->idle_bias_on = 1; | |
571 | cdriv->endianness = 1; | |
d293abc0 KM |
572 | } |
573 | ||
574 | cdriv->open = test_component_open; | |
575 | cdriv->dapm_widgets = widgets; | |
576 | cdriv->num_dapm_widgets = ARRAY_SIZE(widgets); | |
577 | ||
578 | if (adata->cmp_v) { | |
579 | cdriv->probe = test_component_probe; | |
580 | cdriv->remove = test_component_remove; | |
581 | cdriv->suspend = test_component_suspend; | |
582 | cdriv->resume = test_component_resume; | |
583 | cdriv->set_sysclk = test_component_set_sysclk; | |
584 | cdriv->set_pll = test_component_set_pll; | |
585 | cdriv->set_jack = test_component_set_jack; | |
586 | cdriv->seq_notifier = test_component_seq_notifier; | |
587 | cdriv->stream_event = test_component_stream_event; | |
588 | cdriv->set_bias_level = test_component_set_bias_level; | |
589 | cdriv->close = test_component_close; | |
590 | cdriv->ioctl = test_component_ioctl; | |
591 | cdriv->hw_params = test_component_hw_params; | |
592 | cdriv->hw_free = test_component_hw_free; | |
593 | cdriv->prepare = test_component_prepare; | |
594 | cdriv->sync_stop = test_component_sync_stop; | |
595 | cdriv->get_time_info = test_component_get_time_info; | |
596 | cdriv->be_hw_params_fixup = test_component_be_hw_params_fixup; | |
597 | ||
598 | if (adata->is_cpu) | |
599 | cdriv->pcm_destruct = test_component_pcm_destruct; | |
600 | } | |
601 | ||
602 | i = 0; | |
603 | for_each_endpoint_of_node(node, ep) { | |
604 | snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i); | |
605 | ddriv[i].name = dname[i].name; | |
606 | ||
607 | snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i); | |
608 | ddriv[i].playback.stream_name = dname[i].name_playback; | |
609 | ddriv[i].playback.channels_min = 1; | |
610 | ddriv[i].playback.channels_max = 384; | |
611 | ddriv[i].playback.rates = STUB_RATES; | |
612 | ddriv[i].playback.formats = STUB_FORMATS; | |
613 | ||
614 | snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i); | |
615 | ddriv[i].capture.stream_name = dname[i].name_capture; | |
616 | ddriv[i].capture.channels_min = 1; | |
617 | ddriv[i].capture.channels_max = 384; | |
618 | ddriv[i].capture.rates = STUB_RATES; | |
619 | ddriv[i].capture.formats = STUB_FORMATS; | |
620 | ||
621 | if (adata->dai_v) | |
622 | ddriv[i].ops = &test_verbose_ops; | |
623 | else | |
624 | ddriv[i].ops = &test_ops; | |
625 | ||
626 | i++; | |
627 | } | |
628 | ||
629 | ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num); | |
630 | if (ret < 0) | |
631 | return ret; | |
632 | ||
633 | mile_stone_x(dev); | |
634 | ||
635 | return 0; | |
636 | } | |
637 | ||
53946256 | 638 | static void test_driver_remove(struct platform_device *pdev) |
d293abc0 KM |
639 | { |
640 | mile_stone_x(&pdev->dev); | |
d293abc0 KM |
641 | } |
642 | ||
643 | static struct platform_driver test_driver = { | |
644 | .driver = { | |
645 | .name = "test-component", | |
646 | .of_match_table = test_of_match, | |
647 | }, | |
648 | .probe = test_driver_probe, | |
53946256 | 649 | .remove_new = test_driver_remove, |
d293abc0 KM |
650 | }; |
651 | module_platform_driver(test_driver); | |
652 | ||
653 | MODULE_ALIAS("platform:asoc-test-component"); | |
654 | MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); | |
655 | MODULE_DESCRIPTION("ASoC Test Component"); | |
656 | MODULE_LICENSE("GPL v2"); |