Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // test-component.c  --  Test Audio Component driver
0004 //
0005 // Copyright (C) 2020 Renesas Electronics Corporation
0006 // Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
0007 
0008 #include <linux/slab.h>
0009 #include <linux/of_device.h>
0010 #include <linux/of_graph.h>
0011 #include <linux/module.h>
0012 #include <linux/workqueue.h>
0013 #include <sound/pcm.h>
0014 #include <sound/soc.h>
0015 
0016 #define TEST_NAME_LEN 32
0017 struct test_dai_name {
0018     char name[TEST_NAME_LEN];
0019     char name_playback[TEST_NAME_LEN];
0020     char name_capture[TEST_NAME_LEN];
0021 };
0022 
0023 struct test_priv {
0024     struct device *dev;
0025     struct snd_pcm_substream *substream;
0026     struct delayed_work dwork;
0027     struct snd_soc_component_driver *component_driver;
0028     struct snd_soc_dai_driver *dai_driver;
0029     struct test_dai_name *name;
0030 };
0031 
0032 struct test_adata {
0033     u32 is_cpu:1;
0034     u32 cmp_v:1;
0035     u32 dai_v:1;
0036 };
0037 
0038 #define mile_stone(d)       dev_info((d)->dev, "%s() : %s", __func__, (d)->driver->name)
0039 #define mile_stone_x(dev)   dev_info(dev, "%s()", __func__)
0040 
0041 static int test_dai_set_sysclk(struct snd_soc_dai *dai,
0042                    int clk_id, unsigned int freq, int dir)
0043 {
0044     mile_stone(dai);
0045 
0046     return 0;
0047 }
0048 
0049 static int test_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
0050                 unsigned int freq_in, unsigned int freq_out)
0051 {
0052     mile_stone(dai);
0053 
0054     return 0;
0055 }
0056 
0057 static int test_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
0058 {
0059     mile_stone(dai);
0060 
0061     return 0;
0062 }
0063 
0064 static int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
0065 {
0066     unsigned int format = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
0067     unsigned int clock  = fmt & SND_SOC_DAIFMT_CLOCK_MASK;
0068     unsigned int inv    = fmt & SND_SOC_DAIFMT_INV_MASK;
0069     unsigned int master = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
0070     char *str;
0071 
0072     dev_info(dai->dev, "name   : %s", dai->name);
0073 
0074     str = "unknown";
0075     switch (format) {
0076     case SND_SOC_DAIFMT_I2S:
0077         str = "i2s";
0078         break;
0079     case SND_SOC_DAIFMT_RIGHT_J:
0080         str = "right_j";
0081         break;
0082     case SND_SOC_DAIFMT_LEFT_J:
0083         str = "left_j";
0084         break;
0085     case SND_SOC_DAIFMT_DSP_A:
0086         str = "dsp_a";
0087         break;
0088     case SND_SOC_DAIFMT_DSP_B:
0089         str = "dsp_b";
0090         break;
0091     case SND_SOC_DAIFMT_AC97:
0092         str = "ac97";
0093         break;
0094     case SND_SOC_DAIFMT_PDM:
0095         str = "pdm";
0096         break;
0097     }
0098     dev_info(dai->dev, "format : %s", str);
0099 
0100     if (clock == SND_SOC_DAIFMT_CONT)
0101         str = "continuous";
0102     else
0103         str = "gated";
0104     dev_info(dai->dev, "clock  : %s", str);
0105 
0106     str = "unknown";
0107     switch (master) {
0108     case SND_SOC_DAIFMT_BP_FP:
0109         str = "clk provider, frame provider";
0110         break;
0111     case SND_SOC_DAIFMT_BC_FP:
0112         str = "clk consumer, frame provider";
0113         break;
0114     case SND_SOC_DAIFMT_BP_FC:
0115         str = "clk provider, frame consumer";
0116         break;
0117     case SND_SOC_DAIFMT_BC_FC:
0118         str = "clk consumer, frame consumer";
0119         break;
0120     }
0121     dev_info(dai->dev, "clock  : codec is %s", str);
0122 
0123     str = "unknown";
0124     switch (inv) {
0125     case SND_SOC_DAIFMT_NB_NF:
0126         str = "normal bit, normal frame";
0127         break;
0128     case SND_SOC_DAIFMT_NB_IF:
0129         str = "normal bit, invert frame";
0130         break;
0131     case SND_SOC_DAIFMT_IB_NF:
0132         str = "invert bit, normal frame";
0133         break;
0134     case SND_SOC_DAIFMT_IB_IF:
0135         str = "invert bit, invert frame";
0136         break;
0137     }
0138     dev_info(dai->dev, "signal : %s", str);
0139 
0140     return 0;
0141 }
0142 
0143 static int test_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
0144 {
0145     mile_stone(dai);
0146 
0147     return 0;
0148 }
0149 
0150 static int test_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0151 {
0152     mile_stone(dai);
0153 
0154     return 0;
0155 }
0156 
0157 static void test_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0158 {
0159     mile_stone(dai);
0160 }
0161 
0162 static int test_dai_hw_params(struct snd_pcm_substream *substream,
0163                   struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
0164 {
0165     mile_stone(dai);
0166 
0167     return 0;
0168 }
0169 
0170 static int test_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
0171 {
0172     mile_stone(dai);
0173 
0174     return 0;
0175 }
0176 
0177 static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai)
0178 {
0179     mile_stone(dai);
0180 
0181     return 0;
0182 }
0183 
0184 static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream,
0185                     int cmd, struct snd_soc_dai *dai)
0186 {
0187     mile_stone(dai);
0188 
0189     return 0;
0190 }
0191 
0192 static u64 test_dai_formats =
0193     /*
0194      * Select below from Sound Card, not auto
0195      *  SND_SOC_POSSIBLE_DAIFMT_BP_FP
0196      *  SND_SOC_POSSIBLE_DAIFMT_BC_FP
0197      *  SND_SOC_POSSIBLE_DAIFMT_BP_FC
0198      *  SND_SOC_POSSIBLE_DAIFMT_BC_FC
0199      */
0200     SND_SOC_POSSIBLE_DAIFMT_I2S |
0201     SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
0202     SND_SOC_POSSIBLE_DAIFMT_LEFT_J  |
0203     SND_SOC_POSSIBLE_DAIFMT_DSP_A   |
0204     SND_SOC_POSSIBLE_DAIFMT_DSP_B   |
0205     SND_SOC_POSSIBLE_DAIFMT_AC97    |
0206     SND_SOC_POSSIBLE_DAIFMT_PDM |
0207     SND_SOC_POSSIBLE_DAIFMT_NB_NF   |
0208     SND_SOC_POSSIBLE_DAIFMT_NB_IF   |
0209     SND_SOC_POSSIBLE_DAIFMT_IB_NF   |
0210     SND_SOC_POSSIBLE_DAIFMT_IB_IF;
0211 
0212 static const struct snd_soc_dai_ops test_ops = {
0213     .set_fmt        = test_dai_set_fmt,
0214     .startup        = test_dai_startup,
0215     .shutdown       = test_dai_shutdown,
0216     .auto_selectable_formats    = &test_dai_formats,
0217     .num_auto_selectable_formats    = 1,
0218 };
0219 
0220 static const struct snd_soc_dai_ops test_verbose_ops = {
0221     .set_sysclk     = test_dai_set_sysclk,
0222     .set_pll        = test_dai_set_pll,
0223     .set_clkdiv     = test_dai_set_clkdiv,
0224     .set_fmt        = test_dai_set_fmt,
0225     .mute_stream        = test_dai_mute_stream,
0226     .startup        = test_dai_startup,
0227     .shutdown       = test_dai_shutdown,
0228     .hw_params      = test_dai_hw_params,
0229     .hw_free        = test_dai_hw_free,
0230     .trigger        = test_dai_trigger,
0231     .bespoke_trigger    = test_dai_bespoke_trigger,
0232     .auto_selectable_formats    = &test_dai_formats,
0233     .num_auto_selectable_formats    = 1,
0234 };
0235 
0236 #define STUB_RATES  SNDRV_PCM_RATE_8000_384000
0237 #define STUB_FORMATS    (SNDRV_PCM_FMTBIT_S8        | \
0238              SNDRV_PCM_FMTBIT_U8        | \
0239              SNDRV_PCM_FMTBIT_S16_LE    | \
0240              SNDRV_PCM_FMTBIT_U16_LE    | \
0241              SNDRV_PCM_FMTBIT_S24_LE    | \
0242              SNDRV_PCM_FMTBIT_S24_3LE   | \
0243              SNDRV_PCM_FMTBIT_U24_LE    | \
0244              SNDRV_PCM_FMTBIT_S32_LE    | \
0245              SNDRV_PCM_FMTBIT_U32_LE)
0246 
0247 static int test_component_probe(struct snd_soc_component *component)
0248 {
0249     mile_stone(component);
0250 
0251     return 0;
0252 }
0253 
0254 static void test_component_remove(struct snd_soc_component *component)
0255 {
0256     mile_stone(component);
0257 }
0258 
0259 static int test_component_suspend(struct snd_soc_component *component)
0260 {
0261     mile_stone(component);
0262 
0263     return 0;
0264 }
0265 
0266 static int test_component_resume(struct snd_soc_component *component)
0267 {
0268     mile_stone(component);
0269 
0270     return 0;
0271 }
0272 
0273 #define PREALLOC_BUFFER     (32 * 1024)
0274 static int test_component_pcm_construct(struct snd_soc_component *component,
0275                     struct snd_soc_pcm_runtime *rtd)
0276 {
0277     mile_stone(component);
0278 
0279     snd_pcm_set_managed_buffer_all(
0280         rtd->pcm,
0281         SNDRV_DMA_TYPE_DEV,
0282         rtd->card->snd_card->dev,
0283         PREALLOC_BUFFER, PREALLOC_BUFFER);
0284 
0285     return 0;
0286 }
0287 
0288 static void test_component_pcm_destruct(struct snd_soc_component *component,
0289                     struct snd_pcm *pcm)
0290 {
0291     mile_stone(component);
0292 }
0293 
0294 static int test_component_set_sysclk(struct snd_soc_component *component,
0295                      int clk_id, int source, unsigned int freq, int dir)
0296 {
0297     mile_stone(component);
0298 
0299     return 0;
0300 }
0301 
0302 static int test_component_set_pll(struct snd_soc_component *component, int pll_id,
0303                   int source, unsigned int freq_in, unsigned int freq_out)
0304 {
0305     mile_stone(component);
0306 
0307     return 0;
0308 }
0309 
0310 static int test_component_set_jack(struct snd_soc_component *component,
0311                    struct snd_soc_jack *jack,  void *data)
0312 {
0313     mile_stone(component);
0314 
0315     return 0;
0316 }
0317 
0318 static void test_component_seq_notifier(struct snd_soc_component *component,
0319                     enum snd_soc_dapm_type type, int subseq)
0320 {
0321     mile_stone(component);
0322 }
0323 
0324 static int test_component_stream_event(struct snd_soc_component *component, int event)
0325 {
0326     mile_stone(component);
0327 
0328     return 0;
0329 }
0330 
0331 static int test_component_set_bias_level(struct snd_soc_component *component,
0332                      enum snd_soc_bias_level level)
0333 {
0334     mile_stone(component);
0335 
0336     return 0;
0337 }
0338 
0339 static const struct snd_pcm_hardware test_component_hardware = {
0340     /* Random values to keep userspace happy when checking constraints */
0341     .info           = SNDRV_PCM_INFO_INTERLEAVED    |
0342                   SNDRV_PCM_INFO_MMAP       |
0343                   SNDRV_PCM_INFO_MMAP_VALID,
0344     .buffer_bytes_max   = 32 * 1024,
0345     .period_bytes_min   = 32,
0346     .period_bytes_max   = 8192,
0347     .periods_min        = 1,
0348     .periods_max        = 128,
0349     .fifo_size      = 256,
0350 };
0351 
0352 static int test_component_open(struct snd_soc_component *component,
0353                    struct snd_pcm_substream *substream)
0354 {
0355     struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
0356 
0357     mile_stone(component);
0358 
0359     /* BE's dont need dummy params */
0360     if (!rtd->dai_link->no_pcm)
0361         snd_soc_set_runtime_hwparams(substream, &test_component_hardware);
0362 
0363     return 0;
0364 }
0365 
0366 static int test_component_close(struct snd_soc_component *component,
0367                 struct snd_pcm_substream *substream)
0368 {
0369     mile_stone(component);
0370 
0371     return 0;
0372 }
0373 
0374 static int test_component_ioctl(struct snd_soc_component *component,
0375                 struct snd_pcm_substream *substream,
0376                 unsigned int cmd, void *arg)
0377 {
0378     mile_stone(component);
0379 
0380     return 0;
0381 }
0382 
0383 static int test_component_hw_params(struct snd_soc_component *component,
0384                     struct snd_pcm_substream *substream,
0385                     struct snd_pcm_hw_params *params)
0386 {
0387     mile_stone(component);
0388 
0389     return 0;
0390 }
0391 
0392 static int test_component_hw_free(struct snd_soc_component *component,
0393                   struct snd_pcm_substream *substream)
0394 {
0395     mile_stone(component);
0396 
0397     return 0;
0398 }
0399 
0400 static int test_component_prepare(struct snd_soc_component *component,
0401                   struct snd_pcm_substream *substream)
0402 {
0403     mile_stone(component);
0404 
0405     return 0;
0406 }
0407 
0408 static void test_component_timer_stop(struct test_priv *priv)
0409 {
0410     cancel_delayed_work(&priv->dwork);
0411 }
0412 
0413 static void test_component_timer_start(struct test_priv *priv)
0414 {
0415     schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10));
0416 }
0417 
0418 static void test_component_dwork(struct work_struct *work)
0419 {
0420     struct test_priv *priv = container_of(work, struct test_priv, dwork.work);
0421 
0422     if (priv->substream)
0423         snd_pcm_period_elapsed(priv->substream);
0424 
0425     test_component_timer_start(priv);
0426 }
0427 
0428 static int test_component_trigger(struct snd_soc_component *component,
0429                   struct snd_pcm_substream *substream, int cmd)
0430 {
0431     struct test_priv *priv = dev_get_drvdata(component->dev);
0432 
0433     mile_stone(component);
0434 
0435     switch (cmd) {
0436     case SNDRV_PCM_TRIGGER_START:
0437         test_component_timer_start(priv);
0438         priv->substream = substream; /* set substream later */
0439         break;
0440     case SNDRV_PCM_TRIGGER_STOP:
0441         priv->substream = NULL;
0442         test_component_timer_stop(priv);
0443     }
0444 
0445     return 0;
0446 }
0447 
0448 static int test_component_sync_stop(struct snd_soc_component *component,
0449                     struct snd_pcm_substream *substream)
0450 {
0451     mile_stone(component);
0452 
0453     return 0;
0454 }
0455 
0456 static snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component,
0457                         struct snd_pcm_substream *substream)
0458 {
0459     struct snd_pcm_runtime *runtime = substream->runtime;
0460     static int pointer;
0461 
0462     if (!runtime)
0463         return 0;
0464 
0465     pointer += 10;
0466     if (pointer > PREALLOC_BUFFER)
0467         pointer = 0;
0468 
0469     /* mile_stone(component); */
0470 
0471     return bytes_to_frames(runtime, pointer);
0472 }
0473 
0474 static int test_component_get_time_info(struct snd_soc_component *component,
0475                     struct snd_pcm_substream *substream,
0476                     struct timespec64 *system_ts,
0477                     struct timespec64 *audio_ts,
0478                     struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
0479                     struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
0480 {
0481     mile_stone(component);
0482 
0483     return 0;
0484 }
0485 
0486 static int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
0487                          struct snd_pcm_hw_params *params)
0488 {
0489     mile_stone_x(rtd->dev);
0490 
0491     return 0;
0492 }
0493 
0494 /* CPU */
0495 static const struct test_adata test_cpu     = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, };
0496 static const struct test_adata test_cpu_vv  = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, };
0497 static const struct test_adata test_cpu_nv  = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, };
0498 static const struct test_adata test_cpu_vn  = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, };
0499 /* Codec */
0500 static const struct test_adata test_codec   = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, };
0501 static const struct test_adata test_codec_vv    = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, };
0502 static const struct test_adata test_codec_nv    = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, };
0503 static const struct test_adata test_codec_vn    = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, };
0504 
0505 static const struct of_device_id test_of_match[] = {
0506     { .compatible = "test-cpu",         .data = (void *)&test_cpu,    },
0507     { .compatible = "test-cpu-verbose",     .data = (void *)&test_cpu_vv, },
0508     { .compatible = "test-cpu-verbose-dai",     .data = (void *)&test_cpu_nv, },
0509     { .compatible = "test-cpu-verbose-component",   .data = (void *)&test_cpu_vn, },
0510     { .compatible = "test-codec",           .data = (void *)&test_codec,    },
0511     { .compatible = "test-codec-verbose",       .data = (void *)&test_codec_vv, },
0512     { .compatible = "test-codec-verbose-dai",   .data = (void *)&test_codec_nv, },
0513     { .compatible = "test-codec-verbose-component", .data = (void *)&test_codec_vn, },
0514     {},
0515 };
0516 MODULE_DEVICE_TABLE(of, test_of_match);
0517 
0518 static const struct snd_soc_dapm_widget widgets[] = {
0519     /*
0520      * FIXME
0521      *
0522      * Just IN/OUT is OK for now,
0523      * but need to be updated ?
0524      */
0525     SND_SOC_DAPM_INPUT("IN"),
0526     SND_SOC_DAPM_OUTPUT("OUT"),
0527 };
0528 
0529 static int test_driver_probe(struct platform_device *pdev)
0530 {
0531     struct device *dev = &pdev->dev;
0532     struct device_node *node = dev->of_node;
0533     struct device_node *ep;
0534     const struct test_adata *adata = of_device_get_match_data(&pdev->dev);
0535     struct snd_soc_component_driver *cdriv;
0536     struct snd_soc_dai_driver *ddriv;
0537     struct test_dai_name *dname;
0538     struct test_priv *priv;
0539     int num, ret, i;
0540 
0541     num = of_graph_get_endpoint_count(node);
0542     if (!num) {
0543         dev_err(dev, "no port exits\n");
0544         return -EINVAL;
0545     }
0546 
0547     priv    = devm_kzalloc(dev, sizeof(*priv),      GFP_KERNEL);
0548     cdriv   = devm_kzalloc(dev, sizeof(*cdriv),     GFP_KERNEL);
0549     ddriv   = devm_kzalloc(dev, sizeof(*ddriv) * num,   GFP_KERNEL);
0550     dname   = devm_kzalloc(dev, sizeof(*dname) * num,   GFP_KERNEL);
0551     if (!priv || !cdriv || !ddriv || !dname || !adata)
0552         return -EINVAL;
0553 
0554     priv->dev       = dev;
0555     priv->component_driver  = cdriv;
0556     priv->dai_driver    = ddriv;
0557     priv->name      = dname;
0558 
0559     INIT_DELAYED_WORK(&priv->dwork, test_component_dwork);
0560     dev_set_drvdata(dev, priv);
0561 
0562     if (adata->is_cpu) {
0563         cdriv->name         = "test_cpu";
0564         cdriv->pcm_construct        = test_component_pcm_construct;
0565         cdriv->pointer          = test_component_pointer;
0566         cdriv->trigger          = test_component_trigger;
0567         cdriv->legacy_dai_naming    = 1;
0568     } else {
0569         cdriv->name         = "test_codec";
0570         cdriv->idle_bias_on     = 1;
0571         cdriv->endianness       = 1;
0572     }
0573 
0574     cdriv->open     = test_component_open;
0575     cdriv->dapm_widgets = widgets;
0576     cdriv->num_dapm_widgets = ARRAY_SIZE(widgets);
0577 
0578     if (adata->cmp_v) {
0579         cdriv->probe            = test_component_probe;
0580         cdriv->remove           = test_component_remove;
0581         cdriv->suspend          = test_component_suspend;
0582         cdriv->resume           = test_component_resume;
0583         cdriv->set_sysclk       = test_component_set_sysclk;
0584         cdriv->set_pll          = test_component_set_pll;
0585         cdriv->set_jack         = test_component_set_jack;
0586         cdriv->seq_notifier     = test_component_seq_notifier;
0587         cdriv->stream_event     = test_component_stream_event;
0588         cdriv->set_bias_level       = test_component_set_bias_level;
0589         cdriv->close            = test_component_close;
0590         cdriv->ioctl            = test_component_ioctl;
0591         cdriv->hw_params        = test_component_hw_params;
0592         cdriv->hw_free          = test_component_hw_free;
0593         cdriv->prepare          = test_component_prepare;
0594         cdriv->sync_stop        = test_component_sync_stop;
0595         cdriv->get_time_info        = test_component_get_time_info;
0596         cdriv->be_hw_params_fixup   = test_component_be_hw_params_fixup;
0597 
0598         if (adata->is_cpu)
0599             cdriv->pcm_destruct = test_component_pcm_destruct;
0600     }
0601 
0602     i = 0;
0603     for_each_endpoint_of_node(node, ep) {
0604         snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i);
0605         ddriv[i].name = dname[i].name;
0606 
0607         snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i);
0608         ddriv[i].playback.stream_name   = dname[i].name_playback;
0609         ddriv[i].playback.channels_min  = 1;
0610         ddriv[i].playback.channels_max  = 384;
0611         ddriv[i].playback.rates     = STUB_RATES;
0612         ddriv[i].playback.formats   = STUB_FORMATS;
0613 
0614         snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i);
0615         ddriv[i].capture.stream_name    = dname[i].name_capture;
0616         ddriv[i].capture.channels_min   = 1;
0617         ddriv[i].capture.channels_max   = 384;
0618         ddriv[i].capture.rates      = STUB_RATES;
0619         ddriv[i].capture.formats    = STUB_FORMATS;
0620 
0621         if (adata->dai_v)
0622             ddriv[i].ops = &test_verbose_ops;
0623         else
0624             ddriv[i].ops = &test_ops;
0625 
0626         i++;
0627     }
0628 
0629     ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num);
0630     if (ret < 0)
0631         return ret;
0632 
0633     mile_stone_x(dev);
0634 
0635     return 0;
0636 }
0637 
0638 static int test_driver_remove(struct platform_device *pdev)
0639 {
0640     mile_stone_x(&pdev->dev);
0641 
0642     return 0;
0643 }
0644 
0645 static struct platform_driver test_driver = {
0646     .driver = {
0647         .name = "test-component",
0648         .of_match_table = test_of_match,
0649     },
0650     .probe  = test_driver_probe,
0651     .remove = test_driver_remove,
0652 };
0653 module_platform_driver(test_driver);
0654 
0655 MODULE_ALIAS("platform:asoc-test-component");
0656 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
0657 MODULE_DESCRIPTION("ASoC Test Component");
0658 MODULE_LICENSE("GPL v2");