From patchwork Tue Aug 3 12:54:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 491705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 04C2DC4338F for ; Tue, 3 Aug 2021 13:00:19 +0000 (UTC) Received: from alsa0.perex.cz (alsa0.perex.cz [77.48.224.243]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 773FF60F01 for ; Tue, 3 Aug 2021 13:00:18 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 773FF60F01 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=alsa-project.org Received: from alsa1.perex.cz (alsa1.perex.cz [207.180.221.201]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by alsa0.perex.cz (Postfix) with ESMTPS id F2F0E1793; Tue, 3 Aug 2021 14:59:26 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa0.perex.cz F2F0E1793 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=alsa-project.org; s=default; t=1627995617; bh=7WA5QgqpkxUxA+1QyRw/8r737Ury9lDotF+AGQwhZnA=; h=From:To:Subject:Date:In-Reply-To:References:Cc:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From; b=vdGN/Pa/d60wG40twgBUd1EdWBpAgYtoEnWj6FPrcxlxhmqD2e0vxhM67/kX/ehJz ba117rBVaWZk3c5LLLP+yBuUtMmm4fRUFkZheYD89yhgF9gAH5YlaLr1ebNqbkyCTa NPQUrGFlQqxrv1Y5lC5ghQL+8J8bgPnrP9WlgLEQ= Received: from alsa1.perex.cz (localhost.localdomain [127.0.0.1]) by alsa1.perex.cz (Postfix) with ESMTP id 9BFF2F80549; Tue, 3 Aug 2021 14:54:52 +0200 (CEST) Received: by alsa1.perex.cz (Postfix, from userid 50401) id 4BA43F80542; Tue, 3 Aug 2021 14:54:50 +0200 (CEST) Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by alsa1.perex.cz (Postfix) with ESMTPS id 3D6AEF80506 for ; Tue, 3 Aug 2021 14:54:38 +0200 (CEST) DKIM-Filter: OpenDKIM Filter v2.11.0 alsa1.perex.cz 3D6AEF80506 Authentication-Results: alsa1.perex.cz; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="p14ci8d5" Received: by mail-wm1-x335.google.com with SMTP id h24-20020a1ccc180000b029022e0571d1a0so2058359wmb.5 for ; Tue, 03 Aug 2021 05:54:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=UylhRv8a3g+/viiqNuHDvYEn6A6WdNOdrTNj8PEKZAg=; b=p14ci8d5vAa0paWg9lLX7xgTb9i+fg+Fzqi3fp5C0XALP9yMwBJAt1F+0BgdAHBW25 s3jGKew9FFTXvixuk+m3AFDVKGkUPOAPMfVh4D/Xbcq8BnUKEm71gxLmvLcQDXUJ8PgU tgql4GIAHTKJUAqi7zdpU3V2fBpvg3MhzQQyGJm4sKlv0FTm4DnbBF3wMcHPVu3CG3GN RMANx5sa5K9X58zOgFxU5Jc4GmQtGI4eWEd3yy0YG+gsml0qeJTs/yiIcDEusLJ3HkmM eMPVo9WqpX3Hae1qN7qN+sC35VHxr9YohLNdO3j2Lu/I+r+uHf+fPyeAq6sDP6OOmZX2 ZaAg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=UylhRv8a3g+/viiqNuHDvYEn6A6WdNOdrTNj8PEKZAg=; b=SzNdLIyX+9TieSdIxfoCSJI1iyKragcXRlorx9QAujeceirCtTBlLo15mxyCrLC2rq gsxo9Fk3gersfFJo/kVHpyJdOBOIXWNXRe6Dte5zyfrKCtHeAYiVyOAAY1g0sDtm2n7Q HjUItsrixN95qu1lC1k8cY5IjWy+m917Dar5GSBVWOk5lfzp0ZGlOoOCZ5RI0xMdqIj8 tBIRFx1c4q/rapIha18oZ7IYZdAgfhmKdFY4X7XeV3gV2827P39jxbV/1uShPnStPiID duAUbap7C48wXZDnKzbOmBb0IKVXhKkgZRLsnEuiEocRkz6lhBccnu9MKWCvojsZoXl3 VO/g== X-Gm-Message-State: AOAM533xIFPYV4XcWD0ujdmUCpILjdiFlVowOX7L5F2vA54c/Fjux6/g C1Tt9QJoHCwF1IQo/nr/n9EW/g== X-Google-Smtp-Source: ABdhPJzmSo8QmIAA4EFTn69jSttFzssnZahxCvEyVYhhGvutsEB/O5sZwi9ekFRZfx5Jta/KQkkbnw== X-Received: by 2002:a1c:2390:: with SMTP id j138mr21131727wmj.66.1627995273246; Tue, 03 Aug 2021 05:54:33 -0700 (PDT) Received: from srini-hackbox.lan (cpc86377-aztw32-2-0-cust226.18-1.cable.virginm.net. [92.233.226.227]) by smtp.gmail.com with ESMTPSA id h14sm14695574wrp.55.2021.08.03.05.54.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 03 Aug 2021 05:54:32 -0700 (PDT) From: Srinivas Kandagatla To: bjorn.andersson@linaro.org, broonie@kernel.org, robh@kernel.org Subject: [PATCH v3 09/20] ASoC: qdsp6: q6afe-clocks: move audio-clocks to common file Date: Tue, 3 Aug 2021 13:54:00 +0100 Message-Id: <20210803125411.28066-10-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20210803125411.28066-1-srinivas.kandagatla@linaro.org> References: <20210803125411.28066-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Cc: devicetree@vger.kernel.org, alsa-devel@alsa-project.org, bgoswami@codeaurora.org, tiwai@suse.de, plai@codeaurora.org, lgirdwood@gmail.com 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" Move common parts of q6afe-clocks to q6dsp-audio-clocks so that we could reuse most of the driver for new Q6DSP audio frameworks. This is to make the code reuseable for new Q6DSP AudioReach framework. Signed-off-by: Srinivas Kandagatla --- sound/soc/qcom/qdsp6/Makefile | 3 +- sound/soc/qcom/qdsp6/q6afe-clocks.c | 187 ++-------------------- sound/soc/qcom/qdsp6/q6dsp-audio-clocks.c | 185 +++++++++++++++++++++ sound/soc/qcom/qdsp6/q6dsp-audio-clocks.h | 30 ++++ 4 files changed, 232 insertions(+), 173 deletions(-) create mode 100644 sound/soc/qcom/qdsp6/q6dsp-audio-clocks.c create mode 100644 sound/soc/qcom/qdsp6/q6dsp-audio-clocks.h diff --git a/sound/soc/qcom/qdsp6/Makefile b/sound/soc/qcom/qdsp6/Makefile index 63151b7da140..2a19fd3ae352 100644 --- a/sound/soc/qcom/qdsp6/Makefile +++ b/sound/soc/qcom/qdsp6/Makefile @@ -1,11 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only snd-afe-dai-objs += q6dsp-audio-ports.o q6afe-dai.o +snd-afe-clks-objs := q6dsp-audio-clocks.o q6afe-clocks.o obj-$(CONFIG_SND_SOC_QDSP6_COMMON) += q6dsp-common.o obj-$(CONFIG_SND_SOC_QDSP6_CORE) += q6core.o obj-$(CONFIG_SND_SOC_QDSP6_AFE) += q6afe.o obj-$(CONFIG_SND_SOC_QDSP6_AFE_DAI) += snd-afe-dai.o -obj-$(CONFIG_SND_SOC_QDSP6_AFE_CLOCKS) += q6afe-clocks.o +obj-$(CONFIG_SND_SOC_QDSP6_AFE_CLOCKS) += snd-afe-clks.o obj-$(CONFIG_SND_SOC_QDSP6_ADM) += q6adm.o obj-$(CONFIG_SND_SOC_QDSP6_ROUTING) += q6routing.o obj-$(CONFIG_SND_SOC_QDSP6_ASM) += q6asm.o diff --git a/sound/soc/qcom/qdsp6/q6afe-clocks.c b/sound/soc/qcom/qdsp6/q6afe-clocks.c index 9431656283cd..05e00ceb5a75 100644 --- a/sound/soc/qcom/qdsp6/q6afe-clocks.c +++ b/sound/soc/qcom/qdsp6/q6afe-clocks.c @@ -7,115 +7,18 @@ #include #include #include -#include -#include +#include "q6dsp-audio-clocks.h" #include "q6afe.h" #define Q6AFE_CLK(id) { \ .clk_id = id, \ - .afe_clk_id = Q6AFE_##id, \ + .q6dsp_clk_id = Q6AFE_##id, \ .name = #id, \ .rate = 19200000, \ } -#define Q6AFE_VOTE_CLK(id, blkid, n) { \ - .clk_id = id, \ - .afe_clk_id = blkid, \ - .name = n, \ - } - -struct q6afe_clk_init { - int clk_id; - int afe_clk_id; - char *name; - int rate; -}; - -struct q6afe_clk { - struct device *dev; - int afe_clk_id; - int attributes; - int rate; - uint32_t handle; - struct clk_hw hw; -}; - -#define to_q6afe_clk(_hw) container_of(_hw, struct q6afe_clk, hw) - -struct q6afe_cc { - struct device *dev; - struct q6afe_clk *clks[Q6AFE_MAX_CLK_ID]; -}; - -static int clk_q6afe_prepare(struct clk_hw *hw) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - return q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes, - Q6AFE_LPASS_CLK_ROOT_DEFAULT, clk->rate); -} - -static void clk_q6afe_unprepare(struct clk_hw *hw) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - q6afe_set_lpass_clock(clk->dev, clk->afe_clk_id, clk->attributes, - Q6AFE_LPASS_CLK_ROOT_DEFAULT, 0); -} - -static int clk_q6afe_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - clk->rate = rate; - - return 0; -} - -static unsigned long clk_q6afe_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - return clk->rate; -} - -static long clk_q6afe_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - return rate; -} - -static const struct clk_ops clk_q6afe_ops = { - .prepare = clk_q6afe_prepare, - .unprepare = clk_q6afe_unprepare, - .set_rate = clk_q6afe_set_rate, - .round_rate = clk_q6afe_round_rate, - .recalc_rate = clk_q6afe_recalc_rate, -}; - -static int clk_vote_q6afe_block(struct clk_hw *hw) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - return q6afe_vote_lpass_core_hw(clk->dev, clk->afe_clk_id, - clk_hw_get_name(&clk->hw), &clk->handle); -} -static void clk_unvote_q6afe_block(struct clk_hw *hw) -{ - struct q6afe_clk *clk = to_q6afe_clk(hw); - - q6afe_unvote_lpass_core_hw(clk->dev, clk->afe_clk_id, clk->handle); -} - -static const struct clk_ops clk_vote_q6afe_ops = { - .prepare = clk_vote_q6afe_block, - .unprepare = clk_unvote_q6afe_block, -}; - -static const struct q6afe_clk_init q6afe_clks[] = { +static const struct q6dsp_clk_init q6afe_clks[] = { Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT), Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT), Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT), @@ -176,88 +79,28 @@ static const struct q6afe_clk_init q6afe_clks[] = { Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK), Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK), Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK), - Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE, + Q6DSP_VOTE_CLK(LPASS_HW_AVTIMER_VOTE, Q6AFE_LPASS_CORE_AVTIMER_BLOCK, "LPASS_AVTIMER_MACRO"), - Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE, + Q6DSP_VOTE_CLK(LPASS_HW_MACRO_VOTE, Q6AFE_LPASS_CORE_HW_MACRO_BLOCK, "LPASS_HW_MACRO"), - Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE, + Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK, "LPASS_HW_DCODEC"), }; -static struct clk_hw *q6afe_of_clk_hw_get(struct of_phandle_args *clkspec, - void *data) -{ - struct q6afe_cc *cc = data; - unsigned int idx = clkspec->args[0]; - unsigned int attr = clkspec->args[1]; - - if (idx >= Q6AFE_MAX_CLK_ID || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) { - dev_err(cc->dev, "Invalid clk specifier (%d, %d)\n", idx, attr); - return ERR_PTR(-EINVAL); - } - - if (cc->clks[idx]) { - cc->clks[idx]->attributes = attr; - return &cc->clks[idx]->hw; - } - - return ERR_PTR(-ENOENT); -} - -static int q6afe_clock_dev_probe(struct platform_device *pdev) -{ - struct q6afe_cc *cc; - struct device *dev = &pdev->dev; - int i, ret; - - cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); - if (!cc) - return -ENOMEM; - - cc->dev = dev; - for (i = 0; i < ARRAY_SIZE(q6afe_clks); i++) { - unsigned int id = q6afe_clks[i].clk_id; - struct clk_init_data init = { - .name = q6afe_clks[i].name, - }; - struct q6afe_clk *clk; - - clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); - if (!clk) - return -ENOMEM; - - clk->dev = dev; - clk->afe_clk_id = q6afe_clks[i].afe_clk_id; - clk->rate = q6afe_clks[i].rate; - clk->hw.init = &init; - - if (clk->rate) - init.ops = &clk_q6afe_ops; - else - init.ops = &clk_vote_q6afe_ops; - - cc->clks[id] = clk; - - ret = devm_clk_hw_register(dev, &clk->hw); - if (ret) - return ret; - } - - ret = devm_of_clk_add_hw_provider(dev, q6afe_of_clk_hw_get, cc); - if (ret) - return ret; - - dev_set_drvdata(dev, cc); - - return 0; -} +static const struct q6dsp_clk_desc q6dsp_clk_q6afe = { + .clks = q6afe_clks, + .num_clks = ARRAY_SIZE(q6afe_clks), + .lpass_set_clk = q6afe_set_lpass_clock, + .lpass_vote_clk = q6afe_vote_lpass_core_hw, + .lpass_unvote_clk = q6afe_unvote_lpass_core_hw, +}; #ifdef CONFIG_OF static const struct of_device_id q6afe_clock_device_id[] = { - { .compatible = "qcom,q6afe-clocks" }, + { .compatible = "qcom,q6afe-clocks", .data = &q6dsp_clk_q6afe }, {}, }; MODULE_DEVICE_TABLE(of, q6afe_clock_device_id); @@ -268,7 +111,7 @@ static struct platform_driver q6afe_clock_platform_driver = { .name = "q6afe-clock", .of_match_table = of_match_ptr(q6afe_clock_device_id), }, - .probe = q6afe_clock_dev_probe, + .probe = q6dsp_clock_dev_probe, }; module_platform_driver(q6afe_clock_platform_driver); diff --git a/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.c b/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.c new file mode 100644 index 000000000000..d3b6c9a4bf2b --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2020, Linaro Limited + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "q6dsp-audio-clocks.h" + +#define Q6DSP_MAX_CLK_ID 104 +#define Q6DSP_LPASS_CLK_ROOT_DEFAULT 0 + + +struct q6dsp_clk { + struct device *dev; + int q6dsp_clk_id; + int attributes; + int rate; + uint32_t handle; + struct clk_hw hw; +}; + +#define to_q6dsp_clk(_hw) container_of(_hw, struct q6dsp_clk, hw) + +struct q6dsp_cc { + struct device *dev; + struct q6dsp_clk *clks[Q6DSP_MAX_CLK_ID]; + const struct q6dsp_clk_desc *desc; +}; + +static int clk_q6dsp_prepare(struct clk_hw *hw) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + struct q6dsp_cc *cc = dev_get_drvdata(clk->dev); + + return cc->desc->lpass_set_clk(clk->dev, clk->q6dsp_clk_id, clk->attributes, + Q6DSP_LPASS_CLK_ROOT_DEFAULT, clk->rate); +} + +static void clk_q6dsp_unprepare(struct clk_hw *hw) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + struct q6dsp_cc *cc = dev_get_drvdata(clk->dev); + + cc->desc->lpass_set_clk(clk->dev, clk->q6dsp_clk_id, clk->attributes, + Q6DSP_LPASS_CLK_ROOT_DEFAULT, 0); +} + +static int clk_q6dsp_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + + clk->rate = rate; + + return 0; +} + +static unsigned long clk_q6dsp_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + + return clk->rate; +} + +static long clk_q6dsp_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + return rate; +} + +static const struct clk_ops clk_q6dsp_ops = { + .prepare = clk_q6dsp_prepare, + .unprepare = clk_q6dsp_unprepare, + .set_rate = clk_q6dsp_set_rate, + .round_rate = clk_q6dsp_round_rate, + .recalc_rate = clk_q6dsp_recalc_rate, +}; + +static int clk_vote_q6dsp_block(struct clk_hw *hw) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + struct q6dsp_cc *cc = dev_get_drvdata(clk->dev); + + return cc->desc->lpass_vote_clk(clk->dev, clk->q6dsp_clk_id, + clk_hw_get_name(&clk->hw), &clk->handle); +} + +static void clk_unvote_q6dsp_block(struct clk_hw *hw) +{ + struct q6dsp_clk *clk = to_q6dsp_clk(hw); + struct q6dsp_cc *cc = dev_get_drvdata(clk->dev); + + cc->desc->lpass_unvote_clk(clk->dev, clk->q6dsp_clk_id, clk->handle); +} + +static const struct clk_ops clk_vote_q6dsp_ops = { + .prepare = clk_vote_q6dsp_block, + .unprepare = clk_unvote_q6dsp_block, +}; + + +static struct clk_hw *q6dsp_of_clk_hw_get(struct of_phandle_args *clkspec, + void *data) +{ + struct q6dsp_cc *cc = data; + unsigned int idx = clkspec->args[0]; + unsigned int attr = clkspec->args[1]; + + if (idx >= Q6DSP_MAX_CLK_ID || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) { + dev_err(cc->dev, "Invalid clk specifier (%d, %d)\n", idx, attr); + return ERR_PTR(-EINVAL); + } + + if (cc->clks[idx]) { + cc->clks[idx]->attributes = attr; + return &cc->clks[idx]->hw; + } + + return ERR_PTR(-ENOENT); +} + +int q6dsp_clock_dev_probe(struct platform_device *pdev) +{ + struct q6dsp_cc *cc; + struct device *dev = &pdev->dev; + const struct q6dsp_clk_init *q6dsp_clks; + const struct q6dsp_clk_desc *desc; + int i, ret; + + cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL); + if (!cc) + return -ENOMEM; + + desc = of_device_get_match_data(&pdev->dev); + if (!desc) + return -EINVAL; + + cc->desc = desc; + cc->dev = dev; + q6dsp_clks = desc->clks; + + for (i = 0; i < desc->num_clks; i++) { + unsigned int id = q6dsp_clks[i].clk_id; + struct clk_init_data init = { + .name = q6dsp_clks[i].name, + }; + struct q6dsp_clk *clk; + + clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); + if (!clk) + return -ENOMEM; + + clk->dev = dev; + clk->q6dsp_clk_id = q6dsp_clks[i].q6dsp_clk_id; + clk->rate = q6dsp_clks[i].rate; + clk->hw.init = &init; + + if (clk->rate) + init.ops = &clk_q6dsp_ops; + else + init.ops = &clk_vote_q6dsp_ops; + + cc->clks[id] = clk; + + ret = devm_clk_hw_register(dev, &clk->hw); + if (ret) + return ret; + } + + ret = devm_of_clk_add_hw_provider(dev, q6dsp_of_clk_hw_get, cc); + if (ret) + return ret; + + dev_set_drvdata(dev, cc); + + return 0; +} diff --git a/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.h b/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.h new file mode 100644 index 000000000000..3770d81f2bd6 --- /dev/null +++ b/sound/soc/qcom/qdsp6/q6dsp-audio-clocks.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __Q6DSP_AUDIO_CLOCKS_H__ +#define __Q6DSP_AUDIO_CLOCKS_H__ + +struct q6dsp_clk_init { + int clk_id; + int q6dsp_clk_id; + char *name; + int rate; +}; + +#define Q6DSP_VOTE_CLK(id, blkid, n) { \ + .clk_id = id, \ + .q6dsp_clk_id = blkid, \ + .name = n, \ + } + +struct q6dsp_clk_desc { + const struct q6dsp_clk_init *clks; + size_t num_clks; + int (*lpass_set_clk)(struct device *dev, int clk_id, int attr, + int root_clk, unsigned int freq); + int (*lpass_vote_clk)(struct device *dev, uint32_t hid, const char *n, uint32_t *h); + int (*lpass_unvote_clk)(struct device *dev, uint32_t hid, uint32_t h); +}; + +int q6dsp_clock_dev_probe(struct platform_device *pdev); + +#endif /* __Q6DSP_AUDIO_CLOCKS_H__ */