From patchwork Mon May 23 13:28:39 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859030 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 B53F3C433EF for ; Mon, 23 May 2022 13:32:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=VoCnBLNh5pEmx6eQ3umg4+wz5GtjSxRKjC7O47jdhb4=; b=p/cAeGoxND6BXs 3qWsg0SQk6XJiLM+xrPYTApuc3xOa8hk6YFqeNfYJkTc/JHW7sY+sPZVGG/YWG/+GDlC10uQlF9D4 gQOqUapRvqRCRiZykzlQEYI9PTcToj0EmMlNsnlrWO/USNquUBpSIHIZ9/Tte6lKwqxdYcvQeu1ne JHZ5D++UrVO165BrT7QFulOPkPPnTzpvwosrIMGcqM9T3/tAu8NpyYZMLL3caPQEpH1ycnGmzzBvK 8IuNQMaY2yNzaF9XVIjgiI/NaPSCoXyRYCu3gfi16NSv2pYsRN3lDk7S5XTx+Bz4kb6eGKgc4X98n eVDqeDgNG4aWANOZm+ng==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt89F-004Pwu-QQ; Mon, 23 May 2022 13:31:02 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt87a-004P5u-4R; Mon, 23 May 2022 13:29:19 +0000 X-UUID: cadce5eb3ded486498323f457a419db3-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:3554a649-f37e-4483-b77d-3953db52a1f9, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:2a19b09, CLOUDID:3cf93de3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: cadce5eb3ded486498323f457a419db3-20220523 Received: from mtkcas67.mediatek.inc [(172.29.193.45)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1068637182; Mon, 23 May 2022 06:29:05 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:03 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:01 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:01 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 01/20] ASoC: mediatek: mt6366: support for mt6366 codec Date: Mon, 23 May 2022 21:28:39 +0800 Message-ID: <20220523132858.22166-2-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_062918_243897_F7061202 X-CRM114-Status: GOOD ( 10.98 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Mt6366 is a new version of mt6358, and they are same about audio part. So we can reuse the driver of mt6358 that add a new compatible string inside of the mt6358 driver. Signed-off-by: Jiaxin Yu --- sound/soc/codecs/mt6358.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 9b263a9a669d..1fdd2f8cf877 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -2477,6 +2477,7 @@ static int mt6358_platform_driver_probe(struct platform_device *pdev) static const struct of_device_id mt6358_of_match[] = { {.compatible = "mediatek,mt6358-sound",}, + {.compatible = "mediatek,mt6366-sound",}, {} }; MODULE_DEVICE_TABLE(of, mt6358_of_match); From patchwork Mon May 23 13:28:40 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859029 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 E3B6CC433F5 for ; Mon, 23 May 2022 13:31:40 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=ThyBRmqYu2QOeuGLR1mPOL5eZH/txlobTmHaftNGgcc=; b=cKptucsoWkVY34 h78sk+p3ig1cEt6kTbj6WyxqhDhhjfE3TZNLywZZ+HfoOheeQZOLCN6GqrPgh1iQRzRCGdULKpbvv 4eVg4jRW7OTv8HzleHhfRPYw+rxKoUU9/8K5t8uADp016EvYuAo5Gh+wrOph5D7Hq5Ps3rVSj3afG F6qPyZ7ark++IbfDCNlp1zVxbeSWXKx1PV2zsKGC1UhSMcY+uUpg/Q2MX3Sqv2U+KJGNKlliAX9fN zchoml/iRhVKfl99/0XGkfo+LqAx7AfH0/cCas7dhM8H/aRNSokerjBLgNg5AgLES4lOh2+GjVBrJ hVlBGqpKM8C+VU7sFcIA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt88l-004Pg3-UX; Mon, 23 May 2022 13:30:32 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt87a-004P58-46; Mon, 23 May 2022 13:29:19 +0000 X-UUID: be68f2dde89042f8a1d675f826ea460b-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:2da1ab01-c6c9-4c0f-a433-d5658622674e, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:2a19b09, CLOUDID:3bf93de3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: be68f2dde89042f8a1d675f826ea460b-20220523 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1604979621; Mon, 23 May 2022 06:29:06 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:04 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:03 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:02 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu , Rob Herring Subject: [PATCH v5 02/20] dt-bindings: mediatek: mt6358: add new compatible for using mt6366 Date: Mon, 23 May 2022 21:28:40 +0800 Message-ID: <20220523132858.22166-3-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_062918_273683_A66D8CF0 X-CRM114-Status: UNSURE ( 9.35 ) X-CRM114-Notice: Please train this message. X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add new compatible string "mediatek,mt6366-sound" for using mt6366. Signed-off-by: Jiaxin Yu Acked-by: Rob Herring --- Documentation/devicetree/bindings/sound/mt6358.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/mt6358.txt b/Documentation/devicetree/bindings/sound/mt6358.txt index 59a73ffdf1d3..fbe9e55c68f5 100644 --- a/Documentation/devicetree/bindings/sound/mt6358.txt +++ b/Documentation/devicetree/bindings/sound/mt6358.txt @@ -7,7 +7,9 @@ Must be a child node of PMIC wrapper. Required properties: -- compatible : "mediatek,mt6358-sound". +- compatible - "string" - One of: + "mediatek,mt6358-sound" + "mediatek,mt6366-sound" - Avdd-supply : power source of AVDD Optional properties: From patchwork Mon May 23 13:28:41 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859045 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 32D77C433EF for ; Mon, 23 May 2022 13:32:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=BJwe44H329jnA+NSTraBzT1VZWlCVn2ay3rJBzdHWVE=; b=HSKGuoqt0H8NNW Hv/fC+RXcWdGlgE+Dsi0534GiOOQeNWpsWj2mFy3/r6LSISxJyQ7DA9AMlb5tUHArSwYkO7X3KnQY VQGkw+U2L0d5pijROqjv1Fu97BxufzU7fHAlRut8VNE65KO5uAgMFHyy+JCjgcI/8OHhTL8wY30Jf 5jBVztWWSYIb28MYJ1KCwjn02sQl3FIsw+4WYlzN5VDUAeHXti3WXnuelOj0Rn9V3rZEdAk7gm7pW +krdM78FdK0JCJOQe+1nICaz99CQE+PMvGnEVIjKegXj9pLSBjrrsBeV3aMwF3dH6McIG3HMtU84n HwHDv2yur5yVFc4ssZbw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt89a-004Q8n-B0; Mon, 23 May 2022 13:31:23 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt87a-004P5E-47; Mon, 23 May 2022 13:29:21 +0000 X-UUID: da5a682a5832496abd194153554948ed-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:0c18d3d5-87e4-4e2f-9beb-360975b5ca3a, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:-5 X-CID-META: VersionHash:2a19b09, CLOUDID:3cf14d7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: da5a682a5832496abd194153554948ed-20220523 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1878826690; Mon, 23 May 2022 06:29:06 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:05 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:04 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:03 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 03/20] ASoC: mediatek: mt8186: support audsys clock control Date: Mon, 23 May 2022 21:28:41 +0800 Message-ID: <20220523132858.22166-4-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_062918_238602_E2F3F416 X-CRM114-Status: GOOD ( 16.61 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 audio cg control. Audio clock gates are registered to CCF for reference count and clock parent management. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- sound/soc/mediatek/mt8186/mt8186-audsys-clk.c | 150 ++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-audsys-clk.h | 15 ++ .../soc/mediatek/mt8186/mt8186-audsys-clkid.h | 45 ++++++ 3 files changed, 210 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clk.h create mode 100644 sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c new file mode 100644 index 000000000000..578969ca91c8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-audsys-clk.h -- Mediatek 8186 audsys clock control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include +#include "mt8186-afe-common.h" +#include "mt8186-audsys-clk.h" +#include "mt8186-audsys-clkid.h" +#include "mt8186-reg.h" + +struct afe_gate { + int id; + const char *name; + const char *parent_name; + int reg; + u8 bit; + const struct clk_ops *ops; + unsigned long flags; + u8 cg_flags; +}; + +#define GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, _flags, _cgflags) {\ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .reg = _reg, \ + .bit = _bit, \ + .flags = _flags, \ + .cg_flags = _cgflags, \ + } + +#define GATE_AFE(_id, _name, _parent, _reg, _bit) \ + GATE_AFE_FLAGS(_id, _name, _parent, _reg, _bit, \ + CLK_SET_RATE_PARENT, CLK_GATE_SET_TO_DISABLE) + +#define GATE_AUD0(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON0, _bit) + +#define GATE_AUD1(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON1, _bit) + +#define GATE_AUD2(_id, _name, _parent, _bit) \ + GATE_AFE(_id, _name, _parent, AUDIO_TOP_CON2, _bit) + +static const struct afe_gate aud_clks[CLK_AUD_NR_CLK] = { + /* AUD0 */ + GATE_AUD0(CLK_AUD_AFE, "aud_afe_clk", "top_audio", 2), + GATE_AUD0(CLK_AUD_22M, "aud_apll22m_clk", "top_aud_engen1", 8), + GATE_AUD0(CLK_AUD_24M, "aud_apll24m_clk", "top_aud_engen2", 9), + GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner_clk", "top_aud_engen2", 18), + GATE_AUD0(CLK_AUD_APLL_TUNER, "aud_apll_tuner_clk", "top_aud_engen1", 19), + GATE_AUD0(CLK_AUD_TDM, "aud_tdm_clk", "top_aud_1", 20), + GATE_AUD0(CLK_AUD_ADC, "aud_adc_clk", "top_audio", 24), + GATE_AUD0(CLK_AUD_DAC, "aud_dac_clk", "top_audio", 25), + GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis_clk", "top_audio", 26), + GATE_AUD0(CLK_AUD_TML, "aud_tml_clk", "top_audio", 27), + GATE_AUD0(CLK_AUD_NLE, "aud_nle_clk", "top_audio", 28), + + /* AUD1 */ + GATE_AUD1(CLK_AUD_I2S1_BCLK, "aud_i2s1_bclk", "top_audio", 4), + GATE_AUD1(CLK_AUD_I2S2_BCLK, "aud_i2s2_bclk", "top_audio", 5), + GATE_AUD1(CLK_AUD_I2S3_BCLK, "aud_i2s3_bclk", "top_audio", 6), + GATE_AUD1(CLK_AUD_I2S4_BCLK, "aud_i2s4_bclk", "top_audio", 7), + GATE_AUD1(CLK_AUD_CONNSYS_I2S_ASRC, "aud_connsys_i2s_asrc", "top_audio", 12), + GATE_AUD1(CLK_AUD_GENERAL1_ASRC, "aud_general1_asrc", "top_audio", 13), + GATE_AUD1(CLK_AUD_GENERAL2_ASRC, "aud_general2_asrc", "top_audio", 14), + GATE_AUD1(CLK_AUD_DAC_HIRES, "aud_dac_hires_clk", "top_audio_h", 15), + GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires_clk", "top_audio_h", 16), + GATE_AUD1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", "top_audio_h", 17), + GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "top_audio", 20), + GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "top_audio_h", 21), + GATE_AUD1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "top_audio", 28), + GATE_AUD1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", "top_audio", 29), + GATE_AUD1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", "top_audio", 30), + GATE_AUD1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", "top_audio_h", 31), + + /* AUD2 */ + GATE_AUD2(CLK_AUD_ETDM_IN1_BCLK, "aud_etdm_in1_bclk", "top_audio", 23), + GATE_AUD2(CLK_AUD_ETDM_OUT1_BCLK, "aud_etdm_out1_bclk", "top_audio", 24), +}; + +int mt8186_audsys_clk_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + afe_priv->lookup = devm_kcalloc(afe->dev, CLK_AUD_NR_CLK, + sizeof(*afe_priv->lookup), + GFP_KERNEL); + + if (!afe_priv->lookup) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + const struct afe_gate *gate = &aud_clks[i]; + + clk = clk_register_gate(afe->dev, gate->name, gate->parent_name, + gate->flags, afe->base_addr + gate->reg, + gate->bit, gate->cg_flags, NULL); + + if (IS_ERR(clk)) { + dev_err(afe->dev, "Failed to register clk %s: %ld\n", + gate->name, PTR_ERR(clk)); + continue; + } + + /* add clk_lookup for devm_clk_get(SND_SOC_DAPM_CLOCK_SUPPLY) */ + cl = kzalloc(sizeof(*cl), GFP_KERNEL); + if (!cl) + return -ENOMEM; + + cl->clk = clk; + cl->con_id = gate->name; + cl->dev_id = dev_name(afe->dev); + clkdev_add(cl); + + afe_priv->lookup[i] = cl; + } + + return 0; +} + +void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct clk *clk; + struct clk_lookup *cl; + int i; + + if (!afe_priv) + return; + + for (i = 0; i < CLK_AUD_NR_CLK; i++) { + cl = afe_priv->lookup[i]; + if (!cl) + continue; + + clk = cl->clk; + clk_unregister_gate(clk); + + clkdev_drop(cl); + } +} diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h new file mode 100644 index 000000000000..b8d6a06e11e8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clk.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-audsys-clk.h -- Mediatek 8186 audsys clock definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Trevor Wu + */ + +#ifndef _MT8186_AUDSYS_CLK_H_ +#define _MT8186_AUDSYS_CLK_H_ + +int mt8186_audsys_clk_register(struct mtk_base_afe *afe); +void mt8186_audsys_clk_unregister(struct mtk_base_afe *afe); + +#endif diff --git a/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h new file mode 100644 index 000000000000..3ce5937c1823 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-audsys-clkid.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-audsys-clkid.h -- Mediatek 8186 audsys clock id definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AUDSYS_CLKID_H_ +#define _MT8186_AUDSYS_CLKID_H_ + +enum{ + CLK_AUD_AFE, + CLK_AUD_22M, + CLK_AUD_24M, + CLK_AUD_APLL2_TUNER, + CLK_AUD_APLL_TUNER, + CLK_AUD_TDM, + CLK_AUD_ADC, + CLK_AUD_DAC, + CLK_AUD_DAC_PREDIS, + CLK_AUD_TML, + CLK_AUD_NLE, + CLK_AUD_I2S1_BCLK, + CLK_AUD_I2S2_BCLK, + CLK_AUD_I2S3_BCLK, + CLK_AUD_I2S4_BCLK, + CLK_AUD_CONNSYS_I2S_ASRC, + CLK_AUD_GENERAL1_ASRC, + CLK_AUD_GENERAL2_ASRC, + CLK_AUD_DAC_HIRES, + CLK_AUD_ADC_HIRES, + CLK_AUD_ADC_HIRES_TML, + CLK_AUD_ADDA6_ADC, + CLK_AUD_ADDA6_ADC_HIRES, + CLK_AUD_3RD_DAC, + CLK_AUD_3RD_DAC_PREDIS, + CLK_AUD_3RD_DAC_TML, + CLK_AUD_3RD_DAC_HIRES, + CLK_AUD_ETDM_IN1_BCLK, + CLK_AUD_ETDM_OUT1_BCLK, + CLK_AUD_NR_CLK, +}; + +#endif From patchwork Mon May 23 13:28:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859062 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 2D58AC433EF for ; Mon, 23 May 2022 13:42:02 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=E+ntb3HX1prK6QTQzxsIej902XvERui9O9+ozKRIMBQ=; b=BeBAb2MINGXEyD jwcpXVbftHCoGmt0kTdEvxNzE4vd87mjUaTmt4H/71HM57aFThGeEmMZjuN08TEXjHkyeAB/HYgzJ Rdtbyk3/o/7yXpLJYBZ1k6AeQEV3B6cfeQtGMYFBFYqBtRItC0A0RN3/ofX02u5dok+acRa8h+9oX LxxcVBZ/CDwlhpZc0KGCnj7yKreBX7y2CRgNxYPDNtGNcCppxrmUZ8nUYRsEA6LR5Bw5BY1hitTkI fKCiR+L0uI5zusFZEaGlj8fF/wwcLYjtrszAwTHbShwPZYbfGNVKIB1XA4HmxrF+KvoyD1weYgOKe ejWx8EhWTyNyDSelGIBQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8IA-004T3S-Bt; Mon, 23 May 2022 13:40:14 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HD-004SgT-A9; Mon, 23 May 2022 13:39:20 +0000 X-UUID: 565489a68bde49f2befafae9c9baeffc-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:32d778b1-a8b8-4e04-b8e6-619b5cbe12fe, OB:0, LO B:0,IP:0,URL:5,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:5 X-CID-META: VersionHash:2a19b09, CLOUDID:8b204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: 565489a68bde49f2befafae9c9baeffc-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1461416464; Mon, 23 May 2022 06:39:08 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:06 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:05 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:04 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 04/20] ASoC: mediatek: mt8186: support adda in platform driver Date: Mon, 23 May 2022 21:28:42 +0800 Message-ID: <20220523132858.22166-5-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063915_404266_F4684005 X-CRM114-Status: GOOD ( 19.67 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 adda dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- sound/soc/mediatek/mt8186/mt8186-dai-adda.c | 873 ++++++++++++++++++++ 1 file changed, 873 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-adda.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-adda.c b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c new file mode 100644 index 000000000000..c66861fd197d --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-adda.c @@ -0,0 +1,873 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI ADDA Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +enum { + UL_IIR_SW = 0, + UL_IIR_5HZ, + UL_IIR_10HZ, + UL_IIR_25HZ, + UL_IIR_50HZ, + UL_IIR_75HZ, +}; + +enum { + AUDIO_SDM_LEVEL_MUTE = 0, + AUDIO_SDM_LEVEL_NORMAL = 0x1d, + /* if you change level normal */ + /* you need to change formula of hp impedance and dc trim too */ +}; + +enum { + AUDIO_SDM_2ND = 0, + AUDIO_SDM_3RD, +}; + +enum { + DELAY_DATA_MISO1 = 0, + DELAY_DATA_MISO2, +}; + +enum { + MTK_AFE_ADDA_DL_RATE_8K = 0, + MTK_AFE_ADDA_DL_RATE_11K = 1, + MTK_AFE_ADDA_DL_RATE_12K = 2, + MTK_AFE_ADDA_DL_RATE_16K = 3, + MTK_AFE_ADDA_DL_RATE_22K = 4, + MTK_AFE_ADDA_DL_RATE_24K = 5, + MTK_AFE_ADDA_DL_RATE_32K = 6, + MTK_AFE_ADDA_DL_RATE_44K = 7, + MTK_AFE_ADDA_DL_RATE_48K = 8, + MTK_AFE_ADDA_DL_RATE_96K = 9, + MTK_AFE_ADDA_DL_RATE_192K = 10, +}; + +enum { + MTK_AFE_ADDA_UL_RATE_8K = 0, + MTK_AFE_ADDA_UL_RATE_16K = 1, + MTK_AFE_ADDA_UL_RATE_32K = 2, + MTK_AFE_ADDA_UL_RATE_48K = 3, + MTK_AFE_ADDA_UL_RATE_96K = 4, + MTK_AFE_ADDA_UL_RATE_192K = 5, + MTK_AFE_ADDA_UL_RATE_48K_HD = 6, +}; + +#define SDM_AUTO_RESET_THRESHOLD 0x190000 + +struct mtk_afe_adda_priv { + int dl_rate; + int ul_rate; +}; + +static struct mtk_afe_adda_priv *get_adda_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id; + + if (strncmp(name, "aud_dac_hires_clk", 7) == 0 || + strncmp(name, "aud_adc_hires_clk", 7) == 0) + dai_id = MT8186_DAI_ADDA; + else + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +static unsigned int adda_dl_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_DL_RATE_8K; + case 11025: + return MTK_AFE_ADDA_DL_RATE_11K; + case 12000: + return MTK_AFE_ADDA_DL_RATE_12K; + case 16000: + return MTK_AFE_ADDA_DL_RATE_16K; + case 22050: + return MTK_AFE_ADDA_DL_RATE_22K; + case 24000: + return MTK_AFE_ADDA_DL_RATE_24K; + case 32000: + return MTK_AFE_ADDA_DL_RATE_32K; + case 44100: + return MTK_AFE_ADDA_DL_RATE_44K; + case 48000: + return MTK_AFE_ADDA_DL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_DL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_DL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + } + + return MTK_AFE_ADDA_DL_RATE_48K; +} + +static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe, + unsigned int rate) +{ + switch (rate) { + case 8000: + return MTK_AFE_ADDA_UL_RATE_8K; + case 16000: + return MTK_AFE_ADDA_UL_RATE_16K; + case 32000: + return MTK_AFE_ADDA_UL_RATE_32K; + case 48000: + return MTK_AFE_ADDA_UL_RATE_48K; + case 96000: + return MTK_AFE_ADDA_UL_RATE_96K; + case 192000: + return MTK_AFE_ADDA_UL_RATE_192K; + default: + dev_info(afe->dev, "%s(), rate %d invalid, use 48kHz!!!\n", + __func__, rate); + } + + return MTK_AFE_ADDA_UL_RATE_48K; +} + +/* dai component */ +static const struct snd_kcontrol_new mtk_adda_dl_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN3, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN3, I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN3, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN3, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN3_1, I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN3_1, I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN3_1, I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN3_1, I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN3, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN3, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN3, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN3, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH1 Switch", AFE_CONN3, + I_PCM_2_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN3_1, + I_SRC_1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH1 Switch", AFE_CONN3_1, + I_SRC_2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_adda_dl_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN4, I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN4, I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN4, I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN4, I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN4, I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN4, I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN4, I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN4_1, I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN4_1, I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN4_1, I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN4_1, I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN4, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN4, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN4, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN4, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN4, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN4_1, + I_SRC_1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_2_OUT_CH2 Switch", AFE_CONN4_1, + I_SRC_2_OUT_CH2, 1, 0), +}; + +enum { + SUPPLY_SEQ_ADDA_AFE_ON, + SUPPLY_SEQ_ADDA_DL_ON, + SUPPLY_SEQ_ADDA_AUD_PAD_TOP, + SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SUPPLY_SEQ_ADDA_FIFO, + SUPPLY_SEQ_ADDA_AP_DMIC, + SUPPLY_SEQ_ADDA_UL_ON, +}; + +static int mtk_adda_ul_src_dmic(struct mtk_base_afe *afe, int id) +{ + unsigned int reg; + + switch (id) { + case MT8186_DAI_ADDA: + case MT8186_DAI_AP_DMIC: + reg = AFE_ADDA_UL_SRC_CON0; + break; + default: + return -EINVAL; + } + + /* dmic mode, 3.25M*/ + regmap_update_bits(afe->regmap, reg, + DIGMIC_3P25M_1P625M_SEL_MASK_SFT, 0); + regmap_update_bits(afe->regmap, reg, + DMIC_LOW_POWER_CTL_MASK_SFT, 0); + + /* turn on dmic, ch1, ch2 */ + regmap_update_bits(afe->regmap, reg, + UL_SDM_3_LEVEL_MASK_SFT, + BIT(UL_SDM_3_LEVEL_SFT)); + regmap_update_bits(afe->regmap, reg, + UL_MODE_3P25M_CH1_CTL_MASK_SFT, + BIT(UL_MODE_3P25M_CH1_CTL_SFT)); + regmap_update_bits(afe->regmap, reg, + UL_MODE_3P25M_CH2_CTL_MASK_SFT, + BIT(UL_MODE_3P25M_CH2_CTL_SFT)); + + return 0; +} + +static int mtk_adda_ul_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int mtkaif_dmic = afe_priv->mtkaif_dmic; + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x, mtkaif_dmic %d\n", + __func__, w->name, event, mtkaif_dmic); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 1); + + /* update setting to dmic */ + if (mtkaif_dmic) { + /* mtkaif_rxif_data_mode = 1, dmic */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, + 0x1, 0x1); + + /* dmic mode, 3.25M*/ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, + MTKAIF_RXIF_VOICE_MODE_MASK_SFT, + 0x0); + mtk_adda_ul_src_dmic(afe, MT8186_DAI_ADDA); + } + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 1); + + /* reset dmic */ + afe_priv->mtkaif_dmic = 0; + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_pad_top_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x39); + else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31); + else + regmap_write(afe->regmap, AFE_AUD_PAD_TOP, 0x31); + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_mtkaif_cfg_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int delay_data; + int delay_cycle; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2_CLK_P2) { + /* set protocol 2 */ + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000); + /* mtkaif_rxif_clkinv_adc inverse */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_CFG0, + MTKAIF_RXIF_CLKINV_ADC_MASK_SFT, + BIT(MTKAIF_RXIF_CLKINV_ADC_SFT)); + + if (strcmp(w->name, "ADDA_MTKAIF_CFG") == 0) { + if (afe_priv->mtkaif_chosen_phase[0] < 0 && + afe_priv->mtkaif_chosen_phase[1] < 0) { + dev_err(afe->dev, + "%s(), calib fail mtkaif_chosen_phase[0/1]:%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1]); + break; + } + + if (afe_priv->mtkaif_chosen_phase[0] < 0 || + afe_priv->mtkaif_chosen_phase[1] < 0) { + dev_err(afe->dev, + "%s(), skip dealy setting mtkaif_chosen_phase[0/1]:%d/%d\n", + __func__, + afe_priv->mtkaif_chosen_phase[0], + afe_priv->mtkaif_chosen_phase[1]); + break; + } + } + + /* set delay for ch12 */ + if (afe_priv->mtkaif_phase_cycle[0] >= + afe_priv->mtkaif_phase_cycle[1]) { + delay_data = DELAY_DATA_MISO1; + delay_cycle = afe_priv->mtkaif_phase_cycle[0] - + afe_priv->mtkaif_phase_cycle[1]; + } else { + delay_data = DELAY_DATA_MISO2; + delay_cycle = afe_priv->mtkaif_phase_cycle[1] - + afe_priv->mtkaif_phase_cycle[0]; + } + + regmap_update_bits(afe->regmap, + AFE_ADDA_MTKAIF_RX_CFG2, + MTKAIF_RXIF_DELAY_DATA_MASK_SFT, + delay_data << + MTKAIF_RXIF_DELAY_DATA_SFT); + + regmap_update_bits(afe->regmap, + AFE_ADDA_MTKAIF_RX_CFG2, + MTKAIF_RXIF_DELAY_CYCLE_MASK_SFT, + delay_cycle << + MTKAIF_RXIF_DELAY_CYCLE_SFT); + + } else if (afe_priv->mtkaif_protocol == MTKAIF_PROTOCOL_2) { + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0x10000); + } else { + regmap_write(afe->regmap, AFE_ADDA_MTKAIF_CFG0, 0); + } + + break; + default: + break; + } + + return 0; +} + +static int mtk_adda_dl_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_ADDA, 0); + break; + case SND_SOC_DAPM_POST_PMD: + /* should delayed 1/fs(smallest is 8k) = 125us before afe off */ + usleep_range(125, 135); + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_ADDA, 0); + break; + default: + break; + } + + return 0; +} + +static int mt8186_adda_dmic_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + ucontrol->value.integer.value[0] = afe_priv->mtkaif_dmic; + + return 0; +} + +static int mt8186_adda_dmic_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dmic_on; + + dmic_on = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, dmic_on %d\n", + __func__, kcontrol->id.name, dmic_on); + + if (afe_priv->mtkaif_dmic == dmic_on) + return 0; + + afe_priv->mtkaif_dmic = dmic_on; + + return 1; +} + +static const struct snd_kcontrol_new mtk_adda_controls[] = { + SOC_SINGLE("ADDA_DL_GAIN", AFE_ADDA_DL_SRC2_CON1, + DL_2_GAIN_CTL_PRE_SFT, DL_2_GAIN_CTL_PRE_MASK, 0), + SOC_SINGLE_BOOL_EXT("MTKAIF_DMIC Switch", 0, + mt8186_adda_dmic_get, mt8186_adda_dmic_set), +}; + +/* ADDA UL MUX */ +enum { + ADDA_UL_MUX_MTKAIF = 0, + ADDA_UL_MUX_AP_DMIC, + ADDA_UL_MUX_MASK = 0x1, +}; + +static const char * const adda_ul_mux_map[] = { + "MTKAIF", "AP_DMIC" +}; + +static int adda_ul_map_value[] = { + ADDA_UL_MUX_MTKAIF, + ADDA_UL_MUX_AP_DMIC, +}; + +static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum, + SND_SOC_NOPM, + 0, + ADDA_UL_MUX_MASK, + adda_ul_mux_map, + adda_ul_map_value); + +static const struct snd_kcontrol_new adda_ul_mux_control = + SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("ADDA_DL_CH1", SND_SOC_NOPM, 0, 0, + mtk_adda_dl_ch1_mix, + ARRAY_SIZE(mtk_adda_dl_ch1_mix)), + SND_SOC_DAPM_MIXER("ADDA_DL_CH2", SND_SOC_NOPM, 0, 0, + mtk_adda_dl_ch2_mix, + ARRAY_SIZE(mtk_adda_dl_ch2_mix)), + + SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON, + AFE_ADDA_UL_DL_CON0, ADDA_AFE_ON_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ADDA Playback Enable", SUPPLY_SEQ_ADDA_DL_ON, + AFE_ADDA_DL_SRC2_CON0, + DL_2_SRC_ON_CTL_PRE_SFT, 0, + mtk_adda_dl_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON, + AFE_ADDA_UL_SRC_CON0, + UL_SRC_ON_CTL_SFT, 0, + mtk_adda_ul_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S("AUD_PAD_TOP", SUPPLY_SEQ_ADDA_AUD_PAD_TOP, + 0, 0, 0, + mtk_adda_pad_top_event, + SND_SOC_DAPM_PRE_PMU), + SND_SOC_DAPM_SUPPLY_S("ADDA_MTKAIF_CFG", SUPPLY_SEQ_ADDA_MTKAIF_CFG, + SND_SOC_NOPM, 0, 0, + mtk_adda_mtkaif_cfg_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC, + AFE_ADDA_UL_SRC_CON0, + UL_AP_DMIC_ON_SFT, 0, + NULL, 0), + + SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO, + AFE_ADDA_UL_DL_CON0, + AFE_ADDA_FIFO_AUTO_RST_SFT, 1, + NULL, 0), + + SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0, + &adda_ul_mux_control), + + SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"), + + /* clock */ + SND_SOC_DAPM_CLOCK_SUPPLY("top_mux_audio_h"), + + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_hires_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_dac_predis_clk"), + + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_clk"), + SND_SOC_DAPM_CLOCK_SUPPLY("aud_adc_hires_clk"), +}; + +#define HIRES_THRESHOLD 48000 +static int mtk_afe_dac_hires_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_adda_priv *adda_priv; + + adda_priv = get_adda_priv_by_name(afe, w->name); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return 0; + } + + return (adda_priv->dl_rate > HIRES_THRESHOLD) ? 1 : 0; +} + +static int mtk_afe_adc_hires_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_adda_priv *adda_priv; + + adda_priv = get_adda_priv_by_name(afe, w->name); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return 0; + } + + return (adda_priv->ul_rate > HIRES_THRESHOLD) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = { + /* playback */ + {"ADDA_DL_CH1", "DL1_CH1 Switch", "DL1"}, + {"ADDA_DL_CH2", "DL1_CH1 Switch", "DL1"}, + {"ADDA_DL_CH2", "DL1_CH2 Switch", "DL1"}, + + {"ADDA_DL_CH1", "DL12_CH1 Switch", "DL12"}, + {"ADDA_DL_CH2", "DL12_CH2 Switch", "DL12"}, + + {"ADDA_DL_CH1", "DL6_CH1 Switch", "DL6"}, + {"ADDA_DL_CH2", "DL6_CH2 Switch", "DL6"}, + + {"ADDA_DL_CH1", "DL8_CH1 Switch", "DL8"}, + {"ADDA_DL_CH2", "DL8_CH2 Switch", "DL8"}, + + {"ADDA_DL_CH1", "DL2_CH1 Switch", "DL2"}, + {"ADDA_DL_CH2", "DL2_CH1 Switch", "DL2"}, + {"ADDA_DL_CH2", "DL2_CH2 Switch", "DL2"}, + + {"ADDA_DL_CH1", "DL3_CH1 Switch", "DL3"}, + {"ADDA_DL_CH2", "DL3_CH1 Switch", "DL3"}, + {"ADDA_DL_CH2", "DL3_CH2 Switch", "DL3"}, + + {"ADDA_DL_CH1", "DL4_CH1 Switch", "DL4"}, + {"ADDA_DL_CH2", "DL4_CH2 Switch", "DL4"}, + + {"ADDA_DL_CH1", "DL5_CH1 Switch", "DL5"}, + {"ADDA_DL_CH2", "DL5_CH2 Switch", "DL5"}, + + {"ADDA Playback", NULL, "ADDA_DL_CH1"}, + {"ADDA Playback", NULL, "ADDA_DL_CH2"}, + + {"ADDA Playback", NULL, "ADDA Enable"}, + {"ADDA Playback", NULL, "ADDA Playback Enable"}, + + /* capture */ + {"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"}, + {"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"}, + + {"ADDA Capture", NULL, "ADDA Enable"}, + {"ADDA Capture", NULL, "ADDA Capture Enable"}, + {"ADDA Capture", NULL, "AUD_PAD_TOP"}, + {"ADDA Capture", NULL, "ADDA_MTKAIF_CFG"}, + + {"AP DMIC Capture", NULL, "ADDA Enable"}, + {"AP DMIC Capture", NULL, "ADDA Capture Enable"}, + {"AP DMIC Capture", NULL, "ADDA_FIFO"}, + {"AP DMIC Capture", NULL, "AP_DMIC_EN"}, + + {"AP DMIC Capture", NULL, "AP_DMIC_INPUT"}, + + /* clk */ + {"ADDA Playback", NULL, "aud_dac_clk"}, + {"ADDA Playback", NULL, "aud_dac_predis_clk"}, + {"ADDA Playback", NULL, "aud_dac_hires_clk", mtk_afe_dac_hires_connect}, + + {"ADDA Capture Enable", NULL, "aud_adc_clk"}, + {"ADDA Capture Enable", NULL, "aud_adc_hires_clk", + mtk_afe_adc_hires_connect}, + + /* hires source from apll1 */ + {"top_mux_audio_h", NULL, APLL2_W_NAME}, + + {"aud_dac_hires_clk", NULL, "top_mux_audio_h"}, + {"aud_adc_hires_clk", NULL, "top_mux_audio_h"}, +}; + +/* dai ops */ +static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + unsigned int rate = params_rate(params); + int id = dai->id; + struct mtk_afe_adda_priv *adda_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, id, substream->stream, rate); + + if (!adda_priv) { + dev_err(afe->dev, "%s(), adda_priv == NULL", __func__); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + unsigned int dl_src2_con0; + unsigned int dl_src2_con1; + + adda_priv->dl_rate = rate; + + /* set sampling rate */ + dl_src2_con0 = adda_dl_rate_transform(afe, rate) << + DL_2_INPUT_MODE_CTL_SFT; + + /* set output mode, UP_SAMPLING_RATE_X8 */ + dl_src2_con0 |= (0x3 << DL_2_OUTPUT_SEL_CTL_SFT); + + /* turn off mute function */ + dl_src2_con0 |= BIT(DL_2_MUTE_CH2_OFF_CTL_PRE_SFT); + dl_src2_con0 |= BIT(DL_2_MUTE_CH1_OFF_CTL_PRE_SFT); + + /* set voice input data if input sample rate is 8k or 16k */ + if (rate == 8000 || rate == 16000) + dl_src2_con0 |= BIT(DL_2_VOICE_MODE_CTL_PRE_SFT); + + /* SA suggest apply -0.3db to audio/speech path */ + dl_src2_con1 = MTK_AFE_ADDA_DL_GAIN_NORMAL << + DL_2_GAIN_CTL_PRE_SFT; + + /* turn on down-link gain */ + dl_src2_con0 |= BIT(DL_2_GAIN_ON_CTL_PRE_SFT); + + if (id == MT8186_DAI_ADDA) { + /* clean predistortion */ + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON0, 0); + regmap_write(afe->regmap, AFE_ADDA_PREDIS_CON1, 0); + + regmap_write(afe->regmap, + AFE_ADDA_DL_SRC2_CON0, dl_src2_con0); + regmap_write(afe->regmap, + AFE_ADDA_DL_SRC2_CON1, dl_src2_con1); + + /* set sdm gain */ + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DCCOMP_CON, + ATTGAIN_CTL_MASK_SFT, + AUDIO_SDM_LEVEL_NORMAL << + ATTGAIN_CTL_SFT); + + /* Use new 2nd sdm */ + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DITHER_CON, + AFE_DL_SDM_DITHER_64TAP_EN_MASK_SFT, + BIT(AFE_DL_SDM_DITHER_64TAP_EN_SFT)); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + AFE_DL_USE_NEW_2ND_SDM_MASK_SFT, + BIT(AFE_DL_USE_NEW_2ND_SDM_SFT)); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_DCCOMP_CON, + USE_3RD_SDM_MASK_SFT, + AUDIO_SDM_2ND << USE_3RD_SDM_SFT); + + /* sdm auto reset */ + regmap_write(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + SDM_AUTO_RESET_THRESHOLD); + regmap_update_bits(afe->regmap, + AFE_ADDA_DL_SDM_AUTO_RESET_CON, + SDM_AUTO_RESET_TEST_ON_MASK_SFT, + BIT(SDM_AUTO_RESET_TEST_ON_SFT)); + } + } else { + unsigned int ul_src_con0 = 0; + unsigned int voice_mode = adda_ul_rate_transform(afe, rate); + + adda_priv->ul_rate = rate; + ul_src_con0 |= (voice_mode << 17) & (0x7 << 17); + + /* enable iir */ + ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) & + UL_IIR_ON_TMP_CTL_MASK_SFT; + ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) & + UL_IIRMODE_CTL_MASK_SFT; + switch (id) { + case MT8186_DAI_ADDA: + case MT8186_DAI_AP_DMIC: + /* 35Hz @ 48k */ + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_02_01, 0); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_04_03, 0x3fb8); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_06_05, 0x3fb80000); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_08_07, 0x3fb80000); + regmap_write(afe->regmap, + AFE_ADDA_IIR_COEF_10_09, 0xc048); + + regmap_write(afe->regmap, + AFE_ADDA_UL_SRC_CON0, ul_src_con0); + + /* Using Internal ADC */ + regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, BIT(0), 0); + + /* mtkaif_rxif_data_mode = 0, amic */ + regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIF_RX_CFG0, BIT(0), 0); + break; + default: + break; + } + + /* ap dmic */ + switch (id) { + case MT8186_DAI_AP_DMIC: + mtk_adda_ul_src_dmic(afe, id); + break; + default: + break; + } + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_adda_ops = { + .hw_params = mtk_dai_adda_hw_params, +}; + +/* dai driver */ +#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_adda_driver[] = { + { + .name = "ADDA", + .id = MT8186_DAI_ADDA, + .playback = { + .stream_name = "ADDA Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_PLAYBACK_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .capture = { + .stream_name = "ADDA Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, + { + .name = "AP_DMIC", + .id = MT8186_DAI_AP_DMIC, + .capture = { + .stream_name = "AP DMIC Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_ADDA_CAPTURE_RATES, + .formats = MTK_ADDA_FORMATS, + }, + .ops = &mtk_dai_adda_ops, + }, +}; + +int mt8186_dai_adda_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_adda_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver); + + dai->controls = mtk_adda_controls; + dai->num_controls = ARRAY_SIZE(mtk_adda_controls); + dai->dapm_widgets = mtk_dai_adda_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets); + dai->dapm_routes = mtk_dai_adda_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes); + + /* set dai priv */ + ret = mt8186_dai_set_priv(afe, MT8186_DAI_ADDA, + sizeof(struct mtk_afe_adda_priv), NULL); + if (ret) + return ret; + + /* ap dmic priv share with adda */ + afe_priv->dai_priv[MT8186_DAI_AP_DMIC] = + afe_priv->dai_priv[MT8186_DAI_ADDA]; + + return 0; +} From patchwork Mon May 23 13:28:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859028 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 70AE6C433EF for ; Mon, 23 May 2022 13:31:11 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8MCfm0yjlmcroj14ZK+4s1dneSMgmPOVOAB+hT8gbHY=; b=mbJKHmmfM3WU57 DgJC5y7i54hntJzEJ8nq+rZuxsE7aa7E/R6qIyLJ2fF+/WjqU+jW/r2R8yDL1/3MTks+E/a20Yb8p HL4hEXs+342Au4f/oEDAqMvZM7K8kpFY0ZfbolrWG2Ep/+DqDHfwVLqcZIdKmL6CvOO53P+E9uDe+ jCLTnmyjS4SctvvZLcn8Q+Wt9bwwUUORRruB7SA8iO8N39vkBa4CfRWaxb1c35S0kDFZaLPjfWHE+ 21f8b7cBEdvzgiFGYI6DZU54O8TR9LklSqadV1eDxiBIXvnVJax6bkC+7/9NJv4eCddg/2cpwzFGL 8YtfFoePG+I7+Ul3Munw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt88A-004POf-LQ; Mon, 23 May 2022 13:29:54 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt87V-004P6h-Uh; Mon, 23 May 2022 13:29:16 +0000 X-UUID: ec9d79b06eee415c91bb1945cbb49de2-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:2db5055f-2f14-4eec-9ab8-9a9d504d71ed, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:2a19b09, CLOUDID:87f14d7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: ec9d79b06eee415c91bb1945cbb49de2-20220523 Received: from mtkcas68.mediatek.inc [(172.29.94.19)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 720450094; Mon, 23 May 2022 06:29:09 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:07 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:05 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:05 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 05/20] ASoC: mediatek: mt8186: support hostless in platform driver Date: Mon, 23 May 2022 21:28:43 +0800 Message-ID: <20220523132858.22166-6-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_062914_036806_656149ED X-CRM114-Status: GOOD ( 15.82 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 hostless dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- .../soc/mediatek/mt8186/mt8186-dai-hostless.c | 298 ++++++++++++++++++ 1 file changed, 298 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hostless.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c new file mode 100644 index 000000000000..bf0d83840cf4 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hostless.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI Hostless Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include "mt8186-afe-common.h" + +static const struct snd_pcm_hardware mt8186_hostless_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .period_bytes_min = 256, + .period_bytes_max = 4 * 48 * 1024, + .periods_min = 2, + .periods_max = 256, + .buffer_bytes_max = 4 * 48 * 1024, + .fifo_size = 0, +}; + +/* dai component */ +static const struct snd_soc_dapm_route mtk_dai_hostless_routes[] = { + /* Hostless ADDA Loopback */ + {"ADDA_DL_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"ADDA_DL_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S1_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S1_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S3_CH1", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S3_CH1", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"I2S3_CH2", "ADDA_UL_CH1 Switch", "Hostless LPBK DL"}, + {"I2S3_CH2", "ADDA_UL_CH2 Switch", "Hostless LPBK DL"}, + {"Hostless LPBK UL", NULL, "ADDA_UL_Mux"}, + + /* Hostelss FM */ + /* connsys_i2s to hw gain 1*/ + {"Hostless FM UL", NULL, "Connsys I2S"}, + + {"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1 Switch", "Hostless FM DL"}, + {"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2 Switch", "Hostless FM DL"}, + /* hw gain to adda dl */ + {"Hostless FM UL", NULL, "HW Gain 1 Out"}, + + {"ADDA_DL_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"ADDA_DL_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + /* hw gain to i2s3 */ + {"I2S3_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"I2S3_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + /* hw gain to i2s1 */ + {"I2S1_CH1", "GAIN1_OUT_CH1 Switch", "Hostless FM DL"}, + {"I2S1_CH2", "GAIN1_OUT_CH2 Switch", "Hostless FM DL"}, + + /* Hostless_SRC */ + {"ADDA_DL_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"ADDA_DL_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"I2S1_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"I2S1_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"I2S3_CH1", "SRC_1_OUT_CH1 Switch", "Hostless_SRC_1_DL"}, + {"I2S3_CH2", "SRC_1_OUT_CH2 Switch", "Hostless_SRC_1_DL"}, + {"Hostless_SRC_1_UL", NULL, "HW_SRC_1_Out"}, + + /* Hostless_SRC_bargein */ + {"HW_SRC_1_IN_CH1", "I2S0_CH1 Switch", "Hostless_SRC_Bargein_DL"}, + {"HW_SRC_1_IN_CH2", "I2S0_CH2 Switch", "Hostless_SRC_Bargein_DL"}, + {"Hostless_SRC_Bargein_UL", NULL, "I2S0"}, + + /* Hostless AAudio */ + {"Hostless HW Gain AAudio In", NULL, "HW Gain 2 In"}, + {"Hostless SRC AAudio UL", NULL, "HW Gain 2 Out"}, + {"HW_SRC_2_IN_CH1", "HW_GAIN2_OUT_CH1 Switch", "Hostless SRC AAudio DL"}, + {"HW_SRC_2_IN_CH2", "HW_GAIN2_OUT_CH2 Switch", "Hostless SRC AAudio DL"}, +}; + +/* dai ops */ +static int mtk_dai_hostless_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + snd_soc_set_runtime_hwparams(substream, &mt8186_hostless_hardware); + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) { + dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_hostless_ops = { + .startup = mtk_dai_hostless_startup, +}; + +/* dai driver */ +#define MTK_HOSTLESS_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_HOSTLESS_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_hostless_driver[] = { + { + .name = "Hostless LPBK DAI", + .id = MT8186_DAI_HOSTLESS_LPBK, + .playback = { + .stream_name = "Hostless LPBK DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless LPBK UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless FM DAI", + .id = MT8186_DAI_HOSTLESS_FM, + .playback = { + .stream_name = "Hostless FM DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless FM UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_SRC_1_DAI", + .id = MT8186_DAI_HOSTLESS_SRC_1, + .playback = { + .stream_name = "Hostless_SRC_1_DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless_SRC_1_UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_SRC_Bargein_DAI", + .id = MT8186_DAI_HOSTLESS_SRC_BARGEIN, + .playback = { + .stream_name = "Hostless_SRC_Bargein_DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless_SRC_Bargein_UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + /* BE dai */ + { + .name = "Hostless_UL1 DAI", + .id = MT8186_DAI_HOSTLESS_UL1, + .capture = { + .stream_name = "Hostless_UL1 UL", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL2 DAI", + .id = MT8186_DAI_HOSTLESS_UL2, + .capture = { + .stream_name = "Hostless_UL2 UL", + .channels_min = 1, + .channels_max = 4, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL3 DAI", + .id = MT8186_DAI_HOSTLESS_UL3, + .capture = { + .stream_name = "Hostless_UL3 UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL5 DAI", + .id = MT8186_DAI_HOSTLESS_UL5, + .capture = { + .stream_name = "Hostless_UL5 UL", + .channels_min = 1, + .channels_max = 12, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless_UL6 DAI", + .id = MT8186_DAI_HOSTLESS_UL6, + .capture = { + .stream_name = "Hostless_UL6 UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless HW Gain AAudio DAI", + .id = MT8186_DAI_HOSTLESS_HW_GAIN_AAUDIO, + .capture = { + .stream_name = "Hostless HW Gain AAudio In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, + { + .name = "Hostless SRC AAudio DAI", + .id = MT8186_DAI_HOSTLESS_SRC_AAUDIO, + .playback = { + .stream_name = "Hostless SRC AAudio DL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .capture = { + .stream_name = "Hostless SRC AAudio UL", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HOSTLESS_RATES, + .formats = MTK_HOSTLESS_FORMATS, + }, + .ops = &mtk_dai_hostless_ops, + }, +}; + +int mt8186_dai_hostless_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_hostless_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_hostless_driver); + + dai->dapm_routes = mtk_dai_hostless_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hostless_routes); + + return 0; +} From patchwork Mon May 23 13:28:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859075 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 7AC29C433F5 for ; Mon, 23 May 2022 13:43:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=vval5dthgFtkbiZfxocT/k44alSZzkYDmcBMfWuh5+A=; b=xn/M4sKeEnVsLO F59Ni9fhMFjgZPCqrwGlaCXpDDlEmkgPNiv7pv1XEG2CNEbzqN9XlTYEbxZKTaVuH66ZqqWewmqMH qiD+hg1ARrqUZJaZGYMqbjS0jJRXi7De2ErsT46l54LzpGKQPnNIXFvnoCM9SqBImq8m4hPiGAVzQ CpWxyRpSw/Jm50s7H7VmiSpx2jWnt+XoOvQmYWwgDNSRyGqLJeKG7hEEsrEmlrdpRibkuNeBYMGpD zGs33m1x6uyTCvLcK2T/oUyXTWstSH9n9KNarWhrOyW8OUPiNk+YmzZmaPGG1njsIVw4dHB7rTiAf sU3CpWjuW/QTpBMpt60A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Je-004Tl5-2W; Mon, 23 May 2022 13:41:46 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HF-004SjD-1l; Mon, 23 May 2022 13:39:25 +0000 X-UUID: f0f736288eff4ff28ef680946bb89f95-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:ee2cd84c-9a95-495d-9e07-4f8f643ceb7a, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:23,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:23 X-CID-META: VersionHash:2a19b09, CLOUDID:aa204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:4,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: f0f736288eff4ff28ef680946bb89f95-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1707906767; Mon, 23 May 2022 06:39:10 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:09 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:06 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:06 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 06/20] ASoC: mediatek: mt8186: support hw gain in platform driver Date: Mon, 23 May 2022 21:28:44 +0800 Message-ID: <20220523132858.22166-7-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063917_131263_A201E1FA X-CRM114-Status: GOOD ( 15.51 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 hw gain dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- .../soc/mediatek/mt8186/mt8186-dai-hw-gain.c | 236 ++++++++++++++++++ 1 file changed, 236 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c new file mode 100644 index 000000000000..33edd6cbde12 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-hw-gain.c @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI HW Gain Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include "mt8186-afe-common.h" +#include "mt8186-interconnection.h" + +#define HW_GAIN_1_EN_W_NAME "HW GAIN 1 Enable" +#define HW_GAIN_2_EN_W_NAME "HW GAIN 2 Enable" + +/* dai component */ +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1 Switch", AFE_CONN13_1, + I_CONNSYS_I2S_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2 Switch", AFE_CONN14_1, + I_CONNSYS_I2S_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN15, + I_ADDA_UL_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain2_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN16, + I_ADDA_UL_CH2, 1, 0), +}; + +static int mtk_hw_gain_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + unsigned int gain_cur; + unsigned int gain_con1; + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strcmp(w->name, HW_GAIN_1_EN_W_NAME) == 0) { + gain_cur = AFE_GAIN1_CUR; + gain_con1 = AFE_GAIN1_CON1; + } else { + gain_cur = AFE_GAIN2_CUR; + gain_con1 = AFE_GAIN2_CON1; + } + + /* let hw gain ramp up, set cur gain to 0 */ + regmap_update_bits(afe->regmap, gain_cur, AFE_GAIN1_CUR_MASK_SFT, 0); + + /* set target gain to 0 */ + regmap_update_bits(afe->regmap, gain_con1, GAIN1_TARGET_MASK_SFT, 0); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_hw_gain_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_gain1_in_ch1_mix, + ARRAY_SIZE(mtk_hw_gain1_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN1_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_gain1_in_ch2_mix, + ARRAY_SIZE(mtk_hw_gain1_in_ch2_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_gain2_in_ch1_mix, + ARRAY_SIZE(mtk_hw_gain2_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_GAIN2_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_gain2_in_ch2_mix, + ARRAY_SIZE(mtk_hw_gain2_in_ch2_mix)), + + SND_SOC_DAPM_SUPPLY(HW_GAIN_1_EN_W_NAME, + AFE_GAIN1_CON0, GAIN1_ON_SFT, 0, + mtk_hw_gain_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_SUPPLY(HW_GAIN_2_EN_W_NAME, + AFE_GAIN2_CON0, GAIN2_ON_SFT, 0, + mtk_hw_gain_event, + SND_SOC_DAPM_PRE_PMU), + + SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"), + SND_SOC_DAPM_INPUT("HW Gain 2 Out Endpoint"), + SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"), +}; + +static const struct snd_soc_dapm_route mtk_dai_hw_gain_routes[] = { + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"}, + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"}, + {"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH1"}, + {"HW Gain 2 In", NULL, "HW_GAIN2_IN_CH2"}, + + {"HW Gain 1 In", NULL, HW_GAIN_1_EN_W_NAME}, + {"HW Gain 1 Out", NULL, HW_GAIN_1_EN_W_NAME}, + {"HW Gain 2 In", NULL, HW_GAIN_2_EN_W_NAME}, + {"HW Gain 2 Out", NULL, HW_GAIN_2_EN_W_NAME}, + + {"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"}, + {"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"}, + {"HW Gain 2 Out", NULL, "HW Gain 2 Out Endpoint"}, +}; + +static const struct snd_kcontrol_new mtk_hw_gain_controls[] = { + SOC_SINGLE("HW Gain 1 Volume", AFE_GAIN1_CON1, + GAIN1_TARGET_SFT, GAIN1_TARGET_MASK, 0), + SOC_SINGLE("HW Gain 2 Volume", AFE_GAIN2_CON1, + GAIN2_TARGET_SFT, GAIN2_TARGET_MASK, 0), +}; + +/* dai ops */ +static int mtk_dai_gain_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id); + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, dai->id, substream->stream, rate); + + /* rate */ + regmap_update_bits(afe->regmap, + dai->id == MT8186_DAI_HW_GAIN_1 ? + AFE_GAIN1_CON0 : AFE_GAIN2_CON0, + GAIN1_MODE_MASK_SFT, + rate_reg << GAIN1_MODE_SFT); + + /* sample per step */ + regmap_update_bits(afe->regmap, + dai->id == MT8186_DAI_HW_GAIN_1 ? + AFE_GAIN1_CON0 : AFE_GAIN2_CON0, + GAIN1_SAMPLE_PER_STEP_MASK_SFT, + (dai->id == MT8186_DAI_HW_GAIN_1 ? 0x40 : 0x0) << + GAIN1_SAMPLE_PER_STEP_SFT); + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_gain_ops = { + .hw_params = mtk_dai_gain_hw_params, +}; + +/* dai driver */ +#define MTK_HW_GAIN_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_HW_GAIN_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_gain_driver[] = { + { + .name = "HW Gain 1", + .id = MT8186_DAI_HW_GAIN_1, + .playback = { + .stream_name = "HW Gain 1 In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .capture = { + .stream_name = "HW Gain 1 Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .ops = &mtk_dai_gain_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + }, + { + .name = "HW Gain 2", + .id = MT8186_DAI_HW_GAIN_2, + .playback = { + .stream_name = "HW Gain 2 In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .capture = { + .stream_name = "HW Gain 2 Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_HW_GAIN_RATES, + .formats = MTK_HW_GAIN_FORMATS, + }, + .ops = &mtk_dai_gain_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + }, +}; + +int mt8186_dai_hw_gain_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_gain_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_gain_driver); + + dai->controls = mtk_hw_gain_controls; + dai->num_controls = ARRAY_SIZE(mtk_hw_gain_controls); + dai->dapm_widgets = mtk_dai_hw_gain_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_hw_gain_widgets); + dai->dapm_routes = mtk_dai_hw_gain_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_hw_gain_routes); + return 0; +} From patchwork Mon May 23 13:28:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859081 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 233E5C433F5 for ; Mon, 23 May 2022 13:46:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=YLuDkP5bbJcXnk3a7JJeqfhFyDJ0F22luKoAn3q0fBg=; b=sKjAMGHLiOrZ7k 4Xu/BxYeD0HjTjTjd3b374+m1Va1mzlUUjUZNnGYQiCWqHgJRGypUEEHU8/lsjftRBNZPz5ymG6Jj SgTgVQZaAtfHlwvwDcieOYP51Og8PI0szDrbb1SWZDYQtedbk7PNYBfYQ/Fe4HX8vbcSnxQPJnATv 3dy/4QOaN58WRTAX49WtvkZpUK0T/cthCz33aRLCh+ZGmFPurKPC2oTdV2C8KC2tGoSIz8SYWAwoi nClW7LW0q02CAVCZ3nTJE1Eqj/3D45HE++C/xDfFH+58i/2+PbmO6gGkU1wYL24h/RKt6XbyQ4S7b qGD26YCztVmW2qFNmV9A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Mc-004VTA-8Z; Mon, 23 May 2022 13:44:50 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HH-004SkM-3f; Mon, 23 May 2022 13:39:35 +0000 X-UUID: 33563c885f2842a8a773657907f322a8-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:83bbcb29-bf26-4a6a-8380-7fe477298736, OB:0, LO B:0,IP:0,URL:5,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:5 X-CID-META: VersionHash:2a19b09, CLOUDID:ae204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: 33563c885f2842a8a773657907f322a8-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 310138387; Mon, 23 May 2022 06:39:11 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:09 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:07 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:07 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 07/20] ASoC: mediatek: mt8186: support i2s in platform driver Date: Mon, 23 May 2022 21:28:45 +0800 Message-ID: <20220523132858.22166-8-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063919_221523_E66DEA73 X-CRM114-Status: GOOD ( 15.21 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 i2s dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- sound/soc/mediatek/mt8186/mt8186-dai-i2s.c | 1286 ++++++++++++++++++++ 1 file changed, 1286 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-i2s.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c new file mode 100644 index 000000000000..5c1290b950e8 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-i2s.c @@ -0,0 +1,1286 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI I2S Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +enum { + I2S_FMT_EIAJ = 0, + I2S_FMT_I2S = 1, +}; + +enum { + I2S_WLEN_16_BIT = 0, + I2S_WLEN_32_BIT = 1, +}; + +enum { + I2S_HD_NORMAL = 0, + I2S_HD_LOW_JITTER = 1, +}; + +enum { + I2S1_SEL_O28_O29 = 0, + I2S1_SEL_O03_O04 = 1, +}; + +enum { + I2S_IN_PAD_CONNSYS = 0, + I2S_IN_PAD_IO_MUX = 1, +}; + +struct mtk_afe_i2s_priv { + int id; + int rate; /* for determine which apll to use */ + int low_jitter_en; + int master; /* only i2s0 has slave mode*/ + + const char *share_property_name; + int share_i2s_id; + + int mclk_id; + int mclk_rate; + int mclk_apll; +}; + +static unsigned int get_i2s_wlen(snd_pcm_format_t format) +{ + return snd_pcm_format_physical_width(format) <= 16 ? + I2S_WLEN_16_BIT : I2S_WLEN_32_BIT; +} + +#define MTK_AFE_I2S0_KCONTROL_NAME "I2S0_HD_Mux" +#define MTK_AFE_I2S1_KCONTROL_NAME "I2S1_HD_Mux" +#define MTK_AFE_I2S2_KCONTROL_NAME "I2S2_HD_Mux" +#define MTK_AFE_I2S3_KCONTROL_NAME "I2S3_HD_Mux" +#define MTK_AFE_I2S0_SRC_KCONTROL_NAME "I2S0_SRC_Mux" + +#define I2S0_HD_EN_W_NAME "I2S0_HD_EN" +#define I2S1_HD_EN_W_NAME "I2S1_HD_EN" +#define I2S2_HD_EN_W_NAME "I2S2_HD_EN" +#define I2S3_HD_EN_W_NAME "I2S3_HD_EN" + +#define I2S0_MCLK_EN_W_NAME "I2S0_MCLK_EN" +#define I2S1_MCLK_EN_W_NAME "I2S1_MCLK_EN" +#define I2S2_MCLK_EN_W_NAME "I2S2_MCLK_EN" +#define I2S3_MCLK_EN_W_NAME "I2S3_MCLK_EN" + +static int get_i2s_id_by_name(struct mtk_base_afe *afe, + const char *name) +{ + if (strncmp(name, "I2S0", 4) == 0) + return MT8186_DAI_I2S_0; + else if (strncmp(name, "I2S1", 4) == 0) + return MT8186_DAI_I2S_1; + else if (strncmp(name, "I2S2", 4) == 0) + return MT8186_DAI_I2S_2; + else if (strncmp(name, "I2S3", 4) == 0) + return MT8186_DAI_I2S_3; + + return -EINVAL; +} + +static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe, + const char *name) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_i2s_id_by_name(afe, name); + + if (dai_id < 0) + return NULL; + + return afe_priv->dai_priv[dai_id]; +} + +/* low jitter control */ +static const char * const mt8186_i2s_hd_str[] = { + "Normal", "Low_Jitter" +}; + +static const struct soc_enum mt8186_i2s_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_i2s_hd_str), + mt8186_i2s_hd_str), +}; + +static int mt8186_i2s_hd_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = i2s_priv->low_jitter_en; + + return 0; +} + +static int mt8186_i2s_hd_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int hd_en; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + hd_en = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n", + __func__, kcontrol->id.name, hd_en); + + i2s_priv = get_i2s_priv_by_name(afe, kcontrol->id.name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + if (i2s_priv->low_jitter_en == hd_en) + return 0; + + i2s_priv->low_jitter_en = hd_en; + + return 1; +} + +static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = { + SOC_ENUM_EXT(MTK_AFE_I2S0_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S1_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S2_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), + SOC_ENUM_EXT(MTK_AFE_I2S3_KCONTROL_NAME, mt8186_i2s_enum[0], + mt8186_i2s_hd_get, mt8186_i2s_hd_set), +}; + +/* dai component */ +/* i2s virtual mux to output widget */ +static const char * const i2s_mux_map[] = { + "Normal", "Dummy_Widget", +}; + +static int i2s_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + i2s_mux_map, + i2s_mux_map_value); + +static const struct snd_kcontrol_new i2s0_in_mux_control = + SOC_DAPM_ENUM("I2S0 In Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s1_out_mux_control = + SOC_DAPM_ENUM("I2S1 Out Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s2_in_mux_control = + SOC_DAPM_ENUM("I2S2 In Select", i2s_mux_map_enum); + +static const struct snd_kcontrol_new i2s3_out_mux_control = + SOC_DAPM_ENUM("I2S3 Out Select", i2s_mux_map_enum); + +/* i2s in lpbk */ +static const char * const i2s_lpbk_mux_map[] = { + "Normal", "Lpbk", +}; + +static int i2s_lpbk_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s0_lpbk_mux_map_enum, + AFE_I2S_CON, + I2S_LOOPBACK_SFT, + 1, + i2s_lpbk_mux_map, + i2s_lpbk_mux_map_value); + +static const struct snd_kcontrol_new i2s0_lpbk_mux_control = + SOC_DAPM_ENUM("I2S Lpbk Select", i2s0_lpbk_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(i2s2_lpbk_mux_map_enum, + AFE_I2S_CON2, + I2S3_LOOPBACK_SFT, + 1, + i2s_lpbk_mux_map, + i2s_lpbk_mux_map_value); + +static const struct snd_kcontrol_new i2s2_lpbk_mux_control = + SOC_DAPM_ENUM("I2S Lpbk Select", i2s2_lpbk_mux_map_enum); + +/* interconnection */ +static const struct snd_kcontrol_new mtk_i2s3_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN0, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN0, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN0, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN0, + I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN0, + I_DL12_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN0_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN0_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN0_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN0_1, + I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN0, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN0, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN0, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN0, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN0, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN0_1, + I_SRC_1_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s3_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN1, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN1, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN1, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN1, + I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN1, + I_DL12_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN1_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN1_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN1_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN1_1, + I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN1, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN1, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN1, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3 Switch", AFE_CONN1, + I_ADDA_UL_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN1, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN1, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN1_1, + I_SRC_1_OUT_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s1_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN28, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN28, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN28, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH1 Switch", AFE_CONN28, + I_DL12_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH3 Switch", AFE_CONN28, + I_DL12_CH3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN28_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN28_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN28_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1 Switch", AFE_CONN28_1, + I_DL8_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH1 Switch", AFE_CONN28, + I_GAIN1_OUT_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN28, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1 Switch", AFE_CONN28, + I_PCM_1_CAP_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH1 Switch", AFE_CONN28_1, + I_SRC_1_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_i2s1_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN29, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN29, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN29, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH2 Switch", AFE_CONN29, + I_DL12_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL12_CH4 Switch", AFE_CONN29, + I_DL12_CH4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN29_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN29_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN29_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2 Switch", AFE_CONN29_1, + I_DL8_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("GAIN1_OUT_CH2 Switch", AFE_CONN29, + I_GAIN1_OUT_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN29, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2 Switch", AFE_CONN29, + I_PCM_1_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("PCM_2_CAP_CH2 Switch", AFE_CONN29, + I_PCM_2_CAP_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("SRC_1_OUT_CH2 Switch", AFE_CONN29_1, + I_SRC_1_OUT_CH2, 1, 0), +}; + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_I2S_MCLK_EN, + SUPPLY_SEQ_I2S_HD_EN, + SUPPLY_SEQ_I2S_EN, +}; + +static int mtk_i2s_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, i2s_priv->id, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, i2s_priv->id, 0); + break; + default: + break; + } + + return 0; +} + +static int mtk_apll_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8186_apll1_enable(afe); + else + mt8186_apll2_enable(afe); + break; + case SND_SOC_DAPM_POST_PMD: + if (strcmp(w->name, APLL1_W_NAME) == 0) + mt8186_apll1_disable(afe); + else + mt8186_apll2_disable(afe); + break; + default: + break; + } + + return 0; +} + +static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + i2s_priv->mclk_rate = 0; + mt8186_mck_disable(afe, i2s_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = { + SND_SOC_DAPM_INPUT("CONNSYS"), + + SND_SOC_DAPM_MIXER("I2S1_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2s1_ch1_mix, + ARRAY_SIZE(mtk_i2s1_ch1_mix)), + SND_SOC_DAPM_MIXER("I2S1_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2s1_ch2_mix, + ARRAY_SIZE(mtk_i2s1_ch2_mix)), + + SND_SOC_DAPM_MIXER("I2S3_CH1", SND_SOC_NOPM, 0, 0, + mtk_i2s3_ch1_mix, + ARRAY_SIZE(mtk_i2s3_ch1_mix)), + SND_SOC_DAPM_MIXER("I2S3_CH2", SND_SOC_NOPM, 0, 0, + mtk_i2s3_ch2_mix, + ARRAY_SIZE(mtk_i2s3_ch2_mix)), + + /* i2s en*/ + SND_SOC_DAPM_SUPPLY_S("I2S0_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S1_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON1, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S2_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON2, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S("I2S3_EN", SUPPLY_SEQ_I2S_EN, + AFE_I2S_CON3, I2S_EN_SFT, 0, + mtk_i2s_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* i2s hd en */ + SND_SOC_DAPM_SUPPLY_S(I2S0_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON, I2S1_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S1_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON1, I2S2_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S2_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON2, I2S3_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S3_HD_EN_W_NAME, SUPPLY_SEQ_I2S_HD_EN, + AFE_I2S_CON3, I2S4_HD_EN_SFT, 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* i2s mclk en */ + SND_SOC_DAPM_SUPPLY_S(I2S0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(I2S3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN, + SND_SOC_NOPM, 0, 0, + mtk_mclk_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* apll */ + SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL, + SND_SOC_NOPM, 0, 0, + mtk_apll_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* allow i2s on without codec on */ + SND_SOC_DAPM_OUTPUT("I2S_DUMMY_OUT"), + SND_SOC_DAPM_MUX("I2S1_Out_Mux", + SND_SOC_NOPM, 0, 0, &i2s1_out_mux_control), + SND_SOC_DAPM_MUX("I2S3_Out_Mux", + SND_SOC_NOPM, 0, 0, &i2s3_out_mux_control), + SND_SOC_DAPM_INPUT("I2S_DUMMY_IN"), + SND_SOC_DAPM_MUX("I2S0_In_Mux", + SND_SOC_NOPM, 0, 0, &i2s0_in_mux_control), + SND_SOC_DAPM_MUX("I2S2_In_Mux", + SND_SOC_NOPM, 0, 0, &i2s2_in_mux_control), + + /* i2s in lpbk */ + SND_SOC_DAPM_MUX("I2S0_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &i2s0_lpbk_mux_control), + SND_SOC_DAPM_MUX("I2S2_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &i2s2_lpbk_mux_control), +}; + +static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (i2s_priv->share_i2s_id < 0) + return 0; + + return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name); +} + +static int mtk_afe_i2s_hd_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (get_i2s_id_by_name(afe, sink->name) == + get_i2s_id_by_name(afe, source->name)) + return i2s_priv->low_jitter_en; + + /* check if share i2s need hd en */ + if (i2s_priv->share_i2s_id < 0) + return 0; + + if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name)) + return i2s_priv->low_jitter_en; + + return 0; +} + +static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + int i2s_need_apll; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + /* choose APLL from i2s rate */ + i2s_need_apll = mt8186_get_apll_by_rate(afe, i2s_priv->rate); + + return (i2s_need_apll == cur_apll) ? 1 : 0; +} + +static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + + i2s_priv = get_i2s_priv_by_name(afe, sink->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + if (get_i2s_id_by_name(afe, sink->name) == + get_i2s_id_by_name(afe, source->name)) + return (i2s_priv->mclk_rate > 0) ? 1 : 0; + + /* check if share i2s need mclk */ + if (i2s_priv->share_i2s_id < 0) + return 0; + + if (i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name)) + return (i2s_priv->mclk_rate > 0) ? 1 : 0; + + return 0; +} + +static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mtk_afe_i2s_priv *i2s_priv; + int cur_apll; + + i2s_priv = get_i2s_priv_by_name(afe, w->name); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + return (i2s_priv->mclk_apll == cur_apll) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = { + {"Connsys I2S", NULL, "CONNSYS"}, + + /* i2s0 */ + {"I2S0", NULL, "I2S0_EN"}, + {"I2S0", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S0", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S0", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S0", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S0", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S0_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S0_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S0", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S0", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s1 */ + {"I2S1_CH1", "DL1_CH1 Switch", "DL1"}, + {"I2S1_CH2", "DL1_CH2 Switch", "DL1"}, + + {"I2S1_CH1", "DL2_CH1 Switch", "DL2"}, + {"I2S1_CH2", "DL2_CH2 Switch", "DL2"}, + + {"I2S1_CH1", "DL3_CH1 Switch", "DL3"}, + {"I2S1_CH2", "DL3_CH2 Switch", "DL3"}, + + {"I2S1_CH1", "DL12_CH1 Switch", "DL12"}, + {"I2S1_CH2", "DL12_CH2 Switch", "DL12"}, + + {"I2S1_CH1", "DL12_CH3 Switch", "DL12"}, + {"I2S1_CH2", "DL12_CH4 Switch", "DL12"}, + + {"I2S1_CH1", "DL6_CH1 Switch", "DL6"}, + {"I2S1_CH2", "DL6_CH2 Switch", "DL6"}, + + {"I2S1_CH1", "DL4_CH1 Switch", "DL4"}, + {"I2S1_CH2", "DL4_CH2 Switch", "DL4"}, + + {"I2S1_CH1", "DL5_CH1 Switch", "DL5"}, + {"I2S1_CH2", "DL5_CH2 Switch", "DL5"}, + + {"I2S1_CH1", "DL8_CH1 Switch", "DL8"}, + {"I2S1_CH2", "DL8_CH2 Switch", "DL8"}, + + {"I2S1", NULL, "I2S1_CH1"}, + {"I2S1", NULL, "I2S1_CH2"}, + + {"I2S1", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S1", NULL, "I2S1_EN"}, + {"I2S1", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S1", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S1", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S1", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S1_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S1_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S1", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S1", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s2 */ + {"I2S2", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S2", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S2", NULL, "I2S2_EN"}, + {"I2S2", NULL, "I2S3_EN", mtk_afe_i2s_share_connect}, + + {"I2S2", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S2", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S2_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S2_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S2", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S2", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* i2s3 */ + {"I2S3_CH1", "DL1_CH1 Switch", "DL1"}, + {"I2S3_CH2", "DL1_CH2 Switch", "DL1"}, + + {"I2S3_CH1", "DL2_CH1 Switch", "DL2"}, + {"I2S3_CH2", "DL2_CH2 Switch", "DL2"}, + + {"I2S3_CH1", "DL3_CH1 Switch", "DL3"}, + {"I2S3_CH2", "DL3_CH2 Switch", "DL3"}, + + {"I2S3_CH1", "DL12_CH1 Switch", "DL12"}, + {"I2S3_CH2", "DL12_CH2 Switch", "DL12"}, + + {"I2S3_CH1", "DL12_CH3 Switch", "DL12"}, + {"I2S3_CH2", "DL12_CH4 Switch", "DL12"}, + + {"I2S3_CH1", "DL6_CH1 Switch", "DL6"}, + {"I2S3_CH2", "DL6_CH2 Switch", "DL6"}, + + {"I2S3_CH1", "DL4_CH1 Switch", "DL4"}, + {"I2S3_CH2", "DL4_CH2 Switch", "DL4"}, + + {"I2S3_CH1", "DL5_CH1 Switch", "DL5"}, + {"I2S3_CH2", "DL5_CH2 Switch", "DL5"}, + + {"I2S3_CH1", "DL8_CH1 Switch", "DL8"}, + {"I2S3_CH2", "DL8_CH2 Switch", "DL8"}, + + {"I2S3", NULL, "I2S3_CH1"}, + {"I2S3", NULL, "I2S3_CH2"}, + + {"I2S3", NULL, "I2S0_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S1_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S2_EN", mtk_afe_i2s_share_connect}, + {"I2S3", NULL, "I2S3_EN"}, + + {"I2S3", NULL, I2S0_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S1_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S2_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {"I2S3", NULL, I2S3_HD_EN_W_NAME, mtk_afe_i2s_hd_connect}, + {I2S3_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect}, + {I2S3_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect}, + + {"I2S3", NULL, I2S0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {"I2S3", NULL, I2S3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect}, + {I2S3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect}, + {I2S3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect}, + + /* allow i2s on without codec on */ + {"I2S0", NULL, "I2S0_In_Mux"}, + {"I2S0_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"}, + + {"I2S1_Out_Mux", "Dummy_Widget", "I2S1"}, + {"I2S_DUMMY_OUT", NULL, "I2S1_Out_Mux"}, + + {"I2S2", NULL, "I2S2_In_Mux"}, + {"I2S2_In_Mux", "Dummy_Widget", "I2S_DUMMY_IN"}, + + {"I2S3_Out_Mux", "Dummy_Widget", "I2S3"}, + {"I2S_DUMMY_OUT", NULL, "I2S3_Out_Mux"}, + + /* i2s in lpbk */ + {"I2S0_Lpbk_Mux", "Lpbk", "I2S3"}, + {"I2S2_Lpbk_Mux", "Lpbk", "I2S1"}, + {"I2S0", NULL, "I2S0_Lpbk_Mux"}, + {"I2S2", NULL, "I2S2_Lpbk_Mux"}, +}; + +/* dai ops */ +static int mtk_dai_connsys_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, + rate, dai->id); + unsigned int i2s_con = 0; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, dai->id, substream->stream, rate); + + /* non-inverse, i2s mode, slave, 16bits, from connsys */ + i2s_con |= 0 << INV_PAD_CTRL_SFT; + i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= 1 << I2S_SRC_SFT; + i2s_con |= get_i2s_wlen(SNDRV_PCM_FORMAT_S16_LE) << I2S_WLEN_SFT; + i2s_con |= 0 << I2SIN_PAD_SEL_SFT; + regmap_write(afe->regmap, AFE_CONNSYS_I2S_CON, i2s_con); + + /* use asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_BYPSRC_MASK_SFT, 0); + + /* slave mode, set i2s for asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_MODE_MASK_SFT, rate_reg << I2S_MODE_SFT); + + if (rate == 44100) + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1b9000); + else if (rate == 32000) + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x140000); + else + regmap_write(afe->regmap, AFE_ASRC_2CH_CON3, 0x1e0000); + + /* Calibration setting */ + regmap_write(afe->regmap, AFE_ASRC_2CH_CON4, 0x140000); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON9, 0x36000); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON10, 0x2fc00); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON6, 0x7ef4); + regmap_write(afe->regmap, AFE_ASRC_2CH_CON5, 0xff5986); + + /* 0:Stereo 1:Mono */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2, + CHSET_IS_MONO_MASK_SFT, 0); + + return 0; +} + +static int mtk_dai_connsys_i2s_trigger(struct snd_pcm_substream *substream, + int cmd, struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + dev_dbg(afe->dev, "%s(), cmd %d, stream %d\n", + __func__, cmd, substream->stream); + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* i2s enable */ + regmap_update_bits(afe->regmap, + AFE_CONNSYS_I2S_CON, + I2S_EN_MASK_SFT, + BIT(I2S_EN_SFT)); + + /* calibrator enable */ + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON5, + CALI_EN_MASK_SFT, + BIT(CALI_EN_SFT)); + + /* asrc enable */ + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON0, + CON0_CHSET_STR_CLR_MASK_SFT, + BIT(CON0_CHSET_STR_CLR_SFT)); + regmap_update_bits(afe->regmap, + AFE_ASRC_2CH_CON0, + CON0_ASM_ON_MASK_SFT, + BIT(CON0_ASM_ON_SFT)); + + afe_priv->dai_on[dai->id] = true; + return 0; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + CON0_ASM_ON_MASK_SFT, 0); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5, + CALI_EN_MASK_SFT, 0); + + /* i2s disable */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_EN_MASK_SFT, 0); + + /* bypass asrc */ + regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON, + I2S_BYPSRC_MASK_SFT, BIT(I2S_BYPSRC_SFT)); + + afe_priv->dai_on[dai->id] = false; + return 0; + default: + return -EINVAL; + } + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_connsys_i2s_ops = { + .hw_params = mtk_dai_connsys_i2s_hw_params, + .trigger = mtk_dai_connsys_i2s_trigger, +}; + +/* i2s */ +static int mtk_dai_i2s_config(struct mtk_base_afe *afe, + struct snd_pcm_hw_params *params, + int i2s_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[i2s_id]; + + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, + rate, i2s_id); + snd_pcm_format_t format = params_format(params); + unsigned int i2s_con = 0; + int ret; + + dev_dbg(afe->dev, "%s(), id %d, rate %d, format %d\n", + __func__, i2s_id, rate, format); + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + i2s_priv->rate = rate; + + switch (i2s_id) { + case MT8186_DAI_I2S_0: + i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT; + i2s_con |= rate_reg << I2S_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_1: + i2s_con = I2S1_SEL_O28_O29 << I2S2_SEL_O03_O04_SFT; + i2s_con |= rate_reg << I2S2_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S2_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S2_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON1, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_2: + i2s_con = 8 << I2S3_UPDATE_WORD_SFT; + i2s_con |= rate_reg << I2S3_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S3_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S3_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON2, + 0xffffeffa, i2s_con); + break; + case MT8186_DAI_I2S_3: + i2s_con = rate_reg << I2S4_OUT_MODE_SFT; + i2s_con |= I2S_FMT_I2S << I2S4_FMT_SFT; + i2s_con |= get_i2s_wlen(format) << I2S4_WLEN_SFT; + regmap_update_bits(afe->regmap, AFE_I2S_CON3, + 0xffffeffa, i2s_con); + break; + default: + dev_err(afe->dev, "%s(), id %d not support\n", + __func__, i2s_id); + return -EINVAL; + } + + /* set share i2s */ + if (i2s_priv && i2s_priv->share_i2s_id >= 0) { + ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id); + if (ret) + return ret; + } + + return 0; +} + +static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + return mtk_dai_i2s_config(afe, params, dai->id); +} + +static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[dai->id]; + int apll; + int apll_rate; + + if (!i2s_priv) { + dev_err(afe->dev, "%s(), i2s_priv == NULL", __func__); + return -EINVAL; + } + + if (dir != SND_SOC_CLOCK_OUT) { + dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__); + return -EINVAL; + } + + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); + + apll = mt8186_get_apll_by_rate(afe, freq); + apll_rate = mt8186_get_apll_rate(afe, apll); + + if (freq > apll_rate) { + dev_err(afe->dev, "%s(), freq > apll rate", __func__); + return -EINVAL; + } + + if (apll_rate % freq != 0) { + dev_err(afe->dev, "%s(), APLL cannot generate freq Hz", __func__); + return -EINVAL; + } + + i2s_priv->mclk_rate = freq; + i2s_priv->mclk_apll = apll; + + if (i2s_priv->share_i2s_id > 0) { + struct mtk_afe_i2s_priv *share_i2s_priv; + + share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id]; + if (!share_i2s_priv) { + dev_err(afe->dev, "%s(), share_i2s_priv == NULL", __func__); + return -EINVAL; + } + + share_i2s_priv->mclk_rate = i2s_priv->mclk_rate; + share_i2s_priv->mclk_apll = i2s_priv->mclk_apll; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_i2s_ops = { + .hw_params = mtk_dai_i2s_hw_params, + .set_sysclk = mtk_dai_i2s_set_sysclk, +}; + +/* dai driver */ +#define MTK_CONNSYS_I2S_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) + +#define MTK_I2S_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = { + { + .name = "CONNSYS_I2S", + .id = MT8186_DAI_CONNSYS_I2S, + .capture = { + .stream_name = "Connsys I2S", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_CONNSYS_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_connsys_i2s_ops, + }, + { + .name = "I2S0", + .id = MT8186_DAI_I2S_0, + .capture = { + .stream_name = "I2S0", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S1", + .id = MT8186_DAI_I2S_1, + .playback = { + .stream_name = "I2S1", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S2", + .id = MT8186_DAI_I2S_2, + .capture = { + .stream_name = "I2S2", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + }, + { + .name = "I2S3", + .id = MT8186_DAI_I2S_3, + .playback = { + .stream_name = "I2S3", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_I2S_RATES, + .formats = MTK_I2S_FORMATS, + }, + .ops = &mtk_dai_i2s_ops, + } +}; + +/* this enum is merely for mtk_afe_i2s_priv declare */ +enum { + DAI_I2S0 = 0, + DAI_I2S1, + DAI_I2S2, + DAI_I2S3, + DAI_I2S_NUM, +}; + +static const struct mtk_afe_i2s_priv mt8186_i2s_priv[DAI_I2S_NUM] = { + [DAI_I2S0] = { + .id = MT8186_DAI_I2S_0, + .mclk_id = MT8186_I2S0_MCK, + .share_property_name = "i2s0-share", + .share_i2s_id = -1, + }, + [DAI_I2S1] = { + .id = MT8186_DAI_I2S_1, + .mclk_id = MT8186_I2S1_MCK, + .share_property_name = "i2s1-share", + .share_i2s_id = -1, + }, + [DAI_I2S2] = { + .id = MT8186_DAI_I2S_2, + .mclk_id = MT8186_I2S2_MCK, + .share_property_name = "i2s2-share", + .share_i2s_id = -1, + }, + [DAI_I2S3] = { + .id = MT8186_DAI_I2S_3, + /* clock gate naming is hf_faud_i2s4_m_ck*/ + .mclk_id = MT8186_I2S4_MCK, + .share_property_name = "i2s3-share", + .share_i2s_id = -1, + } +}; + +static int mt8186_dai_i2s_get_share(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + const struct device_node *of_node = afe->dev->of_node; + const char *of_str; + const char *property_name; + struct mtk_afe_i2s_priv *i2s_priv; + int i; + + for (i = 0; i < DAI_I2S_NUM; i++) { + i2s_priv = afe_priv->dai_priv[mt8186_i2s_priv[i].id]; + property_name = mt8186_i2s_priv[i].share_property_name; + if (of_property_read_string(of_node, property_name, &of_str)) + continue; + i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str); + } + + return 0; +} + +static int mt8186_dai_i2s_set_priv(struct mtk_base_afe *afe) +{ + int i; + int ret; + + for (i = 0; i < DAI_I2S_NUM; i++) { + ret = mt8186_dai_set_priv(afe, mt8186_i2s_priv[i].id, + sizeof(struct mtk_afe_i2s_priv), + &mt8186_i2s_priv[i]); + if (ret) + return ret; + } + + return 0; +} + +int mt8186_dai_i2s_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_i2s_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver); + + dai->controls = mtk_dai_i2s_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls); + dai->dapm_widgets = mtk_dai_i2s_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets); + dai->dapm_routes = mtk_dai_i2s_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes); + + /* set all dai i2s private data */ + ret = mt8186_dai_i2s_set_priv(afe); + if (ret) + return ret; + + /* parse share i2s */ + ret = mt8186_dai_i2s_get_share(afe); + if (ret) + return ret; + + return 0; +} From patchwork Mon May 23 13:28:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859078 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 CD3C8C433F5 for ; Mon, 23 May 2022 13:43:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XnLER4DkR7D14AZnLvZtW++cJySXL0lbAxUb4VEu8ns=; b=fRhpKeVq7DrmYz uDwBZRws3dJb2AAQbJHO1XpgsZEz9agEz9tn9cH3DnAiLs1hKYMmbjt+Gq2RkG3LCaxOCIgAlpUZs T6y08wMlL4yLuTtpxrzpxPBejemBTr3EwOSy5r2CxkZfAnIJomu4p5U8AC9IG6CXwpunciB9gY4px zIW5EVz+jSwXb7ZHDvnBdzEVGs0keMN5NK8uj1lKPsvvZa7VUjRWT+S3BPZy6tMhLd+fJVJvE0/jU KCq8BFgRkG1hZvwIM/r35ow4Z0pVAag2lhfzGRHQ+WJSzNX9tl9XD6yoZUNYejLRS+YRXQl1OKjrZ JB+dwpW3ki299kj5woQw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8KY-004UJc-B2; Mon, 23 May 2022 13:42:42 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HG-004SjY-2W; Mon, 23 May 2022 13:39:26 +0000 X-UUID: 9bed5f7fe0a94ce98c8075c217a8e26a-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:7853ff64-8d9b-47d9-b0e5-e46dd18dc811, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:2a19b09, CLOUDID:0f293ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 9bed5f7fe0a94ce98c8075c217a8e26a-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 248448301; Mon, 23 May 2022 06:39:11 -0700 Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:10 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:08 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:08 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 08/20] ASoC: mediatek: mt8186: support pcm in platform driver Date: Mon, 23 May 2022 21:28:46 +0800 Message-ID: <20220523132858.22166-9-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063918_177774_E683A0B9 X-CRM114-Status: GOOD ( 18.02 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 pcm dai driver. Signed-off-by: Jiaxin Yu Reviewed-by: AngeloGioacchino Del Regno --- sound/soc/mediatek/mt8186/mt8186-dai-pcm.c | 423 +++++++++++++++++++++ 1 file changed, 423 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-pcm.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c new file mode 100644 index 000000000000..0b0032ecfe6d --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-pcm.c @@ -0,0 +1,423 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI I2S Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +struct mtk_afe_pcm_priv { + unsigned int id; + unsigned int fmt; + unsigned int bck_invert; + unsigned int lck_invert; +}; + +enum aud_tx_lch_rpt { + AUD_TX_LCH_RPT_NO_REPEAT = 0, + AUD_TX_LCH_RPT_REPEAT = 1 +}; + +enum aud_vbt_16k_mode { + AUD_VBT_16K_MODE_DISABLE = 0, + AUD_VBT_16K_MODE_ENABLE = 1 +}; + +enum aud_ext_modem { + AUD_EXT_MODEM_SELECT_INTERNAL = 0, + AUD_EXT_MODEM_SELECT_EXTERNAL = 1 +}; + +enum aud_pcm_sync_type { + /* bck sync length = 1 */ + AUD_PCM_ONE_BCK_CYCLE_SYNC = 0, + /* bck sync length = PCM_INTF_CON1[9:13] */ + AUD_PCM_EXTENDED_BCK_CYCLE_SYNC = 1 +}; + +enum aud_bt_mode { + AUD_BT_MODE_DUAL_MIC_ON_TX = 0, + AUD_BT_MODE_SINGLE_MIC_ON_TX = 1 +}; + +enum aud_pcm_afifo_src { + /* slave mode & external modem uses different crystal */ + AUD_PCM_AFIFO_ASRC = 0, + /* slave mode & external modem uses the same crystal */ + AUD_PCM_AFIFO_AFIFO = 1 +}; + +enum aud_pcm_clock_source { + AUD_PCM_CLOCK_MASTER_MODE = 0, + AUD_PCM_CLOCK_SLAVE_MODE = 1 +}; + +enum aud_pcm_wlen { + AUD_PCM_WLEN_PCM_32_BCK_CYCLES = 0, + AUD_PCM_WLEN_PCM_64_BCK_CYCLES = 1 +}; + +enum aud_pcm_24bit { + AUD_PCM_24BIT_PCM_16_BITS = 0, + AUD_PCM_24BIT_PCM_24_BITS = 1 +}; + +enum aud_pcm_mode { + AUD_PCM_MODE_PCM_MODE_8K = 0, + AUD_PCM_MODE_PCM_MODE_16K = 1, + AUD_PCM_MODE_PCM_MODE_32K = 2, + AUD_PCM_MODE_PCM_MODE_48K = 3, +}; + +enum aud_pcm_fmt { + AUD_PCM_FMT_I2S = 0, + AUD_PCM_FMT_EIAJ = 1, + AUD_PCM_FMT_PCM_MODE_A = 2, + AUD_PCM_FMT_PCM_MODE_B = 3 +}; + +enum aud_bclk_out_inv { + AUD_BCLK_OUT_INV_NO_INVERSE = 0, + AUD_BCLK_OUT_INV_INVERSE = 1 +}; + +enum aud_lrclk_out_inv { + AUD_LRCLK_OUT_INV_NO_INVERSE = 0, + AUD_LRCLK_OUT_INV_INVERSE = 1 +}; + +enum aud_pcm_en { + AUD_PCM_EN_DISABLE = 0, + AUD_PCM_EN_ENABLE = 1 +}; + +/* dai component */ +static const struct snd_kcontrol_new mtk_pcm_1_playback_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1 Switch", AFE_CONN7, + I_ADDA_UL_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN7, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN7_1, + I_DL4_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_pcm_1_playback_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2 Switch", AFE_CONN8, + I_ADDA_UL_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN8, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN8_1, + I_DL4_CH2, 1, 0), +}; + +static int mtk_pcm_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + + dev_dbg(afe->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, MT8186_DAI_PCM, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, MT8186_DAI_PCM, 0); + break; + } + + return 0; +} + +/* pcm in/out lpbk */ +static const char * const pcm_lpbk_mux_map[] = { + "Normal", "Lpbk", +}; + +static int pcm_lpbk_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_in_lpbk_mux_map_enum, + PCM_INTF_CON1, + PCM_I2S_PCM_LOOPBACK_SFT, + 1, + pcm_lpbk_mux_map, + pcm_lpbk_mux_map_value); + +static const struct snd_kcontrol_new pcm_in_lpbk_mux_control = + SOC_DAPM_ENUM("PCM In Lpbk Select", pcm_in_lpbk_mux_map_enum); + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(pcm_out_lpbk_mux_map_enum, + PCM_INTF_CON1, + PCM_I2S_PCM_LOOPBACK_SFT, + 1, + pcm_lpbk_mux_map, + pcm_lpbk_mux_map_value); + +static const struct snd_kcontrol_new pcm_out_lpbk_mux_control = + SOC_DAPM_ENUM("PCM Out Lpbk Select", pcm_out_lpbk_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_pcm_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("PCM_1_PB_CH1", SND_SOC_NOPM, 0, 0, + mtk_pcm_1_playback_ch1_mix, + ARRAY_SIZE(mtk_pcm_1_playback_ch1_mix)), + SND_SOC_DAPM_MIXER("PCM_1_PB_CH2", SND_SOC_NOPM, 0, 0, + mtk_pcm_1_playback_ch2_mix, + ARRAY_SIZE(mtk_pcm_1_playback_ch2_mix)), + + SND_SOC_DAPM_SUPPLY("PCM_1_EN", + PCM_INTF_CON1, PCM_EN_SFT, 0, + mtk_pcm_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + /* pcm in lpbk */ + SND_SOC_DAPM_MUX("PCM_In_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &pcm_in_lpbk_mux_control), + + /* pcm out lpbk */ + SND_SOC_DAPM_MUX("PCM_Out_Lpbk_Mux", + SND_SOC_NOPM, 0, 0, &pcm_out_lpbk_mux_control), +}; + +static const struct snd_soc_dapm_route mtk_dai_pcm_routes[] = { + {"PCM 1 Playback", NULL, "PCM_1_PB_CH1"}, + {"PCM 1 Playback", NULL, "PCM_1_PB_CH2"}, + + {"PCM 1 Playback", NULL, "PCM_1_EN"}, + {"PCM 1 Capture", NULL, "PCM_1_EN"}, + + {"PCM_1_PB_CH1", "DL2_CH1 Switch", "DL2"}, + {"PCM_1_PB_CH2", "DL2_CH2 Switch", "DL2"}, + + {"PCM_1_PB_CH1", "DL4_CH1 Switch", "DL4"}, + {"PCM_1_PB_CH2", "DL4_CH2 Switch", "DL4"}, + + /* pcm out lpbk */ + {"PCM_Out_Lpbk_Mux", "Lpbk", "PCM 1 Playback"}, + {"I2S0", NULL, "PCM_Out_Lpbk_Mux"}, + + /* pcm in lpbk */ + {"PCM_In_Lpbk_Mux", "Lpbk", "PCM 1 Capture"}, + {"I2S3", NULL, "PCM_In_Lpbk_Mux"}, +}; + +/* dai ops */ +static int mtk_dai_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int pcm_id = dai->id; + struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[pcm_id]; + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, dai->id); + snd_pcm_format_t format = params_format(params); + unsigned int data_width = + snd_pcm_format_width(format); + unsigned int wlen_width = + snd_pcm_format_physical_width(format); + unsigned int pcm_con = 0; + + dev_dbg(afe->dev, "%s(), id %d, stream %d, widget active p %d, c %d\n", + __func__, dai->id, substream->stream, dai->playback_widget->active, + dai->capture_widget->active); + dev_dbg(afe->dev, "%s(), rate %d, rate_reg %d, data_width %d, wlen_width %d\n", + __func__, rate, rate_reg, data_width, wlen_width); + + if (dai->playback_widget->active || dai->capture_widget->active) + return 0; + + switch (dai->id) { + case MT8186_DAI_PCM: + pcm_con |= AUD_TX_LCH_RPT_NO_REPEAT << PCM_TX_LCH_RPT_SFT; + pcm_con |= AUD_VBT_16K_MODE_DISABLE << PCM_VBT_16K_MODE_SFT; + pcm_con |= AUD_EXT_MODEM_SELECT_EXTERNAL << PCM_EXT_MODEM_SFT; + pcm_con |= AUD_PCM_ONE_BCK_CYCLE_SYNC << PCM_SYNC_TYPE_SFT; + pcm_con |= AUD_BT_MODE_DUAL_MIC_ON_TX << PCM_BT_MODE_SFT; + pcm_con |= AUD_PCM_AFIFO_AFIFO << PCM_BYP_ASRC_SFT; + pcm_con |= AUD_PCM_CLOCK_MASTER_MODE << PCM_SLAVE_SFT; + pcm_con |= 0 << PCM_SYNC_LENGTH_SFT; + + /* sampling rate */ + pcm_con |= rate_reg << PCM_MODE_SFT; + + /* format */ + pcm_con |= pcm_priv->fmt << PCM_FMT_SFT; + + /* 24bit data width */ + if (data_width > 16) + pcm_con |= AUD_PCM_24BIT_PCM_24_BITS << PCM_24BIT_SFT; + else + pcm_con |= AUD_PCM_24BIT_PCM_16_BITS << PCM_24BIT_SFT; + + /* wlen width*/ + if (wlen_width > 16) + pcm_con |= AUD_PCM_WLEN_PCM_64_BCK_CYCLES << PCM_WLEN_SFT; + else + pcm_con |= AUD_PCM_WLEN_PCM_32_BCK_CYCLES << PCM_WLEN_SFT; + + /* clock invert */ + pcm_con |= pcm_priv->lck_invert << PCM_SYNC_OUT_INV_SFT; + pcm_con |= pcm_priv->bck_invert << PCM_BCLK_OUT_INV_SFT; + + regmap_update_bits(afe->regmap, PCM_INTF_CON1, 0xfffffffe, pcm_con); + break; + default: + dev_err(afe->dev, "%s(), id %d not support\n", __func__, dai->id); + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_pcm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_pcm_priv *pcm_priv = afe_priv->dai_priv[dai->id]; + + if (!pcm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + /* DAI mode*/ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + pcm_priv->fmt = AUD_PCM_FMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + pcm_priv->fmt = AUD_PCM_FMT_EIAJ; + break; + case SND_SOC_DAIFMT_DSP_A: + pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_A; + break; + case SND_SOC_DAIFMT_DSP_B: + pcm_priv->fmt = AUD_PCM_FMT_PCM_MODE_B; + break; + default: + pcm_priv->fmt = AUD_PCM_FMT_I2S; + } + + /* DAI clock inversion*/ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + case SND_SOC_DAIFMT_NB_IF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; + break; + case SND_SOC_DAIFMT_IB_NF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + case SND_SOC_DAIFMT_IB_IF: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_INVERSE; + pcm_priv->lck_invert = AUD_BCLK_OUT_INV_INVERSE; + break; + default: + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + break; + } + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_pcm_ops = { + .hw_params = mtk_dai_pcm_hw_params, + .set_fmt = mtk_dai_pcm_set_fmt, +}; + +/* dai driver */ +#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000 |\ + SNDRV_PCM_RATE_16000 |\ + SNDRV_PCM_RATE_32000 |\ + SNDRV_PCM_RATE_48000) + +#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_pcm_driver[] = { + { + .name = "PCM 1", + .id = MT8186_DAI_PCM, + .playback = { + .stream_name = "PCM 1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .capture = { + .stream_name = "PCM 1 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_PCM_RATES, + .formats = MTK_PCM_FORMATS, + }, + .ops = &mtk_dai_pcm_ops, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, + }, +}; + +static struct mtk_afe_pcm_priv *init_pcm_priv_data(struct mtk_base_afe *afe) +{ + struct mtk_afe_pcm_priv *pcm_priv; + + pcm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_pcm_priv), + GFP_KERNEL); + if (!pcm_priv) + return NULL; + + pcm_priv->id = MT8186_DAI_PCM; + pcm_priv->fmt = AUD_PCM_FMT_I2S; + pcm_priv->bck_invert = AUD_BCLK_OUT_INV_NO_INVERSE; + pcm_priv->lck_invert = AUD_LRCLK_OUT_INV_NO_INVERSE; + + return pcm_priv; +} + +int mt8186_dai_pcm_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_pcm_priv *pcm_priv; + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_pcm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_pcm_driver); + + dai->dapm_widgets = mtk_dai_pcm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_pcm_widgets); + dai->dapm_routes = mtk_dai_pcm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_pcm_routes); + + pcm_priv = init_pcm_priv_data(afe); + if (!pcm_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8186_DAI_PCM] = pcm_priv; + + return 0; +} From patchwork Mon May 23 13:28:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859082 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 D1805C433F5 for ; Mon, 23 May 2022 13:46:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=N4/BEflA40UyLnlatWAbq9UKl0Fg2zgzw88yg10r9JA=; b=WmEA/tVyuPE7Mx sw7rLfw5J5QrpOx0bIE78UTPtn+KcVxxNQMYG4dmKW0hBwRtFl9A8yW29X2TEVWGvHunTyMWdSF2/ hz2qebfctS42rb+h5kVbZLuAK17g6u6SP5CLIKO9c6s1H3x7YtY2+LNKtv7dYO2X0LZZQ4Q0OhY+H 7BHe+BPu/KMZiLjw+EEdGG3AR5IU2tE3N89Hd6CkdYHl5n3i7DhZYSCEIo+t1MjWKCWMChSjeaGXi TDtk+wRy7sTrVqFcxRO23h1ocX6D0cNjPzJ0YH1WKR+a0FD8S+HWVTim0eje4SEePjMFVYdhQSbGJ dwUi2m8y1xRkIBHRMkCw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Mu-004VeI-6f; Mon, 23 May 2022 13:45:08 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Hb-004Srh-Ja; Mon, 23 May 2022 13:39:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Type:Content-Transfer-Encoding :MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From: Sender:Reply-To:Content-ID:Content-Description; bh=wnnypbz//h/UKFlI2sKEngD20bIm0YnKS9MYlLqt/tQ=; b=B1RoRdu6YTCw485ETJbooechJZ XrUXKXUzp/DgNR0/UwGotSMqbevUm3w0Lt5V7bq/Vv9Uf2iI6QAdJgyvAXVrXRBfis4z9wQDjIyVt q5jtP1omGusKFoP7WLr2KeiURoJC9E4r93XZ3IYq9x2ZEKk8G1GqPffhkInfgp5Tae9fqfWWUY9vs qb/NRUHQDOGaMsSGCvluKH5yX6fFUYN6H4R2pMs65lAvNRZOhxdq/YBZMhyjugsuuaKUSvC5qGPpj jmrKQifugT2KcGDYI1/LpA5dHB+SbyCei238aaZe+KZQj88m2tiLmAr/lF8N7o8HDUPAvBlK5hU3J SpeHsSqg==; Received: from mailgw02.mediatek.com ([216.200.240.185]) by desiato.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HR-0014MK-Jt; Mon, 23 May 2022 13:39:36 +0000 X-UUID: 44d62e30ec0640799cc3d550c9ba7105-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:1d68133c-e3d6-4605-86ba-f2c28459dbe4, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-20,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,AC TION:release,TS:-20 X-CID-META: VersionHash:2a19b09, CLOUDID:26293ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:1,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 44d62e30ec0640799cc3d550c9ba7105-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1221805884; Mon, 23 May 2022 06:39:13 -0700 Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:11 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.15; Mon, 23 May 2022 21:29:09 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:08 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 09/20] ASoC: mediatek: mt8186: support src in platform driver Date: Mon, 23 May 2022 21:28:47 +0800 Message-ID: <20220523132858.22166-10-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_143930_639330_1F949E41 X-CRM114-Status: GOOD ( 18.28 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 src dai driver Signed-off-by: Jiaxin Yu --- sound/soc/mediatek/mt8186/mt8186-dai-src.c | 695 +++++++++++++++++++++ 1 file changed, 695 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-src.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-src.c b/sound/soc/mediatek/mt8186/mt8186-dai-src.c new file mode 100644 index 000000000000..67989ffd67ca --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-src.c @@ -0,0 +1,695 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI SRC Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include "mt8186-afe-common.h" +#include "mt8186-interconnection.h" + +struct mtk_afe_src_priv { + int dl_rate; + int ul_rate; +}; + +static const unsigned int src_iir_coeff_32_to_16[] = { + 0x0dbae6, 0xff9b0a, 0x0dbae6, 0x05e488, 0xe072b9, 0x000002, + 0x0dbae6, 0x000f3b, 0x0dbae6, 0x06a537, 0xe17d79, 0x000002, + 0x0dbae6, 0x01246a, 0x0dbae6, 0x087261, 0xe306be, 0x000002, + 0x0dbae6, 0x03437d, 0x0dbae6, 0x0bc16f, 0xe57c87, 0x000002, + 0x0dbae6, 0x072981, 0x0dbae6, 0x111dd3, 0xe94f2a, 0x000002, + 0x0dbae6, 0x0dc4a6, 0x0dbae6, 0x188611, 0xee85a0, 0x000002, + 0x0dbae6, 0x168b9a, 0x0dbae6, 0x200e8f, 0xf3ccf1, 0x000002, + 0x000000, 0x1b75cb, 0x1b75cb, 0x2374a2, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_44_to_16[] = { + 0x09ae28, 0xf7d97d, 0x09ae28, 0x212a3d, 0xe0ac3a, 0x000002, + 0x09ae28, 0xf8525a, 0x09ae28, 0x216d72, 0xe234be, 0x000002, + 0x09ae28, 0xf980f5, 0x09ae28, 0x22a057, 0xe45a81, 0x000002, + 0x09ae28, 0xfc0a08, 0x09ae28, 0x24d3bd, 0xe7752d, 0x000002, + 0x09ae28, 0x016162, 0x09ae28, 0x27da01, 0xeb6ea8, 0x000002, + 0x09ae28, 0x0b67df, 0x09ae28, 0x2aca4a, 0xef34c4, 0x000002, + 0x000000, 0x135c50, 0x135c50, 0x2c1079, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_44_to_32[] = { + 0x096966, 0x0c4d35, 0x096966, 0xedee81, 0xf05070, 0x000003, + 0x12d2cc, 0x193910, 0x12d2cc, 0xddbf4f, 0xe21e1d, 0x000002, + 0x12d2cc, 0x1a9e60, 0x12d2cc, 0xe18916, 0xe470fd, 0x000002, + 0x12d2cc, 0x1d06e0, 0x12d2cc, 0xe8a4a6, 0xe87b24, 0x000002, + 0x12d2cc, 0x207578, 0x12d2cc, 0xf4fe62, 0xef5917, 0x000002, + 0x12d2cc, 0x24055f, 0x12d2cc, 0x05ee2b, 0xf8b502, 0x000002, + 0x000000, 0x25a599, 0x25a599, 0x0fabe2, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_48_to_16[] = { + 0x0296a4, 0xfd69dd, 0x0296a4, 0x209439, 0xe01ff9, 0x000002, + 0x0f4ff3, 0xf0d6d4, 0x0f4ff3, 0x209bc9, 0xe076c3, 0x000002, + 0x0e8490, 0xf1fe63, 0x0e8490, 0x20cfd6, 0xe12124, 0x000002, + 0x14852f, 0xed794a, 0x14852f, 0x21503d, 0xe28b32, 0x000002, + 0x136222, 0xf17677, 0x136222, 0x225be1, 0xe56964, 0x000002, + 0x0a8d85, 0xfc4a97, 0x0a8d85, 0x24310c, 0xea6952, 0x000002, + 0x05eff5, 0x043455, 0x05eff5, 0x4ced8f, 0xe134d6, 0x000001, + 0x000000, 0x3aebe6, 0x3aebe6, 0x04f3b0, 0x000000, 0x000004 +}; + +static const unsigned int src_iir_coeff_48_to_32[] = { + 0x10c1b8, 0x10a7df, 0x10c1b8, 0xe7514e, 0xe0b41f, 0x000002, + 0x10c1b8, 0x116257, 0x10c1b8, 0xe9402f, 0xe25aaa, 0x000002, + 0x10c1b8, 0x130c89, 0x10c1b8, 0xed3cc3, 0xe4dddb, 0x000002, + 0x10c1b8, 0x1600dd, 0x10c1b8, 0xf48000, 0xe90c55, 0x000002, + 0x10c1b8, 0x1a672e, 0x10c1b8, 0x00494c, 0xefa807, 0x000002, + 0x10c1b8, 0x1f38e6, 0x10c1b8, 0x0ee076, 0xf7c5f3, 0x000002, + 0x000000, 0x218370, 0x218370, 0x168b40, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_48_to_44[] = { + 0x0bf71c, 0x170f3f, 0x0bf71c, 0xe3a4c8, 0xf096cb, 0x000003, + 0x0bf71c, 0x17395e, 0x0bf71c, 0xe58085, 0xf210c8, 0x000003, + 0x0bf71c, 0x1782bd, 0x0bf71c, 0xe95ef6, 0xf4c899, 0x000003, + 0x0bf71c, 0x17cd97, 0x0bf71c, 0xf1608a, 0xfa3b18, 0x000003, + 0x000000, 0x2fdc6f, 0x2fdc6f, 0xf15663, 0x000000, 0x000001 +}; + +static const unsigned int src_iir_coeff_96_to_16[] = { + 0x0805a1, 0xf21ae3, 0x0805a1, 0x3840bb, 0xe02a2e, 0x000002, + 0x0d5dd8, 0xe8f259, 0x0d5dd8, 0x1c0af6, 0xf04700, 0x000003, + 0x0bb422, 0xec08d9, 0x0bb422, 0x1bfccc, 0xf09216, 0x000003, + 0x08fde6, 0xf108be, 0x08fde6, 0x1bf096, 0xf10ae0, 0x000003, + 0x0ae311, 0xeeeda3, 0x0ae311, 0x37c646, 0xe385f5, 0x000002, + 0x044089, 0xfa7242, 0x044089, 0x37a785, 0xe56526, 0x000002, + 0x00c75c, 0xffb947, 0x00c75c, 0x378ba3, 0xe72c5f, 0x000002, + 0x000000, 0x0ef76e, 0x0ef76e, 0x377fda, 0x000000, 0x000001, +}; + +static const unsigned int src_iir_coeff_96_to_44[] = { + 0x08b543, 0xfd80f4, 0x08b543, 0x0e2332, 0xe06ed0, 0x000002, + 0x1b6038, 0xf90e7e, 0x1b6038, 0x0ec1ac, 0xe16f66, 0x000002, + 0x188478, 0xfbb921, 0x188478, 0x105859, 0xe2e596, 0x000002, + 0x13eff3, 0xffa707, 0x13eff3, 0x13455c, 0xe533b7, 0x000002, + 0x0dc239, 0x03d458, 0x0dc239, 0x17f120, 0xe8b617, 0x000002, + 0x0745f1, 0x05d790, 0x0745f1, 0x1e3d75, 0xed5f18, 0x000002, + 0x05641f, 0x085e2b, 0x05641f, 0x48efd0, 0xe3e9c8, 0x000001, + 0x000000, 0x28f632, 0x28f632, 0x273905, 0x000000, 0x000001, +}; + +static unsigned int mtk_get_src_freq_mode(struct mtk_base_afe *afe, int rate) +{ + switch (rate) { + case 8000: + return 0x50000; + case 11025: + return 0x6e400; + case 12000: + return 0x78000; + case 16000: + return 0xa0000; + case 22050: + return 0xdc800; + case 24000: + return 0xf0000; + case 32000: + return 0x140000; + case 44100: + return 0x1b9000; + case 48000: + return 0x1e0000; + case 88200: + return 0x372000; + case 96000: + return 0x3c0000; + case 176400: + return 0x6e4000; + case 192000: + return 0x780000; + default: + dev_err(afe->dev, "%s(), rate %d invalid!!!\n", + __func__, rate); + return 0; + } +} + +static const unsigned int *get_iir_coeff(unsigned int rate_in, + unsigned int rate_out, + unsigned int *param_num) +{ + if (rate_in == 32000 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_32_to_16); + return src_iir_coeff_32_to_16; + } else if (rate_in == 44100 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_44_to_16); + return src_iir_coeff_44_to_16; + } else if (rate_in == 44100 && rate_out == 32000) { + *param_num = ARRAY_SIZE(src_iir_coeff_44_to_32); + return src_iir_coeff_44_to_32; + } else if ((rate_in == 48000 && rate_out == 16000) || + (rate_in == 96000 && rate_out == 32000)) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_16); + return src_iir_coeff_48_to_16; + } else if (rate_in == 48000 && rate_out == 32000) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_32); + return src_iir_coeff_48_to_32; + } else if (rate_in == 48000 && rate_out == 44100) { + *param_num = ARRAY_SIZE(src_iir_coeff_48_to_44); + return src_iir_coeff_48_to_44; + } else if (rate_in == 96000 && rate_out == 16000) { + *param_num = ARRAY_SIZE(src_iir_coeff_96_to_16); + return src_iir_coeff_96_to_16; + } else if ((rate_in == 96000 && rate_out == 44100) || + (rate_in == 48000 && rate_out == 22050)) { + *param_num = ARRAY_SIZE(src_iir_coeff_96_to_44); + return src_iir_coeff_96_to_44; + } + + *param_num = 0; + return NULL; +} + +static int mtk_set_src_1_param(struct mtk_base_afe *afe, int id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int iir_coeff_num; + unsigned int iir_stage; + int rate_in = src_priv->dl_rate; + int rate_out = src_priv->ul_rate; + unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out); + unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in); + + /* set out freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON3, + G_SRC_ASM_FREQ_4_MASK_SFT, + out_freq_mode << G_SRC_ASM_FREQ_4_SFT); + + /* set in freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON4, + G_SRC_ASM_FREQ_5_MASK_SFT, + in_freq_mode << G_SRC_ASM_FREQ_5_SFT); + + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5986); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON5, 0x3f5987); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON6, 0x1fbd); + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, 0); + + /* set iir if in_rate > out_rate */ + if (rate_in > rate_out) { + int i; + const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out, + &iir_coeff_num); + + if (iir_coeff_num == 0 || !iir_coeff) { + dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n", + __func__, iir_coeff_num, iir_coeff); + return -EINVAL; + } + + /* COEFF_SRAM_CTRL */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, + BIT(G_SRC_COEFF_SRAM_CTRL_SFT)); + /* Clear coeff history to r/w coeff from the first position */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON13, + G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0); + /* Write SRC coeff, should not read the reg during write */ + for (i = 0; i < iir_coeff_num; i++) + regmap_write(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON12, + iir_coeff[i]); + /* disable sram access */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0); + /* CHSET_IIR_STAGE */ + iir_stage = (iir_coeff_num / 6) - 1; + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_STAGE_MASK_SFT, + iir_stage << G_SRC_CHSET_IIR_STAGE_SFT); + /* CHSET_IIR_EN */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, + BIT(G_SRC_CHSET_IIR_EN_SFT)); + } else { + /* CHSET_IIR_EN off */ + regmap_update_bits(afe->regmap, AFE_GENERAL1_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, 0); + } + + return 0; +} + +static int mtk_set_src_2_param(struct mtk_base_afe *afe, int id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int iir_coeff_num; + unsigned int iir_stage; + int rate_in = src_priv->dl_rate; + int rate_out = src_priv->ul_rate; + unsigned int out_freq_mode = mtk_get_src_freq_mode(afe, rate_out); + unsigned int in_freq_mode = mtk_get_src_freq_mode(afe, rate_in); + + /* set out freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON3, + G_SRC_ASM_FREQ_4_MASK_SFT, + out_freq_mode << G_SRC_ASM_FREQ_4_SFT); + + /* set in freq mode */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON4, + G_SRC_ASM_FREQ_5_MASK_SFT, + in_freq_mode << G_SRC_ASM_FREQ_5_SFT); + + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5986); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON5, 0x3f5987); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON6, 0x1fbd); + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, 0); + + /* set iir if in_rate > out_rate */ + if (rate_in > rate_out) { + int i; + const unsigned int *iir_coeff = get_iir_coeff(rate_in, rate_out, + &iir_coeff_num); + + if (iir_coeff_num == 0 || !iir_coeff) { + dev_err(afe->dev, "%s(), iir coeff error, num %d, coeff %p\n", + __func__, iir_coeff_num, iir_coeff); + return -EINVAL; + } + + /* COEFF_SRAM_CTRL */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, + BIT(G_SRC_COEFF_SRAM_CTRL_SFT)); + /* Clear coeff history to r/w coeff from the first position */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON13, + G_SRC_COEFF_SRAM_ADR_MASK_SFT, 0); + /* Write SRC coeff, should not read the reg during write */ + for (i = 0; i < iir_coeff_num; i++) + regmap_write(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON12, + iir_coeff[i]); + /* disable sram access */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON0, + G_SRC_COEFF_SRAM_CTRL_MASK_SFT, 0); + /* CHSET_IIR_STAGE */ + iir_stage = (iir_coeff_num / 6) - 1; + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_STAGE_MASK_SFT, + iir_stage << G_SRC_CHSET_IIR_STAGE_SFT); + /* CHSET_IIR_EN */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, + BIT(G_SRC_CHSET_IIR_EN_SFT)); + } else { + /* CHSET_IIR_EN off */ + regmap_update_bits(afe->regmap, AFE_GENERAL2_ASRC_2CH_CON2, + G_SRC_CHSET_IIR_EN_MASK_SFT, 0); + } + + return 0; +} + +#define HW_SRC_1_EN_W_NAME "HW_SRC_1_Enable" +#define HW_SRC_2_EN_W_NAME "HW_SRC_2_Enable" + +static int mtk_hw_src_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id; + struct mtk_afe_src_priv *src_priv; + unsigned int reg; + + if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0) + id = MT8186_DAI_SRC_1; + else + id = MT8186_DAI_SRC_2; + + src_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, + "%s(), name %s, event 0x%x, id %d, src_priv %p, dl_rate %d, ul_rate %d\n", + __func__, w->name, event, id, src_priv, + src_priv->dl_rate, src_priv->ul_rate); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + if (id == MT8186_DAI_SRC_1) + mtk_set_src_1_param(afe, id); + else + mtk_set_src_2_param(afe, id); + break; + case SND_SOC_DAPM_POST_PMU: + reg = (id == MT8186_DAI_SRC_1) ? + AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0; + /* ASM_ON */ + regmap_update_bits(afe->regmap, reg, + G_SRC_ASM_ON_MASK_SFT, + BIT(G_SRC_ASM_ON_SFT)); + /* CHSET_ON */ + regmap_update_bits(afe->regmap, reg, + G_SRC_CHSET_ON_MASK_SFT, + BIT(G_SRC_CHSET_ON_SFT)); + /* CHSET_STR_CLR */ + regmap_update_bits(afe->regmap, reg, + G_SRC_CHSET_STR_CLR_MASK_SFT, + BIT(G_SRC_CHSET_STR_CLR_SFT)); + break; + case SND_SOC_DAPM_PRE_PMD: + reg = (id == MT8186_DAI_SRC_1) ? + AFE_GENERAL1_ASRC_2CH_CON0 : AFE_GENERAL2_ASRC_2CH_CON0; + /* ASM_OFF */ + regmap_update_bits(afe->regmap, reg, G_SRC_ASM_ON_MASK_SFT, 0); + /* CHSET_OFF */ + regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_ON_MASK_SFT, 0); + /* CHSET_STR_CLR */ + regmap_update_bits(afe->regmap, reg, G_SRC_CHSET_STR_CLR_MASK_SFT, 0); + break; + default: + break; + } + + return 0; +} + +/* dai component */ +static const struct snd_kcontrol_new mtk_hw_src_1_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN40, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN40, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN40, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN40_1, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN40_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH1 Switch", AFE_CONN40, + I_I2S0_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN40_1, + I_DL5_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_1_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN41, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN41, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN41, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN41_1, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN41_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I2S0_CH2 Switch", AFE_CONN41, + I_I2S0_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN41_1, + I_DL5_CH2, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_2_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1 Switch", AFE_CONN42, + I_DL1_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1 Switch", AFE_CONN42, + I_DL2_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1 Switch", AFE_CONN42, + I_DL3_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1 Switch", AFE_CONN42, + I_DL4_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1 Switch", AFE_CONN42_1, + I_DL5_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1 Switch", AFE_CONN42_1, + I_DL6_CH1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH1 Switch", AFE_CONN42, + I_GAIN2_OUT_CH1, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_src_2_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2 Switch", AFE_CONN43, + I_DL1_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2 Switch", AFE_CONN43, + I_DL2_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2 Switch", AFE_CONN43, + I_DL3_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2 Switch", AFE_CONN43, + I_DL4_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2 Switch", AFE_CONN43_1, + I_DL5_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2 Switch", AFE_CONN43_1, + I_DL6_CH2, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN2_OUT_CH2 Switch", AFE_CONN43, + I_GAIN2_OUT_CH2, 1, 0), +}; + +static const struct snd_soc_dapm_widget mtk_dai_src_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_src_1_in_ch1_mix, + ARRAY_SIZE(mtk_hw_src_1_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_1_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_src_1_in_ch2_mix, + ARRAY_SIZE(mtk_hw_src_1_in_ch2_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH1", SND_SOC_NOPM, 0, 0, + mtk_hw_src_2_in_ch1_mix, + ARRAY_SIZE(mtk_hw_src_2_in_ch1_mix)), + SND_SOC_DAPM_MIXER("HW_SRC_2_IN_CH2", SND_SOC_NOPM, 0, 0, + mtk_hw_src_2_in_ch2_mix, + ARRAY_SIZE(mtk_hw_src_2_in_ch2_mix)), + + SND_SOC_DAPM_SUPPLY(HW_SRC_1_EN_W_NAME, + GENERAL_ASRC_EN_ON, GENERAL1_ASRC_EN_ON_SFT, 0, + mtk_hw_src_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY(HW_SRC_2_EN_W_NAME, + GENERAL_ASRC_EN_ON, GENERAL2_ASRC_EN_ON_SFT, 0, + mtk_hw_src_event, + SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_INPUT("HW SRC 1 Out Endpoint"), + SND_SOC_DAPM_INPUT("HW SRC 2 Out Endpoint"), + SND_SOC_DAPM_OUTPUT("HW SRC 1 In Endpoint"), + SND_SOC_DAPM_OUTPUT("HW SRC 2 In Endpoint"), +}; + +static int mtk_afe_src_en_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = source; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_src_priv *src_priv; + + if (strcmp(w->name, HW_SRC_1_EN_W_NAME) == 0) + src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_1]; + else + src_priv = afe_priv->dai_priv[MT8186_DAI_SRC_2]; + + dev_dbg(afe->dev, + "%s(), source %s, sink %s, dl_rate %d, ul_rate %d\n", + __func__, source->name, sink->name, + src_priv->dl_rate, src_priv->ul_rate); + + return (src_priv->dl_rate > 0 && src_priv->ul_rate > 0) ? 1 : 0; +} + +static const struct snd_soc_dapm_route mtk_dai_src_routes[] = { + {"HW_SRC_1_IN_CH1", "DL1_CH1 Switch", "DL1"}, + {"HW_SRC_1_IN_CH2", "DL1_CH2 Switch", "DL1"}, + {"HW_SRC_2_IN_CH1", "DL1_CH1 Switch", "DL1"}, + {"HW_SRC_2_IN_CH2", "DL1_CH2 Switch", "DL1"}, + {"HW_SRC_1_IN_CH1", "DL2_CH1 Switch", "DL2"}, + {"HW_SRC_1_IN_CH2", "DL2_CH2 Switch", "DL2"}, + {"HW_SRC_2_IN_CH1", "DL2_CH1 Switch", "DL2"}, + {"HW_SRC_2_IN_CH2", "DL2_CH2 Switch", "DL2"}, + {"HW_SRC_1_IN_CH1", "DL3_CH1 Switch", "DL3"}, + {"HW_SRC_1_IN_CH2", "DL3_CH2 Switch", "DL3"}, + {"HW_SRC_2_IN_CH1", "DL3_CH1 Switch", "DL3"}, + {"HW_SRC_2_IN_CH2", "DL3_CH2 Switch", "DL3"}, + {"HW_SRC_1_IN_CH1", "DL6_CH1 Switch", "DL6"}, + {"HW_SRC_1_IN_CH2", "DL6_CH2 Switch", "DL6"}, + {"HW_SRC_2_IN_CH1", "DL6_CH1 Switch", "DL6"}, + {"HW_SRC_2_IN_CH2", "DL6_CH2 Switch", "DL6"}, + {"HW_SRC_1_IN_CH1", "DL5_CH1 Switch", "DL5"}, + {"HW_SRC_1_IN_CH2", "DL5_CH2 Switch", "DL5"}, + {"HW_SRC_2_IN_CH1", "DL5_CH1 Switch", "DL5"}, + {"HW_SRC_2_IN_CH2", "DL5_CH2 Switch", "DL5"}, + {"HW_SRC_1_IN_CH1", "DL4_CH1 Switch", "DL4"}, + {"HW_SRC_1_IN_CH2", "DL4_CH2 Switch", "DL4"}, + {"HW_SRC_2_IN_CH1", "DL4_CH1 Switch", "DL4"}, + {"HW_SRC_2_IN_CH2", "DL4_CH2 Switch", "DL4"}, + + {"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH1"}, + {"HW_SRC_1_In", NULL, "HW_SRC_1_IN_CH2"}, + + {"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH1"}, + {"HW_SRC_2_In", NULL, "HW_SRC_2_IN_CH2"}, + + {"HW_SRC_1_In", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_1_Out", NULL, HW_SRC_1_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_2_In", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect}, + {"HW_SRC_2_Out", NULL, HW_SRC_2_EN_W_NAME, mtk_afe_src_en_connect}, + + {"HW SRC 1 In Endpoint", NULL, "HW_SRC_1_In"}, + {"HW SRC 2 In Endpoint", NULL, "HW_SRC_2_In"}, + {"HW_SRC_1_Out", NULL, "HW SRC 1 Out Endpoint"}, + {"HW_SRC_2_Out", NULL, "HW SRC 2 Out Endpoint"}, +}; + +/* dai ops */ +static int mtk_dai_src_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id = dai->id; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + unsigned int sft, mask; + unsigned int rate = params_rate(params); + unsigned int rate_reg = mt8186_rate_transform(afe->dev, rate, id); + + dev_dbg(afe->dev, "%s(), id %d, stream %d, rate %d\n", + __func__, id, substream->stream, rate); + + /* rate */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + src_priv->dl_rate = rate; + if (id == MT8186_DAI_SRC_1) { + sft = GENERAL1_ASRCIN_MODE_SFT; + mask = GENERAL1_ASRCIN_MODE_MASK; + } else { + sft = GENERAL2_ASRCIN_MODE_SFT; + mask = GENERAL2_ASRCIN_MODE_MASK; + } + } else { + src_priv->ul_rate = rate; + if (id == MT8186_DAI_SRC_1) { + sft = GENERAL1_ASRCOUT_MODE_SFT; + mask = GENERAL1_ASRCOUT_MODE_MASK; + } else { + sft = GENERAL2_ASRCOUT_MODE_SFT; + mask = GENERAL2_ASRCOUT_MODE_MASK; + } + } + + regmap_update_bits(afe->regmap, GENERAL_ASRC_MODE, mask << sft, rate_reg << sft); + + return 0; +} + +static int mtk_dai_src_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int id = dai->id; + struct mtk_afe_src_priv *src_priv = afe_priv->dai_priv[id]; + + dev_dbg(afe->dev, "%s(), id %d, stream %d\n", + __func__, id, substream->stream); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + src_priv->dl_rate = 0; + else + src_priv->ul_rate = 0; + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_src_ops = { + .hw_params = mtk_dai_src_hw_params, + .hw_free = mtk_dai_src_hw_free, +}; + +/* dai driver */ +#define MTK_SRC_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_SRC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_src_driver[] = { + { + .name = "HW_SRC_1", + .id = MT8186_DAI_SRC_1, + .playback = { + .stream_name = "HW_SRC_1_In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .capture = { + .stream_name = "HW_SRC_1_Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .ops = &mtk_dai_src_ops, + }, + { + .name = "HW_SRC_2", + .id = MT8186_DAI_SRC_2, + .playback = { + .stream_name = "HW_SRC_2_In", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .capture = { + .stream_name = "HW_SRC_2_Out", + .channels_min = 1, + .channels_max = 2, + .rates = MTK_SRC_RATES, + .formats = MTK_SRC_FORMATS, + }, + .ops = &mtk_dai_src_ops, + }, +}; + +int mt8186_dai_src_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + int ret; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_src_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_src_driver); + + dai->dapm_widgets = mtk_dai_src_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_src_widgets); + dai->dapm_routes = mtk_dai_src_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_src_routes); + + /* set dai priv */ + ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_1, + sizeof(struct mtk_afe_src_priv), NULL); + if (ret) + return ret; + + ret = mt8186_dai_set_priv(afe, MT8186_DAI_SRC_2, + sizeof(struct mtk_afe_src_priv), NULL); + if (ret) + return ret; + + return 0; +} From patchwork Mon May 23 13:28:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859060 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 0E819C433EF for ; Mon, 23 May 2022 13:41:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=hVA7ns5qmFh6jyEV3JFJnFEqmiqx2ND3yqa+fTVs+40=; b=4l9wrHOYJGGnGR T0UbrfP7SpAMC30gnCW3WpTuV4tXsFxspPLcsxbwurpdLLT5ZyYO4J6eKm/mWUefVE2i2XCYtB+ID Q58yIfLEK/1h+Uw8WzjRYlremrjdLk7woJVOC86kyfV1Lj3AJw7OioFmJdGarBs0MIszEhwhHlZVY t0ms9XlSpT0PMJFmasXkr23pXewqB1aT/VRobxWwyDbPgeqW3TYA8ce0Dxrt3o9H+mSuSo0wZbqOK XvtZ+FtQBTVZNRRpsfUO2uyLpb5ywer4Qv+AdmYFakVCGk74FbNr4FF+l9l6N37zUo4qzRMl2PUM4 zQPywor71o6fYT2/ED/A==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Hp-004SvH-AU; Mon, 23 May 2022 13:39:53 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HC-004ShK-Q6; Mon, 23 May 2022 13:39:19 +0000 X-UUID: d9df7b861e1f4926831958c4a4ffac93-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:3481db82-0ad9-48fb-b11e-26b6adaf1ad4, OB:0, LO B:0,IP:0,URL:5,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:5 X-CID-META: VersionHash:2a19b09, CLOUDID:8a204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: d9df7b861e1f4926831958c4a4ffac93-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 773125197; Mon, 23 May 2022 06:39:08 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:12 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:10 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:09 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 10/20] ASoC: mediatek: mt8186: support tdm in platform driver Date: Mon, 23 May 2022 21:28:48 +0800 Message-ID: <20220523132858.22166-11-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063914_885444_406BED98 X-CRM114-Status: GOOD ( 18.79 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 tdm dai driver. Signed-off-by: Jiaxin Yu --- sound/soc/mediatek/mt8186/mt8186-dai-tdm.c | 698 +++++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-dai-tdm.c diff --git a/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c new file mode 100644 index 000000000000..dfff209b60da --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-dai-tdm.c @@ -0,0 +1,698 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// MediaTek ALSA SoC Audio DAI TDM Control +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include + +#include "mt8186-afe-clk.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-interconnection.h" + +#define TDM_HD_EN_W_NAME "TDM_HD_EN" +#define TDM_MCLK_EN_W_NAME "TDM_MCLK_EN" +#define MTK_AFE_TDM_KCONTROL_NAME "TDM_HD_Mux" + +struct mtk_afe_tdm_priv { + unsigned int id; + unsigned int rate; /* for determine which apll to use */ + unsigned int bck_invert; + unsigned int lck_invert; + unsigned int lrck_width; + unsigned int mclk_id; + unsigned int mclk_multiple; /* according to sample rate */ + unsigned int mclk_rate; + unsigned int mclk_apll; + unsigned int tdm_mode; + unsigned int data_mode; + unsigned int slave_mode; + unsigned int low_jitter_en; +}; + +enum { + TDM_IN_I2S = 0, + TDM_IN_LJ = 1, + TDM_IN_RJ = 2, + TDM_IN_DSP_A = 4, + TDM_IN_DSP_B = 5, +}; + +enum { + TDM_DATA_ONE_PIN = 0, + TDM_DATA_MULTI_PIN, +}; + +enum { + TDM_BCK_NON_INV = 0, + TDM_BCK_INV = 1, +}; + +enum { + TDM_LCK_NON_INV = 0, + TDM_LCK_INV = 1, +}; + +static unsigned int get_tdm_lrck_width(snd_pcm_format_t format, + unsigned int mode) +{ + if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B) + return 0; + + return snd_pcm_format_physical_width(format) - 1; +} + +static unsigned int get_tdm_ch_fixup(unsigned int channels) +{ + if (channels > 4) + return 8; + else if (channels > 2) + return 4; + + return 2; +} + +static unsigned int get_tdm_ch_per_sdata(unsigned int mode, + unsigned int channels) +{ + if (mode == TDM_IN_DSP_A || mode == TDM_IN_DSP_B) + return get_tdm_ch_fixup(channels); + + return 2; +} + +enum { + SUPPLY_SEQ_APLL, + SUPPLY_SEQ_TDM_MCK_EN, + SUPPLY_SEQ_TDM_HD_EN, + SUPPLY_SEQ_TDM_EN, +}; + +static int get_tdm_id_by_name(const char *name) +{ + return MT8186_DAI_TDM_IN; +} + +static int mtk_tdm_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x\n", + __func__, w->name, event); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_afe_gpio_request(afe->dev, true, tdm_priv->id, 0); + break; + case SND_SOC_DAPM_POST_PMD: + mt8186_afe_gpio_request(afe->dev, false, tdm_priv->id, 0); + break; + default: + break; + } + + return 0; +} + +static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, + int event) +{ + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + dev_dbg(cmpnt->dev, "%s(), name %s, event 0x%x, dai_id %d\n", + __func__, w->name, event, dai_id); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + mt8186_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate); + break; + case SND_SOC_DAPM_POST_PMD: + tdm_priv->mclk_rate = 0; + mt8186_mck_disable(afe, tdm_priv->mclk_id); + break; + default: + break; + } + + return 0; +} + +/* dai component */ +/* tdm virtual mux to output widget */ +static const char * const tdm_mux_map[] = { + "Normal", "Dummy_Widget", +}; + +static int tdm_mux_map_value[] = { + 0, 1, +}; + +static SOC_VALUE_ENUM_SINGLE_AUTODISABLE_DECL(tdm_mux_map_enum, + SND_SOC_NOPM, + 0, + 1, + tdm_mux_map, + tdm_mux_map_value); + +static const struct snd_kcontrol_new tdm_in_mux_control = + SOC_DAPM_ENUM("TDM In Select", tdm_mux_map_enum); + +static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = { + SND_SOC_DAPM_CLOCK_SUPPLY("aud_tdm_clk"), + + SND_SOC_DAPM_SUPPLY_S("TDM_EN", SUPPLY_SEQ_TDM_EN, + ETDM_IN1_CON0, ETDM_IN1_CON0_REG_ETDM_IN_EN_SFT, + 0, mtk_tdm_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + /* tdm hd en */ + SND_SOC_DAPM_SUPPLY_S(TDM_HD_EN_W_NAME, SUPPLY_SEQ_TDM_HD_EN, + ETDM_IN1_CON2, ETDM_IN1_CON2_REG_CLOCK_SOURCE_SEL_SFT, + 0, NULL, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_SUPPLY_S(TDM_MCLK_EN_W_NAME, SUPPLY_SEQ_TDM_MCK_EN, + SND_SOC_NOPM, 0, 0, + mtk_tdm_mck_en_event, + SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + + SND_SOC_DAPM_INPUT("TDM_DUMMY_IN"), + + SND_SOC_DAPM_MUX("TDM_In_Mux", + SND_SOC_NOPM, 0, 0, &tdm_in_mux_control), +}; + +static int mtk_afe_tdm_mclk_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + return (tdm_priv->mclk_rate > 0) ? 1 : 0; +} + +static int mtk_afe_tdm_mclk_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + int cur_apll; + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0; +} + +static int mtk_afe_tdm_hd_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + return tdm_priv->low_jitter_en; +} + +static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source, + struct snd_soc_dapm_widget *sink) +{ + struct snd_soc_dapm_widget *w = sink; + struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(w->name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + int cur_apll; + int tdm_need_apll; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return 0; + } + + /* which apll */ + cur_apll = mt8186_get_apll_by_name(afe, source->name); + + /* choose APLL from tdm rate */ + tdm_need_apll = mt8186_get_apll_by_rate(afe, tdm_priv->rate); + + return (tdm_need_apll == cur_apll) ? 1 : 0; +} + +/* low jitter control */ +static const char * const mt8186_tdm_hd_str[] = { + "Normal", "Low_Jitter" +}; + +static const struct soc_enum mt8186_tdm_enum[] = { + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mt8186_tdm_hd_str), + mt8186_tdm_hd_str), +}; + +static int mt8186_tdm_hd_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(kcontrol->id.name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + ucontrol->value.integer.value[0] = tdm_priv->low_jitter_en; + + return 0; +} + +static int mt8186_tdm_hd_set(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *cmpnt = snd_soc_kcontrol_component(kcontrol); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int dai_id = get_tdm_id_by_name(kcontrol->id.name); + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id]; + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + int hd_en; + + if (ucontrol->value.enumerated.item[0] >= e->items) + return -EINVAL; + + hd_en = ucontrol->value.integer.value[0]; + + dev_dbg(afe->dev, "%s(), kcontrol name %s, hd_en %d\n", + __func__, kcontrol->id.name, hd_en); + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + if (tdm_priv->low_jitter_en == hd_en) + return 0; + + tdm_priv->low_jitter_en = hd_en; + + return 1; +} + +static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = { + SOC_ENUM_EXT(MTK_AFE_TDM_KCONTROL_NAME, mt8186_tdm_enum[0], + mt8186_tdm_hd_get, mt8186_tdm_hd_set), +}; + +static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = { + {"TDM IN", NULL, "aud_tdm_clk"}, + {"TDM IN", NULL, "TDM_EN"}, + {"TDM IN", NULL, TDM_HD_EN_W_NAME, mtk_afe_tdm_hd_connect}, + {TDM_HD_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect}, + {TDM_HD_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect}, + + {"TDM IN", NULL, TDM_MCLK_EN_W_NAME, mtk_afe_tdm_mclk_connect}, + {TDM_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_tdm_mclk_apll_connect}, + {TDM_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_tdm_mclk_apll_connect}, + + /* allow tdm on without codec on */ + {"TDM IN", NULL, "TDM_In_Mux"}, + {"TDM_In_Mux", "Dummy_Widget", "TDM_DUMMY_IN"}, +}; + +/* dai ops */ +static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe, + struct mtk_afe_tdm_priv *tdm_priv, + int freq) +{ + int apll; + int apll_rate; + + apll = mt8186_get_apll_by_rate(afe, freq); + apll_rate = mt8186_get_apll_rate(afe, apll); + + if (!freq || freq > apll_rate) { + dev_err(afe->dev, + "%s(), freq(%d Hz) invalid\n", __func__, freq); + return -EINVAL; + } + + if (apll_rate % freq != 0) { + dev_err(afe->dev, + "%s(), APLL cannot generate %d Hz", __func__, freq); + return -EINVAL; + } + + tdm_priv->mclk_rate = freq; + tdm_priv->mclk_apll = apll; + + return 0; +} + +static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int tdm_id = dai->id; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[tdm_id]; + unsigned int tdm_mode = tdm_priv->tdm_mode; + unsigned int data_mode = tdm_priv->data_mode; + unsigned int rate = params_rate(params); + unsigned int channels = params_channels(params); + snd_pcm_format_t format = params_format(params); + unsigned int bit_width = + snd_pcm_format_physical_width(format); + unsigned int tdm_channels = (data_mode == TDM_DATA_ONE_PIN) ? + get_tdm_ch_per_sdata(tdm_mode, channels) : 2; + unsigned int lrck_width = + get_tdm_lrck_width(format, tdm_mode); + unsigned int tdm_con = 0; + bool slave_mode = tdm_priv->slave_mode; + bool lrck_inv = tdm_priv->lck_invert; + bool bck_inv = tdm_priv->bck_invert; + unsigned int tran_rate; + unsigned int tran_relatch_rate; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + tdm_priv->rate = rate; + + tran_rate = mt8186_rate_transform(afe->dev, rate, dai->id); + tran_relatch_rate = mt8186_tdm_relatch_rate_transform(afe->dev, rate); + + /* calculate mclk_rate, if not set explicitly */ + if (!tdm_priv->mclk_rate) { + tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple; + mtk_dai_tdm_cal_mclk(afe, + tdm_priv, + tdm_priv->mclk_rate); + } + + /* ETDM_IN1_CON0 */ + tdm_con |= slave_mode << ETDM_IN1_CON0_REG_SLAVE_MODE_SFT; + tdm_con |= tdm_mode << ETDM_IN1_CON0_REG_FMT_SFT; + tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_BIT_LENGTH_SFT; + tdm_con |= (bit_width - 1) << ETDM_IN1_CON0_REG_WORD_LENGTH_SFT; + tdm_con |= (tdm_channels - 1) << ETDM_IN1_CON0_REG_CH_NUM_SFT; + /* need to disable sync mode otherwise this may cause latch data error */ + tdm_con |= 0 << ETDM_IN1_CON0_REG_SYNC_MODE_SFT; + /* relatch 1x en clock fix to h26m */ + tdm_con |= 0 << ETDM_IN1_CON0_REG_RELATCH_1X_EN_SEL_DOMAIN_SFT; + regmap_update_bits(afe->regmap, ETDM_IN1_CON0, ETDM_IN_CON0_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON1 */ + tdm_con = 0; + tdm_con |= 0 << ETDM_IN1_CON1_REG_LRCK_AUTO_MODE_SFT; + tdm_con |= 1 << ETDM_IN1_CON1_PINMUX_MCLK_CTRL_OE_SFT; + tdm_con |= (lrck_width - 1) << ETDM_IN1_CON1_REG_LRCK_WIDTH_SFT; + regmap_update_bits(afe->regmap, ETDM_IN1_CON1, ETDM_IN_CON1_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON3 */ + tdm_con = 0; + tdm_con = ETDM_IN_CON3_FS(tran_rate); + regmap_update_bits(afe->regmap, ETDM_IN1_CON3, ETDM_IN_CON3_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON4 */ + tdm_con = 0; + tdm_con = ETDM_IN_CON4_FS(tran_relatch_rate); + if (slave_mode) { + if (lrck_inv) + tdm_con |= ETDM_IN_CON4_CON0_SLAVE_LRCK_INV; + if (bck_inv) + tdm_con |= ETDM_IN_CON4_CON0_SLAVE_BCK_INV; + } else { + if (lrck_inv) + tdm_con |= ETDM_IN_CON4_CON0_MASTER_LRCK_INV; + if (bck_inv) + tdm_con |= ETDM_IN_CON4_CON0_MASTER_BCK_INV; + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON4, ETDM_IN_CON4_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON2 */ + tdm_con = 0; + if (data_mode == TDM_DATA_MULTI_PIN) { + tdm_con |= ETDM_IN_CON2_MULTI_IP_2CH_MODE; + tdm_con |= ETDM_IN_CON2_MULTI_IP_CH(channels); + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON2, ETDM_IN_CON2_CTRL_MASK, tdm_con); + + /* ETDM_IN1_CON8 */ + tdm_con = 0; + if (slave_mode) { + tdm_con |= 1 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT; + tdm_con |= 0 << ETDM_IN1_CON8_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT; + tdm_con |= ETDM_IN_CON8_FS(tran_relatch_rate); + } else { + tdm_con |= 0 << ETDM_IN1_CON8_REG_ETDM_USE_AFIFO_SFT; + } + regmap_update_bits(afe->regmap, ETDM_IN1_CON8, ETDM_IN_CON8_CTRL_MASK, tdm_con); + + return 0; +} + +static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + if (dir != SND_SOC_CLOCK_IN) { + dev_err(afe->dev, "%s(), dir != SND_SOC_CLOCK_OUT", __func__); + return -EINVAL; + } + + dev_dbg(afe->dev, "%s(), freq %d\n", __func__, freq); + + return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq); +} + +static int mtk_dai_tdm_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + if (!tdm_priv) { + dev_err(afe->dev, "%s(), tdm_priv == NULL", __func__); + return -EINVAL; + } + + /* DAI mode*/ + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + tdm_priv->tdm_mode = TDM_IN_I2S; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_LEFT_J: + tdm_priv->tdm_mode = TDM_IN_LJ; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_RIGHT_J: + tdm_priv->tdm_mode = TDM_IN_RJ; + tdm_priv->data_mode = TDM_DATA_MULTI_PIN; + break; + case SND_SOC_DAIFMT_DSP_A: + tdm_priv->tdm_mode = TDM_IN_DSP_A; + tdm_priv->data_mode = TDM_DATA_ONE_PIN; + break; + case SND_SOC_DAIFMT_DSP_B: + tdm_priv->tdm_mode = TDM_IN_DSP_B; + tdm_priv->data_mode = TDM_DATA_ONE_PIN; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_FORMAT_MASK", __func__); + return -EINVAL; + } + + /* DAI clock inversion*/ + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + tdm_priv->bck_invert = TDM_BCK_NON_INV; + tdm_priv->lck_invert = TDM_LCK_NON_INV; + break; + case SND_SOC_DAIFMT_NB_IF: + tdm_priv->bck_invert = TDM_BCK_NON_INV; + tdm_priv->lck_invert = TDM_LCK_INV; + break; + case SND_SOC_DAIFMT_IB_NF: + tdm_priv->bck_invert = TDM_BCK_INV; + tdm_priv->lck_invert = TDM_LCK_NON_INV; + break; + case SND_SOC_DAIFMT_IB_IF: + tdm_priv->bck_invert = TDM_BCK_INV; + tdm_priv->lck_invert = TDM_LCK_INV; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_INV_MASK", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { + case SND_SOC_DAIFMT_CBP_CFP: + tdm_priv->slave_mode = false; + break; + case SND_SOC_DAIFMT_CBC_CFC: + tdm_priv->slave_mode = true; + break; + default: + dev_err(afe->dev, "%s(), invalid DAIFMT_CLOCK_PROVIDER_MASK", + __func__); + return -EINVAL; + } + + return 0; +} + +static int mtk_dai_tdm_set_tdm_slot(struct snd_soc_dai *dai, + unsigned int tx_mask, + unsigned int rx_mask, + int slots, + int slot_width) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dai->dev); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai->id]; + + dev_dbg(dai->dev, "%s %d slot_width %d\n", __func__, dai->id, slot_width); + + tdm_priv->lrck_width = slot_width; + + return 0; +} + +static const struct snd_soc_dai_ops mtk_dai_tdm_ops = { + .hw_params = mtk_dai_tdm_hw_params, + .set_sysclk = mtk_dai_tdm_set_sysclk, + .set_fmt = mtk_dai_tdm_set_fmt, + .set_tdm_slot = mtk_dai_tdm_set_tdm_slot, +}; + +/* dai driver */ +#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\ + SNDRV_PCM_RATE_88200 |\ + SNDRV_PCM_RATE_96000 |\ + SNDRV_PCM_RATE_176400 |\ + SNDRV_PCM_RATE_192000) + +#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE) + +static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = { + { + .name = "TDM IN", + .id = MT8186_DAI_TDM_IN, + .capture = { + .stream_name = "TDM IN", + .channels_min = 2, + .channels_max = 8, + .rates = MTK_TDM_RATES, + .formats = MTK_TDM_FORMATS, + }, + .ops = &mtk_dai_tdm_ops, + }, +}; + +static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe) +{ + struct mtk_afe_tdm_priv *tdm_priv; + + tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv), + GFP_KERNEL); + if (!tdm_priv) + return NULL; + + tdm_priv->mclk_multiple = 512; + tdm_priv->mclk_id = MT8186_TDM_MCK; + tdm_priv->id = MT8186_DAI_TDM_IN; + + return tdm_priv; +} + +int mt8186_dai_tdm_register(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_tdm_priv *tdm_priv; + struct mtk_base_afe_dai *dai; + + dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL); + if (!dai) + return -ENOMEM; + + list_add(&dai->list, &afe->sub_dais); + + dai->dai_drivers = mtk_dai_tdm_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver); + + dai->controls = mtk_dai_tdm_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls); + dai->dapm_widgets = mtk_dai_tdm_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets); + dai->dapm_routes = mtk_dai_tdm_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes); + + tdm_priv = init_tdm_priv_data(afe); + if (!tdm_priv) + return -ENOMEM; + + afe_priv->dai_priv[MT8186_DAI_TDM_IN] = tdm_priv; + + return 0; +} From patchwork Mon May 23 13:28:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859061 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 C1BEFC433EF for ; Mon, 23 May 2022 13:41:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=1kE6VkH+awApfJy15qjJfxUqeZbHOjZBxP0foOhZ0Ag=; b=OFNdtLxGm0tOdE 2z9ksc/LdracSLlZQXTDieiFwEsPg1Mrn7QYzFazkXQk8EYgpRNJslqvDXkAnTxCTAX72xbUFjlSK gh0828B1DH4FjTYUzjwcR2DqDhs0LVetkoLgeBbh1ZXNApcLZsaiIdiglzSUC4P3n7gNa+uZaFT4F Gg22EH9SRfVVLus6p1TGxRYTCsa4Bj9bRl73m46oA4wNEktqjhERntPStT2kKSs+vTnOblKitRoJN 2lF+C/bXqGZGJgjUNqU/OAKtGeQf079qvinSmvAbyr8W/54aBoBPfeXru4h5u9VUHaTXXqOUy6ZRA Itzf1U7mbW5gmZsmbVjQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8IR-004TDO-HY; Mon, 23 May 2022 13:40:31 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HD-004Sgq-F0; Mon, 23 May 2022 13:39:21 +0000 X-UUID: f5a30cafa6a24db285033b55d5925600-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:9082271e-6d21-494a-8b86-d2bb0bc38aa4, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:-5 X-CID-META: VersionHash:2a19b09, CLOUDID:f2283ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: f5a30cafa6a24db285033b55d5925600-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1781128492; Mon, 23 May 2022 06:39:08 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:13 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:11 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:10 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 11/20] ASoC: mediatek: mt8186: support audio clock control in platform driver Date: Mon, 23 May 2022 21:28:49 +0800 Message-ID: <20220523132858.22166-12-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063915_584692_E938E340 X-CRM114-Status: GOOD ( 16.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add audio clock control with CCF interface. Signed-off-by: Jiaxin Yu --- sound/soc/mediatek/mt8186/mt8186-afe-clk.c | 651 +++++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-afe-clk.h | 106 ++++ 2 files changed, 757 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-clk.h diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.c b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c new file mode 100644 index 000000000000..0275f66ddc18 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.c @@ -0,0 +1,651 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-afe-clk.c -- Mediatek 8186 afe clock ctrl +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include +#include + +#include "mt8186-afe-common.h" +#include "mt8186-afe-clk.h" +#include "mt8186-audsys-clk.h" + +static DEFINE_MUTEX(mutex_request_dram); + +static const char *aud_clks[CLK_NUM] = { + [CLK_AFE] = "aud_afe_clk", + [CLK_DAC] = "aud_dac_clk", + [CLK_DAC_PREDIS] = "aud_dac_predis_clk", + [CLK_ADC] = "aud_adc_clk", + [CLK_TML] = "aud_tml_clk", + [CLK_APLL22M] = "aud_apll22m_clk", + [CLK_APLL24M] = "aud_apll24m_clk", + [CLK_APLL1_TUNER] = "aud_apll_tuner_clk", + [CLK_APLL2_TUNER] = "aud_apll2_tuner_clk", + [CLK_TDM] = "aud_tdm_clk", + [CLK_NLE] = "aud_nle_clk", + [CLK_DAC_HIRES] = "aud_dac_hires_clk", + [CLK_ADC_HIRES] = "aud_adc_hires_clk", + [CLK_I2S1_BCLK] = "aud_i2s1_bclk", + [CLK_I2S2_BCLK] = "aud_i2s2_bclk", + [CLK_I2S3_BCLK] = "aud_i2s3_bclk", + [CLK_I2S4_BCLK] = "aud_i2s4_bclk", + [CLK_CONNSYS_I2S_ASRC] = "aud_connsys_i2s_asrc", + [CLK_GENERAL1_ASRC] = "aud_general1_asrc", + [CLK_GENERAL2_ASRC] = "aud_general2_asrc", + [CLK_ADC_HIRES_TML] = "aud_adc_hires_tml", + [CLK_ADDA6_ADC] = "aud_adda6_adc", + [CLK_ADDA6_ADC_HIRES] = "aud_adda6_adc_hires", + [CLK_3RD_DAC] = "aud_3rd_dac", + [CLK_3RD_DAC_PREDIS] = "aud_3rd_dac_predis", + [CLK_3RD_DAC_TML] = "aud_3rd_dac_tml", + [CLK_3RD_DAC_HIRES] = "aud_3rd_dac_hires", + [CLK_ETDM_IN1_BCLK] = "aud_etdm_in1_bclk", + [CLK_ETDM_OUT1_BCLK] = "aud_etdm_out1_bclk", + [CLK_INFRA_SYS_AUDIO] = "aud_infra_clk", + [CLK_INFRA_AUDIO_26M] = "mtkaif_26m_clk", + [CLK_MUX_AUDIO] = "top_mux_audio", + [CLK_MUX_AUDIOINTBUS] = "top_mux_audio_int", + [CLK_TOP_MAINPLL_D2_D4] = "top_mainpll_d2_d4", + [CLK_TOP_MUX_AUD_1] = "top_mux_aud_1", + [CLK_TOP_APLL1_CK] = "top_apll1_ck", + [CLK_TOP_MUX_AUD_2] = "top_mux_aud_2", + [CLK_TOP_APLL2_CK] = "top_apll2_ck", + [CLK_TOP_MUX_AUD_ENG1] = "top_mux_aud_eng1", + [CLK_TOP_APLL1_D8] = "top_apll1_d8", + [CLK_TOP_MUX_AUD_ENG2] = "top_mux_aud_eng2", + [CLK_TOP_APLL2_D8] = "top_apll2_d8", + [CLK_TOP_MUX_AUDIO_H] = "top_mux_audio_h", + [CLK_TOP_I2S0_M_SEL] = "top_i2s0_m_sel", + [CLK_TOP_I2S1_M_SEL] = "top_i2s1_m_sel", + [CLK_TOP_I2S2_M_SEL] = "top_i2s2_m_sel", + [CLK_TOP_I2S4_M_SEL] = "top_i2s4_m_sel", + [CLK_TOP_TDM_M_SEL] = "top_tdm_m_sel", + [CLK_TOP_APLL12_DIV0] = "top_apll12_div0", + [CLK_TOP_APLL12_DIV1] = "top_apll12_div1", + [CLK_TOP_APLL12_DIV2] = "top_apll12_div2", + [CLK_TOP_APLL12_DIV4] = "top_apll12_div4", + [CLK_TOP_APLL12_DIV_TDM] = "top_apll12_div_tdm", + [CLK_CLK26M] = "top_clk26m_clk", +}; + +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, + int clk_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIOINTBUS], + afe_priv->clk[clk_id]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], + aud_clks[clk_id], ret); + return ret; + } + + return 0; +} + +static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + if (enable) { + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_1]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1], + afe_priv->clk[CLK_TOP_APLL1_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], + aud_clks[CLK_TOP_APLL1_CK], ret); + return ret; + } + + /* 180.6336 / 8 = 22.5792MHz */ + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1], + afe_priv->clk[CLK_TOP_APLL1_D8]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], + aud_clks[CLK_TOP_APLL1_D8], ret); + return ret; + } + } else { + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG1], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG1]); + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_1], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_1], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_1]); + } + + return 0; +} + +static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + if (enable) { + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_2]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2], + afe_priv->clk[CLK_TOP_APLL2_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], + aud_clks[CLK_TOP_APLL2_CK], ret); + return ret; + } + + /* 196.608 / 8 = 24.576MHz */ + ret = clk_prepare_enable(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2], + afe_priv->clk[CLK_TOP_APLL2_D8]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], + aud_clks[CLK_TOP_APLL2_D8], ret); + return ret; + } + } else { + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_ENG2], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_ENG2]); + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUD_2], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUD_2], + aud_clks[CLK_CLK26M], ret); + return ret; + } + clk_disable_unprepare(afe_priv->clk[CLK_TOP_MUX_AUD_2]); + } + + return 0; +} + +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret = 0; + int i; + + for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) { + ret = clk_prepare_enable(afe_priv->clk[i]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[i], ret); + return ret; + } + } + + return 0; +} + +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int i; + + for (i = CLK_I2S1_BCLK; i <= CLK_ETDM_OUT1_BCLK; i++) + clk_disable_unprepare(afe_priv->clk[i]); +} + +int mt8186_afe_enable_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret = 0; + + ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_INFRA_SYS_AUDIO], ret); + goto clk_infra_sys_audio_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_INFRA_AUDIO_26M], ret); + goto clk_infra_audio_26m_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIO]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIO], ret); + goto clk_mux_audio_err; + } + ret = clk_set_parent(afe_priv->clk[CLK_MUX_AUDIO], + afe_priv->clk[CLK_CLK26M]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIO], + aud_clks[CLK_CLK26M], ret); + goto clk_mux_audio_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, + CLK_TOP_MAINPLL_D2_D4); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + ret = clk_set_parent(afe_priv->clk[CLK_TOP_MUX_AUDIO_H], + afe_priv->clk[CLK_TOP_APLL2_CK]); + if (ret) { + dev_err(afe->dev, "%s clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[CLK_TOP_MUX_AUDIO_H], + aud_clks[CLK_TOP_APLL2_CK], ret); + goto clk_mux_audio_h_parent_err; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_AFE]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_AFE], ret); + goto clk_afe_err; + } + + return 0; + +clk_afe_err: + clk_disable_unprepare(afe_priv->clk[CLK_AFE]); +clk_mux_audio_h_parent_err: +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); +clk_mux_audio_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]); +clk_infra_sys_audio_err: + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); +clk_infra_audio_26m_err: + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + + return ret; +} + +void mt8186_afe_disable_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + clk_disable_unprepare(afe_priv->clk[CLK_AFE]); + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIO]); + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_AUDIO_26M]); + clk_disable_unprepare(afe_priv->clk[CLK_INFRA_SYS_AUDIO]); +} + +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* set audio int bus to 26M */ + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + + return 0; + +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_TOP_MAINPLL_D2_D4); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + return ret; +} + +int mt8186_afe_resume_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* set audio int bus to normal working clock */ + ret = clk_prepare_enable(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + if (ret) { + dev_info(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_MUX_AUDIOINTBUS], ret); + goto clk_mux_audio_intbus_err; + } + ret = mt8186_set_audio_int_bus_parent(afe, + CLK_TOP_MAINPLL_D2_D4); + if (ret) + goto clk_mux_audio_intbus_parent_err; + + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + + return 0; + +clk_mux_audio_intbus_parent_err: + mt8186_set_audio_int_bus_parent(afe, CLK_CLK26M); +clk_mux_audio_intbus_err: + clk_disable_unprepare(afe_priv->clk[CLK_MUX_AUDIOINTBUS]); + return ret; +} + +int mt8186_apll1_enable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* setting for APLL */ + apll1_mux_setting(afe, true); + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL22M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL22M], ret); + goto err_clk_apll22m; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL1_TUNER]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL1_TUNER], ret); + goto err_clk_apll1_tuner; + } + + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0xfff7, 0x832); + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0x1); + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_ON_MASK_SFT, BIT(AFE_22M_ON_SFT)); + + return 0; + +err_clk_apll1_tuner: + clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]); +err_clk_apll22m: + clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]); + + return ret; +} + +void mt8186_apll1_disable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_ON_MASK_SFT, 0); + + regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG, 0x1, 0); + + clk_disable_unprepare(afe_priv->clk[CLK_APLL1_TUNER]); + clk_disable_unprepare(afe_priv->clk[CLK_APLL22M]); + + apll1_mux_setting(afe, false); +} + +int mt8186_apll2_enable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int ret; + + /* setting for APLL */ + apll2_mux_setting(afe, true); + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL24M]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL24M], ret); + goto err_clk_apll24m; + } + + ret = clk_prepare_enable(afe_priv->clk[CLK_APLL2_TUNER]); + if (ret) { + dev_err(afe->dev, "%s clk_prepare_enable %s fail %d\n", + __func__, aud_clks[CLK_APLL2_TUNER], ret); + goto err_clk_apll2_tuner; + } + + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0xfff7, 0x634); + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0x1); + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_ON_MASK_SFT, BIT(AFE_24M_ON_SFT)); + + return 0; + +err_clk_apll2_tuner: + clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]); +err_clk_apll24m: + clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]); + + return ret; +} + +void mt8186_apll2_disable(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_ON_MASK_SFT, 0); + + regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG, 0x1, 0); + + clk_disable_unprepare(afe_priv->clk[CLK_APLL2_TUNER]); + clk_disable_unprepare(afe_priv->clk[CLK_APLL24M]); + + apll2_mux_setting(afe, false); +} + +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll) +{ + return (apll == MT8186_APLL1) ? 180633600 : 196608000; +} + +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate) +{ + return ((rate % 8000) == 0) ? MT8186_APLL2 : MT8186_APLL1; +} + +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name) +{ + if (strcmp(name, APLL1_W_NAME) == 0) + return MT8186_APLL1; + + return MT8186_APLL2; +} + +/* mck */ +struct mt8186_mck_div { + u32 m_sel_id; + u32 div_clk_id; +}; + +static const struct mt8186_mck_div mck_div[MT8186_MCK_NUM] = { + [MT8186_I2S0_MCK] = { + .m_sel_id = CLK_TOP_I2S0_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV0, + }, + [MT8186_I2S1_MCK] = { + .m_sel_id = CLK_TOP_I2S1_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV1, + }, + [MT8186_I2S2_MCK] = { + .m_sel_id = CLK_TOP_I2S2_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV2, + }, + [MT8186_I2S4_MCK] = { + .m_sel_id = CLK_TOP_I2S4_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV4, + }, + [MT8186_TDM_MCK] = { + .m_sel_id = CLK_TOP_TDM_M_SEL, + .div_clk_id = CLK_TOP_APLL12_DIV_TDM, + }, +}; + +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int apll = mt8186_get_apll_by_rate(afe, rate); + int apll_clk_id = apll == MT8186_APLL1 ? + CLK_TOP_MUX_AUD_1 : CLK_TOP_MUX_AUD_2; + int m_sel_id = mck_div[mck_id].m_sel_id; + int div_clk_id = mck_div[mck_id].div_clk_id; + int ret; + + /* select apll */ + if (m_sel_id >= 0) { + ret = clk_prepare_enable(afe_priv->clk[m_sel_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", + __func__, aud_clks[m_sel_id], ret); + return ret; + } + ret = clk_set_parent(afe_priv->clk[m_sel_id], + afe_priv->clk[apll_clk_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_set_parent %s-%s fail %d\n", + __func__, aud_clks[m_sel_id], + aud_clks[apll_clk_id], ret); + return ret; + } + } + + /* enable div, set rate */ + ret = clk_prepare_enable(afe_priv->clk[div_clk_id]); + if (ret) { + dev_err(afe->dev, "%s(), clk_prepare_enable %s fail %d\n", + __func__, aud_clks[div_clk_id], ret); + return ret; + } + ret = clk_set_rate(afe_priv->clk[div_clk_id], rate); + if (ret) { + dev_err(afe->dev, "%s(), clk_set_rate %s, rate %d, fail %d\n", + __func__, aud_clks[div_clk_id], rate, ret); + return ret; + } + + return 0; +} + +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + int m_sel_id = mck_div[mck_id].m_sel_id; + int div_clk_id = mck_div[mck_id].div_clk_id; + + clk_disable_unprepare(afe_priv->clk[div_clk_id]); + if (m_sel_id >= 0) + clk_disable_unprepare(afe_priv->clk[m_sel_id]); +} + +int mt8186_init_clock(struct mtk_base_afe *afe) +{ + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct device_node *of_node = afe->dev->of_node; + int i = 0; + + mt8186_audsys_clk_register(afe); + + afe_priv->clk = devm_kcalloc(afe->dev, CLK_NUM, sizeof(*afe_priv->clk), + GFP_KERNEL); + if (!afe_priv->clk) + return -ENOMEM; + + for (i = 0; i < CLK_NUM; i++) { + afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]); + if (IS_ERR(afe_priv->clk[i])) { + dev_err(afe->dev, "%s devm_clk_get %s fail, ret %ld\n", + __func__, + aud_clks[i], PTR_ERR(afe_priv->clk[i])); + afe_priv->clk[i] = NULL; + } + } + + afe_priv->apmixedsys = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,apmixedsys"); + if (IS_ERR(afe_priv->apmixedsys)) { + dev_err(afe->dev, "%s() Cannot find apmixedsys controller: %ld\n", + __func__, PTR_ERR(afe_priv->apmixedsys)); + return PTR_ERR(afe_priv->apmixedsys); + } + + afe_priv->topckgen = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,topckgen"); + if (IS_ERR(afe_priv->topckgen)) { + dev_err(afe->dev, "%s() Cannot find topckgen controller: %ld\n", + __func__, PTR_ERR(afe_priv->topckgen)); + return PTR_ERR(afe_priv->topckgen); + } + + afe_priv->infracfg = syscon_regmap_lookup_by_phandle(of_node, + "mediatek,infracfg"); + if (IS_ERR(afe_priv->infracfg)) { + dev_err(afe->dev, "%s() Cannot find infracfg: %ld\n", + __func__, PTR_ERR(afe_priv->infracfg)); + return PTR_ERR(afe_priv->infracfg); + } + + return 0; +} + +void mt8186_deinit_clock(struct mtk_base_afe *afe) +{ + mt8186_audsys_clk_unregister(afe); +} diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-clk.h b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h new file mode 100644 index 000000000000..c539557d7c78 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-clk.h @@ -0,0 +1,106 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt8186-afe-clk.h -- Mediatek 8186 afe clock ctrl definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AFE_CLOCK_CTRL_H_ +#define _MT8186_AFE_CLOCK_CTRL_H_ + +#define PERI_BUS_DCM_CTRL 0x74 + +/* APLL */ +#define APLL1_W_NAME "APLL1" +#define APLL2_W_NAME "APLL2" +enum { + MT8186_APLL1 = 0, + MT8186_APLL2, +}; + +enum { + CLK_AFE = 0, + CLK_DAC, + CLK_DAC_PREDIS, + CLK_ADC, + CLK_TML, + CLK_APLL22M, + CLK_APLL24M, + CLK_APLL1_TUNER, + CLK_APLL2_TUNER, + CLK_TDM, + CLK_NLE, + CLK_DAC_HIRES, + CLK_ADC_HIRES, + CLK_I2S1_BCLK, + CLK_I2S2_BCLK, + CLK_I2S3_BCLK, + CLK_I2S4_BCLK, + CLK_CONNSYS_I2S_ASRC, + CLK_GENERAL1_ASRC, + CLK_GENERAL2_ASRC, + CLK_ADC_HIRES_TML, + CLK_ADDA6_ADC, + CLK_ADDA6_ADC_HIRES, + CLK_3RD_DAC, + CLK_3RD_DAC_PREDIS, + CLK_3RD_DAC_TML, + CLK_3RD_DAC_HIRES, + CLK_ETDM_IN1_BCLK, + CLK_ETDM_OUT1_BCLK, + CLK_INFRA_SYS_AUDIO, + CLK_INFRA_AUDIO_26M, + CLK_MUX_AUDIO, + CLK_MUX_AUDIOINTBUS, + CLK_TOP_MAINPLL_D2_D4, + /* apll related mux */ + CLK_TOP_MUX_AUD_1, + CLK_TOP_APLL1_CK, + CLK_TOP_MUX_AUD_2, + CLK_TOP_APLL2_CK, + CLK_TOP_MUX_AUD_ENG1, + CLK_TOP_APLL1_D8, + CLK_TOP_MUX_AUD_ENG2, + CLK_TOP_APLL2_D8, + CLK_TOP_MUX_AUDIO_H, + CLK_TOP_I2S0_M_SEL, + CLK_TOP_I2S1_M_SEL, + CLK_TOP_I2S2_M_SEL, + CLK_TOP_I2S4_M_SEL, + CLK_TOP_TDM_M_SEL, + CLK_TOP_APLL12_DIV0, + CLK_TOP_APLL12_DIV1, + CLK_TOP_APLL12_DIV2, + CLK_TOP_APLL12_DIV4, + CLK_TOP_APLL12_DIV_TDM, + CLK_CLK26M, + CLK_NUM +}; + +struct mtk_base_afe; +int mt8186_set_audio_int_bus_parent(struct mtk_base_afe *afe, int clk_id); +int mt8186_init_clock(struct mtk_base_afe *afe); +void mt8186_deinit_clock(struct mtk_base_afe *afe); +int mt8186_afe_enable_cgs(struct mtk_base_afe *afe); +void mt8186_afe_disable_cgs(struct mtk_base_afe *afe); +int mt8186_afe_enable_clock(struct mtk_base_afe *afe); +void mt8186_afe_disable_clock(struct mtk_base_afe *afe); +int mt8186_afe_suspend_clock(struct mtk_base_afe *afe); +int mt8186_afe_resume_clock(struct mtk_base_afe *afe); + +int mt8186_apll1_enable(struct mtk_base_afe *afe); +void mt8186_apll1_disable(struct mtk_base_afe *afe); + +int mt8186_apll2_enable(struct mtk_base_afe *afe); +void mt8186_apll2_disable(struct mtk_base_afe *afe); + +int mt8186_get_apll_rate(struct mtk_base_afe *afe, int apll); +int mt8186_get_apll_by_rate(struct mtk_base_afe *afe, int rate); +int mt8186_get_apll_by_name(struct mtk_base_afe *afe, const char *name); + +/* these will be replaced by using CCF */ +int mt8186_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate); +void mt8186_mck_disable(struct mtk_base_afe *afe, int mck_id); + +#endif From patchwork Mon May 23 13:28:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859079 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 A072EC433F5 for ; Mon, 23 May 2022 13:44:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=XF+r7cugg2OP64BCFznEaUYZ6Q5iU+lWwxLRvb/h2vY=; b=R+rjHTo7nDNIMq pXQy013chU7Nyt8lcOXgNvw6nYOewQor6HH25J8rffW+KCYwqQJ08OIrlhUGSVMTINW93tzu5/pNS ZMr8e2BTiYPqlEMkLSmxUZPleBG6C83+S6QGlO6vzohqO4/sVFX3XfAIgvQ2lHP35XAT7okAB7kSc yvCZE09cBEwFAFcWBVDtOwBe1r483v1cVuaIN4RYo5hIxDQ6VkZudjUUnWRGHPGb1mT91zM6i4c+B oJurOZpm65b1Cpo20juPGS+EwxMILf3BubKdPA62ea5cusLe2+Qz6ZK2slEC37KPeE4L7y27/t79/ lTSQdXAtRYXt2jiYQvhA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8L2-004UaI-AR; Mon, 23 May 2022 13:43:12 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HG-004SkA-RA; Mon, 23 May 2022 13:39:28 +0000 X-UUID: 93ed12183a7f460d9608a638db823d21-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:e843d853-ca24-4ec9-bea2-cc4644b3202a, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:-5 X-CID-META: VersionHash:2a19b09, CLOUDID:ce204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 93ed12183a7f460d9608a638db823d21-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 776208234; Mon, 23 May 2022 06:39:13 -0700 Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:14 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:12 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:11 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 12/20] ASoC: mediatek: mt8186: support gpio control in platform driver Date: Mon, 23 May 2022 21:28:50 +0800 Message-ID: <20220523132858.22166-13-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063918_941299_8D75C172 X-CRM114-Status: GOOD ( 18.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add gpio control for all audio interface separately. Signed-off-by: Jiaxin Yu --- sound/soc/mediatek/mt8186/mt8186-afe-gpio.c | 244 ++++++++++++++++++++ sound/soc/mediatek/mt8186/mt8186-afe-gpio.h | 19 ++ 2 files changed, 263 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-afe-gpio.h diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c new file mode 100644 index 000000000000..5ba28095b7da --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-afe-gpio.c -- Mediatek 8186 afe gpio ctrl +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu + +#include +#include + +#include "mt8186-afe-common.h" +#include "mt8186-afe-gpio.h" + +struct pinctrl *aud_pinctrl; + +enum mt8186_afe_gpio { + MT8186_AFE_GPIO_CLK_MOSI_OFF, + MT8186_AFE_GPIO_CLK_MOSI_ON, + MT8186_AFE_GPIO_CLK_MISO_OFF, + MT8186_AFE_GPIO_CLK_MISO_ON, + MT8186_AFE_GPIO_DAT_MISO_OFF, + MT8186_AFE_GPIO_DAT_MISO_ON, + MT8186_AFE_GPIO_DAT_MOSI_OFF, + MT8186_AFE_GPIO_DAT_MOSI_ON, + MT8186_AFE_GPIO_I2S0_OFF, + MT8186_AFE_GPIO_I2S0_ON, + MT8186_AFE_GPIO_I2S1_OFF, + MT8186_AFE_GPIO_I2S1_ON, + MT8186_AFE_GPIO_I2S2_OFF, + MT8186_AFE_GPIO_I2S2_ON, + MT8186_AFE_GPIO_I2S3_OFF, + MT8186_AFE_GPIO_I2S3_ON, + MT8186_AFE_GPIO_TDM_OFF, + MT8186_AFE_GPIO_TDM_ON, + MT8186_AFE_GPIO_PCM_OFF, + MT8186_AFE_GPIO_PCM_ON, + MT8186_AFE_GPIO_GPIO_NUM +}; + +struct audio_gpio_attr { + const char *name; + bool gpio_prepare; + struct pinctrl_state *gpioctrl; +}; + +static struct audio_gpio_attr aud_gpios[MT8186_AFE_GPIO_GPIO_NUM] = { + [MT8186_AFE_GPIO_CLK_MOSI_OFF] = {"aud_clk_mosi_off", false, NULL}, + [MT8186_AFE_GPIO_CLK_MOSI_ON] = {"aud_clk_mosi_on", false, NULL}, + [MT8186_AFE_GPIO_CLK_MISO_OFF] = {"aud_clk_miso_off", false, NULL}, + [MT8186_AFE_GPIO_CLK_MISO_ON] = {"aud_clk_miso_on", false, NULL}, + [MT8186_AFE_GPIO_DAT_MISO_OFF] = {"aud_dat_miso_off", false, NULL}, + [MT8186_AFE_GPIO_DAT_MISO_ON] = {"aud_dat_miso_on", false, NULL}, + [MT8186_AFE_GPIO_DAT_MOSI_OFF] = {"aud_dat_mosi_off", false, NULL}, + [MT8186_AFE_GPIO_DAT_MOSI_ON] = {"aud_dat_mosi_on", false, NULL}, + [MT8186_AFE_GPIO_I2S0_OFF] = {"aud_gpio_i2s0_off", false, NULL}, + [MT8186_AFE_GPIO_I2S0_ON] = {"aud_gpio_i2s0_on", false, NULL}, + [MT8186_AFE_GPIO_I2S1_OFF] = {"aud_gpio_i2s1_off", false, NULL}, + [MT8186_AFE_GPIO_I2S1_ON] = {"aud_gpio_i2s1_on", false, NULL}, + [MT8186_AFE_GPIO_I2S2_OFF] = {"aud_gpio_i2s2_off", false, NULL}, + [MT8186_AFE_GPIO_I2S2_ON] = {"aud_gpio_i2s2_on", false, NULL}, + [MT8186_AFE_GPIO_I2S3_OFF] = {"aud_gpio_i2s3_off", false, NULL}, + [MT8186_AFE_GPIO_I2S3_ON] = {"aud_gpio_i2s3_on", false, NULL}, + [MT8186_AFE_GPIO_TDM_OFF] = {"aud_gpio_tdm_off", false, NULL}, + [MT8186_AFE_GPIO_TDM_ON] = {"aud_gpio_tdm_on", false, NULL}, + [MT8186_AFE_GPIO_PCM_OFF] = {"aud_gpio_pcm_off", false, NULL}, + [MT8186_AFE_GPIO_PCM_ON] = {"aud_gpio_pcm_on", false, NULL}, +}; + +static DEFINE_MUTEX(gpio_request_mutex); + +int mt8186_afe_gpio_init(struct device *dev) +{ + int i, j, ret; + + aud_pinctrl = devm_pinctrl_get(dev); + if (IS_ERR(aud_pinctrl)) { + ret = PTR_ERR(aud_pinctrl); + dev_err(dev, "%s(), ret %d, cannot get aud_pinctrl!\n", + __func__, ret); + return ret; + } + + for (i = 0; i < ARRAY_SIZE(aud_gpios); i++) { + aud_gpios[i].gpioctrl = pinctrl_lookup_state(aud_pinctrl, + aud_gpios[i].name); + if (IS_ERR(aud_gpios[i].gpioctrl)) { + ret = PTR_ERR(aud_gpios[i].gpioctrl); + dev_info(dev, "%s(), pinctrl_lookup_state %s fail, ret %d\n", + __func__, aud_gpios[i].name, ret); + } else { + aud_gpios[i].gpio_prepare = true; + } + } + + /* gpio status init */ + for (i = MT8186_DAI_ADDA; i <= MT8186_DAI_TDM_IN; i++) { + for (j = 0; j <= 1; j++) + mt8186_afe_gpio_request(dev, false, i, j); + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt8186_afe_gpio_init); + +static int mt8186_afe_gpio_select(struct device *dev, + enum mt8186_afe_gpio type) +{ + int ret = 0; + + if (type < 0 || type >= MT8186_AFE_GPIO_GPIO_NUM) { + dev_err(dev, "%s(), error, invalid gpio type %d\n", + __func__, type); + return -EINVAL; + } + + if (!aud_gpios[type].gpio_prepare) { + dev_err(dev, "%s(), error, gpio type %d not prepared\n", + __func__, type); + return -EIO; + } + + ret = pinctrl_select_state(aud_pinctrl, + aud_gpios[type].gpioctrl); + if (ret) { + dev_err(dev, "%s(), error, can not set gpio type %d\n", + __func__, type); + return ret; + } + + return 0; +} + +static int mt8186_afe_gpio_adda_dl(struct device *dev, bool enable) +{ + int ret; + + if (enable) { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_ON); + if (ret) { + dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_ON); + if (ret) { + dev_err(dev, "%s(), MOSI DAT ON slect fail!\n", __func__); + return ret; + } + } else { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MOSI_OFF); + if (ret) { + dev_err(dev, "%s(), MOSI DAT OFF slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MOSI_OFF); + if (ret) { + dev_err(dev, "%s(), MOSI CLK ON slect fail!\n", __func__); + return ret; + } + } + + return 0; +} + +static int mt8186_afe_gpio_adda_ul(struct device *dev, bool enable) +{ + int ret; + + if (enable) { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_ON); + if (ret) { + dev_err(dev, "%s(), MISO CLK ON slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_ON); + if (ret) { + dev_err(dev, "%s(), MISO DAT ON slect fail!\n", __func__); + return ret; + } + } else { + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_DAT_MISO_OFF); + if (ret) { + dev_err(dev, "%s(), MISO DAT OFF slect fail!\n", __func__); + return ret; + } + + ret = mt8186_afe_gpio_select(dev, MT8186_AFE_GPIO_CLK_MISO_OFF); + if (ret) { + dev_err(dev, "%s(), MISO CLK OFF slect fail!\n", __func__); + return ret; + } + } + + return 0; +} + +int mt8186_afe_gpio_request(struct device *dev, bool enable, + int dai, int uplink) +{ + enum mt8186_afe_gpio sel; + int ret = -EINVAL; + + mutex_lock(&gpio_request_mutex); + + switch (dai) { + case MT8186_DAI_ADDA: + if (uplink) + ret = mt8186_afe_gpio_adda_ul(dev, enable); + else + ret = mt8186_afe_gpio_adda_dl(dev, enable); + goto unlock; + case MT8186_DAI_I2S_0: + sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF; + break; + case MT8186_DAI_I2S_1: + sel = enable ? MT8186_AFE_GPIO_I2S1_ON : MT8186_AFE_GPIO_I2S1_OFF; + break; + case MT8186_DAI_I2S_2: + sel = enable ? MT8186_AFE_GPIO_I2S2_ON : MT8186_AFE_GPIO_I2S2_OFF; + break; + case MT8186_DAI_I2S_3: + sel = enable ? MT8186_AFE_GPIO_I2S3_ON : MT8186_AFE_GPIO_I2S3_OFF; + break; + case MT8186_DAI_TDM_IN: + sel = enable ? MT8186_AFE_GPIO_TDM_ON : MT8186_AFE_GPIO_TDM_OFF; + break; + case MT8186_DAI_PCM: + sel = enable ? MT8186_AFE_GPIO_PCM_ON : MT8186_AFE_GPIO_PCM_OFF; + break; + default: + mutex_unlock(&gpio_request_mutex); + dev_err(dev, "%s(), invalid dai %d\n", __func__, dai); + goto unlock; + } + + ret = mt8186_afe_gpio_select(dev, sel); + +unlock: + mutex_unlock(&gpio_request_mutex); + + return ret; +} diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h new file mode 100644 index 000000000000..1ddc27838eb1 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mt6833-afe-gpio.h -- Mediatek 6833 afe gpio ctrl definition + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_AFE_GPIO_H_ +#define _MT8186_AFE_GPIO_H_ + +struct mtk_base_afe; + +int mt8186_afe_gpio_init(struct device *dev); + +int mt8186_afe_gpio_request(struct device *dev, bool enable, + int dai, int uplink); + +#endif From patchwork Mon May 23 13:28:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859063 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 CA009C4332F for ; Mon, 23 May 2022 13:42:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=6R7FH6ZKhFtUXDnVapS3BQMLkE/IYC5RgNutznTTfPc=; b=y4MTIl60sO3xJb ieZBV2xRopYmCGAwlBy4MpdmlEs9hDNMVjVfU8hKLdXLF78ueMG1GchbZ61kVUS3OPd/sSqbv+RnO xAjA/TCJSIUrtQdoKw0UmbnokQspGYaLGZsojn11m7nwtrUOSRCMPA+3OOa90dN0MkAAY56cryvfx tf6lu1iKVtBdA1rYP5ffdMhxpbtJiNnl9MnKuLpH76aQZ38hb56Ha2tRQJ5LZbcR6qetoJideX8qV 5aYMWsAKQGSnzE4dYHH1IUfMwZbsCfTCKMnxM4LVv3L0sZRtnWgTLh/PvakqnDh1KYcAhKlw6laEQ CEOLVPQpWGThhhpYvZrg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Iz-004TT7-7K; Mon, 23 May 2022 13:41:05 +0000 Received: from mailgw01.mediatek.com ([216.200.240.184]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HE-004SiR-JH; Mon, 23 May 2022 13:39:23 +0000 X-UUID: 7b3278a24c114df6b368c5d53f766b4e-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:98e324bd-0fa3-4d40-9db4-19fae5b8a8e1, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACTI ON:release,TS:0 X-CID-META: VersionHash:2a19b09, CLOUDID:0e293ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 7b3278a24c114df6b368c5d53f766b4e-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw01.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1547542892; Mon, 23 May 2022 06:39:11 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N2.mediatek.inc (172.29.193.42) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:17 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:15 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:14 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 15/20] ASoC: mediatek: mt8186: add mt8186-mt6366 common driver Date: Mon, 23 May 2022 21:28:53 +0800 Message-ID: <20220523132858.22166-16-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063916_699121_D0CEAB90 X-CRM114-Status: GOOD ( 14.68 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186-mt6366 common driver for mt8186 series machine. Signed-off-by: Jiaxin Yu --- .../mediatek/mt8186/mt8186-mt6366-common.c | 59 +++++++++++++++++++ .../mediatek/mt8186/mt8186-mt6366-common.h | 17 ++++++ 2 files changed, 76 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-common.c create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-common.h diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c new file mode 100644 index 000000000000..94e1128e8128 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-mt6366-common.c +// -- MT8186 MT6366 ALSA common driver +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu +// +#include + +#include "../../codecs/mt6358.h" +#include "../common/mtk-afe-platform-driver.h" +#include "mt8186-afe-common.h" +#include "mt8186-mt6366-common.h" + +int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_afe = + snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME); + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt_afe); + struct mt8186_afe_private *afe_priv = afe->platform_priv; + struct snd_soc_dapm_context *dapm = &rtd->card->dapm; + int ret; + + /* set mtkaif protocol */ + mt6358_set_mtkaif_protocol(cmpnt_codec, + MT6358_MTKAIF_PROTOCOL_1); + afe_priv->mtkaif_protocol = MT6358_MTKAIF_PROTOCOL_1; + + ret = snd_soc_dapm_sync(dapm); + if (ret) { + dev_info(rtd->dev, "failed to snd_soc_dapm_sync\n"); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt8186_mt6366_init); + +int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + char *link_name) +{ + int ret; + + if (node && strcmp(link->name, link_name) == 0) { + ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link); + if (ret < 0) { + dev_err_probe(card->dev, ret, "get dai link codecs fail\n"); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(mt8186_mt6366_card_set_be_link); diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h new file mode 100644 index 000000000000..907d8f5e46b1 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * mt8186-mt6366-common.h + * + * Copyright (c) 2022 MediaTek Inc. + * Author: Jiaxin Yu + */ + +#ifndef _MT8186_MT6366_COMMON_H_ +#define _MT8186_MT6366_COMMON_H_ + +int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd); +int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card, + struct snd_soc_dai_link *link, + struct device_node *node, + char *link_name); +#endif From patchwork Mon May 23 13:28:54 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859059 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 5ABB8C433FE for ; Mon, 23 May 2022 13:40:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=xrLTRH2rVQSO1vWOtVDbQzVdKaGrENLyeZo+75sGrwc=; b=U3DrVrWC2pb6yu Xk2lNNyOI9qEgPfg0QTxmV39AedHsWsrdJSfgvHVz6pASctyQ8RzPPi4xQhRqlVR8o3/8iEvOGvdh aIiuM510ws/A4YVCoLlSXpa+4/ojetS/PKJsliXLwsmH9U++rIzVkHynMxcfj+98UhT7/GDoe5UwK ksaVUvRNvPqcRjS2NnqhfgqZ+Ur5nV7yC0R/Cfa29z7AL0qeDwhUqi7qIXmKk1vprXuJGJ/Gaibc1 ouORfb5U8n2PtpReyFirZHsrK4OwyyTlnM10oE62Oo/YSzwbwmCVeXzZ2ED7rajGs4XdzHbXD3TmL jhDj3bDq/lZrjsxsDydQ==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8He-004SsX-BS; Mon, 23 May 2022 13:39:42 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HB-004SgT-Ai; Mon, 23 May 2022 13:39:15 +0000 X-UUID: a8a641fc3d2f4a3cb60666e9813d04f6-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:03ebd050-2d46-4325-abfc-c84250af35df, OB:0, LO B:0,IP:0,URL:25,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,AC TION:release,TS:20 X-CID-META: VersionHash:2a19b09, CLOUDID:ed283ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: a8a641fc3d2f4a3cb60666e9813d04f6-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 2030457199; Mon, 23 May 2022 06:39:08 -0700 Received: from mtkmbs10n1.mediatek.inc (172.21.101.34) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:17 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs10n1.mediatek.inc (172.21.101.34) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.15; Mon, 23 May 2022 21:29:16 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:15 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu , Rob Herring Subject: [PATCH v5 16/20] dt-bindings: mediatek: mt8186: add audio afe document Date: Mon, 23 May 2022 21:28:54 +0800 Message-ID: <20220523132858.22166-17-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063913_403143_8A986A50 X-CRM114-Status: GOOD ( 11.13 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add mt8186 audio afe document. Signed-off-by: Jiaxin Yu Reviewed-by: Rob Herring --- .../bindings/sound/mt8186-afe-pcm.yaml | 175 ++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml diff --git a/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml new file mode 100644 index 000000000000..88f82d096443 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt8186-afe-pcm.yaml @@ -0,0 +1,175 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mt8186-afe-pcm.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek AFE PCM controller for mt8186 + +maintainers: + - Jiaxin Yu + +properties: + compatible: + const: mediatek,mt8186-sound + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + resets: + maxItems: 1 + + reset-names: + const: audiosys + + mediatek,apmixedsys: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of the mediatek apmixedsys controller + + mediatek,infracfg: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of the mediatek infracfg controller + + mediatek,topckgen: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of the mediatek topckgen controller + + clocks: + items: + - description: audio infra sys clock + - description: audio infra 26M clock + - description: audio top mux + - description: audio intbus mux + - description: mainpll 136.5M clock + - description: faud1 mux + - description: apll1 clock + - description: faud2 mux + - description: apll2 clock + - description: audio engen1 mux + - description: apll1_d8 22.5792M clock + - description: audio engen2 mux + - description: apll2_d8 24.576M clock + - description: i2s0 mclk mux + - description: i2s1 mclk mux + - description: i2s2 mclk mux + - description: i2s4 mclk mux + - description: tdm mclk mux + - description: i2s0_mck divider + - description: i2s1_mck divider + - description: i2s2_mck divider + - description: i2s4_mck divider + - description: tdm_mck divider + - description: audio hires mux + - description: 26M clock + + clock-names: + items: + - const: aud_infra_clk + - const: mtkaif_26m_clk + - const: top_mux_audio + - const: top_mux_audio_int + - const: top_mainpll_d2_d4 + - const: top_mux_aud_1 + - const: top_apll1_ck + - const: top_mux_aud_2 + - const: top_apll2_ck + - const: top_mux_aud_eng1 + - const: top_apll1_d8 + - const: top_mux_aud_eng2 + - const: top_apll2_d8 + - const: top_i2s0_m_sel + - const: top_i2s1_m_sel + - const: top_i2s2_m_sel + - const: top_i2s4_m_sel + - const: top_tdm_m_sel + - const: top_apll12_div0 + - const: top_apll12_div1 + - const: top_apll12_div2 + - const: top_apll12_div4 + - const: top_apll12_div_tdm + - const: top_mux_audio_h + - const: top_clk26m_clk + +required: + - compatible + - interrupts + - resets + - reset-names + - mediatek,apmixedsys + - mediatek,infracfg + - mediatek,topckgen + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + + afe: mt8186-afe-pcm@11210000 { + compatible = "mediatek,mt8186-sound"; + reg = <0x11210000 0x2000>; + interrupts = ; + resets = <&watchdog 17>; //MT8186_TOPRGU_AUDIO_SW_RST + reset-names = "audiosys"; + mediatek,apmixedsys = <&apmixedsys>; + mediatek,infracfg = <&infracfg>; + mediatek,topckgen = <&topckgen>; + clocks = <&infracfg_ao 44>, //CLK_INFRA_AO_AUDIO + <&infracfg_ao 54>, //CLK_INFRA_AO_AUDIO_26M_BCLK + <&topckgen 15>, //CLK_TOP_AUDIO + <&topckgen 16>, //CLK_TOP_AUD_INTBUS + <&topckgen 70>, //CLK_TOP_MAINPLL_D2_D4 + <&topckgen 17>, //CLK_TOP_AUD_1 + <&apmixedsys 12>, //CLK_APMIXED_APLL1 + <&topckgen 18>, //CLK_TOP_AUD_2 + <&apmixedsys 13>, //CLK_APMIXED_APLL2 + <&topckgen 19>, //CLK_TOP_AUD_ENGEN1 + <&topckgen 101>, //CLK_TOP_APLL1_D8 + <&topckgen 20>, //CLK_TOP_AUD_ENGEN2 + <&topckgen 104>, //CLK_TOP_APLL2_D8 + <&topckgen 63>, //CLK_TOP_APLL_I2S0_MCK_SEL + <&topckgen 64>, //CLK_TOP_APLL_I2S1_MCK_SEL + <&topckgen 65>, //CLK_TOP_APLL_I2S2_MCK_SEL + <&topckgen 66>, //CLK_TOP_APLL_I2S4_MCK_SEL + <&topckgen 67>, //CLK_TOP_APLL_TDMOUT_MCK_SEL + <&topckgen 131>, //CLK_TOP_APLL12_CK_DIV0 + <&topckgen 132>, //CLK_TOP_APLL12_CK_DIV1 + <&topckgen 133>, //CLK_TOP_APLL12_CK_DIV2 + <&topckgen 134>, //CLK_TOP_APLL12_CK_DIV4 + <&topckgen 135>, //CLK_TOP_APLL12_CK_DIV_TDMOUT_M + <&topckgen 44>, //CLK_TOP_AUDIO_H + <&clk26m>; + clock-names = "aud_infra_clk", + "mtkaif_26m_clk", + "top_mux_audio", + "top_mux_audio_int", + "top_mainpll_d2_d4", + "top_mux_aud_1", + "top_apll1_ck", + "top_mux_aud_2", + "top_apll2_ck", + "top_mux_aud_eng1", + "top_apll1_d8", + "top_mux_aud_eng2", + "top_apll2_d8", + "top_i2s0_m_sel", + "top_i2s1_m_sel", + "top_i2s2_m_sel", + "top_i2s4_m_sel", + "top_tdm_m_sel", + "top_apll12_div0", + "top_apll12_div1", + "top_apll12_div2", + "top_apll12_div4", + "top_apll12_div_tdm", + "top_mux_audio_h", + "top_clk26m_clk"; + }; + +... From patchwork Mon May 23 13:28:55 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859080 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 4D2DDC433F5 for ; Mon, 23 May 2022 13:45:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=5lwQEcVicb/TaSwRTCttXkZbik4U6C1kfBKJ30Yt5n4=; b=IpxgT8RUF2HtUy 1Djm1YQWhrPijdZlpQvawhxGS5YF5rHwUz7xISBUcOeDHgtSM2MkzDxa/4DKcahAV1q1miHHO7a7v 3yQT0creAWVcXC2noaZ3UewyTs+PFUAkzw9J8ibbxHqMX3ximWJAFlQ1BFmfv5TRnzomgU9guqBz3 l+9yiqWZsA0u1kiUybHxLW7ydcClx/w6FMzgHyUcitmef4N4IM0dJLp9sMgWSblF6yvfrUrEs8smJ 2HOm+9lXTyfZ0pZIWquvoTGxpFRws5hGs3rqLTixQocMC8Wn9Zh+asaLaN2jFmEgY/qHlCoKMH6Wy q40hoSECmZupU6QxPYJw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Lw-004V5M-Oi; Mon, 23 May 2022 13:44:10 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HH-004ShK-Uo; Mon, 23 May 2022 13:39:35 +0000 X-UUID: 8c945bd7d65d46d6af101b9f2295febb-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:352254e8-a424-46eb-9c1c-51dcad1a82f1, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:-5 X-CID-META: VersionHash:2a19b09, CLOUDID:d0204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 8c945bd7d65d46d6af101b9f2295febb-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 679819188; Mon, 23 May 2022 06:39:13 -0700 Received: from mtkmbs11n2.mediatek.inc (172.21.101.187) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:19 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n2.mediatek.inc (172.21.101.187) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:17 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:16 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 17/20] ASoC: mediatek: mt8186: add machine driver with mt6366, da7219 and max98357 Date: Mon, 23 May 2022 21:28:55 +0800 Message-ID: <20220523132858.22166-18-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063920_048529_2F829FA1 X-CRM114-Status: GOOD ( 17.54 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add support for mt8186 board with mt6366, da7219 and max98357. Signed-off-by: Jiaxin Yu --- .../mt8186/mt8186-mt6366-da7219-max98357.c | 1003 +++++++++++++++++ 1 file changed, 1003 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c new file mode 100644 index 000000000000..72159dde227d --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-da7219-max98357.c @@ -0,0 +1,1003 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-mt6366-da7219-max98357.c +// -- MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu +// + +#include +#include +#include +#include +#include +#include + +#include "../../codecs/da7219-aad.h" +#include "../../codecs/da7219.h" +#include "../../codecs/mt6358.h" +#include "../common/mtk-afe-platform-driver.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-clk.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-mt6366-common.h" + +#define DA7219_CODEC_DAI "da7219-hifi" +#define DA7219_DEV_NAME "da7219.5-001a" + +struct mt8186_mt6366_da7219_max98357_priv { + struct snd_soc_jack headset_jack, hdmi_jack; +}; + +static struct snd_soc_codec_conf mt8186_mt6366_da7219_max98357_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("mt6358-sound"), + .name_prefix = "Mt6366", + }, + { + .dlc = COMP_CODEC_CONF("bt-sco"), + .name_prefix = "Mt8186 bt", + }, + { + .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), + .name_prefix = "Mt8186 hdmi", + }, +}; + +static int mt8186_da7219_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8186_mt6366_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &priv->headset_jack; + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + int ret; + + /* Enable Headset and 4 Buttons Jack detection */ + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3 | SND_JACK_LINEOUT, + jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + da7219_aad_jack_det(cmpnt_codec, &priv->headset_jack); + + return 0; +} + +static int mt8186_da7219_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 256; + unsigned int mclk_fs = rate * mclk_fs_ratio; + unsigned int freq; + int ret = 0, j; + + ret = snd_soc_dai_set_sysclk(asoc_rtd_to_cpu(rtd, 0), 0, + mclk_fs, SND_SOC_CLOCK_OUT); + if (ret < 0) { + dev_err(rtd->dev, "failed to set cpu dai sysclk: %d\n", ret); + return ret; + } + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { + ret = snd_soc_dai_set_sysclk(codec_dai, + DA7219_CLKSRC_MCLK, + mclk_fs, + SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(rtd->dev, "failed to set sysclk: %d\n", + ret); + return ret; + } + + if ((rate % 8000) == 0) + freq = DA7219_PLL_FREQ_OUT_98304; + else + freq = DA7219_PLL_FREQ_OUT_90316; + + ret = snd_soc_dai_set_pll(codec_dai, 0, + DA7219_SYSCLK_PLL_SRM, + 0, freq); + if (ret) { + dev_err(rtd->dev, "failed to start PLL: %d\n", + ret); + return ret; + } + } + } + + return 0; +} + +static int mt8186_da7219_i2s_hw_free(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_dai *codec_dai; + int ret = 0, j; + + for_each_rtd_codec_dais(rtd, j, codec_dai) { + if (!strcmp(codec_dai->component->name, DA7219_DEV_NAME)) { + ret = snd_soc_dai_set_pll(codec_dai, + 0, DA7219_SYSCLK_MCLK, 0, 0); + if (ret < 0) { + dev_err(rtd->dev, "failed to stop PLL: %d\n", + ret); + break; + } + } + } + + return ret; +} + +static const struct snd_soc_ops mt8186_da7219_i2s_ops = { + .hw_params = mt8186_da7219_i2s_hw_params, + .hw_free = mt8186_da7219_i2s_hw_free, +}; + +static int mt8186_mt6366_da7219_max98357_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mt8186_mt6366_da7219_max98357_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); + return ret; + } + + return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); +} + +static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params, + snd_pcm_format_t fmt) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); + + /* fix BE i2s channel to 2 channel */ + channels->min = 2; + channels->max = 2; + + /* clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, fmt); + + return 0; +} + +static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); +} + +static int mt8186_anx7625_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); +} + +static int mt8186_mt6366_da7219_max98357_playback_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_playback_ops = { + .startup = mt8186_mt6366_da7219_max98357_playback_startup, +}; + +static int mt8186_mt6366_da7219_max98357_capture_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 1, 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8186_mt6366_da7219_max98357_capture_ops = { + .startup = mt8186_mt6366_da7219_max98357_capture_startup, +}; + +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback12, + DAILINK_COMP_ARRAY(COMP_CPU("DL12")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback4, + DAILINK_COMP_ARRAY(COMP_CPU("DL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback5, + DAILINK_COMP_ARRAY(COMP_CPU("DL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback6, + DAILINK_COMP_ARRAY(COMP_CPU("DL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback7, + DAILINK_COMP_ARRAY(COMP_CPU("DL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback8, + DAILINK_COMP_ARRAY(COMP_CPU("DL8")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture4, + DAILINK_COMP_ARRAY(COMP_CPU("UL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture5, + DAILINK_COMP_ARRAY(COMP_CPU("UL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture6, + DAILINK_COMP_ARRAY(COMP_CPU("UL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture7, + DAILINK_COMP_ARRAY(COMP_CPU("UL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_lpbk, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_fm, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_bargein, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(adda, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", + "mt6358-snd-codec-aif1"), + COMP_CODEC("dmic-codec", + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain1, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain2, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src1, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src2, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(connsys_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(tdm_in, + DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_ul1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul2, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul3, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul5, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul6, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +static struct snd_soc_dai_link mt8186_mt6366_da7219_max98357_dai_links[] = { + /* Front End DAI links */ + { + .name = "Playback_1", + .stream_name = "Playback_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_da7219_max98357_playback_ops, + SND_SOC_DAILINK_REG(playback1), + }, + { + .name = "Playback_12", + .stream_name = "Playback_12", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback12), + }, + { + .name = "Playback_2", + .stream_name = "Playback_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(playback2), + }, + { + .name = "Playback_3", + .stream_name = "Playback_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_da7219_max98357_playback_ops, + SND_SOC_DAILINK_REG(playback3), + }, + { + .name = "Playback_4", + .stream_name = "Playback_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback4), + }, + { + .name = "Playback_5", + .stream_name = "Playback_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback5), + }, + { + .name = "Playback_6", + .stream_name = "Playback_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback6), + }, + { + .name = "Playback_7", + .stream_name = "Playback_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback7), + }, + { + .name = "Playback_8", + .stream_name = "Playback_8", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback8), + }, + { + .name = "Capture_1", + .stream_name = "Capture_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture1), + }, + { + .name = "Capture_2", + .stream_name = "Capture_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_da7219_max98357_capture_ops, + SND_SOC_DAILINK_REG(capture2), + }, + { + .name = "Capture_3", + .stream_name = "Capture_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture3), + }, + { + .name = "Capture_4", + .stream_name = "Capture_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_da7219_max98357_capture_ops, + SND_SOC_DAILINK_REG(capture4), + }, + { + .name = "Capture_5", + .stream_name = "Capture_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture5), + }, + { + .name = "Capture_6", + .stream_name = "Capture_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(capture6), + }, + { + .name = "Capture_7", + .stream_name = "Capture_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture7), + }, + { + .name = "Hostless_LPBK", + .stream_name = "Hostless_LPBK", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_lpbk), + }, + { + .name = "Hostless_FM", + .stream_name = "Hostless_FM", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_fm), + }, + { + .name = "Hostless_SRC_1", + .stream_name = "Hostless_SRC_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src1), + }, + { + .name = "Hostless_SRC_Bargein", + .stream_name = "Hostless_SRC_Bargein", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_bargein), + }, + { + .name = "Hostless_HW_Gain_AAudio", + .stream_name = "Hostless_HW_Gain_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), + }, + { + .name = "Hostless_SRC_AAudio", + .stream_name = "Hostless_SRC_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_aaudio), + }, + /* Back End DAI links */ + { + .name = "Primary Codec", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .init = mt8186_mt6366_init, + SND_SOC_DAILINK_REG(adda), + }, + { + .name = "I2S3", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_IF | + SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + .ignore_suspend = 1, + .init = mt8186_mt6366_da7219_max98357_hdmi_init, + .be_hw_params_fixup = mt8186_anx7625_i2s_hw_params_fixup, + SND_SOC_DAILINK_REG(i2s3), + }, + { + .name = "I2S0", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + .ops = &mt8186_da7219_i2s_ops, + SND_SOC_DAILINK_REG(i2s0), + }, + { + .name = "I2S1", + .no_pcm = 1, + .dpcm_playback = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + .init = mt8186_da7219_init, + .ops = &mt8186_da7219_i2s_ops, + SND_SOC_DAILINK_REG(i2s1), + }, + { + .name = "I2S2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + SND_SOC_DAILINK_REG(i2s2), + }, + { + .name = "HW Gain 1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain1), + }, + { + .name = "HW Gain 2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain2), + }, + { + .name = "HW_SRC_1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src1), + }, + { + .name = "HW_SRC_2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src2), + }, + { + .name = "CONNSYS_I2S", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(connsys_i2s), + }, + { + .name = "PCM 1", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF, + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), + }, + { + .name = "TDM IN", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm_in), + }, + /* dummy BE for ul memif to record from dl memif */ + { + .name = "Hostless_UL1", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul1), + }, + { + .name = "Hostless_UL2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul2), + }, + { + .name = "Hostless_UL3", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul3), + }, + { + .name = "Hostless_UL5", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul5), + }, + { + .name = "Hostless_UL6", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul6), + }, +}; + +static const struct snd_soc_dapm_widget +mt8186_mt6366_da7219_max98357_widgets[] = { + SND_SOC_DAPM_SPK("SPK Out", NULL), + SND_SOC_DAPM_OUTPUT("HDMI Out"), +}; + +static const struct snd_soc_dapm_route +mt8186_mt6366_da7219_max98357_routes[] = { + /* SPK */ + { "SPK Out", NULL, "Speaker" }, + /* HDMI */ + { "HDMI Out", NULL, "TX" }, +}; + +static const struct snd_kcontrol_new +mt8186_mt6366_da7219_max98357_controls[] = { + SOC_DAPM_PIN_SWITCH("SPK Out"), + SOC_DAPM_PIN_SWITCH("HDMI Out"), +}; + +static struct snd_soc_card mt8186_mt6366_da7219_max98357_soc_card = { + .name = "mt8186_mt6366_da7219_max98357", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_da7219_max98357_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_dai_links), + .controls = mt8186_mt6366_da7219_max98357_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_controls), + .dapm_widgets = mt8186_mt6366_da7219_max98357_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_widgets), + .dapm_routes = mt8186_mt6366_da7219_max98357_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_routes), + .codec_conf = mt8186_mt6366_da7219_max98357_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_da7219_max98357_codec_conf), +}; + +static int mt8186_mt6366_da7219_max98357_dev_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card; + struct snd_soc_dai_link *dai_link; + struct mt8186_mt6366_da7219_max98357_priv *priv; + struct device_node *platform_node, *headset_codec, *playback_codec; + int ret, i; + + card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); + if (!card) + return -EINVAL; + card->dev = &pdev->dev; + + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); + if (!platform_node) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); + goto err_platform_node; + } + + playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs"); + if (!playback_codec) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); + goto err_playback_codec; + } + + headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); + if (!headset_codec) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); + goto err_headset_codec; + } + + for_each_card_prelinks(card, i, dai_link) { + ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", + dai_link->name); + goto err_probe; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dai_link->name); + goto err_probe; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dai_link->name); + goto err_probe; + } + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto err_probe; + } + + snd_soc_card_set_drvdata(card, priv); + + ret = mt8186_afe_gpio_init(&pdev->dev); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); + goto err_probe; + } + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); + +err_probe: + of_node_put(headset_codec); +err_headset_codec: + of_node_put(playback_codec); +err_playback_codec: + of_node_put(platform_node); +err_platform_node: + return ret; +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id mt8186_mt6366_da7219_max98357_dt_match[] = { + { .compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound", + .data = &mt8186_mt6366_da7219_max98357_soc_card, + }, + {} +}; +#endif + +static struct platform_driver mt8186_mt6366_da7219_max98357_driver = { + .driver = { + .name = "mt8186_mt6366_da7219_max98357", +#if IS_ENABLED(CONFIG_OF) + .of_match_table = mt8186_mt6366_da7219_max98357_dt_match, +#endif + .pm = &snd_soc_pm_ops, + }, + .probe = mt8186_mt6366_da7219_max98357_dev_probe, +}; + +module_platform_driver(mt8186_mt6366_da7219_max98357_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8186-MT6366-DA7219-MAX98357 ALSA SoC machine driver"); +MODULE_AUTHOR("Jiaxin Yu "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("mt8186_mt6366_da7219_max98357 soc card"); From patchwork Mon May 23 13:28:56 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859058 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 25FF8C433F5 for ; Mon, 23 May 2022 13:40:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=LqYimZ5joe4WEKI05J0MvVgbr62YKX24hmsgbmITj9I=; b=BLgrlMJD6Sgxpn jsYyX+MoJX53Gkrz2oewuRDDw1b++pdfl0zTXjCJQev5DOedJC1zI0GceWgju5AsMH9Lwd3QO+/s9 HZZWqL8OUw7eGUlqt1q0aZIMo/FkBN8dqSnuDMJbuGFRS/vjoyPRDhs7ncJhDakqqHVtYbO/TMW/A doicFVnYLzGYD6fuDrM2Yb+tp+DIphuOXdZRzDDK43zIJ87kS1K9Ti8NekeQF4PUmbnYQ/BDwiqQn +dvrYAx8Q1Qquz1lkHZ9u8QjxXh3Nj2E0ecuNHQp1ALF17XMrsrAGpk3T3Fl7ckJEigQvR0CYlhf+ mPKk9gwAWZ1qUBAxBX/g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HJ-004Skq-De; Mon, 23 May 2022 13:39:21 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HB-004Sgq-Q4; Mon, 23 May 2022 13:39:15 +0000 X-UUID: 73028e6b7144491f8e76eacef76a61f5-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:4203e0dd-0b75-461f-b781-2a6191945630, OB:0, LO B:0,IP:0,URL:25,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:25 X-CID-META: VersionHash:2a19b09, CLOUDID:ee283ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: 73028e6b7144491f8e76eacef76a61f5-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1591876696; Mon, 23 May 2022 06:39:08 -0700 Received: from MTKMBS07N2.mediatek.inc (172.21.101.141) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:20 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n2.mediatek.inc (172.21.101.141) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:18 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:17 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 18/20] dt-bindings: mediatek: mt8186: add mt8186-mt6366-da7219-max98357 document Date: Mon, 23 May 2022 21:28:56 +0800 Message-ID: <20220523132858.22166-19-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063913_871571_D375ED29 X-CRM114-Status: GOOD ( 11.41 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add document for mt8186 board with mt6366, da7219 and max98357. Signed-off-by: Jiaxin Yu Acked-by: Rob Herring --- .../sound/mt8186-mt6366-da7219-max98357.yaml | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml new file mode 100644 index 000000000000..513cd28b2027 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-da7219-max98357.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mt8186-mt6366-da7219-max98357.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek MT8186 with MT6366, DA7219 and MAX98357 ASoC sound card driver + +maintainers: + - Jiaxin Yu + +description: + This binding describes the MT8186 sound card. + +properties: + compatible: + enum: + - mediatek,mt8186-mt6366-da7219-max98357-sound + + mediatek,platform: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of MT8186 ASoC platform. + + headset-codec: + type: object + additionalProperties: false + properties: + sound-dai: + maxItems: 1 + required: + - sound-dai + + playback-codecs: + type: object + additionalProperties: false + properties: + sound-dai: + items: + - description: phandle of dp codec + - description: phandle of l channel speaker codec + - description: phandle of r channel speaker codec + minItems: 2 + required: + - sound-dai + +additionalProperties: false + +required: + - compatible + - mediatek,platform + - headset-codec + - playback-codecs + +examples: + - | + + sound: mt8186-sound { + compatible = "mediatek,mt8186-mt6366-da7219-max98357-sound"; + mediatek,platform = <&afe>; + pinctrl-names = "aud_clk_mosi_off", + "aud_clk_mosi_on"; + pinctrl-0 = <&aud_clk_mosi_off>; + pinctrl-1 = <&aud_clk_mosi_on>; + + headset-codec { + sound-dai = <&da7219>; + }; + + playback-codecs { + sound-dai = <&anx_bridge_dp>, + <&max98357a>; + }; + }; + +... From patchwork Mon May 23 13:28:57 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859077 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 04218C433EF for ; Mon, 23 May 2022 13:43:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=X2HiZzDP9S9xiRQShW/KJ1sroPIeH0+s1SC9yrnzLhM=; b=H42kMx+IyVD+4R ZAN7Jp8NPqddm347/7OqFM5IxEDncG9pyBYIAxWLT2DXKiuqTD/p97iLKQiC/MAbjhwbZ/fxq0nqb udX3q28vbZszIaqnhyAh24PSy5NzWyO6KLFEjWlyye8shMNOW0zDvcLQVBVYfqnnPIlHQ+Dx+epZw mzJKhB06oY2Dr3d5Ab+wyHYB+Wke+SP9XyUER6tPUu/QXBVD+qBflQI663IQXgKTL5lUJxdQCN7+G GYv9bVl4IiyPwPzXHFQxEW2fM9bnXSrSViZmdHETIWLUJwBqdBzDWCLS/mFecLNZl8BFtN1Zz7ZRw VACQ18t6fqnDyhjjV5Bg==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8KE-004U6h-8n; Mon, 23 May 2022 13:42:22 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HD-004SiE-Tb; Mon, 23 May 2022 13:39:26 +0000 X-UUID: 5625c8fb5831401680e36d66d3282835-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:5056d410-2ff0-4c01-bf38-3c37df65dcbd, OB:0, LO B:0,IP:0,URL:0,TC:0,Content:-5,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:-5 X-CID-META: VersionHash:2a19b09, CLOUDID:8d204e7a-5ef6-470b-96c9-bdb8ced32786, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:0,File:nil ,QS:0,BEC:nil X-UUID: 5625c8fb5831401680e36d66d3282835-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1952179030; Mon, 23 May 2022 06:39:08 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by MTKMBS62DR.mediatek.inc (172.29.94.18) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:21 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs11n1.mediatek.inc (172.21.101.185) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.2.792.3; Mon, 23 May 2022 21:29:19 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:19 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 19/20] ASoC: mediatek: mt8186: add machine driver with mt6366, rt1019 and rt5682s Date: Mon, 23 May 2022 21:28:57 +0800 Message-ID: <20220523132858.22166-20-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063916_040597_F87BE2F9 X-CRM114-Status: GOOD ( 16.50 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add support for mt8186 board with mt6366, rt1019 and rt5682s. Signed-off-by: Jiaxin Yu --- .../mt8186/mt8186-mt6366-rt1019-rt5682s.c | 979 ++++++++++++++++++ 1 file changed, 979 insertions(+) create mode 100644 sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c new file mode 100644 index 000000000000..bbf7bd849e43 --- /dev/null +++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-rt1019-rt5682s.c @@ -0,0 +1,979 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt8186-mt6366-rt1019-rt5682s.c +// -- MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Jiaxin Yu +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../codecs/mt6358.h" +#include "../../codecs/rt5682.h" +#include "../common/mtk-afe-platform-driver.h" +#include "mt8186-afe-common.h" +#include "mt8186-afe-clk.h" +#include "mt8186-afe-gpio.h" +#include "mt8186-mt6366-common.h" + +#define RT1019_CODEC_DAI "HiFi" +#define RT1019_DEV0_NAME "rt1019p" + +#define RT5682S_CODEC_DAI "rt5682s-aif1" +#define RT5682S_DEV0_NAME "rt5682s.5-001a" + +struct mt8186_mt6366_rt1019_rt5682s_priv { + struct snd_soc_jack headset_jack, hdmi_jack; +}; + +static struct snd_soc_codec_conf mt8186_mt6366_rt1019_rt5682s_codec_conf[] = { + { + .dlc = COMP_CODEC_CONF("mt6358-sound"), + .name_prefix = "Mt6366", + }, + { + .dlc = COMP_CODEC_CONF("bt-sco"), + .name_prefix = "Mt8186 bt", + }, + { + .dlc = COMP_CODEC_CONF("hdmi-audio-codec"), + .name_prefix = "Mt8186 hdmi", + }, +}; + +static int mt8186_rt5682s_init(struct snd_soc_pcm_runtime *rtd) +{ + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + struct snd_soc_jack *jack = &priv->headset_jack; + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | + SND_JACK_BTN_3, + jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret); + return ret; + } + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN); + + return snd_soc_component_set_jack(cmpnt_codec, jack, NULL); +} + +static int mt8186_rt5682s_i2s_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + unsigned int rate = params_rate(params); + unsigned int mclk_fs_ratio = 128; + unsigned int mclk_fs = rate * mclk_fs_ratio; + int bitwidth; + int ret; + + bitwidth = snd_pcm_format_width(params_format(params)); + if (bitwidth < 0) { + dev_err(card->dev, "invalid bit width: %d\n", bitwidth); + return bitwidth; + } + + ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth); + if (ret) { + dev_err(card->dev, "failed to set tdm slot\n"); + return ret; + } + + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL1, + RT5682_PLL1_S_BCLK1, + params_rate(params) * 64, + params_rate(params) * 512); + if (ret) { + dev_err(card->dev, "failed to set pll\n"); + return ret; + } + + ret = snd_soc_dai_set_sysclk(codec_dai, + RT5682_SCLK_S_PLL1, + params_rate(params) * 512, + SND_SOC_CLOCK_IN); + if (ret) { + dev_err(card->dev, "failed to set sysclk\n"); + return ret; + } + + return snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_fs, SND_SOC_CLOCK_OUT); +} + +static const struct snd_soc_ops mt8186_rt5682s_i2s_ops = { + .hw_params = mt8186_rt5682s_i2s_hw_params, +}; + +static int mt8186_mt6366_rt1019_rt5682s_hdmi_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *cmpnt_codec = + asoc_rtd_to_codec(rtd, 0)->component; + struct mt8186_mt6366_rt1019_rt5682s_priv *priv = + snd_soc_card_get_drvdata(rtd->card); + int ret; + + ret = snd_soc_card_jack_new(rtd->card, "HDMI Jack", SND_JACK_LINEOUT, + &priv->hdmi_jack, NULL, 0); + if (ret) { + dev_err(rtd->dev, "HDMI Jack creation failed: %d\n", ret); + return ret; + } + + return snd_soc_component_set_jack(cmpnt_codec, &priv->hdmi_jack, NULL); +} + +static int mt8186_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params, + snd_pcm_format_t fmt) +{ + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + dev_dbg(rtd->dev, "%s(), fix format to %d\n", __func__, fmt); + + /* fix BE i2s channel to 2 channel */ + channels->min = 2; + channels->max = 2; + + /* clean param mask first */ + snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT), + 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST); + + params_set_format(params, fmt); + + return 0; +} + +static int mt8186_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S24_LE); +} + +static int mt8186_it6505_i2s_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + return mt8186_hw_params_fixup(rtd, params, SNDRV_PCM_FORMAT_S32_LE); +} + +static int mt8186_mt6366_rt1019_rt5682s_playback_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_playback_ops = { + .startup = mt8186_mt6366_rt1019_rt5682s_playback_startup, +}; + +static int mt8186_mt6366_rt1019_rt5682s_capture_startup(struct snd_pcm_substream *substream) +{ + static const unsigned int rates[] = { + 48000 + }; + static const unsigned int channels[] = { + 1, 2 + }; + static const struct snd_pcm_hw_constraint_list constraints_rates = { + .count = ARRAY_SIZE(rates), + .list = rates, + .mask = 0, + }; + static const struct snd_pcm_hw_constraint_list constraints_channels = { + .count = ARRAY_SIZE(channels), + .list = channels, + .mask = 0, + }; + + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + int ret; + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list rate failed\n"); + return ret; + } + + ret = snd_pcm_hw_constraint_list(runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + if (ret < 0) { + dev_err(rtd->dev, "hw_constraint_list channel failed\n"); + return ret; + } + + return 0; +} + +static const struct snd_soc_ops mt8186_mt6366_rt1019_rt5682s_capture_ops = { + .startup = mt8186_mt6366_rt1019_rt5682s_capture_startup, +}; + +/* FE */ +SND_SOC_DAILINK_DEFS(playback1, + DAILINK_COMP_ARRAY(COMP_CPU("DL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback12, + DAILINK_COMP_ARRAY(COMP_CPU("DL12")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback3, + DAILINK_COMP_ARRAY(COMP_CPU("DL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback4, + DAILINK_COMP_ARRAY(COMP_CPU("DL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback5, + DAILINK_COMP_ARRAY(COMP_CPU("DL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback6, + DAILINK_COMP_ARRAY(COMP_CPU("DL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback7, + DAILINK_COMP_ARRAY(COMP_CPU("DL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(playback8, + DAILINK_COMP_ARRAY(COMP_CPU("DL8")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture1, + DAILINK_COMP_ARRAY(COMP_CPU("UL1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture2, + DAILINK_COMP_ARRAY(COMP_CPU("UL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture3, + DAILINK_COMP_ARRAY(COMP_CPU("UL3")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture4, + DAILINK_COMP_ARRAY(COMP_CPU("UL4")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture5, + DAILINK_COMP_ARRAY(COMP_CPU("UL5")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture6, + DAILINK_COMP_ARRAY(COMP_CPU("UL6")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(capture7, + DAILINK_COMP_ARRAY(COMP_CPU("UL7")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_lpbk, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless LPBK DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_fm, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless FM DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_1_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_bargein, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_SRC_Bargein_DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* BE */ +SND_SOC_DAILINK_DEFS(adda, + DAILINK_COMP_ARRAY(COMP_CPU("ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6358-sound", + "mt6358-snd-codec-aif1"), + COMP_CODEC("dmic-codec", + "dmic-hifi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s0, + DAILINK_COMP_ARRAY(COMP_CPU("I2S0")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s1, + DAILINK_COMP_ARRAY(COMP_CPU("I2S1")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s2, + DAILINK_COMP_ARRAY(COMP_CPU("I2S2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain1, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_gain2, + DAILINK_COMP_ARRAY(COMP_CPU("HW Gain 2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src1, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_1")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hw_src2, + DAILINK_COMP_ARRAY(COMP_CPU("HW_SRC_2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(connsys_i2s, + DAILINK_COMP_ARRAY(COMP_CPU("CONNSYS_I2S")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(pcm1, + DAILINK_COMP_ARRAY(COMP_CPU("PCM 1")), + DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm-wb")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(tdm_in, + DAILINK_COMP_ARRAY(COMP_CPU("TDM IN")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* hostless */ +SND_SOC_DAILINK_DEFS(hostless_ul1, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL1 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul2, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL2 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul3, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL3 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul5, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL5 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_ul6, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless_UL6 DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_hw_gain_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless HW Gain AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(hostless_src_aaudio, + DAILINK_COMP_ARRAY(COMP_CPU("Hostless SRC AAudio DAI")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +static struct snd_soc_dai_link mt8186_mt6366_rt1019_rt5682s_dai_links[] = { + /* Front End DAI links */ + { + .name = "Playback_1", + .stream_name = "Playback_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, + SND_SOC_DAILINK_REG(playback1), + }, + { + .name = "Playback_12", + .stream_name = "Playback_12", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback12), + }, + { + .name = "Playback_2", + .stream_name = "Playback_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(playback2), + }, + { + .name = "Playback_3", + .stream_name = "Playback_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_rt1019_rt5682s_playback_ops, + SND_SOC_DAILINK_REG(playback3), + }, + { + .name = "Playback_4", + .stream_name = "Playback_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback4), + }, + { + .name = "Playback_5", + .stream_name = "Playback_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback5), + }, + { + .name = "Playback_6", + .stream_name = "Playback_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback6), + }, + { + .name = "Playback_7", + .stream_name = "Playback_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback7), + }, + { + .name = "Playback_8", + .stream_name = "Playback_8", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + SND_SOC_DAILINK_REG(playback8), + }, + { + .name = "Capture_1", + .stream_name = "Capture_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture1), + }, + { + .name = "Capture_2", + .stream_name = "Capture_2", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, + SND_SOC_DAILINK_REG(capture2), + }, + { + .name = "Capture_3", + .stream_name = "Capture_3", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture3), + }, + { + .name = "Capture_4", + .stream_name = "Capture_4", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + .ops = &mt8186_mt6366_rt1019_rt5682s_capture_ops, + SND_SOC_DAILINK_REG(capture4), + }, + { + .name = "Capture_5", + .stream_name = "Capture_5", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture5), + }, + { + .name = "Capture_6", + .stream_name = "Capture_6", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_format = 1, + .dpcm_merged_chan = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(capture6), + }, + { + .name = "Capture_7", + .stream_name = "Capture_7", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(capture7), + }, + { + .name = "Hostless_LPBK", + .stream_name = "Hostless_LPBK", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_lpbk), + }, + { + .name = "Hostless_FM", + .stream_name = "Hostless_FM", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_fm), + }, + { + .name = "Hostless_SRC_1", + .stream_name = "Hostless_SRC_1", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src1), + }, + { + .name = "Hostless_SRC_Bargein", + .stream_name = "Hostless_SRC_Bargein", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_bargein), + }, + { + .name = "Hostless_HW_Gain_AAudio", + .stream_name = "Hostless_HW_Gain_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_hw_gain_aaudio), + }, + { + .name = "Hostless_SRC_AAudio", + .stream_name = "Hostless_SRC_AAudio", + .trigger = {SND_SOC_DPCM_TRIGGER_PRE, + SND_SOC_DPCM_TRIGGER_PRE}, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_src_aaudio), + }, + /* Back End DAI links */ + { + .name = "Primary Codec", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .init = mt8186_mt6366_init, + SND_SOC_DAILINK_REG(adda), + }, + { + .name = "I2S3", + .no_pcm = 1, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_IB_IF | + SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + .ignore_suspend = 1, + .init = mt8186_mt6366_rt1019_rt5682s_hdmi_init, + .be_hw_params_fixup = mt8186_it6505_i2s_hw_params_fixup, + SND_SOC_DAILINK_REG(i2s3), + }, + { + .name = "I2S0", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + .ops = &mt8186_rt5682s_i2s_ops, + SND_SOC_DAILINK_REG(i2s0), + }, + { + .name = "I2S1", + .no_pcm = 1, + .dpcm_playback = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + .init = mt8186_rt5682s_init, + .ops = &mt8186_rt5682s_i2s_ops, + SND_SOC_DAILINK_REG(i2s1), + }, + { + .name = "I2S2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + .be_hw_params_fixup = mt8186_i2s_hw_params_fixup, + SND_SOC_DAILINK_REG(i2s2), + }, + { + .name = "HW Gain 1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain1), + }, + { + .name = "HW Gain 2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_gain2), + }, + { + .name = "HW_SRC_1", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src1), + }, + { + .name = "HW_SRC_2", + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hw_src2), + }, + { + .name = "CONNSYS_I2S", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(connsys_i2s), + }, + { + .name = "PCM 1", + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_IF, + .no_pcm = 1, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(pcm1), + }, + { + .name = "TDM IN", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(tdm_in), + }, + /* dummy BE for ul memif to record from dl memif */ + { + .name = "Hostless_UL1", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul1), + }, + { + .name = "Hostless_UL2", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul2), + }, + { + .name = "Hostless_UL3", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul3), + }, + { + .name = "Hostless_UL5", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul5), + }, + { + .name = "Hostless_UL6", + .no_pcm = 1, + .dpcm_capture = 1, + .ignore_suspend = 1, + SND_SOC_DAILINK_REG(hostless_ul6), + }, +}; + +static const struct snd_soc_dapm_widget +mt8186_mt6366_rt1019_rt5682s_widgets[] = { + SND_SOC_DAPM_SPK("SPK Out", NULL), + SND_SOC_DAPM_OUTPUT("HDMI Out"), +}; + +static const struct snd_soc_dapm_route +mt8186_mt6366_rt1019_rt5682s_routes[] = { + /* SPK */ + { "SPK Out", NULL, "Speaker" }, + /* HDMI */ + { "HDMI Out", NULL, "TX" }, +}; + +static const struct snd_kcontrol_new +mt8186_mt6366_rt1019_rt5682s_controls[] = { + SOC_DAPM_PIN_SWITCH("SPK Out"), + SOC_DAPM_PIN_SWITCH("HDMI Out"), +}; + +static struct snd_soc_card mt8186_mt6366_rt1019_rt5682s_soc_card = { + .name = "mt8186_mt6366_rt1019_rt5682s", + .owner = THIS_MODULE, + .dai_link = mt8186_mt6366_rt1019_rt5682s_dai_links, + .num_links = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_dai_links), + .controls = mt8186_mt6366_rt1019_rt5682s_controls, + .num_controls = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_controls), + .dapm_widgets = mt8186_mt6366_rt1019_rt5682s_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_widgets), + .dapm_routes = mt8186_mt6366_rt1019_rt5682s_routes, + .num_dapm_routes = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_routes), + .codec_conf = mt8186_mt6366_rt1019_rt5682s_codec_conf, + .num_configs = ARRAY_SIZE(mt8186_mt6366_rt1019_rt5682s_codec_conf), +}; + +static int mt8186_mt6366_rt1019_rt5682s_dev_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card; + struct snd_soc_dai_link *dai_link; + struct mt8186_mt6366_rt1019_rt5682s_priv *priv; + struct device_node *platform_node, *headset_codec, *playback_codec; + int ret, i; + + card = (struct snd_soc_card *)of_device_get_match_data(&pdev->dev); + if (!card) + return -EINVAL; + card->dev = &pdev->dev; + + platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); + if (!platform_node) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'platform' missing or invalid\n"); + goto err_platform_node; + } + + playback_codec = of_get_child_by_name(pdev->dev.of_node, "playback-codecs"); + if (!playback_codec) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'speaker-codecs' missing or invalid\n"); + goto err_playback_codec; + } + + headset_codec = of_get_child_by_name(pdev->dev.of_node, "headset-codec"); + if (!headset_codec) { + ret = -EINVAL; + dev_err_probe(&pdev->dev, ret, "Property 'headset-codec' missing or invalid\n"); + goto err_headset_codec; + } + + for_each_card_prelinks(card, i, dai_link) { + ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set speaker_codec fail\n", + dai_link->name); + goto err_probe; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dai_link->name); + goto err_probe; + } + + ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1"); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s set headset_codec fail\n", + dai_link->name); + goto err_probe; + } + + if (!dai_link->platforms->name) + dai_link->platforms->of_node = platform_node; + } + + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + goto err_probe; + } + + snd_soc_card_set_drvdata(card, priv); + + ret = mt8186_afe_gpio_init(&pdev->dev); + if (ret) { + dev_err_probe(&pdev->dev, ret, "%s init gpio error\n", __func__); + goto err_probe; + } + + ret = devm_snd_soc_register_card(&pdev->dev, card); + if (ret) + dev_err_probe(&pdev->dev, ret, "%s snd_soc_register_card fail\n", __func__); + +err_probe: + of_node_put(headset_codec); +err_headset_codec: + of_node_put(playback_codec); +err_playback_codec: + of_node_put(platform_node); +err_platform_node: + return ret; +} + +#if IS_ENABLED(CONFIG_OF) +static const struct of_device_id mt8186_mt6366_rt1019_rt5682s_dt_match[] = { + { .compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound", + .data = &mt8186_mt6366_rt1019_rt5682s_soc_card, + }, + {} +}; +#endif + +static struct platform_driver mt8186_mt6366_rt1019_rt5682s_driver = { + .driver = { + .name = "mt8186_mt6366_rt1019_rt5682s", +#if IS_ENABLED(CONFIG_OF) + .of_match_table = mt8186_mt6366_rt1019_rt5682s_dt_match, +#endif + .pm = &snd_soc_pm_ops, + }, + .probe = mt8186_mt6366_rt1019_rt5682s_dev_probe, +}; + +module_platform_driver(mt8186_mt6366_rt1019_rt5682s_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8186-MT6366-RT1019-RT5682S ALSA SoC machine driver"); +MODULE_AUTHOR("Jiaxin Yu "); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("mt8186_mt6366_rt1019_rt5682s soc card"); From patchwork Mon May 23 13:28:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiaxin Yu X-Patchwork-Id: 12859076 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 bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (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 8C6F2C433F5 for ; Mon, 23 May 2022 13:43:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=9trME+9Bc+is3VKcOtpe52WJW70qNZW89aSgYI+QoIg=; b=OzDNaT8w3kXFyH 7egxQoiCjHXY8hOSXzfX86M/G2fp71/g2dXyeFpUg91/lBYw/hUHALSLimrIsUijvuUEqXE01VPJc zTaOOgiuHDGpf0Zgbcrc6KwS6FDBqNy1mvjcmTXaTnFhi8vPXJv0rIYhkN2VaKocHi9xVwkkVtaMr OhcBpER9UpSu1lveR/ah9CHDKQZdfdvoe3ORuhiyqPFpQbYd4Hmo73SjEaE7uWEIshnhRtAfj1NdG HNCl899KjJdB1Fw6NRpuyxsOS/KDhFuh4+GYaiYsTSf2ojSgrAkGs+gC89kU6xdMYSCvi1v6EHo1V Ny1F/dNqg0f503suIh4g==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8Jv-004TwU-9R; Mon, 23 May 2022 13:42:03 +0000 Received: from mailgw02.mediatek.com ([216.200.240.185]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1nt8HF-004SjX-VT; Mon, 23 May 2022 13:39:25 +0000 X-UUID: 93046b3840d7478a968149792662eb2e-20220523 X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.5, REQID:ff730dc1-c304-427e-a134-b8712d859543, OB:0, LO B:0,IP:0,URL:25,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,RULE:Release_Ham,ACT ION:release,TS:25 X-CID-META: VersionHash:2a19b09, CLOUDID:23293ee3-edbf-4bd4-8a34-dfc5f7bb086d, C OID:IGNORED,Recheck:0,SF:nil,TC:nil,Content:0,EDM:-3,IP:nil,URL:1,File:nil ,QS:0,BEC:nil X-UUID: 93046b3840d7478a968149792662eb2e-20220523 Received: from mtkcas66.mediatek.inc [(172.29.193.44)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-SHA384 256/256) with ESMTP id 1616617256; Mon, 23 May 2022 06:39:13 -0700 Received: from mtkmbs07n1.mediatek.inc (172.21.101.16) by MTKMBS62N1.mediatek.inc (172.29.193.41) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 06:29:22 -0700 Received: from mtkcas10.mediatek.inc (172.21.101.39) by mtkmbs07n1.mediatek.inc (172.21.101.16) with Microsoft SMTP Server (TLS) id 15.0.1497.2; Mon, 23 May 2022 21:29:20 +0800 Received: from localhost.localdomain (10.17.3.154) by mtkcas10.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.0.1497.2 via Frontend Transport; Mon, 23 May 2022 21:29:19 +0800 From: Jiaxin Yu To: , , CC: , , , , , , , , , , , Jiaxin Yu Subject: [PATCH v5 20/20] dt-bindings: mediatek: mt8186: add mt8186-mt6366-rt1019-rt5682s document Date: Mon, 23 May 2022 21:28:58 +0800 Message-ID: <20220523132858.22166-21-jiaxin.yu@mediatek.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220523132858.22166-1-jiaxin.yu@mediatek.com> References: <20220523132858.22166-1-jiaxin.yu@mediatek.com> MIME-Version: 1.0 X-MTK: N X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220523_063918_054680_18C7A2BA X-CRM114-Status: GOOD ( 11.31 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org Add document for mt8186 board with mt6366, rt1019 and rt5682s. Signed-off-by: Jiaxin Yu Acked-by: Rob Herring --- .../sound/mt8186-mt6366-rt1019-rt5682s.yaml | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml diff --git a/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml new file mode 100644 index 000000000000..059a7629b2d3 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt8186-mt6366-rt1019-rt5682s.yaml @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mt8186-mt6366-rt1019-rt5682s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek MT8186 with MT6366, RT1019 and RT5682S ASoC sound card driver + +maintainers: + - Jiaxin Yu + +description: + This binding describes the MT8186 sound card. + +properties: + compatible: + enum: + - mediatek,mt8186-mt6366-rt1019-rt5682s-sound + + mediatek,platform: + $ref: "/schemas/types.yaml#/definitions/phandle" + description: The phandle of MT8186 ASoC platform. + + headset-codec: + type: object + additionalProperties: false + properties: + sound-dai: + maxItems: 1 + required: + - sound-dai + + playback-codecs: + type: object + additionalProperties: false + properties: + sound-dai: + items: + - description: phandle of dp codec + - description: phandle of l channel speaker codec + - description: phandle of r channel speaker codec + minItems: 2 + required: + - sound-dai + +additionalProperties: false + +required: + - compatible + - mediatek,platform + - headset-codec + - playback-codecs + +examples: + - | + + sound: mt8186-sound { + compatible = "mediatek,mt8186-mt6366-rt1019-rt5682s-sound"; + mediatek,platform = <&afe>; + pinctrl-names = "aud_clk_mosi_off", + "aud_clk_mosi_on"; + pinctrl-0 = <&aud_clk_mosi_off>; + pinctrl-1 = <&aud_clk_mosi_on>; + + headset-codec { + sound-dai = <&rt5682s>; + }; + + playback-codecs { + sound-dai = <&it6505dptx>, + <&rt1019p>; + }; + }; + +...