From patchwork Mon Feb 26 14:01:40 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776103 Received: from mail-lj1-f173.google.com (mail-lj1-f173.google.com [209.85.208.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9D75C129A97 for ; Mon, 26 Feb 2024 14:02:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956133; cv=none; b=oYHl7IXDDFK/EedCCfUVUt36IkUmh8n2x5L1eOqTn19aKPbhcnVL0K1AklKmOG0ltOToNyhvPjGnXShrGtaWOypjzKNXhEHMRTOTUqy7yz4O1XgEiHN9MYuWT4HOaWZruIM162BR40BOjr7S/sBKTJenwZpMdF/dSKMjPS9POx0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956133; c=relaxed/simple; bh=RB7Eb842OpfsNPEOj+50LxyJbOuZfxgXUF/IRPIlUPQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mYKfgvQZ3618oFGnEx8I3ThzuPHwT/drrhaa3BupCuhuHbZ01ErpSHquJHtAX8qeeydAS10AC5MqY+EGLmNvHCaYM3MJq2JjKqc20d/LSofsgFJg+yQbbXmx564pUf5MrI5iGiiDt4kyRqqktVvK7696elMxw/C4tIG39N3/hoA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=jaEfZJGZ; arc=none smtp.client-ip=209.85.208.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="jaEfZJGZ" Received: by mail-lj1-f173.google.com with SMTP id 38308e7fff4ca-2d23a22233fso30419191fa.2 for ; Mon, 26 Feb 2024 06:02:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956130; x=1709560930; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=sJrWsRR3ts/FqJ8eyXIf3fjxmrfS3S4Qmfe209Uxc5s=; b=jaEfZJGZTuMWv/2ajCyFsOmpVp7xFe8Tn187QpqMiYCROzwNuOVf0ykVEGGxSuqmXs 6w4Y2g9MriLE49eaSsp/Pt1UIWfqK9ggnX7GrD9cxw4qLuJA39+/TCUEHZD2sfhz7ENV JHdYMsxAHFl7gxIKAtmkQrN4afXFZh3XdH3ZIdqqVvUM+pWpvR32dxE+WbPHC2U0+p9C vTa82jQzR5m7l5nUeBbANZuedG29tpZXksWqbE1I+IhPHrYiM0ZRurSx3YuZ019mWBL5 ryE88OJ72ZrbA9di0+ixIG/yDajU6tEAVBLfc1qiybsyBxtb0y0feTrccv8bA1Mf/tDn pNGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956130; x=1709560930; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=sJrWsRR3ts/FqJ8eyXIf3fjxmrfS3S4Qmfe209Uxc5s=; b=naI4Zu2214alpPMhxO7E+FYkKihEzFCPJQ5HbMkAZCF9JcwABFV8tBnNIpAZiA1DUZ UivN744TyjFdtvCoEv5o6yIkYsA8+BVsjTSebMzwEGAnC2GmK/pjMWQQoFlZ6z9ZrnMz mszcDBeB8mUbA0mqGfUAlxoqVtVSKlN8yrxozHxWGzCJxhgHr6yg44nDONGhOx8IFwP4 U1ZcSsdwj4Jj9GBJfF1iF/il/2/drwL5UOIrosmUuikG6ro05cmhComdpmafZS0A1QPo W8Ej7/kDX3k9CUgjlchFxp4OFP1AiFXicqkKwHsNqumfZg8/jxGA3gMo38wmZOddS9W6 w21w== X-Forwarded-Encrypted: i=1; AJvYcCUcCY+L62Oc/xo8ZXWyH/mRQ4N+Nvpv/t/wb3oFXcVYkjL67JIUlN4oDwYZIQFBpg69QMtGOE47ywCr8iZAPz4wBx/wShSq+tziB3A= X-Gm-Message-State: AOJu0YwfhFKMtC51zCm9TCxLbK83KWxocVzl4aoQRyz2WoDTC2vgdJyT FpI2YCaySgVHaHWCiay9jIEqSZC7IAUfefNOkQ+354M59xQqyuDht6sZkDSIVQk= X-Google-Smtp-Source: AGHT+IHDZFe0UVmHW49F9REvA6iVNdf2dZuGdONwBfA2sUMFo7E6cmXdifUIZXkHWrSREuG4kPnzdg== X-Received: by 2002:a2e:be87:0:b0:2d2:6200:e661 with SMTP id a7-20020a2ebe87000000b002d26200e661mr5150052ljr.51.1708956129400; Mon, 26 Feb 2024 06:02:09 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:08 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:40 +0100 Subject: [PATCH 02/18] ASoC: dt-bindings: mediatek,mt8365-mt6357: Add audio sound card document Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-2-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3936; i=amergnat@baylibre.com; h=from:subject:message-id; bh=RB7Eb842OpfsNPEOj+50LxyJbOuZfxgXUF/IRPIlUPQ=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncV4ua0Er/v7s+bW1PDrfmI/r/eo2np+/0blY8 AicPQtaJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURURJEA CStUBeJ8/Qq1vZrA9KzH/y9WMN4PUjkealopyiDxH2qcK9wceUHZ4XqZmjdR/w3HnZhoIEp7+nhb6t gNCBBTKKTYkEJeKnWFcOIzshxvUF3v880968wo+j6XkCJCNUVgU2uoGLi80iv9Cw4s+xAtGl68DE1t MKCtsl8/Z2h03HWmM4/D27mxa0Ynh5VWIwkSpSieqrWD/2CYW9gyq4Q4NltQlg1IVzkkMNdYaviq+R dE3BR6wwx45UfG1JocWbN4FjhgScINA5hy9LfRLLAGIeqX/xFbz3RetQ4jPMBrFhAUbqm6QXiXJ8HU BRV7RGXS8LjeCFo6Gb8TuYFpNd7aEJW4VZvf8KWmbW6Q08u5cLlhW05R4zSoUmkVd35n0ivv2mJbBW asIyHtP42GeCvbK1uQXZCcXp527nW5H4i6AZtE3r4m24MaQykrCkwyo/Xg5Azbk4scn4Z2U0jk1+jl 0QvZ41IRAuHvwsnsYEqAyrdXpwiPzLlW1a6slshF0sMLqHd6x7n5I5PbzyQMUw3dnTz/iRHgEJhh1A hGZcPtokNWAOYXe2iajGauzr5KlUWa0Cyg650ze7IlYW3UyArh4ZQ60L19ovBJB1FWvYxIOyHXKm0b SaN/2bFaJirdgpXsM6Ux4tFyasECdxgDza7JsQDXacXggb49zGECpPRc/5ig== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add soundcard bindings for the MT8365 SoC with the MT6357 audio codec. Signed-off-by: Alexandre Mergnat --- .../bindings/sound/mediatek,mt8365-mt6357.yaml | 127 +++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml new file mode 100644 index 000000000000..f469611ec6b6 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mediatek,mt8365-mt6357.yaml @@ -0,0 +1,127 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mediatek,mt8365-mt6357.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek MT8365 sound card with MT6357 sound codec. + +maintainers: + - Alexandre Mergnat + +description: + This binding describes the MT8365 sound card. + +properties: + compatible: + const: mediatek,mt8365-mt6357 + + mediatek,hp-pull-down: + description: + Earphone driver positive output stage short to the + audio reference ground. + Default value is false. + type: boolean + + mediatek,micbias0-microvolt: + description: | + Selects MIC Bias 0 output voltage. + [1.7v, 1.8v, 1.9v, 2.0v, 2.1v, 2.5v, 2.6v, 2.7v] + enum: [0, 1, 2, 3, 4, 5, 6, 7] + + mediatek,micbias1-microvolt: + description: | + Selects MIC Bias 1 output voltage. + [1.7v, 1.8v, 1.9v, 2.0v, 2.1v, 2.5v, 2.6v, 2.7v] + enum: [0, 1, 2, 3, 4, 5, 6, 7] + + mediatek,platform: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle of MT8365 ASoC platform. + + pinctrl-names: + minItems: 1 + items: + - const: aud_default + - const: aud_dmic + - const: aud_miso_off + - const: aud_miso_on + - const: aud_mosi_off + - const: aud_mosi_on + + vaud28-supply: + description: + 2.8 volt supply for the audio codec + +patternProperties: + "^dai-link-[0-9]+$": + type: object + description: + Container for dai-link level properties and CODEC sub-nodes. + + properties: + codec: + type: object + description: Holds subnode which indicates codec dai. + + properties: + sound-dai: + maxItems: 1 + description: phandle of the codec DAI + + additionalProperties: false + + link-name: + description: + This property corresponds to the name of the BE dai-link to which + we are going to update parameters in this node. + items: + const: 2ND I2S BE + + sound-dai: + maxItems: 1 + description: phandle of the CPU DAI + + additionalProperties: false + + required: + - link-name + - sound-dai + +additionalProperties: false + +required: + - compatible + - mediatek,platform + - pinctrl-names + - vaud28-supply + +examples: + - | + sound { + compatible = "mediatek,mt8365-mt6357"; + mediatek,platform = <&afe>; + pinctrl-names = "aud_default", + "aud_dmic", + "aud_miso_off", + "aud_miso_on", + "aud_mosi_off", + "aud_mosi_on"; + pinctrl-0 = <&aud_default_pins>; + pinctrl-1 = <&aud_dmic_pins>; + pinctrl-2 = <&aud_miso_off_pins>; + pinctrl-3 = <&aud_miso_on_pins>; + pinctrl-4 = <&aud_mosi_off_pins>; + pinctrl-5 = <&aud_mosi_on_pins>; + vaud28-supply = <&mt6357_vaud28_reg>; + + /* hdmi interface */ + dai-link-0 { + sound-dai = <&afe>; + link-name = "2ND I2S BE"; + + codec { + sound-dai = <&it66121hdmitx>; + }; + }; + }; From patchwork Mon Feb 26 14:01:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776102 Received: from mail-wm1-f47.google.com (mail-wm1-f47.google.com [209.85.128.47]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 80B3E12BEA5 for ; Mon, 26 Feb 2024 14:02:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.47 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956138; cv=none; b=BuQOHGzWiQUhB60r12iLvEdG2LxKpMcWLFZGb4/nnheN5ErZvcVdGzIZk7sb/NE6g3aPit5CVlRZpH0qhoM6u//gwB8nyT2oe0/YAnBrk2XCI+gAz5hIdsUAc9Yyy0b1rr1puHCyTLAr/bdc+inq+t/Amq6XAozX4iqOPp00+Rg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956138; c=relaxed/simple; bh=Nv/SNlQULb1KRNckO+Ew2YoaagjfViQHWfHxhZF7KHA=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Vf6Qcnl6NvA7vqhvMub1cMeFk3Kw2QQXm3AjlmvBBA3IGdcoLVXTPeXzTl2JUH1AYKJzwG7pAxZceXybaT0CsGLpO0L7L6S9/czqD60PtlWuNT3VcLhIEr1wzy8o5s6/vmHTq6A/jAsB6nHNmPdx+GZAZLA58jO3NsNjOdlM+Ds= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=vLz5zFFx; arc=none smtp.client-ip=209.85.128.47 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="vLz5zFFx" Received: by mail-wm1-f47.google.com with SMTP id 5b1f17b1804b1-412949fd224so15375145e9.1 for ; Mon, 26 Feb 2024 06:02:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956134; x=1709560934; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=R+Fk5ARyfKwpPMc0wOcVSaPohn2gY9yOXX3nP3+GHb0=; b=vLz5zFFx/MDEGgi1UWiIQU+9vUJXi2kvXXrkricP7p8uq36CwiFuB6JuEMNxspEgkl 2VvnmQ7c44141jPg1nUxh8MnqdjhDEUc33uM51Qnh4bduH/dftokP+VzluywVT0TmoJ6 epQ1R4znaEYipVetVMb7w/tt7q41idjCBgxqC4VqyfncZH00uYqhgUVBPpVzQ81oqpDy kEkAjvwSlLpCBAqEz+RDuA3pll8ZEG8ccmFGoB/5sHVqpjjnZUJOnm2W5+0IdFGtYTU6 B0LTKxYsVC75LkQxAvgAYy7sokwiCynjsP4t4auh1MIvDh/Z4tbgaftqcCxRvEnIRnHG v7AA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956134; x=1709560934; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=R+Fk5ARyfKwpPMc0wOcVSaPohn2gY9yOXX3nP3+GHb0=; b=WNEWPjuY9EtQPJpeHfBYR8pgfTtzU35iFSOFHObMpgaCC3SoSpBvVJityAOwKoRJzn RZJ2iRx3432/o2P3Jc5diQJ+lGqxO+08sIqYMgEAc4ITycQDxY9d9qluRur95XqCBq69 tDt6OFgy7jhFWWShb88ND80uy60SbgRSGHkhPqNfQ0TeUDQT3U9I+P8nr0jKWxu06pR/ YnGwhbgScSXPbAAT3A3G3mpln5+iPqjIjSJWVp+uDUW3Zk2XTSi8f2DtHJRgthoBPF7S j+wYUP8i/THxkVR/nHdMuvhmSMwHNTXKzkMQk9qBbWrNK2cWuviwemJ/vTmWZvLQkrRu IzjQ== X-Forwarded-Encrypted: i=1; AJvYcCUVEPWyz6ta7uGJqOBOz8jtn5+0Tj61YvG2tPu/+F5EwnghqGZui/LrSRbIOldaiX/OaB0lOhlZWhwI5CVsduJwAjFSkJxWaa/HNog= X-Gm-Message-State: AOJu0Yz6RYy7kpC0WjefGPLwF7AxOtJw6xzgOT0hODhZ7SaQwUzPItrd tqXqB2jUOMUCfjvJ6i8WCxNU2dFYru6R8Z7YQHcc/A0ZoJcV5PC++FOWWX4L5+w= X-Google-Smtp-Source: AGHT+IFoLzWWMWwawBeOKSrUJ4JswyDMTL5FYfExtg0qw0kHlD/Q58ZbMZB9XVjOHu1k17wyEvG2lg== X-Received: by 2002:a05:600c:3584:b0:412:a0f9:391 with SMTP id p4-20020a05600c358400b00412a0f90391mr4273725wmq.2.1708956133833; Mon, 26 Feb 2024 06:02:13 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:13 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:43 +0100 Subject: [PATCH 05/18] SoC: mediatek: mt8365: support audio clock control Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-5-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=15462; i=amergnat@baylibre.com; h=from:subject:message-id; bh=Nv/SNlQULb1KRNckO+Ew2YoaagjfViQHWfHxhZF7KHA=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncRVenGxBKherRH8juHQZksGti57QrriAKPJQs EceAtmGJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURbruEA CGQv3LbJ7H8QbLt132D/0zBU/itb5aq6MedG4XI0QLdgt/jq1oYFeMnddvhRAdIHYNuuyAhZpFf6Io G/5G5RJkloyDUUsJlnf0l3a2Ia/9tIFckc/8f8R8l+FLUsNZlr7CeVVryF728BH0wW7FAGGzw5Sc8D oyFBehSGokO49ueK9ux7JY5cofZr5+LZLM8KX+Ccm6X7putxbMDK6UdaPRv3yOtJItyj2INWseiym1 l4KrF2jDVZaJ70cSliBxDYeiFv7qfReYJ2tociNJVRTkesPo/P7L9RPElC5LNbN1O3AjcAGmf4au36 xge5XtmLFgQB79j/z1sgQU8MU4Q0RTRZIKBdGtXHsIRhPw6KSsRTVl7AO7PBwGoK/Vs9ChmuwH5iil pqXv8o/KGlF1xoBBCMh6/jqo0xqHmV/lrhuRPpcod3mtJicNJfNAT+J/s9YQUfbvz8VgIySw2kmFxm Gt0lhpv1SU8ebM+QtY7qnnHeIkVV4+CNo7VHRsGiPk5+kDdL0lxgIrwPUBdE+ls7YZPi8sTAYeSjsr /OGq73de8FTrpJpIARLuUHb1fJr/wysWv9mW4wX7ma++zVB0KArx6AUgJI0PyVCHyNhZrHQJjkhqD3 oTVac7bLX3+xP1sop+RMz4jl1BK3dcxfIaBqQSS5blwuCaEEiKcQArnT7+aQ== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add audio clock wrapper and audio tuner control. Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/mt8365/mt8365-afe-clk.c | 455 +++++++++++++++++++++++++++++ sound/soc/mediatek/mt8365/mt8365-afe-clk.h | 55 ++++ 2 files changed, 510 insertions(+) diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c new file mode 100644 index 000000000000..2df781a22bf0 --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c @@ -0,0 +1,455 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek 8365 AFE clock control + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Jia Zeng + * Alexandre Mergnat + */ + +#include "mt8365-afe-clk.h" +#include "mt8365-afe-common.h" +#include "mt8365-reg.h" +#include "../common/mtk-base-afe.h" +#include +#include + +static const char *aud_clks[MT8365_CLK_NUM] = { + [MT8365_CLK_TOP_AUD_SEL] = "top_audio_sel", + [MT8365_CLK_AUD_I2S0_M] = "audio_i2s0_m", + [MT8365_CLK_AUD_I2S1_M] = "audio_i2s1_m", + [MT8365_CLK_AUD_I2S2_M] = "audio_i2s2_m", + [MT8365_CLK_AUD_I2S3_M] = "audio_i2s3_m", + [MT8365_CLK_ENGEN1] = "engen1", + [MT8365_CLK_ENGEN2] = "engen2", + [MT8365_CLK_AUD1] = "aud1", + [MT8365_CLK_AUD2] = "aud2", + [MT8365_CLK_I2S0_M_SEL] = "i2s0_m_sel", + [MT8365_CLK_I2S1_M_SEL] = "i2s1_m_sel", + [MT8365_CLK_I2S2_M_SEL] = "i2s2_m_sel", + [MT8365_CLK_I2S3_M_SEL] = "i2s3_m_sel", + [MT8365_CLK_CLK26M] = "top_clk26m_clk", +}; + +int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe) +{ + size_t i; + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + for (i = 0; i < ARRAY_SIZE(aud_clks); i++) { + afe_priv->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]); + if (IS_ERR(afe_priv->clocks[i])) { + dev_err(afe->dev, "%s devm_clk_get %s fail\n", + __func__, aud_clks[i]); + return PTR_ERR(afe_priv->clocks[i]); + } + } + return 0; + + afe_priv->topckgen = syscon_regmap_lookup_by_phandle(afe->dev->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); + } +} + +int mt8365_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + int ret; + + if (clk) { + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(afe->dev, "Failed to enable clk\n"); + return ret; + } + } + return 0; +} + +void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk) +{ + if (clk) + clk_disable_unprepare(clk); +} + +int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, + unsigned int rate) +{ + int ret; + + if (clk) { + ret = clk_set_rate(clk, rate); + if (ret) { + dev_err(afe->dev, "Failed to set rate\n"); + return ret; + } + } + return 0; +} + +int mt8365_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, + struct clk *parent) +{ + int ret; + + if (clk && parent) { + ret = clk_set_parent(clk, parent); + if (ret) { + dev_err(afe->dev, "Failed to set parent\n"); + return ret; + } + } + return 0; +} + +static unsigned int get_top_cg_reg(unsigned int cg_type) +{ + switch (cg_type) { + case MT8365_TOP_CG_AFE: + case MT8365_TOP_CG_I2S_IN: + case MT8365_TOP_CG_22M: + case MT8365_TOP_CG_24M: + case MT8365_TOP_CG_INTDIR_CK: + case MT8365_TOP_CG_APLL2_TUNER: + case MT8365_TOP_CG_APLL_TUNER: + case MT8365_TOP_CG_SPDIF: + case MT8365_TOP_CG_TDM_OUT: + case MT8365_TOP_CG_TDM_IN: + case MT8365_TOP_CG_ADC: + case MT8365_TOP_CG_DAC: + case MT8365_TOP_CG_DAC_PREDIS: + case MT8365_TOP_CG_TML: + return AUDIO_TOP_CON0; + case MT8365_TOP_CG_I2S1_BCLK: + case MT8365_TOP_CG_I2S2_BCLK: + case MT8365_TOP_CG_I2S3_BCLK: + case MT8365_TOP_CG_I2S4_BCLK: + case MT8365_TOP_CG_DMIC0_ADC: + case MT8365_TOP_CG_DMIC1_ADC: + case MT8365_TOP_CG_DMIC2_ADC: + case MT8365_TOP_CG_DMIC3_ADC: + case MT8365_TOP_CG_CONNSYS_I2S_ASRC: + case MT8365_TOP_CG_GENERAL1_ASRC: + case MT8365_TOP_CG_GENERAL2_ASRC: + case MT8365_TOP_CG_TDM_ASRC: + return AUDIO_TOP_CON1; + default: + return 0; + } +} + +static unsigned int get_top_cg_mask(unsigned int cg_type) +{ + switch (cg_type) { + case MT8365_TOP_CG_AFE: + return AUD_TCON0_PDN_AFE; + case MT8365_TOP_CG_I2S_IN: + return AUD_TCON0_PDN_I2S_IN; + case MT8365_TOP_CG_22M: + return AUD_TCON0_PDN_22M; + case MT8365_TOP_CG_24M: + return AUD_TCON0_PDN_24M; + case MT8365_TOP_CG_INTDIR_CK: + return AUD_TCON0_PDN_INTDIR; + case MT8365_TOP_CG_APLL2_TUNER: + return AUD_TCON0_PDN_APLL2_TUNER; + case MT8365_TOP_CG_APLL_TUNER: + return AUD_TCON0_PDN_APLL_TUNER; + case MT8365_TOP_CG_SPDIF: + return AUD_TCON0_PDN_SPDIF; + case MT8365_TOP_CG_TDM_OUT: + return AUD_TCON0_PDN_TDM_OUT; + case MT8365_TOP_CG_TDM_IN: + return AUD_TCON0_PDN_TDM_IN; + case MT8365_TOP_CG_ADC: + return AUD_TCON0_PDN_ADC; + case MT8365_TOP_CG_DAC: + return AUD_TCON0_PDN_DAC; + case MT8365_TOP_CG_DAC_PREDIS: + return AUD_TCON0_PDN_DAC_PREDIS; + case MT8365_TOP_CG_TML: + return AUD_TCON0_PDN_TML; + case MT8365_TOP_CG_I2S1_BCLK: + return AUD_TCON1_PDN_I2S1_BCLK; + case MT8365_TOP_CG_I2S2_BCLK: + return AUD_TCON1_PDN_I2S2_BCLK; + case MT8365_TOP_CG_I2S3_BCLK: + return AUD_TCON1_PDN_I2S3_BCLK; + case MT8365_TOP_CG_I2S4_BCLK: + return AUD_TCON1_PDN_I2S4_BCLK; + case MT8365_TOP_CG_DMIC0_ADC: + return AUD_TCON1_PDN_DMIC0_ADC; + case MT8365_TOP_CG_DMIC1_ADC: + return AUD_TCON1_PDN_DMIC1_ADC; + case MT8365_TOP_CG_DMIC2_ADC: + return AUD_TCON1_PDN_DMIC2_ADC; + case MT8365_TOP_CG_DMIC3_ADC: + return AUD_TCON1_PDN_DMIC3_ADC; + case MT8365_TOP_CG_CONNSYS_I2S_ASRC: + return AUD_TCON1_PDN_CONNSYS_I2S_ASRC; + case MT8365_TOP_CG_GENERAL1_ASRC: + return AUD_TCON1_PDN_GENERAL1_ASRC; + case MT8365_TOP_CG_GENERAL2_ASRC: + return AUD_TCON1_PDN_GENERAL2_ASRC; + case MT8365_TOP_CG_TDM_ASRC: + return AUD_TCON1_PDN_TDM_ASRC; + default: + return 0; + } +} + +static unsigned int get_top_cg_on_val(unsigned int cg_type) +{ + return 0; +} + +static unsigned int get_top_cg_off_val(unsigned int cg_type) +{ + return get_top_cg_mask(cg_type); +} + +int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_on_val(cg_type); + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + + afe_priv->top_cg_ref_cnt[cg_type]++; + if (afe_priv->top_cg_ref_cnt[cg_type] == 1) + regmap_update_bits(afe->regmap, reg, mask, val); + + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + + return 0; +} + +int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + unsigned int reg = get_top_cg_reg(cg_type); + unsigned int mask = get_top_cg_mask(cg_type); + unsigned int val = get_top_cg_off_val(cg_type); + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + + afe_priv->top_cg_ref_cnt[cg_type]--; + if (afe_priv->top_cg_ref_cnt[cg_type] == 0) + regmap_update_bits(afe->regmap, reg, mask, val); + else if (afe_priv->top_cg_ref_cnt[cg_type] < 0) + afe_priv->top_cg_ref_cnt[cg_type] = 0; + + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + + return 0; +} + +int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + mt8365_afe_enable_clk(afe, afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]); + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE); + mt8365_afe_enable_afe_on(afe); + + return 0; +} + +int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + mt8365_afe_disable_afe_on(afe); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE); + mt8365_afe_disable_clk(afe, afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL]); + + return 0; +} + +int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe) +{ + return 0; +} + +int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe) +{ + return 0; +} + +int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + + afe_priv->afe_on_ref_cnt++; + if (afe_priv->afe_on_ref_cnt == 1) + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1); + + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + + return 0; +} + +int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + unsigned long flags; + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + + afe_priv->afe_on_ref_cnt--; + if (afe_priv->afe_on_ref_cnt == 0) + regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x0); + else if (afe_priv->afe_on_ref_cnt < 0) + afe_priv->afe_on_ref_cnt = 0; + + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); + + return 0; +} + +int mt8365_afe_hd_engen_enable(struct mtk_base_afe *afe, bool apll1) +{ + if (apll1) + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_PLL_EN, AFE_22M_PLL_EN); + else + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_PLL_EN, AFE_24M_PLL_EN); + + return 0; +} + +int mt8365_afe_hd_engen_disable(struct mtk_base_afe *afe, bool apll1) +{ + if (apll1) + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_22M_PLL_EN, ~AFE_22M_PLL_EN); + else + regmap_update_bits(afe->regmap, AFE_HD_ENGEN_ENABLE, + AFE_24M_PLL_EN, ~AFE_24M_PLL_EN); + + return 0; +} + +int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, + unsigned int apll) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + mutex_lock(&afe_priv->afe_clk_mutex); + + afe_priv->apll_tuner_ref_cnt[apll]++; + if (afe_priv->apll_tuner_ref_cnt[apll] != 1) { + mutex_unlock(&afe_priv->afe_clk_mutex); + return 0; + } + + if (apll == MT8365_AFE_APLL1) { + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG, + AFE_APLL_TUNER_CFG_MASK, 0x432); + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG, + AFE_APLL_TUNER_CFG_EN_MASK, 0x1); + } else { + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1, + AFE_APLL_TUNER_CFG1_MASK, 0x434); + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1, + AFE_APLL_TUNER_CFG1_EN_MASK, 0x1); + } + + mutex_unlock(&afe_priv->afe_clk_mutex); + return 0; +} + +int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, + unsigned int apll) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + mutex_lock(&afe_priv->afe_clk_mutex); + + afe_priv->apll_tuner_ref_cnt[apll]--; + if (afe_priv->apll_tuner_ref_cnt[apll] == 0) { + if (apll == MT8365_AFE_APLL1) + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG, + AFE_APLL_TUNER_CFG_EN_MASK, 0x0); + else + regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG1, + AFE_APLL_TUNER_CFG1_EN_MASK, 0x0); + + } else if (afe_priv->apll_tuner_ref_cnt[apll] < 0) { + afe_priv->apll_tuner_ref_cnt[apll] = 0; + } + + mutex_unlock(&afe_priv->afe_clk_mutex); + return 0; +} + +int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, + unsigned int apll) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + if (apll == MT8365_AFE_APLL1) { + if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN1])) { + dev_info(afe->dev, "%s Failed to enable ENGEN1 clk\n", + __func__); + return 0; + } + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_22M); + mt8365_afe_hd_engen_enable(afe, true); +#ifdef ENABLE_AFE_APLL_TUNER + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER); + mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL1); +#endif + } else { + if (clk_prepare_enable(afe_priv->clocks[MT8365_CLK_ENGEN2])) { + dev_info(afe->dev, "%s Failed to enable ENGEN2 clk\n", + __func__); + return 0; + } + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_24M); + mt8365_afe_hd_engen_enable(afe, false); +#ifdef ENABLE_AFE_APLL_TUNER + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER); + mt8365_afe_enable_apll_tuner_cfg(afe, MT8365_AFE_APLL2); +#endif + } + + return 0; +} + +int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, + unsigned int apll) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + if (apll == MT8365_AFE_APLL1) { +#ifdef ENABLE_AFE_APLL_TUNER + mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL1); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL_TUNER); +#endif + mt8365_afe_hd_engen_disable(afe, true); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_22M); + clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN1]); + } else { +#ifdef ENABLE_AFE_APLL_TUNER + mt8365_afe_disable_apll_tuner_cfg(afe, MT8365_AFE_APLL2); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_APLL2_TUNER); +#endif + mt8365_afe_hd_engen_disable(afe, false); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_24M); + clk_disable_unprepare(afe_priv->clocks[MT8365_CLK_ENGEN2]); + } + + return 0; +} diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.h b/sound/soc/mediatek/mt8365/mt8365-afe-clk.h new file mode 100644 index 000000000000..89377464c2b5 --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Mediatek 8365 AFE clock control definitions + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Jia Zeng + * Alexandre Mergnat + */ + +#ifndef _MT8365_AFE_UTILS_H_ +#define _MT8365_AFE_UTILS_H_ + +struct mtk_base_afe; +struct clk; + +int mt8365_afe_init_audio_clk(struct mtk_base_afe *afe); + +int mt8365_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk); + +void mt8365_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk); + +int mt8365_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk, + unsigned int rate); + +int mt8365_afe_set_clk_parent(struct mtk_base_afe *afe, struct clk *clk, + struct clk *parent); + +int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type); + +int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type); + +int mt8365_afe_enable_main_clk(struct mtk_base_afe *afe); + +int mt8365_afe_disable_main_clk(struct mtk_base_afe *afe); + +int mt8365_afe_emi_clk_on(struct mtk_base_afe *afe); + +int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe); + +int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe); + +int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe); + +int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, + unsigned int apll); + +int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, + unsigned int apll); + +int mt8365_afe_enable_apll_associated_cfg(struct mtk_base_afe *afe, + unsigned int apll); + +int mt8365_afe_disable_apll_associated_cfg(struct mtk_base_afe *afe, + unsigned int apll); +#endif From patchwork Mon Feb 26 14:01:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776101 Received: from mail-lf1-f53.google.com (mail-lf1-f53.google.com [209.85.167.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D465F12BF19 for ; Mon, 26 Feb 2024 14:02:17 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956142; cv=none; b=nhDzIEdJhjbzVN8jtHr4MrR/fEGIyv4HKObPmVTWNUnzokEYsnEQTlVkZloegmCQYp173JNb9ZWA+nCJFskVZ433kn6lMUL4hw20V179+KjMz3q/ts8Nh2n4sY1uxzZo7s+SAoSu/MJ0OAOg7FXP2wtf1mLH1K03S3JuNIEg3KE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956142; c=relaxed/simple; bh=OW3LG3VxX57dLshaBcXcYIEO0k2g7jycb4s6LabjFk8=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N7QeNMdPG0zO5dINNlY8yVAryG6mXbniCxV6vrDTbDP1eDIc54txU66WPJBaCkN/eSxQttS00Y9qQGsa952gT8vn7GjB5l6F8N8J+8FrzSYydXcIONxJNpk+wbfwgochYW/PylRFtuF3tQLgOP37yndIrztODPAbyNkGIHwShH0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=D60K98WN; arc=none smtp.client-ip=209.85.167.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="D60K98WN" Received: by mail-lf1-f53.google.com with SMTP id 2adb3069b0e04-512ed314881so2884049e87.2 for ; Mon, 26 Feb 2024 06:02:17 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956136; x=1709560936; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=H5MtUL1IabuadPQ+i4gp25hXm9l+Ixi169pISzOeLTg=; b=D60K98WN5VlTjEOfn9rzrxv9J/5DVhIdKV47O+7bEXnAHWJCKWW07XOsZXJjD8CAM1 JFRSPPhlHLJLA8LI+UOIsjo7XJEhyO8TSYOEu146yhU0gal0YXm+CJLEzP43JE8b4mI6 XTT8ZW25ueGQoPOLcUdzT2J2Chh9WrukTwSinxebjqDl/b11S4ibUAxIGCIRV8ssSwqo vtPgIB8+5WpHJc8QUeApZ9G8NO8GEAuTELy9iiEa4AtBTYuBN9ZhtIs6MAvCje6RttSt udYGUxx7bPOZCkAduR0hSV4a31ukAEdZCckQSBUZbDendcLTZ/ex9koeYsap6bdLgMXe Q1aA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956136; x=1709560936; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=H5MtUL1IabuadPQ+i4gp25hXm9l+Ixi169pISzOeLTg=; b=BloNFPnPkclXIi/xOpIagKpOaZ+4DvnbuKy2sqOKcL4PVdyacGt9yvzi0rya2zkSq5 ojR9OEMDUxUKRN5yjbbVxk7m5KMegqWn+uGZ9VjMNrNb79iJCDGPCxyvFiYqVKAI9pgD +58NuMvlTHymRdh9mad1HfN+cRexWoFub6Foo51v+RodSjGJXnVgHLQjJSB9EQPV93jp 6Q8GKhP0uDanyAIu6DMhzj+KFFmLbQXzsi8ef9fSsSpxtTAYr3nKgOs0pZ5uArKbV1m3 jp6iqppQszgjdfimiHrpyRZvRqIRfpM+cSSDrUjY2tcw6XyMBSmG/Moblj5nWqVWCSWR ddfA== X-Forwarded-Encrypted: i=1; AJvYcCV01i7hkYt+V4KjfVDScnG0dkWq96+uPT4QNmPAqvpNgvoygocEH+ayzgfkl1X9vF8LfCgyurkoVu8T9IM+vZDugfZY3lRQPKoHc8I= X-Gm-Message-State: AOJu0Yz1D99mET3GOxI5dCwj1tD2oUkJmchovjn0N1JQSfyVvnvlpBln qYjfwiG4PpUH/HkmypDEMqHzipWRR4qNqN/a39AiJ5D9uIHNyH4aEyLnIANe8Z0= X-Google-Smtp-Source: AGHT+IFlW3G64wf7NuW2/owU8CEOGn8aLNQE8HkSUSVugItFkWe2FGhb/Sv9IvRVsGRugIOPZuvAmQ== X-Received: by 2002:a05:6512:3692:b0:512:f84b:b4f2 with SMTP id d18-20020a056512369200b00512f84bb4f2mr2108587lfs.52.1708956135099; Mon, 26 Feb 2024 06:02:15 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:14 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:44 +0100 Subject: [PATCH 06/18] ASoC: mediatek: mt8365: Add I2S DAI support Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-6-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=28849; i=amergnat@baylibre.com; h=from:subject:message-id; bh=OW3LG3VxX57dLshaBcXcYIEO0k2g7jycb4s6LabjFk8=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3Jnc1lr3pJ/6Kv8d0qD54Bu2VtssBU6fZeaZCzK4 zu/ti96JAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURfO/D/ 9qEvxq/DBz1sdfkvd6JlGFkCXUy4wEHOwyuitM3cr5Xap8hZprcO/+asD64OLkS4onnrgc5Ue2zzJp 4u0M2wHhKdbD4MNWl6yhLby9C/M1ppjkhvf6NT5I//aq3E21Mdsam0nkHyzADRe+qOJpQcjDitMjA7 BhJb2UvciZAuHTeFDcaKAKm3MxFBuANRb+uReEenxwccv07T5idQv4qdqqaUb2ghBiIkaHfeIOJ3Fa eSXgOWa9rlk1HHEvvLMCVNkXNENsQuXJfh/oSxy1XecFIQcEt2/MZB3z90xE+PaXQibebYSWmPDi/5 h3giyj/Vl/iyiv0/TZ4x9oZfYpnP8iE+BkP+kwyYTQw0Y5HZocXeusIM/f6N6RjOeylGaWSlAAXlxh no3NEzJUydOBh7gTsu+BU9dyN2dIx6frVPDnNGvsM9Z3rHx7pSIoY+1A5+OWbMWEAtKDboI16efa7D NGV4RMUb5vuntde/9+uGP4Ew3MAc+GkNJ2JSWT44P4xxY3sW/3NWAJn2ALHLSmjrG6peF8wi58fEQ9 E32CHwuPQCvLN8DqV0FGtP5hgkU2z/Gsvx+7FTQmBbg7hTLgx88onqvRFOohRdeTxEGguHryfYr/Qg aPJGnHJTVJsQHqtYEoCJ0fdws1+OrgpQkVAFCIrSBEihHdiLDKFTk3qBgKyA== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add I2S Device Audio Interface support for MT8365 SoC. Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/mt8365/mt8365-dai-i2s.c | 901 +++++++++++++++++++++++++++++ 1 file changed, 901 insertions(+) diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c new file mode 100644 index 000000000000..ba704d92094b --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c @@ -0,0 +1,901 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek 8365 ALSA SoC Audio DAI I2S Control + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Jia Zeng + * Alexandre Mergnat + */ + +#include +#include +#include +#include "mt8365-afe-clk.h" +#include "mt8365-afe-common.h" + +struct mtk_afe_i2s_priv { + bool adda_link; + bool shared_clk; + int i2s_out_on_ref_cnt; + int id; + int low_jitter_en; + int mclk_id; + int share_i2s_id; + unsigned int clk_id_in; + unsigned int clk_id_in_m_sel; + unsigned int clk_id_out; + unsigned int clk_id_out_m_sel; + unsigned int clk_in_mult; + unsigned int clk_out_mult; + unsigned int config_val_in; + unsigned int config_val_out; + unsigned int dynamic_bck; + unsigned int reg_off_in; + unsigned int reg_off_out; +}; + +/* This enum is merely for mtk_afe_i2s_priv declare */ +enum { + DAI_I2S0 = 0, + DAI_I2S3, + DAI_I2S_NUM, +}; + +static const struct mtk_afe_i2s_priv mt8365_i2s_priv[DAI_I2S_NUM] = { + [DAI_I2S0] = { + .id = MT8365_AFE_IO_I2S, + .mclk_id = MT8365_I2S0_MCK, + .share_i2s_id = -1, + .clk_id_in = MT8365_CLK_AUD_I2S2_M, + .clk_id_out = MT8365_CLK_AUD_I2S1_M, + .clk_id_in_m_sel = MT8365_CLK_I2S2_M_SEL, + .clk_id_out_m_sel = MT8365_CLK_I2S1_M_SEL, + .clk_in_mult = 256, + .clk_out_mult = 256, + .adda_link = true, + .config_val_out = AFE_I2S_CON1_I2S2_TO_PAD, + .reg_off_in = AFE_I2S_CON2, + .reg_off_out = AFE_I2S_CON1, + }, + [DAI_I2S3] = { + .id = MT8365_AFE_IO_2ND_I2S, + .mclk_id = MT8365_I2S3_MCK, + .share_i2s_id = -1, + .clk_id_in = MT8365_CLK_AUD_I2S0_M, + .clk_id_out = MT8365_CLK_AUD_I2S3_M, + .clk_id_in_m_sel = MT8365_CLK_I2S0_M_SEL, + .clk_id_out_m_sel = MT8365_CLK_I2S3_M_SEL, + .clk_in_mult = 256, + .clk_out_mult = 256, + .adda_link = false, + .config_val_in = AFE_I2S_CON_FROM_IO_MUX, + .reg_off_in = AFE_I2S_CON, + .reg_off_out = AFE_I2S_CON3, + }, +}; + +static const u32 *get_iir_coef(unsigned int input_fs, + unsigned int output_fs, unsigned int *count) +{ +#define RATIOVER 9 +#define INV_COEF 10 +#define NO_NEED 11 + + static const u32 IIR_COEF_48_TO_44p1[30] = { + 0x061fb0, 0x0bd256, 0x061fb0, 0xe3a3e6, 0xf0a300, 0x000003, + 0x0e416d, 0x1bb577, 0x0e416d, 0xe59178, 0xf23637, 0x000003, + 0x0c7d72, 0x189060, 0x0c7d72, 0xe96f09, 0xf505b2, 0x000003, + 0x126054, 0x249143, 0x126054, 0xe1fc0c, 0xf4b20a, 0x000002, + 0x000000, 0x323c85, 0x323c85, 0xf76d4e, 0x000000, 0x000002, + }; + + static const u32 IIR_COEF_44p1_TO_32[42] = { + 0x0a6074, 0x0d237a, 0x0a6074, 0xdd8d6c, 0xe0b3f6, 0x000002, + 0x0e41f8, 0x128d48, 0x0e41f8, 0xefc14e, 0xf12d7a, 0x000003, + 0x0cfa60, 0x11e89c, 0x0cfa60, 0xf1b09e, 0xf27205, 0x000003, + 0x15b69c, 0x20e7e4, 0x15b69c, 0xea799a, 0xe9314a, 0x000002, + 0x0f79e2, 0x1a7064, 0x0f79e2, 0xf65e4a, 0xf03d8e, 0x000002, + 0x10c34f, 0x1ffe4b, 0x10c34f, 0x0bbecb, 0xf2bc4b, 0x000001, + 0x000000, 0x23b063, 0x23b063, 0x07335f, 0x000000, 0x000002, + }; + + static const u32 IIR_COEF_48_TO_32[42] = { + 0x0a2a9b, 0x0a2f05, 0x0a2a9b, 0xe73873, 0xe0c525, 0x000002, + 0x0dd4ad, 0x0e765a, 0x0dd4ad, 0xf49808, 0xf14844, 0x000003, + 0x18a8cd, 0x1c40d0, 0x18a8cd, 0xed2aab, 0xe542ec, 0x000002, + 0x13e044, 0x1a47c4, 0x13e044, 0xf44aed, 0xe9acc7, 0x000002, + 0x1abd9c, 0x2a5429, 0x1abd9c, 0xff3441, 0xe0fc5f, 0x000001, + 0x0d86db, 0x193e2e, 0x0d86db, 0x1a6f15, 0xf14507, 0x000001, + 0x000000, 0x1f820c, 0x1f820c, 0x0a1b1f, 0x000000, 0x000002, + }; + + static const u32 IIR_COEF_32_TO_16[48] = { + 0x122893, 0xffadd4, 0x122893, 0x0bc205, 0xc0ee1c, 0x000001, + 0x1bab8a, 0x00750d, 0x1bab8a, 0x06a983, 0xe18a5c, 0x000002, + 0x18f68e, 0x02706f, 0x18f68e, 0x0886a9, 0xe31bcb, 0x000002, + 0x149c05, 0x054487, 0x149c05, 0x0bec31, 0xe5973e, 0x000002, + 0x0ea303, 0x07f24a, 0x0ea303, 0x115ff9, 0xe967b6, 0x000002, + 0x0823fd, 0x085531, 0x0823fd, 0x18d5b4, 0xee8d21, 0x000002, + 0x06888e, 0x0acbbb, 0x06888e, 0x40b55c, 0xe76dce, 0x000001, + 0x000000, 0x2d31a9, 0x2d31a9, 0x23ba4f, 0x000000, 0x000001, + }; + + static const u32 IIR_COEF_96_TO_44p1[48] = { + 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 const u32 IIR_COEF_44p1_TO_16[48] = { + 0x0998fb, 0xf7f925, 0x0998fb, 0x1e54a0, 0xe06605, 0x000002, + 0x0d828e, 0xf50f97, 0x0d828e, 0x0f41b5, 0xf0a999, 0x000003, + 0x17ebeb, 0xee30d8, 0x17ebeb, 0x1f48ca, 0xe2ae88, 0x000002, + 0x12fab5, 0xf46ddc, 0x12fab5, 0x20cc51, 0xe4d068, 0x000002, + 0x0c7ac6, 0xfbd00e, 0x0c7ac6, 0x2337da, 0xe8028c, 0x000002, + 0x060ddc, 0x015b3e, 0x060ddc, 0x266754, 0xec21b6, 0x000002, + 0x0407b5, 0x04f827, 0x0407b5, 0x52e3d0, 0xe0149f, 0x000001, + 0x000000, 0x1f9521, 0x1f9521, 0x2ac116, 0x000000, 0x000001, + }; + + static const u32 IIR_COEF_48_TO_16[48] = { + 0x0955ff, 0xf6544a, 0x0955ff, 0x2474e5, 0xe062e6, 0x000002, + 0x0d4180, 0xf297f4, 0x0d4180, 0x12415b, 0xf0a3b0, 0x000003, + 0x0ba079, 0xf4f0b0, 0x0ba079, 0x1285d3, 0xf1488b, 0x000003, + 0x12247c, 0xf1033c, 0x12247c, 0x2625be, 0xe48e0d, 0x000002, + 0x0b98e0, 0xf96d1a, 0x0b98e0, 0x27e79c, 0xe7798a, 0x000002, + 0x055e3b, 0xffed09, 0x055e3b, 0x2a2e2d, 0xeb2854, 0x000002, + 0x01a934, 0x01ca03, 0x01a934, 0x2c4fea, 0xee93ab, 0x000002, + 0x000000, 0x1c46c5, 0x1c46c5, 0x2d37dc, 0x000000, 0x000001, + }; + + static const u32 IIR_COEF_96_TO_16[48] = { + 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 struct { + const u32 *coef; + unsigned int cnt; + } iir_coef_tbl_list[8] = { + /* 0: 0.9188 */ + { IIR_COEF_48_TO_44p1, ARRAY_SIZE(IIR_COEF_48_TO_44p1) }, + /* 1: 0.7256 */ + { IIR_COEF_44p1_TO_32, ARRAY_SIZE(IIR_COEF_44p1_TO_32) }, + /* 2: 0.6667 */ + { IIR_COEF_48_TO_32, ARRAY_SIZE(IIR_COEF_48_TO_32) }, + /* 3: 0.5 */ + { IIR_COEF_32_TO_16, ARRAY_SIZE(IIR_COEF_32_TO_16) }, + /* 4: 0.4594 */ + { IIR_COEF_96_TO_44p1, ARRAY_SIZE(IIR_COEF_96_TO_44p1) }, + /* 5: 0.3628 */ + { IIR_COEF_44p1_TO_16, ARRAY_SIZE(IIR_COEF_44p1_TO_16) }, + /* 6: 0.3333 */ + { IIR_COEF_48_TO_16, ARRAY_SIZE(IIR_COEF_48_TO_16) }, + /* 7: 0.1667 */ + { IIR_COEF_96_TO_16, ARRAY_SIZE(IIR_COEF_96_TO_16) }, + }; + + static const u32 freq_new_index[16] = { + 0, 1, 2, 99, 3, 4, 5, 99, 6, 7, 8, 9, 10, 11, 12, 99 + }; + + static const u32 iir_coef_tbl_matrix[13][13] = { + {/*0*/ + NO_NEED, NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED + }, + {/*1*/ + 1, NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*2*/ + 2, 0, NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED + }, + {/*3*/ + 3, INV_COEF, INV_COEF, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*4*/ + 5, 3, INV_COEF, 2, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*5*/ + 6, 4, 3, 2, 0, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED + }, + {/*6*/ + INV_COEF, INV_COEF, INV_COEF, 3, INV_COEF, + INV_COEF, NO_NEED, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED + }, + {/*7*/ + INV_COEF, INV_COEF, INV_COEF, 5, 3, + INV_COEF, 1, NO_NEED, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*8*/ + 7, INV_COEF, INV_COEF, 6, 4, 3, 2, 0, NO_NEED, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*9*/ + INV_COEF, INV_COEF, INV_COEF, INV_COEF, + INV_COEF, INV_COEF, 5, 3, INV_COEF, + NO_NEED, NO_NEED, NO_NEED, NO_NEED + }, + {/*10*/ + INV_COEF, INV_COEF, INV_COEF, 7, INV_COEF, + INV_COEF, 6, 4, 3, 0, + NO_NEED, NO_NEED, NO_NEED + }, + { /*11*/ + RATIOVER, INV_COEF, INV_COEF, INV_COEF, + INV_COEF, INV_COEF, INV_COEF, INV_COEF, + INV_COEF, 3, INV_COEF, NO_NEED, NO_NEED + }, + {/*12*/ + RATIOVER, RATIOVER, INV_COEF, INV_COEF, + INV_COEF, INV_COEF, 7, INV_COEF, + INV_COEF, 4, 3, 0, NO_NEED + }, + }; + + const u32 *coef = NULL; + unsigned int cnt = 0; + u32 i = freq_new_index[input_fs]; + u32 j = freq_new_index[output_fs]; + + if (i >= 13 || j >= 13) { + } else { + u32 k = iir_coef_tbl_matrix[i][j]; + + if (k >= NO_NEED) { + } else if (k == RATIOVER) { + } else if (k == INV_COEF) { + } else { + coef = iir_coef_tbl_list[k].coef; + cnt = iir_coef_tbl_list[k].cnt; + } + } + *count = cnt; + return coef; +} + +int mt8365_dai_set_config(struct mtk_base_afe *afe, + struct mtk_afe_i2s_priv *i2s_data, bool is_input, + unsigned int rate, int bit_width) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[i2s_data->id - MT8365_AFE_BACKEND_BASE]; + unsigned int val, reg_off; + int fs = mt8365_afe_fs_timing(rate); + + if (fs < 0) + return -EINVAL; + + val = AFE_I2S_CON_LOW_JITTER_CLK | + FIELD_PREP(AFE_I2S_CON_RATE_MASK, fs) | + AFE_I2S_CON_FORMAT_I2S; + + if (is_input) { + reg_off = i2s_data->reg_off_in; + if (i2s_data->adda_link) + val |= i2s_data->config_val_in; + } else { + reg_off = i2s_data->reg_off_out; + val |= i2s_data->config_val_in; + } + + /* 1:bck=32lrck(16bit) or bck=64lrck(32bit) 0:fix bck=64lrck */ + if (i2s_data->dynamic_bck) { + if (bit_width > 16) + val |= AFE_I2S_CON_WLEN_32BIT; + else + val &= ~(u32)AFE_I2S_CON_WLEN_32BIT; + } else + val |= AFE_I2S_CON_WLEN_32BIT; + + if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) + == SND_SOC_DAIFMT_CBM_CFM) { + val |= AFE_I2S_CON_SRC_SLAVE; + val &= ~(u32)AFE_I2S_CON_FROM_IO_MUX;//from consys + } + + regmap_update_bits(afe->regmap, reg_off, + ~(u32)AFE_I2S_CON_EN, val); + + if (i2s_data->adda_link && is_input) + regmap_update_bits(afe->regmap, AFE_ADDA_TOP_CON0, 0x1, 0x1); + + return 0; +} + +int mt8365_afe_set_i2s_out(struct mtk_base_afe *afe, unsigned int rate, + int bit_width) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data = + afe_priv->dai_priv[MT8365_AFE_IO_I2S]; + + return mt8365_dai_set_config(afe, i2s_data, false, rate, bit_width); +} + +static int mt8365_afe_set_2nd_i2s_asrc(struct mtk_base_afe *afe, + unsigned int rate_in, + unsigned int rate_out, unsigned int width, + unsigned int mono, int o16bit, int tracking) +{ + int ifs, ofs = 0; + unsigned int val = 0; + unsigned int mask = 0; + const u32 *coef; + u32 iir_stage; + unsigned int coef_count = 0; + + ifs = mt8365_afe_fs_timing(rate_in); + + if (ifs < 0) + return -EINVAL; + + ofs = mt8365_afe_fs_timing(rate_out); + + if (ofs < 0) + return -EINVAL; + + val = FIELD_PREP(O16BIT, o16bit) | FIELD_PREP(IS_MONO, mono); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2, + O16BIT | IS_MONO, val); + + coef = get_iir_coef(ifs, ofs, &coef_count); + iir_stage = ((u32)coef_count / 6) - 1; + + if (coef) { + unsigned int i; + + /* CPU control IIR coeff SRAM */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + COEFF_SRAM_CTRL, COEFF_SRAM_CTRL); + + /* set to 0, IIR coeff SRAM addr */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON13, + 0xffffffff, 0x0); + + for (i = 0; i < coef_count; ++i) + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON12, + 0xffffffff, coef[i]); + + /* disable IIR coeff SRAM access */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + COEFF_SRAM_CTRL, ~COEFF_SRAM_CTRL); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2, + CLR_IIR_HISTORY | IIR_EN | IIR_STAGE_MASK, + CLR_IIR_HISTORY | IIR_EN | FIELD_PREP(IIR_STAGE_MASK, iir_stage)); + } else { + /* disable IIR */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON2, IIR_EN, ~IIR_EN); + } + + /* CON3 setting (RX OFS) */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON3, + 0x00FFFFFF, rx_frequency_palette(ofs)); + /* CON4 setting (RX IFS) */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON4, + 0x00FFFFFF, rx_frequency_palette(ifs)); + + /* CON5 setting */ + if (tracking) { + val = CALI_64_CYCLE | + CALI_AUTORST | + AUTO_TUNE_FREQ5 | + COMP_FREQ_RES | + CALI_BP_DGL | + CALI_AUTO_RESTART | + CALI_USE_FREQ_OUT | + CALI_SEL_01; + + mask = CALI_CYCLE_MASK | + CALI_AUTORST | + AUTO_TUNE_FREQ5 | + COMP_FREQ_RES | + CALI_SEL_MASK | + CALI_BP_DGL | + AUTO_TUNE_FREQ4 | + CALI_AUTO_RESTART | + CALI_USE_FREQ_OUT| + CALI_ON; + + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5, + mask, val); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5, + CALI_ON, CALI_ON); + } else { + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON5, + 0xffffffff, 0x0); + } + /* CON6 setting fix 8125 */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON6, + 0x0000ffff, 0x1FBD); + /* CON9 setting (RX IFS) */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON9, + 0x000fffff, AutoRstThHi(ifs)); + /* CON10 setting (RX IFS) */ + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON10, + 0x000fffff, AutoRstThLo(ifs)); + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + CHSET_STR_CLR, CHSET_STR_CLR); + + return 0; +} + +static int mt8365_afe_set_2nd_i2s_asrc_enable( + struct mtk_base_afe *afe, bool enable) +{ + if (enable) + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + ASM_ON, ASM_ON); + else + regmap_update_bits(afe->regmap, AFE_ASRC_2CH_CON0, + ASM_ON, ~ASM_ON); + + return 0; +} + +void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable) +{ + int i; + unsigned long flags; + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data; + + for (i = 0; i < DAI_I2S_NUM; i++) { + if (mt8365_i2s_priv[i].adda_link) + i2s_data = afe_priv->dai_priv[mt8365_i2s_priv[i].id]; + } + + spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags); + + if (enable) { + i2s_data->i2s_out_on_ref_cnt++; + if (i2s_data->i2s_out_on_ref_cnt == 1) + regmap_update_bits(afe->regmap, + AFE_I2S_CON1, 0x1, enable); + } else { + i2s_data->i2s_out_on_ref_cnt--; + if (i2s_data->i2s_out_on_ref_cnt == 0) + regmap_update_bits(afe->regmap, + AFE_I2S_CON1, 0x1, enable); + else if (i2s_data->i2s_out_on_ref_cnt < 0) + i2s_data->i2s_out_on_ref_cnt = 0; + } + + spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags); +} + +static void mt8365_dai_set_enable(struct mtk_base_afe *afe, + struct mtk_afe_i2s_priv *i2s_data, bool is_input, bool enable) +{ + unsigned int reg_off; + + if (is_input) { + reg_off = i2s_data->reg_off_in; + } else { + if (i2s_data->adda_link) { + mt8365_afe_set_i2s_out_enable(afe, enable); + return; + } else { + reg_off = i2s_data->reg_off_out; + } + } + regmap_update_bits(afe->regmap, reg_off, 0x1, enable); +} + +static int mt8365_dai_i2s_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id]; + const bool shared_clk = i2s_data->shared_clk; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + const bool i2s_in_slave = (substream->stream + == SNDRV_PCM_STREAM_CAPTURE) + && ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) + == SND_SOC_DAIFMT_CBM_CFM); + + dev_dbg(afe->dev, "%s '%s'\n", + __func__, snd_pcm_stream_str(substream)); + + if (shared_clk && snd_soc_dai_active(dai)) + return 0; + + mt8365_afe_enable_main_clk(afe); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK || shared_clk) + mt8365_afe_enable_clk(afe, + afe_priv->clocks[i2s_data->clk_id_out]); + + if ((substream->stream == SNDRV_PCM_STREAM_CAPTURE || shared_clk) + && !i2s_in_slave) + mt8365_afe_enable_clk(afe, + afe_priv->clocks[i2s_data->clk_id_in]); + + if (i2s_in_slave) + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_I2S_IN); + + return 0; +} + +static void mt8365_dai_i2s_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id]; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + const unsigned int rate = substream->runtime->rate; + const unsigned int stream = substream->stream; + const bool shared_clk = + i2s_data->shared_clk; + const bool reset_i2s_out_change = + (stream == SNDRV_PCM_STREAM_PLAYBACK) || shared_clk; + const bool reset_i2s_in_change = + (stream == SNDRV_PCM_STREAM_CAPTURE) || shared_clk; + const bool i2s_in_slave = (substream->stream + == SNDRV_PCM_STREAM_CAPTURE) + && ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) + == SND_SOC_DAIFMT_CBM_CFM); + + dev_dbg(afe->dev, "%s '%s'\n", + __func__, snd_pcm_stream_str(substream)); + + if (shared_clk && snd_soc_dai_active(dai)) + return; + + if (be->prepared[stream]) { + if (reset_i2s_out_change) + mt8365_dai_set_enable(afe, i2s_data, false, false); + + if (reset_i2s_in_change) + mt8365_dai_set_enable(afe, i2s_data, true, false); + + if (rate % 8000) + mt8365_afe_disable_apll_associated_cfg(afe, + MT8365_AFE_APLL1); + else + mt8365_afe_disable_apll_associated_cfg(afe, + MT8365_AFE_APLL2); + + if (reset_i2s_out_change) + be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = false; + + if (reset_i2s_in_change) + be->prepared[SNDRV_PCM_STREAM_CAPTURE] = false; + } + + if (reset_i2s_out_change) + mt8365_afe_disable_clk(afe, + afe_priv->clocks[i2s_data->clk_id_out]); + + if (reset_i2s_in_change && !i2s_in_slave) + mt8365_afe_disable_clk(afe, + afe_priv->clocks[i2s_data->clk_id_in]); + + if (i2s_in_slave) + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_I2S_IN); + + mt8365_afe_disable_main_clk(afe); +} + +static int mt8365_dai_i2s_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id]; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + struct snd_soc_dapm_widget *p = snd_soc_dai_get_widget_playback(dai); + struct snd_soc_dapm_widget *c = snd_soc_dai_get_widget_capture(dai); + const unsigned int rate = substream->runtime->rate; + const int bit_width = snd_pcm_format_width(substream->runtime->format); + const unsigned int stream = substream->stream; + const bool shared_clk = i2s_data->shared_clk; + const bool apply_i2s_out_change = + (stream == SNDRV_PCM_STREAM_PLAYBACK) || shared_clk; + const bool apply_i2s_in_change = + (stream == SNDRV_PCM_STREAM_CAPTURE) || shared_clk; + int ret; + + if (shared_clk && (p->power || c->power)) { + dev_dbg(afe->dev, "%s '%s' widget powered(%u-%u) already\n", + __func__, snd_pcm_stream_str(substream), + p->power, + c->power); + return 0; + } + + if (be->prepared[stream]) { + dev_info(afe->dev, "%s '%s' prepared already\n", + __func__, snd_pcm_stream_str(substream)); + return 0; + } + + if (apply_i2s_out_change) { + ret = mt8365_dai_set_config(afe, i2s_data, + false, rate, bit_width); + if (ret) + return ret; + } + + if (apply_i2s_in_change) { + if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) + == SND_SOC_DAIFMT_CBM_CFM) { + ret = mt8365_afe_set_2nd_i2s_asrc(afe, 32000, rate, + (unsigned int)bit_width, 0, 0, 1); + if (ret < 0) + return ret; + } + ret = mt8365_dai_set_config(afe, i2s_data, + true, rate, bit_width); + if (ret) + return ret; + } + + if (rate % 8000) + mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL1); + else + mt8365_afe_enable_apll_associated_cfg(afe, MT8365_AFE_APLL2); + + if (apply_i2s_out_change) { + mt8365_afe_set_clk_parent(afe, + afe_priv->clocks[i2s_data->clk_id_out_m_sel], + ((rate % 8000) ? + afe_priv->clocks[MT8365_CLK_AUD1] : + afe_priv->clocks[MT8365_CLK_AUD2])); + + mt8365_afe_set_clk_rate(afe, + afe_priv->clocks[i2s_data->clk_id_out], + rate * i2s_data->clk_out_mult); + + mt8365_dai_set_enable(afe, i2s_data, false, true); + be->prepared[SNDRV_PCM_STREAM_PLAYBACK] = true; + } + + if (apply_i2s_in_change) { + mt8365_afe_set_clk_parent(afe, + afe_priv->clocks[i2s_data->clk_id_in_m_sel], + ((rate % 8000) ? + afe_priv->clocks[MT8365_CLK_AUD1] : + afe_priv->clocks[MT8365_CLK_AUD2])); + + mt8365_afe_set_clk_rate(afe, + afe_priv->clocks[i2s_data->clk_id_in], + rate * i2s_data->clk_in_mult); + + mt8365_dai_set_enable(afe, i2s_data, true, true); + + if ((be->fmt_mode & SND_SOC_DAIFMT_MASTER_MASK) + == SND_SOC_DAIFMT_CBM_CFM) + mt8365_afe_set_2nd_i2s_asrc_enable(afe, true); + + be->prepared[SNDRV_PCM_STREAM_CAPTURE] = true; + } + return 0; +} + +static int mt8365_afe_2nd_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 width_val = params_width(params) > 16 ? + (AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01) : 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + regmap_update_bits(afe->regmap, AFE_CONN_24BIT, + AFE_CONN_24BIT_O00 | AFE_CONN_24BIT_O01, width_val); + + return 0; +} + +static int mt8365_afe_2nd_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mtk_afe_i2s_priv *i2s_data = afe_priv->dai_priv[dai->id]; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + const bool shared_clk = i2s_data->shared_clk; + + be->fmt_mode = 0; + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + be->fmt_mode |= SND_SOC_DAIFMT_I2S; + break; + case SND_SOC_DAIFMT_LEFT_J: + be->fmt_mode |= SND_SOC_DAIFMT_LEFT_J; + break; + default: + dev_info(afe->dev, "invalid audio format for 2nd i2s!\n"); + return -EINVAL; + } + + if (((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) && + ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_IF) && + ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_NF) && + ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_IB_IF)) { + dev_info(afe->dev, "invalid audio format for 2nd i2s!\n"); + return -EINVAL; + } + + be->fmt_mode |= (fmt & SND_SOC_DAIFMT_INV_MASK); + + if (((fmt & SND_SOC_DAIFMT_MASTER_MASK) == SND_SOC_DAIFMT_CBM_CFM) && + !shared_clk) + be->fmt_mode |= (fmt & SND_SOC_DAIFMT_MASTER_MASK); + + return 0; +} + +static const struct snd_soc_dai_ops mt8365_afe_i2s_ops = { + .startup = mt8365_dai_i2s_startup, + .shutdown = mt8365_dai_i2s_shutdown, + .prepare = mt8365_dai_i2s_prepare, +}; + +static const struct snd_soc_dai_ops mt8365_afe_2nd_i2s_ops = { + .startup = mt8365_dai_i2s_startup, + .shutdown = mt8365_dai_i2s_shutdown, + .hw_params = mt8365_afe_2nd_i2s_hw_params, + .prepare = mt8365_dai_i2s_prepare, + .set_fmt = mt8365_afe_2nd_i2s_set_fmt, +}; + +static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = { + { + .name = "I2S", + .id = MT8365_AFE_IO_I2S, + .playback = { + .stream_name = "I2S Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "I2S Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_i2s_ops, + }, { + .name = "2ND I2S", + .id = MT8365_AFE_IO_2ND_I2S, + .playback = { + .stream_name = "2ND I2S Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "2ND I2S Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_2nd_i2s_ops, + } +}; + +/* low jitter control */ +static const char * const mt8365_i2s_hd_str[] = { + "Normal", "Low_Jitter" +}; + +static SOC_ENUM_SINGLE_EXT_DECL(mt8365_i2s_enum, mt8365_i2s_hd_str); + +static const char * const fmi2sin_text[] = { + "OPEN", "FM_2ND_I2S_IN" +}; + +static SOC_ENUM_SINGLE_VIRT_DECL(fmi2sin_enum, fmi2sin_text); + +static const struct snd_kcontrol_new fmi2sin_mux = + SOC_DAPM_ENUM("FM 2ND I2S Source", fmi2sin_enum); + +static const struct snd_kcontrol_new i2s_o03_o04_enable_ctl = + SOC_DAPM_SINGLE_VIRT("Switch", 1); + +static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = { + SND_SOC_DAPM_SWITCH("I2S O03_O04", SND_SOC_NOPM, 0, 0, + &i2s_o03_o04_enable_ctl), + SND_SOC_DAPM_MUX("FM 2ND I2S Mux", SND_SOC_NOPM, 0, 0, &fmi2sin_mux), + SND_SOC_DAPM_INPUT("2ND I2S In"), +}; + +static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = { + {"I2S O03_O04", "Switch", "O03"}, + {"I2S O03_O04", "Switch", "O04"}, + {"I2S Playback", NULL, "I2S O03_O04"}, + {"2ND I2S Playback", NULL, "O00"}, + {"2ND I2S Playback", NULL, "O01"}, + {"2ND I2S Capture", NULL, "2ND I2S In"}, + {"FM 2ND I2S Mux", "FM_2ND_I2S_IN", "2ND I2S Capture"}, +}; + +static int mt8365_dai_i2s_set_priv(struct mtk_base_afe *afe) +{ + int i, ret; + bool tmp; + struct mt8365_afe_private *afe_priv = afe->platform_priv; + + tmp = of_property_read_bool(afe->dev->of_node, + "mediatek,i2s-shared-clock"); + + for (i = 0; i < DAI_I2S_NUM; i++) { + ret = mt8365_dai_set_priv(afe, mt8365_i2s_priv[i].id, + sizeof(struct mtk_afe_i2s_priv), + &mt8365_i2s_priv[i]); + if (ret) + return ret; + ((struct mtk_afe_i2s_priv *)afe_priv->dai_priv[mt8365_i2s_priv[i].id])-> + shared_clk = tmp; + } + return 0; +} + +int mt8365_dai_i2s_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dev_dbg(afe->dev, "%s()\n", __func__); + + 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->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 */ + return mt8365_dai_i2s_set_priv(afe); +} From patchwork Mon Feb 26 14:01:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776100 Received: from mail-wm1-f54.google.com (mail-wm1-f54.google.com [209.85.128.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 47AC912C52B for ; Mon, 26 Feb 2024 14:02:20 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956143; cv=none; b=Vx5ysT8B8UsWaugGhE2PnIzL6uzK8Dc8e0pvFc7u9hw7D7cmZQSJ+1s6Q5Ks0iDnibjEyCbERvF2PGOWsqWwW3d5lUyYyhFVZVskdcxNVFrRFJFQnU8T0BaQbnn/xw39cyAwCI/F0lC3RlpPDAeCHMW1pso0g0pl/h8Uv0dPYGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956143; c=relaxed/simple; bh=WhYTUc5nyLor7cp1cySzYWqCVaRGz/+mjJw6xD9dCo0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=QifPjVrYnDixdFpeX2mj3e0fxQhRQCc/13QfQGAyCiqlR8BD7rNwgkxM8K9oA4WeLQJsecki/gtxre8/6bdIYxMWW9P/y2BqEESPN6ParVLSbEh33u2qEBQBunLGwjGJ1wpp5xq4uNtif+oL3c0aLaazEL58Fgd8zeUSnXsBYRo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=GdUICceG; arc=none smtp.client-ip=209.85.128.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="GdUICceG" Received: by mail-wm1-f54.google.com with SMTP id 5b1f17b1804b1-412a87f0d8eso2800445e9.2 for ; Mon, 26 Feb 2024 06:02:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956139; x=1709560939; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=RKZ18lBh1OnYQ3TyOPJzfLNre2iMelEjg2dX28Xj+Jw=; b=GdUICceGYcRRvNuyMqYXTack4QGx32xB+VN6uaS7NP5YFnDRgGD4LKGq1jteD0KFw8 hw+VLxClSSg1X+x3wIvzWAlDkSo+ICOh7amLQ+y8QyPMAiHTpHHFilHZNMUMV8wamhk9 zU8L/vktGShU9kCZylxrPKoIFMuygRhbFlZiFBhX2Ixqtgrk5bPPUHPyxJEx5VX6MaeU ZgUbP13VZxfbSA2UDPGDSMa0n4UHYSKK+4qUv0lDRgIQHNoIq/JnfOa4qfl4H7os1ahm Tb0JCFkGVuep7TiL9T2Ola5CoNFwXfybwvVF3pqQ5/vg/lJ6UXSRNoJSW7O1Lzb4JMjL zpZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956139; x=1709560939; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RKZ18lBh1OnYQ3TyOPJzfLNre2iMelEjg2dX28Xj+Jw=; b=Cd4OuDeVpfXbFGpTgguhLeEmE5fa/khFgeyfXKGJya9vd8J0Fz62oQRsWvURouGSFd +t3JZfsqS/GqsqjncrY1+Ksj1KnnL/U8BrnGPTLOnkAQJjiO3R8jcZvOZ2J1E9Q3sXpa e+iXMSDKdyhPvI41xc8oOCn/ln3DD+w9LPju3L0aaiTUse/iyT6FlJiGgkXsBpHn5Ryn oahH0jjEuMt8KH3jPmMAwTc6o/Z96EKOB7f0oUs3VHk6pBRVeL0qXNipcDxXITSVKBL9 WrqHv+5JWGqKdEfladhdq4LCg0M+WXtgMUj7YjKq0x4JeLveoRmtXGtMOTGN6Zld498q XX5Q== X-Forwarded-Encrypted: i=1; AJvYcCUl4BSlQDeh9tSNDMYnSidgq4nxvrBox1XDt3l34BmnB5mDdlzJhsUSD3/D2B5QBmguO3HYX9wM0ua+1STvDq1U6jRp4TXsIQALgh4= X-Gm-Message-State: AOJu0YwTTHcfFxHAV8tRsKLjnHeG8jIcAO4TnwVAgIHipOfd1UBXiL0W 5C9QpAVO9hBpThMsXbt7FgkJ+iU5uUSID+ji0Y8fizaUTcnpYSvitHXpCf/jmck= X-Google-Smtp-Source: AGHT+IFYicg4bzNhih8j+7WUKcW85bRUXiYGXRoj2/rhkpW98Ex9kfqJG6uFOs4oxvH5U1F7iqJ8/w== X-Received: by 2002:a05:600c:3ba6:b0:412:9694:71a9 with SMTP id n38-20020a05600c3ba600b00412969471a9mr4216263wms.10.1708956138677; Mon, 26 Feb 2024 06:02:18 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:18 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:46 +0100 Subject: [PATCH 08/18] ASoC: mediatek: mt8365: Add DMIC DAI support Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-8-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=14289; i=amergnat@baylibre.com; h=from:subject:message-id; bh=WhYTUc5nyLor7cp1cySzYWqCVaRGz/+mjJw6xD9dCo0=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncI9fvx+/egkjArf7CY8inuUTtBgKzEp47N8ZO 3IPFHNCJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURSV/D/ 0chIIqI6FUHeI7rRyihvR4ao/+dJLrwRvRzV1gWduyCMyDnOnG9QMAxzkX83YhMAt7d+r+HlnAR61G TpbHsY7gZjSLhmfmRqeoQzZjWtlU05XmVKei9kqXU5DHUqCssQKgF7xcKqY+Fc5RIbvpNAu2Uriu6P PtA74cu9Uec9CzGpzv/RpzqZN5tTNw1YoVCxMlH7TqL2WcLw00vHeXrjsUOdVTSKzTnMfZSoT46dVy RibkVryYVmmTHlirWYr26IXaJ4qXjQxJAOuTFgY4tQ9bYA17Fw8P9Glo+aR8Aa2eoUWAmsWy6YvLPI 5KTPJc2dNcXcVe7qNzNi2Tb0+CInKcQkvCHoo37+48fIdUrF1ZCTMBwOu+x2bFvHsIPJK9Ijv+wDXK j23azVQnMnqT5//fRCBcFvZkF3j9XwROqh0h1BvDNMTlSfqmQRzzBLQQrJyNpIs+30CSMudqAHzlS8 Ud+z0CIRayTz++KjLE0d8zZU4THFoLJ8fstDuK0ZheuTJjS/6XQUn3NRgq77t8Ws523/Mtbra70MvU Xl7QKbp+q6kRqCb/9FKWPpMS8sUAXAENgXdjhfFbNJjCDgJ3lVXsJxCvn5p4dX4F7C8Mz81Xtb1caU 7wFCOam22CxUM1+2Sts1vWXfpjOFUQBHIQwGJMhRcFHK0Q7JfR13ehzBxXqw== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add Digital Micro Device Audio Interface support for MT8365 SoC. Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/mt8365/mt8365-dai-dmic.c | 475 ++++++++++++++++++++++++++++ 1 file changed, 475 insertions(+) diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c new file mode 100644 index 000000000000..1e59f456b7c9 --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-dai-dmic.c @@ -0,0 +1,475 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek 8365 ALSA SoC Audio DAI DMIC Control + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Jia Zeng + * Alexandre Mergnat + */ + +#include +#include +#include +#include "mt8365-afe-clk.h" +#include "mt8365-afe-common.h" + +struct mt8365_dmic_data { + bool two_wire_mode; + unsigned int clk_phase_sel_ch1; + unsigned int clk_phase_sel_ch2; + bool iir_on; + unsigned int irr_mode; + unsigned int dmic_mode; + unsigned int dmic_channel; +}; + +/* DAI Drivers */ + +static void audio_dmic_adda_enable(struct mtk_base_afe *afe) +{ + mt8365_dai_enable_adda_on(afe); + regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, + AFE_ADDA_UL_DL_DMIC_CLKDIV_ON, AFE_ADDA_UL_DL_DMIC_CLKDIV_ON); +} + +static void audio_dmic_adda_disable(struct mtk_base_afe *afe) +{ + regmap_update_bits(afe->regmap, AFE_ADDA_UL_DL_CON0, + AFE_ADDA_UL_DL_DMIC_CLKDIV_ON, ~AFE_ADDA_UL_DL_DMIC_CLKDIV_ON); + mt8365_dai_disable_adda_on(afe); +} + +static void mt8365_dai_enable_dmic(struct mtk_base_afe *afe, + struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC]; + unsigned int val_mask; + + /* val and mask will be always same to enable */ + val_mask = DMIC_TOP_CON_CH1_ON | + DMIC_TOP_CON_CH2_ON | + DMIC_TOP_CON_SRC_ON; + + switch (dmic_data->dmic_channel) { + case 8: + fallthrough; + case 7: + regmap_update_bits(afe->regmap, AFE_DMIC3_UL_SRC_CON0, + val_mask, val_mask); + fallthrough; + case 6: + fallthrough; + case 5: + regmap_update_bits(afe->regmap, AFE_DMIC2_UL_SRC_CON0, + val_mask, val_mask); + fallthrough; + case 4: + fallthrough; + case 3: + regmap_update_bits(afe->regmap, AFE_DMIC1_UL_SRC_CON0, + val_mask, val_mask); + fallthrough; + case 2: + fallthrough; + case 1: + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + val_mask, val_mask); + break; + default: + break; + } +} + +static void mt8365_dai_disable_dmic(struct mtk_base_afe *afe, + struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC]; + unsigned int val, mask; + + dev_info(afe->dev, "%s dmic_channel %d\n", + __func__, dmic_data->dmic_channel); + + mask = DMIC_TOP_CON_CH1_ON | + DMIC_TOP_CON_CH2_ON | + DMIC_TOP_CON_SRC_ON | + DMIC_TOP_CON_SDM3_LEVEL_MODE; + + /* CH1, CH1 and ARC = 0 */ + val = DMIC_TOP_CON_SDM3_DE_SELECT; + + switch (dmic_data->dmic_channel) { + case 8: + fallthrough; + case 7: + regmap_update_bits(afe->regmap, AFE_DMIC3_UL_SRC_CON0, + mask, val); + + fallthrough; + case 6: + fallthrough; + case 5: + regmap_update_bits(afe->regmap, AFE_DMIC2_UL_SRC_CON0, + mask, val); + fallthrough; + case 4: + case 3: + regmap_update_bits(afe->regmap, AFE_DMIC1_UL_SRC_CON0, + mask, val); + fallthrough; + case 2: + fallthrough; + case 1: + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + mask, val); + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + DMIC_TOP_CON_CH2_ON, 0); + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + DMIC_TOP_CON_SRC_ON, 0); + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + DMIC_TOP_CON_SDM3_LEVEL_MODE, + DMIC_TOP_CON_SDM3_DE_SELECT); + break; + default: + break; + } +} + +static const struct reg_sequence mt8365_afe_dmic_iir_coeff_reg_defaults[] = { + { AFE_DMIC0_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC0_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC0_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC0_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC0_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC1_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC1_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC1_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC1_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC1_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC2_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC2_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC2_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC2_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC2_IIR_COEF_10_09, 0x0000C048 }, + { AFE_DMIC3_IIR_COEF_02_01, 0x00000000 }, + { AFE_DMIC3_IIR_COEF_04_03, 0x00003FB8 }, + { AFE_DMIC3_IIR_COEF_06_05, 0x3FB80000 }, + { AFE_DMIC3_IIR_COEF_08_07, 0x3FB80000 }, + { AFE_DMIC3_IIR_COEF_10_09, 0x0000C048 }, +}; + +static int mt8365_dai_load_dmic_iir_coeff_table(struct mtk_base_afe *afe) +{ + return regmap_multi_reg_write(afe->regmap, + mt8365_afe_dmic_iir_coeff_reg_defaults, + ARRAY_SIZE(mt8365_afe_dmic_iir_coeff_reg_defaults)); +} + +static int mt8365_dai_configure_dmic(struct mtk_base_afe *afe, + struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC]; + bool two_wire_mode = dmic_data->two_wire_mode; + unsigned int clk_phase_sel_ch1 = dmic_data->clk_phase_sel_ch1; + unsigned int clk_phase_sel_ch2 = dmic_data->clk_phase_sel_ch2; + bool iir_on = dmic_data->iir_on; + unsigned int irr_mode = dmic_data->irr_mode; + unsigned int dmic_mode = dmic_data->dmic_mode; + unsigned int val = 0; + unsigned int channels = dai->channels; + unsigned int rate = dai->rate; + + dmic_data->dmic_channel = channels; + + dev_info(afe->dev, "%s dmic_channel %d dmic_rate %d dmic_mode %d\n", + __func__, dmic_data->dmic_channel, rate, dmic_mode); + + val |= DMIC_TOP_CON_SDM3_LEVEL_MODE; + + if (dmic_mode > DMIC_MODE_1P625M) + val |= DMIC_TOP_CON_LOW_POWER_MODE(dmic_mode); + else { + val |= DMIC_TOP_CON_LOW_POWER_MODE(0) | + FIELD_PREP(DMIC_TOP_CON_INPUT_MODE, dmic_mode); + } + + if (two_wire_mode) { + val |= DMIC_TOP_CON_TWO_WIRE_MODE; + } else { + val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH1, clk_phase_sel_ch1); + val |= FIELD_PREP(DMIC_TOP_CON_CK_PHASE_SEL_CH2, clk_phase_sel_ch2); + } + + switch (rate) { + case 48000: + val |= DMIC_TOP_CON_VOICE_MODE_48K; + break; + case 32000: + val |= DMIC_TOP_CON_VOICE_MODE_32K; + break; + case 16000: + val |= DMIC_TOP_CON_VOICE_MODE_16K; + break; + case 8000: + val |= DMIC_TOP_CON_VOICE_MODE_8K; + break; + default: + return -EINVAL; + } + + if (iir_on) { + if (irr_mode == IIR_MODE0) + mt8365_dai_load_dmic_iir_coeff_table(afe); /* SW mode */ + val |= FIELD_PREP(DMIC_TOP_CON_IIR_MODE, irr_mode); + val |= DMIC_TOP_CON_IIR_ON; + } + + switch (dmic_data->dmic_channel) { + case 8: + fallthrough; + case 7: + regmap_update_bits(afe->regmap, AFE_DMIC3_UL_SRC_CON0, + DMIC_TOP_CON_CONFIG_MASK, val); + fallthrough; + case 6: + fallthrough; + case 5: + regmap_update_bits(afe->regmap, AFE_DMIC2_UL_SRC_CON0, + DMIC_TOP_CON_CONFIG_MASK, val); + fallthrough; + case 4: + fallthrough; + case 3: + regmap_update_bits(afe->regmap, AFE_DMIC1_UL_SRC_CON0, + DMIC_TOP_CON_CONFIG_MASK, val); + fallthrough; + case 2: + fallthrough; + case 1: + regmap_update_bits(afe->regmap, AFE_DMIC0_UL_SRC_CON0, + DMIC_TOP_CON_CONFIG_MASK, val); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int mt8365_dai_dmic_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + mt8365_afe_enable_main_clk(afe); + + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC); + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC); + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC); + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC); + + audio_dmic_adda_enable(afe); + + return 0; +} + +static void mt8365_dai_dmic_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + mt8365_dai_disable_dmic(afe, substream, dai); + audio_dmic_adda_disable(afe); + /* HW Request delay 125ms before CG off */ + udelay(125); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC3_ADC); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC2_ADC); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC1_ADC); + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_DMIC0_ADC); + + mt8365_afe_disable_main_clk(afe); +} + +static int mt8365_dai_dmic_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + mt8365_dai_configure_dmic(afe, substream, dai); + mt8365_dai_enable_dmic(afe, substream, dai); + + return 0; +} + +static const struct snd_soc_dai_ops mt8365_afe_dmic_ops = { + .startup = mt8365_dai_dmic_startup, + .shutdown = mt8365_dai_dmic_shutdown, + .prepare = mt8365_dai_dmic_prepare, +}; + +static struct snd_soc_dai_driver mtk_dai_dmic_driver[] = { + { + .name = "DMIC", + .id = MT8365_AFE_IO_DMIC, + .capture = { + .stream_name = "DMIC Capture", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_dmic_ops, + } +}; + +/* DAI Controls */ + +static int mt8365_afe_dmic_mode_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 mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC]; + + ucontrol->value.integer.value[0] = dmic_data->dmic_mode; + + return 0; +} + +static int mt8365_afe_dmic_mode_put(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 mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_data = afe_priv->dai_priv[MT8365_AFE_IO_DMIC]; + + unsigned int val = ucontrol->value.integer.value[0]; + + if (dmic_data->dmic_mode == val) + return 0; + + dmic_data->dmic_mode = ucontrol->value.integer.value[0]; + + return 0; +} + +static const char *const dmic_mode_func[] = { + ENUM_TO_STR(DMIC_MODE_3P25M), + ENUM_TO_STR(DMIC_MODE_1P625M), + ENUM_TO_STR(DMIC_MODE_812P5K), + ENUM_TO_STR(DMIC_MODE_406P25K), +}; + +static const struct soc_enum mt8365_afe_soc_enum = + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(dmic_mode_func), dmic_mode_func); + +static const struct snd_kcontrol_new mtk_dai_dmic_controls[] = { + SOC_ENUM_EXT("DMIC_Mode_Select", + mt8365_afe_soc_enum, + mt8365_afe_dmic_mode_get, + mt8365_afe_dmic_mode_put), +}; + +/* DAI widget */ + +static const struct snd_soc_dapm_widget mtk_dai_dmic_widgets[] = { + SND_SOC_DAPM_INPUT("DMIC In"), +}; + +/* DAI route */ + +static const struct snd_soc_dapm_route mtk_dai_dmic_routes[] = { + {"I14", NULL, "DMIC Capture"}, + {"I15", NULL, "DMIC Capture"}, + {"I16", NULL, "DMIC Capture"}, + {"I17", NULL, "DMIC Capture"}, + {"I18", NULL, "DMIC Capture"}, + {"I19", NULL, "DMIC Capture"}, + {"I20", NULL, "DMIC Capture"}, + {"I21", NULL, "DMIC Capture"}, + {"DMIC Capture", NULL, "DMIC In"}, +}; + + +static int init_dmic_priv_data(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_dmic_data *dmic_priv; + struct device_node *np = afe->dev->of_node; + unsigned int temps[4]; + int ret; + + dmic_priv = devm_kzalloc(afe->dev, sizeof(struct mt8365_dmic_data), + GFP_KERNEL); + if (!dmic_priv) + return -ENOMEM; + + ret = of_property_read_u32_array(np, "mediatek,dmic-mode", + &temps[0], + 1); + if (ret == 0) + dmic_priv->dmic_mode = temps[0]; + + dmic_priv->two_wire_mode = of_property_read_bool(np, + "mediatek,dmic-two-wire-mode"); + + ret = of_property_read_u32_array(np, "mediatek,dmic-clk-phases", + &temps[0], + 2); + if (ret == 0) { + dmic_priv->clk_phase_sel_ch1 = temps[0]; + dmic_priv->clk_phase_sel_ch2 = temps[1]; + } else if (!dmic_priv->two_wire_mode) { + dmic_priv->clk_phase_sel_ch1 = 0; + dmic_priv->clk_phase_sel_ch2 = 4; + } + + dmic_priv->iir_on = of_property_read_bool(np, + "mediatek,dmic-iir-on"); + + if (dmic_priv->iir_on) { + ret = of_property_read_u32_array(np, "mediatek,dmic-irr-mode", + &temps[0], + 1); + if (ret == 0) + dmic_priv->irr_mode = temps[0]; + } + + afe_priv->dai_priv[MT8365_AFE_IO_DMIC] = dmic_priv; + return 0; +} + +int mt8365_dai_dmic_register(struct mtk_base_afe *afe) +{ + struct mtk_base_afe_dai *dai; + + dev_dbg(afe->dev, "%s()\n", __func__); + + 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_dmic_driver; + dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_dmic_driver); + dai->controls = mtk_dai_dmic_controls; + dai->num_controls = ARRAY_SIZE(mtk_dai_dmic_controls); + dai->dapm_widgets = mtk_dai_dmic_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_dmic_widgets); + dai->dapm_routes = mtk_dai_dmic_routes; + dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_dmic_routes); + + return init_dmic_priv_data(afe); +} From patchwork Mon Feb 26 14:01:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776099 Received: from mail-wm1-f51.google.com (mail-wm1-f51.google.com [209.85.128.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DE7D312C7E4 for ; Mon, 26 Feb 2024 14:02:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956146; cv=none; b=D9kTM9zppV6q3CE0DB4d3RsRuE9K5EslkShBobBQVrUWvsk769e6ni1xjx3kxzJWwyVR5pNzt4LTxvuzmf6IYbjNpZiMK79JsSOS8wZWnD4zc1T8/qtF93jOGJDS5NhMN8tbPdL+Y06ow1P9mBYIunfJyd3yN5B0ne3BETzRs6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956146; c=relaxed/simple; bh=8zzU+qG1fPk8vRLOgYFfZg88F+aOnzuUmVOQbwvKUaM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=UD0a1BqQ3VSsAbfTf1sEbqrJYkjIuseH7RkeYTlYzLqfeIuvTVL6HcE22mVpy/LbDZOeb8Q/blFC6VK1ysxEzxgEjHgrEYcGoPTLbFX+E/4fycuPRRoUCTLgOSKJUrT2FapDq8kAIEkWt1pFMZrohCmWP8i9KbTb6KvxreX8ZRg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=DZz38flU; arc=none smtp.client-ip=209.85.128.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="DZz38flU" Received: by mail-wm1-f51.google.com with SMTP id 5b1f17b1804b1-412a390347dso8641555e9.3 for ; Mon, 26 Feb 2024 06:02:22 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956141; x=1709560941; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=7rk/tSJl5kLzfsbNzKXk0J46mO1xUX9mq9pT6k284dM=; b=DZz38flU6+Vnw3SLGwu0XXmLb7iADzGDUFttLtPprCNrOOywtHk9ywekcVsQg0BY1l I6HwKbWL6PZihtHNBaBluv0s33YjBbikAek1uqqrXHev/+SBOLQORr/Ub4Jv2D5/cDdb aGpU9qlDNm2J6a1lV0wIc+aqtUQwnnWF6yVvMxfzXsfPrEp+n7Sw9QjwReJi0Mr72ikq tGhmgPq2rAUxr1PCqeQuBHa9WFrCc5Fs6VGRlGY/iBPmtCp1b2N1X2sqSDKwlCGrqH+5 Ze6JnCy8+i5fjiQ8ciWqaA4n44OUwRlrG6gVz5og9lHCURgRc/y0SHCLSZ0RfFNwx6he FoRg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956141; x=1709560941; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7rk/tSJl5kLzfsbNzKXk0J46mO1xUX9mq9pT6k284dM=; b=UgXyBoKQJktP0Kqifflm4zLIRbGzcnjVW8Hs1FX0SL+iNCX3Ib7EDak+Ge/HO7lhhd rVc7AU0Dl7+g8qNjTZbFw8j5drKnLhvc9DpT/OUGUXbe8XGFD0Od11zuoHgmWI6In2J/ 8/5zmVn2wzsLlgznwIfGyrkQ9NEaedCW6Ctrle4PilEO7sJwdXLJ+9x4JlXiwipm9DDT 7DT2DGWZCbhETkqfDcnynn9H6CctJgH8CVUJqvxJd4zM5128VscOvQhlrAE7bbNHUj0F ty4s6i4lJAudt4sZ3UAA3w/+DHt9KZheJTZviVguTWQjLStjYSLt89CNT3m6h0NaH+ln 9BAw== X-Forwarded-Encrypted: i=1; AJvYcCU72CywJqYzjw2hCpYVPVcyZquVH4mv5zwd+n5G2P9EIWV8WfzFlaVWibpSwlV+AqP2dIR+AT52+z5Y7pHYxEN8/hFvu0ZstTWhwRw= X-Gm-Message-State: AOJu0Yw1PNlODcp17m8+AFtDe3GktdnDCXfKMVlstTLeuQCljlp3VhWj ltX3sI8DL9IfNWtpMDC7WYhoOpa4Cd/IrBVoceq+/jxrp35wj3va5CUbUnq1nOU= X-Google-Smtp-Source: AGHT+IH5GQoT6M+RJiV3VuRpIKlT4Tt2IfyYzZ7kuzYARaCi5A89a5llh+LVXN8Sa2iJNPcuyc/N4A== X-Received: by 2002:a05:600c:1c94:b0:412:a7d0:6205 with SMTP id k20-20020a05600c1c9400b00412a7d06205mr1336284wms.11.1708956141193; Mon, 26 Feb 2024 06:02:21 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:20 -0800 (PST) From: amergnat@baylibre.com Date: Mon, 26 Feb 2024 15:01:48 +0100 Subject: [PATCH 10/18] ASoc: mediatek: mt8365: Add a specific soundcard for EVK Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-10-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat , Nicolas Belin X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=10979; i=amergnat@baylibre.com; h=from:subject:message-id; bh=uBK7Yymo2RSrOcLwG3FQocwjl9A/GkudWfrF/KTinSk=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncPH4l5IUg+l31d/JAjVl6JDVLmtD7tebTfEj5 Hh7Iv06JAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURZkdEA CqpOUUsGSTW+nZFIzg3gkQuWQFWxpzgMGSx/HIu6xu4Gsciub3B+V4uM8WqTfaCt1CpOwJj2QgjkVh DJzxSTXKnrAyA3ohevTA4bDKWo1x2No1lTHWrd9t0xDntRG2FK6Hj9mUDBKNZPV/Gb2owvcvUqqdKa R+uDMko6pI7knqfN58ZTX3fdkbI8uHITfI2nMvYJQDjoD7m/HoVeP4vmhkgHX4nmoDpqmxfQX2zlkm /uEBOQYAGzJD9SiCwRjXrIQFZ5+TPswDiEIjFb0E+L2Pq67Dz2B1APM1xzo0E9T4GMAt7iNSeCjls+ fQhNFbhPWuFGHP7276LLng1lMFYeyqmSOOsyXUTKTQmNC6aPYyEeUDzmd2roRQz9RxBJHhNSi2/zxc UZZtu+2xxpzMI/i+UgYmIRJtrlwOFZieFoDY+fg66DwgFGCgcbGZSwvaDQxw1f2R+x7Yh7Hmsm79kH zVQP7BScQA5UP//7hq4DkBP0EODB/g6jKvwT13zEXmkX1YASTHBM6+1JCPUHP5Lj6yMMxOyyGXk21y R9WjzurfLF43OlU1JeCpU6NYslCgUOxkSGqsgAWxlOqjpg78X0i8sReRxN5sIhVr/GQOtv40kel0Zf H1jxf4/xK1+HET59UK7e0AWAXZpZ8PgklFzEnznhbgvSkYGtGP+g7R2i1RJw== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 From: Nicolas Belin Add a specific soundcard for mt8365-evk. It supports audio jack in/out, dmics, the amic and lineout. Signed-off-by: Nicolas Belin Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/mt8365/mt8365-mt6357.c | 379 ++++++++++++++++++++++++++++++ 1 file changed, 379 insertions(+) diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c new file mode 100644 index 000000000000..5192b35458e6 --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c @@ -0,0 +1,379 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek MT8365 Sound Card driver + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Nicolas Belin + */ + +#include +#include +#include +#include +#include "mt8365-afe-common.h" +#include +#include "../common/mtk-soundcard-driver.h" + +enum PINCTRL_PIN_STATE { + PIN_STATE_DEFAULT = 0, + PIN_STATE_DMIC, + PIN_STATE_MISO_OFF, + PIN_STATE_MISO_ON, + PIN_STATE_MOSI_OFF, + PIN_STATE_MOSI_ON, + PIN_STATE_MAX +}; + +static const char * const mt8365_mt6357_pin_str[PIN_STATE_MAX] = { + "aud_default", + "aud_dmic", + "aud_miso_off", + "aud_miso_on", + "aud_mosi_off", + "aud_mosi_on", +}; + +struct mt8365_mt6357_priv { + struct pinctrl *pinctrl; + struct pinctrl_state *pin_states[PIN_STATE_MAX]; +}; + +struct mt8365_dai_link_prop { + char *name; + unsigned int link_id; +}; + +enum { + /* FE */ + DAI_LINK_DL1_PLAYBACK = 0, + DAI_LINK_DL2_PLAYBACK, + DAI_LINK_AWB_CAPTURE, + DAI_LINK_VUL_CAPTURE, + /* BE */ + DAI_LINK_2ND_I2S_INTF, + DAI_LINK_DMIC, + DAI_LINK_INT_ADDA, + DAI_LINK_NUM +}; + +static const struct snd_soc_dapm_widget mt8365_mt6357_widgets[] = { + SND_SOC_DAPM_OUTPUT("HDMI Out"), +}; + +static const struct snd_soc_dapm_route mt8365_mt6357_routes[] = { + {"HDMI Out", NULL, "2ND I2S Playback"}, + {"DMIC In", NULL, "MICBIAS0"}, +}; + +static int mt8365_mt6357_int_adda_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card); + int ret = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_ON])) + return ret; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_MOSI_ON]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (IS_ERR(priv->pin_states[PIN_STATE_MISO_ON])) + return ret; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_MISO_ON]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + } + + return 0; +} + +static void mt8365_mt6357_int_adda_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(rtd->card); + int ret = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + if (IS_ERR(priv->pin_states[PIN_STATE_MOSI_OFF])) + return; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_MOSI_OFF]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + } + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + if (IS_ERR(priv->pin_states[PIN_STATE_MISO_OFF])) + return; + + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[PIN_STATE_MISO_OFF]); + if (ret) + dev_err(rtd->card->dev, "%s failed to select state %d\n", + __func__, ret); + } + +} + +static const struct snd_soc_ops mt8365_mt6357_int_adda_ops = { + .startup = mt8365_mt6357_int_adda_startup, + .shutdown = mt8365_mt6357_int_adda_shutdown, +}; + +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(playback2, + DAILINK_COMP_ARRAY(COMP_CPU("DL2")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(awb_capture, + DAILINK_COMP_ARRAY(COMP_CPU("AWB")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(vul, + DAILINK_COMP_ARRAY(COMP_CPU("VUL")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +SND_SOC_DAILINK_DEFS(i2s3, + DAILINK_COMP_ARRAY(COMP_CPU("2ND I2S")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(dmic, + DAILINK_COMP_ARRAY(COMP_CPU("DMIC")), + DAILINK_COMP_ARRAY(COMP_DUMMY()), + DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(primary_codec, + DAILINK_COMP_ARRAY(COMP_CPU("INT ADDA")), + DAILINK_COMP_ARRAY(COMP_CODEC("mt6357-sound", "mt6357-snd-codec-aif1")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + +/* Digital audio interface glue - connects codec <---> CPU */ +static struct snd_soc_dai_link mt8365_mt6357_dais[] = { + /* Front End DAI links */ + [DAI_LINK_DL1_PLAYBACK] = { + .name = "DL1_FE", + .stream_name = "MultiMedia1_PLayback", + .id = DAI_LINK_DL1_PLAYBACK, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST + }, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(playback1), + }, + [DAI_LINK_DL2_PLAYBACK] = { + .name = "DL2_FE", + .stream_name = "MultiMedia2_PLayback", + .id = DAI_LINK_DL2_PLAYBACK, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST + }, + .dynamic = 1, + .dpcm_playback = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(playback2), + }, + [DAI_LINK_AWB_CAPTURE] = { + .name = "AWB_FE", + .stream_name = "DL1_AWB_Record", + .id = DAI_LINK_AWB_CAPTURE, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST + }, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(awb_capture), + }, + [DAI_LINK_VUL_CAPTURE] = { + .name = "VUL_FE", + .stream_name = "MultiMedia1_Capture", + .id = DAI_LINK_VUL_CAPTURE, + .trigger = { + SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST + }, + .dynamic = 1, + .dpcm_capture = 1, + .dpcm_merged_rate = 1, + SND_SOC_DAILINK_REG(vul), + }, + /* Back End DAI links */ + [DAI_LINK_2ND_I2S_INTF] = { + .name = "2ND I2S BE", + .no_pcm = 1, + .id = DAI_LINK_2ND_I2S_INTF, + .dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS, + .dpcm_playback = 1, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(i2s3), + }, + [DAI_LINK_DMIC] = { + .name = "DMIC BE", + .no_pcm = 1, + .id = DAI_LINK_DMIC, + .dpcm_capture = 1, + SND_SOC_DAILINK_REG(dmic), + }, + [DAI_LINK_INT_ADDA] = { + .name = "MTK Codec", + .no_pcm = 1, + .id = DAI_LINK_INT_ADDA, + .dpcm_playback = 1, + .dpcm_capture = 1, + .ops = &mt8365_mt6357_int_adda_ops, + SND_SOC_DAILINK_REG(primary_codec), + }, +}; + +static int pinctrl_setup(struct snd_soc_card *card, + struct mt8365_mt6357_priv *priv, + unsigned int pin_id) +{ + int ret = 0; + /* if pin exist */ + if (!IS_ERR(priv->pin_states[pin_id])) { + ret = pinctrl_select_state(priv->pinctrl, + priv->pin_states[pin_id]); + if (ret) + dev_err(card->dev, + "%s failed to select state %d\n", + __func__, ret); + } + return ret; +} + +static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card) +{ + struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card); + int ret = 0; + int i; + + priv->pinctrl = devm_pinctrl_get(card->dev); + if (IS_ERR(priv->pinctrl)) { + ret = PTR_ERR(priv->pinctrl); + dev_err(card->dev, "%s devm_pinctrl_get failed %d\n", + __func__, ret); + return ret; + } + + for (i = 0 ; i < PIN_STATE_MAX ; i++) { + priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl, + mt8365_mt6357_pin_str[i]); + if (IS_ERR(priv->pin_states[i])) { + ret = PTR_ERR(priv->pin_states[i]); + dev_err(card->dev, "%s Can't find pin state %s %d\n", + __func__, mt8365_mt6357_pin_str[i], ret); + } + } + + /* Setup pins */ + ret |= pinctrl_setup(card, priv, PIN_STATE_DEFAULT); + ret |= pinctrl_setup(card, priv, PIN_STATE_DMIC); + ret |= pinctrl_setup(card, priv, PIN_STATE_MISO_OFF); + ret |= pinctrl_setup(card, priv, PIN_STATE_MOSI_OFF); + + return ret; +} + +static struct snd_soc_card mt8365_mt6357_card = { + .name = "mt8365-evk", + .owner = THIS_MODULE, + .dai_link = mt8365_mt6357_dais, + .num_links = ARRAY_SIZE(mt8365_mt6357_dais), + .dapm_widgets = mt8365_mt6357_widgets, + .num_dapm_widgets = ARRAY_SIZE(mt8365_mt6357_widgets), + .dapm_routes = mt8365_mt6357_routes, + .num_dapm_routes = ARRAY_SIZE(mt8365_mt6357_routes), +}; + +static int mt8365_mt6357_dev_probe(struct platform_device *pdev) +{ + struct snd_soc_card *card = &mt8365_mt6357_card; + struct device *dev = &pdev->dev; + struct device_node *platform_node; + struct mt8365_mt6357_priv *priv; + int i, ret; + + card->dev = dev; + ret = parse_dai_link_info(card); + if (ret) + goto err; + + platform_node = of_parse_phandle(dev->of_node, "mediatek,platform", 0); + if (!platform_node) { + dev_err(dev, "Property 'platform' missing or invalid\n"); + return -EINVAL; + } + + for (i = 0; i < card->num_links; i++) { + if (mt8365_mt6357_dais[i].platforms->name) + continue; + mt8365_mt6357_dais[i].platforms->of_node = platform_node; + } + + priv = devm_kzalloc(dev, sizeof(struct mt8365_mt6357_priv), + GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(dev, "%s allocate card private data fail %d\n", + __func__, ret); + return ret; + } + + snd_soc_card_set_drvdata(card, priv); + + mt8365_mt6357_gpio_probe(card); + + ret = devm_snd_soc_register_card(dev, card); + if (ret) + dev_err(dev, "%s snd_soc_register_card fail %d\n", + __func__, ret); +err: + of_node_put(platform_node); + clean_card_reference(card); + return ret; +} + +static const struct of_device_id mt8365_mt6357_dt_match[] = { + { .compatible = "mediatek,mt8365-mt6357", }, + { } +}; +MODULE_DEVICE_TABLE(of, mt8365_mt6357_dt_match); + +static struct platform_driver mt8365_mt6357_driver = { + .driver = { + .name = "mt8365_mt6357", + .of_match_table = mt8365_mt6357_dt_match, + .pm = &snd_soc_pm_ops, + }, + .probe = mt8365_mt6357_dev_probe, +}; + +module_platform_driver(mt8365_mt6357_driver); + +/* Module information */ +MODULE_DESCRIPTION("MT8365 EVK SoC machine driver"); +MODULE_AUTHOR("Nicolas Belin "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("mt8365 mt6357 soc card"); From patchwork Mon Feb 26 14:01:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776097 Received: from mail-wm1-f41.google.com (mail-wm1-f41.google.com [209.85.128.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 86C2612C53E for ; Mon, 26 Feb 2024 14:02:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956153; cv=none; b=DMoy4C1qU5GoSfwiufi479aXCnsunUwh6p/YrcLBFNJLgUu8yTqiE2Hzj4dL+fxmY6sDnPA0qI+l8i0fM0EG1dNJRadn32b8cqiHP4VAK0+EO8J2PCt0wrn5mOn0eMiH1LGRVd20/+lfyajm4HXBeAX61TV5oz3Db30E5YnQSh4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956153; c=relaxed/simple; bh=DUfIVA0hQOxiGtkvvTZJpZoPeoD/Qsx4aX+oLcdc5cM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=N272UslXsRwK6A+Btetg0E9AIF/HnKn7Cr6Hl+U9Ws0AfYx/WrWns4PhO2TR0+6AIlVBP8Nyxqw+gF5Jmn7DH1gawi9TTbMVqe9oXJwN6X/q4G59dsvrgpfnD7IMXmPCRWwAwZWzPOLsFYVds/gLKo6WOWvivRPgW0ZRr9clwdU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=JRpXHxHA; arc=none smtp.client-ip=209.85.128.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="JRpXHxHA" Received: by mail-wm1-f41.google.com with SMTP id 5b1f17b1804b1-4129ed6f514so11406495e9.1 for ; Mon, 26 Feb 2024 06:02:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956143; x=1709560943; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=k6iw5i8mM5Of+bzkU8Il1nyfuL7fgtIVdKq81GmS1M0=; b=JRpXHxHAwn0QZdBRtK+Xe9WKYEi17R16y3FhXqTfpUN4IIokc/Q29nfsitmS+hnhkE fBwDgQvlccJhJCgZPU9/GuAUsNcWD5/bkDrfEp00PQM9DvkyB8Ei8QDZ65uPXHGWyeUB nqcHUimFN+GCSJYv5zMHzJ1Sz7flpNftaSPwlonBJ/QqKiTaFUUVyvqEKkDksuqhwxzo WmUx37g/p0QCkARhAxMUBy9v95xO1z0AAEPPOCezZIb85TvJW/0rqGGe895elhxhgp1R +KJnaAR8hgmfrhmiBlqDH9mFkrVFcSVGX8YD0c9Ri4xIj2D3lMfdqz+1WUHn6vmo3Sdp wq0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956143; x=1709560943; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=k6iw5i8mM5Of+bzkU8Il1nyfuL7fgtIVdKq81GmS1M0=; b=a730Q2t463gPKwgSA/81baQksXXU9YLzIhYwtCSAZv1o8xR2Ix+oTVWVuh2PjFaDX/ T5lLA0zmMMIPfYCum3jQ8P9lIoxn8x+kpK2M+JM1qoN19V8ts6pJQn0P+wkhz+ANwKv3 5eOQRkmdgM4XDu0296Bdqi3MKMkp57vAmR/QjjbMqPgeB9d53myK5pY341I78J18fJZ/ sUv4pjqSFDB43YBogDogEYP73jy6npyymANb5vCdF7L5bcxGQk215i/+68V3cUCC3VV5 7m8dXi32+mqtPgWdIrpNrynOtHyFwwUzrZWDWvQt+dE7rtEcndNbDfYwMDFJGhPtr562 hJqQ== X-Forwarded-Encrypted: i=1; AJvYcCU1pyK5mmgT74Wit51l2EAY9mtLrWsYBEcy4zISYLxKIostL+oZZriQl9Rh5n95YvajqGqzApj3PvoXF2cOHjbWEddCoARoJEXilhI= X-Gm-Message-State: AOJu0YycjsKNHHy3JXh1mON0tIlkNsL0qHheocHwn8beNERgemddCzDT qo1VxXo3v3Z02XcbOo9lBqCiocvqMl01BxX4W3SuvJhyZ5Iz2b5N11cnI4gVni8= X-Google-Smtp-Source: AGHT+IHkvR9ZUclyEEJ0ejvL7o/nRoAN9Jmk3yQWRUJ6eg+W8O7NTFCmrst76LLu8wh9p9m5DRBtug== X-Received: by 2002:a05:600c:4ece:b0:412:a20c:dd6f with SMTP id g14-20020a05600c4ece00b00412a20cdd6fmr3113816wmq.1.1708956142639; Mon, 26 Feb 2024 06:02:22 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:22 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:49 +0100 Subject: [PATCH 11/18] ASoC: mediatek: mt8365: Add platform driver Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-11-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=74542; i=amergnat@baylibre.com; h=from:subject:message-id; bh=DUfIVA0hQOxiGtkvvTZJpZoPeoD/Qsx4aX+oLcdc5cM=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncMVurgbU519rWYVXdMtMA6u+saxVoApCD/Env aaKelwiJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURTEMD/ 9CRu/0mEBzWFDRZKWVHuw5KtL4jrAVJUMf21zXNxXxwSypJCCnqekffvFDv3AFTl/KbQQImFIHrdsZ PB+jhnO6Uw51xTllvSSXXo7MsMRsa73mQl3YGDoQSOrSHyMtTNPajoiW8glgEyIbxPLRcPmdQCcd0X 76mh9lxmz4WdYD9WkO0PGG93C0Hzrqfl7aNs0H+FXOfjnGsHdHAiq2EJua+9GyKtGRUNhL4F2RnVxS NMBkPko+yriF1/pGouzrMN5kCmxfTrvBfdiG1toUD/hHMMH5faPuqxxWOBAe/ilZ1fBi4R8xkMoe1D Xu5s3xoxI7n64nq0/tR3annhM4Xj9dg7kJtPhJ3mgq6SRffeZ1VszxWSitdyXoUIIA33CvCTP6Nwwm 11qAxYAPtho8YuFQVKm2f0tNjDPLNBTpA/3nAMKocibwMEW3cu+HqPIkmYrZvCxyg6BMfKVDRtqsZy hqUikrBUG3jbMG23bkxyEgGiq3CNcuVCpigGy0ZKwGMr7zwbFLh3d70wf0iVdeCFze/r6q9BHca5es sK5H6o/3/1eCL7BTA/umPCPRw++QrJDEX3hBs8ZBXXWlnt1pNuR9/HhesRLvaNIUaTPBeJifhnU1Lt ty9B3mLg7mZcX76tSKaxLszhm3lT4o1dbnYm42W4xYZsAjLqdkHCr0/cTRWg== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add mt8365 platform driver. Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/mt8365/mt8365-afe-pcm.c | 2347 ++++++++++++++++++++++++++++ 1 file changed, 2347 insertions(+) diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c new file mode 100644 index 000000000000..16592f9ec3ec --- /dev/null +++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c @@ -0,0 +1,2347 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Mediatek 8365 ALSA SoC AFE platform driver + * + * Copyright (c) 2024 MediaTek Inc. + * Authors: Jia Zeng + * Alexandre Mergnat + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt8365-afe-common.h" +#include "mt8365-afe-clk.h" +#include "mt8365-reg.h" +#include "../common/mtk-base-afe.h" +#include "../common/mtk-afe-platform-driver.h" +#include "../common/mtk-afe-fe-dai.h" + +#define AFE_BASE_END_OFFSET 8 + +static unsigned int mCM2Input; + +static const unsigned int mt8365_afe_backup_list[] = { + AUDIO_TOP_CON0, + AFE_CONN0, + AFE_CONN1, + AFE_CONN3, + AFE_CONN4, + AFE_CONN5, + AFE_CONN6, + AFE_CONN7, + AFE_CONN8, + AFE_CONN9, + AFE_CONN10, + AFE_CONN11, + AFE_CONN12, + AFE_CONN13, + AFE_CONN14, + AFE_CONN15, + AFE_CONN16, + AFE_CONN17, + AFE_CONN18, + AFE_CONN19, + AFE_CONN20, + AFE_CONN21, + AFE_CONN26, + AFE_CONN27, + AFE_CONN28, + AFE_CONN29, + AFE_CONN30, + AFE_CONN31, + AFE_CONN32, + AFE_CONN33, + AFE_CONN34, + AFE_CONN35, + AFE_CONN36, + AFE_CONN_24BIT, + AFE_CONN_24BIT_1, + AFE_DAC_CON0, + AFE_DAC_CON1, + AFE_DL1_BASE, + AFE_DL1_END, + AFE_DL2_BASE, + AFE_DL2_END, + AFE_VUL_BASE, + AFE_VUL_END, + AFE_AWB_BASE, + AFE_AWB_END, + AFE_VUL3_BASE, + AFE_VUL3_END, + AFE_HDMI_OUT_BASE, + AFE_HDMI_OUT_END, + AFE_HDMI_IN_2CH_BASE, + AFE_HDMI_IN_2CH_END, + AFE_ADDA_UL_DL_CON0, + AFE_ADDA_DL_SRC2_CON0, + AFE_ADDA_DL_SRC2_CON1, + AFE_I2S_CON, + AFE_I2S_CON1, + AFE_I2S_CON2, + AFE_I2S_CON3, + AFE_ADDA_UL_SRC_CON0, + AFE_AUD_PAD_TOP, + AFE_HD_ENGEN_ENABLE, +}; + +static const struct snd_pcm_hardware mt8365_afe_hardware = { + .info = (SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID), + .buffer_bytes_max = 256 * 1024, + .period_bytes_min = 512, + .period_bytes_max = 128 * 1024, + .periods_min = 2, + .periods_max = 256, + .fifo_size = 0, +}; + +struct mt8365_afe_rate { + unsigned int rate; + unsigned int reg_val; +}; + +static const struct mt8365_afe_rate mt8365_afe_fs_rates[] = { + { .rate = 8000, .reg_val = MT8365_FS_8K }, + { .rate = 11025, .reg_val = MT8365_FS_11D025K }, + { .rate = 12000, .reg_val = MT8365_FS_12K }, + { .rate = 16000, .reg_val = MT8365_FS_16K }, + { .rate = 22050, .reg_val = MT8365_FS_22D05K }, + { .rate = 24000, .reg_val = MT8365_FS_24K }, + { .rate = 32000, .reg_val = MT8365_FS_32K }, + { .rate = 44100, .reg_val = MT8365_FS_44D1K }, + { .rate = 48000, .reg_val = MT8365_FS_48K }, + { .rate = 88200, .reg_val = MT8365_FS_88D2K }, + { .rate = 96000, .reg_val = MT8365_FS_96K }, + { .rate = 176400, .reg_val = MT8365_FS_176D4K }, + { .rate = 192000, .reg_val = MT8365_FS_192K }, +}; + +int mt8365_afe_fs_timing(unsigned int rate) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(mt8365_afe_fs_rates); i++) + if (mt8365_afe_fs_rates[i].rate == rate) + return mt8365_afe_fs_rates[i].reg_val; + + return -EINVAL; +} + +bool mt8365_afe_rate_supported(unsigned int rate, unsigned int id) +{ + switch (id) { + case MT8365_AFE_IO_TDM_IN: + if (rate >= 8000 && rate <= 192000) + return true; + break; + case MT8365_AFE_IO_DMIC: + if (rate >= 8000 && rate <= 48000) + return true; + break; + default: + break; + } + + return false; +} + +bool mt8365_afe_channel_supported(unsigned int channel, unsigned int id) +{ + switch (id) { + case MT8365_AFE_IO_TDM_IN: + if (channel >= 1 && channel <= 8) + return true; + break; + case MT8365_AFE_IO_DMIC: + if (channel >= 1 && channel <= 8) + return true; + break; + default: + break; + } + + return false; +} + +bool mt8365_afe_clk_group_44k(int sample_rate) +{ + if ((sample_rate == 11025) + || (sample_rate == 22050) + || (sample_rate == 44100) + || (sample_rate == 88200) + || (sample_rate == 176400)) + return true; + else + return false; +} + +bool mt8365_afe_clk_group_48k(int sample_rate) +{ + return (!mt8365_afe_clk_group_44k(sample_rate)); +} + +int mt8365_dai_set_priv(struct mtk_base_afe *afe, int id, + int priv_size, const void *priv_data) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + void *temp_data; + + temp_data = devm_kzalloc(afe->dev, + priv_size, + GFP_KERNEL); + if (!temp_data) + return -ENOMEM; + + if (priv_data) + memcpy(temp_data, priv_data, priv_size); + + afe_priv->dai_priv[id] = temp_data; + + return 0; +} + +static int mt8365_afe_irq_direction_enable(struct mtk_base_afe *afe, + int irq_id, + int direction) +{ + struct mtk_base_afe_irq *irq; + + if (irq_id >= MT8365_AFE_IRQ_NUM) + return -1; + + irq = &afe->irqs[irq_id]; + + if (direction == MT8365_AFE_IRQ_DIR_MCU) { + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN, + (1 << irq->irq_data->irq_clr_shift), + 0); + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, + (1 << irq->irq_data->irq_clr_shift), + (1 << irq->irq_data->irq_clr_shift)); + } else if (direction == MT8365_AFE_IRQ_DIR_DSP) { + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN, + (1 << irq->irq_data->irq_clr_shift), + (1 << irq->irq_data->irq_clr_shift)); + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, + (1 << irq->irq_data->irq_clr_shift), + 0); + } else { + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_DSP_EN, + (1 << irq->irq_data->irq_clr_shift), + (1 << irq->irq_data->irq_clr_shift)); + regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, + (1 << irq->irq_data->irq_clr_shift), + (1 << irq->irq_data->irq_clr_shift)); + } + return 0; +} + +static int mt8365_memif_fs(struct snd_pcm_substream *substream, + unsigned int rate) +{ + return mt8365_afe_fs_timing(rate); +} + +static int mt8365_irq_fs(struct snd_pcm_substream *substream, + unsigned int rate) +{ + return mt8365_memif_fs(substream, rate); +} + +static const struct mt8365_cm_ctrl_reg cm_ctrl_reg[MT8365_CM_NUM] = { + [MT8365_CM1] = { + .con0 = AFE_CM1_CON0, + .con1 = AFE_CM1_CON1, + .con2 = AFE_CM1_CON2, + .con3 = AFE_CM1_CON3, + .con4 = AFE_CM1_CON4, + }, + [MT8365_CM2] = { + .con0 = AFE_CM2_CON0, + .con1 = AFE_CM2_CON1, + .con2 = AFE_CM2_CON2, + .con3 = AFE_CM2_CON3, + .con4 = AFE_CM2_CON4, + } +}; + +static int mt8365_afe_cm2_mux_conn(struct mtk_base_afe *afe) +{ + struct mt8365_afe_private *afe_priv = afe->platform_priv; + unsigned int input = afe_priv->cm2_mux_input; + + dev_dbg(afe->dev, "%s input %d\n", __func__, input); + + /* TDM_IN interconnect to CM2 */ + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG1_MASK, + CM2_AFE_CM2_CONN_CFG1(TDM_IN_CH0)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG2_MASK, + CM2_AFE_CM2_CONN_CFG2(TDM_IN_CH1)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG3_MASK, + CM2_AFE_CM2_CONN_CFG3(TDM_IN_CH2)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG4_MASK, + CM2_AFE_CM2_CONN_CFG4(TDM_IN_CH3)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG5_MASK, + CM2_AFE_CM2_CONN_CFG5(TDM_IN_CH4)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN0, + CM2_AFE_CM2_CONN_CFG6_MASK, + CM2_AFE_CM2_CONN_CFG6(TDM_IN_CH5)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG7_MASK, + CM2_AFE_CM2_CONN_CFG7(TDM_IN_CH6)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG8_MASK, + CM2_AFE_CM2_CONN_CFG8(TDM_IN_CH7)); + + /* ref data interconnect to CM2 */ + if (input == MT8365_FROM_GASRC1) { + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG9_MASK, + CM2_AFE_CM2_CONN_CFG9(GENERAL1_ASRC_OUT_LCH)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG10_MASK, + CM2_AFE_CM2_CONN_CFG10(GENERAL1_ASRC_OUT_RCH)); + } else if (input == MT8365_FROM_GASRC2) { + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG9_MASK, + CM2_AFE_CM2_CONN_CFG9(GENERAL2_ASRC_OUT_LCH)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG10_MASK, + CM2_AFE_CM2_CONN_CFG10(GENERAL2_ASRC_OUT_RCH)); + } else if (input == MT8365_FROM_TDM_ASRC) { + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG9_MASK, + CM2_AFE_CM2_CONN_CFG9(TDM_OUT_ASRC_CH0)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG10_MASK, + CM2_AFE_CM2_CONN_CFG10(TDM_OUT_ASRC_CH1)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG11_MASK, + CM2_AFE_CM2_CONN_CFG11(TDM_OUT_ASRC_CH2)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN1, + CM2_AFE_CM2_CONN_CFG12_MASK, + CM2_AFE_CM2_CONN_CFG12(TDM_OUT_ASRC_CH3)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN2, + CM2_AFE_CM2_CONN_CFG13_MASK, + CM2_AFE_CM2_CONN_CFG13(TDM_OUT_ASRC_CH4)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN2, + CM2_AFE_CM2_CONN_CFG14_MASK, + CM2_AFE_CM2_CONN_CFG14(TDM_OUT_ASRC_CH5)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN2, + CM2_AFE_CM2_CONN_CFG15_MASK, + CM2_AFE_CM2_CONN_CFG15(TDM_OUT_ASRC_CH6)); + regmap_update_bits(afe->regmap, AFE_CM2_CONN2, + CM2_AFE_CM2_CONN_CFG16_MASK, + CM2_AFE_CM2_CONN_CFG16(TDM_OUT_ASRC_CH7)); + } else { + dev_dbg(afe->dev, "%s wrong CM2 input %d\n", + __func__, input); + return -1; + } + + return 0; +} + +static int mt8365_afe_get_cm_update_cnt(struct mtk_base_afe *afe, + enum mt8365_cm_num cmNum, unsigned int rate, unsigned int channel) +{ + + /* calculate cm update cnt */ + /* total_cnt = clk / fs, clk is 26m or 24m or 22m*/ + /* div_cnt = total_cnt / ch_pair, max ch 16ch ,2ch is a set */ + /* best_cnt < div_cnt ,we set best_cnt = div_cnt -10 */ + /* ch01 = best_cnt, ch23 = 2* ch01_up_cnt */ + /* ch45 = 3* ch01_up_cnt ...ch1415 = 8* ch01_up_cnt */ + + unsigned int total_cnt, div_cnt, ch_pair, best_cnt; + unsigned int ch_update_cnt[MT8365_CM_UPDATA_CNT_SET]; + int i; + + if (cmNum == MT8365_CM1) { + total_cnt = MT8365_CLK_26M / rate; + } else if (cmNum == MT8365_CM2) { + if (mt8365_afe_clk_group_48k(rate)) + total_cnt = MT8365_CLK_24M / rate; + else + total_cnt = MT8365_CLK_22M / rate; + } else { + dev_dbg(afe->dev, "%s wrong cmNum %d\n", + __func__, cmNum); + return -1; + } + + if (channel % 2) + ch_pair = (channel / 2) + 1; + else + ch_pair = channel / 2; + + div_cnt = total_cnt / ch_pair; + best_cnt = div_cnt - 10; + + if (best_cnt <= 0) { + dev_dbg(afe->dev, "%s wrong best_cnt %d\n", + __func__, best_cnt); + return -1; + } + + for (i = 0; i < ch_pair; i++) + ch_update_cnt[i] = (i + 1) * best_cnt; + + dev_dbg(afe->dev, "%s channel %d ch_pair %d\n", + __func__, channel, ch_pair); + + switch (channel) { + case 16: + fallthrough; + case 15: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4, + CM_AFE_CM_UPDATE_CNT2_MASK, + CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[7])); + fallthrough; + case 14: + fallthrough; + case 13: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con4, + CM_AFE_CM_UPDATE_CNT1_MASK, + CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[6])); + fallthrough; + case 12: + fallthrough; + case 11: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3, + CM_AFE_CM_UPDATE_CNT2_MASK, + CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[5])); + fallthrough; + case 10: + fallthrough; + case 9: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con3, + CM_AFE_CM_UPDATE_CNT1_MASK, + CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[4])); + fallthrough; + case 8: + fallthrough; + case 7: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2, + CM_AFE_CM_UPDATE_CNT2_MASK, + CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[3])); + fallthrough; + case 6: + fallthrough; + case 5: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con2, + CM_AFE_CM_UPDATE_CNT1_MASK, + CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[2])); + fallthrough; + case 4: + fallthrough; + case 3: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1, + CM_AFE_CM_UPDATE_CNT2_MASK, + CM_AFE_CM_UPDATE_CNT2(ch_update_cnt[1])); + fallthrough; + case 2: + fallthrough; + case 1: + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con1, + CM_AFE_CM_UPDATE_CNT1_MASK, + CM_AFE_CM_UPDATE_CNT1(ch_update_cnt[0])); + break; + default: + return -1; + } + + return 0; +} + +static int mt8365_afe_configure_cm(struct mtk_base_afe *afe, + enum mt8365_cm_num cmNum, + unsigned int channels, + unsigned int rate) +{ + unsigned int val, mask; + unsigned int fs = mt8365_afe_fs_timing(rate); + + val = FIELD_PREP(CM_AFE_CM_CH_NUM_MASK, (channels - 1)) | + FIELD_PREP(CM_AFE_CM_START_DATA_MASK, 0); + + mask = CM_AFE_CM_CH_NUM_MASK | + CM_AFE_CM_START_DATA_MASK; + + if (cmNum == MT8365_CM1) { + val |= FIELD_PREP(CM_AFE_CM1_IN_MODE_MASK, fs); + + mask |= CM_AFE_CM1_VUL_SEL | + CM_AFE_CM1_IN_MODE_MASK; + } else if (cmNum == MT8365_CM2) { + if (mt8365_afe_clk_group_48k(rate)) + val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 0); + else + val |= FIELD_PREP(CM_AFE_CM2_CLK_SEL, 1); + + val |= FIELD_PREP(CM_AFE_CM2_TDM_SEL, 1); + + mask |= CM_AFE_CM2_TDM_SEL | + CM_AFE_CM1_IN_MODE_MASK | + CM_AFE_CM2_CLK_SEL; + + mt8365_afe_cm2_mux_conn(afe); + } else { + dev_dbg(afe->dev, "%s wrong cmNum %d\n", + __func__, cmNum); + return -1; + } + + regmap_update_bits(afe->regmap, cm_ctrl_reg[cmNum].con0, mask, val); + + mt8365_afe_get_cm_update_cnt(afe, cmNum, rate, channels); + + return 0; +} + +int mt8365_afe_fe_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct snd_pcm_runtime *runtime = substream->runtime; + int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; + const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware; + int ret; + + memif->substream = substream; + + snd_pcm_hw_constraint_step(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16); + + snd_soc_set_runtime_hwparams(substream, mtk_afe_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"); + + mt8365_afe_enable_main_clk(afe); + return ret; +} + +static void mt8365_afe_fe_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int memif_num = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[memif_num]; + + dev_dbg(afe->dev, "%s %s\n", __func__, memif->data->name); + + memif->substream = NULL; + + mt8365_afe_disable_main_clk(afe); +} + +static int mt8365_afe_fe_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data; + struct mtk_base_afe_memif *memif = &afe->memif[dai_id]; + struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id]; + const size_t request_size = params_buffer_bytes(params); + unsigned int channels = params_channels(params); + unsigned int rate = params_rate(params); + int ret, fs = 0; + unsigned int base_end_offset = 8; + + dev_info(afe->dev, + "%s %s period = %d rate = %d channels = %d\n", + __func__, memif->data->name, params_period_size(params), + rate, channels); + + if (dai_id == MT8365_AFE_MEMIF_VUL2) { + if (!ctrl_data->bypass_cm1) + /* configure cm1 */ + mt8365_afe_configure_cm(afe, + MT8365_CM1, channels, rate); + else + regmap_update_bits(afe->regmap, AFE_CM1_CON0, + CM_AFE_CM1_VUL_SEL, CM_AFE_CM1_VUL_SEL); + } else if (dai_id == MT8365_AFE_MEMIF_TDM_IN) { + if (!ctrl_data->bypass_cm2) + /* configure cm2 */ + mt8365_afe_configure_cm(afe, + MT8365_CM2, channels, rate); + else + regmap_update_bits(afe->regmap, AFE_CM2_CON0, + CM_AFE_CM2_TDM_SEL, ~CM_AFE_CM2_TDM_SEL); + + base_end_offset = 4; + } + + if (request_size > fe_data->sram_size) { + ret = snd_pcm_lib_malloc_pages(substream, request_size); + if (ret < 0) { + dev_err(afe->dev, + "%s %s malloc pages %zu bytes failed %d\n", + __func__, memif->data->name, request_size, ret); + return ret; + } + + fe_data->use_sram = false; + + mt8365_afe_emi_clk_on(afe); + } else { + struct snd_dma_buffer *dma_buf = &substream->dma_buffer; + + dma_buf->dev.type = SNDRV_DMA_TYPE_DEV; + dma_buf->dev.dev = substream->pcm->card->dev; + dma_buf->area = (unsigned char *)fe_data->sram_vir_addr; + dma_buf->addr = fe_data->sram_phy_addr; + dma_buf->bytes = request_size; + snd_pcm_set_runtime_buffer(substream, dma_buf); + + fe_data->use_sram = true; + } + + memif->phys_buf_addr = lower_32_bits(substream->runtime->dma_addr); + memif->buffer_size = substream->runtime->dma_bytes; + + /* start */ + regmap_write(afe->regmap, memif->data->reg_ofs_base, + memif->phys_buf_addr); + /* end */ + regmap_write(afe->regmap, + memif->data->reg_ofs_base + base_end_offset, + memif->phys_buf_addr + memif->buffer_size - 1); + + /* set channel */ + if (memif->data->mono_shift >= 0) { + unsigned int mono = (params_channels(params) == 1) ? 1 : 0; + + if (memif->data->mono_reg < 0) + dev_info(afe->dev, "%s mono_reg is NULL\n", __func__); + else + regmap_update_bits(afe->regmap, memif->data->mono_reg, + 1 << memif->data->mono_shift, + mono << memif->data->mono_shift); + } + + /* set rate */ + if (memif->data->fs_shift < 0) + return 0; + + fs = afe->memif_fs(substream, params_rate(params)); + + if (fs < 0) + return -EINVAL; + + if (memif->data->fs_reg < 0) + dev_info(afe->dev, "%s fs_reg is NULL\n", __func__); + else + regmap_update_bits(afe->regmap, memif->data->fs_reg, + memif->data->fs_maskbit << memif->data->fs_shift, + fs << memif->data->fs_shift); + + return 0; +} + +static int mt8365_afe_fe_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[dai_id]; + struct mt8365_fe_dai_data *fe_data = &afe_priv->fe_data[dai_id]; + int ret = 0; + + dev_dbg(afe->dev, "%s %s\n", __func__, memif->data->name); + + if (fe_data->use_sram) { + snd_pcm_set_runtime_buffer(substream, NULL); + } else { + ret = snd_pcm_lib_free_pages(substream); + + mt8365_afe_emi_clk_off(afe); + } + + return ret; +} + +static int mt8365_afe_fe_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mtk_base_afe_memif *memif = &afe->memif[dai_id]; + + /* set format */ + if (memif->data->hd_reg >= 0) { + switch (substream->runtime->format) { + case SNDRV_PCM_FORMAT_S16_LE: + regmap_update_bits(afe->regmap, memif->data->hd_reg, + 3 << memif->data->hd_shift, + 0 << memif->data->hd_shift); + break; + case SNDRV_PCM_FORMAT_S32_LE: + regmap_update_bits(afe->regmap, memif->data->hd_reg, + 3 << memif->data->hd_shift, + 3 << memif->data->hd_shift); + + if (dai_id == MT8365_AFE_MEMIF_TDM_IN) { + regmap_update_bits(afe->regmap, + memif->data->hd_reg, + 3 << memif->data->hd_shift, + 1 << memif->data->hd_shift); + regmap_update_bits(afe->regmap, + memif->data->hd_reg, + 1 << memif->data->hd_align_mshift, + 1 << memif->data->hd_align_mshift); + } + break; + case SNDRV_PCM_FORMAT_S24_LE: + regmap_update_bits(afe->regmap, memif->data->hd_reg, + 3 << memif->data->hd_shift, + 1 << memif->data->hd_shift); + break; + default: + return -EINVAL; + } + } + + mt8365_afe_irq_direction_enable(afe, + memif->irq_usage, + MT8365_AFE_IRQ_DIR_MCU); + + return 0; +} + +int mt8365_afe_fe_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + int dai_id = snd_soc_rtd_to_cpu(rtd, 0)->id; + struct mt8365_control_data *ctrl_data = &afe_priv->ctrl_data; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_RESUME: + /* enable channel merge */ + if (dai_id == MT8365_AFE_MEMIF_VUL2 && + !ctrl_data->bypass_cm1) { + regmap_update_bits(afe->regmap, + AFE_CM1_CON0, + CM_AFE_CM_ON, CM_AFE_CM_ON); + } else if (dai_id == MT8365_AFE_MEMIF_TDM_IN && + !ctrl_data->bypass_cm2) { + regmap_update_bits(afe->regmap, + AFE_CM2_CON0, + CM_AFE_CM_ON, CM_AFE_CM_ON); + } + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_SUSPEND: + /* disable channel merge */ + if (dai_id == MT8365_AFE_MEMIF_VUL2 && + !ctrl_data->bypass_cm1) { + regmap_update_bits(afe->regmap, + AFE_CM1_CON0, + CM_AFE_CM_ON, ~CM_AFE_CM_ON); + } else if (dai_id == MT8365_AFE_MEMIF_TDM_IN && + !ctrl_data->bypass_cm2) { + regmap_update_bits(afe->regmap, + AFE_CM2_CON0, + CM_AFE_CM_ON, ~CM_AFE_CM_ON); + } + break; + default: + break; + } + + return mtk_afe_fe_trigger(substream, cmd, dai); +} + +static int mt8365_afe_hw_gain1_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + + mt8365_afe_enable_main_clk(afe); + return 0; +} + +static void mt8365_afe_hw_gain1_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + + const unsigned int stream = substream->stream; + + if (be->prepared[stream]) { + regmap_update_bits(afe->regmap, AFE_GAIN1_CON0, + AFE_GAIN1_CON0_EN_MASK, 0); + be->prepared[stream] = false; + } + mt8365_afe_disable_main_clk(afe); +} + +static int mt8365_afe_hw_gain1_prepare(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_pcm_runtime * const runtime = substream->runtime; + struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + struct mt8365_be_dai_data *be = + &afe_priv->be_data[dai->id - MT8365_AFE_BACKEND_BASE]; + + const unsigned int rate = runtime->rate; + const unsigned int stream = substream->stream; + int fs; + unsigned int val1 = 0, val2 = 0; + + if (be->prepared[stream]) { + dev_info(afe->dev, "%s prepared already\n", __func__); + return 0; + } + + fs = mt8365_afe_fs_timing(rate); + regmap_update_bits(afe->regmap, AFE_GAIN1_CON0, + AFE_GAIN1_CON0_MODE_MASK, (unsigned int)fs<<4); + + regmap_read(afe->regmap, AFE_GAIN1_CON1, &val1); + regmap_read(afe->regmap, AFE_GAIN1_CUR, &val2); + if ((val1 & AFE_GAIN1_CON1_MASK) != (val2 & AFE_GAIN1_CUR_MASK)) + regmap_update_bits(afe->regmap, AFE_GAIN1_CUR, + AFE_GAIN1_CUR_MASK, val1); + + regmap_update_bits(afe->regmap, AFE_GAIN1_CON0, + AFE_GAIN1_CON0_EN_MASK, 1); + be->prepared[stream] = true; + + return 0; +} + +static const struct snd_pcm_hardware mt8365_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 = 8 * 48 * 1024, + .fifo_size = 0, +}; + +/* 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, &mt8365_hostless_hardware); + + ret = snd_pcm_hw_constraint_integer(runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + dev_info(afe->dev, "snd_pcm_hw_constraint_integer failed\n"); + return ret; +} + +/* FE DAIs */ +static const struct snd_soc_dai_ops mt8365_afe_fe_dai_ops = { + .startup = mt8365_afe_fe_startup, + .shutdown = mt8365_afe_fe_shutdown, + .hw_params = mt8365_afe_fe_hw_params, + .hw_free = mt8365_afe_fe_hw_free, + .prepare = mt8365_afe_fe_prepare, + .trigger = mt8365_afe_fe_trigger, +}; + +static const struct snd_soc_dai_ops mt8365_dai_hostless_ops = { + .startup = mtk_dai_hostless_startup, +}; + +static const struct snd_soc_dai_ops mt8365_afe_hw_gain1_ops = { + .startup = mt8365_afe_hw_gain1_startup, + .shutdown = mt8365_afe_hw_gain1_shutdown, + .prepare = mt8365_afe_hw_gain1_prepare, +}; + +static struct snd_soc_dai_driver mt8365_memif_dai_driver[] = { + /* FE DAIs: memory intefaces to CPU */ + { + .name = "DL1", + .id = MT8365_AFE_MEMIF_DL1, + .playback = { + .stream_name = "DL1", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "DL2", + .id = MT8365_AFE_MEMIF_DL2, + .playback = { + .stream_name = "DL2", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "TDM_OUT", + .id = MT8365_AFE_MEMIF_TDM_OUT, + .playback = { + .stream_name = "TDM_OUT", + .channels_min = 1, + .channels_max = 8, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "AWB", + .id = MT8365_AFE_MEMIF_AWB, + .capture = { + .stream_name = "AWB", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "VUL", + .id = MT8365_AFE_MEMIF_VUL, + .capture = { + .stream_name = "VUL", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "VUL2", + .id = MT8365_AFE_MEMIF_VUL2, + .capture = { + .stream_name = "VUL2", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "VUL3", + .id = MT8365_AFE_MEMIF_VUL3, + .capture = { + .stream_name = "VUL3", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "TDM_IN", + .id = MT8365_AFE_MEMIF_TDM_IN, + .capture = { + .stream_name = "TDM_IN", + .channels_min = 1, + .channels_max = 16, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_fe_dai_ops, + }, { + .name = "Hostless FM DAI", + .id = MT8365_AFE_IO_VIRTUAL_FM, + .playback = { + .stream_name = "Hostless FM DL", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "Hostless FM UL", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_dai_hostless_ops, + }, { + .name = "HW_GAIN1", + .id = MT8365_AFE_IO_HW_GAIN1, + .playback = { + .stream_name = "HW Gain 1 In", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .capture = { + .stream_name = "HW Gain 1 Out", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_8000_192000, + .formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE, + }, + .ops = &mt8365_afe_hw_gain1_ops, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + }, +}; + +static const struct snd_kcontrol_new mt8365_afe_o00_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN0, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN0, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o01_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN1, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN1, 8, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o03_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN3, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN3, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN3, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I10 Switch", AFE_CONN3, 10, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o04_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN4, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN4, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN4, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I11 Switch", AFE_CONN4, 11, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o05_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN5, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN5, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN5, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN5, 7, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN5, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN5, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN5, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN5, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN5, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN5, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I10L Switch", AFE_CONN5, 10, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o06_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN6, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN6, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN6, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN6, 8, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN6, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN6, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN6, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN6, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN6, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN6, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I11L Switch", AFE_CONN6, 11, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o07_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN7, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN7, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o08_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN8, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN8, 8, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o09_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN9, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN9, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN9, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN9, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN9, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN9, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN9, 20, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o10_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN10, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN10, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN10, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN10, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN10, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN10, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN10, 21, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o11_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN11, 0, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN11, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I09 Switch", AFE_CONN11, 9, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN11, 14, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN11, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN11, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN11, 20, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o12_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN12, 1, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN12, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I22 Switch", AFE_CONN12, 22, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN12, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN12, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN12, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN12, 21, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o13_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I00 Switch", AFE_CONN13, 0, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o14_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I01 Switch", AFE_CONN14, 1, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o15_mix[] = { +}; + +static const struct snd_kcontrol_new mt8365_afe_o16_mix[] = { +}; + +static const struct snd_kcontrol_new mt8365_afe_o17_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I03 Switch", AFE_CONN17, 3, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I14 Switch", AFE_CONN17, 14, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o18_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN18, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I15 Switch", AFE_CONN18, 15, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN18, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN18, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o19_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I04 Switch", AFE_CONN19, 4, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I16 Switch", AFE_CONN19, 16, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN19, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN19, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN19, 25, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN19, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o20_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN20, 17, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN20, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN20, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o21_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN21, 18, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN21, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN21, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o22_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I19 Switch", AFE_CONN22, 19, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN22, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN22, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o23_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I20 Switch", AFE_CONN23, 20, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN23, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN23, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o24_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I21 Switch", AFE_CONN24, 21, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN24, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN24, 26, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN24, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN24, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o25_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I27 Switch", AFE_CONN25, 27, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I23 Switch", AFE_CONN25, 23, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I25 Switch", AFE_CONN25, 25, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o26_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I28 Switch", AFE_CONN26, 28, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I24 Switch", AFE_CONN26, 24, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I26 Switch", AFE_CONN26, 26, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o27_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN27, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN27, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o28_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN28, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN28, 8, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o29_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN29, 5, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I07 Switch", AFE_CONN29, 7, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o30_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN30, 6, 1, 0), + SOC_DAPM_SINGLE_AUTODISABLE("I08 Switch", AFE_CONN30, 8, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o31_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I29 Switch", AFE_CONN31, 29, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o32_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I30 Switch", AFE_CONN32, 30, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o33_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I31 Switch", AFE_CONN33, 31, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o34_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I32 Switch", AFE_CONN34_1, 0, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o35_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I33 Switch", AFE_CONN35_1, 1, 1, 0), +}; + +static const struct snd_kcontrol_new mt8365_afe_o36_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("I34 Switch", AFE_CONN36_1, 2, 1, 0), +}; + + +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch1_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH1", AFE_CONN13, + 0, 1, 0), +}; + +static const struct snd_kcontrol_new mtk_hw_gain1_in_ch2_mix[] = { + SOC_DAPM_SINGLE_AUTODISABLE("CONNSYS_I2S_CH2", AFE_CONN14, + 1, 1, 0), +}; + +static int mt8365_afe_cm2_io_input_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + ucontrol->value.integer.value[0] = mCM2Input; + + return 0; +} + +static int mt8365_afe_cm2_io_input_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct snd_soc_component *comp = snd_soc_dapm_to_component(dapm); + struct mtk_base_afe *afe = snd_soc_component_get_drvdata(comp); + struct mt8365_afe_private *afe_priv = afe->platform_priv; + int ret; + + mCM2Input = ucontrol->value.enumerated.item[0]; + + afe_priv->cm2_mux_input = mCM2Input; + ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); + + return ret; +} + +static const char * const fmhwgain_text[] = { + "OPEN", "FM_HW_GAIN_IO" +}; + +static const char * const ain_text[] = { + "INT ADC", "EXT ADC", +}; + +static const char * const vul2_in_input_text[] = { + "VUL2_IN_FROM_O17O18", "VUL2_IN_FROM_CM1", +}; + +static const char * const mt8365_afe_cm2_mux_text[] = { + "OPEN", "FROM_GASRC1_OUT", "FROM_GASRC2_OUT", "FROM_TDM_ASRC_OUT", +}; + +static SOC_ENUM_SINGLE_VIRT_DECL(fmhwgain_enum, fmhwgain_text); +static SOC_ENUM_SINGLE_DECL(ain_enum, AFE_ADDA_TOP_CON0, 0, ain_text); +static SOC_ENUM_SINGLE_VIRT_DECL(vul2_in_input_enum, vul2_in_input_text); +static SOC_ENUM_SINGLE_VIRT_DECL(mt8365_afe_cm2_mux_input_enum, + mt8365_afe_cm2_mux_text); + +static const struct snd_kcontrol_new fmhwgain_mux = + SOC_DAPM_ENUM("FM HW Gain Source", fmhwgain_enum); + +static const struct snd_kcontrol_new ain_mux = + SOC_DAPM_ENUM("AIN Source", ain_enum); + +static const struct snd_kcontrol_new vul2_in_input_mux = + SOC_DAPM_ENUM("VUL2 Input", vul2_in_input_enum); + +static const struct snd_kcontrol_new mt8365_afe_cm2_mux_input_mux = + SOC_DAPM_ENUM_EXT("CM2_MUX Source", mt8365_afe_cm2_mux_input_enum, + mt8365_afe_cm2_io_input_mux_get, + mt8365_afe_cm2_io_input_mux_put); + +static const struct snd_soc_dapm_widget mt8365_memif_widgets[] = { + /* inter-connections */ + SND_SOC_DAPM_MIXER("I00", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I01", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I03", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I04", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I07", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I08", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I05L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I06L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I07L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I08L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I09", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I10", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I11", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I10L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I11L", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I12", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I13", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I14", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I15", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I16", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I19", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I20", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I21", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I22", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I23", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I24", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I25", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I26", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I27", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I28", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I29", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I30", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I31", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I32", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I33", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("I34", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("O00", SND_SOC_NOPM, 0, 0, + mt8365_afe_o00_mix, ARRAY_SIZE(mt8365_afe_o00_mix)), + SND_SOC_DAPM_MIXER("O01", SND_SOC_NOPM, 0, 0, + mt8365_afe_o01_mix, ARRAY_SIZE(mt8365_afe_o01_mix)), + SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0, + mt8365_afe_o03_mix, ARRAY_SIZE(mt8365_afe_o03_mix)), + SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0, + mt8365_afe_o04_mix, ARRAY_SIZE(mt8365_afe_o04_mix)), + SND_SOC_DAPM_MIXER("O05", SND_SOC_NOPM, 0, 0, + mt8365_afe_o05_mix, ARRAY_SIZE(mt8365_afe_o05_mix)), + SND_SOC_DAPM_MIXER("O06", SND_SOC_NOPM, 0, 0, + mt8365_afe_o06_mix, ARRAY_SIZE(mt8365_afe_o06_mix)), + SND_SOC_DAPM_MIXER("O07", SND_SOC_NOPM, 0, 0, + mt8365_afe_o07_mix, ARRAY_SIZE(mt8365_afe_o07_mix)), + SND_SOC_DAPM_MIXER("O08", SND_SOC_NOPM, 0, 0, + mt8365_afe_o08_mix, ARRAY_SIZE(mt8365_afe_o08_mix)), + SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0, + mt8365_afe_o09_mix, ARRAY_SIZE(mt8365_afe_o09_mix)), + SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0, + mt8365_afe_o10_mix, ARRAY_SIZE(mt8365_afe_o10_mix)), + SND_SOC_DAPM_MIXER("O11", SND_SOC_NOPM, 0, 0, + mt8365_afe_o11_mix, ARRAY_SIZE(mt8365_afe_o11_mix)), + SND_SOC_DAPM_MIXER("O12", SND_SOC_NOPM, 0, 0, + mt8365_afe_o12_mix, ARRAY_SIZE(mt8365_afe_o12_mix)), + SND_SOC_DAPM_MIXER("O13", SND_SOC_NOPM, 0, 0, + mt8365_afe_o13_mix, ARRAY_SIZE(mt8365_afe_o13_mix)), + SND_SOC_DAPM_MIXER("O14", SND_SOC_NOPM, 0, 0, + mt8365_afe_o14_mix, ARRAY_SIZE(mt8365_afe_o14_mix)), + SND_SOC_DAPM_MIXER("O15", SND_SOC_NOPM, 0, 0, + mt8365_afe_o15_mix, ARRAY_SIZE(mt8365_afe_o15_mix)), + SND_SOC_DAPM_MIXER("O16", SND_SOC_NOPM, 0, 0, + mt8365_afe_o16_mix, ARRAY_SIZE(mt8365_afe_o16_mix)), + SND_SOC_DAPM_MIXER("O17", SND_SOC_NOPM, 0, 0, + mt8365_afe_o17_mix, ARRAY_SIZE(mt8365_afe_o17_mix)), + SND_SOC_DAPM_MIXER("O18", SND_SOC_NOPM, 0, 0, + mt8365_afe_o18_mix, ARRAY_SIZE(mt8365_afe_o18_mix)), + SND_SOC_DAPM_MIXER("O19", SND_SOC_NOPM, 0, 0, + mt8365_afe_o19_mix, ARRAY_SIZE(mt8365_afe_o19_mix)), + SND_SOC_DAPM_MIXER("O20", SND_SOC_NOPM, 0, 0, + mt8365_afe_o20_mix, ARRAY_SIZE(mt8365_afe_o20_mix)), + SND_SOC_DAPM_MIXER("O21", SND_SOC_NOPM, 0, 0, + mt8365_afe_o21_mix, ARRAY_SIZE(mt8365_afe_o21_mix)), + SND_SOC_DAPM_MIXER("O22", SND_SOC_NOPM, 0, 0, + mt8365_afe_o22_mix, ARRAY_SIZE(mt8365_afe_o22_mix)), + SND_SOC_DAPM_MIXER("O23", SND_SOC_NOPM, 0, 0, + mt8365_afe_o23_mix, ARRAY_SIZE(mt8365_afe_o23_mix)), + SND_SOC_DAPM_MIXER("O24", SND_SOC_NOPM, 0, 0, + mt8365_afe_o24_mix, ARRAY_SIZE(mt8365_afe_o24_mix)), + SND_SOC_DAPM_MIXER("O25", SND_SOC_NOPM, 0, 0, + mt8365_afe_o25_mix, ARRAY_SIZE(mt8365_afe_o25_mix)), + SND_SOC_DAPM_MIXER("O26", SND_SOC_NOPM, 0, 0, + mt8365_afe_o26_mix, ARRAY_SIZE(mt8365_afe_o26_mix)), + SND_SOC_DAPM_MIXER("O27", SND_SOC_NOPM, 0, 0, + mt8365_afe_o27_mix, ARRAY_SIZE(mt8365_afe_o27_mix)), + SND_SOC_DAPM_MIXER("O28", SND_SOC_NOPM, 0, 0, + mt8365_afe_o28_mix, ARRAY_SIZE(mt8365_afe_o28_mix)), + SND_SOC_DAPM_MIXER("O29", SND_SOC_NOPM, 0, 0, + mt8365_afe_o29_mix, ARRAY_SIZE(mt8365_afe_o29_mix)), + SND_SOC_DAPM_MIXER("O30", SND_SOC_NOPM, 0, 0, + mt8365_afe_o30_mix, ARRAY_SIZE(mt8365_afe_o30_mix)), + SND_SOC_DAPM_MIXER("O31", SND_SOC_NOPM, 0, 0, + mt8365_afe_o31_mix, ARRAY_SIZE(mt8365_afe_o31_mix)), + SND_SOC_DAPM_MIXER("O32", SND_SOC_NOPM, 0, 0, + mt8365_afe_o32_mix, ARRAY_SIZE(mt8365_afe_o32_mix)), + SND_SOC_DAPM_MIXER("O33", SND_SOC_NOPM, 0, 0, + mt8365_afe_o33_mix, ARRAY_SIZE(mt8365_afe_o33_mix)), + SND_SOC_DAPM_MIXER("O34", SND_SOC_NOPM, 0, 0, + mt8365_afe_o34_mix, ARRAY_SIZE(mt8365_afe_o34_mix)), + SND_SOC_DAPM_MIXER("O35", SND_SOC_NOPM, 0, 0, + mt8365_afe_o35_mix, ARRAY_SIZE(mt8365_afe_o35_mix)), + SND_SOC_DAPM_MIXER("O36", SND_SOC_NOPM, 0, 0, + mt8365_afe_o36_mix, ARRAY_SIZE(mt8365_afe_o36_mix)), + SND_SOC_DAPM_MIXER("CM2_Mux IO", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("CM1_IO", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_MIXER("O17O18", SND_SOC_NOPM, 0, 0, NULL, 0), + /* 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_INPUT("DL Source"), + + SND_SOC_DAPM_MUX("CM2_Mux_IO Input Mux", + SND_SOC_NOPM, 0, 0, &mt8365_afe_cm2_mux_input_mux), + SND_SOC_DAPM_MUX("AIN Mux", SND_SOC_NOPM, 0, 0, &ain_mux), + SND_SOC_DAPM_MUX("VUL2 Input Mux", + SND_SOC_NOPM, 0, 0, &vul2_in_input_mux), + SND_SOC_DAPM_MUX("FM HW Gain Mux", SND_SOC_NOPM, 0, 0, &fmhwgain_mux), + + SND_SOC_DAPM_INPUT("HW Gain 1 Out Endpoint"), + SND_SOC_DAPM_OUTPUT("HW Gain 1 In Endpoint"), +}; + +static const struct snd_soc_dapm_route mt8365_memif_routes[] = { + /* downlink */ + {"I00", NULL, "2ND I2S Capture"}, + {"I01", NULL, "2ND I2S Capture"}, + {"I05", NULL, "DL1"}, + {"I06", NULL, "DL1"}, + {"I07", NULL, "DL2"}, + {"I08", NULL, "DL2"}, + + {"O03", "I05 Switch", "I05"}, + {"O04", "I06 Switch", "I06"}, + {"O00", "I05 Switch", "I05"}, + {"O01", "I06 Switch", "I06"}, + {"O07", "I05 Switch", "I05"}, + {"O08", "I06 Switch", "I06"}, + {"O27", "I05 Switch", "I05"}, + {"O28", "I06 Switch", "I06"}, + {"O29", "I05 Switch", "I05"}, + {"O30", "I06 Switch", "I06"}, + + {"O03", "I07 Switch", "I07"}, + {"O04", "I08 Switch", "I08"}, + {"O00", "I07 Switch", "I07"}, + {"O01", "I08 Switch", "I08"}, + {"O07", "I07 Switch", "I07"}, + {"O08", "I08 Switch", "I08"}, + + /* uplink */ + {"AWB", NULL, "O05"}, + {"AWB", NULL, "O06"}, + {"VUL", NULL, "O09"}, + {"VUL", NULL, "O10"}, + {"VUL3", NULL, "O11"}, + {"VUL3", NULL, "O12"}, + + {"AIN Mux", "EXT ADC", "I2S Capture"}, + {"I03", NULL, "AIN Mux"}, + {"I04", NULL, "AIN Mux"}, + + {"HW_GAIN1_IN_CH1", "CONNSYS_I2S_CH1", "Hostless FM DL"}, + {"HW_GAIN1_IN_CH2", "CONNSYS_I2S_CH2", "Hostless FM DL"}, + + {"HW Gain 1 In Endpoint", NULL, "HW Gain 1 In"}, + {"HW Gain 1 Out", NULL, "HW Gain 1 Out Endpoint"}, + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH1"}, + {"HW Gain 1 In", NULL, "HW_GAIN1_IN_CH2"}, + + {"FM HW Gain Mux", "FM_HW_GAIN_IO", "HW Gain 1 Out"}, + {"Hostless FM UL", NULL, "FM HW Gain Mux"}, + {"Hostless FM UL", NULL, "FM 2ND I2S Mux"}, + + {"O05", "I05 Switch", "I05L"}, + {"O06", "I06 Switch", "I06L"}, + {"O05", "I07 Switch", "I07L"}, + {"O06", "I08 Switch", "I08L"}, + + {"O05", "I03 Switch", "I03"}, + {"O06", "I04 Switch", "I04"}, + {"O05", "I00 Switch", "I00"}, + {"O06", "I01 Switch", "I01"}, + {"O05", "I09 Switch", "I09"}, + {"O06", "I22 Switch", "I22"}, + {"O05", "I14 Switch", "I14"}, + {"O06", "I15 Switch", "I15"}, + {"O05", "I16 Switch", "I16"}, + {"O06", "I17 Switch", "I17"}, + {"O05", "I18 Switch", "I18"}, + {"O06", "I19 Switch", "I19"}, + {"O05", "I20 Switch", "I20"}, + {"O06", "I21 Switch", "I21"}, + {"O05", "I23 Switch", "I23"}, + {"O06", "I24 Switch", "I24"}, + + {"O09", "I03 Switch", "I03"}, + {"O10", "I04 Switch", "I04"}, + {"O09", "I00 Switch", "I00"}, + {"O10", "I01 Switch", "I01"}, + {"O09", "I09 Switch", "I09"}, + {"O10", "I22 Switch", "I22"}, + {"O09", "I14 Switch", "I14"}, + {"O10", "I15 Switch", "I15"}, + {"O09", "I16 Switch", "I16"}, + {"O10", "I17 Switch", "I17"}, + {"O09", "I18 Switch", "I18"}, + {"O10", "I19 Switch", "I19"}, + {"O09", "I20 Switch", "I20"}, + {"O10", "I21 Switch", "I21"}, + + {"O11", "I03 Switch", "I03"}, + {"O12", "I04 Switch", "I04"}, + {"O11", "I00 Switch", "I00"}, + {"O12", "I01 Switch", "I01"}, + {"O11", "I09 Switch", "I09"}, + {"O12", "I22 Switch", "I22"}, + {"O11", "I14 Switch", "I14"}, + {"O12", "I15 Switch", "I15"}, + {"O11", "I16 Switch", "I16"}, + {"O12", "I17 Switch", "I17"}, + {"O11", "I18 Switch", "I18"}, + {"O12", "I19 Switch", "I19"}, + {"O11", "I20 Switch", "I20"}, + {"O12", "I21 Switch", "I21"}, + + /* CM2_Mux*/ + {"CM2_Mux IO", NULL, "CM2_Mux_IO Input Mux"}, + + /* VUL2 */ + {"VUL2", NULL, "VUL2 Input Mux"}, + {"VUL2 Input Mux", "VUL2_IN_FROM_O17O18", "O17O18"}, + {"VUL2 Input Mux", "VUL2_IN_FROM_CM1", "CM1_IO"}, + + {"O17O18", NULL, "O17"}, + {"O17O18", NULL, "O18"}, + {"CM1_IO", NULL, "O17"}, + {"CM1_IO", NULL, "O18"}, + {"CM1_IO", NULL, "O19"}, + {"CM1_IO", NULL, "O20"}, + {"CM1_IO", NULL, "O21"}, + {"CM1_IO", NULL, "O22"}, + {"CM1_IO", NULL, "O23"}, + {"CM1_IO", NULL, "O24"}, + {"CM1_IO", NULL, "O25"}, + {"CM1_IO", NULL, "O26"}, + {"CM1_IO", NULL, "O31"}, + {"CM1_IO", NULL, "O32"}, + {"CM1_IO", NULL, "O33"}, + {"CM1_IO", NULL, "O34"}, + {"CM1_IO", NULL, "O35"}, + {"CM1_IO", NULL, "O36"}, + + {"O17", "I14 Switch", "I14"}, + {"O18", "I15 Switch", "I15"}, + {"O19", "I16 Switch", "I16"}, + {"O20", "I17 Switch", "I17"}, + {"O21", "I18 Switch", "I18"}, + {"O22", "I19 Switch", "I19"}, + {"O23", "I20 Switch", "I20"}, + {"O24", "I21 Switch", "I21"}, + {"O25", "I23 Switch", "I23"}, + {"O26", "I24 Switch", "I24"}, + {"O25", "I25 Switch", "I25"}, + {"O26", "I26 Switch", "I26"}, + + {"O17", "I03 Switch", "I03"}, + {"O18", "I04 Switch", "I04"}, + {"O18", "I23 Switch", "I23"}, + {"O18", "I25 Switch", "I25"}, + {"O19", "I04 Switch", "I04"}, + {"O19", "I23 Switch", "I23"}, + {"O19", "I24 Switch", "I24"}, + {"O19", "I25 Switch", "I25"}, + {"O19", "I26 Switch", "I26"}, + {"O20", "I24 Switch", "I24"}, + {"O20", "I26 Switch", "I26"}, + {"O21", "I23 Switch", "I23"}, + {"O21", "I25 Switch", "I25"}, + {"O22", "I24 Switch", "I24"}, + {"O22", "I26 Switch", "I26"}, + + {"O23", "I23 Switch", "I23"}, + {"O23", "I25 Switch", "I25"}, + {"O24", "I24 Switch", "I24"}, + {"O24", "I26 Switch", "I26"}, + {"O24", "I23 Switch", "I23"}, + {"O24", "I25 Switch", "I25"}, + {"O13", "I00 Switch", "I00"}, + {"O14", "I01 Switch", "I01"}, + {"O03", "I10 Switch", "I10"}, + {"O04", "I11 Switch", "I11"}, +}; + +static const struct mtk_base_memif_data memif_data[MT8365_AFE_MEMIF_NUM] = { + { + .name = "DL1", + .id = MT8365_AFE_MEMIF_DL1, + .reg_ofs_base = AFE_DL1_BASE, + .reg_ofs_cur = AFE_DL1_CUR, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 0, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 21, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 16, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 1, + .msb_reg = -1, + .msb_shift = -1, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "DL2", + .id = MT8365_AFE_MEMIF_DL2, + .reg_ofs_base = AFE_DL2_BASE, + .reg_ofs_cur = AFE_DL2_CUR, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 4, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 22, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 18, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 2, + .msb_reg = -1, + .msb_shift = -1, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "TDM OUT", + .id = MT8365_AFE_MEMIF_TDM_OUT, + .reg_ofs_base = AFE_HDMI_OUT_BASE, + .reg_ofs_cur = AFE_HDMI_OUT_CUR, + .fs_reg = -1, + .fs_shift = -1, + .fs_maskbit = -1, + .mono_reg = -1, + .mono_shift = -1, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 28, + .enable_reg = AFE_HDMI_OUT_CON0, + .enable_shift = 0, + .msb_reg = -1, + .msb_shift = -1, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "AWB", + .id = MT8365_AFE_MEMIF_AWB, + .reg_ofs_base = AFE_AWB_BASE, + .reg_ofs_cur = AFE_AWB_CUR, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 12, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 24, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 20, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 6, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 17, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "VUL", + .id = MT8365_AFE_MEMIF_VUL, + .reg_ofs_base = AFE_VUL_BASE, + .reg_ofs_cur = AFE_VUL_CUR, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 16, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON1, + .mono_shift = 27, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 22, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 3, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 20, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "VUL2", + .id = MT8365_AFE_MEMIF_VUL2, + .reg_ofs_base = AFE_VUL_D2_BASE, + .reg_ofs_cur = AFE_VUL_D2_CUR, + .fs_reg = AFE_DAC_CON0, + .fs_shift = 20, + .fs_maskbit = 0xf, + .mono_reg = -1, + .mono_shift = -1, + .hd_reg = AFE_MEMIF_PBUF_SIZE, + .hd_shift = 14, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 9, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 21, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "VUL3", + .id = MT8365_AFE_MEMIF_VUL3, + .reg_ofs_base = AFE_VUL3_BASE, + .reg_ofs_cur = AFE_VUL3_CUR, + .fs_reg = AFE_DAC_CON1, + .fs_shift = 8, + .fs_maskbit = 0xf, + .mono_reg = AFE_DAC_CON0, + .mono_shift = 13, + .hd_reg = AFE_MEMIF_PBUF2_SIZE, + .hd_shift = 10, + .enable_reg = AFE_DAC_CON0, + .enable_shift = 12, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 27, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, { + .name = "TDM IN", + .id = MT8365_AFE_MEMIF_TDM_IN, + .reg_ofs_base = AFE_HDMI_IN_2CH_BASE, + .reg_ofs_cur = AFE_HDMI_IN_2CH_CUR, + .fs_reg = -1, + .fs_shift = -1, + .fs_maskbit = -1, + .mono_reg = AFE_HDMI_IN_2CH_CON0, + .mono_shift = 1, + .hd_reg = AFE_MEMIF_PBUF2_SIZE, + .hd_shift = 8, + .hd_align_mshift = 5, + .enable_reg = AFE_HDMI_IN_2CH_CON0, + .enable_shift = 0, + .msb_reg = AFE_MEMIF_MSB, + .msb_shift = 28, + .agent_disable_reg = -1, + .agent_disable_shift = -1, + }, +}; + +static const struct mtk_base_irq_data irq_data[MT8365_AFE_IRQ_NUM] = { + { + .id = MT8365_AFE_IRQ1, + .irq_cnt_reg = AFE_IRQ_MCU_CNT1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 0, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 4, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 0, + }, { + .id = MT8365_AFE_IRQ2, + .irq_cnt_reg = AFE_IRQ_MCU_CNT2, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 1, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 8, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 1, + }, { + .id = MT8365_AFE_IRQ3, + .irq_cnt_reg = AFE_IRQ_MCU_CNT3, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 2, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 16, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 2, + }, { + .id = MT8365_AFE_IRQ4, + .irq_cnt_reg = AFE_IRQ_MCU_CNT4, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 3, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 20, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 3, + }, { + .id = MT8365_AFE_IRQ5, + .irq_cnt_reg = AFE_IRQ_MCU_CNT5, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON2, + .irq_en_shift = 3, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0x0, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 4, + }, { + .id = MT8365_AFE_IRQ6, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x0, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 13, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0x0, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 5, + }, { + .id = MT8365_AFE_IRQ7, + .irq_cnt_reg = AFE_IRQ_MCU_CNT7, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 14, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 24, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 6, + }, { + .id = MT8365_AFE_IRQ8, + .irq_cnt_reg = AFE_IRQ_MCU_CNT8, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON, + .irq_en_shift = 15, + .irq_fs_reg = AFE_IRQ_MCU_CON, + .irq_fs_shift = 28, + .irq_fs_maskbit = 0xf, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 7, + }, { + .id = MT8365_AFE_IRQ9, + .irq_cnt_reg = -1, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x0, + .irq_en_reg = AFE_IRQ_MCU_CON2, + .irq_en_shift = 2, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0x0, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 8, + }, { + .id = MT8365_AFE_IRQ10, + .irq_cnt_reg = AFE_IRQ_MCU_CNT10, + .irq_cnt_shift = 0, + .irq_cnt_maskbit = 0x3ffff, + .irq_en_reg = AFE_IRQ_MCU_CON2, + .irq_en_shift = 4, + .irq_fs_reg = -1, + .irq_fs_shift = 0, + .irq_fs_maskbit = 0x0, + .irq_clr_reg = AFE_IRQ_MCU_CLR, + .irq_clr_shift = 9, + }, +}; + +static int memif_specified_irqs[MT8365_AFE_MEMIF_NUM] = { + [MT8365_AFE_MEMIF_DL1] = MT8365_AFE_IRQ1, + [MT8365_AFE_MEMIF_DL2] = MT8365_AFE_IRQ2, + [MT8365_AFE_MEMIF_TDM_OUT] = MT8365_AFE_IRQ5, + [MT8365_AFE_MEMIF_AWB] = MT8365_AFE_IRQ3, + [MT8365_AFE_MEMIF_VUL] = MT8365_AFE_IRQ4, + [MT8365_AFE_MEMIF_VUL2] = MT8365_AFE_IRQ7, + [MT8365_AFE_MEMIF_VUL3] = MT8365_AFE_IRQ8, + [MT8365_AFE_MEMIF_TDM_IN] = MT8365_AFE_IRQ10, +}; + +static const struct regmap_config mt8365_afe_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = MAX_REGISTER, + .cache_type = REGCACHE_NONE, +}; + +static irqreturn_t mt8365_afe_irq_handler(int irq, void *dev_id) +{ + struct mtk_base_afe *afe = dev_id; + unsigned int reg_value; + unsigned int mcu_irq_mask; + int i, ret; + + ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, ®_value); + if (ret) { + dev_err(afe->dev, "%s irq status err\n", __func__); + reg_value = AFE_IRQ_STATUS_BITS; + goto err_irq; + } + + ret = regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_irq_mask); + if (ret) { + dev_err(afe->dev, "%s irq mcu_en err\n", __func__); + reg_value = AFE_IRQ_STATUS_BITS; + goto err_irq; + } + + /* only clr cpu irq */ + reg_value &= mcu_irq_mask; + + for (i = 0; i < MT8365_AFE_MEMIF_NUM; i++) { + struct mtk_base_afe_memif *memif = &afe->memif[i]; + struct mtk_base_afe_irq *mcu_irq; + + if (memif->irq_usage < 0) + continue; + + mcu_irq = &afe->irqs[memif->irq_usage]; + + if (!(reg_value & (1 << mcu_irq->irq_data->irq_clr_shift))) + continue; + + snd_pcm_period_elapsed(memif->substream); + } + +err_irq: + /* clear irq */ + regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, + reg_value & AFE_IRQ_STATUS_BITS); + + return IRQ_HANDLED; +} + +static int __maybe_unused mt8365_afe_runtime_suspend(struct device *dev) +{ + return 0; +} + +static int mt8365_afe_runtime_resume(struct device *dev) +{ + return 0; +} + +static int __maybe_unused mt8365_afe_suspend(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + struct regmap *regmap = afe->regmap; + int i; + + mt8365_afe_enable_main_clk(afe); + + if (!afe->reg_back_up) + afe->reg_back_up = + devm_kcalloc(dev, afe->reg_back_up_list_num, + sizeof(unsigned int), GFP_KERNEL); + + for (i = 0; i < afe->reg_back_up_list_num; i++) + regmap_read(regmap, afe->reg_back_up_list[i], + &afe->reg_back_up[i]); + + mt8365_afe_disable_main_clk(afe); + + return 0; +} + +static int __maybe_unused mt8365_afe_resume(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + struct regmap *regmap = afe->regmap; + int i = 0; + + if (!afe->reg_back_up) { + dev_dbg(dev, "%s no reg_backup\n", __func__); + return 0; + } + + mt8365_afe_enable_main_clk(afe); + + for (i = 0; i < afe->reg_back_up_list_num; i++) + regmap_write(regmap, afe->reg_back_up_list[i], + afe->reg_back_up[i]); + + mt8365_afe_disable_main_clk(afe); + + return 0; +} + +static int __maybe_unused mt8365_afe_dev_runtime_suspend(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + + dev_dbg(afe->dev, "%s suspend %d %d >>\n", __func__, + pm_runtime_status_suspended(dev), afe->suspended); + + if (pm_runtime_status_suspended(dev) || afe->suspended) + return 0; + + mt8365_afe_suspend(dev); + + afe->suspended = true; + + dev_dbg(afe->dev, "%s <<\n", __func__); + + return 0; +} + +static int __maybe_unused mt8365_afe_dev_runtime_resume(struct device *dev) +{ + struct mtk_base_afe *afe = dev_get_drvdata(dev); + + dev_dbg(afe->dev, "%s suspend %d %d >>\n", __func__, + pm_runtime_status_suspended(dev), afe->suspended); + + if (pm_runtime_status_suspended(dev) || !afe->suspended) + return 0; + + mt8365_afe_resume(dev); + + afe->suspended = false; + + dev_dbg(afe->dev, "%s <<\n", __func__); + + return 0; +} + +static int mt8365_afe_init_registers(struct mtk_base_afe *afe) +{ + size_t i; + + static struct { + unsigned int reg; + unsigned int mask; + unsigned int val; + } init_regs[] = { + { AFE_CONN_24BIT, GENMASK(31, 0), GENMASK(31, 0) }, + { AFE_CONN_24BIT_1, GENMASK(21, 0), GENMASK(21, 0) }, + }; + + mt8365_afe_enable_main_clk(afe); + + for (i = 0; i < ARRAY_SIZE(init_regs); i++) + regmap_update_bits(afe->regmap, init_regs[i].reg, + init_regs[i].mask, init_regs[i].val); + + mt8365_afe_disable_main_clk(afe); + + return 0; +} + +static int mt8365_afe_component_probe(struct snd_soc_component *component) +{ + return mtk_afe_add_sub_dai_control(component); +} + +static const struct snd_soc_component_driver mt8365_afe_component = { + .name = AFE_PCM_NAME, + .probe = mt8365_afe_component_probe, + .pointer = mtk_afe_pcm_pointer, + .pcm_construct = mtk_afe_pcm_new, +}; + +static const struct snd_soc_component_driver mt8365_afe_pcm_component = { + .name = "mt8365-afe-pcm-dai", +}; + +static int mt8365_dai_memif_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 = mt8365_memif_dai_driver; + dai->num_dai_drivers = ARRAY_SIZE(mt8365_memif_dai_driver); + + dai->dapm_widgets = mt8365_memif_widgets; + dai->num_dapm_widgets = ARRAY_SIZE(mt8365_memif_widgets); + dai->dapm_routes = mt8365_memif_routes; + dai->num_dapm_routes = ARRAY_SIZE(mt8365_memif_routes); + return 0; +} + +typedef int (*dai_register_cb)(struct mtk_base_afe *); +static const dai_register_cb dai_register_cbs[] = { + mt8365_dai_pcm_register, + mt8365_dai_i2s_register, + mt8365_dai_adda_register, + mt8365_dai_dmic_register, + mt8365_dai_memif_register, +}; + +static int mt8365_afe_pcm_dev_probe(struct platform_device *pdev) +{ + struct mtk_base_afe *afe; + struct mt8365_afe_private *afe_priv; + struct device *dev; + int ret, i, sel_irq; + unsigned int irq_id; + struct resource *res; + + afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL); + if (!afe) + return -ENOMEM; + platform_set_drvdata(pdev, afe); + + afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv), + GFP_KERNEL); + if (!afe->platform_priv) + return -ENOMEM; + + afe_priv = afe->platform_priv; + afe->dev = &pdev->dev; + dev = afe->dev; + + spin_lock_init(&afe_priv->afe_ctrl_lock); + mutex_init(&afe_priv->afe_clk_mutex); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + afe->base_addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(afe->base_addr)) + return PTR_ERR(afe->base_addr); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (res) { + afe_priv->afe_sram_vir_addr = + devm_ioremap_resource(&pdev->dev, res); + if (!IS_ERR(afe_priv->afe_sram_vir_addr)) { + afe_priv->afe_sram_phy_addr = res->start; + afe_priv->afe_sram_size = resource_size(res); + } + } + + /* initial audio related clock */ + ret = mt8365_afe_init_audio_clk(afe); + if (ret) { + dev_err(afe->dev, "mt8365_afe_init_audio_clk fail\n"); + return ret; + } + + afe->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "top_audio_sel", + afe->base_addr, &mt8365_afe_regmap_config); + if (IS_ERR(afe->regmap)) + return PTR_ERR(afe->regmap); + + /* memif % irq initialize*/ + afe->memif_size = MT8365_AFE_MEMIF_NUM; + afe->memif = devm_kcalloc(afe->dev, afe->memif_size, + sizeof(*afe->memif), GFP_KERNEL); + if (!afe->memif) + return -ENOMEM; + + afe->irqs_size = MT8365_AFE_IRQ_NUM; + afe->irqs = devm_kcalloc(afe->dev, afe->irqs_size, + sizeof(*afe->irqs), GFP_KERNEL); + if (!afe->irqs) + return -ENOMEM; + + for (i = 0; i < afe->irqs_size; i++) + afe->irqs[i].irq_data = &irq_data[i]; + + irq_id = platform_get_irq(pdev, 0); + if (!irq_id) { + dev_err(afe->dev, "np %s no irq\n", afe->dev->of_node->name); + return -ENXIO; + } + ret = devm_request_irq(afe->dev, irq_id, mt8365_afe_irq_handler, + 0, "Afe_ISR_Handle", (void *)afe); + if (ret) { + dev_err(afe->dev, "could not request_irq\n"); + return ret; + } + + /* init sub_dais */ + INIT_LIST_HEAD(&afe->sub_dais); + + for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) { + ret = dai_register_cbs[i](afe); + if (ret) { + dev_warn(afe->dev, "dai register i %d fail, ret %d\n", + i, ret); + return ret; + } + } + + /* init dai_driver and component_driver */ + ret = mtk_afe_combine_sub_dai(afe); + if (ret) { + dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n", + ret); + return ret; + } + + for (i = 0; i < afe->memif_size; i++) { + afe->memif[i].data = &memif_data[i]; + sel_irq = memif_specified_irqs[i]; + if (sel_irq >= 0) { + afe->memif[i].irq_usage = sel_irq; + afe->memif[i].const_irq = 1; + afe->irqs[sel_irq].irq_occupyed = true; + } else { + afe->memif[i].irq_usage = -1; + } + } + + afe->mtk_afe_hardware = &mt8365_afe_hardware; + afe->memif_fs = mt8365_memif_fs; + afe->irq_fs = mt8365_irq_fs; + + pm_runtime_enable(&pdev->dev); + + pm_runtime_get_sync(&pdev->dev); + afe->reg_back_up_list = mt8365_afe_backup_list; + afe->reg_back_up_list_num = ARRAY_SIZE(mt8365_afe_backup_list); + afe->runtime_resume = mt8365_afe_runtime_resume; + afe->runtime_suspend = mt8365_afe_runtime_suspend; + + /* open afe pdn for dapm read/write audio register */ + mt8365_afe_enable_top_cg(afe, MT8365_TOP_CG_AFE); + + /* Set 26m parent clk */ + mt8365_afe_set_clk_parent(afe, + afe_priv->clocks[MT8365_CLK_TOP_AUD_SEL], + afe_priv->clocks[MT8365_CLK_CLK26M]); + + ret = devm_snd_soc_register_component(&pdev->dev, + &mt8365_afe_component, NULL, 0); + if (ret) { + dev_warn(dev, "err_platform\n"); + return ret; + } + + ret = devm_snd_soc_register_component(&pdev->dev, + &mt8365_afe_pcm_component, + afe->dai_drivers, + afe->num_dai_drivers); + if (ret) { + dev_warn(dev, "err_dai_component\n"); + return ret; + } + + mt8365_afe_init_registers(afe); + + dev_info(&pdev->dev, "MT8365 AFE driver initialized.\n"); + + return 0; +} + +static int mt8365_afe_pcm_dev_remove(struct platform_device *pdev) +{ + struct mtk_base_afe *afe = platform_get_drvdata(pdev); + + mt8365_afe_disable_top_cg(afe, MT8365_TOP_CG_AFE); + + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + mt8365_afe_runtime_suspend(&pdev->dev); + + return 0; +} + +static const struct of_device_id mt8365_afe_pcm_dt_match[] = { + { .compatible = "mediatek,mt8365-afe-pcm", }, + { } +}; +MODULE_DEVICE_TABLE(of, mt8365_afe_pcm_dt_match); + +static const struct dev_pm_ops mt8365_afe_pm_ops = { + SET_RUNTIME_PM_OPS(mt8365_afe_dev_runtime_suspend, + mt8365_afe_dev_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(mt8365_afe_suspend, + mt8365_afe_resume) +}; + +static struct platform_driver mt8365_afe_pcm_driver = { + .driver = { + .name = "mt8365-afe-pcm", + .of_match_table = mt8365_afe_pcm_dt_match, + .pm = &mt8365_afe_pm_ops, + }, + .probe = mt8365_afe_pcm_dev_probe, + .remove = mt8365_afe_pcm_dev_remove, +}; + +module_platform_driver(mt8365_afe_pcm_driver); + +MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver"); +MODULE_AUTHOR("Jia Zeng "); +MODULE_AUTHOR("Alexandre Mergnat "); +MODULE_LICENSE("GPL"); From patchwork Mon Feb 26 14:01:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776098 Received: from mail-lf1-f51.google.com (mail-lf1-f51.google.com [209.85.167.51]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A4BA712DD8C for ; Mon, 26 Feb 2024 14:02:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956151; cv=none; b=mTwCsSP3cgcuyPiZVMn/BFbU7sGyvcEK2LesKtYUMiHWIlY57lhxXIH+gfRAByVwPePK0YyC45cktiRM+dc0D2swYK+cxpoVUsC2Uq9i1L8cTWWD0Ic8D7PNPzKvC6RQ2qyZB8oQh6cvfM79NvCb28diVP3r/X5P0QSIVXG1XvI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956151; c=relaxed/simple; bh=7gKtKZ96mpebE4/UyNGtTbO/tF9O5foCSjcP2W5e+6o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hv06aY2/4P5M+EZkGpFb3EH/2uEs28IvaCiml7stf4FpUBiSwWuGNv+CaqM1SxANEa9iTll9L03lc5F5XzuZAVZvBdJdZPPz/xOgSYKprbwdTQrh3kAr+PLaDTtr5k4Zl9rpXFUQQArvoNpjpVnJ1JXSkUoQzCYHvhCknery67A= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=CHvpZawQ; arc=none smtp.client-ip=209.85.167.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="CHvpZawQ" Received: by mail-lf1-f51.google.com with SMTP id 2adb3069b0e04-5129cdae3c6so3992647e87.1 for ; Mon, 26 Feb 2024 06:02:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956146; x=1709560946; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=zA6Y8WaWiyVxJ/xYCh7GUPTM71b4HBf0Ymw0AKthDEc=; b=CHvpZawQ/AkJeA9oiqBnUcpASxOCV5HJeiHpmAmHapogfO1vKGNRsO2yIt9nQAdoNJ A7a+IuS4Jr9tSxrgvLM35qQ61rbjWBfKBfQUxecJQ0x14QuxCPVaJ/pnzp5BHlE0/LpT /SFA1jOgVEpCSu/9CGFHJFnvVGfB/JEdm4UkDQW8LyzY4WNDUkiY1HfqbSFHEjZQIAu6 dzzIVD2Sz4AxtFjeu+KsxVN+CJwD+Jh7R8IdNJOQSWlg0MLNjm8UXxtidaWkLJJBMck5 GjTIlGDO8qRfPw1SKlMdiuRJ4cHybR3DT/+yc28pqDNj5OA/Use8n0R/arhoMmlGSppz KYvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956146; x=1709560946; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zA6Y8WaWiyVxJ/xYCh7GUPTM71b4HBf0Ymw0AKthDEc=; b=nL9v922p7ol+lZBhkklORLy+jqOuXfRBLPkITXauJ/B8JYF6R/vzTLkldZjiYPbFC6 aK9oxxH0rAKeDDXFElJ6KTHaHK5YcicT4cR9HWHojZxo+LeCog4kCeCzglOS0Zi0CHZH iK6qG82Psh8Pzt20Fsf28mvcRmSvtup5RtFu5BHs/mFIY+izp4qaZA5x4oNY9MsZta4K elPz+jACxUJ3aIqKFG1xTuGZhZMNIz1eoz8eznBzbEGwOl9a2cSfnQDrwp5gU6WcMvZK BChAUifiCL43gdNjcFUHwYjgLvhTHdGoJ5CSf1RA0mv7asy1qJsnHjN8GPEXmoTZR/W6 DbFA== X-Forwarded-Encrypted: i=1; AJvYcCUc+NdK1aP8Cj28FRKzZ/C6aT0b/UKhgLMzyCSden4hSERCZVJNrRPOxVy6a4+qy57axqdvqTNr8bADOERfaU6UfRZ+kFh8ltzSFwQ= X-Gm-Message-State: AOJu0Yy2S8/NYP7Oz2mMKLuOu1QFGzBMjzYGUfHibhbL/vRygTI1trKV lB4MZt3TvXL96owJizC15SUtp228JDYWN5j6ulgwlS5il8UgQcdhxB054bv1hj8= X-Google-Smtp-Source: AGHT+IFZTYGnkejti+WCUV0bUYklgWDkRIQ3OpYZLpgocYTsWqEZ09TnWQAenfEV9LOzKDtQuB6hbw== X-Received: by 2002:a05:6512:3da9:b0:512:aa52:5cce with SMTP id k41-20020a0565123da900b00512aa525ccemr5583650lfv.12.1708956146625; Mon, 26 Feb 2024 06:02:26 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:26 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:52 +0100 Subject: [PATCH 14/18] ASoC: mediatek: Add MT8365 support Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-14-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2430; i=amergnat@baylibre.com; h=from:subject:message-id; bh=7gKtKZ96mpebE4/UyNGtTbO/tF9O5foCSjcP2W5e+6o=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JncDRU2NBAq5rld4NoSuR28KwMZlIfGU8IBQSkN SNQJ2tqJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3AAKCRArRkmdfjHURfDGD/ 9m97Nzpk6hOjVqK3PFbQax0+QGFlRuqovyHNa4EU9vmGuGO8caLPUuugYcx559tE8h+O1jkQCrwNWX Q/XOJ1FDmQ6RI9Q+XZF3AxpJllFfCjLhgqxMDYasFUG3w/1ZZ+ENS9Nl1WonR/58W3CFvWLABh6fqV N3JD01coH9rYNalJvFiv512AS5tFcJFWbfHDgxPE9yPGue60swyFLkrzI5+2j3X4SrKoM6Dgzqq4wc eojs5yS/ONSWbcY0vq3o5QMLyQkPdZBm5BLautmVV3Jy3SHMqvwmuve/casoFCf5K/J3MBxJDDVhqs OxpWXaazPI1cPcWxo3B3pVoK6YuwDtZb6QH3dWTgiJlmdorv3ErELXiBUZy6Sua5s3+zvVJS8RPz8Y VKeco0kB7OYIYUWEs0BT0TVeGj4sUqqyV99af0vY4kP21ygqowS6nN+yioba0wVhvNidAcRHZB/qoL lkBf9JDhphrOQl8xUhvVGCAmMxegJ6est/k6fJZ7hCb1UE3biVtE/p7RAeYSlt8/nMBrXK+2SO58XW AC5zcWZnuO6QzvwI29ZugDYm0/gxJx+tHTdzK7IqfeloT5QeH3QDzvxl0JQBbP3FUXC1vKm59Or25T LhPQU64Udhs7slsra/bjBBFsekuxfIFzBMn9iRPU7SDoam+8QkzwtjU02C5A== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 - Add specific config to enable: - MT8365 sound support - MT6357 audio codec support - Add the mt8365 directory and all drivers under it. Signed-off-by: Alexandre Mergnat --- sound/soc/mediatek/Kconfig | 20 ++++++++++++++++++++ sound/soc/mediatek/Makefile | 1 + sound/soc/mediatek/mt8365/Makefile | 15 +++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index 296b434caf81..671020037a99 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -314,3 +314,23 @@ config SND_SOC_MT8195_MT6359 boards with the MT6359 and other I2S audio codecs. Select Y if you have such device. If unsure select "N". + +config SND_SOC_MT8365 + tristate "ASoC support for Mediatek MT8365 chip" + depends on ARCH_MEDIATEK + select SND_SOC_MEDIATEK + help + This adds ASoC platform driver support for Mediatek MT8365 chip + that can be used with other codecs. + Select Y if you have such device. + If unsure select "N". + +config SND_SOC_MT8365_MT6357 + tristate "ASoC Audio driver for MT8365 with MT6357 codec" + depends on SND_SOC_MT8365 && MTK_PMIC_WRAP + select SND_SOC_MT6357 + help + This adds support for ASoC machine driver for Mediatek MT8365 + boards with the MT6357 codec. + Select Y if you have such device. + If unsure select "N". diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile index 3938e7f75c2e..4b55434f2168 100644 --- a/sound/soc/mediatek/Makefile +++ b/sound/soc/mediatek/Makefile @@ -9,3 +9,4 @@ obj-$(CONFIG_SND_SOC_MT8186) += mt8186/ obj-$(CONFIG_SND_SOC_MT8188) += mt8188/ obj-$(CONFIG_SND_SOC_MT8192) += mt8192/ obj-$(CONFIG_SND_SOC_MT8195) += mt8195/ +obj-$(CONFIG_SND_SOC_MT8365) += mt8365/ diff --git a/sound/soc/mediatek/mt8365/Makefile b/sound/soc/mediatek/mt8365/Makefile new file mode 100644 index 000000000000..52ba45a8498a --- /dev/null +++ b/sound/soc/mediatek/mt8365/Makefile @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0 + +# MTK Platform driver +snd-soc-mt8365-pcm-objs := \ + mt8365-afe-clk.o \ + mt8365-afe-pcm.o \ + mt8365-dai-adda.o \ + mt8365-dai-dmic.o \ + mt8365-dai-i2s.o \ + mt8365-dai-pcm.o + +obj-$(CONFIG_SND_SOC_MT8365) += snd-soc-mt8365-pcm.o + +# Machine driver +obj-$(CONFIG_SND_SOC_MT8365_MT6357) += mt8365-mt6357.o From patchwork Mon Feb 26 14:01:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776096 Received: from mail-lj1-f179.google.com (mail-lj1-f179.google.com [209.85.208.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4293612EBE9 for ; Mon, 26 Feb 2024 14:02:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956155; cv=none; b=AXiiRuyDFhj99NglTDoCOCiTPG/6nsYmHaZdeX3pfk4nj3+gPOtrT4Q/51+koRBfZh3ps1NG6f46MAs+9L3Ho4O0Z4/YAT+tpFaGeccMUid9RrAPi8zx9YJRR6pS+HVqbbk/QokVjRFLmn8d+/475jRz+JHiNjC20ZiDTFgrLtw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956155; c=relaxed/simple; bh=wXzcoZ01ca5dM7JiP+jpbdH0FdMDFiDQ13DjfVwqVVs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=WBgLgD1P8B6z8l7ZdaygYgCtWvW6TKvZJ5tLx/bnG2LmGc4vPj8upzCBNrPV3ahAesFDK3NGi6ZSyxoLXiVEC9qJlkeVEYfEFqt3yvqMzf6CwxbeNL2V6I8LJB8DCGu7P+4YZOMse++bOJ6WxDZMiMTvVYuUTtVv81QLaeYZyKk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=e9qVpzvj; arc=none smtp.client-ip=209.85.208.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="e9qVpzvj" Received: by mail-lj1-f179.google.com with SMTP id 38308e7fff4ca-2d28464c554so20105631fa.3 for ; Mon, 26 Feb 2024 06:02:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956149; x=1709560949; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=zRzHz2xswbllHIIRa+KrVi40UoddaC27mYKCsGC8B5M=; b=e9qVpzvjVEa3SBl3hZRkdwoVdMJZXVn5I/x6LF7WCQ6F2fg1n7iU5cWUwkMuQewu65 eN/4yU1CAluoB8ijpm+pjZJ4ATsVuVHzgqcxgQJGUZwYZrM9sOAgh1OcDRj5wIbJNQ/4 iY5SYSPvJdRlXXktV8p7BL2GXQ2fWYLR1i/DCpGHJ3cq8Ah3RZRKyGUuDrP7rBRSaGL1 ymR7DnukeGPeji36Bxjbq1N/G5CoitqFlGUbsTQCzCXCiApE2zOH6RzAdv61va4DJ7G1 5mAGk8tylW/tIUnhjJaIQ6Err2l2zpEsWQiXHy2ER386fCkDd019yumV1Het7qjLY2x7 8H5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956149; x=1709560949; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zRzHz2xswbllHIIRa+KrVi40UoddaC27mYKCsGC8B5M=; b=QkYfFPvc6T1z0a6LsBeW12Str6GZBoBW9TUurTakfRAguvw28X3QvhLVzUUtx55ZRR p8dXhpfsBeQWkoWqS0csuI5nPXtbAmssX7ZYxrnDmGm+h6e/InmLmkqvz6FiORT0h9Ch VJxo/zDen8MgfBlg03R2JlgSZp7t5Ax3Ll/32iIPzawO0gxyR95oiOveY5OEharBflYl 2Q3iVCpsWGvyvBKk+E/18XjhqUl4j5tYIbj2Sb2gBaWRneHEZgHCqYvFYxvBn+jETzAC j2g8HHZ43FLr1p8TtDLjv+yifWhTeTVYTjMKQo7+QApemqOQYtb5GTaOC8ytLd0U4LsU qDkA== X-Forwarded-Encrypted: i=1; AJvYcCUqRbVitYaP7QbrkXmVwT0JwahkIf6YUTDNzG4yG1gKF5etKUXgFrH7bOHEeap3cQbAG2gJ8nfcpkCpnV2tYsaGbWjH9kogTNwa2A8= X-Gm-Message-State: AOJu0YyRh8r83isN9NerTZ5jsSeakGZfRf9R+AnchOJGx/KHkPNgBJ6E yUrTwTZUsgCPPqfCUQ3JBOzBm4W2oa5ZCaEYmC9rsvGPPrPTtqPOHDotehKofOA= X-Google-Smtp-Source: AGHT+IF3qwR9Gc+h1O6WyIDdP7kIsfb8il8xKzj6tOQtu9QhZUg+J5sdQ8PPlj87e4Oz8wu+C95RXg== X-Received: by 2002:a2e:9247:0:b0:2d2:9185:2017 with SMTP id v7-20020a2e9247000000b002d291852017mr550055ljg.17.1708956149131; Mon, 26 Feb 2024 06:02:29 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:28 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:54 +0100 Subject: [PATCH 16/18] arm64: dts: mediatek: add mt6357 audio codec support Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-16-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=958; i=amergnat@baylibre.com; h=from:subject:message-id; bh=wXzcoZ01ca5dM7JiP+jpbdH0FdMDFiDQ13DjfVwqVVs=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3JndPcSE5JSY3z1YtT9jmziw95lzTv7FpKPgFmzb WqBD0pyJAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3QAKCRArRkmdfjHURQ4gD/ 45DtjX8QtQ9BlpoeQoUHYlLB65IVbXtkjFBMq1f3miUNgR/FSQpZ71R4jQLQ9TUUy/X6lsq1+5i0+m xbD5HeTgN/G7posNpd1nPboTHB/+/7edI6JQwqTfaOOh1ihqQUOk0e+FSQHEb00SBIubf/1gPzKWJ8 pGBTnVMV55xcvqL0QuVarAxPho9t9JKKGENCNytIoPk+Ufd21qFJ4H/w6sbta/F5XQyrj2UmQcPUhH wyP/DFzz0c8/f0Xx/BLOpuO+/9HjIpv2bxvLLEfgaXD6ap8ZqhuAUP1VgXHWdoPY/k/WE/zutLBILv k0R59zI+yJZA9JTJuHF2RJ33LtLQn6YaiKoHjD7PCO0PvdrvnRRzBB+udbHUAj9sIPLjb1JovChRhM SFGQIhRV76UfeL7wiVwUdh/jgsW57n78DhFBsc4ckarEvb6C9u5fgiHCCxc+Hg2q3XxZTvRKy9M4ox 3VMUdtp8ownC1VrR/sQxlHByUgvK8TzwKMwQ0SKRBqhduIs4nF23/tVX7Jo/tRge/28AhdBSHFOe1p ALtfws/Gzp0JaH1zGHdJGLwb2JvAf5ugK56diBaEvIMfQsWGFazGdJBtfzKNT6D3UhbTeofnTuSn62 3boyWxQP16ra4yZJ6OJxzL65SIXw1oLRwvNl57L7wmG/3u/EIp3AdGKmD+iQ== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add audio codec support of MT6357 PMIC. Update the file header. Signed-off-by: Alexandre Mergnat --- arch/arm64/boot/dts/mediatek/mt6357.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/mediatek/mt6357.dtsi b/arch/arm64/boot/dts/mediatek/mt6357.dtsi index 3330a03c2f74..64b693049930 100644 --- a/arch/arm64/boot/dts/mediatek/mt6357.dtsi +++ b/arch/arm64/boot/dts/mediatek/mt6357.dtsi @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0 OR MIT) /* * Copyright (c) 2020 MediaTek Inc. - * Copyright (c) 2023 BayLibre Inc. + * Copyright (c) 2024 BayLibre Inc. */ #include @@ -10,6 +10,10 @@ &pwrap { mt6357_pmic: pmic { compatible = "mediatek,mt6357"; + codec { + compatible = "mediatek,mt6357-sound"; + }; + regulators { mt6357_vproc_reg: buck-vproc { regulator-name = "vproc"; From patchwork Mon Feb 26 14:01:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexandre Mergnat X-Patchwork-Id: 776095 Received: from mail-lj1-f171.google.com (mail-lj1-f171.google.com [209.85.208.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 942D412DDAD for ; Mon, 26 Feb 2024 14:02:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956156; cv=none; b=jePDagov57skzhA9OaaWiWhCbh0JEw5vI5bEiGZlm8jBYC5g4U1Y/FDD08mR+O1xizUAKaBsEMZyfMLF71r0aGWoYCm8zhFrjt1pu7Yx8w5XbTnWJpwcWjvCk7m/9MFtro33Rdibl7RpdczVW7o0oWnT16LMEOObc0uDzT/Zc7E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1708956156; c=relaxed/simple; bh=lbgi9OL1obZblEePDIhhejeSSwFTqveCSkacaUUqnXE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LhoN0/kcXzXOGEvZC3ABrG+X+LwlmYw2nYE1cKIWyXInCuXYMqmrO+foUH9q3JcJoWqh91WhRcvQgxDz3VS4zyMfr6DbAUUfSPPnLfMxniA9WXHSz6fsREGnhUp4yRHLfsA0uU/rUiOCLJbFRZ9Bv3OIWvRUHNRPKHK9cWNzyMs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com; spf=pass smtp.mailfrom=baylibre.com; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b=QNJpHldM; arc=none smtp.client-ip=209.85.208.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=baylibre.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=baylibre.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=baylibre-com.20230601.gappssmtp.com header.i=@baylibre-com.20230601.gappssmtp.com header.b="QNJpHldM" Received: by mail-lj1-f171.google.com with SMTP id 38308e7fff4ca-2d28e3c0fe0so9155821fa.2 for ; Mon, 26 Feb 2024 06:02:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20230601.gappssmtp.com; s=20230601; t=1708956151; x=1709560951; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=Fr6qUv7uphl0F7A/cjSpLzFAuez52U6vdxnRSxFG1Us=; b=QNJpHldMxF9dy98Px1SheVC25WaTU61/4xHpDQHnwlGmNTf/GcJfX9l9WGk6crvuMA 6cdnyj5StEBCz15pwzapq0VlwGgdXIR49HeDwSc43RiRXGWe+e20wRBWN8PSzQB7YwUe IElbS7GFbNCMBkQUUWRzKPS/TF/1MktOCrPBLaDbC5IXFmjeORAJVJxOELsaOiFBTSPh HMuA21ZK3/K5LY20ZLBUERolQ+g0Y8RBa0lUlKSkpGGIQznOPX84EIS6x5IGq5YFbJZF JB0LkSI7husDmA3zC70BjV07MnDBsrGfJ7R3CvMo0ELTACWbDPfjP5ELAZpYivI7TMpi l1SA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1708956151; x=1709560951; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Fr6qUv7uphl0F7A/cjSpLzFAuez52U6vdxnRSxFG1Us=; b=Lm9G+hzjqYpkQ4unG8V+aenbakvX965DK1gFitIIHWYRNrXNxQip565MXw3yYYYaIC 9+GQsm4tQwAZRN2ZVk38hfjkMPb1ZAP8hS6U37O7Usm8EaIPdlGdYiW6M24dLpsk8XE4 v1sIOxVemkyhe11hzL0TkE4Y19AuMECHSj+lfSDIfZRrnsURBKwj5bSAX83dKd/GdFTt mTHL0yJYjP+sguLkumtuM81jeF6jmTi2OE7O7yh6678Y4a8jThC8RuEFS1h2Xbl9iCFT eRhn7qNQsKQh9h/FJ5xDOGH9RhgkBPq9UKw6BE4hV0k8MUrR0xqbzM+MSCkfFWYtQgQj y02Q== X-Forwarded-Encrypted: i=1; AJvYcCVzL5qV3xox5Ykg0X7vVSuVKt9i19zJvJtd6VkT+WEu+TcsEe7tV+jWbwe01uUC/nnRB2OncX0q8MbF4UOd8XCEl3wtdruJiiOTRSI= X-Gm-Message-State: AOJu0YyQeekKTMoUlPA1/OEUGkHRNQYfySOosu2QULTHIJ7y23zCmsjb hIQZuz78Y8f4V9uXJPg5OMBmqlsnI85X8cHRigKPQbOKFpw8yrZGw2oOeRxpcUQ= X-Google-Smtp-Source: AGHT+IFoh8mPmzGM/gZj9w5NAeFQXI6f6EQmCodyO1Vvv8vUKUQrRRqnf2VVbDW26mV1+6aMSpo47A== X-Received: by 2002:a05:651c:10d1:b0:2d2:2012:1fef with SMTP id l17-20020a05651c10d100b002d220121fefmr3638929ljn.47.1708956151700; Mon, 26 Feb 2024 06:02:31 -0800 (PST) Received: from [127.0.1.1] ([93.5.22.158]) by smtp.googlemail.com with ESMTPSA id d33-20020a05600c4c2100b004129f87a2c6sm2838475wmp.1.2024.02.26.06.02.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 26 Feb 2024 06:02:31 -0800 (PST) From: Alexandre Mergnat Date: Mon, 26 Feb 2024 15:01:56 +0100 Subject: [PATCH 18/18] arm64: dts: mediatek: add audio support for mt8365-evk Precedence: bulk X-Mailing-List: linux-media@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240226-audio-i350-v1-18-4fa1cea1667f@baylibre.com> References: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> In-Reply-To: <20240226-audio-i350-v1-0-4fa1cea1667f@baylibre.com> To: Liam Girdwood , Mark Brown , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Matthias Brugger , AngeloGioacchino Del Regno , Lee Jones , Flora Fu , Jaroslav Kysela , Takashi Iwai , Sumit Semwal , =?utf-8?q?Christian_K=C3=B6nig?= , Catalin Marinas , Will Deacon Cc: linux-sound@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-media@vger.kernel.org, dri-devel@lists.freedesktop.org, linaro-mm-sig@lists.linaro.org, Alexandre Mergnat X-Mailer: b4 0.12.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3858; i=amergnat@baylibre.com; h=from:subject:message-id; bh=lbgi9OL1obZblEePDIhhejeSSwFTqveCSkacaUUqnXE=; b=owEBbQKS/ZANAwAKAStGSZ1+MdRFAcsmYgBl3Jnd+w8IF/0MoA24p+dI4JyZDGShEkMctxqnmZ3g z3OxK12JAjMEAAEKAB0WIQQjG17X8+qqcA5g/osrRkmdfjHURQUCZdyZ3QAKCRArRkmdfjHURa4QD/ 95NpJWGzTF7i0U4jGIRjRkcN2D4J42NZKCYbftZ8a5Q4MTVuwCbkEMdy8eOB36kpxWTlq61VxNUsug lAentcdEWSrZEUsczLGt82lKlMdaKuOrVM3RBz+D/4DCgIzuNqw5RtyRK+D9US6UOjV6bAYg+VOCmr E2VvHOXer0VlRm/v1bpjTxH+OXtA8ztKcQFPeK4LFGLDGqSCYnMCT7v0eCZ+Mya9vw7drZY5Eibu/6 5q8nT8GIe5kFdPwaq64D3uV9hsu59MccdcThnyJqTGqYuEn4C1DN+9rkcT22e5Bp1YS7y7juyj6C04 DDOXMgU2bl6P9Lpe7uCpyZPOFb6y7cbRw5YzZPYxONpskn1hFV1XqaalcwBTKgeQWdSZZhU1zLosan j5qZDHkmN6ipbd0We4rQJg512ny8X13q9fH1AbBW85bZLMwOM2cPOA0or/BdWx0CFzyBAuhz+Yikry 8OmWIr07732ikrI661VIF8Pj2ZLa1ryWzMjooj5Y/b8OppHDB1LidcNyTHsVKBep5fdn8yiHYYO3j6 mk7lsczgK/oSLH5NTGz1sViSOvZoYwm2PC2HrHzMCikiFlcqL65mnGQ4Nnr1EqwRfQWlmJadgvAia+ nixt2u4SvthnmJAfycBFbOcGNz/PTqn0gR2UBZ3nNGyog9K0HoQ5yCYLsjTg== X-Developer-Key: i=amergnat@baylibre.com; a=openpgp; fpr=231B5ED7F3EAAA700E60FE8B2B46499D7E31D445 Add the sound node which is linked to the MT8365 SoC AFE and the MT6357 audio codec. Update the file header. Signed-off-by: Alexandre Mergnat --- arch/arm64/boot/dts/mediatek/mt8365-evk.dts | 95 +++++++++++++++++++++++++++-- 1 file changed, 91 insertions(+), 4 deletions(-) diff --git a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts index 50cbaefa1a99..818a8d263949 100644 --- a/arch/arm64/boot/dts/mediatek/mt8365-evk.dts +++ b/arch/arm64/boot/dts/mediatek/mt8365-evk.dts @@ -1,9 +1,9 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2021-2022 BayLibre, SAS. - * Authors: - * Fabien Parent - * Bernhard Rosenkränzer + * Copyright (c) 2024 BayLibre, SAS. + * Authors: Fabien Parent + * Bernhard Rosenkränzer + * Alexandre Mergnat */ /dts-v1/; @@ -86,6 +86,25 @@ optee_reserved: optee@43200000 { reg = <0 0x43200000 0 0x00c00000>; }; }; + + sound: sound { + compatible = "mediatek,mt8365-mt6357"; + mediatek,platform = <&afe>; + pinctrl-names = "aud_default", + "aud_dmic", + "aud_miso_off", + "aud_miso_on", + "aud_mosi_off", + "aud_mosi_on"; + pinctrl-0 = <&aud_default_pins>; + pinctrl-1 = <&aud_dmic_pins>; + pinctrl-2 = <&aud_miso_off_pins>; + pinctrl-3 = <&aud_miso_on_pins>; + pinctrl-4 = <&aud_mosi_off_pins>; + pinctrl-5 = <&aud_mosi_on_pins>; + vaud28-supply = <&mt6357_vaud28_reg>; + status = "okay"; + }; }; &cpu0 { @@ -181,6 +200,67 @@ &mt6357_pmic { }; &pio { + aud_default_pins: audiodefault-pins { + pins { + pinmux = , + , + , + ; + }; + }; + + aud_dmic_pins: audiodmic-pins { + pins { + pinmux = , + , + ; + }; + }; + + aud_miso_off_pins: misooff-pins { + pins { + pinmux = , + , + , + ; + input-enable; + bias-pull-down; + drive-strength = ; + }; + }; + + aud_miso_on_pins: misoon-pins { + pins { + pinmux = , + , + , + ; + drive-strength = ; + }; + }; + + aud_mosi_off_pins: mosioff-pins { + pins { + pinmux = , + , + , + ; + input-enable; + bias-pull-down; + drive-strength = ; + }; + }; + + aud_mosi_on_pins: mosion-pins { + pins { + pinmux = , + , + , + ; + drive-strength = ; + }; + }; + ethernet_pins: ethernet-pins { phy_reset_pins { pinmux = ; @@ -416,3 +496,10 @@ &uart2 { pinctrl-names = "default"; status = "okay"; }; + +&afe { + mediatek,dmic-iir-on; + mediatek,dmic-irr-mode = <5>; + mediatek,dmic-two-wire-mode; + status = "okay"; +};