From nobody Sun Feb 8 17:37:19 2026 Received: from NAM04-MW2-obe.outbound.protection.outlook.com (mail-mw2nam04on2055.outbound.protection.outlook.com [40.107.101.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 31C6027585B; Tue, 29 Apr 2025 06:00:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.101.55 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745906419; cv=fail; b=eJyK0WZk9He2i69AsIcNdzaGuD6thNLPihzyT34lXXrdX2oQwNrPHA4oD+3A9/psIm7T3kWS0yg6G4ZbHM3BgKOEXda6AzhrcFMCBWu2v8xGYuQtQdjIXRUZ+TGkhIrlruOuVrhfWfEhNbNSx+W6X2g4eNy7Z6XO1VtKXGsZQXc= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745906419; c=relaxed/simple; bh=TlYMJ4pTpJdP3SxoPQEIaXfUmt80+YZdh8Ay/mkwdRw=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=CRjCvpo5i27vu9O2q2pU9Xe1wThsplrHk8zL9f22Uwg7p4uew7kZjF+JyEb1KS09J2AdpHvDRZWuDYwvQdKTR+4LRQ7Uxadn1IUC8LxKh19lA5Uema2ekCnko7w1OsgLiLauOiehsh7chWk37ATOzb41J1KevxWnEm+A390X/+4= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=q89gmnw4; arc=fail smtp.client-ip=40.107.101.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="q89gmnw4" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=Hbas0eLnGS4+LFal9yway7ef9l/oqun9f6o275s5HYRd6oPP4LKI12whekbOyxYTuBUcdg9Z4OVb4liNprPh8SXDFPNHuApaXcmnO96elUgJRv/TkWn4iGP1vbFCOgVv3rU6AKv/OsfM1NFCunwSF1PDzvFlioosOoHQDvcG5D4mj4nn3Z/YB9b4tb5/DS6bClDXnODbqCVmK6/0T2edmWTh5RgxqnP3OUD7WA0L2PKa6pVCCsQakKdeXR7nCkcWpCHXYuZgoAS+KzMJ+miVRD9Cmp45VKQFjNJArCeKY/v3XjQZeRaQH6wvVeAZflCviTfIRIx31DpIkjOk5MWsyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=RnlkzjZy0ROvLGnOytKgILJe2WhWONMOCUWcbDn+c5k=; b=OpF8PwDaq4oJT7pVeQj6XLiIB3wPJJxULbmjadKGrq+2zbIFYupIWi0hRpjnFfDDvRKLmQPx5ImiW4TrlJVsnPg9cVSIGP12Fg9c4clyADeReTjLoUMFWPXOrIoU8Yo5NA4p92P0cm6ZDBMMHj+pNw3RClFOC9C2XWDS4msk8JnRMp2UwUrr6aUPB/+RXaPDKlFJJ8+68nmEqc0XryTrcFnydPlJ0j90RBG8oZ8K8vZPXAY9j1JelWb4rDycV8r0fuvDnr7v1DJE+uuS+MG5ON7yjuHFEDY2d9VaWoiJOkk7qXGc2IRZwVse40gCQ18QIjbnPSVgE0D5n9GxoM+swA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.117.160) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RnlkzjZy0ROvLGnOytKgILJe2WhWONMOCUWcbDn+c5k=; b=q89gmnw4Lbwcp27hanYCBlV+eTa0NDoTKg2BZ1HM0TKTigZsLxunEs4kAgrYY4Mr891Us3PMOu56Bmyb1CH2qVj4t5s7Gtw0V1gIP5b/uzvF7z4ZAnNN3B/Pd4s9R/4YjGFjGCC/W2WXYQCr/aIOmuQnLM4us1Q6dXgJKaf6rdtJhFOK217MBp7t0jnazpu3i/bFllYbhRTDdzrBl7xp2wVENiMzhuvYz7wDdOGCEbkPI4Y4mruv4HoK1LOPM52lqWt6cWPer1aSlgKAr/edmjNThyeNJqKfORtUQhEuoD1+zzKQiHmo+RY0K4gk+hprkJyeocnZ5AdZPgJoc5rb2Q== Received: from BN9PR03CA0454.namprd03.prod.outlook.com (2603:10b6:408:139::9) by DM4PR12MB9069.namprd12.prod.outlook.com (2603:10b6:8:b8::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8678.33; Tue, 29 Apr 2025 06:00:08 +0000 Received: from BN1PEPF00004686.namprd03.prod.outlook.com (2603:10b6:408:139:cafe::6) by BN9PR03CA0454.outlook.office365.com (2603:10b6:408:139::9) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8655.41 via Frontend Transport; Tue, 29 Apr 2025 06:00:08 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.117.160) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.117.160 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.117.160; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.117.160) by BN1PEPF00004686.mail.protection.outlook.com (10.167.243.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8678.33 via Frontend Transport; Tue, 29 Apr 2025 06:00:07 +0000 Received: from rnnvmail205.nvidia.com (10.129.68.10) by mail.nvidia.com (10.129.200.66) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.4; Mon, 28 Apr 2025 22:59:48 -0700 Received: from rnnvmail205.nvidia.com (10.129.68.10) by rnnvmail205.nvidia.com (10.129.68.10) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.14; Mon, 28 Apr 2025 22:59:48 -0700 Received: from build-sheetal-bionic-20250305.nvidia.com (10.127.8.13) by mail.nvidia.com (10.129.68.10) with Microsoft SMTP Server id 15.2.1544.14 via Frontend Transport; Mon, 28 Apr 2025 22:59:47 -0700 From: "Sheetal ." To: , , , , CC: , , , , , , , , , , Sheetal Subject: [PATCH v2 07/11] ASoC: tegra: I2S: Add Tegra264 support Date: Tue, 29 Apr 2025 05:59:37 +0000 Message-ID: <20250429055941.901511-8-sheetal@nvidia.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20250429055941.901511-1-sheetal@nvidia.com> References: <20250429055941.901511-1-sheetal@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-NV-OnPremToCloud: AnonymousSubmission X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BN1PEPF00004686:EE_|DM4PR12MB9069:EE_ X-MS-Office365-Filtering-Correlation-Id: 5d4dc975-9b05-40f8-faf7-08dd86e3185f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|1800799024|36860700013|7416014|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?3D8f9TlriT5NmjwdEU3A7b89IJgRY+a0ifgQu2KGJhISlC9dPRIrH0ixS5nH?= =?us-ascii?Q?pmkgCfPgCSkzdvzhIQ9epYP1lZGu4ti86w60bOjXlbTDfRhnKjSvDql7xEK1?= =?us-ascii?Q?OdtH3loByjMqtoYCoDU8KAzK9G/c97DpY4nM0huchmK7MdfOF2jeens1AGzh?= =?us-ascii?Q?5WGVA55eKeXfBqqI75mt09JTndc7zq4dWHVdP9GlE8PSkG6x5PYLN6LIuHqe?= =?us-ascii?Q?m/YECgku0fZmBtAwvXG1hcQNBjW87lYeWQ+rdjz6pQYCWpmO6piGvUqXHqrN?= =?us-ascii?Q?AYZ3gIUkgg8Yo92Dd81D2NvYb2gGt96o4fWnSSrZX22k1JWZXLWRAgH5SFmQ?= =?us-ascii?Q?QwxD7QGxeXCgPcqsrZ4+Q8aqhhHDhJU8hukqCM/fI3plCaTkSLRdFevtulij?= =?us-ascii?Q?AVAGMV5e+n8Fuj6HVeMD9UKcyOcJHvN5+OcehRCOvBpOx8Ec2jWE0IJL1Z0k?= =?us-ascii?Q?PIvagV0xgTX7LU6aetPUD8Y/ZQP2L3HL+4V4blbWW2P4foWVMZtLLN5R/WpZ?= =?us-ascii?Q?PYhzKH+pP5RmWK1a7DynBaiM7KI6SIRDtDPOon6cofORm5zZuyhhveifl+qR?= =?us-ascii?Q?BWxWENgYPgO28SUZ3h0ZASfE3Eb1pbob4XFxULqC9XuMR85PmrJIiBQWeGEN?= =?us-ascii?Q?t4l1sAUTF/K9oBOy06XRdX7E6Oe6s8KEdelS1asCm/RVbwfzkgNMdVJXbOoU?= =?us-ascii?Q?eoJYxKb5mgyPTSsbponB4eUcgYmGp8dFm58sPGElmQXdHPMmAq1eyMBcM3+Z?= =?us-ascii?Q?NpXJmnj9TqJAh5XQmyialXRyiZSwjtUUQ8v7bB5sNUsle0X6xS2l3H85i4DP?= =?us-ascii?Q?7vAoAeGPTInjm0avQgC7KxukUsTa8FTWV6eZ6PkPp5efnUh5iiGCOyEEob4O?= =?us-ascii?Q?7thmqHMrgmrK3ix/GtUNIP+LFUSjtW8kAlfOdR48DSVM0dSQXxFb3mgNc8JO?= =?us-ascii?Q?aRaJVJ/xWGsK0s1bf0gbeKd56KSYZ1DvzC2lRiJr3WFdZ8fGSLXB6CLK7avV?= =?us-ascii?Q?qwJUYh3C6JmF4V7fvmtWlR25GoJPD2IqFBEoPXUTiLvQ1sa2YrRlR4TGO5gD?= =?us-ascii?Q?qGsdZxNVOJDmx4jNfoz8UTpseoLL1nmzLuDx/4SD9NMQTt3X3UmhIc+PkGpB?= =?us-ascii?Q?dDCP4oVW0ZiHCAm/4BgUddWa7z3zyMZvmn2By/nsegVCNqgh9ufOoP+4gVzE?= =?us-ascii?Q?6t/kkTQxGp4wKihr0BAvXXNZ+A5OVp06U1lH3StbGkOq7BfGMFDIii4WyXb7?= =?us-ascii?Q?gZFnNKgyYjV1zZE1j5a8Q6ir65RcfvM7L3MkgEg5i8eRoY6pIgaV2pNETDh7?= =?us-ascii?Q?MP5pLmm3WedXNe+fHYw5KgkMAIOxUGWFvdEulVyaIEgSGH9ir1YPQg+VfynU?= =?us-ascii?Q?SaANnD6/1x51BXQh1sXSw4LMAadKlzAaTWSGhuQ3wIeGXe7WUIWEkhl71dNS?= =?us-ascii?Q?N1fkxRWVnY4ZyDfNEyWLF696iGBPqEu+hUR6MO7EGAnR9/guRICW0kxuBLp3?= =?us-ascii?Q?r4t0kBHXrKqIAjhpbzMtNDCI1hiI18XeASeZ?= X-Forefront-Antispam-Report: CIP:216.228.117.160;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc6edge1.nvidia.com;CAT:NONE;SFS:(13230040)(1800799024)(36860700013)(7416014)(376014)(82310400026);DIR:OUT;SFP:1101; X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 29 Apr 2025 06:00:07.9003 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5d4dc975-9b05-40f8-faf7-08dd86e3185f X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.117.160];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BN1PEPF00004686.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM4PR12MB9069 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Sheetal Add Tegra264 I2S support with following changes: - Add soc_data for Tegra264-specific variations - Tegra264 I2S supports 32 audio channels, hence update the TDM config, CIF configuration API and DAI channel_max parameter. - Register offsets and default values are updated to align with Tegra264. Signed-off-by: Sheetal --- sound/soc/tegra/tegra210_i2s.c | 231 ++++++++++++++++++++++++++------- sound/soc/tegra/tegra210_i2s.h | 51 +++++++- 2 files changed, 233 insertions(+), 49 deletions(-) diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c index 766cddebd5f6..100277c39001 100644 --- a/sound/soc/tegra/tegra210_i2s.c +++ b/sound/soc/tegra/tegra210_i2s.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -// SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AF= FILIATES. +// SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AF= FILIATES. // All rights reserved. // // tegra210_i2s.c - Tegra210 I2S driver @@ -36,14 +36,28 @@ static const struct reg_default tegra210_i2s_reg_defaul= ts[] =3D { { TEGRA210_I2S_CYA, 0x1 }, }; =20 -static void tegra210_i2s_set_slot_ctrl(struct regmap *regmap, +static const struct reg_default tegra264_i2s_reg_defaults[] =3D { + { TEGRA210_I2S_RX_INT_MASK, 0x00000003 }, + { TEGRA210_I2S_RX_CIF_CTRL, 0x00003f00 }, + { TEGRA264_I2S_TX_INT_MASK, 0x00000003 }, + { TEGRA264_I2S_TX_CIF_CTRL, 0x00003f00 }, + { TEGRA264_I2S_CG, 0x1 }, + { TEGRA264_I2S_TIMING, 0x0000001f }, + { TEGRA264_I2S_ENABLE, 0x1 }, + { TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE, 0x1 }, + { TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE, 0x1 }, +}; + +static void tegra210_i2s_set_slot_ctrl(struct tegra210_i2s *i2s, unsigned int total_slots, unsigned int tx_slot_mask, unsigned int rx_slot_mask) { - regmap_write(regmap, TEGRA210_I2S_SLOT_CTRL, total_slots - 1); - regmap_write(regmap, TEGRA210_I2S_TX_SLOT_CTRL, tx_slot_mask); - regmap_write(regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask); + regmap_write(i2s->regmap, TEGRA210_I2S_SLOT_CTRL + i2s->soc_data->i2s_ctr= l_offset, + total_slots - 1); + regmap_write(i2s->regmap, TEGRA210_I2S_TX_SLOT_CTRL + i2s->soc_data->tx_o= ffset, + tx_slot_mask); + regmap_write(i2s->regmap, TEGRA210_I2S_RX_SLOT_CTRL, rx_slot_mask); } =20 static int tegra210_i2s_set_clock_rate(struct device *dev, @@ -53,7 +67,7 @@ static int tegra210_i2s_set_clock_rate(struct device *dev, unsigned int val; int err; =20 - regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offs= et, &val); =20 /* No need to set rates if I2S is being operated in slave */ if (!(val & I2S_CTRL_MASTER_EN)) @@ -100,15 +114,15 @@ static int tegra210_i2s_sw_reset(struct snd_soc_compo= nent *compnt, cif_reg =3D TEGRA210_I2S_RX_CIF_CTRL; stream_reg =3D TEGRA210_I2S_RX_CTRL; } else { - reset_reg =3D TEGRA210_I2S_TX_SOFT_RESET; - cif_reg =3D TEGRA210_I2S_TX_CIF_CTRL; - stream_reg =3D TEGRA210_I2S_TX_CTRL; + reset_reg =3D TEGRA210_I2S_TX_SOFT_RESET + i2s->soc_data->tx_offset; + cif_reg =3D TEGRA210_I2S_TX_CIF_CTRL + i2s->soc_data->tx_offset; + stream_reg =3D TEGRA210_I2S_TX_CTRL + i2s->soc_data->tx_offset; } =20 /* Store CIF and I2S control values */ regmap_read(i2s->regmap, cif_reg, &cif_ctrl); regmap_read(i2s->regmap, stream_reg, &stream_ctrl); - regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &i2s_ctrl); + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offs= et, &i2s_ctrl); =20 /* Reset to make sure the previous transactions are clean */ regmap_update_bits(i2s->regmap, reset_reg, reset_mask, reset_en); @@ -125,7 +139,7 @@ static int tegra210_i2s_sw_reset(struct snd_soc_compone= nt *compnt, /* Restore CIF and I2S control values */ regmap_write(i2s->regmap, cif_reg, cif_ctrl); regmap_write(i2s->regmap, stream_reg, stream_ctrl); - regmap_write(i2s->regmap, TEGRA210_I2S_CTRL, i2s_ctrl); + regmap_write(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_off= set, i2s_ctrl); =20 return 0; } @@ -140,16 +154,13 @@ static int tegra210_i2s_init(struct snd_soc_dapm_widg= et *w, int stream; int err; =20 - switch (w->reg) { - case TEGRA210_I2S_RX_ENABLE: + if (w->reg =3D=3D TEGRA210_I2S_RX_ENABLE) { stream =3D SNDRV_PCM_STREAM_PLAYBACK; status_reg =3D TEGRA210_I2S_RX_STATUS; - break; - case TEGRA210_I2S_TX_ENABLE: + } else if (w->reg =3D=3D (TEGRA210_I2S_TX_ENABLE + i2s->soc_data->tx_offs= et)) { stream =3D SNDRV_PCM_STREAM_CAPTURE; - status_reg =3D TEGRA210_I2S_TX_STATUS; - break; - default: + status_reg =3D TEGRA210_I2S_TX_STATUS + i2s->soc_data->tx_offset; + } else { return -EINVAL; } =20 @@ -199,7 +210,7 @@ static void tegra210_i2s_set_data_offset(struct tegra21= 0_i2s *i2s, unsigned int data_offset) { /* Capture path */ - regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL, + regmap_update_bits(i2s->regmap, TEGRA210_I2S_TX_CTRL + i2s->soc_data->tx_= offset, I2S_CTRL_DATA_OFFSET_MASK, data_offset << I2S_DATA_SHIFT); =20 @@ -282,7 +293,8 @@ static int tegra210_i2s_set_fmt(struct snd_soc_dai *dai, return -EINVAL; } =20 - regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, mask, val); + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ct= rl_offset, + mask, val); =20 i2s->dai_fmt =3D fmt & SND_SOC_DAIFMT_FORMAT_MASK; =20 @@ -296,10 +308,10 @@ static int tegra210_i2s_set_tdm_slot(struct snd_soc_d= ai *dai, struct tegra210_i2s *i2s =3D snd_soc_dai_get_drvdata(dai); =20 /* Copy the required tx and rx mask */ - i2s->tx_mask =3D (tx_mask > DEFAULT_I2S_SLOT_MASK) ? - DEFAULT_I2S_SLOT_MASK : tx_mask; - i2s->rx_mask =3D (rx_mask > DEFAULT_I2S_SLOT_MASK) ? - DEFAULT_I2S_SLOT_MASK : rx_mask; + i2s->tx_mask =3D (tx_mask > i2s->soc_data->slot_mask) ? + i2s->soc_data->slot_mask : tx_mask; + i2s->rx_mask =3D (rx_mask > i2s->soc_data->slot_mask) ? + i2s->soc_data->slot_mask : rx_mask; =20 return 0; } @@ -327,8 +339,8 @@ static int tegra210_i2s_put_loopback(struct snd_kcontro= l *kcontrol, =20 i2s->loopback =3D value; =20 - regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, I2S_CTRL_LPBK_MASK, - i2s->loopback << I2S_CTRL_LPBK_SHIFT); + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ct= rl_offset, + I2S_CTRL_LPBK_MASK, i2s->loopback << I2S_CTRL_LPBK_SHIFT); =20 return 1; } @@ -364,9 +376,9 @@ static int tegra210_i2s_put_fsync_width(struct snd_kcon= trol *kcontrol, * cases mixer control is used to update custom values. A value * of "N" here means, width is "N + 1" bit clock wide. */ - regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, - I2S_CTRL_FSYNC_WIDTH_MASK, - i2s->fsync_width << I2S_FSYNC_WIDTH_SHIFT); + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ct= rl_offset, + i2s->soc_data->fsync_width_mask, + i2s->fsync_width << i2s->soc_data->fsync_width_shift); =20 return 1; } @@ -562,7 +574,7 @@ static int tegra210_i2s_set_timing_params(struct device= *dev, return err; } =20 - regmap_read(i2s->regmap, TEGRA210_I2S_CTRL, &val); + regmap_read(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ctrl_offs= et, &val); =20 /* * For LRCK mode, channel bit count depends on number of bit clocks @@ -578,7 +590,7 @@ static int tegra210_i2s_set_timing_params(struct device= *dev, case I2S_CTRL_FRAME_FMT_FSYNC_MODE: bit_count =3D (bclk_rate / srate) - 1; =20 - tegra210_i2s_set_slot_ctrl(i2s->regmap, channels, + tegra210_i2s_set_slot_ctrl(i2s, channels, i2s->tx_mask, i2s->rx_mask); break; default: @@ -591,7 +603,7 @@ static int tegra210_i2s_set_timing_params(struct device= *dev, return -EINVAL; } =20 - regmap_write(i2s->regmap, TEGRA210_I2S_TIMING, + regmap_write(i2s->regmap, TEGRA210_I2S_TIMING + i2s->soc_data->i2s_ctrl_o= ffset, bit_count << I2S_TIMING_CH_BIT_CNT_SHIFT); =20 return 0; @@ -673,7 +685,7 @@ static int tegra210_i2s_hw_params(struct snd_pcm_substr= eam *substream, } =20 /* Program sample size */ - regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL, + regmap_update_bits(i2s->regmap, TEGRA210_I2S_CTRL + i2s->soc_data->i2s_ct= rl_offset, I2S_CTRL_BIT_SIZE_MASK, val); =20 srate =3D params_rate(params); @@ -697,13 +709,16 @@ static int tegra210_i2s_hw_params(struct snd_pcm_subs= tream *substream, =20 reg =3D TEGRA210_I2S_RX_CIF_CTRL; } else { - reg =3D TEGRA210_I2S_TX_CIF_CTRL; + reg =3D TEGRA210_I2S_TX_CIF_CTRL + i2s->soc_data->tx_offset; } =20 cif_conf.mono_conv =3D i2s->mono_to_stereo[path]; cif_conf.stereo_conv =3D i2s->stereo_to_mono[path]; =20 - tegra_set_cif(i2s->regmap, reg, &cif_conf); + if (i2s->soc_data->max_ch =3D=3D TEGRA264_I2S_MAX_CHANNEL) + tegra264_set_cif(i2s->regmap, reg, &cif_conf); + else + tegra_set_cif(i2s->regmap, reg, &cif_conf); =20 return tegra210_i2s_set_timing_params(dev, sample_size, srate, cif_conf.client_ch); @@ -808,13 +823,20 @@ static const struct snd_kcontrol_new tegra210_i2s_con= trols[] =3D { tegra210_i2s_put_bclk_ratio), }; =20 -static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] =3D { - SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE, - 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), - SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, TEGRA210_I2S_TX_ENABLE, - 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), - SND_SOC_DAPM_MIC("MIC", NULL), +#define TEGRA_I2S_WIDGETS(tx_enable_reg) \ + SND_SOC_DAPM_AIF_IN_E("RX", NULL, 0, TEGRA210_I2S_RX_ENABLE, \ + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), \ + SND_SOC_DAPM_AIF_OUT_E("TX", NULL, 0, tx_enable_reg, \ + 0, 0, tegra210_i2s_init, SND_SOC_DAPM_PRE_PMU), \ + SND_SOC_DAPM_MIC("MIC", NULL), \ SND_SOC_DAPM_SPK("SPK", NULL), + +static const struct snd_soc_dapm_widget tegra210_i2s_widgets[] =3D { + TEGRA_I2S_WIDGETS(TEGRA210_I2S_TX_ENABLE) +}; + +static const struct snd_soc_dapm_widget tegra264_i2s_widgets[] =3D { + TEGRA_I2S_WIDGETS(TEGRA264_I2S_TX_ENABLE) }; =20 static const struct snd_soc_dapm_route tegra210_i2s_routes[] =3D { @@ -841,6 +863,15 @@ static const struct snd_soc_component_driver tegra210_= i2s_cmpnt =3D { .num_controls =3D ARRAY_SIZE(tegra210_i2s_controls), }; =20 +static const struct snd_soc_component_driver tegra264_i2s_cmpnt =3D { + .dapm_widgets =3D tegra264_i2s_widgets, + .num_dapm_widgets =3D ARRAY_SIZE(tegra264_i2s_widgets), + .dapm_routes =3D tegra210_i2s_routes, + .num_dapm_routes =3D ARRAY_SIZE(tegra210_i2s_routes), + .controls =3D tegra210_i2s_controls, + .num_controls =3D ARRAY_SIZE(tegra210_i2s_controls), +}; + static bool tegra210_i2s_wr_reg(struct device *dev, unsigned int reg) { switch (reg) { @@ -895,7 +926,68 @@ static bool tegra210_i2s_volatile_reg(struct device *d= ev, unsigned int reg) } } =20 -static const struct regmap_config tegra210_i2s_regmap_config =3D { +static bool tegra264_i2s_wr_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_ENABLE ... TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_RX_INT_MASK ... TEGRA264_I2S_RX_CYA: + case TEGRA264_I2S_TX_ENABLE ... TEGRA264_I2S_TX_SOFT_RESET: + case TEGRA264_I2S_TX_INT_MASK ... TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE: + case TEGRA264_I2S_TX_FIFO_THRESHOLD ... TEGRA264_I2S_TX_CYA: + case TEGRA264_I2S_ENABLE ... TEGRA264_I2S_CG: + case TEGRA264_I2S_INT_SET ... TEGRA264_I2S_INT_MASK: + case TEGRA264_I2S_CTRL ... TEGRA264_I2S_CYA: + return true; + default: + return false; + }; +} + +static bool tegra264_i2s_rd_reg(struct device *dev, unsigned int reg) +{ + if (tegra264_i2s_wr_reg(dev, reg)) + return true; + + switch (reg) { + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA264_I2S_RX_CIF_FIFO_STATUS: + case TEGRA264_I2S_TX_STATUS: + case TEGRA264_I2S_TX_INT_STATUS: + case TEGRA264_I2S_TX_FIFO_RD_DATA: + case TEGRA264_I2S_TX_CIF_FIFO_STATUS: + case TEGRA264_I2S_STATUS: + case TEGRA264_I2S_INT_STATUS: + case TEGRA264_I2S_PIO_MODE_ENABLE: + case TEGRA264_I2S_PAD_MACRO_STATUS: + return true; + default: + return false; + }; +} + +static bool tegra264_i2s_volatile_reg(struct device *dev, unsigned int reg) +{ + switch (reg) { + case TEGRA210_I2S_RX_SOFT_RESET: + case TEGRA210_I2S_RX_STATUS: + case TEGRA210_I2S_RX_INT_STATUS: + case TEGRA264_I2S_RX_CIF_FIFO_STATUS: + case TEGRA264_I2S_TX_STATUS: + case TEGRA264_I2S_TX_INT_STATUS: + case TEGRA264_I2S_TX_FIFO_RD_DATA: + case TEGRA264_I2S_TX_CIF_FIFO_STATUS: + case TEGRA264_I2S_STATUS: + case TEGRA264_I2S_INT_STATUS: + case TEGRA264_I2S_TX_SOFT_RESET: + case TEGRA264_I2S_PAD_MACRO_STATUS: + return true; + default: + return false; + }; +} + +static const struct regmap_config tegra210_regmap_conf =3D { .reg_bits =3D 32, .reg_stride =3D 4, .val_bits =3D 32, @@ -942,20 +1034,34 @@ static void tegra210_parse_client_convert(struct dev= ice *dev) i2s->client_sample_format =3D simple_util_get_sample_fmt(&data); } =20 +static const struct regmap_config tegra264_regmap_conf =3D { + .reg_bits =3D 32, + .reg_stride =3D 4, + .val_bits =3D 32, + .max_register =3D TEGRA264_I2S_PAD_MACRO_STATUS, + .writeable_reg =3D tegra264_i2s_wr_reg, + .readable_reg =3D tegra264_i2s_rd_reg, + .volatile_reg =3D tegra264_i2s_volatile_reg, + .reg_defaults =3D tegra264_i2s_reg_defaults, + .num_reg_defaults =3D ARRAY_SIZE(tegra264_i2s_reg_defaults), + .cache_type =3D REGCACHE_FLAT, +}; + static int tegra210_i2s_probe(struct platform_device *pdev) { struct device *dev =3D &pdev->dev; struct tegra210_i2s *i2s; void __iomem *regs; - int err; + int err, id; =20 i2s =3D devm_kzalloc(dev, sizeof(*i2s), GFP_KERNEL); if (!i2s) return -ENOMEM; =20 + i2s->soc_data =3D of_device_get_match_data(&pdev->dev); i2s->rx_fifo_th =3D DEFAULT_I2S_RX_FIFO_THRESHOLD; - i2s->tx_mask =3D DEFAULT_I2S_SLOT_MASK; - i2s->rx_mask =3D DEFAULT_I2S_SLOT_MASK; + i2s->tx_mask =3D i2s->soc_data->slot_mask; + i2s->rx_mask =3D i2s->soc_data->slot_mask; i2s->loopback =3D false; i2s->client_sample_format =3D -EINVAL; =20 @@ -981,7 +1087,7 @@ static int tegra210_i2s_probe(struct platform_device *= pdev) return PTR_ERR(regs); =20 i2s->regmap =3D devm_regmap_init_mmio(dev, regs, - &tegra210_i2s_regmap_config); + i2s->soc_data->regmap_conf); if (IS_ERR(i2s->regmap)) { dev_err(dev, "regmap init failed\n"); return PTR_ERR(i2s->regmap); @@ -991,7 +1097,13 @@ static int tegra210_i2s_probe(struct platform_device = *pdev) =20 regcache_cache_only(i2s->regmap, true); =20 - err =3D devm_snd_soc_register_component(dev, &tegra210_i2s_cmpnt, + /* Update the dais max channel as per soc */ + for (id =3D 0; id < ARRAY_SIZE(tegra210_i2s_dais); id++) { + tegra210_i2s_dais[id].playback.channels_max =3D i2s->soc_data->max_ch; + tegra210_i2s_dais[id].capture.channels_max =3D i2s->soc_data->max_ch; + } + + err =3D devm_snd_soc_register_component(dev, i2s->soc_data->i2s_cmpnt, tegra210_i2s_dais, ARRAY_SIZE(tegra210_i2s_dais)); if (err) { @@ -1015,8 +1127,31 @@ static const struct dev_pm_ops tegra210_i2s_pm_ops = =3D { SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) }; =20 +static const struct tegra_i2s_soc_data soc_data_tegra210 =3D { + .regmap_conf =3D &tegra210_regmap_conf, + .i2s_cmpnt =3D &tegra210_i2s_cmpnt, + .max_ch =3D TEGRA210_I2S_MAX_CHANNEL, + .tx_offset =3D TEGRA210_I2S_TX_OFFSET, + .i2s_ctrl_offset =3D TEGRA210_I2S_CTRL_OFFSET, + .fsync_width_mask =3D I2S_CTRL_FSYNC_WIDTH_MASK, + .fsync_width_shift =3D I2S_FSYNC_WIDTH_SHIFT, + .slot_mask =3D DEFAULT_I2S_SLOT_MASK, +}; + +static const struct tegra_i2s_soc_data soc_data_tegra264 =3D { + .regmap_conf =3D &tegra264_regmap_conf, + .i2s_cmpnt =3D &tegra264_i2s_cmpnt, + .max_ch =3D TEGRA264_I2S_MAX_CHANNEL, + .tx_offset =3D TEGRA264_I2S_TX_OFFSET, + .i2s_ctrl_offset =3D TEGRA264_I2S_CTRL_OFFSET, + .fsync_width_mask =3D TEGRA264_I2S_CTRL_FSYNC_WIDTH_MASK, + .fsync_width_shift =3D TEGRA264_I2S_FSYNC_WIDTH_SHIFT, + .slot_mask =3D TEGRA264_DEFAULT_I2S_SLOT_MASK, +}; + static const struct of_device_id tegra210_i2s_of_match[] =3D { - { .compatible =3D "nvidia,tegra210-i2s" }, + { .compatible =3D "nvidia,tegra210-i2s", .data =3D &soc_data_tegra210 }, + { .compatible =3D "nvidia,tegra264-i2s", .data =3D &soc_data_tegra264 }, {}, }; MODULE_DEVICE_TABLE(of, tegra210_i2s_of_match); diff --git a/sound/soc/tegra/tegra210_i2s.h b/sound/soc/tegra/tegra210_i2s.h index 543332de7405..42be2137342c 100644 --- a/sound/soc/tegra/tegra210_i2s.h +++ b/sound/soc/tegra/tegra210_i2s.h @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0-only - * SPDX-FileCopyrightText: Copyright (c) 2020-2024 NVIDIA CORPORATION & AF= FILIATES. + * SPDX-FileCopyrightText: Copyright (c) 2020-2025 NVIDIA CORPORATION & AF= FILIATES. * All rights reserved. * * tegra210_i2s.h - Definitions for Tegra210 I2S driver @@ -47,9 +47,38 @@ #define TEGRA210_I2S_CLK_TRIM 0xac #define TEGRA210_I2S_CYA 0xb0 =20 +/* T264 specific registers */ +#define TEGRA264_I2S_RX_FIFO_WR_ACCESS_MODE 0x30 +#define TEGRA264_I2S_RX_CYA 0x3c +#define TEGRA264_I2S_RX_CIF_FIFO_STATUS 0x40 +#define TEGRA264_I2S_TX_ENABLE 0x80 +#define TEGRA264_I2S_TX_SOFT_RESET 0x84 +#define TEGRA264_I2S_TX_STATUS 0x8c +#define TEGRA264_I2S_TX_INT_STATUS 0x90 +#define TEGRA264_I2S_TX_INT_MASK 0x94 +#define TEGRA264_I2S_TX_CIF_CTRL 0xa0 +#define TEGRA264_I2S_TX_FIFO_RD_ACCESS_MODE 0xb0 +#define TEGRA264_I2S_TX_FIFO_RD_DATA 0xb4 +#define TEGRA264_I2S_TX_FIFO_THRESHOLD 0xb8 +#define TEGRA264_I2S_TX_CYA 0xbc +#define TEGRA264_I2S_TX_CIF_FIFO_STATUS 0xc0 +#define TEGRA264_I2S_ENABLE 0x100 +#define TEGRA264_I2S_CG 0x108 +#define TEGRA264_I2S_STATUS 0x10c +#define TEGRA264_I2S_INT_STATUS 0x110 +#define TEGRA264_I2S_INT_SET 0x114 +#define TEGRA264_I2S_INT_MASK 0x11c +#define TEGRA264_I2S_CTRL 0x12c +#define TEGRA264_I2S_TIMING 0x130 +#define TEGRA264_I2S_CYA 0x13c +#define TEGRA264_I2S_PIO_MODE_ENABLE 0x140 +#define TEGRA264_I2S_PAD_MACRO_STATUS 0x144 + /* Bit fields, shifts and masks */ #define I2S_DATA_SHIFT 8 #define I2S_CTRL_DATA_OFFSET_MASK (0x7ff << I2S_DATA_SHIFT) +#define TEGRA264_I2S_FSYNC_WIDTH_SHIFT 23 +#define TEGRA264_I2S_CTRL_FSYNC_WIDTH_MASK (0x1ff << TEGRA264_I2S_FSYNC_WI= DTH_SHIFT) =20 #define I2S_EN_SHIFT 0 #define I2S_EN_MASK BIT(I2S_EN_SHIFT) @@ -102,6 +131,14 @@ #define DEFAULT_I2S_RX_FIFO_THRESHOLD 3 =20 #define DEFAULT_I2S_SLOT_MASK 0xffff +#define TEGRA210_I2S_TX_OFFSET 0 +#define TEGRA210_I2S_CTRL_OFFSET 0 +#define TEGRA210_I2S_MAX_CHANNEL 16 + +#define TEGRA264_DEFAULT_I2S_SLOT_MASK 0xffffffff +#define TEGRA264_I2S_TX_OFFSET 0x40 +#define TEGRA264_I2S_CTRL_OFFSET 0x8c +#define TEGRA264_I2S_MAX_CHANNEL 32 =20 enum tegra210_i2s_path { I2S_RX_PATH, @@ -109,7 +146,19 @@ enum tegra210_i2s_path { I2S_PATHS, }; =20 +struct tegra_i2s_soc_data { + const struct regmap_config *regmap_conf; + const struct snd_soc_component_driver *i2s_cmpnt; + unsigned int max_ch; + unsigned int tx_offset; + unsigned int i2s_ctrl_offset; + unsigned int fsync_width_mask; + unsigned int fsync_width_shift; + unsigned int slot_mask; +}; + struct tegra210_i2s { + const struct tegra_i2s_soc_data *soc_data; struct clk *clk_i2s; struct clk *clk_sync_input; struct regmap *regmap; --=20 2.17.1