From patchwork Tue Jul 20 01:39:42 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481639 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 437BAC07E95 for ; Tue, 20 Jul 2021 01:40:51 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6A3BF6108B for ; Tue, 20 Jul 2021 01:40:50 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 6A3BF6108B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 021521683; Tue, 20 Jul 2021 03:39:59 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 021521683 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745249; bh=Ubpx8BzZMfA3pK8OiWFdfcB0dJw+nsjPq/+wgEpNe8c=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=r+A3uZojHNTYxUwfMu6e5yBDzmHqCT1r72phqFchxd8Fn3omEMJiO5msPr3KQ9eI2 3lckau9O0JIfBFIz4hPX55VN/2IU60kETo9oBtHgix7cVXWQoLHg6Ec4eaId0/XOGn JuStu7N/o4Fl8wlNjPET1z4dppvuxtQwyY7O2/uw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 456C5F802DF; Tue, 20 Jul 2021 03:39:56 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 66B15F804D0; Tue, 20 Jul 2021 03:39:53 +0200 (CEST) Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by alsa1.perex.cz (Postfix) with ESMTP id 00890F80218 for ; Tue, 20 Jul 2021 03:39:44 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 00890F80218 Date: 20 Jul 2021 10:39:42 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88129803" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie6.idc.renesas.com with ESMTP; 20 Jul 2021 10:39:42 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 98E2541532CC; Tue, 20 Jul 2021 10:39:40 +0900 (JST) Message-ID: <877dhlwyoz.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 02/14] ASoC: test-component: add Test Component for Sound debug/test User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto We already have dummy-codec, dummy-platform. But its issues are 1) we don't have dummy-cpu, 2) we can't select it via DeviceTree 3) It do nothing Sometimes we want to have Dummy Sound Component for debugging, for testing, for learning Framework behavior, etc, etc... This patch adds Test-Component driver for it. User can select CPU Component by using "test-cpu" compatible, and can select Codec Component by using "test-codec" compatible. It doesn't support Platform so far, but is easy to add. We can verbose print to know its progress if user selected xxx-vn or xxx-nv or xxx-vv compatible driver. for example, test-cpu : silent Component, silent DAI test-cpu-vn : verbose Component, silent DAI test-cpu-nv : silent Component, verbose DAI test-cpu-vv : verbose Component, verbose DAI Signed-off-by: Kuninori Morimoto --- sound/soc/generic/Kconfig | 6 + sound/soc/generic/Makefile | 2 + sound/soc/generic/test-component.c | 659 +++++++++++++++++++++++++++++ 3 files changed, 667 insertions(+) create mode 100644 sound/soc/generic/test-component.c diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index 4cafcf0e2bbf..bb734780669e 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -17,3 +17,9 @@ config SND_AUDIO_GRAPH_CARD This option enables generic simple sound card support with OF-graph DT bindings. It also support DPCM of multi CPU single Codec ststem. + +config SND_TEST_COMPONENT + tristate "ASoC Test component sound support" + depends on OF + help + This option enables test component sound driver support. diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index 21c29e5e0671..988bfd45d2e2 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile @@ -2,7 +2,9 @@ snd-soc-simple-card-utils-objs := simple-card-utils.o snd-soc-simple-card-objs := simple-card.o snd-soc-audio-graph-card-objs := audio-graph-card.o +snd-soc-test-component-objs := test-component.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o +obj-$(CONFIG_SND_TEST_COMPONENT) += snd-soc-test-component.o diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c new file mode 100644 index 000000000000..de0f7f2586b4 --- /dev/null +++ b/sound/soc/generic/test-component.c @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// test-component.c -- Test Audio Component driver +// +// Copyright (C) 2020 Renesas Electronics Corporation +// Kuninori Morimoto + +#include +#include +#include +#include +#include +#include +#include + +#define TEST_NAME_LEN 32 +struct test_dai_name { + char name[TEST_NAME_LEN]; + char name_playback[TEST_NAME_LEN]; + char name_capture[TEST_NAME_LEN]; +}; + +struct test_priv { + struct device *dev; + struct snd_pcm_substream *substream; + struct delayed_work dwork; + struct snd_soc_component_driver *component_driver; + struct snd_soc_dai_driver *dai_driver; + struct test_dai_name *name; +}; + +struct test_adata { + u32 is_cpu:1; + u32 cmp_v:1; + u32 dai_v:1; +}; + +#define mile_stone(d) dev_info((d)->dev, "%s() : %s", __func__, (d)->driver->name) +#define mile_stone_x(dev) dev_info(dev, "%s()", __func__) + +static int test_dai_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + unsigned int format = fmt & SND_SOC_DAIFMT_FORMAT_MASK; + unsigned int clock = fmt & SND_SOC_DAIFMT_CLOCK_MASK; + unsigned int inv = fmt & SND_SOC_DAIFMT_INV_MASK; + unsigned int master = fmt & SND_SOC_DAIFMT_MASTER_MASK; + char *str; + + dev_info(dai->dev, "name : %s", dai->name); + + str = "unknown"; + switch (format) { + case SND_SOC_DAIFMT_I2S: + str = "i2s"; + break; + case SND_SOC_DAIFMT_RIGHT_J: + str = "right_j"; + break; + case SND_SOC_DAIFMT_LEFT_J: + str = "left_j"; + break; + case SND_SOC_DAIFMT_DSP_A: + str = "dsp_a"; + break; + case SND_SOC_DAIFMT_DSP_B: + str = "dsp_b"; + break; + case SND_SOC_DAIFMT_AC97: + str = "ac97"; + break; + case SND_SOC_DAIFMT_PDM: + str = "pdm"; + break; + } + dev_info(dai->dev, "format : %s", str); + + if (clock == SND_SOC_DAIFMT_CONT) + str = "continuous"; + else + str = "gated"; + dev_info(dai->dev, "clock : %s", str); + + str = "unknown"; + switch (master) { + case SND_SOC_DAIFMT_CBP_CFP: + str = "clk provider, frame provider"; + break; + case SND_SOC_DAIFMT_CBC_CFP: + str = "clk consumer, frame provider"; + break; + case SND_SOC_DAIFMT_CBP_CFC: + str = "clk provider, frame consumer"; + break; + case SND_SOC_DAIFMT_CBC_CFC: + str = "clk consumer, frame consumer"; + break; + } + dev_info(dai->dev, "clock : codec is %s", str); + + str = "unknown"; + switch (inv) { + case SND_SOC_DAIFMT_NB_NF: + str = "normal bit, normal frame"; + break; + case SND_SOC_DAIFMT_NB_IF: + str = "normal bit, invert frame"; + break; + case SND_SOC_DAIFMT_IB_NF: + str = "invert bit, normal frame"; + break; + case SND_SOC_DAIFMT_IB_IF: + str = "invert bit, invert frame"; + break; + } + dev_info(dai->dev, "signal : %s", str); + + return 0; +} + +static int test_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + mile_stone(dai); + + return 0; +} + +static void test_dai_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + mile_stone(dai); +} + +static int test_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_hw_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct snd_soc_dai *dai) +{ + mile_stone(dai); + + return 0; +} + +static int test_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + mile_stone(dai); + + return 0; +} + +static u64 test_dai_formats = + /* + * Select below from Sound Card, not auto + * SND_SOC_POSSIBLE_DAIFMT_CBP_CFP + * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP + * SND_SOC_POSSIBLE_DAIFMT_CBP_CFC + * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC + */ + SND_SOC_POSSIBLE_DAIFMT_I2S | + SND_SOC_POSSIBLE_DAIFMT_RIGHT_J | + SND_SOC_POSSIBLE_DAIFMT_LEFT_J | + SND_SOC_POSSIBLE_DAIFMT_DSP_A | + SND_SOC_POSSIBLE_DAIFMT_DSP_B | + SND_SOC_POSSIBLE_DAIFMT_AC97 | + SND_SOC_POSSIBLE_DAIFMT_PDM | + SND_SOC_POSSIBLE_DAIFMT_NB_NF | + SND_SOC_POSSIBLE_DAIFMT_NB_IF | + SND_SOC_POSSIBLE_DAIFMT_IB_NF | + SND_SOC_POSSIBLE_DAIFMT_IB_IF; + +static const struct snd_soc_dai_ops test_ops = { + .set_fmt = test_dai_set_fmt, + .startup = test_dai_startup, + .shutdown = test_dai_shutdown, + .auto_selectable_formats = &test_dai_formats, + .num_auto_selectable_formats = 1, +}; + +static const struct snd_soc_dai_ops test_verbose_ops = { + .set_sysclk = test_dai_set_sysclk, + .set_pll = test_dai_set_pll, + .set_clkdiv = test_dai_set_clkdiv, + .set_fmt = test_dai_set_fmt, + .mute_stream = test_dai_mute_stream, + .startup = test_dai_startup, + .shutdown = test_dai_shutdown, + .hw_params = test_dai_hw_params, + .hw_free = test_dai_hw_free, + .trigger = test_dai_trigger, + .bespoke_trigger = test_dai_bespoke_trigger, + .auto_selectable_formats = &test_dai_formats, + .num_auto_selectable_formats = 1, +}; + +#define STUB_RATES SNDRV_PCM_RATE_8000_384000 +#define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_U8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_U16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE | \ + SNDRV_PCM_FMTBIT_S24_3LE | \ + SNDRV_PCM_FMTBIT_U24_LE | \ + SNDRV_PCM_FMTBIT_S32_LE | \ + SNDRV_PCM_FMTBIT_U32_LE) + +static int test_component_probe(struct snd_soc_component *component) +{ + mile_stone(component); + + return 0; +} + +static void test_component_remove(struct snd_soc_component *component) +{ + mile_stone(component); +} + +static int test_component_suspend(struct snd_soc_component *component) +{ + mile_stone(component); + + return 0; +} + +static int test_component_resume(struct snd_soc_component *component) +{ + mile_stone(component); + + return 0; +} + +#define PREALLOC_BUFFER (32 * 1024) +static int test_component_pcm_construct(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + mile_stone(component); + + snd_pcm_set_managed_buffer_all( + rtd->pcm, + SNDRV_DMA_TYPE_DEV, + rtd->card->snd_card->dev, + PREALLOC_BUFFER, PREALLOC_BUFFER); + + return 0; +} + +static void test_component_pcm_destruct(struct snd_soc_component *component, + struct snd_pcm *pcm) +{ + mile_stone(component); +} + +static int test_component_set_sysclk(struct snd_soc_component *component, + int clk_id, int source, unsigned int freq, int dir) +{ + mile_stone(component); + + return 0; +} + +static int test_component_set_pll(struct snd_soc_component *component, int pll_id, + int source, unsigned int freq_in, unsigned int freq_out) +{ + mile_stone(component); + + return 0; +} + +static int test_component_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + mile_stone(component); + + return 0; +} + +static void test_component_seq_notifier(struct snd_soc_component *component, + enum snd_soc_dapm_type type, int subseq) +{ + mile_stone(component); +} + +static int test_component_stream_event(struct snd_soc_component *component, int event) +{ + mile_stone(component); + + return 0; +} + +static int test_component_set_bias_level(struct snd_soc_component *component, + enum snd_soc_bias_level level) +{ + mile_stone(component); + + return 0; +} + +static const struct snd_pcm_hardware test_component_hardware = { + /* Random values to keep userspace happy when checking constraints */ + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID, + .buffer_bytes_max = 32 * 1024, + .period_bytes_min = 32, + .period_bytes_max = 8192, + .periods_min = 1, + .periods_max = 128, + .fifo_size = 256, +}; + +static int test_component_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + + mile_stone(component); + + /* BE's dont need dummy params */ + if (!rtd->dai_link->no_pcm) + snd_soc_set_runtime_hwparams(substream, &test_component_hardware); + + return 0; +} + +static int test_component_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + mile_stone(component); + + return 0; +} + +static int test_component_ioctl(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + unsigned int cmd, void *arg) +{ + mile_stone(component); + + return 0; +} + +static int test_component_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + mile_stone(component); + + return 0; +} + +static int test_component_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + mile_stone(component); + + return 0; +} + +static int test_component_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + mile_stone(component); + + return 0; +} + +static void test_component_timer_stop(struct test_priv *priv) +{ + cancel_delayed_work(&priv->dwork); +} + +static void test_component_timer_start(struct test_priv *priv) +{ + schedule_delayed_work(&priv->dwork, msecs_to_jiffies(10)); +} + +static void test_component_dwork(struct work_struct *work) +{ + struct test_priv *priv = container_of(work, struct test_priv, dwork.work); + + if (priv->substream) + snd_pcm_period_elapsed(priv->substream); + + test_component_timer_start(priv); +} + +static int test_component_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct test_priv *priv = dev_get_drvdata(component->dev); + + mile_stone(component); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + test_component_timer_start(priv); + priv->substream = substream; /* set substream later */ + break; + case SNDRV_PCM_TRIGGER_STOP: + priv->substream = NULL; + test_component_timer_stop(priv); + } + + return 0; +} + +static int test_component_sync_stop(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + mile_stone(component); + + return 0; +} + +static snd_pcm_uframes_t test_component_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + static int pointer; + + if (!runtime) + return 0; + + pointer += 10; + if (pointer > PREALLOC_BUFFER) + pointer = 0; + + /* mile_stone(component); */ + + return bytes_to_frames(runtime, pointer); +} + +static int 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) +{ + mile_stone(component); + + return 0; +} + +static int test_component_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + mile_stone_x(rtd->dev); + + return 0; +} + +/* CPU */ +static const struct test_adata test_cpu = { .is_cpu = 1, .cmp_v = 0, .dai_v = 0, }; +static const struct test_adata test_cpu_vv = { .is_cpu = 1, .cmp_v = 1, .dai_v = 1, }; +static const struct test_adata test_cpu_nv = { .is_cpu = 1, .cmp_v = 0, .dai_v = 1, }; +static const struct test_adata test_cpu_vn = { .is_cpu = 1, .cmp_v = 1, .dai_v = 0, }; +/* Codec */ +static const struct test_adata test_codec = { .is_cpu = 0, .cmp_v = 0, .dai_v = 0, }; +static const struct test_adata test_codec_vv = { .is_cpu = 0, .cmp_v = 1, .dai_v = 1, }; +static const struct test_adata test_codec_nv = { .is_cpu = 0, .cmp_v = 0, .dai_v = 1, }; +static const struct test_adata test_codec_vn = { .is_cpu = 0, .cmp_v = 1, .dai_v = 0, }; + +static const struct of_device_id test_of_match[] = { + { .compatible = "test-cpu", .data = (void *)&test_cpu, }, + { .compatible = "test-cpu-vv", .data = (void *)&test_cpu_vv, }, + { .compatible = "test-cpu-vn", .data = (void *)&test_cpu_vn, }, + { .compatible = "test-cpu-nv", .data = (void *)&test_cpu_nv, }, + { .compatible = "test-codec", .data = (void *)&test_codec, }, + { .compatible = "test-codec-vv", .data = (void *)&test_codec_vv, }, + { .compatible = "test-codec-vn", .data = (void *)&test_codec_vn, }, + { .compatible = "test-codec-nv", .data = (void *)&test_codec_nv, }, + {}, +}; +MODULE_DEVICE_TABLE(of, test_of_match); + +static const struct snd_soc_dapm_widget widgets[] = { + /* + * FIXME + * + * Just IN/OUT is OK for now, + * but need to be updated ? + */ + SND_SOC_DAPM_INPUT("IN"), + SND_SOC_DAPM_OUTPUT("OUT"), +}; + +static int test_driver_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + struct device_node *ep; + const struct of_device_id *of_id = of_match_device(test_of_match, &pdev->dev); + const struct test_adata *adata = of_id->data; + struct snd_soc_component_driver *cdriv; + struct snd_soc_dai_driver *ddriv; + struct test_dai_name *dname; + struct test_priv *priv; + int num, ret, i; + + num = of_graph_get_endpoint_count(node); + if (!num) { + dev_err(dev, "no port exits\n"); + return -EINVAL; + } + + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + cdriv = devm_kzalloc(dev, sizeof(*cdriv), GFP_KERNEL); + ddriv = devm_kzalloc(dev, sizeof(*ddriv) * num, GFP_KERNEL); + dname = devm_kzalloc(dev, sizeof(*dname) * num, GFP_KERNEL); + if (!priv || !cdriv || !ddriv || !dname) + return -EINVAL; + + priv->dev = dev; + priv->component_driver = cdriv; + priv->dai_driver = ddriv; + priv->name = dname; + + INIT_DELAYED_WORK(&priv->dwork, test_component_dwork); + dev_set_drvdata(dev, priv); + + if (adata->is_cpu) { + cdriv->name = "test_cpu"; + cdriv->pcm_construct = test_component_pcm_construct; + cdriv->pointer = test_component_pointer; + cdriv->trigger = test_component_trigger; + } else { + cdriv->name = "test_codec"; + cdriv->idle_bias_on = 1; + cdriv->endianness = 1; + cdriv->non_legacy_dai_naming = 1; + } + + cdriv->open = test_component_open; + cdriv->dapm_widgets = widgets; + cdriv->num_dapm_widgets = ARRAY_SIZE(widgets); + + if (adata->cmp_v) { + cdriv->probe = test_component_probe; + cdriv->remove = test_component_remove; + cdriv->suspend = test_component_suspend; + cdriv->resume = test_component_resume; + cdriv->set_sysclk = test_component_set_sysclk; + cdriv->set_pll = test_component_set_pll; + cdriv->set_jack = test_component_set_jack; + cdriv->seq_notifier = test_component_seq_notifier; + cdriv->stream_event = test_component_stream_event; + cdriv->set_bias_level = test_component_set_bias_level; + cdriv->close = test_component_close; + cdriv->ioctl = test_component_ioctl; + cdriv->hw_params = test_component_hw_params; + cdriv->hw_free = test_component_hw_free; + cdriv->prepare = test_component_prepare; + cdriv->sync_stop = test_component_sync_stop; + cdriv->get_time_info = test_component_get_time_info; + cdriv->be_hw_params_fixup = test_component_be_hw_params_fixup; + + if (adata->is_cpu) + cdriv->pcm_destruct = test_component_pcm_destruct; + } + + i = 0; + for_each_endpoint_of_node(node, ep) { + snprintf(dname[i].name, TEST_NAME_LEN, "%s.%d", node->name, i); + ddriv[i].name = dname[i].name; + + snprintf(dname[i].name_playback, TEST_NAME_LEN, "DAI%d Playback", i); + ddriv[i].playback.stream_name = dname[i].name_playback; + ddriv[i].playback.channels_min = 1; + ddriv[i].playback.channels_max = 384; + ddriv[i].playback.rates = STUB_RATES; + ddriv[i].playback.formats = STUB_FORMATS; + + snprintf(dname[i].name_capture, TEST_NAME_LEN, "DAI%d Capture", i); + ddriv[i].capture.stream_name = dname[i].name_capture; + ddriv[i].capture.channels_min = 1; + ddriv[i].capture.channels_max = 384; + ddriv[i].capture.rates = STUB_RATES; + ddriv[i].capture.formats = STUB_FORMATS; + + if (adata->dai_v) + ddriv[i].ops = &test_verbose_ops; + else + ddriv[i].ops = &test_ops; + + i++; + } + + ret = devm_snd_soc_register_component(dev, cdriv, ddriv, num); + if (ret < 0) + return ret; + + mile_stone_x(dev); + + return 0; +} + +static int test_driver_remove(struct platform_device *pdev) +{ + mile_stone_x(&pdev->dev); + + return 0; +} + +static struct platform_driver test_driver = { + .driver = { + .name = "test-component", + .of_match_table = test_of_match, + }, + .probe = test_driver_probe, + .remove = test_driver_remove, +}; +module_platform_driver(test_driver); + +MODULE_ALIAS("platform:asoc-test-component"); +MODULE_AUTHOR("Kuninori Morimoto "); +MODULE_DESCRIPTION("ASoC Test Component"); +MODULE_LICENSE("GPL v2"); From patchwork Tue Jul 20 01:40:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481638 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id EDA81C07E9D for ; Tue, 20 Jul 2021 01:41:29 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 42A62610CC for ; Tue, 20 Jul 2021 01:41:29 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 42A62610CC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id D20E81674; Tue, 20 Jul 2021 03:40:37 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz D20E81674 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745287; bh=8JQ+cih0tQrJDhHK1hnYfW2zv5YiefI2MuB8SzUJOeQ=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Xv3AHCURRn7PUjzLC9NCPG7PyoQa76VWV1sTo9g9JeAFHgqi5i2diR/rdt7v5HbKs VVQPG/1H+SHEpOrfG8AQ3vFjbEcdXlNQTKcfQEVXQuuw6NTHq5HnbvDt0I3dENJlvE Pln+w+D1tQKntfFMjxDiC6zx2dIOhPzOw9vPMJ78= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3BE2CF804E2; Tue, 20 Jul 2021 03:40:06 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 87A0DF804E3; Tue, 20 Jul 2021 03:40:04 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 3F645F804DA for ; Tue, 20 Jul 2021 03:40:00 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3F645F804DA Date: 20 Jul 2021 10:40:00 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88181452" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 20 Jul 2021 10:40:00 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 39F8341532CC; Tue, 20 Jul 2021 10:40:00 +0900 (JST) Message-ID: <874kcpwyof.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 04/14] ASoC: simple-card-utils: add codec2codec support User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto codec2codec needs snd_soc_pcm_stream settings. This patch adds it. Signed-off-by: Kuninori Morimoto --- include/sound/simple_card_utils.h | 3 +++ sound/soc/generic/simple-card-utils.c | 18 +++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 520559b0a336..51f287220348 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -42,6 +42,7 @@ struct prop_nums { int cpus; int codecs; int platforms; + int c2c; }; struct asoc_simple_priv { @@ -54,6 +55,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link_component *platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; + struct snd_soc_pcm_stream *c2c_conf; struct prop_nums num; unsigned int mclk_fs; } *dai_props; @@ -64,6 +66,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link_component *dlcs; struct snd_soc_dai_link_component dummy; struct snd_soc_codec_conf *codec_conf; + struct snd_soc_pcm_stream *c2c_conf; struct gpio_desc *pa_gpio; const struct snd_soc_ops *ops; unsigned int dpcm_selectable:1; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 31802b15afd4..16a545201f88 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -619,7 +619,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *cconf = NULL; - int i, dai_num = 0, dlc_num = 0, cnf_num = 0; + struct snd_soc_pcm_stream *c2c_conf = NULL; + int i, dai_num = 0, dlc_num = 0, cnf_num = 0, c2c_num = 0; dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); @@ -638,6 +639,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, if (!li->num[i].cpus) cnf_num += li->num[i].codecs; + + c2c_num += li->num[i].c2c; } dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); @@ -651,6 +654,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, return -ENOMEM; } + if (c2c_num) { + c2c_conf = devm_kcalloc(dev, c2c_num, sizeof(*c2c_conf), GFP_KERNEL); + if (!c2c_conf) + return -ENOMEM; + } + dev_dbg(dev, "link %d, dais %d, ccnf %d\n", li->link, dai_num, cnf_num); @@ -664,6 +673,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, priv->dais = dais; priv->dlcs = dlcs; priv->codec_conf = cconf; + priv->c2c_conf = c2c_conf; card->dai_link = priv->dai_link; card->num_links = li->link; @@ -681,6 +691,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dlcs += li->num[i].cpus; dais += li->num[i].cpus; + + if (li->num[i].c2c) { + /* Codec2Codec */ + dai_props[i].c2c_conf = c2c_conf; + c2c_conf += li->num[i].c2c; + } } else { /* DPCM Be's CPU = dummy */ dai_props[i].cpus = From patchwork Tue Jul 20 01:40:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481637 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64B38C12002 for ; Tue, 20 Jul 2021 01:42:22 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id E1F2C610CC for ; Tue, 20 Jul 2021 01:42:21 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org E1F2C610CC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 867D21694; Tue, 20 Jul 2021 03:41:30 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 867D21694 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745340; bh=fItet+qAikGICqieEtfXfd/D+aOu4JewXq0tANAGlCs=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=I9Y9v70gCNLDsHRyuV5/VmHsGl61o83tuZwVGzFDVPQpO2iESfTKlsil3qAgW+Epd 73xhtE2xm8ksSi4yqwLvu6QHJTDdoTPYxEN7RR5eJoOdG4zlteCfSm7SMeXgTgnyKp rmW7B4ILBDTEFKzw0EoN5RopN1q1kf+IJ53jhqC8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 32238F800C5; Tue, 20 Jul 2021 03:40:23 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 0208CF804FE; Tue, 20 Jul 2021 03:40:21 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id B6752F804F2 for ; Tue, 20 Jul 2021 03:40:14 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B6752F804F2 Date: 20 Jul 2021 10:40:14 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88181496" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 20 Jul 2021 10:40:14 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 4C4ED4153B5D; Tue, 20 Jul 2021 10:40:14 +0900 (JST) Message-ID: <871r7twyo1.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 06/14] ASoC: audio-graph-card2: add DPCM support User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto This patch adds DPCM support to audio-graph-card2. The big difference between audio-graph-card2 DPCM and audio-graph-card DPCM is that audio-graph-card2 uses extra node (X) for it. ******* PCM0 <--> * * <--> DAI0: Codec Headset PCM1 <--> * * <--> DAI1: Codec Speakers PCM2 <--> * DSP * <--> DAI2: MODEM PCM3 <--> * * <--> DAI3: BT * * <--> DAI4: DMIC * * <--> DAI5: FM ******* sound { compatible = "audio-graph-card2"; // indicate routing (A) routing = "xxx Playback", "xxx Playback", "xxx Playback", "xxx Playback", "xxx Playback", "xxx Playback"; // indicate all Front-End, Back-End in DPCM case (B) links = <&dsp_fe0, &dsp_fe1, &dsp_fe2, &dsp_fe3, &dsp_be0, &dsp_be1, &dsp_be2, &dsp_be3, &dsp_be4, &dsp_be5>; }; (X) DSP { compatible = "audio-graph-card2-dsp"; // Front-End ports@0 { (B) dsp_fe0: port@0 { dsp_fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; }; dsp_fe1: port@1 { dsp_fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; }; ... }; // Back-End ports@1 { (B) dsp_be0: port@0 { dsp_be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; }; dsp_be1: port@1 { dsp_be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; }; ... }; CPU { ports { bitclock-master; frame-master; port@0 { pcm0_ep: endpoint { remote-endpoint = <&dsp_fe0_ep>; }; }; port@1 { pcm1_ep: endpoint { remote-endpoint = <&dsp_fe1_ep>; }; }; ... }; }; Codec { ports { port@0 { dai0_ep: endpoint { remote-endpoint = <&dsp_be0_ep>; }; }; port@1 { dai1_ep: endpoint { remote-endpoint = <&dsp_be1_ep>; }; }; ... }; }; It needs to add routing (A) when DPCM case. "links" needs to indicate both Front-End and Back-End (B), instead of CPU/Codec node. Link: https://lore.kernel.org/r/87k0xszlep.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto --- include/sound/graph_card.h | 3 + sound/soc/generic/audio-graph-card2.c | 259 +++++++++++++++++++++++++- 2 files changed, 261 insertions(+), 1 deletion(-) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index b3185783caa7..03df4c5a7151 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -17,6 +17,7 @@ struct graph_custom_hooks { int (*hook_pre)(struct asoc_simple_priv *priv); int (*hook_post)(struct asoc_simple_priv *priv); GRAPH_CUSTOM custom_normal; + GRAPH_CUSTOM custom_dpcm; }; int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); @@ -25,5 +26,7 @@ int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev, int audio_graph2_link_normal(struct asoc_simple_priv *priv, struct device_node *lnk, struct link_info *li); +int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); #endif /* __GRAPH_CARD_H */ diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index f5edf1368e12..b288975ffde2 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -71,12 +71,78 @@ port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; }; }; + + ************************************ + DSP Audio-Graph + ************************************ + + ******* + PCM0 <--> * * <--> DAI0: Codec Headset + PCM1 <--> * * <--> DAI1: Codec Speakers + PCM2 <--> * DSP * <--> DAI2: MODEM + PCM3 <--> * * <--> DAI3: BT + * * <--> DAI4: DMIC + * * <--> DAI5: FM + ******* + + sound { + compatible = "audio-graph-card2"; + + // indicate routing + routing = "xxx Playback", "xxx Playback", + "xxx Playback", "xxx Playback", + "xxx Playback", "xxx Playback"; + + // indicate all Front-End, Back-End in DPCM case + links = <&dsp_fe0, &dsp_fe1, &dsp_fe2, &dsp_fe3, + &dsp_be0, &dsp_be1, &dsp_be2, &dsp_be3, &dsp_be4, &dsp_be5>; + }; + + DSP { + compatible = "audio-graph-card2-dsp"; + + // Front-End + ports@0 { + dsp_fe0: port@0 { dsp_fe0_ep: endpoint { remote-endpoint = <&pcm0_ep>; }; }; + dsp_fe1: port@1 { dsp_fe1_ep: endpoint { remote-endpoint = <&pcm1_ep>; }; }; + ... + }; + + // Back-End + ports@1 { + dsp_be0: port@0 { dsp_be0_ep: endpoint { remote-endpoint = <&dai0_ep>; }; }; + dsp_be1: port@1 { dsp_be1_ep: endpoint { remote-endpoint = <&dai1_ep>; }; }; + ... + }; + ... + }; + + CPU { + ports { + bitclock-master; + frame-master; + port@0 { pcm0_ep: endpoint { remote-endpoint = <&dsp_fe0_ep>; }; }; + port@1 { pcm1_ep: endpoint { remote-endpoint = <&dsp_fe1_ep>; }; }; + ... + }; + }; + + Codec { + ports { + port@0 { dai0_ep: endpoint { remote-endpoint = <&dsp_be0_ep>; }; }; + port@1 { dai1_ep: endpoint { remote-endpoint = <&dsp_be1_ep>; }; }; + ... + }; + }; */ enum graph_type { GRAPH_NORMAL, + GRAPH_DPCM, }; +#define GRAPH_COMPATIBLE_DPCM "audio-graph-card2-dsp" + #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") static enum graph_type graph_get_type(struct asoc_simple_priv *priv, @@ -98,11 +164,24 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv, if (ret < 0) goto end; + if (strcmp(string, GRAPH_COMPATIBLE_DPCM) == 0) + type = GRAPH_DPCM; end: #ifdef DEBUG { const char *str = "Normal"; - + struct device *dev = simple_priv_to_dev(priv); + + switch (type) { + case GRAPH_DPCM: + if (asoc_graph_is_ports0(link)) + str = "DPCM Front-End"; + else + str = "DPCM Back-End"; + break; + default: + break; + } dev_dbg(dev, "%pOF (%s)", link, str); } #endif @@ -220,6 +299,22 @@ static int asoc_simple_parse_dai(struct device_node *ep, return 0; } +static void graph_parse_convert(struct device_node *ep, + struct simple_dai_props *props) +{ + struct device_node *port = of_get_parent(ep); + struct device_node *ports = of_get_parent(port); + struct asoc_simple_data *adata = &props->adata; + + if (of_node_name_eq(ports, "ports")) + asoc_simple_parse_convert(ports, NULL, adata); + asoc_simple_parse_convert(port, NULL, adata); + asoc_simple_parse_convert(ep, NULL, adata); + + of_node_put(port); + of_node_put(ports); +} + static void graph_parse_mclk_fs(struct device_node *ep, struct simple_dai_props *props) { @@ -432,6 +527,128 @@ int audio_graph2_link_normal(struct asoc_simple_priv *priv, } EXPORT_SYMBOL_GPL(audio_graph2_link_normal); +int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct device_node *ep = port_to_endpoint(lnk); + struct device_node *rep = of_graph_get_remote_endpoint(ep); + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + char dai_name[64]; + int is_cpu = asoc_graph_is_ports0(lnk); + int ret; + + if (is_cpu) { + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + int is_single_links = 0; + + /* + * DSP { + * compatible = "audio-graph-card2-dsp"; + * + * // Front-End + * ports@0 { + * => lnk: port@0 { ep: endpoint { remote-endpoint = <&rep>; }; }; + * ... + * }; + * // Back-End + * ports@0 { + * ... + * }; + * }; + * + * CPU { + * rports: ports { + * rport: port@0 { rep: endpoint { ... }; }; + * } + * } + */ + /* + * setup CPU here, Codec is already set as dummy. + * see + * asoc_simple_init_priv() + */ + dai_link->dynamic = 1; + dai_link->dpcm_merged_format = 1; + + ret = graph_parse_node(priv, rep, li, 0, &is_single_links); + if (ret) + goto err; + + snprintf(dai_name, sizeof(dai_name), + "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); + + asoc_simple_canonicalize_cpu(cpus, is_single_links); + } else { + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, 0); + struct device_node *rport; + struct device_node *rports; + + /* + * DSP { + * compatible = "audio-graph-card2-dsp"; + * + * // Front-End + * ports@0 { + * ... + * }; + * // Back-End + * ports@0 { + * => lnk: port@0 { ep: endpoint { remote-endpoint = <&rep>; }; }; + * ... + * }; + * }; + * + * Codec { + * rports: ports { + * rport: port@0 { rep: endpoint { ... }; }; + * } + * } + */ + /* + * setup Codec here, CPU is already set as dummy. + * see + * asoc_simple_init_priv() + */ + + /* BE settings */ + dai_link->no_pcm = 1; + dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; + + ret = graph_parse_node(priv, rep, li, 0, NULL); + if (ret < 0) + goto err; + + snprintf(dai_name, sizeof(dai_name), + "be.%pOFP.%s", codecs->of_node, codecs->dai_name); + + /* check "prefix" from top node */ + rport = of_get_parent(rep); + rports = of_get_parent(rport); + + if (of_node_name_eq(rports, "ports")) + snd_soc_of_parse_node_prefix(rports, cconf, codecs->of_node, "prefix"); + snd_soc_of_parse_node_prefix(rport, cconf, codecs->of_node, "prefix"); + + of_node_put(rport); + of_node_put(rports); + } + + graph_parse_convert(rep, dai_props); + + snd_soc_dai_link_set_capabilities(dai_link); + + ret = graph_link_init(priv, rep, li, is_cpu, dai_name); +err: + of_node_put(ep); + of_node_put(rep); + + return ret; +} +EXPORT_SYMBOL_GPL(audio_graph2_link_dpcm); + static int graph_link(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -449,6 +666,12 @@ static int graph_link(struct asoc_simple_priv *priv, else func = audio_graph2_link_normal; break; + case GRAPH_DPCM: + if (hooks && hooks->custom_dpcm) + func = hooks->custom_dpcm; + else + func = audio_graph2_link_dpcm; + break; } if (!func) { @@ -480,6 +703,37 @@ static int graph_count_normal(struct asoc_simple_priv *priv, return 0; } +static int graph_count_dsp(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + /* + * DSP { + * compatible = "audio-graph-card2-dsp"; + * + * // Front-End + * ports@0 { + * => lnk: port@0 { endpoint { ... }; }; + * ... + * }; + * // Back-End + * ports@1 { + * => lnk: port@0 { endpoint { ... }; }; + * ... + * }; + * }; + */ + if (asoc_graph_is_ports0(lnk)) { + /* Front-End */ + li->num[li->link].cpus = 1; + } else { + /* Back-End */ + li->num[li->link].codecs = 1; + } + + return 0; +} + static int graph_count(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -499,6 +753,9 @@ static int graph_count(struct asoc_simple_priv *priv, case GRAPH_NORMAL: func = graph_count_normal; break; + case GRAPH_DPCM: + func = graph_count_dsp; + break; } if (!func) { From patchwork Tue Jul 20 01:40:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481636 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 087CAC07E95 for ; Tue, 20 Jul 2021 01:43:13 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 67B71610CC for ; Tue, 20 Jul 2021 01:43:12 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 67B71610CC Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 00D513E; Tue, 20 Jul 2021 03:42:21 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 00D513E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745391; bh=L69MH+FiJq7DJKIlzextV0AcPx6ycnJjx3IV9YB19UY=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=aE4iO5v75515D9UjnqQXTj3eue7o8x769fV+Z/CyQsd3yVsTTgCDaJyVFsuXviP1u iBsrTWiB5MSRB9nMyAd23f8FMuQmM68W6PNfxwHantZxdEcTndRmcSF/jFqb5XknxI u0osjPWqrrGSNbhDtJAGdIR55UAi+/e13vvbHBX4= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B1976F8050F; Tue, 20 Jul 2021 03:40:30 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 9370EF80518; Tue, 20 Jul 2021 03:40:29 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 77FE9F8050F for ; Tue, 20 Jul 2021 03:40:25 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 77FE9F8050F Date: 20 Jul 2021 10:40:25 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88181521" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 20 Jul 2021 10:40:25 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 0D8CA4153B50; Tue, 20 Jul 2021 10:40:25 +0900 (JST) Message-ID: <87y2a1vk3a.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 08/14] ASoC: audio-graph-card2: add Codec2Codec support User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto This patch adds Codec2Codec support to audio-graph-card2. It can use Codec2Codec but very limited/simple case only for now. It doesn't have "SWITCH" control yet, thus it start automatically when probed, but can't stop, so far. Thus it needs to be updated around widgets/routing handling, and you need to understand that it is under experimental. It is assuming 2channel, S32_LE format for now. It needs to be updated, too. Codec2Codec support needs to have extra node (= X) to indicate it. Codec2Codec needs "routing" (= A) and "rate" (= C). "links" (= B) needs to indicate Codec2Codec's CPU part node (= D). +--+ | |<-- Codec0 | |--> Codec1 +--+ sound { compatible = "audio-graph-card2"; (A) routing = "OUT" ,"DAI1 Playback", "DAI0 Capture", "IN"; (B) links = <&codec2codec>; }; (X) CODEC2CODEC { compatible = "audio-graph-card2-codec2codec"; (C) rate = <48000>; ports { (D) codec2codec: port@0 { fe_ep: endpoint { remote-endpoint = <&codec0_ep>; }; }; port@1 { be_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; }; }; Codec { ports { port@0 { bitclock-master; frame-master; codec0_ep: endpoint { remote-endpoint = <&fe_ep>; }; }; port@1 { codec1_ep: endpoint { remote-endpoint = <&be_ep>; }; }; }; }; Link: https://lore.kernel.org/r/87k0xszlep.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto --- include/sound/graph_card.h | 3 + sound/soc/generic/audio-graph-card2.c | 164 ++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index d0ccb7afda78..e870ae133a15 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -19,6 +19,7 @@ struct graph_custom_hooks { GRAPH_CUSTOM custom_normal; GRAPH_CUSTOM custom_dpcm; GRAPH_CUSTOM custom_multi; + GRAPH_CUSTOM custom_c2c; }; int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); @@ -31,5 +32,7 @@ int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, struct device_node *lnk, struct link_info *li); int audio_graph2_link_multi(struct asoc_simple_priv *priv, struct device_node *lnk, struct link_info *li); +int audio_graph2_link_c2c(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); #endif /* __GRAPH_CARD_H */ diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c index f77cf02c0eef..06f8556913e0 100644 --- a/sound/soc/generic/audio-graph-card2.c +++ b/sound/soc/generic/audio-graph-card2.c @@ -184,16 +184,58 @@ CPU2 <--> * * <--> Codec2 port@1 { codec2_ep: endpoint { remote-endpoint = <&mcodec2_ep>; }; }; }; }; + + + ************************************ + Codec to Codec + ************************************ + + +--+ + | |<-- Codec0 + | |--> Codec1 + +--+ + + sound { + compatible = "audio-graph-card2"; + + routing = "OUT" ,"DAI1 Playback", + "DAI0 Capture", "IN"; + + links = <&codec2codec>; + }; + + CODEC2CODEC { + compatible = "audio-graph-card2-codec2codec"; + + rate = <48000>; + ports { + codec2codec: port@0 { fe_ep: endpoint { remote-endpoint = <&codec0_ep>; }; }; + port@1 { be_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; + }; + }; + + Codec { + ports { + port@0 { + bitclock-master; + frame-master; + codec0_ep: endpoint { remote-endpoint = <&fe_ep>; }; }; + port@1 { codec1_ep: endpoint { remote-endpoint = <&be_ep>; }; }; + }; + }; + */ enum graph_type { GRAPH_NORMAL, GRAPH_DPCM, GRAPH_MULTI, + GRAPH_C2C, }; #define GRAPH_COMPATIBLE_DPCM "audio-graph-card2-dsp" #define GRAPH_COMPATIBLE_MULTI "audio-graph-card2-multi" +#define GRAPH_COMPATIBLE_C2C "audio-graph-card2-codec2codec" #define port_to_endpoint(port) of_get_child_by_name(port, "endpoint") @@ -220,6 +262,8 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv, type = GRAPH_DPCM; else if (strcmp(string, GRAPH_COMPATIBLE_MULTI) == 0) type = GRAPH_MULTI; + else if (strcmp(string, GRAPH_COMPATIBLE_C2C) == 0) + type = GRAPH_C2C; end: #ifdef DEBUG { @@ -236,6 +280,9 @@ static enum graph_type graph_get_type(struct asoc_simple_priv *priv, case GRAPH_MULTI: str = "MULTI"; break; + case GRAPH_C2C: + str = "Codec2Codec"; + break; default: break; } @@ -777,6 +824,93 @@ int audio_graph2_link_multi(struct asoc_simple_priv *priv, } EXPORT_SYMBOL_GPL(audio_graph2_link_multi); +int audio_graph2_link_c2c(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + struct snd_soc_pcm_stream *c2c_conf = dai_props->c2c_conf; + struct device_node *port = lnk; + struct device_node *ports = of_get_parent(port); + struct device_node *top = of_get_parent(ports); + struct device_node *ep; + struct device_node *rep; + struct device_node *first_rep = NULL; + char dai_name[64]; + u32 val; + int is_cpu; + int ret = -EINVAL; + + /* + * top: CODEC2CODEC { + * compatible = "audio-graph-card2-codec2codec"; + * + * rate = <48000>; + * ports { + * => lnk: port@0 { ep: endpoint { remote-endpoint = <&rep>; }; }; + * port@1 { ... }; + * }; + * }; + */ + if (!of_get_property(top, "rate", &val)) { + struct device *dev = simple_priv_to_dev(priv); + + dev_err(dev, "unknown codec2codec rate\n"); + goto err; + } + + c2c_conf->formats = SNDRV_PCM_FMTBIT_S32_LE; /* update ME */ + c2c_conf->rate_min = + c2c_conf->rate_max = val; + c2c_conf->channels_min = + c2c_conf->channels_max = 2; /* update ME */ + dai_link->params = c2c_conf; + + of_node_get(lnk); + for (is_cpu = 1; is_cpu >= 0; is_cpu--) { + int is_single_links = 0; + + ep = port_to_endpoint(port); + rep = of_graph_get_remote_endpoint(ep); + + if (!first_rep) + first_rep = rep; + + ret = graph_parse_node(priv, rep, li, 0, + is_cpu ? &is_single_links : NULL); + if (ret < 0) + goto err; + + of_node_put(ep); + of_node_put(rep); + + /* + * 1st turn was for CPU part of Codec (is_cpu = 1) + * 2nd turn is for Codec part of Codec (is_cpu = 0) + */ + if (is_cpu) { + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + + asoc_simple_canonicalize_cpu(cpus, is_single_links); + + /* next port = Codec part port */ + port = of_get_next_child(ports, port); + } + } + + snprintf(dai_name, sizeof(dai_name), "codec2codec-%pOFP", top); + + ret = graph_link_init(priv, first_rep, li, 0, dai_name); /* Codec base */ +err: + of_node_put(ports); + of_node_put(port); + of_node_put(top); + + return ret; +} +EXPORT_SYMBOL_GPL(audio_graph2_link_c2c); + static int graph_link(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -806,6 +940,12 @@ static int graph_link(struct asoc_simple_priv *priv, else func = audio_graph2_link_multi; break; + case GRAPH_C2C: + if (hooks && hooks->custom_c2c) + func = hooks->custom_c2c; + else + func = audio_graph2_link_c2c; + break; } if (!func) { @@ -903,6 +1043,27 @@ static int graph_count_multi(struct asoc_simple_priv *priv, return 0; } +static int graph_count_c2c(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + /* + * CODEC2CODEC { + * compatible = "audio-graph-card2-codec2codec"; + * + * ports { + * => lnk: port@0 { endpoint { ... }; }; + * port@1 { endpoint { ... }; }; + * }; + * }; + */ + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].c2c = 1; + + return 0; +} + static int graph_count(struct asoc_simple_priv *priv, struct graph_custom_hooks *hooks, enum graph_type gtype, @@ -928,6 +1089,9 @@ static int graph_count(struct asoc_simple_priv *priv, case GRAPH_MULTI: func = graph_count_multi; break; + case GRAPH_C2C: + func = graph_count_c2c; + break; } if (!func) { From patchwork Tue Jul 20 01:41:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481635 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6BD51C07E9B for ; Tue, 20 Jul 2021 01:43:53 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 89A616108B for ; Tue, 20 Jul 2021 01:43:52 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 89A616108B Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 2A04F1674; Tue, 20 Jul 2021 03:43:01 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 2A04F1674 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745431; bh=pdah/ldGsBecmTkWhtML23PC1NjKwElQ7Trnhsa7/pc=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Pts2xWxva+jpQXmTU3jSYfUrzW1zhfTLbyD77HMx03OR4qfJP+P6nr227XsMJrq8k BSruukGdVIHjnjZ04nkkaXaRJTM3DjECMhzWHTUsO4ARdBJeYfgLHAq+IvKWn+JZPp 4AWfC24YYeRi3rfstj3y2zBWnKWTzl4caT2svsQM= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 3B6C8F804D0; Tue, 20 Jul 2021 03:41:18 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id A481EF804E0; Tue, 20 Jul 2021 03:41:16 +0200 (CEST) Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by alsa1.perex.cz (Postfix) with ESMTP id 91877F80227 for ; Tue, 20 Jul 2021 03:41:13 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 91877F80227 Date: 20 Jul 2021 10:41:12 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88130067" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 20 Jul 2021 10:41:12 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 56854400B9FD; Tue, 20 Jul 2021 10:41:12 +0900 (JST) Message-ID: <87v955vk1z.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 10/14] ASoC: sample-custom-card: add Audio Graph Card2 custome sample User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto One of audio-graph-card issue was that it can't handle *user own* card settings. We can expand audio-graph-card if it was *generic* feature. Latest audio-graph-card has customizing support. Audio Graph Card2 also have customize support. This means user can use its own special settings by using audio-graph-card2 driver parsing. This patch adds Audio Graph Cars2 customize sample driver. It can get basic audio-graph-card2 setups by calling asoc_graph_parse_of2(...), and user can update/expand each own setting on it. Signed-off-by: Kuninori Morimoto --- sound/soc/generic/Kconfig | 6 + sound/soc/generic/Makefile | 2 + sound/soc/generic/sample-custom-card.c | 160 +++++++++++++++++++++++++ 3 files changed, 168 insertions(+) create mode 100644 sound/soc/generic/sample-custom-card.c diff --git a/sound/soc/generic/Kconfig b/sound/soc/generic/Kconfig index 3385c488cd85..c7cd0488e4fc 100644 --- a/sound/soc/generic/Kconfig +++ b/sound/soc/generic/Kconfig @@ -26,6 +26,12 @@ config SND_AUDIO_GRAPH_CARD2 This option enables generic simple sound card support with OF-graph DT bindings. +config SND_SAMPLE_CUSTOM_CARD + tristate "ASoC Audio Graph Sound Card2 base custom card sample support" + depends on OF && SND_AUDIO_GRAPH_CARD2 + help + This option enables Audio Graph Sound Card2 base custom card support + config SND_TEST_COMPONENT tristate "ASoC Test component sound support" depends on OF diff --git a/sound/soc/generic/Makefile b/sound/soc/generic/Makefile index b480f47a330d..1b438202609c 100644 --- a/sound/soc/generic/Makefile +++ b/sound/soc/generic/Makefile @@ -3,10 +3,12 @@ snd-soc-simple-card-utils-objs := simple-card-utils.o snd-soc-simple-card-objs := simple-card.o snd-soc-audio-graph-card-objs := audio-graph-card.o snd-soc-audio-graph-card2-objs := audio-graph-card2.o +snd-soc-sample-custom-card-objs := sample-custom-card.o snd-soc-test-component-objs := test-component.o obj-$(CONFIG_SND_SIMPLE_CARD_UTILS) += snd-soc-simple-card-utils.o obj-$(CONFIG_SND_SIMPLE_CARD) += snd-soc-simple-card.o obj-$(CONFIG_SND_AUDIO_GRAPH_CARD) += snd-soc-audio-graph-card.o obj-$(CONFIG_SND_AUDIO_GRAPH_CARD2) += snd-soc-audio-graph-card2.o +obj-$(CONFIG_SND_SAMPLE_CUSTOM_CARD) += snd-soc-sample-custom-card.o obj-$(CONFIG_SND_TEST_COMPONENT) += snd-soc-test-component.o diff --git a/sound/soc/generic/sample-custom-card.c b/sound/soc/generic/sample-custom-card.c new file mode 100644 index 000000000000..e7b321fb5db9 --- /dev/null +++ b/sound/soc/generic/sample-custom-card.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// sample-custom-card.c +// +// Copyright (c) 2020 Kuninori Morimoto +// +#include +#include +#include +#include + +/* + * Custom driver can have own priv + * which includes asoc_simple_priv. + */ +struct custom_priv { + struct asoc_simple_priv simple_priv; + + /* custom driver's own params */ + int custom_params; +}; + +/* You can get custom_priv from simple_priv */ +#define simple_to_custom(simple) container_of((simple), struct custom_priv, simple_priv) + +static int custom_card_probe(struct snd_soc_card *card) +{ + struct asoc_simple_priv *simple_priv = snd_soc_card_get_drvdata(card); + struct custom_priv *custom_priv = simple_to_custom(simple_priv); + struct device *dev = simple_priv_to_dev(simple_priv); + + dev_info(dev, "custom probe\n"); + + custom_priv->custom_params = 1; + + /* you can use generic probe function */ + return asoc_graph_card_probe(card); +} + +static int custom_hook_pre(struct asoc_simple_priv *priv) +{ + struct device *dev = simple_priv_to_dev(priv); + + /* You can custom before parsing */ + dev_info(dev, "hook : %s\n", __func__); + + return 0; +} + +static int custom_hook_post(struct asoc_simple_priv *priv) +{ + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_card *card; + + /* You can custom after parsing */ + dev_info(dev, "hook : %s\n", __func__); + + card = simple_priv_to_card(priv); + card->probe = custom_card_probe; /* overwrite .probe */ + + return 0; +} + +static int custom_dpcm(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct device *dev = simple_priv_to_dev(priv); + + /* You can custom for DPCM parsing */ + dev_info(dev, "hook : %s\n", __func__); + + return audio_graph2_link_dpcm(priv, lnk, li); +} + +static int custom_c2c(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li) +{ + struct device *dev = simple_priv_to_dev(priv); + + /* You can custom for Codec2Codec parsing */ + dev_info(dev, "hook : %s\n", __func__); + + return audio_graph2_link_c2c(priv, lnk, li); +} + +/* + * audio-graph-card2 has many hooks for your customizing. + */ +static struct graph_custom_hooks custom_hooks = { + .hook_pre = custom_hook_pre, + .hook_post = custom_hook_post, + .custom_dpcm = custom_dpcm, + .custom_c2c = custom_c2c, + /* and more ... */ +}; + +static int custom_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); + struct device *dev = simple_priv_to_dev(priv); + + dev_info(dev, "custom startup\n"); + + return asoc_simple_startup(substream); +} + +/* You can use custom ops */ +static const struct snd_soc_ops custom_ops = { + .startup = custom_startup, + .shutdown = asoc_simple_shutdown, + .hw_params = asoc_simple_hw_params, +}; + +static int custom_probe(struct platform_device *pdev) +{ + struct custom_priv *custom_priv; + struct asoc_simple_priv *simple_priv; + struct device *dev = &pdev->dev; + int ret; + + custom_priv = devm_kzalloc(dev, sizeof(*custom_priv), GFP_KERNEL); + if (!custom_priv) + return -ENOMEM; + + simple_priv = &custom_priv->simple_priv; + simple_priv->ops = &custom_ops; /* customize dai_link ops */ + + /* use audio-graph-card2 parsing with own custom hooks */ + ret = audio_graph2_parse_of(simple_priv, dev, &custom_hooks); + if (ret < 0) + return ret; + + /* customize more if needed */ + + return 0; +} + +static const struct of_device_id custom_of_match[] = { + { .compatible = "sample-custom-card", }, + {}, +}; +MODULE_DEVICE_TABLE(of, custom_of_match); + +static struct platform_driver custom_card = { + .driver = { + .name = "sample-custom-card", + .of_match_table = custom_of_match, + }, + .probe = custom_probe, + .remove = asoc_simple_remove, +}; +module_platform_driver(custom_card); + +MODULE_ALIAS("platform:asoc-sample-custom-card"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("ASoC Audio Graph Sound Card2 Custom"); +MODULE_AUTHOR("Kuninori Morimoto "); From patchwork Tue Jul 20 01:41:27 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481634 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7DF6DC07E9B for ; Tue, 20 Jul 2021 01:44:43 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 05DC86101E for ; Tue, 20 Jul 2021 01:44:43 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 05DC86101E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id 99FC41660; Tue, 20 Jul 2021 03:43:51 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 99FC41660 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745481; bh=Uqzxsp2vBTcWzj9C4CKoSGM79cFjMhOrf6fYHNi5DAM=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=je/P9UN66imeOrrfBHznuNnFqYFK9dqc2jJeAiLVtCphNQjkm5QPFCdCDZ6NaNA1c qgC8ARp79xxgNOSv81+n1FBCc0KCX/3FBw/uk9EYEotzSyFD8ctt0KCuFFwH0HcRyi CN4TDntqt9pcDNe20zv3fR6k/Yti4fFTd6cccBFE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 00C31F804FB; Tue, 20 Jul 2021 03:41:33 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 7B6AEF804FB; Tue, 20 Jul 2021 03:41:31 +0200 (CEST) Received: from relmlie6.idc.renesas.com (relmlor2.renesas.com [210.160.252.172]) by alsa1.perex.cz (Postfix) with ESMTP id B23ABF8051B for ; Tue, 20 Jul 2021 03:41:28 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B23ABF8051B Date: 20 Jul 2021 10:41:27 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88130093" Received: from unknown (HELO relmlir5.idc.renesas.com) ([10.200.68.151]) by relmlie6.idc.renesas.com with ESMTP; 20 Jul 2021 10:41:27 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir5.idc.renesas.com (Postfix) with ESMTP id 6DD124005164; Tue, 20 Jul 2021 10:41:27 +0900 (JST) Message-ID: <87sg09vk1k.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 12/14] ASoC: audio-graph-card2-sample.dtsi: add DPCM sample User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto This patch adds DPCM sample to audio-graph-card2-sample.dtsi. This sample is assuming MIXer connection. CPU2 --\ +-- Codec2 CPU3 --/ Signed-off-by: Kuninori Morimoto --- .../soc/generic/audio-graph-card2-sample.dtsi | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sound/soc/generic/audio-graph-card2-sample.dtsi b/sound/soc/generic/audio-graph-card2-sample.dtsi index 5e83bfed1781..9aab6be176e5 100644 --- a/sound/soc/generic/audio-graph-card2-sample.dtsi +++ b/sound/soc/generic/audio-graph-card2-sample.dtsi @@ -20,6 +20,8 @@ / { /* * cpu0 <--> codec0 // Normal * cpu1 <--> codec1 // Normal + * cpu2 <--> codec2 // DPCM + * cpu3 <-/ // DPCM */ card2 { /* @@ -30,10 +32,27 @@ card2 { */ compatible = "sample-custom-card"; + routing = "TC DAI2 Playback", "DAI2 Playback", + "TC DAI2 Playback", "DAI3 Playback", + "DAI2 Capture", "TC DAI2 Capture", + "DAI3 Capture", "TC DAI2 Capture"; + links = <&cpu0 &cpu1 /* normal: cpu side only */ + &mix_fe0 &mix_fe1 &mix_be0 /* dsp : both fe/be */ >; }; + mix { + compatible = "audio-graph-card2-dsp"; + DSP_FE: ports@0 { + mix_fe0: port@0 { mix_fe0_ep: endpoint { remote-endpoint = <&cpu2_ep>; }; }; + mix_fe1: port@1 { mix_fe1_ep: endpoint { remote-endpoint = <&cpu3_ep>; }; }; + }; + DSP_BE: ports@1 { + mix_be0: port { mix_be0_ep: endpoint { remote-endpoint = <&codec2_ep>; }; }; + }; + }; + test_cpu { /* * update compatible to indicate more detail behaviour @@ -48,6 +67,8 @@ ports { frame-master; cpu0: port@0 { cpu0_ep: endpoint { remote-endpoint = <&codec0_ep>; }; }; cpu1: port@1 { cpu1_ep: endpoint { remote-endpoint = <&codec1_ep>; }; }; + port@2 { cpu2_ep: endpoint { remote-endpoint = <&mix_fe0_ep>; }; }; + port@3 { cpu3_ep: endpoint { remote-endpoint = <&mix_fe1_ep>; }; }; }; }; @@ -61,8 +82,15 @@ test_codec { */ compatible = "test-codec"; ports { + /* + * prefix can be added to *component*, + * see card2::routing + */ + prefix = "TC"; + port@0 { codec0_ep: endpoint { remote-endpoint = <&cpu0_ep>; }; }; port@1 { codec1_ep: endpoint { remote-endpoint = <&cpu1_ep>; }; }; + port@2 { codec2_ep: endpoint { remote-endpoint = <&mix_be0_ep>; }; }; }; }; }; From patchwork Tue Jul 20 01:41:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kuninori Morimoto X-Patchwork-Id: 481633 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-13.7 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 89662C07E9B for ; Tue, 20 Jul 2021 01:45:26 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0162B61165 for ; Tue, 20 Jul 2021 01:45:25 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0162B61165 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=renesas.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-devel-bounces@alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id A5EF0167A; Tue, 20 Jul 2021 03:44:34 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz A5EF0167A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1626745524; bh=9H79nmK33NrdHG1DHvOLTLch7qtZJ0k840i33O4QoD8=; h=Date:From:Subject:To:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QHHJgItiHgql+yaw3e45uT2K/9Sv2G6XnPpubLgvAGQdkeD3Aj+ioHyq93WirxUIV tdWsk5QxSJq4kL30d9WorU9Wl9bTEWGnO23t1JAWKFTV9GfdJ/H5mGsll54rFosFpb +lIz9z8QfZw5m97R0GIs796rsRD3DjusvhY/uYng= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id A8E1BF8051E; Tue, 20 Jul 2021 03:41:45 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1171CF8051E; Tue, 20 Jul 2021 03:41:44 +0200 (CEST) Received: from relmlie5.idc.renesas.com (relmlor1.renesas.com [210.160.252.171]) by alsa1.perex.cz (Postfix) with ESMTP id 43873F80520 for ; Tue, 20 Jul 2021 03:41:36 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 43873F80520 Date: 20 Jul 2021 10:41:36 +0900 X-IronPort-AV: E=Sophos;i="5.84,253,1620658800"; d="scan'208";a="88181700" Received: from unknown (HELO relmlir6.idc.renesas.com) ([10.200.68.152]) by relmlie5.idc.renesas.com with ESMTP; 20 Jul 2021 10:41:36 +0900 Received: from mercury.renesas.com (unknown [10.166.252.133]) by relmlir6.idc.renesas.com (Postfix) with ESMTP id 0133E4153E8B; Tue, 20 Jul 2021 10:41:35 +0900 (JST) Message-ID: <87pmvdvk1b.wl-kuninori.morimoto.gx@renesas.com> From: Kuninori Morimoto Subject: [PATCH v2 14/14] ASoC: audio-graph-card2-sample.dtsi: add Codec2Codec sample. User-Agent: Wanderlust/2.15.9 Emacs/26.3 Mule/6.0 To: Mark Brown In-Reply-To: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> References: <87a6mhwyqn.wl-kuninori.morimoto.gx@renesas.com> MIME-Version: 1.0 (generated by SEMI-EPG 1.14.7 - "Harue") Cc: Linux-ALSA X-BeenThere: alsa-devel@alsa-project.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: "Alsa-devel mailing list for ALSA developers - http://www.alsa-project.org" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: alsa-devel-bounces@alsa-project.org Sender: "Alsa-devel" From: Kuninori Morimoto This patch adds Codec2Codec sample to audio-graph-card2-sample.dtsi. Because it can use very basic connection only for now, it can use only - 2channels - S32_LE format Test-Component driver has "IN" and "OUT" widget. Thus the route is +--+ | | <-- Codec5 | | --> Codec6 +--+ (*) "IN" -> "DAI5 Capture" -> "DAI6 Playback" -> "OUT" (*) routing is using "TC" prefix on this sample. One note here is that it will start works when it boot. In other words we can't stop it so far. We need to update driver for it in the future. Signed-off-by: Kuninori Morimoto --- .../soc/generic/audio-graph-card2-sample.dtsi | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/sound/soc/generic/audio-graph-card2-sample.dtsi b/sound/soc/generic/audio-graph-card2-sample.dtsi index 1d18aba22011..9d491cf6b776 100644 --- a/sound/soc/generic/audio-graph-card2-sample.dtsi +++ b/sound/soc/generic/audio-graph-card2-sample.dtsi @@ -24,6 +24,8 @@ / { * cpu3 <-/ // DPCM * cpu4 <==> codec3 // Multi (*1) * cpu5 <==> codec4 // Multi (*1) + * /=> codec5 // Codec2Codec + * \=> codec6 // Codec2Codec */ card2 { /* @@ -37,11 +39,14 @@ card2 { routing = "TC DAI2 Playback", "DAI2 Playback", "TC DAI2 Playback", "DAI3 Playback", "DAI2 Capture", "TC DAI2 Capture", - "DAI3 Capture", "TC DAI2 Capture"; + "DAI3 Capture", "TC DAI2 Capture", + "TC OUT" ,"TC DAI6 Playback", + "TC DAI5 Capture", "TC IN"; links = <&cpu0 &cpu1 /* normal: cpu side only */ &mix_fe0 &mix_fe1 &mix_be0 /* dsp : both fe/be */ &multi_cpu /* multi : cpu side only */ + &c2c /* c2c : first one only */ >; }; @@ -76,6 +81,16 @@ multi_codec: ports@1 { }; }; + codec2codec { + compatible = "audio-graph-card2-codec2codec"; + + rate = <48000>; + ports { + c2c: port@0 { c2c_0_ep: endpoint { remote-endpoint = <&codec5_ep>; }; }; + port@1 { c2c_1_ep: endpoint { remote-endpoint = <&codec6_ep>; }; }; + }; + }; + test_cpu { /* * update compatible to indicate more detail behaviour @@ -118,6 +133,8 @@ ports { port@2 { codec2_ep: endpoint { remote-endpoint = <&mix_be0_ep>; }; }; port@3 { codec3_ep: endpoint { remote-endpoint = <&multi_10_ep>; }; }; port@4 { codec4_ep: endpoint { remote-endpoint = <&multi_11_ep>; }; }; + port@5 { codec5_ep: endpoint { remote-endpoint = <&c2c_0_ep>; }; }; + port@6 { codec6_ep: endpoint { remote-endpoint = <&c2c_1_ep>; }; }; }; }; };