162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci// 362306a36Sopenharmony_ci// test-component.c -- Test Audio Component driver 462306a36Sopenharmony_ci// 562306a36Sopenharmony_ci// Copyright (C) 2020 Renesas Electronics Corporation 662306a36Sopenharmony_ci// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/slab.h> 962306a36Sopenharmony_ci#include <linux/of_device.h> 1062306a36Sopenharmony_ci#include <linux/of_graph.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/workqueue.h> 1362306a36Sopenharmony_ci#include <sound/pcm.h> 1462306a36Sopenharmony_ci#include <sound/soc.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#define TEST_NAME_LEN 32 1762306a36Sopenharmony_cistruct test_dai_name { 1862306a36Sopenharmony_ci char name[TEST_NAME_LEN]; 1962306a36Sopenharmony_ci char name_playback[TEST_NAME_LEN]; 2062306a36Sopenharmony_ci char name_capture[TEST_NAME_LEN]; 2162306a36Sopenharmony_ci}; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistruct test_priv { 2462306a36Sopenharmony_ci struct device *dev; 2562306a36Sopenharmony_ci struct snd_pcm_substream *substream; 2662306a36Sopenharmony_ci struct delayed_work dwork; 2762306a36Sopenharmony_ci struct snd_soc_component_driver *component_driver; 2862306a36Sopenharmony_ci struct snd_soc_dai_driver *dai_driver; 2962306a36Sopenharmony_ci struct test_dai_name *name; 3062306a36Sopenharmony_ci}; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistruct test_adata { 3362306a36Sopenharmony_ci u32 is_cpu:1; 3462306a36Sopenharmony_ci u32 cmp_v:1; 3562306a36Sopenharmony_ci u32 dai_v:1; 3662306a36Sopenharmony_ci}; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define mile_stone(d) dev_info((d)->dev, "%s() : %s", __func__, (d)->driver->name) 3962306a36Sopenharmony_ci#define mile_stone_x(dev) dev_info(dev, "%s()", __func__) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistatic int test_dai_set_sysclk(struct snd_soc_dai *dai, 4262306a36Sopenharmony_ci int clk_id, unsigned int freq, int dir) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci mile_stone(dai); 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic int test_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, 5062306a36Sopenharmony_ci unsigned int freq_in, unsigned int freq_out) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci mile_stone(dai); 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return 0; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic int test_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) 5862306a36Sopenharmony_ci{ 5962306a36Sopenharmony_ci mile_stone(dai); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci unsigned int format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; 6762306a36Sopenharmony_ci unsigned int clock = fmt & SND_SOC_DAIFMT_CLOCK_MASK; 6862306a36Sopenharmony_ci unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK; 6962306a36Sopenharmony_ci unsigned int master = fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK; 7062306a36Sopenharmony_ci char *str; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci dev_info(dai->dev, "name : %s", dai->name); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci str = "unknown"; 7562306a36Sopenharmony_ci switch (format) { 7662306a36Sopenharmony_ci case SND_SOC_DAIFMT_I2S: 7762306a36Sopenharmony_ci str = "i2s"; 7862306a36Sopenharmony_ci break; 7962306a36Sopenharmony_ci case SND_SOC_DAIFMT_RIGHT_J: 8062306a36Sopenharmony_ci str = "right_j"; 8162306a36Sopenharmony_ci break; 8262306a36Sopenharmony_ci case SND_SOC_DAIFMT_LEFT_J: 8362306a36Sopenharmony_ci str = "left_j"; 8462306a36Sopenharmony_ci break; 8562306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_A: 8662306a36Sopenharmony_ci str = "dsp_a"; 8762306a36Sopenharmony_ci break; 8862306a36Sopenharmony_ci case SND_SOC_DAIFMT_DSP_B: 8962306a36Sopenharmony_ci str = "dsp_b"; 9062306a36Sopenharmony_ci break; 9162306a36Sopenharmony_ci case SND_SOC_DAIFMT_AC97: 9262306a36Sopenharmony_ci str = "ac97"; 9362306a36Sopenharmony_ci break; 9462306a36Sopenharmony_ci case SND_SOC_DAIFMT_PDM: 9562306a36Sopenharmony_ci str = "pdm"; 9662306a36Sopenharmony_ci break; 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci dev_info(dai->dev, "format : %s", str); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci if (clock == SND_SOC_DAIFMT_CONT) 10162306a36Sopenharmony_ci str = "continuous"; 10262306a36Sopenharmony_ci else 10362306a36Sopenharmony_ci str = "gated"; 10462306a36Sopenharmony_ci dev_info(dai->dev, "clock : %s", str); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci str = "unknown"; 10762306a36Sopenharmony_ci switch (master) { 10862306a36Sopenharmony_ci case SND_SOC_DAIFMT_BP_FP: 10962306a36Sopenharmony_ci str = "clk provider, frame provider"; 11062306a36Sopenharmony_ci break; 11162306a36Sopenharmony_ci case SND_SOC_DAIFMT_BC_FP: 11262306a36Sopenharmony_ci str = "clk consumer, frame provider"; 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci case SND_SOC_DAIFMT_BP_FC: 11562306a36Sopenharmony_ci str = "clk provider, frame consumer"; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci case SND_SOC_DAIFMT_BC_FC: 11862306a36Sopenharmony_ci str = "clk consumer, frame consumer"; 11962306a36Sopenharmony_ci break; 12062306a36Sopenharmony_ci } 12162306a36Sopenharmony_ci dev_info(dai->dev, "clock : codec is %s", str); 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci str = "unknown"; 12462306a36Sopenharmony_ci switch (inv) { 12562306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_NF: 12662306a36Sopenharmony_ci str = "normal bit, normal frame"; 12762306a36Sopenharmony_ci break; 12862306a36Sopenharmony_ci case SND_SOC_DAIFMT_NB_IF: 12962306a36Sopenharmony_ci str = "normal bit, invert frame"; 13062306a36Sopenharmony_ci break; 13162306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_NF: 13262306a36Sopenharmony_ci str = "invert bit, normal frame"; 13362306a36Sopenharmony_ci break; 13462306a36Sopenharmony_ci case SND_SOC_DAIFMT_IB_IF: 13562306a36Sopenharmony_ci str = "invert bit, invert frame"; 13662306a36Sopenharmony_ci break; 13762306a36Sopenharmony_ci } 13862306a36Sopenharmony_ci dev_info(dai->dev, "signal : %s", str); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci return 0; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic int test_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci mile_stone(dai); 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci return 0; 14862306a36Sopenharmony_ci} 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_cistatic int test_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 15162306a36Sopenharmony_ci{ 15262306a36Sopenharmony_ci mile_stone(dai); 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci return 0; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_cistatic void test_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 15862306a36Sopenharmony_ci{ 15962306a36Sopenharmony_ci mile_stone(dai); 16062306a36Sopenharmony_ci} 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_cistatic int test_dai_hw_params(struct snd_pcm_substream *substream, 16362306a36Sopenharmony_ci struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) 16462306a36Sopenharmony_ci{ 16562306a36Sopenharmony_ci mile_stone(dai); 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci return 0; 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int test_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci mile_stone(dai); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_cistatic int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) 17862306a36Sopenharmony_ci{ 17962306a36Sopenharmony_ci mile_stone(dai); 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return 0; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, 18562306a36Sopenharmony_ci int cmd, struct snd_soc_dai *dai) 18662306a36Sopenharmony_ci{ 18762306a36Sopenharmony_ci mile_stone(dai); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci return 0; 19062306a36Sopenharmony_ci} 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic u64 test_dai_formats = 19362306a36Sopenharmony_ci /* 19462306a36Sopenharmony_ci * Select below from Sound Card, not auto 19562306a36Sopenharmony_ci * SND_SOC_POSSIBLE_DAIFMT_BP_FP 19662306a36Sopenharmony_ci * SND_SOC_POSSIBLE_DAIFMT_BC_FP 19762306a36Sopenharmony_ci * SND_SOC_POSSIBLE_DAIFMT_BP_FC 19862306a36Sopenharmony_ci * SND_SOC_POSSIBLE_DAIFMT_BC_FC 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_I2S | 20162306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | 20262306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_LEFT_J | 20362306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_DSP_A | 20462306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_DSP_B | 20562306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_AC97 | 20662306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_PDM | 20762306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_NB_NF | 20862306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_NB_IF | 20962306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_IB_NF | 21062306a36Sopenharmony_ci SND_SOC_POSSIBLE_DAIFMT_IB_IF; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic const struct snd_soc_dai_ops test_ops = { 21362306a36Sopenharmony_ci .set_fmt = test_dai_set_fmt, 21462306a36Sopenharmony_ci .startup = test_dai_startup, 21562306a36Sopenharmony_ci .shutdown = test_dai_shutdown, 21662306a36Sopenharmony_ci .auto_selectable_formats = &test_dai_formats, 21762306a36Sopenharmony_ci .num_auto_selectable_formats = 1, 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic const struct snd_soc_dai_ops test_verbose_ops = { 22162306a36Sopenharmony_ci .set_sysclk = test_dai_set_sysclk, 22262306a36Sopenharmony_ci .set_pll = test_dai_set_pll, 22362306a36Sopenharmony_ci .set_clkdiv = test_dai_set_clkdiv, 22462306a36Sopenharmony_ci .set_fmt = test_dai_set_fmt, 22562306a36Sopenharmony_ci .mute_stream = test_dai_mute_stream, 22662306a36Sopenharmony_ci .startup = test_dai_startup, 22762306a36Sopenharmony_ci .shutdown = test_dai_shutdown, 22862306a36Sopenharmony_ci .hw_params = test_dai_hw_params, 22962306a36Sopenharmony_ci .hw_free = test_dai_hw_free, 23062306a36Sopenharmony_ci .trigger = test_dai_trigger, 23162306a36Sopenharmony_ci .bespoke_trigger = test_dai_bespoke_trigger, 23262306a36Sopenharmony_ci .auto_selectable_formats = &test_dai_formats, 23362306a36Sopenharmony_ci .num_auto_selectable_formats = 1, 23462306a36Sopenharmony_ci}; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci#define STUB_RATES SNDRV_PCM_RATE_8000_384000 23762306a36Sopenharmony_ci#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ 23862306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_U8 | \ 23962306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S16_LE | \ 24062306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_U16_LE | \ 24162306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_LE | \ 24262306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S24_3LE | \ 24362306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_U24_LE | \ 24462306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_S32_LE | \ 24562306a36Sopenharmony_ci SNDRV_PCM_FMTBIT_U32_LE) 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic int test_component_probe(struct snd_soc_component *component) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci mile_stone(component); 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci return 0; 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic void test_component_remove(struct snd_soc_component *component) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci mile_stone(component); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic int test_component_suspend(struct snd_soc_component *component) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci mile_stone(component); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci return 0; 26462306a36Sopenharmony_ci} 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic int test_component_resume(struct snd_soc_component *component) 26762306a36Sopenharmony_ci{ 26862306a36Sopenharmony_ci mile_stone(component); 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci return 0; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci#define PREALLOC_BUFFER (32 * 1024) 27462306a36Sopenharmony_cistatic int test_component_pcm_construct(struct snd_soc_component *component, 27562306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci mile_stone(component); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci snd_pcm_set_managed_buffer_all( 28062306a36Sopenharmony_ci rtd->pcm, 28162306a36Sopenharmony_ci SNDRV_DMA_TYPE_DEV, 28262306a36Sopenharmony_ci rtd->card->snd_card->dev, 28362306a36Sopenharmony_ci PREALLOC_BUFFER, PREALLOC_BUFFER); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return 0; 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic void test_component_pcm_destruct(struct snd_soc_component *component, 28962306a36Sopenharmony_ci struct snd_pcm *pcm) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci mile_stone(component); 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic int test_component_set_sysclk(struct snd_soc_component *component, 29562306a36Sopenharmony_ci int clk_id, int source, unsigned int freq, int dir) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci mile_stone(component); 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci return 0; 30062306a36Sopenharmony_ci} 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_cistatic int test_component_set_pll(struct snd_soc_component *component, int pll_id, 30362306a36Sopenharmony_ci int source, unsigned int freq_in, unsigned int freq_out) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci mile_stone(component); 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci return 0; 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic int test_component_set_jack(struct snd_soc_component *component, 31162306a36Sopenharmony_ci struct snd_soc_jack *jack, void *data) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci mile_stone(component); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return 0; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic void test_component_seq_notifier(struct snd_soc_component *component, 31962306a36Sopenharmony_ci enum snd_soc_dapm_type type, int subseq) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci mile_stone(component); 32262306a36Sopenharmony_ci} 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_cistatic int test_component_stream_event(struct snd_soc_component *component, int event) 32562306a36Sopenharmony_ci{ 32662306a36Sopenharmony_ci mile_stone(component); 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci return 0; 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_cistatic int test_component_set_bias_level(struct snd_soc_component *component, 33262306a36Sopenharmony_ci enum snd_soc_bias_level level) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci mile_stone(component); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci return 0; 33762306a36Sopenharmony_ci} 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic const struct snd_pcm_hardware test_component_hardware = { 34062306a36Sopenharmony_ci /* Random values to keep userspace happy when checking constraints */ 34162306a36Sopenharmony_ci .info = SNDRV_PCM_INFO_INTERLEAVED | 34262306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP | 34362306a36Sopenharmony_ci SNDRV_PCM_INFO_MMAP_VALID, 34462306a36Sopenharmony_ci .buffer_bytes_max = 32 * 1024, 34562306a36Sopenharmony_ci .period_bytes_min = 32, 34662306a36Sopenharmony_ci .period_bytes_max = 8192, 34762306a36Sopenharmony_ci .periods_min = 1, 34862306a36Sopenharmony_ci .periods_max = 128, 34962306a36Sopenharmony_ci .fifo_size = 256, 35062306a36Sopenharmony_ci}; 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_cistatic int test_component_open(struct snd_soc_component *component, 35362306a36Sopenharmony_ci struct snd_pcm_substream *substream) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci mile_stone(component); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci /* BE's dont need dummy params */ 36062306a36Sopenharmony_ci if (!rtd->dai_link->no_pcm) 36162306a36Sopenharmony_ci snd_soc_set_runtime_hwparams(substream, &test_component_hardware); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return 0; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_cistatic int test_component_close(struct snd_soc_component *component, 36762306a36Sopenharmony_ci struct snd_pcm_substream *substream) 36862306a36Sopenharmony_ci{ 36962306a36Sopenharmony_ci mile_stone(component); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci return 0; 37262306a36Sopenharmony_ci} 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_cistatic int test_component_ioctl(struct snd_soc_component *component, 37562306a36Sopenharmony_ci struct snd_pcm_substream *substream, 37662306a36Sopenharmony_ci unsigned int cmd, void *arg) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci mile_stone(component); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci return 0; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic int test_component_hw_params(struct snd_soc_component *component, 38462306a36Sopenharmony_ci struct snd_pcm_substream *substream, 38562306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci mile_stone(component); 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci return 0; 39062306a36Sopenharmony_ci} 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int test_component_hw_free(struct snd_soc_component *component, 39362306a36Sopenharmony_ci struct snd_pcm_substream *substream) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci mile_stone(component); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return 0; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic int test_component_prepare(struct snd_soc_component *component, 40162306a36Sopenharmony_ci struct snd_pcm_substream *substream) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci mile_stone(component); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return 0; 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cistatic void test_component_timer_stop(struct test_priv *priv) 40962306a36Sopenharmony_ci{ 41062306a36Sopenharmony_ci cancel_delayed_work(&priv->dwork); 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic void test_component_timer_start(struct test_priv *priv) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10)); 41662306a36Sopenharmony_ci} 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_cistatic void test_component_dwork(struct work_struct *work) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct test_priv *priv = container_of(work, struct test_priv, dwork.work); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci if (priv->substream) 42362306a36Sopenharmony_ci snd_pcm_period_elapsed(priv->substream); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci test_component_timer_start(priv); 42662306a36Sopenharmony_ci} 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_cistatic int test_component_trigger(struct snd_soc_component *component, 42962306a36Sopenharmony_ci struct snd_pcm_substream *substream, int cmd) 43062306a36Sopenharmony_ci{ 43162306a36Sopenharmony_ci struct test_priv *priv = dev_get_drvdata(component->dev); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci mile_stone(component); 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci switch (cmd) { 43662306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_START: 43762306a36Sopenharmony_ci test_component_timer_start(priv); 43862306a36Sopenharmony_ci priv->substream = substream; /* set substream later */ 43962306a36Sopenharmony_ci break; 44062306a36Sopenharmony_ci case SNDRV_PCM_TRIGGER_STOP: 44162306a36Sopenharmony_ci priv->substream = NULL; 44262306a36Sopenharmony_ci test_component_timer_stop(priv); 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return 0; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_cistatic int test_component_sync_stop(struct snd_soc_component *component, 44962306a36Sopenharmony_ci struct snd_pcm_substream *substream) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci mile_stone(component); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci return 0; 45462306a36Sopenharmony_ci} 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_cistatic snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component, 45762306a36Sopenharmony_ci struct snd_pcm_substream *substream) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci struct snd_pcm_runtime *runtime = substream->runtime; 46062306a36Sopenharmony_ci static int pointer; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci if (!runtime) 46362306a36Sopenharmony_ci return 0; 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci pointer += 10; 46662306a36Sopenharmony_ci if (pointer > PREALLOC_BUFFER) 46762306a36Sopenharmony_ci pointer = 0; 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci /* mile_stone(component); */ 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci return bytes_to_frames(runtime, pointer); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cistatic int test_component_get_time_info(struct snd_soc_component *component, 47562306a36Sopenharmony_ci struct snd_pcm_substream *substream, 47662306a36Sopenharmony_ci struct timespec64 *system_ts, 47762306a36Sopenharmony_ci struct timespec64 *audio_ts, 47862306a36Sopenharmony_ci struct snd_pcm_audio_tstamp_config *audio_tstamp_config, 47962306a36Sopenharmony_ci struct snd_pcm_audio_tstamp_report *audio_tstamp_report) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci mile_stone(component); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return 0; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, 48762306a36Sopenharmony_ci struct snd_pcm_hw_params *params) 48862306a36Sopenharmony_ci{ 48962306a36Sopenharmony_ci mile_stone_x(rtd->dev); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci return 0; 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/* CPU */ 49562306a36Sopenharmony_cistatic const struct test_adata test_cpu = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, }; 49662306a36Sopenharmony_cistatic const struct test_adata test_cpu_vv = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, }; 49762306a36Sopenharmony_cistatic const struct test_adata test_cpu_nv = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, }; 49862306a36Sopenharmony_cistatic const struct test_adata test_cpu_vn = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, }; 49962306a36Sopenharmony_ci/* Codec */ 50062306a36Sopenharmony_cistatic const struct test_adata test_codec = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, }; 50162306a36Sopenharmony_cistatic const struct test_adata test_codec_vv = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, }; 50262306a36Sopenharmony_cistatic const struct test_adata test_codec_nv = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, }; 50362306a36Sopenharmony_cistatic const struct test_adata test_codec_vn = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, }; 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_cistatic const struct of_device_id test_of_match[] = { 50662306a36Sopenharmony_ci { .compatible = "test-cpu", .data = (void *)&test_cpu, }, 50762306a36Sopenharmony_ci { .compatible = "test-cpu-verbose", .data = (void *)&test_cpu_vv, }, 50862306a36Sopenharmony_ci { .compatible = "test-cpu-verbose-dai", .data = (void *)&test_cpu_nv, }, 50962306a36Sopenharmony_ci { .compatible = "test-cpu-verbose-component", .data = (void *)&test_cpu_vn, }, 51062306a36Sopenharmony_ci { .compatible = "test-codec", .data = (void *)&test_codec, }, 51162306a36Sopenharmony_ci { .compatible = "test-codec-verbose", .data = (void *)&test_codec_vv, }, 51262306a36Sopenharmony_ci { .compatible = "test-codec-verbose-dai", .data = (void *)&test_codec_nv, }, 51362306a36Sopenharmony_ci { .compatible = "test-codec-verbose-component", .data = (void *)&test_codec_vn, }, 51462306a36Sopenharmony_ci {}, 51562306a36Sopenharmony_ci}; 51662306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, test_of_match); 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget widgets[] = { 51962306a36Sopenharmony_ci /* 52062306a36Sopenharmony_ci * FIXME 52162306a36Sopenharmony_ci * 52262306a36Sopenharmony_ci * Just IN/OUT is OK for now, 52362306a36Sopenharmony_ci * but need to be updated ? 52462306a36Sopenharmony_ci */ 52562306a36Sopenharmony_ci SND_SOC_DAPM_INPUT("IN"), 52662306a36Sopenharmony_ci SND_SOC_DAPM_OUTPUT("OUT"), 52762306a36Sopenharmony_ci}; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int test_driver_probe(struct platform_device *pdev) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct device *dev = &pdev->dev; 53262306a36Sopenharmony_ci struct device_node *node = dev->of_node; 53362306a36Sopenharmony_ci struct device_node *ep; 53462306a36Sopenharmony_ci const struct test_adata *adata = of_device_get_match_data(&pdev->dev); 53562306a36Sopenharmony_ci struct snd_soc_component_driver *cdriv; 53662306a36Sopenharmony_ci struct snd_soc_dai_driver *ddriv; 53762306a36Sopenharmony_ci struct test_dai_name *dname; 53862306a36Sopenharmony_ci struct test_priv *priv; 53962306a36Sopenharmony_ci int num, ret, i; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci num = of_graph_get_endpoint_count(node); 54262306a36Sopenharmony_ci if (!num) { 54362306a36Sopenharmony_ci dev_err(dev, "no port exits\n"); 54462306a36Sopenharmony_ci return -EINVAL; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 54862306a36Sopenharmony_ci cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); 54962306a36Sopenharmony_ci ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); 55062306a36Sopenharmony_ci dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); 55162306a36Sopenharmony_ci if (!priv || !cdriv || !ddriv || !dname || !adata) 55262306a36Sopenharmony_ci return -EINVAL; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci priv->dev = dev; 55562306a36Sopenharmony_ci priv->component_driver = cdriv; 55662306a36Sopenharmony_ci priv->dai_driver = ddriv; 55762306a36Sopenharmony_ci priv->name = dname; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci INIT_DELAYED_WORK(&priv->dwork, test_component_dwork); 56062306a36Sopenharmony_ci dev_set_drvdata(dev, priv); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci if (adata->is_cpu) { 56362306a36Sopenharmony_ci cdriv->name = "test_cpu"; 56462306a36Sopenharmony_ci cdriv->pcm_construct = test_component_pcm_construct; 56562306a36Sopenharmony_ci cdriv->pointer = test_component_pointer; 56662306a36Sopenharmony_ci cdriv->trigger = test_component_trigger; 56762306a36Sopenharmony_ci cdriv->legacy_dai_naming = 1; 56862306a36Sopenharmony_ci } else { 56962306a36Sopenharmony_ci cdriv->name = "test_codec"; 57062306a36Sopenharmony_ci cdriv->idle_bias_on = 1; 57162306a36Sopenharmony_ci cdriv->endianness = 1; 57262306a36Sopenharmony_ci } 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci cdriv->open = test_component_open; 57562306a36Sopenharmony_ci cdriv->dapm_widgets = widgets; 57662306a36Sopenharmony_ci cdriv->num_dapm_widgets = ARRAY_SIZE(widgets); 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (adata->cmp_v) { 57962306a36Sopenharmony_ci cdriv->probe = test_component_probe; 58062306a36Sopenharmony_ci cdriv->remove = test_component_remove; 58162306a36Sopenharmony_ci cdriv->suspend = test_component_suspend; 58262306a36Sopenharmony_ci cdriv->resume = test_component_resume; 58362306a36Sopenharmony_ci cdriv->set_sysclk = test_component_set_sysclk; 58462306a36Sopenharmony_ci cdriv->set_pll = test_component_set_pll; 58562306a36Sopenharmony_ci cdriv->set_jack = test_component_set_jack; 58662306a36Sopenharmony_ci cdriv->seq_notifier = test_component_seq_notifier; 58762306a36Sopenharmony_ci cdriv->stream_event = test_component_stream_event; 58862306a36Sopenharmony_ci cdriv->set_bias_level = test_component_set_bias_level; 58962306a36Sopenharmony_ci cdriv->close = test_component_close; 59062306a36Sopenharmony_ci cdriv->ioctl = test_component_ioctl; 59162306a36Sopenharmony_ci cdriv->hw_params = test_component_hw_params; 59262306a36Sopenharmony_ci cdriv->hw_free = test_component_hw_free; 59362306a36Sopenharmony_ci cdriv->prepare = test_component_prepare; 59462306a36Sopenharmony_ci cdriv->sync_stop = test_component_sync_stop; 59562306a36Sopenharmony_ci cdriv->get_time_info = test_component_get_time_info; 59662306a36Sopenharmony_ci cdriv->be_hw_params_fixup = test_component_be_hw_params_fixup; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (adata->is_cpu) 59962306a36Sopenharmony_ci cdriv->pcm_destruct = test_component_pcm_destruct; 60062306a36Sopenharmony_ci } 60162306a36Sopenharmony_ci 60262306a36Sopenharmony_ci i = 0; 60362306a36Sopenharmony_ci for_each_endpoint_of_node(node, ep) { 60462306a36Sopenharmony_ci snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i); 60562306a36Sopenharmony_ci ddriv[i].name = dname[i].name; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i); 60862306a36Sopenharmony_ci ddriv[i].playback.stream_name = dname[i].name_playback; 60962306a36Sopenharmony_ci ddriv[i].playback.channels_min = 1; 61062306a36Sopenharmony_ci ddriv[i].playback.channels_max = 384; 61162306a36Sopenharmony_ci ddriv[i].playback.rates = STUB_RATES; 61262306a36Sopenharmony_ci ddriv[i].playback.formats = STUB_FORMATS; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i); 61562306a36Sopenharmony_ci ddriv[i].capture.stream_name = dname[i].name_capture; 61662306a36Sopenharmony_ci ddriv[i].capture.channels_min = 1; 61762306a36Sopenharmony_ci ddriv[i].capture.channels_max = 384; 61862306a36Sopenharmony_ci ddriv[i].capture.rates = STUB_RATES; 61962306a36Sopenharmony_ci ddriv[i].capture.formats = STUB_FORMATS; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci if (adata->dai_v) 62262306a36Sopenharmony_ci ddriv[i].ops = &test_verbose_ops; 62362306a36Sopenharmony_ci else 62462306a36Sopenharmony_ci ddriv[i].ops = &test_ops; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci i++; 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num); 63062306a36Sopenharmony_ci if (ret < 0) 63162306a36Sopenharmony_ci return ret; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci mile_stone_x(dev); 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci return 0; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_cistatic void test_driver_remove(struct platform_device *pdev) 63962306a36Sopenharmony_ci{ 64062306a36Sopenharmony_ci mile_stone_x(&pdev->dev); 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic struct platform_driver test_driver = { 64462306a36Sopenharmony_ci .driver = { 64562306a36Sopenharmony_ci .name = "test-component", 64662306a36Sopenharmony_ci .of_match_table = test_of_match, 64762306a36Sopenharmony_ci }, 64862306a36Sopenharmony_ci .probe = test_driver_probe, 64962306a36Sopenharmony_ci .remove_new = test_driver_remove, 65062306a36Sopenharmony_ci}; 65162306a36Sopenharmony_cimodule_platform_driver(test_driver); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ciMODULE_ALIAS("platform:asoc-test-component"); 65462306a36Sopenharmony_ciMODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>"); 65562306a36Sopenharmony_ciMODULE_DESCRIPTION("ASoC Test Component"); 65662306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 657