From patchwork Thu Mar 17 17:50:26 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784401 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id CFF89C433EF for ; Thu, 17 Mar 2022 17:53:28 +0000 (UTC) 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 F2D4818BB; Thu, 17 Mar 2022 18:52:36 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz F2D4818BB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539607; bh=Px5WUh7+GYyzaDBhCLmS0KV1WQ96drJzbOBM7gBMx2w=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=CyNdqf4orpxEVMjt5Uhc51Mn3Cpk1IAyrEZJHd5fog/c4csY8OU3PJOwFMax6iC0y yr+8CIG+UbxS1Hu6kjZZ04N2RFC4U9yeQElFPZtwTVcfixritf14KRoZtQcBtyg0/J ogSe+u3/TuD+Cq0U1QTa/h4+scY3gqyByif6VJwk= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id BE5B0F8051A; Thu, 17 Mar 2022 18:51:52 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1617DF80516; Thu, 17 Mar 2022 18:51:50 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 25EABF80132 for ; Thu, 17 Mar 2022 18:51:42 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 25EABF80132 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="b2vHk6Dg" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539504; x=1679075504; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Px5WUh7+GYyzaDBhCLmS0KV1WQ96drJzbOBM7gBMx2w=; b=b2vHk6DgszM5nOVij/4tVVOEg1epxHmStxCl9rE01G5jDbIMiwoQ1nLb LhLBIvt8OykT7v19WosWvWzU8aH60fFTlkRxvgW93lFLQHIfUFR0SN5Ln n7r7fl1LAZ1lzI+hm6XLz+bdYeXPavKp/PLIfWqZXCdVCFgNF0gqmy2N2 ySbjlLxHhJPgiz38yRl6a4HQ+7zgWwXKPL7iMpz4J3Kx+9GyaaXTSLVHV NwjCR0F+0+qRqnGFzqKkmB7wjNeBksjxgN0edxqOCBu9qoOqqp+029B3d NUYx6zB9ffgMUJvvBmRcDNmCSxICNwE/mVUKD1O7ADC7vsOHz/XmWpx0X Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492896" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492896" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431106" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 01/19] ASoC: SOF: set up scheduler widget before all other widgets in the pipeline Date: Thu, 17 Mar 2022 10:50:26 -0700 Message-Id: <20220317175044.1752400-2-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" For dynamic pipelines, We set up the DAI widget during BE DAI hw_params and this results in it getting set up before the scheduler widget for the pipeline it belongs to is set up. Move the scheduler widget set up into sof_widget_setup() to ensure that the scheduler widget is always the first widget in a pipeline to be set up and the last one to get freed after all the other widgets have been freed. Fixes: 5fcdbb2d45df ('ASoC: SOF: Add support for dynamic pipelines') Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/sof-audio.c | 82 +++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 38 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 683c290bb69a..cc0d647a2d0d 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -104,7 +104,7 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) .id = swidget->comp_id, }; struct sof_ipc_reply reply; - int ret, ret1; + int ret, err; if (!swidget->private) return 0; @@ -136,31 +136,41 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) } /* continue to disable core even if IPC fails */ - ret = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), + err = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), &reply, sizeof(reply)); - if (ret < 0) + if (err < 0) dev_err(sdev->dev, "error: failed to free widget %s\n", swidget->widget->name); /* * disable widget core. continue to route setup status and complete flag * even if this fails and return the appropriate error */ - ret1 = snd_sof_dsp_core_put(sdev, swidget->core); - if (ret1 < 0) { + ret = snd_sof_dsp_core_put(sdev, swidget->core); + if (ret < 0) { dev_err(sdev->dev, "error: failed to disable target core: %d for widget %s\n", swidget->core, swidget->widget->name); - if (!ret) - ret = ret1; + if (!err) + err = ret; } /* reset route setup status for all routes that contain this widget */ sof_reset_route_setup_status(sdev, swidget); swidget->complete = 0; - if (!ret) + /* + * free the scheduler widget (same as pipe_widget) associated with the current swidget. + * skip for static pipelines + */ + if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { + ret = sof_widget_free(sdev, swidget->pipe_widget); + if (ret < 0 && !err) + err = ret; + } + + if (!err) dev_dbg(sdev->dev, "widget %s freed\n", swidget->widget->name); - return ret; + return err; } EXPORT_SYMBOL(sof_widget_free); @@ -181,12 +191,32 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (++swidget->use_count > 1) return 0; + /* + * The scheduler widget for a pipeline is not part of the connected DAPM + * widget list and it needs to be set up before the widgets in the pipeline + * are set up. The use_count for the scheduler widget is incremented for every + * widget in a given pipeline to ensure that it is freed only after the last + * widget in the pipeline is freed. Skip setting up scheduler widget for static pipelines. + */ + if (swidget->dynamic_pipeline_widget && swidget->id != snd_soc_dapm_scheduler) { + if (!swidget->pipe_widget) { + dev_err(sdev->dev, "No scheduler widget set for %s\n", + swidget->widget->name); + ret = -EINVAL; + goto use_count_dec; + } + + ret = sof_widget_setup(sdev, swidget->pipe_widget); + if (ret < 0) + goto use_count_dec; + } + /* enable widget core */ ret = snd_sof_dsp_core_get(sdev, swidget->core); if (ret < 0) { dev_err(sdev->dev, "error: failed to enable target core for widget %s\n", swidget->widget->name); - goto use_count_dec; + goto pipe_widget_free; } switch (swidget->id) { @@ -257,6 +287,9 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) core_put: snd_sof_dsp_core_put(sdev, swidget->core); +pipe_widget_free: + if (swidget->id != snd_soc_dapm_scheduler) + sof_widget_free(sdev, swidget->pipe_widget); use_count_dec: swidget->use_count--; return ret; @@ -374,36 +407,14 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in /* set up widgets in the list */ for_each_dapm_widgets(list, num_widgets, widget) { struct snd_sof_widget *swidget = widget->dobj.private; - struct snd_sof_widget *pipe_widget; if (!swidget) continue; - /* - * The scheduler widget for a pipeline is not part of the connected DAPM - * widget list and it needs to be set up before the widgets in the pipeline - * are set up. The use_count for the scheduler widget is incremented for every - * widget in a given pipeline to ensure that it is freed only after the last - * widget in the pipeline is freed. - */ - pipe_widget = swidget->pipe_widget; - if (!pipe_widget) { - dev_err(sdev->dev, "error: no pipeline widget found for %s\n", - swidget->widget->name); - ret = -EINVAL; - goto widget_free; - } - - ret = sof_widget_setup(sdev, pipe_widget); - if (ret < 0) - goto widget_free; - /* set up the widget */ ret = sof_widget_setup(sdev, swidget); - if (ret < 0) { - sof_widget_free(sdev, pipe_widget); + if (ret < 0) goto widget_free; - } } /* @@ -456,7 +467,6 @@ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, in break; sof_widget_free(sdev, swidget); - sof_widget_free(sdev, swidget->pipe_widget); } return ret; @@ -490,10 +500,6 @@ int sof_widget_list_free(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int ret = sof_widget_free(sdev, swidget); if (ret < 0) ret1 = ret; - - ret = sof_widget_free(sdev, swidget->pipe_widget); - if (ret < 0) - ret1 = ret; } snd_soc_dapm_dai_free_widgets(&list); From patchwork Thu Mar 17 17:50:27 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 0129AC433F5 for ; Thu, 17 Mar 2022 17:56:00 +0000 (UTC) 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 36F9918D9; Thu, 17 Mar 2022 18:55:09 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 36F9918D9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539759; bh=EoyOH2QdU+zVON+BM/kXe3KoKzgX0+z/yk9kOPJSOeo=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=bmuZpaiE3J9T70TdzIcoU7aSlZPeHqP/KlPFL3vBVIu6VOwyu2B4Fne3IuwL1s6A3 2ZyxP19QMaPyS9Kz/MYjownUAZFOQhfevGSNdJXJbWkZ+gwVOOQOP+PKCjDNO+aHS5 gCZpkA5lm5JPbsT+usbXAdFGcth6Diye6H3p/k2Q= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 6211AF80544; Thu, 17 Mar 2022 18:52:14 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 39567F80536; Thu, 17 Mar 2022 18:52:05 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 88B00F80519 for ; Thu, 17 Mar 2022 18:51:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 88B00F80519 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="OiDUVWbD" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539512; x=1679075512; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=EoyOH2QdU+zVON+BM/kXe3KoKzgX0+z/yk9kOPJSOeo=; b=OiDUVWbDWDyVOEqacge0vdcyPOqb1hy1hFU4NCkG6esRJZeGI8OggCuz Js9JaVAllYyT2cLQFBKjYecVuFTLOi55Z2ArMiRDDg7S159qFTbFiRgrx yYsfNjERNi+WlodMZpMJqX7UhG69OYciqDk5pR3yBU8YKzj0qcbxwuA+o qm9fLk7WyqsO1IPtKp5i03E54KaHyyAGRCgU6DP+nUOiY7Oh1IvPUMzry HSw7tK/+yjzGM4DPplRIGJ3EzcPWfQcsqyhcaxTIUlPQZAtblspEAVZsA bIxxoaLcRn/lClS6gCE2mSDa9ceVYojSJn7VULU57N6EG+vOG9a8ceLSR Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492899" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492899" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431109" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 02/19] ASoC: SOF: Make sof_widget_setup/free IPC agnostic Date: Thu, 17 Mar 2022 10:50:27 -0700 Message-Id: <20220317175044.1752400-3-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart , broonie@kernel.org, Bard Liao 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" Add 3 new topology IPC ops for widget_setup, widget_free and dai_config in order to make the pipeline management code IPC agnostic and implement the ops for IPC3. Use the newly introduced tplg dai_config op to configure the DAI during BE DAI hw_params and hw_free. Also, in preparation for IPC4, modify BE hw_params callback to skip setting up the DAI widget. All widgets will be set up during FW hw_params and the DAI_CONFIG IPC should be sent only if the widget use_count is > 0. With setting up/freeing removed from the BE hw_params, remove the configured flag as it is no longer needed. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao --- sound/soc/sof/intel/hda-dai.c | 97 +++---------------- sound/soc/sof/intel/hda.c | 169 +++++++++------------------------- sound/soc/sof/intel/hda.h | 7 +- sound/soc/sof/ipc3-topology.c | 150 ++++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.c | 136 +++++---------------------- sound/soc/sof/sof-audio.h | 13 ++- 6 files changed, 246 insertions(+), 326 deletions(-) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index 9b78eea8d76b..f9cb9f1f0237 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -162,58 +162,19 @@ static int hda_link_dma_params(struct hdac_ext_stream *hext_stream, return 0; } -/* Update config for the DAI widget */ -static struct sof_ipc_dai_config *hda_dai_update_config(struct snd_soc_dapm_widget *w, - int channel) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct sof_dai_private_data *private; - struct sof_ipc_dai_config *config; - struct snd_sof_dai *sof_dai; - - if (!swidget) - return NULL; - - sof_dai = swidget->private; - - if (!sof_dai || !sof_dai->private) { - dev_err(swidget->scomp->dev, "%s: No private data for DAI %s\n", __func__, - w->name); - return NULL; - } - - private = sof_dai->private; - if (!private->dai_config) { - dev_err(swidget->scomp->dev, "%s: No config for DAI %s\n", __func__, w->name); - return NULL; - } - - config = &private->dai_config[sof_dai->current_config]; - - /* update config with stream tag */ - config->hda.link_dma_ch = channel; - - return config; -} - static int hda_link_dai_widget_update(struct sof_intel_hda_stream *hda_stream, struct snd_soc_dapm_widget *w, int channel, bool widget_setup) { - struct snd_sof_dev *sdev = hda_stream->sdev; - struct sof_ipc_dai_config *config; + struct snd_sof_dai_config_data data; - config = hda_dai_update_config(w, channel); - if (!config) { - dev_err(sdev->dev, "error: no config for DAI %s\n", w->name); - return -ENOENT; - } + data.dai_data = channel; /* set up/free DAI widget and send DAI_CONFIG IPC */ if (widget_setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP); + return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_2_STEP_STOP, &data); - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE); + return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); } static int hda_link_hw_params(struct snd_pcm_substream *substream, @@ -302,35 +263,16 @@ static int hda_link_dai_config_pause_push_ipc(struct snd_soc_dapm_widget *w) struct snd_sof_widget *swidget = w->dobj.private; struct snd_soc_component *component = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct sof_dai_private_data *private; - struct sof_ipc_dai_config *config; - struct snd_sof_dai *sof_dai; - struct sof_ipc_reply reply; - int ret; - - sof_dai = swidget->private; - - if (!sof_dai || !sof_dai->private) { - dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name); - return -EINVAL; - } + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + int ret = 0; - private = sof_dai->private; - if (!private->dai_config) { - dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name); - return -EINVAL; + if (tplg_ops->dai_config) { + ret = tplg_ops->dai_config(sdev, swidget, SOF_DAI_CONFIG_FLAGS_PAUSE, NULL); + if (ret < 0) + dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, + w->name); } - config = &private->dai_config[sof_dai->current_config]; - - /* set PAUSE command flag */ - config->flags = FIELD_PREP(SOF_DAI_CONFIG_FLAGS_CMD_MASK, SOF_DAI_CONFIG_FLAGS_PAUSE); - - ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, - &reply, sizeof(reply)); - if (ret < 0) - dev_err(sdev->dev, "DAI config for %s failed during pause push\n", w->name); - return ret; } @@ -470,30 +412,17 @@ struct ssp_dai_dma_data { static int ssp_dai_setup_or_free(struct snd_pcm_substream *substream, struct snd_soc_dai *dai, bool setup) { - struct snd_soc_component *component; - struct snd_sof_widget *swidget; struct snd_soc_dapm_widget *w; - struct sof_ipc_fw_version *v; - struct snd_sof_dev *sdev; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) w = dai->playback_widget; else w = dai->capture_widget; - swidget = w->dobj.private; - component = swidget->scomp; - sdev = snd_soc_component_get_drvdata(component); - v = &sdev->fw_ready.version; - - /* DAI_CONFIG IPC during hw_params is not supported in older firmware */ - if (v->abi_version < SOF_ABI_VER(3, 18, 0)) - return 0; - if (setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE); + return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE); + return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, NULL); } static int ssp_dai_startup(struct snd_pcm_substream *substream, diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 7403b9848a56..019f8d6b91d4 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -41,114 +41,68 @@ #define EXCEPT_MAX_HDR_SIZE 0x400 #define HDA_EXT_ROM_STATUS_SIZE 8 -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags) +int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, + struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; struct snd_soc_component *component = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct sof_ipc_dai_config *config; - struct sof_dai_private_data *private; - struct snd_sof_dai *sof_dai; - struct sof_ipc_reply reply; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + struct snd_sof_dai *sof_dai = swidget->private; int ret; - sof_dai = swidget->private; - - if (!sof_dai || !sof_dai->private) { - dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name); - return -EINVAL; - } - - private = sof_dai->private; - if (!private->dai_config) { - dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name); + if (!sof_dai) { + dev_err(sdev->dev, "%s: No DAI for DAI widget %s\n", __func__, w->name); return -EINVAL; } - /* DAI already configured, reset it before reconfiguring it */ - if (sof_dai->configured) { - ret = hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE); - if (ret < 0) - return ret; - } - - config = &private->dai_config[sof_dai->current_config]; - - /* - * For static pipelines, the DAI widget would already be set up and calling - * sof_widget_setup() simply returns without doing anything. - * For dynamic pipelines, the DAI widget will be set up now. - */ - ret = sof_widget_setup(sdev, swidget); - if (ret < 0) { - dev_err(sdev->dev, "error: failed setting up DAI widget %s\n", w->name); - return ret; - } + if (tplg_ops->dai_config) { + unsigned int flags; - /* set HW_PARAMS flag along with quirks */ - config->flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + /* set HW_PARAMS flag along with quirks */ + flags = SOF_DAI_CONFIG_FLAGS_HW_PARAMS | + quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - - /* send DAI_CONFIG IPC */ - ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, - &reply, sizeof(reply)); - if (ret < 0) { - dev_err(sdev->dev, "error: failed setting DAI config for %s\n", w->name); - return ret; + ret = tplg_ops->dai_config(sdev, swidget, flags, data); + if (ret < 0) { + dev_err(sdev->dev, "%s: DAI config failed for widget %s\n", __func__, + w->name); + return ret; + } } - sof_dai->configured = true; - return 0; } -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags) +int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, + struct snd_sof_dai_config_data *data) { struct snd_sof_widget *swidget = w->dobj.private; struct snd_soc_component *component = swidget->scomp; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct sof_dai_private_data *private; - struct sof_ipc_dai_config *config; - struct snd_sof_dai *sof_dai; - struct sof_ipc_reply reply; - int ret; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + struct snd_sof_dai *sof_dai = swidget->private; - sof_dai = swidget->private; - - if (!sof_dai || !sof_dai->private) { - dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name); - return -EINVAL; - } - - private = sof_dai->private; - if (!private->dai_config) { - dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name); + if (!sof_dai) { + dev_err(sdev->dev, "%s: No DAI for BE DAI widget %s\n", __func__, w->name); return -EINVAL; } - /* nothing to do if hw_free() is called without restarting the stream after resume. */ - if (!sof_dai->configured) - return 0; - - config = &private->dai_config[sof_dai->current_config]; + if (tplg_ops->dai_config) { + unsigned int flags; + int ret; - /* set HW_FREE flag along with any quirks */ - config->flags = SOF_DAI_CONFIG_FLAGS_HW_FREE | - quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; + /* set HW_FREE flag along with any quirks */ + flags = SOF_DAI_CONFIG_FLAGS_HW_FREE | + quirk_flags << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT; - ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, - &reply, sizeof(reply)); - if (ret < 0) - dev_err(sdev->dev, "error: failed resetting DAI config for %s\n", w->name); - - /* - * Reset the configured_flag and free the widget even if the IPC fails to keep - * the widget use_count balanced - */ - sof_dai->configured = false; + ret = tplg_ops->dai_config(sdev, swidget, flags, data); + if (ret < 0) + dev_err(sdev->dev, "%s: DAI config failed for widget '%s'\n", __func__, + w->name); + } - return sof_widget_free(sdev, swidget); + return 0; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) @@ -163,69 +117,34 @@ static int sdw_clock_stop_quirks = SDW_INTEL_CLK_STOP_BUS_RESET; module_param(sdw_clock_stop_quirks, int, 0444); MODULE_PARM_DESC(sdw_clock_stop_quirks, "SOF SoundWire clock stop quirks"); -static int sdw_dai_config_ipc(struct snd_sof_dev *sdev, - struct snd_soc_dapm_widget *w, - int link_id, int alh_stream_id, int dai_id, bool setup) -{ - struct snd_sof_widget *swidget = w->dobj.private; - struct sof_dai_private_data *private; - struct sof_ipc_dai_config *config; - struct snd_sof_dai *sof_dai; - - if (!swidget) { - dev_err(sdev->dev, "error: No private data for widget %s\n", w->name); - return -EINVAL; - } - - sof_dai = swidget->private; - - if (!sof_dai || !sof_dai->private) { - dev_err(sdev->dev, "%s: No private data for DAI %s\n", __func__, w->name); - return -EINVAL; - } - - private = sof_dai->private; - if (!private->dai_config) { - dev_err(sdev->dev, "%s: No config for DAI %s\n", __func__, w->name); - return -EINVAL; - } - - config = &private->dai_config[sof_dai->current_config]; - - /* update config with link and stream ID */ - config->dai_index = (link_id << 8) | dai_id; - config->alh.stream_id = alh_stream_id; - - if (setup) - return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE); - - return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE); -} - static int sdw_params_stream(struct device *dev, struct sdw_intel_stream_params_data *params_data) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_soc_dai *d = params_data->dai; + struct snd_sof_dai_config_data data; struct snd_soc_dapm_widget *w; w = snd_soc_dai_get_widget(d, params_data->stream); + data.dai_index = (params_data->link_id << 8) | d->id; + data.dai_data = params_data->alh_stream_id; - return sdw_dai_config_ipc(sdev, w, params_data->link_id, params_data->alh_stream_id, - d->id, true); + return hda_ctrl_dai_widget_setup(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); } static int sdw_free_stream(struct device *dev, struct sdw_intel_stream_free_data *free_data) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); struct snd_soc_dai *d = free_data->dai; + struct snd_sof_dai_config_data data; struct snd_soc_dapm_widget *w; w = snd_soc_dai_get_widget(d, free_data->stream); + data.dai_index = (free_data->link_id << 8) | d->id; /* send invalid stream_id */ - return sdw_dai_config_ipc(sdev, w, free_data->link_id, 0xFFFF, d->id, false); + data.dai_data = 0xFFFF; + + return hda_ctrl_dai_widget_free(w, SOF_DAI_CONFIG_FLAGS_NONE, &data); } static const struct sdw_intel_ops sdw_callback = { diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 13b509c9f481..05e5e158614a 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -17,6 +17,7 @@ #include #include #include "../sof-client-probes.h" +#include "../sof-audio.h" #include "shim.h" /* PCI registers */ @@ -730,8 +731,10 @@ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) struct snd_sof_dai; struct sof_ipc_dai_config; -int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags); -int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags); +int hda_ctrl_dai_widget_setup(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, + struct snd_sof_dai_config_data *data); +int hda_ctrl_dai_widget_free(struct snd_soc_dapm_widget *w, unsigned int quirk_flags, + struct snd_sof_dai_config_data *data); #define SOF_HDA_POSITION_QUIRK_USE_SKYLAKE_LEGACY (0) /* previous implementation */ #define SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS (1) /* recommended if VC0 only */ diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index fe1d5a56080a..8d08ffb37008 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -1909,6 +1909,153 @@ static int sof_ipc3_complete_pipeline(struct snd_sof_dev *sdev, struct snd_sof_w return 1; } +static int sof_ipc3_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) +{ + struct sof_ipc_free ipc_free = { + .hdr = { + .size = sizeof(ipc_free), + .cmd = SOF_IPC_GLB_TPLG_MSG, + }, + .id = swidget->comp_id, + }; + struct sof_ipc_reply reply; + int ret; + + if (!swidget->private) + return 0; + + switch (swidget->id) { + case snd_soc_dapm_scheduler: + { + ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE; + break; + } + case snd_soc_dapm_buffer: + ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE; + break; + default: + ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE; + break; + } + + ret = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), + &reply, sizeof(reply)); + if (ret < 0) + dev_err(sdev->dev, "failed to free widget %s\n", swidget->widget->name); + + return ret; +} + +static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, + unsigned int flags, struct snd_sof_dai_config_data *data) +{ + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; + struct snd_sof_dai *dai = swidget->private; + struct sof_dai_private_data *private; + struct sof_ipc_dai_config *config; + struct sof_ipc_reply reply; + int ret = 0; + + if (!dai || !dai->private) { + dev_err(sdev->dev, "No private data for DAI %s\n", swidget->widget->name); + return -EINVAL; + } + + private = dai->private; + if (!private->dai_config) { + dev_err(sdev->dev, "No config for DAI %s\n", dai->name); + return -EINVAL; + } + + config = &private->dai_config[dai->current_config]; + if (!config) { + dev_err(sdev->dev, "Invalid current config for DAI %s\n", dai->name); + return -EINVAL; + } + + switch (config->type) { + case SOF_DAI_INTEL_SSP: + /* + * DAI_CONFIG IPC during hw_params/hw_free for SSP DAI's is not supported in older + * firmware + */ + if (v->abi_version < SOF_ABI_VER(3, 18, 0) && + ((flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) || + (flags & SOF_DAI_CONFIG_FLAGS_HW_FREE))) + return 0; + break; + case SOF_DAI_INTEL_HDA: + if (data) + config->hda.link_dma_ch = data->dai_data; + break; + case SOF_DAI_INTEL_ALH: + if (data) { + config->dai_index = data->dai_index; + config->alh.stream_id = data->dai_data; + } + break; + default: + break; + } + + config->flags = flags; + + /* only send the IPC if the widget is set up in the DSP */ + if (swidget->use_count > 0) { + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, + &reply, sizeof(reply)); + if (ret < 0) + dev_err(sdev->dev, "Failed to set dai config for %s\n", dai->name); + } + + return ret; +} + +static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) +{ + struct sof_ipc_comp_reply reply; + int ret; + + if (!swidget->private) + return 0; + + switch (swidget->id) { + case snd_soc_dapm_dai_in: + case snd_soc_dapm_dai_out: + { + struct snd_sof_dai *dai = swidget->private; + struct sof_dai_private_data *dai_data = dai->private; + struct sof_ipc_comp *comp = &dai_data->comp_dai->comp; + + ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai, + comp->hdr.size, &reply, sizeof(reply)); + break; + } + case snd_soc_dapm_scheduler: + { + struct sof_ipc_pipe_new *pipeline; + + pipeline = swidget->private; + ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, + sizeof(*pipeline), &reply, sizeof(reply)); + break; + } + default: + { + struct sof_ipc_cmd_hdr *hdr; + + hdr = swidget->private; + ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, swidget->private, hdr->size, + &reply, sizeof(reply)); + break; + } + } + if (ret < 0) + dev_err(sdev->dev, "Failed to setup widget %s\n", swidget->widget->name); + + return ret; +} + /* token list for each topology object */ static enum sof_tokens host_token_list[] = { SOF_CORE_TOKENS, @@ -2012,6 +2159,9 @@ static const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .control_free = sof_ipc3_control_free, .pipeline_complete = sof_ipc3_complete_pipeline, .token_list = ipc3_token_list, + .widget_free = sof_ipc3_widget_free, + .widget_setup = sof_ipc3_widget_setup, + .dai_config = sof_ipc3_dai_config, }; const struct sof_ipc_ops ipc3_ops = { diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index cc0d647a2d0d..7aa4ac313de3 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -27,31 +27,6 @@ static int sof_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_control * return ret; } -static int sof_dai_config_setup(struct snd_sof_dev *sdev, struct snd_sof_dai *dai) -{ - struct sof_dai_private_data *private = dai->private; - struct sof_ipc_dai_config *config; - struct sof_ipc_reply reply; - int ret; - - config = &private->dai_config[dai->current_config]; - if (!config) { - dev_err(sdev->dev, "error: no config for DAI %s\n", dai->name); - return -EINVAL; - } - - /* set NONE flag to clear all previous settings */ - config->flags = SOF_DAI_CONFIG_FLAGS_NONE; - - ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, config->hdr.size, - &reply, sizeof(reply)); - - if (ret < 0) - dev_err(sdev->dev, "error: failed to set dai config for %s\n", dai->name); - - return ret; -} - static int sof_widget_kcontrol_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { struct snd_sof_control *scontrol; @@ -96,15 +71,9 @@ static void sof_reset_route_setup_status(struct snd_sof_dev *sdev, struct snd_so int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - struct sof_ipc_free ipc_free = { - .hdr = { - .size = sizeof(ipc_free), - .cmd = SOF_IPC_GLB_TPLG_MSG, - }, - .id = swidget->comp_id, - }; - struct sof_ipc_reply reply; - int ret, err; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + int err = 0; + int ret; if (!swidget->private) return 0; @@ -113,33 +82,9 @@ int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (--swidget->use_count) return 0; - switch (swidget->id) { - case snd_soc_dapm_scheduler: - { - ipc_free.hdr.cmd |= SOF_IPC_TPLG_PIPE_FREE; - break; - } - case snd_soc_dapm_buffer: - ipc_free.hdr.cmd |= SOF_IPC_TPLG_BUFFER_FREE; - break; - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - { - struct snd_sof_dai *dai = swidget->private; - - dai->configured = false; - fallthrough; - } - default: - ipc_free.hdr.cmd |= SOF_IPC_TPLG_COMP_FREE; - break; - } - /* continue to disable core even if IPC fails */ - err = sof_ipc_tx_message(sdev->ipc, ipc_free.hdr.cmd, &ipc_free, sizeof(ipc_free), - &reply, sizeof(reply)); - if (err < 0) - dev_err(sdev->dev, "error: failed to free widget %s\n", swidget->widget->name); + if (tplg_ops->widget_free) + err = tplg_ops->widget_free(sdev, swidget); /* * disable widget core. continue to route setup status and complete flag @@ -176,11 +121,7 @@ EXPORT_SYMBOL(sof_widget_free); int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) { - struct sof_ipc_pipe_new *pipeline; - struct sof_ipc_comp_reply r; - struct sof_ipc_cmd_hdr *hdr; - struct sof_ipc_comp *comp; - struct snd_sof_dai *dai; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; int ret; /* skip if there is no private data */ @@ -219,53 +160,22 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) goto pipe_widget_free; } - switch (swidget->id) { - case snd_soc_dapm_dai_in: - case snd_soc_dapm_dai_out: - { - struct sof_dai_private_data *dai_data; - - dai = swidget->private; - dai_data = dai->private; - comp = &dai_data->comp_dai->comp; - dai->configured = false; - - ret = sof_ipc_tx_message(sdev->ipc, comp->hdr.cmd, dai_data->comp_dai, - comp->hdr.size, &r, sizeof(r)); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to load widget %s\n", - swidget->widget->name); + /* setup widget in the DSP */ + if (tplg_ops->widget_setup) { + ret = tplg_ops->widget_setup(sdev, swidget); + if (ret < 0) goto core_put; - } + } - ret = sof_dai_config_setup(sdev, dai); - if (ret < 0) { - dev_err(sdev->dev, "error: failed to load dai config for DAI %s\n", - swidget->widget->name); + /* send config for DAI components */ + if (WIDGET_IS_DAI(swidget->id)) { + unsigned int flags = SOF_DAI_CONFIG_FLAGS_NONE; - /* - * widget use_count and core ref_count will both be decremented by - * sof_widget_free() - */ - sof_widget_free(sdev, swidget); - return ret; + if (tplg_ops->dai_config) { + ret = tplg_ops->dai_config(sdev, swidget, flags, NULL); + if (ret < 0) + goto widget_free; } - break; - } - case snd_soc_dapm_scheduler: - pipeline = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, pipeline->hdr.cmd, pipeline, - sizeof(*pipeline), &r, sizeof(r)); - break; - default: - hdr = swidget->private; - ret = sof_ipc_tx_message(sdev->ipc, hdr->cmd, swidget->private, hdr->size, - &r, sizeof(r)); - break; - } - if (ret < 0) { - dev_err(sdev->dev, "error: failed to load widget %s\n", swidget->widget->name); - goto core_put; } /* restore kcontrols for widget */ @@ -273,18 +183,16 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) if (ret < 0) { dev_err(sdev->dev, "error: failed to restore kcontrols for widget %s\n", swidget->widget->name); - /* - * widget use_count and core ref_count will both be decremented by - * sof_widget_free() - */ - sof_widget_free(sdev, swidget); - return ret; + goto widget_free; } dev_dbg(sdev->dev, "widget %s setup complete\n", swidget->widget->name); return 0; +widget_free: + /* widget use_count and core ref_count will both be decremented by sof_widget_free() */ + sof_widget_free(sdev, swidget); core_put: snd_sof_dsp_core_put(sdev, swidget->core); pipe_widget_free: diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 622d43707b27..19386184d8f3 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -40,6 +40,11 @@ struct snd_sof_widget; struct snd_sof_route; struct snd_sof_control; +struct snd_sof_dai_config_data { + int dai_index; + int dai_data; /* contains DAI-specific information */ +}; + /** * struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets * @ipc_setup: Function pointer for setting up widget IPC params @@ -69,6 +74,9 @@ struct sof_ipc_tplg_widget_ops { * @control_setup: Function pointer for setting up kcontrol IPC-specific data * @control_free: Function pointer for freeing kcontrol IPC-specific data * @pipeline_complete: Function pointer for pipeline complete IPC + * @widget_setup: Function pointer for setting up setup in the DSP + * @widget_free: Function pointer for freeing widget in the DSP + * @dai_config: Function pointer for sending DAI config IPC to the DSP */ struct sof_ipc_tplg_ops { const struct sof_ipc_tplg_widget_ops *widget; @@ -77,6 +85,10 @@ struct sof_ipc_tplg_ops { int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); int (*control_free)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); int (*pipeline_complete)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + int (*widget_setup)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); + int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, + unsigned int flags, struct snd_sof_dai_config_data *data); }; /** struct snd_sof_tuple - Tuple info @@ -276,7 +288,6 @@ struct snd_sof_dai { int number_configs; int current_config; - bool configured; /* DAI configured during BE hw_params */ struct list_head list; /* list in sdev dai list */ void *private; }; From patchwork Thu Mar 17 17:50:28 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784402 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 5D72FC433F5 for ; Thu, 17 Mar 2022 17:53:46 +0000 (UTC) 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 5E74C189F; Thu, 17 Mar 2022 18:52:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5E74C189F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539624; bh=iA84qKSwThV4/LPQbLW0cH6iio1/WonLJ719lT3zsf4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=fRsYKpn88Fju0CWW8Pc1v09kuWd+hTSX/UIoKpESa8Qqxfbwhf8AWx1pUv5FZ0eVo zLJbKZHKZIN3Zrf7+UqKWWmZo5iIvwhMz1SIuoYoxsOX0zwr3Oy5VuUq2bi8eo8Kt3 ezMhHLv65DDnRiI/OqTRFDHTmUj9hBDzf+jiZ1Z8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 2078EF80524; Thu, 17 Mar 2022 18:51:58 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C89CAF80524; Thu, 17 Mar 2022 18:51:54 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id C2F24F8023A for ; Thu, 17 Mar 2022 18:51:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz C2F24F8023A Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="DaGsNf7R" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539507; x=1679075507; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=iA84qKSwThV4/LPQbLW0cH6iio1/WonLJ719lT3zsf4=; b=DaGsNf7R84wx05CSes6PjOVo4mTfU+tZL7sZNEKUfmx9hOFDPcPzOnN1 VuxJG7WeMv7bXzw/RmOcmWJKgS+x6+uqrFO59dvF985gG5ktsQDoX5gki Umuy0Ghv65y9ngLnhHcQ+q+wQb8+cEBJd8+Y83FwUpo3SL5NZvReIznpU 36vDfBEEg3EcS6Qc6MAxREzxCX3RD2MQbziUN5ftEGp+0BcjSLj88Dhuj ttm2cK8Aj6KnkC+33J3H0Co563SSCGf/SFl8GsnsW5RykVTUBiHUDMhiD Yn3dTMlMBD5qrvHvGAcPoPL+0uxMO97mkWlByxHxW7Op5Je1Glxel5bWT A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492900" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492900" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431113" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 03/19] ASoC: SOF: Make sof_suspend/resume IPC agnostic Date: Thu, 17 Mar 2022 10:50:28 -0700 Message-Id: <20220317175044.1752400-4-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Add a new set of IPC ops for PM with the ctx_save and ctx_restore ops for suspend/resume and implement the ops for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/ipc.c | 1 + sound/soc/sof/ipc3-ops.h | 19 +++++++++++ sound/soc/sof/ipc3-topology.c | 7 ++-- sound/soc/sof/ipc3.c | 44 ++++++++++++++++++++++++ sound/soc/sof/pm.c | 63 ++++++++++++++--------------------- sound/soc/sof/sof-priv.h | 14 ++++++-- 7 files changed, 104 insertions(+), 46 deletions(-) create mode 100644 sound/soc/sof/ipc3-ops.h create mode 100644 sound/soc/sof/ipc3.c diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index e13dab59764c..59482903a243 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,7 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\ - ipc3-topology.o + ipc3-topology.o ipc3.o ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),) snd-sof-objs += sof-client.o endif diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 19a294cbbb8d..46a989be9a82 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -17,6 +17,7 @@ #include "sof-priv.h" #include "sof-audio.h" #include "ops.h" +#include "ipc3-ops.h" typedef void (*ipc_rx_callback)(struct snd_sof_dev *sdev, void *msg_buf); diff --git a/sound/soc/sof/ipc3-ops.h b/sound/soc/sof/ipc3-ops.h new file mode 100644 index 000000000000..5d8cab92c1a4 --- /dev/null +++ b/sound/soc/sof/ipc3-ops.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2021 Intel Corporation. All rights reserved. + * + * Author: Ranjani Sridharan + */ + +#ifndef __SOUND_SOC_SOF_IPC3_OPS_H +#define __SOUND_SOC_SOF_IPC3_OPS_H + +#include "sof-priv.h" + +extern const struct sof_ipc_tplg_ops ipc3_tplg_ops; +extern const struct sof_ipc_ops ipc3_ops; + +#endif diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 8d08ffb37008..bf0cf38f4524 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -11,6 +11,7 @@ #include #include "sof-priv.h" #include "sof-audio.h" +#include "ipc3-ops.h" #include "ops.h" /* Full volume for default values */ @@ -2152,7 +2153,7 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY sof_ipc3_widget_bind_event}, }; -static const struct sof_ipc_tplg_ops ipc3_tplg_ops = { +const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .widget = tplg_ipc3_widget_ops, .route_setup = sof_ipc3_route_setup, .control_setup = sof_ipc3_control_setup, @@ -2163,7 +2164,3 @@ static const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .widget_setup = sof_ipc3_widget_setup, .dai_config = sof_ipc3_dai_config, }; - -const struct sof_ipc_ops ipc3_ops = { - .tplg = &ipc3_tplg_ops, -}; diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c new file mode 100644 index 000000000000..e71cf30908c6 --- /dev/null +++ b/sound/soc/sof/ipc3.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// + +#include "sof-priv.h" +#include "ipc3-ops.h" + +static int sof_ipc3_ctx_ipc(struct snd_sof_dev *sdev, int cmd) +{ + struct sof_ipc_pm_ctx pm_ctx = { + .hdr.size = sizeof(pm_ctx), + .hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd, + }; + struct sof_ipc_reply reply; + + /* send ctx save ipc to dsp */ + return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx, + sizeof(pm_ctx), &reply, sizeof(reply)); +} + +static int sof_ipc3_ctx_save(struct snd_sof_dev *sdev) +{ + return sof_ipc3_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE); +} + +static int sof_ipc3_ctx_restore(struct snd_sof_dev *sdev) +{ + return sof_ipc3_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE); +} + +static const struct sof_ipc_pm_ops ipc3_pm_ops = { + .ctx_save = sof_ipc3_ctx_save, + .ctx_restore = sof_ipc3_ctx_restore, +}; + +const struct sof_ipc_ops ipc3_ops = { + .tplg = &ipc3_tplg_ops, + .pm = &ipc3_pm_ops, +}; diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 7300ecadabd9..10adbbd0a9cd 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -48,22 +48,6 @@ static u32 snd_sof_dsp_power_target(struct snd_sof_dev *sdev) return target_dsp_state; } -static int sof_send_pm_ctx_ipc(struct snd_sof_dev *sdev, int cmd) -{ - struct sof_ipc_pm_ctx pm_ctx; - struct sof_ipc_reply reply; - - memset(&pm_ctx, 0, sizeof(pm_ctx)); - - /* configure ctx save ipc message */ - pm_ctx.hdr.size = sizeof(pm_ctx); - pm_ctx.hdr.cmd = SOF_IPC_GLB_PM_MSG | cmd; - - /* send ctx save ipc to dsp */ - return sof_ipc_tx_message(sdev->ipc, pm_ctx.hdr.cmd, &pm_ctx, - sizeof(pm_ctx), &reply, sizeof(reply)); -} - #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_ENABLE_DEBUGFS_CACHE) static void sof_cache_debugfs(struct snd_sof_dev *sdev) { @@ -86,6 +70,7 @@ static void sof_cache_debugfs(struct snd_sof_dev *sdev) static int sof_resume(struct device *dev, bool runtime_resume) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); + const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; u32 old_state = sdev->dsp_power_state.state; int ret; @@ -171,11 +156,11 @@ static int sof_resume(struct device *dev, bool runtime_resume) sof_resume_clients(sdev); /* notify DSP of system resume */ - ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_RESTORE); - if (ret < 0) - dev_err(sdev->dev, - "error: ctx_restore ipc error during resume %d\n", - ret); + if (pm_ops && pm_ops->ctx_restore) { + ret = pm_ops->ctx_restore(sdev); + if (ret < 0) + dev_err(sdev->dev, "ctx_restore IPC error during resume: %d\n", ret); + } return ret; } @@ -183,6 +168,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) static int sof_suspend(struct device *dev, bool runtime_suspend) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); + const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; pm_message_t pm_state; u32 target_state = 0; int ret; @@ -232,21 +218,20 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) sof_cache_debugfs(sdev); #endif /* notify DSP of upcoming power down */ - ret = sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE); - if (ret == -EBUSY || ret == -EAGAIN) { - /* - * runtime PM has logic to handle -EBUSY/-EAGAIN so - * pass these errors up - */ - dev_err(sdev->dev, - "error: ctx_save ipc error during suspend %d\n", - ret); - return ret; - } else if (ret < 0) { - /* FW in unexpected state, continue to power down */ - dev_warn(sdev->dev, - "ctx_save ipc error %d, proceeding with suspend\n", - ret); + if (pm_ops && pm_ops->ctx_save) { + ret = pm_ops->ctx_save(sdev); + if (ret == -EBUSY || ret == -EAGAIN) { + /* + * runtime PM has logic to handle -EBUSY/-EAGAIN so + * pass these errors up + */ + dev_err(sdev->dev, "ctx_save IPC error during suspend: %d\n", ret); + return ret; + } else if (ret < 0) { + /* FW in unexpected state, continue to power down */ + dev_warn(sdev->dev, "ctx_save IPC error: %d, proceeding with suspend\n", + ret); + } } suspend: @@ -278,9 +263,11 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) int snd_sof_dsp_power_down_notify(struct snd_sof_dev *sdev) { + const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; + /* Notify DSP of upcoming power down */ - if (sof_ops(sdev)->remove) - return sof_send_pm_ctx_ipc(sdev, SOF_IPC_PM_CTX_SAVE); + if (sof_ops(sdev)->remove && pm_ops && pm_ops->ctx_save) + return pm_ops->ctx_save(sdev); return 0; } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 0b89c3e6ef21..3e883044dd0f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -360,18 +360,28 @@ struct snd_sof_ipc_msg { bool ipc_complete; }; +/** + * struct sof_ipc_pm_ops - IPC-specific PM ops + * @ctx_save: Function pointer for context save + * @ctx_restore: Function pointer for context restore + */ +struct sof_ipc_pm_ops { + int (*ctx_save)(struct snd_sof_dev *sdev); + int (*ctx_restore)(struct snd_sof_dev *sdev); +}; + struct sof_ipc_tplg_ops; /** * struct sof_ipc_ops - IPC-specific ops * @tplg: Pointer to IPC-specific topology ops + * @pm: Pointer to PM ops */ struct sof_ipc_ops { const struct sof_ipc_tplg_ops *tplg; + const struct sof_ipc_pm_ops *pm; }; -extern const struct sof_ipc_ops ipc3_ops; - /* SOF generic IPC data */ struct snd_sof_ipc { struct snd_sof_dev *sdev; From patchwork Thu Mar 17 17:50:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784400 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 0B310C433F5 for ; Thu, 17 Mar 2022 17:53:12 +0000 (UTC) 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 48D1918CF; Thu, 17 Mar 2022 18:52:20 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 48D1918CF DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539590; bh=Tptf8VyQob+r1azRJ8hK+4qcr+k5LUpR31+UaaqCeag=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=MtjhekSiQUPyJGXJ5/1iOzsqF7gHpnogg2C3kvOjmm1HvWnjqlWsVMnSO+Vv6bLW5 cUbDYCg8G7j7hsl/hbK8cJnrAobPtgtm1xIJuWHuCzg0zlJYeuMJJq9bvyqqdqCFJa BKjRfpxSHBfpvfAgVPbFMRxrPZ8m1lSs1SL41Jyw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B718EF80515; Thu, 17 Mar 2022 18:51:51 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1DBE3F80132; Thu, 17 Mar 2022 18:51:50 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6C71FF80159 for ; Thu, 17 Mar 2022 18:51:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6C71FF80159 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jm5vjAL4" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539506; x=1679075506; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Tptf8VyQob+r1azRJ8hK+4qcr+k5LUpR31+UaaqCeag=; b=jm5vjAL4zLDoDRDqCmBYScn26QbqvfyuBZw6z/QGh8V2XC8ONI6zSSFW yeFqtNPFG24r7rmydQl3W6S8KQ5bf/TiCEws7rm7sSuHs5D6vKMX9m5De AhNUs9hIOi52y5ueX6gZdXfw2sfsgPaPfrXJy3X+zietaz/i28VywSb2L 2AUHuNfWfXOOMwHY43qipxl+pP+GOdx2/j2Rt5yeWI3XiDrstccy786p7 PGAIHHfaLMfelFOE4hi8EhuLgoydcsVps6WfNJq6/1kkydYb9YAQiv7ug 1nX2OZAtv7cKutK6jBW58dQjm+/dnfj6GGKyuMxMO034wIgAjhLYe+wam g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492903" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492903" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431116" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:21 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 04/19] ASoC: SOF: Introduce IPC ops for kcontrol IO Date: Thu, 17 Mar 2022 10:50:29 -0700 Message-Id: <20220317175044.1752400-5-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Introduce IPC-specific ops for kcontrol IO in struct ipc_tplg_ops. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/sof-audio.h | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 19386184d8f3..d241dd84e708 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -45,6 +45,28 @@ struct snd_sof_dai_config_data { int dai_data; /* contains DAI-specific information */ }; +/** + * struct ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO + */ +struct ipc_tplg_control_ops { + bool (*volume_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*volume_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + bool (*switch_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*switch_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + bool (*enum_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*enum_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*bytes_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*bytes_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); + int (*bytes_ext_get)(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size); + int (*bytes_ext_volatile_get)(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size); + int (*bytes_ext_put)(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size); + /* update control data based on notification from the DSP */ + void (*update)(struct snd_sof_dev *sdev, void *ipc_control_message); +}; + /** * struct sof_ipc_tplg_widget_ops - IPC-specific ops for topology widgets * @ipc_setup: Function pointer for setting up widget IPC params @@ -67,6 +89,7 @@ struct sof_ipc_tplg_widget_ops { * @widget: Array of pointers to IPC-specific ops for widgets. This should always be of size * SND_SOF_DAPM_TYPE_COUNT i.e one per widget type. Unsupported widget types will be * initialized to 0. + * @control: Pointer to the IPC-specific ops for topology kcontrol IO * @route_setup: Function pointer for setting up pipeline connections * @token_list: List of all tokens supported by the IPC version. The size of the token_list * array should be SOF_TOKEN_COUNT. The unused elements in the array will be @@ -80,6 +103,7 @@ struct sof_ipc_tplg_widget_ops { */ struct sof_ipc_tplg_ops { const struct sof_ipc_tplg_widget_ops *widget; + const struct ipc_tplg_control_ops *control; int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); const struct sof_token_info *token_list; int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); From patchwork Thu Mar 17 17:50:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784407 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id F3035C433EF for ; Thu, 17 Mar 2022 17:54:19 +0000 (UTC) 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 446B317B2; Thu, 17 Mar 2022 18:53:28 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 446B317B2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539658; bh=9unt2N52EbKS2HF2tphkjJLDhjfQqpdmrEjnrjDszUo=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=GL6W4ixftSzwUDwmlYw9bPAd23o/lvTnbOVZRathZX1suRdsxrkV7FZycT1PCF1sk 2Ommnv5YuARJxNJqWCOqEb+/jkoot6Qs/KwVkQ1Tmr/c8J+C/cp7bFfSZmDQTwMqTH GUVYqCavydUuGrY+fXvFrKmTgbEC8Teo+bQljM5Y= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 49008F80535; Thu, 17 Mar 2022 18:52:00 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1B466F802DF; Thu, 17 Mar 2022 18:51:56 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 73E5EF80124 for ; Thu, 17 Mar 2022 18:51:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 73E5EF80124 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AVRrgyAa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539508; x=1679075508; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=9unt2N52EbKS2HF2tphkjJLDhjfQqpdmrEjnrjDszUo=; b=AVRrgyAa4DuVN8v8mum76T8lEI+QIv2zp01Klt1awB03SKzuB6yCuaaN K2ObjSCZ53tfSH3xHAg0UCuX+TK384XSa88ybePqwnniK072u18CY28XD rbAmsyUGKPBjVA5NqJci3pGM7W/+l6MC1UKwtOQPV6ax6cwoTJxYdgrf5 XnN4L3rwmoTw5qv7oMsMPL7zM1Zjpo0gCY90ni4OtANom+GvH592yIeX3 oedLet96MV6k5epO1o1dfqKbT3d/IfSsFnrhVPDGLezzmApR8EQP4Dx24 T2EGT9Xinj4PKsptmjQSfu8aYCu4okiSOrmSn21HB8dqGtinECLKLwFIS A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492905" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492905" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431122" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 05/19] ASoC: SOF: Add IPC3 topology control ops Date: Thu, 17 Mar 2022 10:50:30 -0700 Message-Id: <20220317175044.1752400-6-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Define the topology control IPC ops for IPC3, implement the control_notify op and use it. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/control.c | 144 ------------------------------- sound/soc/sof/ipc.c | 6 +- sound/soc/sof/ipc3-control.c | 156 ++++++++++++++++++++++++++++++++++ sound/soc/sof/ipc3-ops.h | 1 + sound/soc/sof/ipc3-topology.c | 1 + sound/soc/sof/sof-audio.h | 6 +- 7 files changed, 166 insertions(+), 150 deletions(-) create mode 100644 sound/soc/sof/ipc3-control.c diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index 59482903a243..f6d68a3096d9 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,7 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\ - ipc3-topology.o ipc3.o + ipc3-topology.o ipc3.o ipc3-control.o ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),) snd-sof-objs += sof-client.o endif diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 21ee0545945d..fb2311d880d3 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -526,147 +526,3 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, return 0; } - -static void snd_sof_update_control(struct snd_sof_control *scontrol, - struct sof_ipc_ctrl_data *cdata) -{ - struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *local_cdata; - int i; - - local_cdata = scontrol->ipc_control_data; - - if (cdata->cmd == SOF_CTRL_CMD_BINARY) { - if (cdata->num_elems != local_cdata->data->size) { - dev_err(scomp->dev, - "error: cdata binary size mismatch %u - %u\n", - cdata->num_elems, local_cdata->data->size); - return; - } - - /* copy the new binary data */ - memcpy(local_cdata->data, cdata->data, cdata->num_elems); - } else if (cdata->num_elems != scontrol->num_channels) { - dev_err(scomp->dev, - "error: cdata channel count mismatch %u - %d\n", - cdata->num_elems, scontrol->num_channels); - } else { - /* copy the new values */ - for (i = 0; i < cdata->num_elems; i++) - local_cdata->chanv[i].value = cdata->chanv[i].value; - } -} - -void snd_sof_control_notify(struct snd_sof_dev *sdev, - struct sof_ipc_ctrl_data *cdata) -{ - struct snd_soc_dapm_widget *widget; - struct snd_sof_control *scontrol; - struct snd_sof_widget *swidget; - struct snd_kcontrol *kc = NULL; - struct soc_mixer_control *sm; - struct soc_bytes_ext *be; - size_t expected_size; - struct soc_enum *se; - bool found = false; - int i, type; - - if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET || - cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) { - dev_err(sdev->dev, - "Component data is not supported in control notification\n"); - return; - } - - /* Find the swidget first */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (swidget->comp_id == cdata->comp_id) { - found = true; - break; - } - } - - if (!found) - return; - - /* Translate SOF cmd to TPLG type */ - switch (cdata->cmd) { - case SOF_CTRL_CMD_VOLUME: - case SOF_CTRL_CMD_SWITCH: - type = SND_SOC_TPLG_TYPE_MIXER; - break; - case SOF_CTRL_CMD_BINARY: - type = SND_SOC_TPLG_TYPE_BYTES; - break; - case SOF_CTRL_CMD_ENUM: - type = SND_SOC_TPLG_TYPE_ENUM; - break; - default: - dev_err(sdev->dev, "error: unknown cmd %u\n", cdata->cmd); - return; - } - - widget = swidget->widget; - for (i = 0; i < widget->num_kcontrols; i++) { - /* skip non matching types or non matching indexes within type */ - if (widget->dobj.widget.kcontrol_type[i] == type && - widget->kcontrol_news[i].index == cdata->index) { - kc = widget->kcontrols[i]; - break; - } - } - - if (!kc) - return; - - switch (cdata->cmd) { - case SOF_CTRL_CMD_VOLUME: - case SOF_CTRL_CMD_SWITCH: - sm = (struct soc_mixer_control *)kc->private_value; - scontrol = sm->dobj.private; - break; - case SOF_CTRL_CMD_BINARY: - be = (struct soc_bytes_ext *)kc->private_value; - scontrol = be->dobj.private; - break; - case SOF_CTRL_CMD_ENUM: - se = (struct soc_enum *)kc->private_value; - scontrol = se->dobj.private; - break; - default: - return; - } - - expected_size = sizeof(struct sof_ipc_ctrl_data); - switch (cdata->type) { - case SOF_CTRL_TYPE_VALUE_CHAN_GET: - case SOF_CTRL_TYPE_VALUE_CHAN_SET: - expected_size += cdata->num_elems * - sizeof(struct sof_ipc_ctrl_value_chan); - break; - case SOF_CTRL_TYPE_DATA_GET: - case SOF_CTRL_TYPE_DATA_SET: - expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); - break; - default: - return; - } - - if (cdata->rhdr.hdr.size != expected_size) { - dev_err(sdev->dev, "error: component notification size mismatch\n"); - return; - } - - if (cdata->num_elems) - /* - * The message includes the updated value/data, update the - * control's local cache using the received notification - */ - snd_sof_update_control(scontrol, cdata); - else - /* Mark the scontrol that the value/data is changed in SOF */ - scontrol->comp_data_dirty = true; - - snd_ctl_notify_one(swidget->scomp->card->snd_card, - SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); -} diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index 46a989be9a82..af0ae137842b 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -470,6 +470,7 @@ EXPORT_SYMBOL(snd_sof_ipc_reply); static void ipc_comp_notification(struct snd_sof_dev *sdev, void *msg_buf) { + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; struct sof_ipc_cmd_hdr *hdr = msg_buf; u32 msg_type = hdr->cmd & SOF_CMD_TYPE_MASK; @@ -482,7 +483,8 @@ static void ipc_comp_notification(struct snd_sof_dev *sdev, void *msg_buf) return; } - snd_sof_control_notify(sdev, msg_buf); + if (tplg_ops->control->update) + tplg_ops->control->update(sdev, msg_buf); } /* DSP firmware has sent host a message */ @@ -1031,7 +1033,7 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev) ipc->ops = &ipc3_ops; /* check for mandatory ops */ - if (!ipc->ops->tplg || !ipc->ops->tplg->widget) { + if (!ipc->ops->tplg || !ipc->ops->tplg->widget || !ipc->ops->tplg->control) { dev_err(sdev->dev, "Invalid topology IPC ops\n"); return NULL; } diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c new file mode 100644 index 000000000000..d4086e805c18 --- /dev/null +++ b/sound/soc/sof/ipc3-control.c @@ -0,0 +1,156 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// + +#include "sof-priv.h" +#include "sof-audio.h" +#include "ipc3-ops.h" + +static void snd_sof_update_control(struct snd_sof_control *scontrol, + struct sof_ipc_ctrl_data *cdata) +{ + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_ipc_ctrl_data *local_cdata; + int i; + + local_cdata = scontrol->ipc_control_data; + + if (cdata->cmd == SOF_CTRL_CMD_BINARY) { + if (cdata->num_elems != local_cdata->data->size) { + dev_err(scomp->dev, "cdata binary size mismatch %u - %u\n", + cdata->num_elems, local_cdata->data->size); + return; + } + + /* copy the new binary data */ + memcpy(local_cdata->data, cdata->data, cdata->num_elems); + } else if (cdata->num_elems != scontrol->num_channels) { + dev_err(scomp->dev, "cdata channel count mismatch %u - %d\n", + cdata->num_elems, scontrol->num_channels); + } else { + /* copy the new values */ + for (i = 0; i < cdata->num_elems; i++) + local_cdata->chanv[i].value = cdata->chanv[i].value; + } +} + +static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_message) +{ + struct sof_ipc_ctrl_data *cdata = ipc_control_message; + struct snd_soc_dapm_widget *widget; + struct snd_sof_control *scontrol; + struct snd_sof_widget *swidget; + struct snd_kcontrol *kc = NULL; + struct soc_mixer_control *sm; + struct soc_bytes_ext *be; + size_t expected_size; + struct soc_enum *se; + bool found = false; + int i, type; + + if (cdata->type == SOF_CTRL_TYPE_VALUE_COMP_GET || + cdata->type == SOF_CTRL_TYPE_VALUE_COMP_SET) { + dev_err(sdev->dev, "Component data is not supported in control notification\n"); + return; + } + + /* Find the swidget first */ + list_for_each_entry(swidget, &sdev->widget_list, list) { + if (swidget->comp_id == cdata->comp_id) { + found = true; + break; + } + } + + if (!found) + return; + + /* Translate SOF cmd to TPLG type */ + switch (cdata->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_SWITCH: + type = SND_SOC_TPLG_TYPE_MIXER; + break; + case SOF_CTRL_CMD_BINARY: + type = SND_SOC_TPLG_TYPE_BYTES; + break; + case SOF_CTRL_CMD_ENUM: + type = SND_SOC_TPLG_TYPE_ENUM; + break; + default: + dev_err(sdev->dev, "Unknown cmd %u in %s\n", cdata->cmd, __func__); + return; + } + + widget = swidget->widget; + for (i = 0; i < widget->num_kcontrols; i++) { + /* skip non matching types or non matching indexes within type */ + if (widget->dobj.widget.kcontrol_type[i] == type && + widget->kcontrol_news[i].index == cdata->index) { + kc = widget->kcontrols[i]; + break; + } + } + + if (!kc) + return; + + switch (cdata->cmd) { + case SOF_CTRL_CMD_VOLUME: + case SOF_CTRL_CMD_SWITCH: + sm = (struct soc_mixer_control *)kc->private_value; + scontrol = sm->dobj.private; + break; + case SOF_CTRL_CMD_BINARY: + be = (struct soc_bytes_ext *)kc->private_value; + scontrol = be->dobj.private; + break; + case SOF_CTRL_CMD_ENUM: + se = (struct soc_enum *)kc->private_value; + scontrol = se->dobj.private; + break; + default: + return; + } + + expected_size = sizeof(struct sof_ipc_ctrl_data); + switch (cdata->type) { + case SOF_CTRL_TYPE_VALUE_CHAN_GET: + case SOF_CTRL_TYPE_VALUE_CHAN_SET: + expected_size += cdata->num_elems * + sizeof(struct sof_ipc_ctrl_value_chan); + break; + case SOF_CTRL_TYPE_DATA_GET: + case SOF_CTRL_TYPE_DATA_SET: + expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr); + break; + default: + return; + } + + if (cdata->rhdr.hdr.size != expected_size) { + dev_err(sdev->dev, "Component notification size mismatch\n"); + return; + } + + if (cdata->num_elems) + /* + * The message includes the updated value/data, update the + * control's local cache using the received notification + */ + snd_sof_update_control(scontrol, cdata); + else + /* Mark the scontrol that the value/data is changed in SOF */ + scontrol->comp_data_dirty = true; + + snd_ctl_notify_one(swidget->scomp->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, kc, 0); +} + +const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { + .update = sof_ipc3_control_update, +}; diff --git a/sound/soc/sof/ipc3-ops.h b/sound/soc/sof/ipc3-ops.h index 5d8cab92c1a4..f3d6010d0b77 100644 --- a/sound/soc/sof/ipc3-ops.h +++ b/sound/soc/sof/ipc3-ops.h @@ -15,5 +15,6 @@ extern const struct sof_ipc_tplg_ops ipc3_tplg_ops; extern const struct sof_ipc_ops ipc3_ops; +extern const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops; #endif diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index bf0cf38f4524..55be97ee816b 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2155,6 +2155,7 @@ static const struct sof_ipc_tplg_widget_ops tplg_ipc3_widget_ops[SND_SOC_DAPM_TY const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .widget = tplg_ipc3_widget_ops, + .control = &tplg_ipc3_control_ops, .route_setup = sof_ipc3_route_setup, .control_setup = sof_ipc3_control_setup, .control_free = sof_ipc3_control_free, diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index d241dd84e708..bcd38c882078 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -46,9 +46,9 @@ struct snd_sof_dai_config_data { }; /** - * struct ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO + * struct sof_ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO */ -struct ipc_tplg_control_ops { +struct sof_ipc_tplg_control_ops { bool (*volume_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); int (*volume_get)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); bool (*switch_put)(struct snd_sof_control *scontrol, struct snd_ctl_elem_value *ucontrol); @@ -103,7 +103,7 @@ struct sof_ipc_tplg_widget_ops { */ struct sof_ipc_tplg_ops { const struct sof_ipc_tplg_widget_ops *widget; - const struct ipc_tplg_control_ops *control; + const struct sof_ipc_tplg_control_ops *control; int (*route_setup)(struct snd_sof_dev *sdev, struct snd_sof_route *sroute); const struct sof_token_info *token_list; int (*control_setup)(struct snd_sof_dev *sdev, struct snd_sof_control *scontrol); From patchwork Thu Mar 17 17:50:31 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784403 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 86864C433EF for ; Thu, 17 Mar 2022 17:54:02 +0000 (UTC) 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 CF9A018E2; Thu, 17 Mar 2022 18:53:10 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz CF9A018E2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539640; bh=fHsyIITrqRUCS4qFa0kVAZRjYFat2lFNdC2Uyn3h9IE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=tRqu2bMryvbjB/V6+4oHFmimJsQ2npxnfCmARsSnDPK551j3E4shuBx86JyxdrnVA yUhLX382ioRuuAMGQsco7qQIbt7lq+WT+3eHqn04gWHnPvO6XF51WGG1oBHSihek/0 A5SGDIaSEUL0JY/u01nmWfgvdr/sCPDwCxec1mLg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 77869F80529; Thu, 17 Mar 2022 18:51:59 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5431DF80526; Thu, 17 Mar 2022 18:51:55 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 1E49FF802DF for ; Thu, 17 Mar 2022 18:51:47 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 1E49FF802DF Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hFprFEBc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539509; x=1679075509; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=fHsyIITrqRUCS4qFa0kVAZRjYFat2lFNdC2Uyn3h9IE=; b=hFprFEBc76umj9i4PItQ684bfULWpj/lTKf7MHiK8EEKGPwoZPXWF9sb mV6AAYC38q5XZAyjmlTRvmXKAoP3BouoA7fbqnf5Rl+/KlE76oQm1yTvN MOa1+GKjOMJopAINEfM/8rM1cGeFH3dyTHlDyV8HGU0F9fbZ9+f//lqrC 4HaVuE5DlKqC80h0lwM5tc3F4uOd4ZZQPvnrpl5Hw1ZTKmO31x6tnzAfI 0CYMbjnkULv5bZUIK0AyNSpOe41ZXhGBySrH8wfK3yLGmbrVh5BiH2OTr MrcBaC3DmgpFXveK8jYOddvpl0pJFjVIyz0ZnuUQVQfX7utXCtE2l/FEB A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492908" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492908" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431125" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 06/19] ASoC: SOF: Add volume_get/put IPC3 ops Date: Thu, 17 Mar 2022 10:50:31 -0700 Message-Id: <20220317175044.1752400-7-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Define and set the volume_get/put control IPC ops for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/control.c | 64 +++++----------------- sound/soc/sof/ipc3-control.c | 100 +++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 50 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index fb2311d880d3..9eb54b7024b3 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -45,26 +45,6 @@ static void update_mute_led(struct snd_sof_control *scontrol, #endif } -static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) -{ - if (value >= size) - return volume_map[size - 1]; - - return volume_map[value]; -} - -static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size) -{ - int i; - - for (i = 0; i < size; i++) { - if (volume_map[i] >= value) - return i; - } - - return i - 1; -} - static void snd_sof_refresh_control(struct snd_sof_control *scontrol) { struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; @@ -85,7 +65,8 @@ static void snd_sof_refresh_control(struct snd_sof_control *scontrol) scontrol->comp_data_dirty = false; ret = snd_sof_ipc_set_get_comp_data(scontrol, false); if (ret < 0) { - dev_err(scomp->dev, "error: failed to get control data: %d\n", ret); + dev_err(scomp->dev, "Failed to get control data: %d\n", ret); + /* Set the flag to re-try next time to get the data */ scontrol->comp_data_dirty = true; } @@ -94,19 +75,14 @@ static void snd_sof_refresh_control(struct snd_sof_control *scontrol) int snd_sof_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - snd_sof_refresh_control(scontrol); - - /* read back each channel */ - for (i = 0; i < channels; i++) - ucontrol->value.integer.value[i] = - ipc_to_mixer(cdata->chanv[i].value, - scontrol->volume_table, sm->max + 1); + if (tplg_ops->control->volume_get) + return tplg_ops->control->volume_get(scontrol, ucontrol); return 0; } @@ -114,28 +90,16 @@ int snd_sof_volume_get(struct snd_kcontrol *kcontrol, int snd_sof_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - bool change = false; - u32 value; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* update each channel */ - for (i = 0; i < channels; i++) { - value = mixer_to_ipc(ucontrol->value.integer.value[i], - scontrol->volume_table, sm->max + 1); - change = change || (value != cdata->chanv[i].value); - cdata->chanv[i].channel = i; - cdata->chanv[i].value = value; - } + if (tplg_ops->control->volume_put) + return tplg_ops->control->volume_put(scontrol, ucontrol); - /* notify DSP of mixer updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); - return change; + return false; } int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index d4086e805c18..12aeb3ae4e52 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -11,6 +11,104 @@ #include "sof-audio.h" #include "ipc3-ops.h" +static inline u32 mixer_to_ipc(unsigned int value, u32 *volume_map, int size) +{ + if (value >= size) + return volume_map[size - 1]; + + return volume_map[value]; +} + +static inline u32 ipc_to_mixer(u32 value, u32 *volume_map, int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (volume_map[i] >= value) + return i; + } + + return i - 1; +} + +static void snd_sof_refresh_control(struct snd_sof_control *scontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + int ret; + + if (!scontrol->comp_data_dirty) + return; + + if (!pm_runtime_active(scomp->dev)) + return; + + /* set the ABI header values */ + cdata->data->magic = SOF_ABI_MAGIC; + cdata->data->abi = SOF_ABI_VERSION; + + /* refresh the component data from DSP */ + scontrol->comp_data_dirty = false; + ret = snd_sof_ipc_set_get_comp_data(scontrol, false); + if (ret < 0) { + dev_err(scomp->dev, "Failed to get control data: %d\n", ret); + + /* Set the flag to re-try next time to get the data */ + scontrol->comp_data_dirty = true; + } +} + +static int sof_ipc3_volume_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + unsigned int channels = scontrol->num_channels; + unsigned int i; + + snd_sof_refresh_control(scontrol); + + /* read back each channel */ + for (i = 0; i < channels; i++) + ucontrol->value.integer.value[i] = ipc_to_mixer(cdata->chanv[i].value, + scontrol->volume_table, + scontrol->max + 1); + + return 0; +} + +static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + unsigned int channels = scontrol->num_channels; + unsigned int i; + bool change = false; + + /* update each channel */ + for (i = 0; i < channels; i++) { + u32 value = mixer_to_ipc(ucontrol->value.integer.value[i], + scontrol->volume_table, scontrol->max + 1); + + change = change || (value != cdata->chanv[i].value); + cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; + } + + /* notify DSP of mixer updates */ + if (pm_runtime_active(scomp->dev)) { + int ret = snd_sof_ipc_set_get_comp_data(scontrol, true); + + if (ret < 0) { + dev_err(scomp->dev, "Failed to set mixer updates for %s\n", + scontrol->name); + return false; + } + } + + return change; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -152,5 +250,7 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_ } const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { + .volume_put = sof_ipc3_volume_put, + .volume_get = sof_ipc3_volume_get, .update = sof_ipc3_control_update, }; From patchwork Thu Mar 17 17:50:32 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784409 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id EB7B6C433EF for ; Thu, 17 Mar 2022 17:54:52 +0000 (UTC) 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 5073D190E; Thu, 17 Mar 2022 18:54:01 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 5073D190E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539691; bh=qrj+8coW8BvPuBpDzZ4ZnvZqtifeLF8E0+NNixmxoqE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=kbnlVCpUyjWidnZeSAx1USD+7u3v1mZ0D+MDFq9X0uap8zZ83nUrrD9XKJNcFGg7z P5HyeFUcEtF63jtyddoVS5r8fo2Jap9ZEwi7BX88V3NmpuZPYiwmoeqon5QH+Ms/3y 1hyTLIAo0YSxcdJA+YliKbASlu+sp8GS6a691l6I= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id C87A7F80520; Thu, 17 Mar 2022 18:52:11 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id CF9A6F80525; Thu, 17 Mar 2022 18:51:57 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 6D845F80159 for ; Thu, 17 Mar 2022 18:51:49 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 6D845F80159 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="B1ZcZQWa" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539510; x=1679075510; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qrj+8coW8BvPuBpDzZ4ZnvZqtifeLF8E0+NNixmxoqE=; b=B1ZcZQWaRibprhKfYI/9Gsv1LV8p6Zt5M6yu0JdCKjHVdxRE2nADx4eO 5An2P6aoWo622Ydgp7Lf4IHWoxfO6DwsT5nKJVT8D1l9Jrd3bLr6gb9y2 SwEuI6iiHY7eMCmJd2o8bYrBJtlUOKpX7D8A0GKpuAsI6Tsr5EYXFQ9XV ORtIB8OpNM+DZIGU31ipd5xp6fCQ7Rp9yaV6i2Sse5qVFBd/G6FUBax97 51tI5XtUoNgwE/ssJ3BdQo+O+QDf6nt6UWqV6R4t+bFoZAeFuKwgw32/n 3in5nsnlcxBOhw9947miJ7U3w6LgoWx/LQCKMatWX4MIa7hLxfIziF3MG g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492911" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492911" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431127" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 07/19] ASoC: SOF: Add switch get/put IPC3 ops Date: Thu, 17 Mar 2022 10:50:32 -0700 Message-Id: <20220317175044.1752400-8-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Add the switch_get/put control IPC ops for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/control.c | 39 +++++++++------------------- sound/soc/sof/ipc3-control.c | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 9eb54b7024b3..f9f8bd37b480 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -127,17 +127,14 @@ int snd_sof_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info int snd_sof_switch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - - snd_sof_refresh_control(scontrol); + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* read back each channel */ - for (i = 0; i < channels; i++) - ucontrol->value.integer.value[i] = cdata->chanv[i].value; + if (tplg_ops->control->switch_get) + return tplg_ops->control->switch_get(scontrol, ucontrol); return 0; } @@ -145,31 +142,19 @@ int snd_sof_switch_get(struct snd_kcontrol *kcontrol, int snd_sof_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_mixer_control *sm = - (struct soc_mixer_control *)kcontrol->private_value; + struct soc_mixer_control *sm = (struct soc_mixer_control *)kcontrol->private_value; struct snd_sof_control *scontrol = sm->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - bool change = false; - u32 value; - - /* update each channel */ - for (i = 0; i < channels; i++) { - value = ucontrol->value.integer.value[i]; - change = change || (value != cdata->chanv[i].value); - cdata->chanv[i].channel = i; - cdata->chanv[i].value = value; - } + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; if (scontrol->led_ctl.use_led) update_mute_led(scontrol, kcontrol, ucontrol); - /* notify DSP of mixer updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); + if (tplg_ops->control->switch_put) + return tplg_ops->control->switch_put(scontrol, ucontrol); - return change; + return false; } int snd_sof_enum_get(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 12aeb3ae4e52..ba9cde011b5a 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -109,6 +109,54 @@ static bool sof_ipc3_volume_put(struct snd_sof_control *scontrol, return change; } +static int sof_ipc3_switch_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + unsigned int channels = scontrol->num_channels; + unsigned int i; + + snd_sof_refresh_control(scontrol); + + /* read back each channel */ + for (i = 0; i < channels; i++) + ucontrol->value.integer.value[i] = cdata->chanv[i].value; + + return 0; +} + +static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + unsigned int channels = scontrol->num_channels; + unsigned int i; + bool change = false; + u32 value; + + /* update each channel */ + for (i = 0; i < channels; i++) { + value = ucontrol->value.integer.value[i]; + change = change || (value != cdata->chanv[i].value); + cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; + } + + /* notify DSP of mixer updates */ + if (pm_runtime_active(scomp->dev)) { + int ret = snd_sof_ipc_set_get_comp_data(scontrol, true); + + if (ret < 0) { + dev_err(scomp->dev, "Failed to set mixer updates for %s\n", + scontrol->name); + return false; + } + } + + return change; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -252,5 +300,7 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .volume_put = sof_ipc3_volume_put, .volume_get = sof_ipc3_volume_get, + .switch_put = sof_ipc3_switch_put, + .switch_get = sof_ipc3_switch_get, .update = sof_ipc3_control_update, }; From patchwork Thu Mar 17 17:50:33 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784408 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C85A1C433EF for ; Thu, 17 Mar 2022 17:54:36 +0000 (UTC) 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 E814B18BD; Thu, 17 Mar 2022 18:53:44 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz E814B18BD DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539675; bh=icr7OkwnHEwr801hagV2X9F7RXGHcVlRXX/SRsTK6Rc=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=bkUB0J/Y5NgeCT5wvfFuOgn/iZ8dpU1VMm9ZgOIoQxJX/SEFlYgeSlUsU9xpfHT3K cnORGRNqb9berauH/24zBHh9TmExI9gZQ5jIOciEkLLwDFQlWmyjd290GvaZE0Tw3I JffeUwXuh6jghaatG6tcyXfCgUdca+wTn3mm9CRg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 582BFF80519; Thu, 17 Mar 2022 18:52:10 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 653C0F80526; Thu, 17 Mar 2022 18:51:57 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 209A9F8020D for ; Thu, 17 Mar 2022 18:51:49 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 209A9F8020D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="UxG59dZc" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539511; x=1679075511; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=icr7OkwnHEwr801hagV2X9F7RXGHcVlRXX/SRsTK6Rc=; b=UxG59dZcrpivfAxkrXKU4Rpzw3Pd08Bc0TKpkRZkZx6i8w0GxTcAofgP OBN3Ts6D9osYBa1TICW3ueVknmEGVXGU/2EcCOfz+JZqZW2rEcpbplI4C uh1k+GCAj/awzzH03p3NzRT07IczvLyUb6eCZIj6Ycvhf9LRzavxDKdT9 7zYZeAj9EMhkjtJzLwgBmcsXDfARzEP678iBjo5GJK6452Lf8igmN7sDD 6uuZ9WkmniZe1I4GEjz5sSaB7QpoQBy7xkFKKkGx3KLpP29fx1+pQXiW6 b2FfBvYehysndSXtzbJk9Vbz0rGvOkF2VJlP1oZVRYg5R6LasKSWqS9tJ Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492913" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492913" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431129" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 08/19] ASoC: SOF: Add enum_get/put control ops for IPC3 Date: Thu, 17 Mar 2022 10:50:33 -0700 Message-Id: <20220317175044.1752400-9-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Define and set the enum_get/put control IPC ops for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/control.c | 39 +++++++++------------------- sound/soc/sof/ipc3-control.c | 50 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index f9f8bd37b480..499d426c5d38 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -160,17 +160,14 @@ int snd_sof_switch_put(struct snd_kcontrol *kcontrol, int snd_sof_enum_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_enum *se = - (struct soc_enum *)kcontrol->private_value; + struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; struct snd_sof_control *scontrol = se->dobj.private; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - - snd_sof_refresh_control(scontrol); + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* read back each channel */ - for (i = 0; i < channels; i++) - ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; + if (tplg_ops->control->enum_get) + return tplg_ops->control->enum_get(scontrol, ucontrol); return 0; } @@ -178,28 +175,16 @@ int snd_sof_enum_get(struct snd_kcontrol *kcontrol, int snd_sof_enum_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_enum *se = - (struct soc_enum *)kcontrol->private_value; + struct soc_enum *se = (struct soc_enum *)kcontrol->private_value; struct snd_sof_control *scontrol = se->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - unsigned int i, channels = scontrol->num_channels; - bool change = false; - u32 value; - - /* update each channel */ - for (i = 0; i < channels; i++) { - value = ucontrol->value.enumerated.item[i]; - change = change || (value != cdata->chanv[i].value); - cdata->chanv[i].channel = i; - cdata->chanv[i].value = value; - } + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* notify DSP of enum updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); + if (tplg_ops->control->enum_put) + return tplg_ops->control->enum_put(scontrol, ucontrol); - return change; + return false; } int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index ba9cde011b5a..03948f8f7eb0 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -157,6 +157,54 @@ static bool sof_ipc3_switch_put(struct snd_sof_control *scontrol, return change; } +static int sof_ipc3_enum_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + unsigned int channels = scontrol->num_channels; + unsigned int i; + + snd_sof_refresh_control(scontrol); + + /* read back each channel */ + for (i = 0; i < channels; i++) + ucontrol->value.enumerated.item[i] = cdata->chanv[i].value; + + return 0; +} + +static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + unsigned int channels = scontrol->num_channels; + unsigned int i; + bool change = false; + u32 value; + + /* update each channel */ + for (i = 0; i < channels; i++) { + value = ucontrol->value.enumerated.item[i]; + change = change || (value != cdata->chanv[i].value); + cdata->chanv[i].channel = i; + cdata->chanv[i].value = value; + } + + /* notify DSP of enum updates */ + if (pm_runtime_active(scomp->dev)) { + int ret = snd_sof_ipc_set_get_comp_data(scontrol, true); + + if (ret < 0) { + dev_err(scomp->dev, "Failed to set enum updates for %s\n", + scontrol->name); + return false; + } + } + + return change; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -302,5 +350,7 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .volume_get = sof_ipc3_volume_get, .switch_put = sof_ipc3_switch_put, .switch_get = sof_ipc3_switch_get, + .enum_put = sof_ipc3_enum_put, + .enum_get = sof_ipc3_enum_get, .update = sof_ipc3_control_update, }; From patchwork Thu Mar 17 17:50:34 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784410 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 83A81C433EF for ; Thu, 17 Mar 2022 17:55:10 +0000 (UTC) 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 B14A518E5; Thu, 17 Mar 2022 18:54:18 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B14A518E5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539708; bh=//31PYFIAylqF9BN8lgzTSi6M1KjhCNv4fekcap99XU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=kwAo71GQLZdDuDGhBp9M7XGqTvgFFn8Abv2JK8APHrhLnnvnS1BQJpQWS2As1MWMG QAarvgxEb1PCYSsGif81YzuvMGnP8o6B8zsYsYdSm88R+TlbrI64ZDw5G9BhnsegO7 YJoeqLD2LnbUaOCfyEivpCnTGQhArutJqOYMTBzE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 59A1DF8052E; Thu, 17 Mar 2022 18:52:12 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id C7284F80534; Thu, 17 Mar 2022 18:51:59 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 70ED7F80516 for ; Thu, 17 Mar 2022 18:51:51 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 70ED7F80516 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="S08ff3/+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539512; x=1679075512; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=//31PYFIAylqF9BN8lgzTSi6M1KjhCNv4fekcap99XU=; b=S08ff3/+JMxFJCYL3MvyTcm6AJpJHLlKwvdhkg5IwqJko59Mh+ShWzLS UpAI1NJyXWLZemNITtotC3hwGFTWFqYu9Znb3RRdPCiXy2ig+cYus9Xce 7vrGFnUuOVS9T2fMXaLVAg+9USyK3nI3uVdSZqeRWc/sliWgiE+An2w0f 490DeW0AhGzM1a2pQo+NxTWm8/vXUiOei7LrnEiSPUk8i4y/l7Iew9XwX E7Tja8m67Uy+cx6msPdTQGCEbNyF+QrmpQqHfoUOksBvSwTxt4RnLlQBv DfZoOHRi9MWcxohA5uGMIyIfVwiKm8jG5C1/pI60xRXtAKbwIoTSMnQ6m A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492916" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492916" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431134" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 09/19] ASoC: SOF: Add bytes_get/put control IPC ops for IPC3 Date: Thu, 17 Mar 2022 10:50:34 -0700 Message-Id: <20220317175044.1752400-10-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Define and set the bytes_get/put IPC control ops for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/control.c | 64 ++++++---------------------------- sound/soc/sof/ipc3-control.c | 67 ++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 54 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 499d426c5d38..2a4997e1cd1e 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -190,35 +190,14 @@ int snd_sof_enum_put(struct snd_kcontrol *kcontrol, int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *be = - (struct soc_bytes_ext *)kcontrol->private_value; + struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct sof_abi_hdr *data = cdata->data; - size_t size; - - snd_sof_refresh_control(scontrol); - - if (be->max > sizeof(ucontrol->value.bytes.data)) { - dev_err_ratelimited(scomp->dev, - "error: data max %d exceeds ucontrol data array size\n", - be->max); - return -EINVAL; - } - - /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (data->size > be->max - sizeof(*data)) { - dev_err_ratelimited(scomp->dev, - "error: %u bytes of control data is invalid, max is %zu\n", - data->size, be->max - sizeof(*data)); - return -EINVAL; - } - - size = data->size + sizeof(*data); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* copy back to kcontrol */ - memcpy(ucontrol->value.bytes.data, data, size); + if (tplg_ops->control->bytes_get) + return tplg_ops->control->bytes_get(scontrol, ucontrol); return 0; } @@ -226,37 +205,14 @@ int snd_sof_bytes_get(struct snd_kcontrol *kcontrol, int snd_sof_bytes_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct soc_bytes_ext *be = - (struct soc_bytes_ext *)kcontrol->private_value; + struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct sof_abi_hdr *data = cdata->data; - size_t size; - - if (be->max > sizeof(ucontrol->value.bytes.data)) { - dev_err_ratelimited(scomp->dev, - "error: data max %d exceeds ucontrol data array size\n", - be->max); - return -EINVAL; - } - - /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (data->size > be->max - sizeof(*data)) { - dev_err_ratelimited(scomp->dev, - "error: data size too big %u bytes max is %zu\n", - data->size, be->max - sizeof(*data)); - return -EINVAL; - } - - size = data->size + sizeof(*data); - - /* copy from kcontrol */ - memcpy(data, ucontrol->value.bytes.data, size); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - /* notify DSP of byte control updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); + if (tplg_ops->control->bytes_put) + return tplg_ops->control->bytes_put(scontrol, ucontrol); return 0; } diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index 03948f8f7eb0..df8e4df9663d 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -205,6 +205,71 @@ static bool sof_ipc3_enum_put(struct snd_sof_control *scontrol, return change; } +static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + size_t size; + + snd_sof_refresh_control(scontrol); + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, + "%u bytes of control data is invalid, max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy back to kcontrol */ + memcpy(ucontrol->value.bytes.data, data, size); + + return 0; +} + +static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct sof_abi_hdr *data = cdata->data; + size_t size; + + if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) { + dev_err_ratelimited(scomp->dev, "data max %zu exceeds ucontrol data array size\n", + scontrol->max_size); + return -EINVAL; + } + + /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */ + if (data->size > scontrol->max_size - sizeof(*data)) { + dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n", + data->size, scontrol->max_size - sizeof(*data)); + return -EINVAL; + } + + size = data->size + sizeof(*data); + + /* copy from kcontrol */ + memcpy(data, ucontrol->value.bytes.data, size); + + /* notify DSP of byte control updates */ + if (pm_runtime_active(scomp->dev)) + return snd_sof_ipc_set_get_comp_data(scontrol, true); + + return 0; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -352,5 +417,7 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .switch_get = sof_ipc3_switch_get, .enum_put = sof_ipc3_enum_put, .enum_get = sof_ipc3_enum_get, + .bytes_put = sof_ipc3_bytes_put, + .bytes_get = sof_ipc3_bytes_get, .update = sof_ipc3_control_update, }; From patchwork Thu Mar 17 17:50:35 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784414 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C062DC433EF for ; Thu, 17 Mar 2022 17:56:12 +0000 (UTC) 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 0C64617F1; Thu, 17 Mar 2022 18:55:21 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 0C64617F1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539771; bh=s54QIOYxLYpwYIrccYCban+d46ntW9dfhPYNkjuOt28=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=BygShfO/Fpq4qipndOHstSUIqVoI3fpuFCysmNtC/E6FPPiiuAnFm97yLZ/9Q3OSi FUKLuo7JQ5eifWttElLFBK4up2nd+C4C0D9XPSQTDOnkbyorgSJbdb3W2hl55M1hoR H2Le54R3uad2cX/LHFNCUOcCYFWLHlQK0skgaS8c= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id F3133F80551; Thu, 17 Mar 2022 18:52:14 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 2B752F8023A; Thu, 17 Mar 2022 18:52:06 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id DEC97F8023A for ; Thu, 17 Mar 2022 18:51:53 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz DEC97F8023A Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hSYyJpIU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539515; x=1679075515; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=s54QIOYxLYpwYIrccYCban+d46ntW9dfhPYNkjuOt28=; b=hSYyJpIUJ/sK2rGxsZkQ9kA/Qopt2MyP41rO3cCJ4tlKz+Ca+yOAUHPq G6XxmSwdzk+cBWFLOMMIWlG8kv+rEOH3Nm720fwA8SCpxbQBzA0pbhuWS BpKdmggGbsTe/NGB036d/kjB/MeiRDTy8KgrNCyjlEOyO/mIjdY1dyFsS g84iToAbcys/OpuS0J2tHyINQSyBOECN2J833/1GuODkcizLVNiLngNJy kCshb3RwAwMbEFQgGpKfHk95k7NG7o8W1EV1SFINEm+nQzukqCtdFfOPN Rs/U1tf3qzB3sMCN2zXIgVK2mkT3MlCaGif+l9DFGj/gNBDkvlN8mqAYX Q==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492918" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492918" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431139" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:22 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 10/19] ASoC: SOF: Add bytes_ext control IPC ops for IPC3 Date: Thu, 17 Mar 2022 10:50:35 -0700 Message-Id: <20220317175044.1752400-11-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Define and set the get/put/volatile_get control IPC ops for byte controls for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/control.c | 197 +++-------------------------------- sound/soc/sof/ipc3-control.c | 171 ++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 180 deletions(-) diff --git a/sound/soc/sof/control.c b/sound/soc/sof/control.c index 2a4997e1cd1e..de1778c4002b 100644 --- a/sound/soc/sof/control.c +++ b/sound/soc/sof/control.c @@ -45,33 +45,6 @@ static void update_mute_led(struct snd_sof_control *scontrol, #endif } -static void snd_sof_refresh_control(struct snd_sof_control *scontrol) -{ - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_soc_component *scomp = scontrol->scomp; - int ret; - - if (!scontrol->comp_data_dirty) - return; - - if (!pm_runtime_active(scomp->dev)) - return; - - /* set the ABI header values */ - cdata->data->magic = SOF_ABI_MAGIC; - cdata->data->abi = SOF_ABI_VERSION; - - /* refresh the component data from DSP */ - scontrol->comp_data_dirty = false; - ret = snd_sof_ipc_set_get_comp_data(scontrol, false); - if (ret < 0) { - dev_err(scomp->dev, "Failed to get control data: %d\n", ret); - - /* Set the flag to re-try next time to get the data */ - scontrol->comp_data_dirty = true; - } -} - int snd_sof_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -221,74 +194,18 @@ int snd_sof_bytes_ext_put(struct snd_kcontrol *kcontrol, const unsigned int __user *binary_data, unsigned int size) { - struct soc_bytes_ext *be = - (struct soc_bytes_ext *)kcontrol->private_value; + struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_ctl_tlv header; - const struct snd_ctl_tlv __user *tlvd = - (const struct snd_ctl_tlv __user *)binary_data; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; /* make sure we have at least a header */ if (size < sizeof(struct snd_ctl_tlv)) return -EINVAL; - /* - * The beginning of bytes data contains a header from where - * the length (as bytes) is needed to know the correct copy - * length of data from tlvd->tlv. - */ - if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) - return -EFAULT; - - /* make sure TLV info is consistent */ - if (header.length + sizeof(struct snd_ctl_tlv) > size) { - dev_err_ratelimited(scomp->dev, "error: inconsistent TLV, data %d + header %zu > %d\n", - header.length, sizeof(struct snd_ctl_tlv), size); - return -EINVAL; - } - - /* be->max is coming from topology */ - if (header.length > be->max) { - dev_err_ratelimited(scomp->dev, "error: Bytes data size %d exceeds max %d.\n", - header.length, be->max); - return -EINVAL; - } - - /* Check that header id matches the command */ - if (header.numid != cdata->cmd) { - dev_err_ratelimited(scomp->dev, - "error: incorrect numid %d\n", - header.numid); - return -EINVAL; - } - - if (copy_from_user(cdata->data, tlvd->tlv, header.length)) - return -EFAULT; - - if (cdata->data->magic != SOF_ABI_MAGIC) { - dev_err_ratelimited(scomp->dev, - "error: Wrong ABI magic 0x%08x.\n", - cdata->data->magic); - return -EINVAL; - } - - if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { - dev_err_ratelimited(scomp->dev, "error: Incompatible ABI version 0x%08x.\n", - cdata->data->abi); - return -EINVAL; - } - - /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ - if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "error: Mismatch in ABI data size (truncated?).\n"); - return -EINVAL; - } - - /* notify DSP of byte control updates */ - if (pm_runtime_active(scomp->dev)) - snd_sof_ipc_set_get_comp_data(scontrol, true); + if (tplg_ops->control->bytes_ext_put) + return tplg_ops->control->bytes_ext_put(scontrol, binary_data, size); return 0; } @@ -299,67 +216,24 @@ int snd_sof_bytes_ext_volatile_get(struct snd_kcontrol *kcontrol, unsigned int _ struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_ctl_tlv header; - struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; - size_t data_size; - int ret; - int err; - - /* - * Decrement the limit by ext bytes header size to - * ensure the user space buffer is not exceeded. - */ - if (size < sizeof(struct snd_ctl_tlv)) - return -ENOSPC; - size -= sizeof(struct snd_ctl_tlv); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; + int ret, err; ret = pm_runtime_get_sync(scomp->dev); if (ret < 0 && ret != -EACCES) { - dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to resume %d\n", ret); + dev_err_ratelimited(scomp->dev, "%s: failed to resume %d\n", __func__, ret); pm_runtime_put_noidle(scomp->dev); return ret; } - /* set the ABI header values */ - cdata->data->magic = SOF_ABI_MAGIC; - cdata->data->abi = SOF_ABI_VERSION; - /* get all the component data from DSP */ - ret = snd_sof_ipc_set_get_comp_data(scontrol, false); - if (ret < 0) - goto out; - - /* check data size doesn't exceed max coming from topology */ - if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n", - cdata->data->size, - be->max - sizeof(struct sof_abi_hdr)); - ret = -EINVAL; - goto out; - } - - data_size = cdata->data->size + sizeof(struct sof_abi_hdr); + if (tplg_ops->control->bytes_ext_volatile_get) + ret = tplg_ops->control->bytes_ext_volatile_get(scontrol, binary_data, size); - /* make sure we don't exceed size provided by user space for data */ - if (data_size > size) { - ret = -ENOSPC; - goto out; - } - - header.numid = cdata->cmd; - header.length = data_size; - if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) { - ret = -EFAULT; - goto out; - } - - if (copy_to_user(tlvd->tlv, cdata->data, data_size)) - ret = -EFAULT; -out: pm_runtime_mark_last_busy(scomp->dev); err = pm_runtime_put_autosuspend(scomp->dev); if (err < 0) - dev_err_ratelimited(scomp->dev, "error: bytes_ext get failed to idle %d\n", err); + dev_err_ratelimited(scomp->dev, "%s: failed to idle %d\n", __func__, err); return ret; } @@ -368,51 +242,14 @@ int snd_sof_bytes_ext_get(struct snd_kcontrol *kcontrol, unsigned int __user *binary_data, unsigned int size) { - struct soc_bytes_ext *be = - (struct soc_bytes_ext *)kcontrol->private_value; + struct soc_bytes_ext *be = (struct soc_bytes_ext *)kcontrol->private_value; struct snd_sof_control *scontrol = be->dobj.private; struct snd_soc_component *scomp = scontrol->scomp; - struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; - struct snd_ctl_tlv header; - struct snd_ctl_tlv __user *tlvd = - (struct snd_ctl_tlv __user *)binary_data; - size_t data_size; - - snd_sof_refresh_control(scontrol); - - /* - * Decrement the limit by ext bytes header size to - * ensure the user space buffer is not exceeded. - */ - if (size < sizeof(struct snd_ctl_tlv)) - return -ENOSPC; - size -= sizeof(struct snd_ctl_tlv); - - /* set the ABI header values */ - cdata->data->magic = SOF_ABI_MAGIC; - cdata->data->abi = SOF_ABI_VERSION; - - /* check data size doesn't exceed max coming from topology */ - if (cdata->data->size > be->max - sizeof(struct sof_abi_hdr)) { - dev_err_ratelimited(scomp->dev, "error: user data size %d exceeds max size %zu.\n", - cdata->data->size, - be->max - sizeof(struct sof_abi_hdr)); - return -EINVAL; - } - - data_size = cdata->data->size + sizeof(struct sof_abi_hdr); - - /* make sure we don't exceed size provided by user space for data */ - if (data_size > size) - return -ENOSPC; - - header.numid = cdata->cmd; - header.length = data_size; - if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) - return -EFAULT; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; - if (copy_to_user(tlvd->tlv, cdata->data, data_size)) - return -EFAULT; + if (tplg_ops->control->bytes_ext_get) + return tplg_ops->control->bytes_ext_get(scontrol, binary_data, size); return 0; } diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c index df8e4df9663d..cdd5ad860a94 100644 --- a/sound/soc/sof/ipc3-control.c +++ b/sound/soc/sof/ipc3-control.c @@ -270,6 +270,174 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol, return 0; } +static int sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, unsigned int size) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_ctl_tlv header; + size_t data_size; + + snd_sof_refresh_control(scontrol); + + /* + * Decrement the limit by ext bytes header size to + * ensure the user space buffer is not exceeded. + */ + if (size < sizeof(struct snd_ctl_tlv)) + return -ENOSPC; + + size -= sizeof(struct snd_ctl_tlv); + + /* set the ABI header values */ + cdata->data->magic = SOF_ABI_MAGIC; + cdata->data->abi = SOF_ABI_VERSION; + + /* check data size doesn't exceed max coming from topology */ + if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { + dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", + cdata->data->size, + scontrol->max_size - sizeof(struct sof_abi_hdr)); + return -EINVAL; + } + + data_size = cdata->data->size + sizeof(struct sof_abi_hdr); + + /* make sure we don't exceed size provided by user space for data */ + if (data_size > size) + return -ENOSPC; + + header.numid = cdata->cmd; + header.length = data_size; + if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + if (copy_to_user(tlvd->tlv, cdata->data, data_size)) + return -EFAULT; + + return 0; +} + +static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + const struct snd_ctl_tlv __user *tlvd = (const struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_ctl_tlv header; + + /* + * The beginning of bytes data contains a header from where + * the length (as bytes) is needed to know the correct copy + * length of data from tlvd->tlv. + */ + if (copy_from_user(&header, tlvd, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + /* make sure TLV info is consistent */ + if (header.length + sizeof(struct snd_ctl_tlv) > size) { + dev_err_ratelimited(scomp->dev, "Inconsistent TLV, data %d + header %zu > %d\n", + header.length, sizeof(struct snd_ctl_tlv), size); + return -EINVAL; + } + + /* be->max is coming from topology */ + if (header.length > scontrol->max_size) { + dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n", + header.length, scontrol->max_size); + return -EINVAL; + } + + /* Check that header id matches the command */ + if (header.numid != cdata->cmd) { + dev_err_ratelimited(scomp->dev, "Incorrect command for bytes put %d\n", + header.numid); + return -EINVAL; + } + + if (copy_from_user(cdata->data, tlvd->tlv, header.length)) + return -EFAULT; + + if (cdata->data->magic != SOF_ABI_MAGIC) { + dev_err_ratelimited(scomp->dev, "Wrong ABI magic 0x%08x\n", cdata->data->magic); + return -EINVAL; + } + + if (SOF_ABI_VERSION_INCOMPATIBLE(SOF_ABI_VERSION, cdata->data->abi)) { + dev_err_ratelimited(scomp->dev, "Incompatible ABI version 0x%08x\n", + cdata->data->abi); + return -EINVAL; + } + + /* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */ + if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { + dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n"); + return -EINVAL; + } + + /* notify DSP of byte control updates */ + if (pm_runtime_active(scomp->dev)) + return snd_sof_ipc_set_get_comp_data(scontrol, true); + + return 0; +} + +static int sof_ipc3_bytes_ext_volatile_get(struct snd_sof_control *scontrol, + const unsigned int __user *binary_data, + unsigned int size) +{ + struct snd_ctl_tlv __user *tlvd = (struct snd_ctl_tlv __user *)binary_data; + struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data; + struct snd_soc_component *scomp = scontrol->scomp; + struct snd_ctl_tlv header; + size_t data_size; + int ret; + + /* + * Decrement the limit by ext bytes header size to + * ensure the user space buffer is not exceeded. + */ + if (size < sizeof(struct snd_ctl_tlv)) + return -ENOSPC; + + size -= sizeof(struct snd_ctl_tlv); + + /* set the ABI header values */ + cdata->data->magic = SOF_ABI_MAGIC; + cdata->data->abi = SOF_ABI_VERSION; + + /* get all the component data from DSP */ + ret = snd_sof_ipc_set_get_comp_data(scontrol, false); + if (ret < 0) + return ret; + + /* check data size doesn't exceed max coming from topology */ + if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) { + dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n", + cdata->data->size, + scontrol->max_size - sizeof(struct sof_abi_hdr)); + return -EINVAL; + } + + data_size = cdata->data->size + sizeof(struct sof_abi_hdr); + + /* make sure we don't exceed size provided by user space for data */ + if (data_size > size) + return -ENOSPC; + + header.numid = cdata->cmd; + header.length = data_size; + if (copy_to_user(tlvd, &header, sizeof(struct snd_ctl_tlv))) + return -EFAULT; + + if (copy_to_user(tlvd->tlv, cdata->data, data_size)) + return -EFAULT; + + return ret; +} + static void snd_sof_update_control(struct snd_sof_control *scontrol, struct sof_ipc_ctrl_data *cdata) { @@ -419,5 +587,8 @@ const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops = { .enum_get = sof_ipc3_enum_get, .bytes_put = sof_ipc3_bytes_put, .bytes_get = sof_ipc3_bytes_get, + .bytes_ext_put = sof_ipc3_bytes_ext_put, + .bytes_ext_get = sof_ipc3_bytes_ext_get, + .bytes_ext_volatile_get = sof_ipc3_bytes_ext_volatile_get, .update = sof_ipc3_control_update, }; From patchwork Thu Mar 17 17:50:36 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784412 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 48E62C433EF for ; Thu, 17 Mar 2022 17:55:43 +0000 (UTC) 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 9559018FE; Thu, 17 Mar 2022 18:54:51 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 9559018FE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539741; bh=oh448Xd11lB3oMc5RnUnNqrLe+WesJgQE7IDz0X9HDk=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=HA7L8ulG7FtVNdAPDkYtkesJWng561MP4BxYvFBpat8lsPME9/7h4Vbs0Lrs79j7j Rv5KHcHZ6IP9uY4CsKaIEAVTG/LnrkpGLfpurDb0vlOXiU8xGKAo2OLLwbBh/D7vqS 2iGK/hkP56sKevscUuZJnBbYlGAgtc9UJfwC9OFc= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id B31C2F8053C; Thu, 17 Mar 2022 18:52:13 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 8E6FEF80537; Thu, 17 Mar 2022 18:52:01 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 95E88F8051F for ; Thu, 17 Mar 2022 18:51:53 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 95E88F8051F Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="e2OKFquU" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539514; x=1679075514; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=oh448Xd11lB3oMc5RnUnNqrLe+WesJgQE7IDz0X9HDk=; b=e2OKFquUAaWTgy/OwGLiHgHfb4biYHEdxeJ4Icw2M4mg2JhyHopU2tv3 sAmjIbW5UOusGuLxx9gSTRILQuFtmVV/Slj3thKfGDMAn6SM7LqGBRM8a PlYscSKksdRp9iR0we2t9QZ7q3IwDd9pxfDcRvDOBKwKC66CvnpcXDa7N oerR5UxZsdW60T/qCfDBMOUtlRHJEsjepmMp6AONqBE6aCbJ5/xgEfXAB QW8BmDKaeeZOSq1a0WHDYQTY8avrTIW76fZq1ZYpPVg9MoyR5UzRADEvO KJFyXX5Vy7FbwLp1uaV+YZl7t5rx9UP0CfLNb7yBtxihYSnhmhrWBqUEM w==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492921" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492921" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431142" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 11/19] ASoC: SOF: Introduce IPC-specific PCM ops Date: Thu, 17 Mar 2022 10:50:36 -0700 Message-Id: <20220317175044.1752400-12-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Introduce the IPC-specific PCM ops that will be used to abstract the PCM related IPC's. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/sof-audio.h | 17 +++++++++++++++++ sound/soc/sof/sof-priv.h | 3 +++ 2 files changed, 20 insertions(+) diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index bcd38c882078..4d25e781e5ae 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -45,6 +45,23 @@ struct snd_sof_dai_config_data { int dai_data; /* contains DAI-specific information */ }; +/** + * struct sof_ipc_pcm_ops - IPC-specific PCM ops + * @hw_params: Function pointer for hw_params + * @hw_free: Function pointer for hw_free + * @trigger: Function pointer for trigger + * @dai_link_fixup: Function pointer for DAI link fixup + */ +struct sof_ipc_pcm_ops { + int (*hw_params)(struct snd_soc_component *component, struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_sof_platform_stream_params *platform_params); + int (*hw_free)(struct snd_soc_component *component, struct snd_pcm_substream *substream); + int (*trigger)(struct snd_soc_component *component, struct snd_pcm_substream *substream, + int cmd); + int (*dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); +}; + /** * struct sof_ipc_tplg_control_ops - IPC-specific ops for topology kcontrol IO */ diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index 3e883044dd0f..0d9b640ae24c 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -371,15 +371,18 @@ struct sof_ipc_pm_ops { }; struct sof_ipc_tplg_ops; +struct sof_ipc_pcm_ops; /** * struct sof_ipc_ops - IPC-specific ops * @tplg: Pointer to IPC-specific topology ops * @pm: Pointer to PM ops + * @pcm: Pointer to PCM ops */ struct sof_ipc_ops { const struct sof_ipc_tplg_ops *tplg; const struct sof_ipc_pm_ops *pm; + const struct sof_ipc_pcm_ops *pcm; }; /* SOF generic IPC data */ From patchwork Thu Mar 17 17:50:37 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784411 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 434B3C433F5 for ; Thu, 17 Mar 2022 17:55:27 +0000 (UTC) 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 6CE8C18F4; Thu, 17 Mar 2022 18:54:35 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 6CE8C18F4 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539725; bh=HwwaPa4ACpnTuzFjP03Rd66VY8t8NuKVtfI4ogqbS/M=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=eIQOAKcNw+XepFALZKNZ5rj1eqR5pPIX2ibwHBHr6ND48UHObgRr+XhGHANcRNLLo KidS8nKFlC8+D95h0gUI34KRBWbBPIRdriSvCsYAU8aqblo93C4/BCjoHFHCdabis+ BCqhw4m9b6RObx81mAcezCjoSIZ3Stok6Yv2s7J8= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 0E765F8053A; Thu, 17 Mar 2022 18:52:13 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 28098F80538; Thu, 17 Mar 2022 18:52:01 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3B7B5F8051B for ; Thu, 17 Mar 2022 18:51:52 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3B7B5F8051B Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="bvKV79+/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539513; x=1679075513; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=HwwaPa4ACpnTuzFjP03Rd66VY8t8NuKVtfI4ogqbS/M=; b=bvKV79+/IV5QZgsmKUA4FfIKRdOu7oY+Hd/DbEEVPmNFVvPW9z1TJp5l 1GLvFw4YlpJ9NvdmYLi8pNPIz9m7jJylZJrLwIDUzYsKIKL5H4xep7qcG OnanxxHb2opT1TXWnuwC7FMsESabbW+i+Wjk9COD1hoYnBvd8UwnuXM3l qrnV42IFs49IO0IL60dlpuglKllqv/HSbS1P5vivA9QXZxY0xKdiU0JIs CuwVtORX4ZJd6BfJ4wo896Gkzku6jQBnmP5D86U8A9GDJE8eFsQdfuybe ZmFM0RzeFXMfuMTqQlhs0EQnDEKW1RwmJ4E9fm/TDZHKHyLuU2HtcWtzP g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492923" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492923" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431145" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 12/19] ASoC: SOF: pcm: expose the sof_pcm_setup_connected_widgets() function Date: Thu, 17 Mar 2022 10:50:37 -0700 Message-Id: <20220317175044.1752400-13-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" It will be used in IPC-specific code. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/pcm.c | 5 ++--- sound/soc/sof/sof-audio.h | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 1661b0bc6f12..47599b57ff19 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -105,9 +105,8 @@ int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev return ret; } -static int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, - struct snd_soc_pcm_runtime *rtd, - struct snd_sof_pcm *spcm, int dir) +int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd, + struct snd_sof_pcm *spcm, int dir) { struct snd_soc_dai *dai; int ret, j; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 4d25e781e5ae..3ec3f746663a 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -457,4 +457,6 @@ int get_token_uuid(void *elem, void *object, u32 offset); int sof_update_ipc_object(struct snd_soc_component *scomp, void *object, enum sof_tokens token_id, struct snd_sof_tuple *tuples, int num_tuples, size_t object_size, int token_instance_num); +int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd, + struct snd_sof_pcm *spcm, int dir); #endif From patchwork Thu Mar 17 17:50:38 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784415 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 73EB3C433F5 for ; Thu, 17 Mar 2022 17:56:29 +0000 (UTC) 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 B9B6E1916; Thu, 17 Mar 2022 18:55:37 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz B9B6E1916 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539787; bh=D0KQyFW4lhP5BunUzzzPjt5Nl0844B5kedzIzPoGh3w=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=vL8AhPMPTI5lL0/9kwQUw0rk6f7JtYrC1d0Yf/79gzTjmwwHWmKGxnkhnABBtNGe2 FVn9EgAz1xgBIsiNFIlY0y1c/8mBDwgRF862KN2T6DETEOCObeaC73IFAANiQowdBo G/oSVssloPwkDf22+NvzatIC4yU3qV1mE3Fl909I= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 86D00F80558; Thu, 17 Mar 2022 18:52:15 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 1E56DF80536; Thu, 17 Mar 2022 18:52:06 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 829B5F802DF for ; Thu, 17 Mar 2022 18:51:55 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 829B5F802DF Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="jDjlu5iS" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539516; x=1679075516; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=D0KQyFW4lhP5BunUzzzPjt5Nl0844B5kedzIzPoGh3w=; b=jDjlu5iSIM7wfk2soKupUAT4rnIGXSJi2ZZS+deRtsH0UjHcCVTVH9uZ nMZlDov6T6cuVmt0J8mg/+TC21C2qXQvB/6VrIXYINFY0rA9YMcBTpLzQ cNeP6Re27ymV68EoibT076v1hRTBhatZsZQIDVZAYZEXFQgI3k/wMtiot OWafPd+2gaRQdzWi+HrXJm/9RiFTo07/4Md1OlxEz5JBINLMYGXAIneol qDWY9HoeY04pVb4g/YPip4thrr5+S/JzX/EbGJ2JRabr6lRLdDNp79EgB TuTBkIbSYbUW4EjONLw8I3iZNJxr2Rd4gb5XEeeIz84x5aomZaWN83u4E A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492926" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492926" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431150" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 13/19] ASoC: SOF: Introduce IPC3 PCM hw_free op Date: Thu, 17 Mar 2022 10:50:38 -0700 Message-Id: <20220317175044.1752400-14-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart , broonie@kernel.org, Bard Liao 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" Add the IPC3 PCM ops, define the hw_free op and modify all users to use the op. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao --- sound/soc/sof/Makefile | 2 +- sound/soc/sof/ipc.c | 5 +++-- sound/soc/sof/ipc3-ops.h | 1 + sound/soc/sof/ipc3-pcm.c | 43 ++++++++++++++++++++++++++++++++++++++ sound/soc/sof/ipc3.c | 1 + sound/soc/sof/pcm.c | 44 +++++++++++++-------------------------- sound/soc/sof/sof-audio.c | 11 +++++++--- 7 files changed, 72 insertions(+), 35 deletions(-) create mode 100644 sound/soc/sof/ipc3-pcm.c diff --git a/sound/soc/sof/Makefile b/sound/soc/sof/Makefile index f6d68a3096d9..18acbc001b9a 100644 --- a/sound/soc/sof/Makefile +++ b/sound/soc/sof/Makefile @@ -2,7 +2,7 @@ snd-sof-objs := core.o ops.o loader.o ipc.o pcm.o pm.o debug.o topology.o\ control.o trace.o iomem-utils.o sof-audio.o stream-ipc.o\ - ipc3-topology.o ipc3.o ipc3-control.o + ipc3-topology.o ipc3.o ipc3-control.o ipc3-pcm.o ifneq ($(CONFIG_SND_SOC_SOF_CLIENT),) snd-sof-objs += sof-client.o endif diff --git a/sound/soc/sof/ipc.c b/sound/soc/sof/ipc.c index af0ae137842b..5f5753608c79 100644 --- a/sound/soc/sof/ipc.c +++ b/sound/soc/sof/ipc.c @@ -1033,8 +1033,9 @@ struct snd_sof_ipc *snd_sof_ipc_init(struct snd_sof_dev *sdev) ipc->ops = &ipc3_ops; /* check for mandatory ops */ - if (!ipc->ops->tplg || !ipc->ops->tplg->widget || !ipc->ops->tplg->control) { - dev_err(sdev->dev, "Invalid topology IPC ops\n"); + if (!ipc->ops->pcm || !ipc->ops->tplg || !ipc->ops->tplg->widget || + !ipc->ops->tplg->control) { + dev_err(sdev->dev, "Invalid IPC ops\n"); return NULL; } diff --git a/sound/soc/sof/ipc3-ops.h b/sound/soc/sof/ipc3-ops.h index f3d6010d0b77..a4784626a3d7 100644 --- a/sound/soc/sof/ipc3-ops.h +++ b/sound/soc/sof/ipc3-ops.h @@ -16,5 +16,6 @@ extern const struct sof_ipc_tplg_ops ipc3_tplg_ops; extern const struct sof_ipc_ops ipc3_ops; extern const struct sof_ipc_tplg_control_ops tplg_ipc3_control_ops; +extern const struct sof_ipc_pcm_ops ipc3_pcm_ops; #endif diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c new file mode 100644 index 000000000000..96f498b4b2d6 --- /dev/null +++ b/sound/soc/sof/ipc3-pcm.c @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) +// +// This file is provided under a dual BSD/GPLv2 license. When using or +// redistributing this file, you may do so under either license. +// +// Copyright(c) 2021 Intel Corporation. All rights reserved. +// +// + +#include +#include "ipc3-ops.h" +#include "ops.h" +#include "sof-priv.h" +#include "sof-audio.h" + +static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + struct snd_sof_pcm *spcm; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + if (!spcm->prepared[substream->stream]) + return 0; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; + stream.comp_id = spcm->stream[substream->stream].comp_id; + + /* send IPC to the DSP */ + return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, + sizeof(stream), &reply, sizeof(reply)); +} + +const struct sof_ipc_pcm_ops ipc3_pcm_ops = { + .hw_free = sof_ipc3_pcm_hw_free, +}; diff --git a/sound/soc/sof/ipc3.c b/sound/soc/sof/ipc3.c index e71cf30908c6..03e914b62728 100644 --- a/sound/soc/sof/ipc3.c +++ b/sound/soc/sof/ipc3.c @@ -41,4 +41,5 @@ static const struct sof_ipc_pm_ops ipc3_pm_ops = { const struct sof_ipc_ops ipc3_ops = { .tplg = &ipc3_tplg_ops, .pm = &ipc3_pm_ops, + .pcm = &ipc3_pcm_ops, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 47599b57ff19..8ef477aff938 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -82,29 +82,6 @@ void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream) } EXPORT_SYMBOL(snd_sof_pcm_period_elapsed); -int sof_pcm_dsp_pcm_free(struct snd_pcm_substream *substream, struct snd_sof_dev *sdev, - struct snd_sof_pcm *spcm) -{ - struct sof_ipc_stream stream; - struct sof_ipc_reply reply; - int ret; - - if (!spcm->prepared[substream->stream]) - return 0; - - stream.hdr.size = sizeof(stream); - stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_FREE; - stream.comp_id = spcm->stream[substream->stream].comp_id; - - /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, - sizeof(stream), &reply, sizeof(reply)); - if (!ret) - spcm->prepared[substream->stream] = false; - - return ret; -} - int sof_pcm_setup_connected_widgets(struct snd_sof_dev *sdev, struct snd_soc_pcm_runtime *rtd, struct snd_sof_pcm *spcm, int dir) { @@ -145,6 +122,7 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; struct snd_sof_platform_stream_params platform_params = { 0 }; struct sof_ipc_fw_version *v = &sdev->fw_ready.version; struct snd_sof_pcm *spcm; @@ -164,9 +142,13 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, * Handle repeated calls to hw_params() without free_pcm() in * between. At least ALSA OSS emulation depends on this. */ - ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); - if (ret < 0) - return ret; + if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + ret = pcm_ops->hw_free(component, substream); + if (ret < 0) + return ret; + + spcm->prepared[substream->stream] = false; + } dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); @@ -289,6 +271,7 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; struct snd_sof_pcm *spcm; int ret, err = 0; @@ -304,10 +287,13 @@ static int sof_pcm_hw_free(struct snd_soc_component *component, spcm->pcm.pcm_id, substream->stream); /* free PCM in the DSP */ - ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); - if (ret < 0) - err = ret; + if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + ret = pcm_ops->hw_free(component, substream); + if (ret < 0) + err = ret; + spcm->prepared[substream->stream] = false; + } /* stop DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 7aa4ac313de3..5088ec7019ed 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -591,12 +591,17 @@ int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify) int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_sof_pcm *spcm, int dir, bool free_widget_list) { + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; int ret; /* Send PCM_FREE IPC to reset pipeline */ - ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm); - if (ret < 0) - return ret; + if (pcm_ops->hw_free && spcm->prepared[substream->stream]) { + ret = pcm_ops->hw_free(sdev->component, substream); + if (ret < 0) + return ret; + } + + spcm->prepared[substream->stream] = false; /* stop the DMA */ ret = snd_sof_pcm_platform_hw_free(sdev, substream); From patchwork Thu Mar 17 17:50:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784417 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id C2C0EC433EF for ; Thu, 17 Mar 2022 17:57:08 +0000 (UTC) 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 065FB1A28; Thu, 17 Mar 2022 18:56:17 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 065FB1A28 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539827; bh=d7Jaj3et29s3ilvuz8zrQpLi6g1T1gU5riiWNKGfRQU=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=vWCwedEtXFbub/deDuva+KAcjNVKqH2aATyr33HIxpRMVTXuXsHQo7hNvaOaV9oLd vzOeX+rWj3wJER/3S4rI4379+BQZEyv/MPd5B9jL3lMVEUHGGLBLQxj1r9+rMX5yAN KyFFAsAwkVloaLoiq1jwRGMGZBKRVpGSXn+nV9oE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 140F5F80578; Thu, 17 Mar 2022 18:52:17 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 5977FF80519; Thu, 17 Mar 2022 18:52:07 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3F6D7F80520 for ; Thu, 17 Mar 2022 18:51:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3F6D7F80520 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="hBprmR+0" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539515; x=1679075515; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=d7Jaj3et29s3ilvuz8zrQpLi6g1T1gU5riiWNKGfRQU=; b=hBprmR+0A31Huny+enmjB0BW+pGI/CZjMMQZP12J41kzIMPI9mkvt3kZ Kuk7G+3MvBDEKsQq0NuXIV5PRt+4W/ZY2D8ZHFQnuw2OqWYL7Qvy74llN IW5cEfUY+ZSmPjTHEo+l4PoYq730nZCNOGlYc/wGeF+jNKt6G9x/7X8dC 8+dliJjNX/766UaAjLxk9LeBox2Q6K3y8VQ3Ofze2kIgCCMVa47DxIFz5 fMJPnwCeJCMdX9zCXeSbmLeBBzCFMwLA43oDpBgG4C/EXUqdBxZZFsEbV qcH8DErC9PcJ1KlWVCo17iy6J+oFuAi4XwBs+Q466DZ5LT3y/0JDpDzxI g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492928" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492928" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431153" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 14/19] ASoC: SOF: Define hw_params PCM op for IPC3 Date: Thu, 17 Mar 2022 10:50:39 -0700 Message-Id: <20220317175044.1752400-15-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Add the hw_params op for IPC3 and use it. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/ipc3-pcm.c | 100 +++++++++++++++++++++++++++++++++++ sound/soc/sof/pcm.c | 110 ++++++--------------------------------- 2 files changed, 115 insertions(+), 95 deletions(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index 96f498b4b2d6..b715199a2aaa 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -38,6 +38,106 @@ static int sof_ipc3_pcm_hw_free(struct snd_soc_component *component, sizeof(stream), &reply, sizeof(reply)); } +static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_sof_platform_stream_params *platform_params) +{ + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; + struct snd_pcm_runtime *runtime = substream->runtime; + struct sof_ipc_pcm_params_reply ipc_params_reply; + struct sof_ipc_pcm_params pcm; + struct snd_sof_pcm *spcm; + int ret; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + memset(&pcm, 0, sizeof(pcm)); + + /* number of pages should be rounded up */ + pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes); + + /* set IPC PCM parameters */ + pcm.hdr.size = sizeof(pcm); + pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; + pcm.comp_id = spcm->stream[substream->stream].comp_id; + pcm.params.hdr.size = sizeof(pcm.params); + pcm.params.buffer.phy_addr = spcm->stream[substream->stream].page_table.addr; + pcm.params.buffer.size = runtime->dma_bytes; + pcm.params.direction = substream->stream; + pcm.params.sample_valid_bytes = params_width(params) >> 3; + pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; + pcm.params.rate = params_rate(params); + pcm.params.channels = params_channels(params); + pcm.params.host_period_bytes = params_period_bytes(params); + + /* container size */ + ret = snd_pcm_format_physical_width(params_format(params)); + if (ret < 0) + return ret; + pcm.params.sample_container_bytes = ret >> 3; + + /* format */ + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16: + pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; + break; + case SNDRV_PCM_FORMAT_S24: + pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; + break; + case SNDRV_PCM_FORMAT_S32: + pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; + break; + case SNDRV_PCM_FORMAT_FLOAT: + pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT; + break; + default: + return -EINVAL; + } + + /* Update the IPC message with information from the platform */ + pcm.params.stream_tag = platform_params->stream_tag; + + if (platform_params->use_phy_address) + pcm.params.buffer.phy_addr = platform_params->phy_addr; + + if (platform_params->no_ipc_position) { + /* For older ABIs set host_period_bytes to zero to inform + * FW we don't want position updates. Newer versions use + * no_stream_position for this purpose. + */ + if (v->abi_version < SOF_ABI_VER(3, 10, 0)) + pcm.params.host_period_bytes = 0; + else + pcm.params.no_stream_position = 1; + } + + dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); + + /* send hw_params IPC to the DSP */ + ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), + &ipc_params_reply, sizeof(ipc_params_reply)); + if (ret < 0) { + dev_err(component->dev, "HW params ipc failed for stream %d\n", + pcm.params.stream_tag); + return ret; + } + + ret = snd_sof_set_stream_data_offset(sdev, substream, ipc_params_reply.posn_offset); + if (ret < 0) { + dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n", + __func__, spcm->pcm.pcm_id); + return ret; + } + + return ret; +} + const struct sof_ipc_pcm_ops ipc3_pcm_ops = { + .hw_params = sof_ipc3_pcm_hw_params, .hw_free = sof_ipc3_pcm_hw_free, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 8ef477aff938..8a194c130981 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -119,15 +119,12 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_platform_stream_params platform_params = { 0 }; - struct sof_ipc_fw_version *v = &sdev->fw_ready.version; + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_sof_pcm *spcm; - struct sof_ipc_pcm_params pcm; - struct sof_ipc_pcm_params_reply ipc_params_reply; int ret; /* nothing to do for BE */ @@ -153,117 +150,40 @@ static int sof_pcm_hw_params(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n", spcm->pcm.pcm_id, substream->stream); - memset(&pcm, 0, sizeof(pcm)); + /* if this is a repeated hw_params without hw_free, skip setting up widgets */ + if (!spcm->stream[substream->stream].list) { + ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream); + if (ret < 0) + return ret; + } /* create compressed page table for audio firmware */ if (runtime->buffer_changed) { ret = create_page_table(component, substream, runtime->dma_area, runtime->dma_bytes); + if (ret < 0) return ret; } - /* number of pages should be rounded up */ - pcm.params.buffer.pages = PFN_UP(runtime->dma_bytes); - - /* set IPC PCM parameters */ - pcm.hdr.size = sizeof(pcm); - pcm.hdr.cmd = SOF_IPC_GLB_STREAM_MSG | SOF_IPC_STREAM_PCM_PARAMS; - pcm.comp_id = spcm->stream[substream->stream].comp_id; - pcm.params.hdr.size = sizeof(pcm.params); - pcm.params.buffer.phy_addr = - spcm->stream[substream->stream].page_table.addr; - pcm.params.buffer.size = runtime->dma_bytes; - pcm.params.direction = substream->stream; - pcm.params.sample_valid_bytes = params_width(params) >> 3; - pcm.params.buffer_fmt = SOF_IPC_BUFFER_INTERLEAVED; - pcm.params.rate = params_rate(params); - pcm.params.channels = params_channels(params); - pcm.params.host_period_bytes = params_period_bytes(params); - - /* container size */ - ret = snd_pcm_format_physical_width(params_format(params)); - if (ret < 0) - return ret; - pcm.params.sample_container_bytes = ret >> 3; - - /* format */ - switch (params_format(params)) { - case SNDRV_PCM_FORMAT_S16: - pcm.params.frame_fmt = SOF_IPC_FRAME_S16_LE; - break; - case SNDRV_PCM_FORMAT_S24: - pcm.params.frame_fmt = SOF_IPC_FRAME_S24_4LE; - break; - case SNDRV_PCM_FORMAT_S32: - pcm.params.frame_fmt = SOF_IPC_FRAME_S32_LE; - break; - case SNDRV_PCM_FORMAT_FLOAT: - pcm.params.frame_fmt = SOF_IPC_FRAME_FLOAT; - break; - default: - return -EINVAL; - } - - /* firmware already configured host stream */ - ret = snd_sof_pcm_platform_hw_params(sdev, - substream, - params, - &platform_params); + ret = snd_sof_pcm_platform_hw_params(sdev, substream, params, &platform_params); if (ret < 0) { - dev_err(component->dev, "error: platform hw params failed\n"); + dev_err(component->dev, "platform hw params failed\n"); return ret; } - /* Update the IPC message with information from the platform */ - pcm.params.stream_tag = platform_params.stream_tag; - - if (platform_params.use_phy_address) - pcm.params.buffer.phy_addr = platform_params.phy_addr; - - if (platform_params.no_ipc_position) { - /* For older ABIs set host_period_bytes to zero to inform - * FW we don't want position updates. Newer versions use - * no_stream_position for this purpose. - */ - if (v->abi_version < SOF_ABI_VER(3, 10, 0)) - pcm.params.host_period_bytes = 0; - else - pcm.params.no_stream_position = 1; - } - - dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag); - - /* if this is a repeated hw_params without hw_free, skip setting up widgets */ - if (!spcm->stream[substream->stream].list) { - ret = sof_pcm_setup_connected_widgets(sdev, rtd, spcm, substream->stream); + if (pcm_ops->hw_params) { + ret = pcm_ops->hw_params(component, substream, params, &platform_params); if (ret < 0) return ret; } - /* send hw_params IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm), - &ipc_params_reply, sizeof(ipc_params_reply)); - if (ret < 0) { - dev_err(component->dev, "error: hw params ipc failed for stream %d\n", - pcm.params.stream_tag); - return ret; - } - - ret = snd_sof_set_stream_data_offset(sdev, substream, - ipc_params_reply.posn_offset); - if (ret < 0) { - dev_err(component->dev, "%s: invalid stream data offset for PCM %d\n", - __func__, spcm->pcm.pcm_id); - return ret; - } - spcm->prepared[substream->stream] = true; /* save pcm hw_params */ memcpy(&spcm->params[substream->stream], params, sizeof(*params)); - return ret; + return 0; } static int sof_pcm_hw_free(struct snd_soc_component *component, From patchwork Thu Mar 17 17:50:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784416 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id BB1AFC433EF for ; Thu, 17 Mar 2022 17:56:45 +0000 (UTC) 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 F306A190C; Thu, 17 Mar 2022 18:55:53 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz F306A190C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539804; bh=qWisgQRCiDNAtpHZOy5FO5/vMlRPNwTm17WeTY5QnTE=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=rk8rMEf1ZQ/B/EqG1b7pPWk/0Ubb70FjXnqoPqFB4l2Cwk2Kwke7y0u+SsTYaZiyW cqzi6YjO8asBNapgyKqe0K5e133T/9r/h8kTCvdc9jivESFVuCVcs4kpzDerlv3ldC 58mfPsMP2Kb3D/cGRx7+qIpSZ8WunRxbkXmg6ess= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 22C1DF8055A; Thu, 17 Mar 2022 18:52:16 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id D5B04F8051B; Thu, 17 Mar 2022 18:52:06 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id D82F3F8051D for ; Thu, 17 Mar 2022 18:51:55 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz D82F3F8051D Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="M1bewocM" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539517; x=1679075517; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=qWisgQRCiDNAtpHZOy5FO5/vMlRPNwTm17WeTY5QnTE=; b=M1bewocMzZT/3sYES8ThvnXpkyTUjttrrWQvvupV3AUpBmhVPNDSXBXH S+yK4vybwUBh66075b1wDCXmjEe9R+UwU18r8i5X2fyI47HdtvnpofGO6 nJOMIQB3llrO/5e0TIFU0HNmt5lHc+9yHPJYWrBmmYpDtk6RRTXny5sqy PuVdgk4m+bxyP87gU5aH91CoTG+hxzYkhZO0GSfKmx5rOUyqv7T3Bk8Fh Up5F2r0NRybiI6k0iERVTeqS/kjLb5JI58HSSyK6PUfNhY5fFEIklCkAn 6n/1g5CVkZUI0J+MzGoPkuuN0pAeUc876QENLS43HQT24JQkLWG5cjyQU A==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492931" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492931" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431155" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 15/19] ASoC: SOF: Add trigger PCM op for IPC3 Date: Thu, 17 Mar 2022 10:50:40 -0700 Message-Id: <20220317175044.1752400-16-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" Add the trigger PCM op for IPC3 and use it. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/ipc3-pcm.c | 43 ++++++++++++++++++++++++++++++++++++++++ sound/soc/sof/pcm.c | 23 ++++++--------------- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index b715199a2aaa..d83d54540bbe 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -137,7 +137,50 @@ static int sof_ipc3_pcm_hw_params(struct snd_soc_component *component, return ret; } +static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct sof_ipc_stream stream; + struct sof_ipc_reply reply; + struct snd_sof_pcm *spcm; + + spcm = snd_sof_find_spcm_dai(component, rtd); + if (!spcm) + return -EINVAL; + + stream.hdr.size = sizeof(stream); + stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG; + stream.comp_id = spcm->stream[substream->stream].comp_id; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; + break; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; + break; + case SNDRV_PCM_TRIGGER_START: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + fallthrough; + case SNDRV_PCM_TRIGGER_STOP: + stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; + break; + default: + dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); + return -EINVAL; + } + + /* send IPC to the DSP */ + return sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, + sizeof(stream), &reply, sizeof(reply)); +} + const struct sof_ipc_pcm_ops ipc3_pcm_ops = { .hw_params = sof_ipc3_pcm_hw_params, .hw_free = sof_ipc3_pcm_hw_free, + .trigger = sof_ipc3_pcm_trigger, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 8a194c130981..dc55a04a1588 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -274,13 +274,12 @@ static int sof_pcm_trigger(struct snd_soc_component *component, { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; struct snd_sof_pcm *spcm; - struct sof_ipc_stream stream; - struct sof_ipc_reply reply; bool reset_hw_params = false; bool free_widget_list = false; bool ipc_first = false; - int ret; + int ret = 0; /* nothing to do for BE */ if (rtd->dai_link->no_pcm) @@ -293,17 +292,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component, dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n", spcm->pcm.pcm_id, substream->stream, cmd); - stream.hdr.size = sizeof(stream); - stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG; - stream.comp_id = spcm->stream[substream->stream].comp_id; - switch (cmd) { case SNDRV_PCM_TRIGGER_PAUSE_PUSH: - stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_PAUSE; ipc_first = true; break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: - stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_RELEASE; break; case SNDRV_PCM_TRIGGER_START: if (spcm->stream[substream->stream].suspend_ignored) { @@ -315,7 +308,6 @@ static int sof_pcm_trigger(struct snd_soc_component *component, spcm->stream[substream->stream].suspend_ignored = false; return 0; } - stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_START; break; case SNDRV_PCM_TRIGGER_SUSPEND: if (sdev->system_suspend_target == SOF_SUSPEND_S0IX && @@ -332,13 +324,11 @@ static int sof_pcm_trigger(struct snd_soc_component *component, free_widget_list = true; fallthrough; case SNDRV_PCM_TRIGGER_STOP: - stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP; ipc_first = true; reset_hw_params = true; break; default: - dev_err(component->dev, "error: unhandled trigger cmd %d\n", - cmd); + dev_err(component->dev, "Unhandled trigger cmd %d\n", cmd); return -EINVAL; } @@ -349,11 +339,10 @@ static int sof_pcm_trigger(struct snd_soc_component *component, if (!ipc_first) snd_sof_pcm_platform_trigger(sdev, substream, cmd); - /* send IPC to the DSP */ - ret = sof_ipc_tx_message(sdev->ipc, stream.hdr.cmd, &stream, - sizeof(stream), &reply, sizeof(reply)); + if (pcm_ops->trigger) + ret = pcm_ops->trigger(component, substream, cmd); - /* need to STOP DMA even if STOP IPC failed */ + /* need to STOP DMA even if trigger IPC failed */ if (ipc_first) snd_sof_pcm_platform_trigger(sdev, substream, cmd); From patchwork Thu Mar 17 17:50:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784420 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id DC890C433EF for ; Thu, 17 Mar 2022 17:58:01 +0000 (UTC) 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 260E41AA5; Thu, 17 Mar 2022 18:57:10 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 260E41AA5 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539880; bh=3WhlAcg6vKx9GuYzLzKN0v8vT66/Uj5AKZpU2z/yvV4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=vOlMrc45d0bifPAKknoXIgXh9ONUN5eWiKcGbwUWskunGntzUaqeIVIlfUKyqCX+a pv/P+o3VyFTeGyw95Y33UjLBYtpkISqkTs5PPwU8N1AuxvW7F2Ezj1/Yvpgr1OjlEp uTY0IpYL5dhQvj6knQy9+cea605IE6yUeZFxVFlw= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 16EF2F805B6; Thu, 17 Mar 2022 18:52:23 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id CA798F8053B; Thu, 17 Mar 2022 18:52:12 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id B9FBDF80526 for ; Thu, 17 Mar 2022 18:51:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz B9FBDF80526 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Xuh6CRmw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539518; x=1679075518; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=3WhlAcg6vKx9GuYzLzKN0v8vT66/Uj5AKZpU2z/yvV4=; b=Xuh6CRmwDX0/+4V4M6W8r+Ppqn2Ve9bpsyHMOw68rNOOXuYMAq05zuO2 fxx+piFQfpXS1spK+FrGO2Uq7y7XvrSyTtDpMyoVRtHBnygQgQQlZBgxL c7NOH8X7duyCqiYt9cGgT3NlKqKfLOa9G+bnTHNYLgraUcDJdOgpQhYEc fdWSYCnAWzWpNYSdrPTQteyRM7HjB9fcChY92i/NSLDHobfzjCvly1Ky2 WEoPczwheDXLP36ukWL2keFQ1HD3k0DD37HdAflaexOHt0dWhkQ9jHz0I z7Wo+Q8vRSyBHsK9LIYfx+UDjugEtMxWRsh1pwspVFRCIslKQ0Bvh1Kte w==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492932" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492932" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431157" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 16/19] ASoC: SOF: Add dai_link_fixup PCM op for IPC3 Date: Thu, 17 Mar 2022 10:50:41 -0700 Message-Id: <20220317175044.1752400-17-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart , broonie@kernel.org, Bard Liao 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" Define the dai_link_fixup PCM op for IPC3 and use it Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao --- sound/soc/sof/ipc3-pcm.c | 186 +++++++++++++++++++++++++++++++++++++++ sound/soc/sof/pcm.c | 174 +----------------------------------- 2 files changed, 189 insertions(+), 171 deletions(-) diff --git a/sound/soc/sof/ipc3-pcm.c b/sound/soc/sof/ipc3-pcm.c index d83d54540bbe..58b75943cf6d 100644 --- a/sound/soc/sof/ipc3-pcm.c +++ b/sound/soc/sof/ipc3-pcm.c @@ -179,8 +179,194 @@ static int sof_ipc3_pcm_trigger(struct snd_soc_component *component, sizeof(stream), &reply, sizeof(reply)); } +static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, + struct snd_pcm_hw_params *params) +{ + struct sof_ipc_dai_config *config; + struct snd_sof_dai *dai; + int i; + + /* + * Search for all matching DAIs as we can have both playback and capture DAI + * associated with the same link. + */ + list_for_each_entry(dai, &sdev->dai_list, list) { + if (!dai->name || strcmp(link_name, dai->name)) + continue; + for (i = 0; i < dai->number_configs; i++) { + struct sof_dai_private_data *private = dai->private; + + config = &private->dai_config[i]; + if (config->ssp.fsync_rate == params_rate(params)) { + dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i); + dai->current_config = i; + break; + } + } + } +} + +static int sof_ipc3_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); + struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); + struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); + struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); + struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct sof_dai_private_data *private; + struct snd_soc_dpcm *dpcm; + + if (!dai) { + dev_err(component->dev, "%s: No DAI found with name %s\n", __func__, + rtd->dai_link->name); + return -EINVAL; + } + + private = dai->private; + if (!private) { + dev_err(component->dev, "%s: No private data found for DAI %s\n", __func__, + rtd->dai_link->name); + return -EINVAL; + } + + /* read format from topology */ + snd_mask_none(fmt); + + switch (private->comp_dai->config.frame_fmt) { + case SOF_IPC_FRAME_S16_LE: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); + break; + case SOF_IPC_FRAME_S24_4LE: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); + break; + case SOF_IPC_FRAME_S32_LE: + snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); + break; + default: + dev_err(component->dev, "No available DAI format!\n"); + return -EINVAL; + } + + /* read rate and channels from topology */ + switch (private->dai_config->type) { + case SOF_DAI_INTEL_SSP: + /* search for config to pcm params match, if not found use default */ + ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params); + + rate->min = private->dai_config[dai->current_config].ssp.fsync_rate; + rate->max = private->dai_config[dai->current_config].ssp.fsync_rate; + channels->min = private->dai_config[dai->current_config].ssp.tdm_slots; + channels->max = private->dai_config[dai->current_config].ssp.tdm_slots; + + dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + + break; + case SOF_DAI_INTEL_DMIC: + /* DMIC only supports 16 or 32 bit formats */ + if (private->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) { + dev_err(component->dev, "Invalid fmt %d for DAI type %d\n", + private->comp_dai->config.frame_fmt, + private->dai_config->type); + } + break; + case SOF_DAI_INTEL_HDA: + /* + * HDAudio does not follow the default trigger + * sequence due to firmware implementation + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { + struct snd_soc_pcm_runtime *fe = dpcm->fe; + + fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = + SND_SOC_DPCM_TRIGGER_POST; + } + break; + case SOF_DAI_INTEL_ALH: + /* + * Dai could run with different channel count compared with + * front end, so get dai channel count from topology + */ + channels->min = private->dai_config->alh.channels; + channels->max = private->dai_config->alh.channels; + break; + case SOF_DAI_IMX_ESAI: + rate->min = private->dai_config->esai.fsync_rate; + rate->max = private->dai_config->esai.fsync_rate; + channels->min = private->dai_config->esai.tdm_slots; + channels->max = private->dai_config->esai.tdm_slots; + + dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_MEDIATEK_AFE: + rate->min = private->dai_config->afe.rate; + rate->max = private->dai_config->afe.rate; + channels->min = private->dai_config->afe.channels; + channels->max = private->dai_config->afe.channels; + + dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_IMX_SAI: + rate->min = private->dai_config->sai.fsync_rate; + rate->max = private->dai_config->sai.fsync_rate; + channels->min = private->dai_config->sai.tdm_slots; + channels->max = private->dai_config->sai.tdm_slots; + + dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_AMD_BT: + rate->min = private->dai_config->acpbt.fsync_rate; + rate->max = private->dai_config->acpbt.fsync_rate; + channels->min = private->dai_config->acpbt.tdm_slots; + channels->max = private->dai_config->acpbt.tdm_slots; + + dev_dbg(component->dev, + "AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "AMD_BT channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_AMD_SP: + rate->min = private->dai_config->acpsp.fsync_rate; + rate->max = private->dai_config->acpsp.fsync_rate; + channels->min = private->dai_config->acpsp.tdm_slots; + channels->max = private->dai_config->acpsp.tdm_slots; + + dev_dbg(component->dev, + "AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "AMD_SP channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + case SOF_DAI_AMD_DMIC: + rate->min = private->dai_config->acpdmic.fsync_rate; + rate->max = private->dai_config->acpdmic.fsync_rate; + channels->min = private->dai_config->acpdmic.tdm_slots; + channels->max = private->dai_config->acpdmic.tdm_slots; + + dev_dbg(component->dev, + "AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max); + dev_dbg(component->dev, "AMD_DMIC channels_min: %d channels_max: %d\n", + channels->min, channels->max); + break; + default: + dev_err(component->dev, "Invalid DAI type %d\n", private->dai_config->type); + break; + } + + return 0; +} + const struct sof_ipc_pcm_ops ipc3_pcm_ops = { .hw_params = sof_ipc3_pcm_hw_params, .hw_free = sof_ipc3_pcm_hw_free, .trigger = sof_ipc3_pcm_trigger, + .dai_link_fixup = sof_ipc3_pcm_dai_link_fixup, }; diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index dc55a04a1588..658cd8966c9a 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -556,33 +556,6 @@ static int sof_pcm_new(struct snd_soc_component *component, return 0; } -static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, - struct snd_pcm_hw_params *params) -{ - struct sof_ipc_dai_config *config; - struct snd_sof_dai *dai; - int i; - - /* - * Search for all matching DAIs as we can have both playback and capture DAI - * associated with the same link. - */ - list_for_each_entry(dai, &sdev->dai_list, list) { - if (!dai->name || strcmp(link_name, dai->name)) - continue; - for (i = 0; i < dai->number_configs; i++) { - struct sof_dai_private_data *private = dai->private; - - config = &private->dai_config[i]; - if (config->ssp.fsync_rate == params_rate(params)) { - dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i); - dai->current_config = i; - break; - } - } - } -} - /* fixup the BE DAI link to match any values from topology */ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -596,8 +569,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); - struct sof_dai_private_data *private = dai->private; - struct snd_soc_dpcm *dpcm; + const struct sof_ipc_pcm_ops *pcm_ops = sdev->ipc->ops->pcm; /* no topology exists for this BE, try a common configuration */ if (!dai) { @@ -618,148 +590,8 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa return 0; } - /* read format from topology */ - snd_mask_none(fmt); - - switch (private->comp_dai->config.frame_fmt) { - case SOF_IPC_FRAME_S16_LE: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); - break; - case SOF_IPC_FRAME_S24_4LE: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE); - break; - case SOF_IPC_FRAME_S32_LE: - snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE); - break; - default: - dev_err(component->dev, "error: No available DAI format!\n"); - return -EINVAL; - } - - /* read rate and channels from topology */ - switch (private->dai_config->type) { - case SOF_DAI_INTEL_SSP: - /* search for config to pcm params match, if not found use default */ - ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params); - - rate->min = private->dai_config[dai->current_config].ssp.fsync_rate; - rate->max = private->dai_config[dai->current_config].ssp.fsync_rate; - channels->min = private->dai_config[dai->current_config].ssp.tdm_slots; - channels->max = private->dai_config[dai->current_config].ssp.tdm_slots; - - dev_dbg(component->dev, - "rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "channels_min: %d channels_max: %d\n", - channels->min, channels->max); - - break; - case SOF_DAI_INTEL_DMIC: - /* DMIC only supports 16 or 32 bit formats */ - if (private->comp_dai->config.frame_fmt == SOF_IPC_FRAME_S24_4LE) { - dev_err(component->dev, - "error: invalid fmt %d for DAI type %d\n", - private->comp_dai->config.frame_fmt, - private->dai_config->type); - } - break; - case SOF_DAI_INTEL_HDA: - /* - * HDAudio does not follow the default trigger - * sequence due to firmware implementation - */ - for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { - struct snd_soc_pcm_runtime *fe = dpcm->fe; - - fe->dai_link->trigger[SNDRV_PCM_STREAM_PLAYBACK] = - SND_SOC_DPCM_TRIGGER_POST; - } - break; - case SOF_DAI_INTEL_ALH: - /* - * Dai could run with different channel count compared with - * front end, so get dai channel count from topology - */ - channels->min = private->dai_config->alh.channels; - channels->max = private->dai_config->alh.channels; - break; - case SOF_DAI_IMX_ESAI: - rate->min = private->dai_config->esai.fsync_rate; - rate->max = private->dai_config->esai.fsync_rate; - channels->min = private->dai_config->esai.tdm_slots; - channels->max = private->dai_config->esai.tdm_slots; - - dev_dbg(component->dev, - "rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - case SOF_DAI_MEDIATEK_AFE: - rate->min = private->dai_config->afe.rate; - rate->max = private->dai_config->afe.rate; - channels->min = private->dai_config->afe.channels; - channels->max = private->dai_config->afe.channels; - - dev_dbg(component->dev, - "rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - case SOF_DAI_IMX_SAI: - rate->min = private->dai_config->sai.fsync_rate; - rate->max = private->dai_config->sai.fsync_rate; - channels->min = private->dai_config->sai.tdm_slots; - channels->max = private->dai_config->sai.tdm_slots; - - dev_dbg(component->dev, - "rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - case SOF_DAI_AMD_BT: - rate->min = private->dai_config->acpbt.fsync_rate; - rate->max = private->dai_config->acpbt.fsync_rate; - channels->min = private->dai_config->acpbt.tdm_slots; - channels->max = private->dai_config->acpbt.tdm_slots; - - dev_dbg(component->dev, - "AMD_BT rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "AMD_BT channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - case SOF_DAI_AMD_SP: - rate->min = private->dai_config->acpsp.fsync_rate; - rate->max = private->dai_config->acpsp.fsync_rate; - channels->min = private->dai_config->acpsp.tdm_slots; - channels->max = private->dai_config->acpsp.tdm_slots; - - dev_dbg(component->dev, - "AMD_SP rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "AMD_SP channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - case SOF_DAI_AMD_DMIC: - rate->min = private->dai_config->acpdmic.fsync_rate; - rate->max = private->dai_config->acpdmic.fsync_rate; - channels->min = private->dai_config->acpdmic.tdm_slots; - channels->max = private->dai_config->acpdmic.tdm_slots; - - dev_dbg(component->dev, - "AMD_DMIC rate_min: %d rate_max: %d\n", rate->min, rate->max); - dev_dbg(component->dev, - "AMD_DMIC channels_min: %d channels_max: %d\n", - channels->min, channels->max); - break; - default: - dev_err(component->dev, "error: invalid DAI type %d\n", - private->dai_config->type); - break; - } + if (pcm_ops->dai_link_fixup) + return pcm_ops->dai_link_fixup(rtd, params); return 0; } From patchwork Thu Mar 17 17:50:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784421 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 45D73C433F5 for ; Thu, 17 Mar 2022 17:58:25 +0000 (UTC) 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 72DD81A92; Thu, 17 Mar 2022 18:57:33 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 72DD81A92 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539903; bh=gUs2VhEZAGhDbjAQmkiKLxXwNNpF/D8m1ekix5YtTh0=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=gZgAHzSGOvSzQbOJXpfnus1Uk1uKZtSw7JY02OIhy+zI0UF6+Byr1yEfgOgj2z+w4 rcoV2z7xs8HTdDHs6HtZ+oqh3ZVHQm1IGWY5rQjHZE8o4bZVJxH8YxaMqEV28PlSqL bOuv52snPMeu/YxbIrNoXTR98ttBExcUHsgXhFHg= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 9E62DF805C0; Thu, 17 Mar 2022 18:52:23 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 32E44F8053C; Thu, 17 Mar 2022 18:52:13 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 48E69F80124 for ; Thu, 17 Mar 2022 18:51:56 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 48E69F80124 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="H2cVNjfi" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539517; x=1679075517; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=gUs2VhEZAGhDbjAQmkiKLxXwNNpF/D8m1ekix5YtTh0=; b=H2cVNjfiXbxkiVMxx/qs7pN/IpzvdMEmSOrQY9mHumPoAvVid1eljIuo xmjPc8YeTJxt/DlJn6SJ7zyjQoHQcCnp4bDRVk9b1HXTrVKM1JP4Xms6y 3EUOIpginPJfjaWD1gzwI6qOYrxHyv/as/DtPdVkw+JFsnAjFBQ1EArg0 0E20TwTcamrOIdzOwAHMWhao6FwlwlTVMiUEu10yatSdDDmQoG7IgMcGm X9mH/AauARnCnrco1tgkB9Mb+8DNyeohYkUDrx11mW7BEkYTf7K4sMbJQ 2DOjesU6hNLA6R2cJpThw9uu3hhorD16wASA4/XaZ4Mzh9X39jniwM/El g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492935" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492935" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:24 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431158" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:23 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 17/19] ASoC: SOF: expose sof_route_setup() Date: Thu, 17 Mar 2022 10:50:42 -0700 Message-Id: <20220317175044.1752400-18-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, broonie@kernel.org, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart 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" This will be used in IPC3-specific code. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart --- sound/soc/sof/sof-audio.c | 4 ++-- sound/soc/sof/sof-audio.h | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 5088ec7019ed..8885709f40df 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -204,8 +204,8 @@ int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget) } EXPORT_SYMBOL(sof_widget_setup); -static int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, - struct snd_soc_dapm_widget *wsink) +int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, + struct snd_soc_dapm_widget *wsink) { const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; struct snd_sof_widget *src_widget = wsource->dobj.private; diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 3ec3f746663a..777da321e2aa 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -441,6 +441,8 @@ void sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata); int sof_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); int sof_widget_free(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); +int sof_route_setup(struct snd_sof_dev *sdev, struct snd_soc_dapm_widget *wsource, + struct snd_soc_dapm_widget *wsink); /* PCM */ int sof_widget_list_setup(struct snd_sof_dev *sdev, struct snd_sof_pcm *spcm, int dir); From patchwork Thu Mar 17 17:50:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784419 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id BCEA0C433F5 for ; Thu, 17 Mar 2022 17:57:45 +0000 (UTC) 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 02BEF1AA0; Thu, 17 Mar 2022 18:56:54 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz 02BEF1AA0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539864; bh=Jnwx6bT6fSpQMaGnu5xMc5DOpIdmZ8vxyY/YFGTnTj4=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=QMWnZMKNvIwDw1nYc2I2k9gZeLAVBq5KiAlnkb67qj5foML3QjvbA2MV18AWna3l/ PxcZXbV9/Yf8668TUU6ghHRMeQWRWfyEguHltxOvmdYg/KOGAV8cMprPjDNIrFCvvd lyVP8LKtLC+c9csys73MCPe2f7vWLQHIQpXuCDCE= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 8A9D6F805B4; Thu, 17 Mar 2022 18:52:22 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 85E0BF80520; Thu, 17 Mar 2022 18:52:11 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 7C8E6F8052E for ; Thu, 17 Mar 2022 18:51:58 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 7C8E6F8052E Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="SEJUUI/+" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539519; x=1679075519; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Jnwx6bT6fSpQMaGnu5xMc5DOpIdmZ8vxyY/YFGTnTj4=; b=SEJUUI/+uxGrFQE3tJx6sHnm0o8mpzMy3l57I3S9Ymtm5Aer89OaiWd8 mxWrhNRD+d4gSzRGPMqPGsGVydzS6iR1hQVVmfh5Hf3QSYMywACJWu4tX NtdtBFsqBjnkjRGvnwLeZE/1izKM1bQr140o7g7iEwQHAMtAuqsp1WNoV MOwkkcDHwBnlH3b2sMWPAY8hlif26wWNsnboaNypVZQ/Q++LUHZu5y/UI lwy4eYNy+fj78VPTaoPXfThG0ed3d3Ig98IshHa51dA40Zdl2bRxBqS/P VuiRdZS99iPVg8eLCJyu3lgoqwEY2OKP9bL9Ug+iCEOrTuNdQnt7HkybC g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492936" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492936" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:24 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431159" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:24 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 18/19] ASoC: SOF: topology: Add ops for setting up and tearing down pipelines Date: Thu, 17 Mar 2022 10:50:43 -0700 Message-Id: <20220317175044.1752400-19-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, =?utf-8?q?P=C3=A9ter_Ujfalusi?= , Ranjani Sridharan , Pierre-Louis Bossart , broonie@kernel.org, Bard Liao 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" Introduce two new ops, set_up_all_pipelines and tear_down_all_pipelines in struct ipc_tplg_ops and define these for IPC3. Signed-off-by: Ranjani Sridharan Reviewed-by: Péter Ujfalusi Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao --- sound/soc/sof/ipc3-topology.c | 197 ++++++++++++++++++++++++++++++++++ sound/soc/sof/pm.c | 17 +-- sound/soc/sof/sof-audio.c | 186 -------------------------------- sound/soc/sof/sof-audio.h | 6 +- sound/soc/sof/topology.c | 55 +++++----- 5 files changed, 235 insertions(+), 226 deletions(-) diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 55be97ee816b..3ac65dacc7b9 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2057,6 +2057,201 @@ static int sof_ipc3_widget_setup(struct snd_sof_dev *sdev, struct snd_sof_widget return ret; } +static int sof_ipc3_set_up_all_pipelines(struct snd_sof_dev *sdev, bool verify) +{ + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; + struct snd_sof_widget *swidget; + struct snd_sof_route *sroute; + int ret; + + /* restore pipeline components */ + list_for_each_entry(swidget, &sdev->widget_list, list) { + /* only set up the widgets belonging to static pipelines */ + if (!verify && swidget->dynamic_pipeline_widget) + continue; + + /* + * For older firmware, skip scheduler widgets in this loop, + * sof_widget_setup() will be called in the 'complete pipeline' loop + */ + if (v->abi_version < SOF_ABI_VER(3, 19, 0) && + swidget->id == snd_soc_dapm_scheduler) + continue; + + /* update DAI config. The IPC will be sent in sof_widget_setup() */ + if (WIDGET_IS_DAI(swidget->id)) { + struct snd_sof_dai *dai = swidget->private; + struct sof_dai_private_data *private; + struct sof_ipc_dai_config *config; + + if (!dai || !dai->private) + continue; + private = dai->private; + if (!private->dai_config) + continue; + + config = private->dai_config; + /* + * The link DMA channel would be invalidated for running + * streams but not for streams that were in the PAUSED + * state during suspend. So invalidate it here before setting + * the dai config in the DSP. + */ + if (config->type == SOF_DAI_INTEL_HDA) + config->hda.link_dma_ch = DMA_CHAN_INVALID; + } + + ret = sof_widget_setup(sdev, swidget); + if (ret < 0) + return ret; + } + + /* restore pipeline connections */ + list_for_each_entry(sroute, &sdev->route_list, list) { + /* only set up routes belonging to static pipelines */ + if (!verify && (sroute->src_widget->dynamic_pipeline_widget || + sroute->sink_widget->dynamic_pipeline_widget)) + continue; + + /* + * For virtual routes, both sink and source are not buffer. IPC3 only supports + * connections between a buffer and a component. Ignore the rest. + */ + if (sroute->src_widget->id != snd_soc_dapm_buffer && + sroute->sink_widget->id != snd_soc_dapm_buffer) + continue; + + ret = sof_route_setup(sdev, sroute->src_widget->widget, + sroute->sink_widget->widget); + if (ret < 0) { + dev_err(sdev->dev, "%s: route set up failed\n", __func__); + return ret; + } + } + + /* complete pipeline */ + list_for_each_entry(swidget, &sdev->widget_list, list) { + switch (swidget->id) { + case snd_soc_dapm_scheduler: + /* only complete static pipelines */ + if (!verify && swidget->dynamic_pipeline_widget) + continue; + + if (v->abi_version < SOF_ABI_VER(3, 19, 0)) { + ret = sof_widget_setup(sdev, swidget); + if (ret < 0) + return ret; + } + + swidget->complete = sof_ipc3_complete_pipeline(sdev, swidget); + if (swidget->complete < 0) + return swidget->complete; + break; + default: + break; + } + } + + return 0; +} + +/* + * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that + * did not get suspended(ex: paused streams) so the widgets can be set up again during resume. + */ +static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) +{ + struct snd_sof_widget *swidget; + struct snd_sof_pcm *spcm; + int dir, ret; + + /* + * free all PCMs and their associated DAPM widgets if their connected DAPM widget + * list is not NULL. This should only be true for paused streams at this point. + * This is equivalent to the handling of FE DAI suspend trigger for running streams. + */ + list_for_each_entry(spcm, &sdev->pcm_list, list) { + for_each_pcm_streams(dir) { + struct snd_pcm_substream *substream = spcm->stream[dir].substream; + + if (!substream || !substream->runtime) + continue; + + if (spcm->stream[dir].list) { + ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); + if (ret < 0) + return ret; + } + } + } + + /* + * free any left over DAI widgets. This is equivalent to the handling of suspend trigger + * for the BE DAI for running streams. + */ + list_for_each_entry(swidget, &sdev->widget_list, list) + if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) { + ret = sof_widget_free(sdev, swidget); + if (ret < 0) + return ret; + } + + return 0; +} + +/* + * For older firmware, this function doesn't free widgets for static pipelines during suspend. + * It only resets use_count for all widgets. + */ +static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verify) +{ + struct sof_ipc_fw_version *v = &sdev->fw_ready.version; + struct snd_sof_widget *swidget; + struct snd_sof_route *sroute; + int ret; + + /* + * This function is called during suspend and for one-time topology verification during + * first boot. In both cases, there is no need to protect swidget->use_count and + * sroute->setup because during suspend all running streams are suspended and during + * topology loading the sound card unavailable to open PCMs. + */ + list_for_each_entry(swidget, &sdev->widget_list, list) { + if (swidget->dynamic_pipeline_widget) + continue; + + /* Do not free widgets for static pipelines with FW ABI older than 3.19 */ + if (!verify && !swidget->dynamic_pipeline_widget && + v->abi_version < SOF_ABI_VER(3, 19, 0)) { + swidget->use_count = 0; + swidget->complete = 0; + continue; + } + + ret = sof_widget_free(sdev, swidget); + if (ret < 0) + return ret; + } + + /* + * Tear down all pipelines associated with PCMs that did not get suspended + * and unset the prepare flag so that they can be set up again during resume. + * Skip this step for older firmware. + */ + if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) { + ret = sof_tear_down_left_over_pipelines(sdev); + if (ret < 0) { + dev_err(sdev->dev, "failed to tear down paused pipelines\n"); + return ret; + } + } + + list_for_each_entry(sroute, &sdev->route_list, list) + sroute->setup = false; + + return 0; +} + /* token list for each topology object */ static enum sof_tokens host_token_list[] = { SOF_CORE_TOKENS, @@ -2164,4 +2359,6 @@ const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .widget_free = sof_ipc3_widget_free, .widget_setup = sof_ipc3_widget_setup, .dai_config = sof_ipc3_dai_config, + .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, + .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, }; diff --git a/sound/soc/sof/pm.c b/sound/soc/sof/pm.c index 10adbbd0a9cd..1c319582ca6f 100644 --- a/sound/soc/sof/pm.c +++ b/sound/soc/sof/pm.c @@ -71,6 +71,7 @@ static int sof_resume(struct device *dev, bool runtime_resume) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; u32 old_state = sdev->dsp_power_state.state; int ret; @@ -144,12 +145,12 @@ static int sof_resume(struct device *dev, bool runtime_resume) } /* restore pipelines */ - ret = sof_set_up_pipelines(sdev, false); - if (ret < 0) { - dev_err(sdev->dev, - "error: failed to restore pipeline after resume %d\n", - ret); - return ret; + if (tplg_ops->set_up_all_pipelines) { + ret = tplg_ops->set_up_all_pipelines(sdev, false); + if (ret < 0) { + dev_err(sdev->dev, "Failed to restore pipeline after resume %d\n", ret); + return ret; + } } /* Notify clients not managed by pm framework about core resume */ @@ -169,6 +170,7 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) { struct snd_sof_dev *sdev = dev_get_drvdata(dev); const struct sof_ipc_pm_ops *pm_ops = sdev->ipc->ops->pm; + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; pm_message_t pm_state; u32 target_state = 0; int ret; @@ -204,7 +206,8 @@ static int sof_suspend(struct device *dev, bool runtime_suspend) goto suspend; } - sof_tear_down_pipelines(sdev, false); + if (tplg_ops->tear_down_all_pipelines) + tplg_ops->tear_down_all_pipelines(sdev, false); /* release trace */ snd_sof_release_trace(sdev); diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 8885709f40df..b4ee65cf9841 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -498,96 +498,6 @@ int sof_set_hw_params_upon_resume(struct device *dev) return snd_sof_dsp_hw_params_upon_resume(sdev); } -int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify) -{ - const struct sof_ipc_tplg_ops *ipc_tplg_ops = sdev->ipc->ops->tplg; - struct sof_ipc_fw_version *v = &sdev->fw_ready.version; - struct snd_sof_widget *swidget; - struct snd_sof_route *sroute; - int ret; - - /* restore pipeline components */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - /* only set up the widgets belonging to static pipelines */ - if (!verify && swidget->dynamic_pipeline_widget) - continue; - - /* - * For older firmware, skip scheduler widgets in this loop, - * sof_widget_setup() will be called in the 'complete pipeline' loop - */ - if (v->abi_version < SOF_ABI_VER(3, 19, 0) && - swidget->id == snd_soc_dapm_scheduler) - continue; - - /* update DAI config. The IPC will be sent in sof_widget_setup() */ - if (WIDGET_IS_DAI(swidget->id)) { - struct snd_sof_dai *dai = swidget->private; - struct sof_dai_private_data *private = dai->private; - struct sof_ipc_dai_config *config; - - if (!dai || !private || !private->dai_config) - continue; - - config = private->dai_config; - /* - * The link DMA channel would be invalidated for running - * streams but not for streams that were in the PAUSED - * state during suspend. So invalidate it here before setting - * the dai config in the DSP. - */ - if (config->type == SOF_DAI_INTEL_HDA) - config->hda.link_dma_ch = DMA_CHAN_INVALID; - } - - ret = sof_widget_setup(sdev, swidget); - if (ret < 0) - return ret; - } - - /* restore pipeline connections */ - list_for_each_entry(sroute, &sdev->route_list, list) { - - /* only set up routes belonging to static pipelines */ - if (!verify && (sroute->src_widget->dynamic_pipeline_widget || - sroute->sink_widget->dynamic_pipeline_widget)) - continue; - - ret = ipc_tplg_ops->route_setup(sdev, sroute); - if (ret < 0) { - dev_err(sdev->dev, "%s: restore pipeline connections failed\n", __func__); - return ret; - } - } - - /* complete pipeline */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - switch (swidget->id) { - case snd_soc_dapm_scheduler: - /* only complete static pipelines */ - if (!verify && swidget->dynamic_pipeline_widget) - continue; - - if (v->abi_version < SOF_ABI_VER(3, 19, 0)) { - ret = sof_widget_setup(sdev, swidget); - if (ret < 0) - return ret; - } - - if (ipc_tplg_ops->pipeline_complete) { - swidget->complete = ipc_tplg_ops->pipeline_complete(sdev, swidget); - if (swidget->complete < 0) - return swidget->complete; - } - break; - default: - break; - } - } - - return 0; -} - int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream, struct snd_sof_pcm *spcm, int dir, bool free_widget_list) { @@ -618,102 +528,6 @@ int sof_pcm_stream_free(struct snd_sof_dev *sdev, struct snd_pcm_substream *subs return ret; } -/* - * Free the PCM, its associated widgets and set the prepared flag to false for all PCMs that - * did not get suspended(ex: paused streams) so the widgets can be set up again during resume. - */ -static int sof_tear_down_left_over_pipelines(struct snd_sof_dev *sdev) -{ - struct snd_sof_widget *swidget; - struct snd_sof_pcm *spcm; - int dir, ret; - - /* - * free all PCMs and their associated DAPM widgets if their connected DAPM widget - * list is not NULL. This should only be true for paused streams at this point. - * This is equivalent to the handling of FE DAI suspend trigger for running streams. - */ - list_for_each_entry(spcm, &sdev->pcm_list, list) - for_each_pcm_streams(dir) { - struct snd_pcm_substream *substream = spcm->stream[dir].substream; - - if (!substream || !substream->runtime) - continue; - - if (spcm->stream[dir].list) { - ret = sof_pcm_stream_free(sdev, substream, spcm, dir, true); - if (ret < 0) - return ret; - } - } - - /* - * free any left over DAI widgets. This is equivalent to the handling of suspend trigger - * for the BE DAI for running streams. - */ - list_for_each_entry(swidget, &sdev->widget_list, list) - if (WIDGET_IS_DAI(swidget->id) && swidget->use_count == 1) { - ret = sof_widget_free(sdev, swidget); - if (ret < 0) - return ret; - } - - return 0; -} - -/* - * For older firmware, this function doesn't free widgets for static pipelines during suspend. - * It only resets use_count for all widgets. - */ -int sof_tear_down_pipelines(struct snd_sof_dev *sdev, bool verify) -{ - struct sof_ipc_fw_version *v = &sdev->fw_ready.version; - struct snd_sof_widget *swidget; - struct snd_sof_route *sroute; - int ret; - - /* - * This function is called during suspend and for one-time topology verification during - * first boot. In both cases, there is no need to protect swidget->use_count and - * sroute->setup because during suspend all running streams are suspended and during - * topology loading the sound card unavailable to open PCMs. - */ - list_for_each_entry(swidget, &sdev->widget_list, list) { - if (swidget->dynamic_pipeline_widget) - continue; - - /* Do not free widgets for static pipelines with FW ABI older than 3.19 */ - if (!verify && !swidget->dynamic_pipeline_widget && - v->abi_version < SOF_ABI_VER(3, 19, 0)) { - swidget->use_count = 0; - swidget->complete = 0; - continue; - } - - ret = sof_widget_free(sdev, swidget); - if (ret < 0) - return ret; - } - - /* - * Tear down all pipelines associated with PCMs that did not get suspended - * and unset the prepare flag so that they can be set up again during resume. - * Skip this step for older firmware. - */ - if (!verify && v->abi_version >= SOF_ABI_VER(3, 19, 0)) { - ret = sof_tear_down_left_over_pipelines(sdev); - if (ret < 0) { - dev_err(sdev->dev, "failed to tear down paused pipelines\n"); - return ret; - } - } - - list_for_each_entry(sroute, &sdev->route_list, list) - sroute->setup = false; - - return 0; -} - /* * Generic object lookup APIs. */ diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index 777da321e2aa..b9a9956b5baa 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -117,6 +117,8 @@ struct sof_ipc_tplg_widget_ops { * @widget_setup: Function pointer for setting up setup in the DSP * @widget_free: Function pointer for freeing widget in the DSP * @dai_config: Function pointer for sending DAI config IPC to the DSP + * @set_up_all_pipelines: Function pointer for setting up all topology pipelines + * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines */ struct sof_ipc_tplg_ops { const struct sof_ipc_tplg_widget_ops *widget; @@ -130,6 +132,8 @@ struct sof_ipc_tplg_ops { int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, unsigned int flags, struct snd_sof_dai_config_data *data); + int (*set_up_all_pipelines)(struct snd_sof_dev *sdev, bool verify); + int (*tear_down_all_pipelines)(struct snd_sof_dev *sdev, bool verify); }; /** struct snd_sof_tuple - Tuple info @@ -429,8 +433,6 @@ int snd_sof_ipc_set_get_comp_data(struct snd_sof_control *scontrol, bool set); int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); /* PM */ -int sof_set_up_pipelines(struct snd_sof_dev *sdev, bool verify); -int sof_tear_down_pipelines(struct snd_sof_dev *sdev, bool verify); int sof_set_hw_params_upon_resume(struct device *dev); bool snd_sof_stream_suspend_ignored(struct snd_sof_dev *sdev); bool snd_sof_dsp_only_d0i3_compatible_stream_active(struct snd_sof_dev *sdev); diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 367fbe2d5b31..9e6545dd415c 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -1797,29 +1797,15 @@ static int sof_route_load(struct snd_soc_component *scomp, int index, sink_swidget->id == snd_soc_dapm_output) goto err; - /* - * For virtual routes, both sink and source are not - * buffer. Since only buffer linked to component is supported by - * FW, others are reported as error, add check in route function, - * do not send it to FW when both source and sink are not buffer - */ - if (source_swidget->id != snd_soc_dapm_buffer && - sink_swidget->id != snd_soc_dapm_buffer) { - dev_dbg(scomp->dev, "warning: neither Linked source component %s nor sink component %s is of buffer type, ignoring link\n", - route->source, route->sink); - goto err; - } else { - sroute->route = route; - dobj->private = sroute; - sroute->src_widget = source_swidget; - sroute->sink_widget = sink_swidget; - - /* add route to route list */ - list_add(&sroute->list, &sdev->route_list); + sroute->route = route; + dobj->private = sroute; + sroute->src_widget = source_swidget; + sroute->sink_widget = sink_swidget; - return 0; - } + /* add route to route list */ + list_add(&sroute->list, &sdev->route_list); + return 0; err: kfree(sroute); return ret; @@ -1918,21 +1904,28 @@ static int sof_complete(struct snd_soc_component *scomp) /* verify topology components loading including dynamic pipelines */ if (sof_debug_check_flag(SOF_DBG_VERIFY_TPLG)) { - ret = sof_set_up_pipelines(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, "error: topology verification failed %d\n", ret); - return ret; - } + if (ipc_tplg_ops->set_up_all_pipelines && ipc_tplg_ops->tear_down_all_pipelines) { + ret = ipc_tplg_ops->set_up_all_pipelines(sdev, true); + if (ret < 0) { + dev_err(sdev->dev, "Failed to set up all topology pipelines: %d\n", + ret); + return ret; + } - ret = sof_tear_down_pipelines(sdev, true); - if (ret < 0) { - dev_err(sdev->dev, "error: topology tear down pipelines failed %d\n", ret); - return ret; + ret = ipc_tplg_ops->tear_down_all_pipelines(sdev, true); + if (ret < 0) { + dev_err(sdev->dev, "Failed to tear down topology pipelines: %d\n", + ret); + return ret; + } } } /* set up static pipelines */ - return sof_set_up_pipelines(sdev, false); + if (ipc_tplg_ops->set_up_all_pipelines) + return ipc_tplg_ops->set_up_all_pipelines(sdev, false); + + return 0; } /* manifest - optional to inform component of manifest */ From patchwork Thu Mar 17 17:50:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ranjani Sridharan X-Patchwork-Id: 12784418 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org 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 smtp.lore.kernel.org (Postfix) with ESMTPS id A1AEEC433F5 for ; Thu, 17 Mar 2022 17:57:37 +0000 (UTC) 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 E0206170E; Thu, 17 Mar 2022 18:56:45 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz E0206170E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1647539855; bh=UFO0mKXc1Pe4BdIkYJ4BmO0PrzhaI/opvkJbUhm0dfI=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=Mx/bufb27BZxRi6rLnV50d9/lF9o9aaG/UCOhcCZXeNNyyvSGgC7roF1OC3hMiM0Z 1BnDcUNSIENtiMv4DKSP2hQJTWflU8MwT1e0v1z4yuitjK/ewRJ429rZ1MOpDIS1Jy DnU3M/t1dIabFlpWa0kasacEchFd2pCuJGija9ME= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 18F59F805AB; Thu, 17 Mar 2022 18:52:22 +0100 (CET) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 65453F8051D; Thu, 17 Mar 2022 18:52:10 +0100 (CET) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id EDB47F80527 for ; Thu, 17 Mar 2022 18:51:57 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz EDB47F80527 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="AZQdrqEt" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1647539519; x=1679075519; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=UFO0mKXc1Pe4BdIkYJ4BmO0PrzhaI/opvkJbUhm0dfI=; b=AZQdrqEtq6KZM8V0ggKoKukvjrOLG+t6cHm2vTEhUi6FmPdlipNH8vCW LPzwpNKJ8Rp7UjN1tiZDsXZYG+p/1Nn1J9o5KZ4hY7ukWrdY+/9VRLKWA CsM7zVvJXN2I472LSU9VKXh0fXVgzo55NFsFOPs8nANLQ9EAkqH8Q70ND IhjKzKI5IcWos75z5qE5NgqMApZRzcUwlAMa4ksK85wj7WqTA04Bq1d3z jiAS9xJ+EaUFfzcRRYU2Vn+k7Aoy2G10q7i6Gf8WKfUR9yEOj6ITrrNou o0JgXLjug6g+p7WenX9s7j+gmcz3LOFU2azHlzNfvT+acoTb0aupZXvyh g==; X-IronPort-AV: E=McAfee;i="6200,9189,10289"; a="254492937" X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="254492937" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga102.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:24 -0700 X-IronPort-AV: E=Sophos;i="5.90,188,1643702400"; d="scan'208";a="550431163" Received: from jfbonin1-mobl6.amr.corp.intel.com (HELO rsridh2-mobl1.localdomain) ([10.255.92.163]) by fmsmga007-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 Mar 2022 10:51:24 -0700 From: Ranjani Sridharan To: alsa-devel@alsa-project.org Subject: [PATCH 19/19] ASoC: SOF: Add a new dai_get_clk topology IPC op Date: Thu, 17 Mar 2022 10:50:44 -0700 Message-Id: <20220317175044.1752400-20-ranjani.sridharan@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> References: <20220317175044.1752400-1-ranjani.sridharan@linux.intel.com> MIME-Version: 1.0 Cc: tiwai@suse.de, Pierre-Louis Bossart , Ranjani Sridharan , broonie@kernel.org, Rander Wang , Bard Liao 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" This will help make the code for getting the mclk and bclk IPC specific. Add the implementation for IPC3 as well. Signed-off-by: Ranjani Sridharan Reviewed-by: Rander Wang Reviewed-by: Pierre-Louis Bossart Reviewed-by: Bard Liao --- sound/soc/sof/ipc3-topology.c | 29 +++++++++++++++++++++++++++++ sound/soc/sof/sof-audio.c | 31 +++++++------------------------ sound/soc/sof/sof-audio.h | 6 ++++++ 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c index 3ac65dacc7b9..2f8450a8c0a1 100644 --- a/sound/soc/sof/ipc3-topology.c +++ b/sound/soc/sof/ipc3-topology.c @@ -2252,6 +2252,34 @@ static int sof_ipc3_tear_down_all_pipelines(struct snd_sof_dev *sdev, bool verif return 0; } +static int sof_ipc3_dai_get_clk(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type) +{ + struct sof_dai_private_data *private = dai->private; + + if (!private || !private->dai_config) + return 0; + + switch (private->dai_config->type) { + case SOF_DAI_INTEL_SSP: + switch (clk_type) { + case SOF_DAI_CLK_INTEL_SSP_MCLK: + return private->dai_config->ssp.mclk_rate; + case SOF_DAI_CLK_INTEL_SSP_BCLK: + return private->dai_config->ssp.bclk_rate; + default: + break; + } + dev_err(sdev->dev, "fail to get SSP clk %d rate\n", clk_type); + break; + default: + /* not yet implemented for platforms other than the above */ + dev_err(sdev->dev, "DAI type %d not supported yet!\n", private->dai_config->type); + break; + } + + return -EINVAL; +} + /* token list for each topology object */ static enum sof_tokens host_token_list[] = { SOF_CORE_TOKENS, @@ -2359,6 +2387,7 @@ const struct sof_ipc_tplg_ops ipc3_tplg_ops = { .widget_free = sof_ipc3_widget_free, .widget_setup = sof_ipc3_widget_setup, .dai_config = sof_ipc3_dai_config, + .dai_get_clk = sof_ipc3_dai_get_clk, .set_up_all_pipelines = sof_ipc3_set_up_all_pipelines, .tear_down_all_pipelines = sof_ipc3_tear_down_all_pipelines, }; diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index b4ee65cf9841..b2f009a0c5b7 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -628,40 +628,23 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, return NULL; } -#define SOF_DAI_CLK_INTEL_SSP_MCLK 0 -#define SOF_DAI_CLK_INTEL_SSP_BCLK 1 - static int sof_dai_get_clk(struct snd_soc_pcm_runtime *rtd, int clk_type) { struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); - struct sof_dai_private_data *private = dai->private; + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + const struct sof_ipc_tplg_ops *tplg_ops = sdev->ipc->ops->tplg; /* use the tplg configured mclk if existed */ - if (!dai || !private || !private->dai_config) + if (!dai) return 0; - switch (private->dai_config->type) { - case SOF_DAI_INTEL_SSP: - switch (clk_type) { - case SOF_DAI_CLK_INTEL_SSP_MCLK: - return private->dai_config->ssp.mclk_rate; - case SOF_DAI_CLK_INTEL_SSP_BCLK: - return private->dai_config->ssp.bclk_rate; - default: - dev_err(rtd->dev, "fail to get SSP clk %d rate\n", - clk_type); - return -EINVAL; - } - break; - default: - /* not yet implemented for platforms other than the above */ - dev_err(rtd->dev, "DAI type %d not supported yet!\n", - private->dai_config->type); - return -EINVAL; - } + if (tplg_ops->dai_get_clk) + return tplg_ops->dai_get_clk(sdev, dai, clk_type); + + return 0; } /* diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index b9a9956b5baa..7f15b3bc8196 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -30,6 +30,9 @@ #define WIDGET_IS_DAI(id) ((id) == snd_soc_dapm_dai_in || (id) == snd_soc_dapm_dai_out) +#define SOF_DAI_CLK_INTEL_SSP_MCLK 0 +#define SOF_DAI_CLK_INTEL_SSP_BCLK 1 + /* * Volume fractional word length define to 16 sets * the volume linear gain value to use Qx.16 format @@ -39,6 +42,7 @@ struct snd_sof_widget; struct snd_sof_route; struct snd_sof_control; +struct snd_sof_dai; struct snd_sof_dai_config_data { int dai_index; @@ -117,6 +121,7 @@ struct sof_ipc_tplg_widget_ops { * @widget_setup: Function pointer for setting up setup in the DSP * @widget_free: Function pointer for freeing widget in the DSP * @dai_config: Function pointer for sending DAI config IPC to the DSP + * @dai_get_clk: Function pointer for getting the DAI clock setting * @set_up_all_pipelines: Function pointer for setting up all topology pipelines * @tear_down_all_pipelines: Function pointer for tearing down all topology pipelines */ @@ -132,6 +137,7 @@ struct sof_ipc_tplg_ops { int (*widget_free)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget); int (*dai_config)(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget, unsigned int flags, struct snd_sof_dai_config_data *data); + int (*dai_get_clk)(struct snd_sof_dev *sdev, struct snd_sof_dai *dai, int clk_type); int (*set_up_all_pipelines)(struct snd_sof_dev *sdev, bool verify); int (*tear_down_all_pipelines)(struct snd_sof_dev *sdev, bool verify); };