From nobody Mon Feb 9 17:35:31 2026 Received: from mx0b-001ae601.pphosted.com (mx0b-001ae601.pphosted.com [67.231.152.168]) (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 B32EA2D9ED9; Fri, 17 Oct 2025 16:16:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=67.231.152.168 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760717792; cv=fail; b=qZ3WKIDsOuttxY/bndcm7/u2m00K0d5MRBVnC00rnaPPM2/ftnYuj2LLd3DwYc1Fc29fy7m91J62qVjWRZKTZuaECarNreF6qhjXyzgpHU88NbqGxxwsgj5/Pf6GQIBquuAdlIcYwWp0xgvfditZFNayE90VRJpiO8HpTrlreX8= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760717792; c=relaxed/simple; bh=l3pNCkiyUnZ5x3phrGFoF0xPvY5RlCLV2Ijfy53Y2Q4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Loh3UkaSYMyd/Z8W8YZijVpLiWc1WSRtdpgqFfEU7+/TsZAutOG9ERP9PxCn4VU+d2zOdTcZn4fvbyPKmBx1aRU8X/qxUTYbPSPiN4VRLKqHEmJsupRDinGBib59jXP+/BP/S+2ey4ialkOHHgK/9/SC8rFSnMQbQqQ+zPKLUdo= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=opensource.cirrus.com; spf=pass smtp.mailfrom=opensource.cirrus.com; dkim=pass (2048-bit key) header.d=cirrus.com header.i=@cirrus.com header.b=Vu1RV2cL; dkim=pass (1024-bit key) header.d=cirrus4.onmicrosoft.com header.i=@cirrus4.onmicrosoft.com header.b=D6ru/oVh; arc=fail smtp.client-ip=67.231.152.168 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=opensource.cirrus.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=opensource.cirrus.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=cirrus.com header.i=@cirrus.com header.b="Vu1RV2cL"; dkim=pass (1024-bit key) header.d=cirrus4.onmicrosoft.com header.i=@cirrus4.onmicrosoft.com header.b="D6ru/oVh" Received: from pps.filterd (m0077474.ppops.net [127.0.0.1]) by mx0b-001ae601.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 59H8PGfb4017904; Fri, 17 Oct 2025 11:16:01 -0500 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus.com; h=cc :content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s= PODMain02222019; bh=StCWOFfXiWO6C333jKx4E39X0RNxaz7WpvtB3gaR6Ks=; b= Vu1RV2cLUxmFoNKbPfvRzriNYAj0viy1C4AYqyAIcF/1HbhUqj4pAlOjvEv8x7ZQ Dk9LlyXBADDqMr7YDE2uQ2i//K/WH7ocbA57nSpg7jJXWhldyvkiMRx2OPzky0kg fhsiuBqavm4QrgcwFPNKyrACEOFkQ+4S10doTY3BRcWHiR255oJnM/JfVxTcTxvi VeL7/I3gMFmHuSCDMqeP88ID5zhWJFP5/CovCvQRYabxjNXkfjnSIxBkC9C9x0GG 26erLrMZR/CnmmwGZYnKdzO5+W8PiH0/i3HRmeGwlf+ISdW+LNrs7YmowRuw7EoT Yg7gOo8P/QXWG9f1ueFwpA== Received: from ch5pr02cu005.outbound.protection.outlook.com (mail-northcentralusazon11022121.outbound.protection.outlook.com [40.107.200.121]) by mx0b-001ae601.pphosted.com (PPS) with ESMTPS id 49u1mnhsbe-1 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Fri, 17 Oct 2025 11:16:01 -0500 (CDT) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=orQQvOfLht3+kLwTB80M69nluEOcALa0RaOqIr+hWE8ZWPeFGAHWfzkvzEbxY7FFNAgTG+r2nwg1ywkQt4x4O7TgafEb/rnZZUKKuRchYayGFPtuDbyxWwWr0ekGychWlYTCeTTT/a4Jks53b/RM5+gPw6RzpgsW9y7k7LIRBz89QpIJ5eh/843KIay3dbE+GfCuDI2YEeriDsUtTwAXgw9NWys8V1eKYe4pxRZK8g+wh+n3ULovM5AD4ME9U9hxu49YyHlHcFQylDUTNaF7ZTcIxX4YTvtvuw83WTbeF6wzG5jI/H5LdpKXUiREHVnwC3WHLg362JoYNEWBbBm9Bg== 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=StCWOFfXiWO6C333jKx4E39X0RNxaz7WpvtB3gaR6Ks=; b=L/rFEDouXcNgtm9Pul2Kbq8oht45Jv9BA9lUYXWAQaE0wI2I0h67Hm4qonB927rPhLm3Oy6m+L51TVJSOXFPO167ZvCinppO5V3u9LVD9h9fUVQ+qsWrWWaorjA/6mhlbcIqFWc1J0m8xsIREToPT/Qwr1utm/ahoRDbmU98RLJJm9N0w+vevepQxjmUKNhBstUKCHgJridCkysg8JBKBbKaJbSSJJ+3osdS/zJ7KuBjbIWw6JJMBc9kJ4iP70cZ6PKjSX9dL/BkJFxPOI/uR0UdCYoH+b7tH3lW6TW8zPR4EzuAsAKnEgw/ZxApFcDkjdpSL7IMUGc8vAhCj6RJpA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=fail (sender ip is 84.19.233.75) smtp.rcpttodomain=cirrus.com smtp.mailfrom=opensource.cirrus.com; dmarc=fail (p=reject sp=reject pct=100) action=oreject header.from=opensource.cirrus.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=cirrus4.onmicrosoft.com; s=selector2-cirrus4-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=StCWOFfXiWO6C333jKx4E39X0RNxaz7WpvtB3gaR6Ks=; b=D6ru/oVhuikR/FzdAgIx/gwymZ5UObSJnBD6kcgsnxiEngVdwGZCCIK67wf5MgwHons4P+1hVL/8Fc+X6Q3piF0LktZ/ROOjhqSOuspTwv3pCPtUvgMHXAjyz72189tch64kMwET7nCNwb0rUo+Fr/M50G2Sbb+ZlDOIFjJVeOI= Received: from SA9PR13CA0101.namprd13.prod.outlook.com (2603:10b6:806:24::16) by SA3PR19MB8241.namprd19.prod.outlook.com (2603:10b6:806:39e::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9228.12; Fri, 17 Oct 2025 16:15:58 +0000 Received: from SN1PEPF0002BA4C.namprd03.prod.outlook.com (2603:10b6:806:24:cafe::7c) by SA9PR13CA0101.outlook.office365.com (2603:10b6:806:24::16) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9253.7 via Frontend Transport; Fri, 17 Oct 2025 16:15:58 +0000 X-MS-Exchange-Authentication-Results: spf=fail (sender IP is 84.19.233.75) smtp.mailfrom=opensource.cirrus.com; dkim=none (message not signed) header.d=none;dmarc=fail action=oreject header.from=opensource.cirrus.com; Received-SPF: Fail (protection.outlook.com: domain of opensource.cirrus.com does not designate 84.19.233.75 as permitted sender) receiver=protection.outlook.com; client-ip=84.19.233.75; helo=edirelay1.ad.cirrus.com; Received: from edirelay1.ad.cirrus.com (84.19.233.75) by SN1PEPF0002BA4C.mail.protection.outlook.com (10.167.242.69) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9253.7 via Frontend Transport; Fri, 17 Oct 2025 16:15:57 +0000 Received: from ediswmail9.ad.cirrus.com (ediswmail9.ad.cirrus.com [198.61.86.93]) by edirelay1.ad.cirrus.com (Postfix) with ESMTPS id 66B43406547; Fri, 17 Oct 2025 16:15:56 +0000 (UTC) Received: from lonswws03.ad.cirrus.com (lonswws03.ad.cirrus.com [198.90.188.34]) by ediswmail9.ad.cirrus.com (Postfix) with ESMTPSA id EDE83820249; Fri, 17 Oct 2025 16:15:55 +0000 (UTC) From: Vitaly Rodionov To: Mark Brown Cc: Krzysztof Kozlowski , Takashi Iwai , Jaroslav Kysela , David Rhodes , Richard Fitzgerald , Liam Girdwood , Rob Herring , Conor Dooley , linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org, patches@opensource.cirrus.com, devicetree@vger.kernel.org, Simon Trimmer , Vitaly Rodionov Subject: [PATCH v4 07/11] ASoC: cs530x: Add CODEC and DAC support Date: Fri, 17 Oct 2025 17:15:34 +0100 Message-ID: <20251017161543.214235-8-vitalyr@opensource.cirrus.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20251017161543.214235-1-vitalyr@opensource.cirrus.com> References: <20251017161543.214235-1-vitalyr@opensource.cirrus.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: SN1PEPF0002BA4C:EE_|SA3PR19MB8241:EE_ X-MS-Office365-Filtering-Correlation-Id: 87eff520-2a6b-4be7-2767-08de0d987505 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700013|61400799027|7416014|376014|82310400026; X-Microsoft-Antispam-Message-Info: =?us-ascii?Q?WX2X+LItay7AfrjJjZpw3kg9k13dRTPhc2WEI/NdGWCNZCLF+iPeb+5d+i8a?= =?us-ascii?Q?Bv8epoZ1e9sgr1sUd9Fx8kH0fYzFmQ8Zpc7MV8an8ro2Az0Y23jQJ+FniFVp?= =?us-ascii?Q?OBN3JwcW1YdnITpN+VtOl7o37jqmCRnF+DT4mEcMtLVQdT61CDSDqwJQmSb1?= =?us-ascii?Q?rB5Kv5bCD6YJLG+SdfXm3ausxD08IyV0K1v32vVVXUabW9ierPda0vrLdLkX?= =?us-ascii?Q?+l9AuPi7fmAoV+TKv1aV9e7w0lZYqDLNySL2K3lT4/yoEIXOTy/tJY5sgkgb?= =?us-ascii?Q?0OsoUTaBst9y6jKZtvVM2hNWZcRTVIzZvdr2SjwJMyGOzX2Yv7iPW70OeiG0?= =?us-ascii?Q?gd8PnbUhXfEXDALaxdxiqd87x+6FY2vP6nUtMyiStNCNAEvtP2OhvX5k7utr?= =?us-ascii?Q?PaXXCNVHJa4rK+JTMaI/pqXVYE+ZlO/53rlx6NHMBBP5OKEb8rWtXCZqR7NC?= =?us-ascii?Q?HmIUHlbB34qNQon1Ppdq4krkUzS7pp3wyYdzPBqr34/tkJYXEu8K7q75HQjd?= =?us-ascii?Q?tmiKJh6hddaeH/Y9oYHtMNuTsFCLJac18vUuwEHF5QB9sGgEcoHOyrRbfzta?= =?us-ascii?Q?g21N/2zgMTAptcwjwJ9kJNLNiEjwj89xR0g2phe6wWLpYU+2Zy2f0YCjzKZh?= =?us-ascii?Q?b3I0MyS6I0Icq0zNrwWq8DHdOo3LXDohzwFGEoVCXomkST+vsFWHvNwXpDSh?= =?us-ascii?Q?YFtQTejeS5i01kXx1lk74gTWgAq5JTiecJZ9oS5ON7zNa6I7MNupWCP7clcn?= =?us-ascii?Q?Ilj+v3CFYs64uxfKqoYBxR5m638VFoKk/PXffhhPuzLPreU5lp/713S028qO?= =?us-ascii?Q?PGpknnCFh5YvmwsEM7aNgc7zPiFjDMOspHO+cWVzhpaO318Edu1kAXqCyR+O?= =?us-ascii?Q?9XMzeLU1Cm0+0j2sAJnldf5PVKKPZeQnJGirKrq1uQsN1nyLNAy56b2AMgAV?= =?us-ascii?Q?TH140O/ih5FueArOHjdVSm0JTmEeuFooTTc+Gkrqf9UiKkwRY56JR0ZlKCND?= =?us-ascii?Q?4amm4454Tl5hKaY/F3S0rj/Tg27uDGhUIprtznmWs5LqINSbkpJOLMAzajQY?= =?us-ascii?Q?Q55yMq0dIZZEhW1NkZrSrnwG5Gf+cBz0omWTB4SKvg+PGnlepiGToRoYIHin?= =?us-ascii?Q?JRB00ThYLpPq8UXhOX60DiJeUNardu6KPTYyGkjWijJMfP27UA+dJK7aFf2N?= =?us-ascii?Q?91rHlaG8wzpvGrO57DvBA7a3Oz8qI1cW2UiLiyqLBN5g6oJKjzXOJuJAOGlL?= =?us-ascii?Q?5J4L6N9z7b7+GaFawFwMMGvy5jhWWv1xM6lj0Va2VESMZr5QPB4VJeanhVgq?= =?us-ascii?Q?HutqWDsz4vNY4x5Q4xEHMikvICFqwk2KrJ08fC2Hzt/pFl+gOkunJGAN7Grg?= =?us-ascii?Q?a4DeOluCN3v1OXvjgU4AbFwDx/bQxUNnq8cBrvbYhgAmbeL8h/4Ws31fS2+b?= =?us-ascii?Q?Vx7qpV0ZSEeok6wSUwc8dXDTrwrNWbfjq7jSxLtLAJBiRh/vdyJKeduEyhAx?= =?us-ascii?Q?SL7WsaVVK3Cw6/ya+7ad//mdp8/EGCIZBwacb61eF9onE8f36LJVivKaT+qE?= =?us-ascii?Q?bOnAKvscaPPjA8LlYUo=3D?= X-Forefront-Antispam-Report: CIP:84.19.233.75;CTRY:GB;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:edirelay1.ad.cirrus.com;PTR:InfoDomainNonexistent;CAT:NONE;SFS:(13230040)(36860700013)(61400799027)(7416014)(376014)(82310400026);DIR:OUT;SFP:1102; X-OriginatorOrg: opensource.cirrus.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 17 Oct 2025 16:15:57.9945 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 87eff520-2a6b-4be7-2767-08de0d987505 X-MS-Exchange-CrossTenant-Id: bec09025-e5bc-40d1-a355-8e955c307de8 X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=bec09025-e5bc-40d1-a355-8e955c307de8;Ip=[84.19.233.75];Helo=[edirelay1.ad.cirrus.com] X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: TreatMessagesAsInternal-SN1PEPF0002BA4C.namprd03.prod.outlook.com X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA3PR19MB8241 X-Authority-Analysis: v=2.4 cv=POACOPqC c=1 sm=1 tr=0 ts=68f26bc1 cx=c_pps a=PlzX2GN61/O3EU/AUs1JWA==:117 a=h1hSm8JtM9GN1ddwPAif2w==:17 a=6eWqkTHjU83fiwn7nKZWdM+Sl24=:19 a=z/mQ4Ysz8XfWz/Q5cLBRGdckG28=:19 a=x6icFKpwvdMA:10 a=s63m1ICgrNkA:10 a=RWc_ulEos4gA:10 a=VkNPw1HP01LnGYTKEx00:22 a=w1d2syhTAAAA:8 a=L8ub6Hg6ihGcwRW8v1IA:9 a=cPQSjfK2_nFv0Q5t_7PE:22 X-Proofpoint-ORIG-GUID: sTHUFQL9pyzinRHYBQrbkYX8741dpos2 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUxMDE3MDEyMCBTYWx0ZWRfX6oBzCWv3JTkd 7I2hTKpjhR2p9nIrgIARmC7qsXjVQrdt0gDYN3NHgTOFuxzNUhCXbvwmwa92cgeULa+uWVzWdOM JICnXD8X3cYyfqLvhLYlz1wf5RF7g14wqrCF68hMvZfkZ56QJQw807UsReckaxzdTvYKrYzprnP MtuinYQfbjPjTcQd3YNFBMuCiDYL8tKM1E+qfNPVrMh+t8bw4YO0abJ8gxKpy9bkfpmhGPVoWg6 EUs+dD7KbGCS/Z+xZ8rdA0mKK+79Ne15VugUZP0w3J6MNwTwk3ZAc72eXLOn+y4x1JKJ+DDohco WgL9NC+1DKzyNbmNt4stKhjsbywcEKDmM0vV7cAXBkAeKZKRlptNI5eAZ5EDSXnqUykEkxl9BtW a/qlHv3GnSxfNndhvY1trEOcABn1Kg== X-Proofpoint-GUID: sTHUFQL9pyzinRHYBQrbkYX8741dpos2 X-Proofpoint-Spam-Reason: safe Content-Type: text/plain; charset="utf-8" From: Simon Trimmer - Added DAC register address constants - Add the new registers to the regmap config - Renamed constants that are shared between the DACs and ADCs - Add the device IDs and device names of the CODEC and DACs along with their different capabilities - Add DAPM widgets, ALSA controls and event handling for the DAC functionality - Add Playback DAI support Signed-off-by: Simon Trimmer Signed-off-by: Vitaly Rodionov --- sound/soc/codecs/cs530x-i2c.c | 16 ++ sound/soc/codecs/cs530x.c | 413 +++++++++++++++++++++++++++++++--- sound/soc/codecs/cs530x.h | 60 +++-- 3 files changed, 441 insertions(+), 48 deletions(-) diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c index d6b7883ba7b9..ab410826f777 100644 --- a/sound/soc/codecs/cs530x-i2c.c +++ b/sound/soc/codecs/cs530x-i2c.c @@ -14,6 +14,18 @@ =20 static const struct of_device_id cs530x_of_match[] =3D { { + .compatible =3D "cirrus,cs4282", + .data =3D (void *)CS4282, + }, { + .compatible =3D "cirrus,cs4302", + .data =3D (void *)CS4302, + }, { + .compatible =3D "cirrus,cs4304", + .data =3D (void *)CS4304, + }, { + .compatible =3D "cirrus,cs4308", + .data =3D (void *)CS4308, + }, { .compatible =3D "cirrus,cs5302", .data =3D (void *)CS5302, }, { @@ -28,6 +40,10 @@ static const struct of_device_id cs530x_of_match[] =3D { MODULE_DEVICE_TABLE(of, cs530x_of_match); =20 static const struct i2c_device_id cs530x_i2c_id[] =3D { + { "cs4282", CS4282 }, + { "cs4302", CS4302 }, + { "cs4304", CS4304 }, + { "cs4308", CS4308 }, { "cs5302", CS5302 }, { "cs5304", CS5304 }, { "cs5308", CS5308 }, diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c index 336ed5f225ea..25dbf401b15d 100644 --- a/sound/soc/codecs/cs530x.c +++ b/sound/soc/codecs/cs530x.c @@ -45,6 +45,18 @@ static const struct reg_default cs530x_reg_defaults[] = =3D { { CS530X_IN_VOL_CTRL3_1, 0x8000 }, { CS530X_IN_VOL_CTRL4_0, 0x8000 }, { CS530X_IN_VOL_CTRL4_1, 0x8000 }, + { CS530X_OUT_ENABLES, 0 }, + { CS530X_OUT_RAMP_SUM, 0x0022 }, + { CS530X_OUT_FILTER, 0 }, + { CS530X_OUT_INV, 0 }, + { CS530X_OUT_VOL_CTRL1_0, 0x8000 }, + { CS530X_OUT_VOL_CTRL1_1, 0x8000 }, + { CS530X_OUT_VOL_CTRL2_0, 0x8000 }, + { CS530X_OUT_VOL_CTRL2_1, 0x8000 }, + { CS530X_OUT_VOL_CTRL3_0, 0x8000 }, + { CS530X_OUT_VOL_CTRL3_1, 0x8000 }, + { CS530X_OUT_VOL_CTRL4_0, 0x8000 }, + { CS530X_OUT_VOL_CTRL4_1, 0x8000 }, { CS530X_PAD_FN, 0 }, { CS530X_PAD_LVL, 0 }, }; @@ -70,6 +82,19 @@ static bool cs530x_read_and_write_regs(unsigned int reg) case CS530X_IN_VOL_CTRL3_1: case CS530X_IN_VOL_CTRL4_0: case CS530X_IN_VOL_CTRL4_1: + case CS530X_OUT_ENABLES: + case CS530X_OUT_RAMP_SUM: + case CS530X_OUT_DEEMPH: + case CS530X_OUT_FILTER: + case CS530X_OUT_INV: + case CS530X_OUT_VOL_CTRL1_0: + case CS530X_OUT_VOL_CTRL1_1: + case CS530X_OUT_VOL_CTRL2_0: + case CS530X_OUT_VOL_CTRL2_1: + case CS530X_OUT_VOL_CTRL3_0: + case CS530X_OUT_VOL_CTRL3_1: + case CS530X_OUT_VOL_CTRL4_0: + case CS530X_OUT_VOL_CTRL4_1: case CS530X_PAD_FN: case CS530X_PAD_LVL: return true; @@ -94,6 +119,7 @@ static bool cs530x_writeable_register(struct device *dev= , unsigned int reg) switch (reg) { case CS530X_SW_RESET: case CS530X_IN_VOL_CTRL5: + case CS530X_OUT_VOL_CTRL5: return true; default: return cs530x_read_and_write_regs(reg); @@ -116,7 +142,7 @@ static int cs530x_put_volsw_vu(struct snd_kcontrol *kco= ntrol, goto volsw_err; =20 /* Write IN_VU bit for the volume change to take effect */ - regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_IN_VU); + regmap_write(regmap, CS530X_IN_VOL_CTRL5, CS530X_INOUT_VU); =20 volsw_err: snd_soc_dapm_mutex_unlock(dapm); @@ -126,7 +152,7 @@ static int cs530x_put_volsw_vu(struct snd_kcontrol *kco= ntrol, =20 static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1270, 50, 0); =20 -static const char * const cs530x_in_filter_text[] =3D { +static const char * const cs530x_inout_filter_text[] =3D { "Min Phase Slow Roll-off", "Min Phase Fast Roll-off", "Linear Phase Slow Roll-off", @@ -134,24 +160,36 @@ static const char * const cs530x_in_filter_text[] =3D= { }; =20 static SOC_ENUM_SINGLE_DECL(cs530x_in_filter_enum, CS530X_IN_FILTER, - CS530X_IN_FILTER_SHIFT, - cs530x_in_filter_text); + CS530X_INOUT_FILTER_SHIFT, + cs530x_inout_filter_text); =20 -static const char * const cs530x_in_4ch_sum_text[] =3D { +static SOC_ENUM_SINGLE_DECL(cs530x_out_filter_enum, CS530X_OUT_FILTER, + CS530X_INOUT_FILTER_SHIFT, + cs530x_inout_filter_text); + +static const char * const cs530x_4ch_sum_text[] =3D { "None", "Groups of 2", "Groups of 4", }; =20 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch4_enum, CS530X_IN_RAMP_SUM, - CS530X_IN_SUM_MODE_SHIFT, - cs530x_in_4ch_sum_text); + CS530X_INOUT_SUM_MODE_SHIFT, + cs530x_4ch_sum_text); =20 static const struct snd_kcontrol_new cs530x_in_sum_4ch_controls[] =3D { SOC_ENUM("IN Sum Select", cs530x_in_sum_ch4_enum), }; =20 -static const char * const cs530x_in_8ch_sum_text[] =3D { +static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch4_enum, CS530X_OUT_RAMP_SUM, + CS530X_INOUT_SUM_MODE_SHIFT, + cs530x_4ch_sum_text); + +static const struct snd_kcontrol_new cs530x_out_sum_4ch_controls[] =3D { +SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch4_enum), +}; + +static const char * const cs530x_8ch_sum_text[] =3D { "None", "Groups of 2", "Groups of 4", @@ -159,13 +197,20 @@ static const char * const cs530x_in_8ch_sum_text[] = =3D { }; =20 static SOC_ENUM_SINGLE_DECL(cs530x_in_sum_ch8_enum, CS530X_IN_RAMP_SUM, - CS530X_IN_SUM_MODE_SHIFT, - cs530x_in_8ch_sum_text); + CS530X_INOUT_SUM_MODE_SHIFT, + cs530x_8ch_sum_text); =20 static const struct snd_kcontrol_new cs530x_in_sum_8ch_controls[] =3D { SOC_ENUM("IN Sum Select", cs530x_in_sum_ch8_enum), }; =20 +static SOC_ENUM_SINGLE_DECL(cs530x_out_sum_ch8_enum, CS530X_OUT_RAMP_SUM, + CS530X_INOUT_SUM_MODE_SHIFT, + cs530x_8ch_sum_text); + +static const struct snd_kcontrol_new cs530x_out_sum_8ch_controls[] =3D { +SOC_ENUM("OUT Sum Select", cs530x_out_sum_ch8_enum), +}; =20 static const char * const cs530x_vol_ramp_text[] =3D { "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", @@ -190,8 +235,8 @@ SOC_ENUM("IN DEC Filter Select", cs530x_in_filter_enum), SOC_ENUM("Input Ramp Up", cs530x_ramp_inc_enum), SOC_ENUM("Input Ramp Down", cs530x_ramp_dec_enum), =20 -SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_IN1_INV_SHIFT, 1, 0= ), -SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_IN2_INV_SHIFT, 1, 0= ), +SOC_SINGLE("ADC1 Invert Switch", CS530X_IN_INV, CS530X_INOUT1_INV_SHIFT, 1= , 0), +SOC_SINGLE("ADC2 Invert Switch", CS530X_IN_INV, CS530X_INOUT2_INV_SHIFT, 1= , 0), }; =20 static const struct snd_kcontrol_new cs530x_in_3_to_4_controls[] =3D { @@ -200,8 +245,8 @@ SOC_SINGLE_EXT_TLV("IN3 Volume", CS530X_IN_VOL_CTRL2_0,= 0, 255, 1, SOC_SINGLE_EXT_TLV("IN4 Volume", CS530X_IN_VOL_CTRL2_1, 0, 255, 1, snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), =20 -SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_IN3_INV_SHIFT, 1, 0= ), -SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_IN4_INV_SHIFT, 1, 0= ), +SOC_SINGLE("ADC3 Invert Switch", CS530X_IN_INV, CS530X_INOUT3_INV_SHIFT, 1= , 0), +SOC_SINGLE("ADC4 Invert Switch", CS530X_IN_INV, CS530X_INOUT4_INV_SHIFT, 1= , 0), }; =20 static const struct snd_kcontrol_new cs530x_in_5_to_8_controls[] =3D { @@ -214,10 +259,10 @@ SOC_SINGLE_EXT_TLV("IN7 Volume", CS530X_IN_VOL_CTRL4_= 0, 0, 255, 1, SOC_SINGLE_EXT_TLV("IN8 Volume", CS530X_IN_VOL_CTRL4_1, 0, 255, 1, snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), =20 -SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_IN5_INV_SHIFT, 1, 0= ), -SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_IN6_INV_SHIFT, 1, 0= ), -SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_IN7_INV_SHIFT, 1, 0= ), -SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_IN8_INV_SHIFT, 1, 0= ), +SOC_SINGLE("ADC5 Invert Switch", CS530X_IN_INV, CS530X_INOUT5_INV_SHIFT, 1= , 0), +SOC_SINGLE("ADC6 Invert Switch", CS530X_IN_INV, CS530X_INOUT6_INV_SHIFT, 1= , 0), +SOC_SINGLE("ADC7 Invert Switch", CS530X_IN_INV, CS530X_INOUT7_INV_SHIFT, 1= , 0), +SOC_SINGLE("ADC8 Invert Switch", CS530X_IN_INV, CS530X_INOUT8_INV_SHIFT, 1= , 0), }; =20 static int cs530x_adc_event(struct snd_soc_dapm_widget *w, @@ -233,24 +278,110 @@ static int cs530x_adc_event(struct snd_soc_dapm_widg= et *w, break; case SND_SOC_DAPM_POST_PMU: regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + - (w->shift * 2), CS530X_IN_MUTE); + (w->shift * 2), CS530X_INOUT_MUTE); regmap_clear_bits(regmap, CS530X_IN_VOL_CTRL1_0 + - ((w->shift + 1) * 2), CS530X_IN_MUTE); + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); =20 cs530x->adc_pairs_count--; if (!cs530x->adc_pairs_count) { usleep_range(1000, 1100); return regmap_write(regmap, CS530X_IN_VOL_CTRL5, - CS530X_IN_VU); + CS530X_INOUT_VU); } break; case SND_SOC_DAPM_PRE_PMD: regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + - (w->shift * 2), CS530X_IN_MUTE); + (w->shift * 2), CS530X_INOUT_MUTE); regmap_set_bits(regmap, CS530X_IN_VOL_CTRL1_0 + - ((w->shift + 1) * 2), CS530X_IN_MUTE); + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); return regmap_write(regmap, CS530X_IN_VOL_CTRL5, - CS530X_IN_VU); + CS530X_INOUT_VU); + default: + return -EINVAL; + } + + return 0; +} + +static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_inc_enum, CS530X_OUT_RAMP_SUM, + CS530X_RAMP_RATE_INC_SHIFT, + cs530x_vol_ramp_text); + +static SOC_ENUM_SINGLE_DECL(cs530x_ramp_out_dec_enum, CS530X_OUT_RAMP_SUM, + CS530X_RAMP_RATE_DEC_SHIFT, + cs530x_vol_ramp_text); + +static const struct snd_kcontrol_new cs530x_out_1_to_2_controls[] =3D { +SOC_SINGLE_EXT_TLV("OUT1 Volume", CS530X_OUT_VOL_CTRL1_0, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), +SOC_SINGLE_EXT_TLV("OUT2 Volume", CS530X_OUT_VOL_CTRL1_1, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), + +SOC_ENUM("OUT DEC Filter Select", cs530x_out_filter_enum), +SOC_ENUM("Output Ramp Up", cs530x_ramp_out_inc_enum), +SOC_ENUM("Output Ramp Down", cs530x_ramp_out_dec_enum), + +SOC_SINGLE("DAC1 Invert Switch", CS530X_OUT_INV, CS530X_INOUT1_INV_SHIFT, = 1, 0), +SOC_SINGLE("DAC2 Invert Switch", CS530X_OUT_INV, CS530X_INOUT2_INV_SHIFT, = 1, 0), +}; + +static const struct snd_kcontrol_new cs530x_out_3_to_4_controls[] =3D { +SOC_SINGLE_EXT_TLV("OUT3 Volume", CS530X_OUT_VOL_CTRL2_0, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), +SOC_SINGLE_EXT_TLV("OUT4 Volume", CS530X_OUT_VOL_CTRL2_1, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), + +SOC_SINGLE("DAC3 Invert Switch", CS530X_OUT_INV, CS530X_INOUT3_INV_SHIFT, = 1, 0), +SOC_SINGLE("DAC4 Invert Switch", CS530X_OUT_INV, CS530X_INOUT4_INV_SHIFT, = 1, 0), +}; + +static const struct snd_kcontrol_new cs530x_out_5_to_8_controls[] =3D { +SOC_SINGLE_EXT_TLV("OUT5 Volume", CS530X_OUT_VOL_CTRL3_0, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), +SOC_SINGLE_EXT_TLV("OUT6 Volume", CS530X_OUT_VOL_CTRL3_1, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), +SOC_SINGLE_EXT_TLV("OUT7 Volume", CS530X_OUT_VOL_CTRL4_0, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), +SOC_SINGLE_EXT_TLV("OUT8 Volume", CS530X_OUT_VOL_CTRL4_1, 0, 255, 1, + snd_soc_get_volsw, cs530x_put_volsw_vu, in_vol_tlv), + +SOC_SINGLE("DAC5 Invert Switch", CS530X_OUT_INV, CS530X_INOUT5_INV_SHIFT, = 1, 0), +SOC_SINGLE("DAC6 Invert Switch", CS530X_OUT_INV, CS530X_INOUT6_INV_SHIFT, = 1, 0), +SOC_SINGLE("DAC7 Invert Switch", CS530X_OUT_INV, CS530X_INOUT7_INV_SHIFT, = 1, 0), +SOC_SINGLE("DAC8 Invert Switch", CS530X_OUT_INV, CS530X_INOUT8_INV_SHIFT, = 1, 0), +}; + +static int cs530x_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component =3D snd_soc_dapm_to_component(w->dapm= ); + struct cs530x_priv *cs530x =3D snd_soc_component_get_drvdata(component); + struct regmap *regmap =3D cs530x->regmap; + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + cs530x->dac_pairs_count++; + break; + case SND_SOC_DAPM_POST_PMU: + regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + + (w->shift * 2), CS530X_INOUT_MUTE); + regmap_clear_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); + + cs530x->dac_pairs_count--; + if (!cs530x->dac_pairs_count) { + usleep_range(1000, 1100); + return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, + CS530X_INOUT_VU); + } + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + + (w->shift * 2), CS530X_INOUT_MUTE); + regmap_set_bits(regmap, CS530X_OUT_VOL_CTRL1_0 + + ((w->shift + 1) * 2), CS530X_INOUT_MUTE); + return regmap_write(regmap, CS530X_OUT_VOL_CTRL5, + CS530X_INOUT_VU); default: return -EINVAL; } @@ -266,8 +397,18 @@ static const struct snd_kcontrol_new adc56_ctrl =3D SOC_DAPM_SINGLE_VIRT("Switch", 1); static const struct snd_kcontrol_new adc78_ctrl =3D SOC_DAPM_SINGLE_VIRT("Switch", 1); +static const struct snd_kcontrol_new dac12_ctrl =3D + SOC_DAPM_SINGLE_VIRT("Switch", 1); +static const struct snd_kcontrol_new dac34_ctrl =3D + SOC_DAPM_SINGLE_VIRT("Switch", 1); +static const struct snd_kcontrol_new dac56_ctrl =3D + SOC_DAPM_SINGLE_VIRT("Switch", 1); +static const struct snd_kcontrol_new dac78_ctrl =3D + SOC_DAPM_SINGLE_VIRT("Switch", 1); static const struct snd_kcontrol_new in_hpf_ctrl =3D SOC_DAPM_SINGLE_VIRT("Switch", 1); +static const struct snd_kcontrol_new out_hpf_ctrl =3D + SOC_DAPM_SINGLE_VIRT("Switch", 1); =20 /* General DAPM widgets for all devices */ static const struct snd_soc_dapm_widget cs530x_gen_dapm_widgets[] =3D { @@ -284,7 +425,7 @@ SND_SOC_DAPM_ADC_E("ADC1", NULL, CS530X_IN_ENABLES, 0, = 0, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_ADC("ADC2", NULL, CS530X_IN_ENABLES, 1, 0), SND_SOC_DAPM_SWITCH("ADC12 Enable", SND_SOC_NOPM, 0, 0, &adc12_ctrl), -SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_IN_HPF_EN_SHIFT, +SND_SOC_DAPM_SWITCH("IN HPF", CS530X_IN_FILTER, CS530X_INOUT_HPF_EN_SHIFT, 0, &in_hpf_ctrl), }; =20 @@ -408,6 +549,153 @@ static void cs530x_add_34_adc_widgets(struct snd_soc_= component *component) ARRAY_SIZE(adc_ch3_4_routes)); } =20 +/* DAC's Channels 1 and 2 plus generic DAC DAPM events */ +static const struct snd_soc_dapm_widget cs530x_dac_ch12_dapm_widgets[] =3D= { +SND_SOC_DAPM_OUTPUT("OUT1"), +SND_SOC_DAPM_OUTPUT("OUT2"), +SND_SOC_DAPM_DAC_E("DAC1", NULL, CS530X_OUT_ENABLES, 0, 0, + cs530x_dac_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC("DAC2", NULL, CS530X_OUT_ENABLES, 1, 0), +SND_SOC_DAPM_SWITCH("DAC12 Enable", SND_SOC_NOPM, 0, 0, &dac12_ctrl), +SND_SOC_DAPM_SWITCH("OUT HPF", CS530X_OUT_FILTER, CS530X_INOUT_HPF_EN_SHIF= T, + 0, &out_hpf_ctrl), +}; + +/* DAC's Channels 3 and 4 */ +static const struct snd_soc_dapm_widget cs530x_dac_ch34_dapm_widgets[] =3D= { +SND_SOC_DAPM_OUTPUT("OUT3"), +SND_SOC_DAPM_OUTPUT("OUT4"), +SND_SOC_DAPM_DAC_E("DAC3", NULL, CS530X_OUT_ENABLES, 2, 0, + cs530x_dac_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC("DAC4", NULL, CS530X_OUT_ENABLES, 3, 0), +SND_SOC_DAPM_SWITCH("DAC34 Enable", SND_SOC_NOPM, 0, 0, &dac34_ctrl), +}; + +/* DAC's Channels 5 to 8 */ +static const struct snd_soc_dapm_widget cs530x_dac_ch58_dapm_widgets[] =3D= { +SND_SOC_DAPM_OUTPUT("OUT5"), +SND_SOC_DAPM_OUTPUT("OUT6"), +SND_SOC_DAPM_OUTPUT("OUT7"), +SND_SOC_DAPM_OUTPUT("OUT8"), +SND_SOC_DAPM_DAC_E("DAC5", NULL, CS530X_OUT_ENABLES, 4, 0, + cs530x_dac_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC("DAC6", NULL, CS530X_OUT_ENABLES, 5, 0), +SND_SOC_DAPM_SWITCH("DAC56 Enable", SND_SOC_NOPM, 0, 0, &dac56_ctrl), +SND_SOC_DAPM_DAC_E("DAC7", NULL, CS530X_OUT_ENABLES, 6, 0, + cs530x_dac_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_PRE_PMU), +SND_SOC_DAPM_DAC("DAC8", NULL, CS530X_OUT_ENABLES, 7, 0), +SND_SOC_DAPM_SWITCH("DAC78 Enable", SND_SOC_NOPM, 0, 0, &dac78_ctrl), +}; + +static const struct snd_soc_dapm_route dac_ch1_2_routes[] =3D { + { "DAC1", NULL, "Global Enable" }, + { "DAC2", NULL, "Global Enable" }, + + { "DAC12 Enable", "Switch", "OUT1" }, + { "DAC12 Enable", "Switch", "OUT2" }, + { "DAC1", NULL, "DAC12 Enable" }, + { "DAC2", NULL, "DAC12 Enable" }, + { "OUT HPF", "Switch", "DAC1" }, + { "OUT HPF", "Switch", "DAC2" }, + + { "OUT HPF", NULL, "AIF Playback" }, + { "DAC1", NULL, "AIF Playback" }, + { "DAC2", NULL, "AIF Playback" }, + + { "OUT1", NULL, "DAC1" }, + { "OUT2", NULL, "DAC2" }, +}; + +static const struct snd_soc_dapm_route dac_ch3_4_routes[] =3D { + { "DAC3", NULL, "Global Enable" }, + { "DAC4", NULL, "Global Enable" }, + + { "DAC34 Enable", "Switch", "OUT3" }, + { "DAC34 Enable", "Switch", "OUT4" }, + { "DAC3", NULL, "DAC34 Enable" }, + { "DAC4", NULL, "DAC34 Enable" }, + { "OUT HPF", "Switch", "DAC3" }, + { "OUT HPF", "Switch", "DAC4" }, + + { "DAC3", NULL, "AIF Playback" }, + { "DAC4", NULL, "AIF Playback" }, + + { "OUT3", NULL, "DAC3" }, + { "OUT4", NULL, "DAC4" }, +}; + +static const struct snd_soc_dapm_route dac_ch5_8_routes[] =3D { + { "DAC5", NULL, "Global Enable" }, + { "DAC6", NULL, "Global Enable" }, + + { "DAC56 Enable", "Switch", "OUT5" }, + { "DAC56 Enable", "Switch", "OUT6" }, + { "DAC5", NULL, "DAC56 Enable" }, + { "DAC6", NULL, "DAC56 Enable" }, + { "OUT HPF", "Switch", "DAC5" }, + { "OUT HPF", "Switch", "DAC6" }, + + { "DAC5", NULL, "AIF Playback" }, + { "DAC6", NULL, "AIF Playback" }, + + { "OUT5", NULL, "DAC5" }, + { "OUT6", NULL, "DAC6" }, + + { "DAC7", NULL, "Global Enable" }, + { "DAC8", NULL, "Global Enable" }, + + { "DAC78 Enable", "Switch", "OUT7" }, + { "DAC78 Enable", "Switch", "OUT8" }, + { "DAC7", NULL, "DAC78 Enable" }, + { "DAC8", NULL, "DAC78 Enable" }, + { "OUT HPF", "Switch", "DAC7" }, + { "OUT HPF", "Switch", "DAC8" }, + + { "DAC7", NULL, "AIF Playback" }, + { "DAC8", NULL, "AIF Playback" }, + + { "OUT7", NULL, "DAC7" }, + { "OUT8", NULL, "DAC8" }, +}; + +static void cs530x_add_12_dac_widgets(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm =3D snd_soc_component_get_dapm(componen= t); + + snd_soc_add_component_controls(component, + cs530x_out_1_to_2_controls, + ARRAY_SIZE(cs530x_out_1_to_2_controls)); + + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch12_dapm_widgets, + ARRAY_SIZE(cs530x_dac_ch12_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, dac_ch1_2_routes, + ARRAY_SIZE(dac_ch1_2_routes)); +} + +static void cs530x_add_34_dac_widgets(struct snd_soc_component *component) +{ + struct snd_soc_dapm_context *dapm =3D snd_soc_component_get_dapm(componen= t); + + snd_soc_add_component_controls(component, + cs530x_out_3_to_4_controls, + ARRAY_SIZE(cs530x_out_3_to_4_controls)); + + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch34_dapm_widgets, + ARRAY_SIZE(cs530x_dac_ch34_dapm_widgets)); + + snd_soc_dapm_add_routes(dapm, dac_ch3_4_routes, + ARRAY_SIZE(dac_ch3_4_routes)); +} + static int cs530x_set_bclk(struct snd_soc_component *component, const int = freq) { struct cs530x_priv *cs530x =3D snd_soc_component_get_drvdata(component); @@ -666,8 +954,11 @@ static const struct snd_soc_dai_driver cs530x_dai =3D { .name =3D "cs530x-dai", .capture =3D { .stream_name =3D "AIF Capture", - .channels_min =3D 2, - .channels_max =3D 8, + .rates =3D SNDRV_PCM_RATE_KNOT, + .formats =3D SNDRV_PCM_FMTBIT_S32_LE, + }, + .playback =3D { + .stream_name =3D "AIF Playback", .rates =3D SNDRV_PCM_RATE_KNOT, .formats =3D SNDRV_PCM_FMTBIT_S32_LE, }, @@ -722,6 +1013,43 @@ static int cs530x_component_probe(struct snd_soc_comp= onent *component) ARRAY_SIZE(cs530x_gen_dapm_widgets)); =20 switch (cs530x->devtype) { + case CS4282: + cs530x_add_12_adc_widgets(component); + cs530x_add_12_dac_widgets(component); + break; + case CS4302: + cs530x_add_12_dac_widgets(component); + break; + case CS4304: + cs530x_add_12_dac_widgets(component); + cs530x_add_34_dac_widgets(component); + + num_widgets =3D ARRAY_SIZE(cs530x_out_sum_4ch_controls); + snd_soc_add_component_controls(component, + cs530x_out_sum_4ch_controls, + num_widgets); + break; + case CS4308: + cs530x_add_12_dac_widgets(component); + cs530x_add_34_dac_widgets(component); + + num_widgets =3D ARRAY_SIZE(cs530x_out_5_to_8_controls); + snd_soc_add_component_controls(component, + cs530x_out_5_to_8_controls, + num_widgets); + + num_widgets =3D ARRAY_SIZE(cs530x_out_sum_8ch_controls); + snd_soc_add_component_controls(component, + cs530x_out_sum_8ch_controls, + num_widgets); + + num_widgets =3D ARRAY_SIZE(cs530x_dac_ch58_dapm_widgets); + snd_soc_dapm_new_controls(dapm, cs530x_dac_ch58_dapm_widgets, + num_widgets); + + snd_soc_dapm_add_routes(dapm, dac_ch5_8_routes, + ARRAY_SIZE(dac_ch5_8_routes)); + break; case CS5302: cs530x_add_12_adc_widgets(component); break; @@ -825,9 +1153,20 @@ static int cs530x_check_device_id(struct cs530x_priv = *cs530x) if (ret) return dev_err_probe(dev, ret, "Can't read REV ID\n"); =20 - dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x\n", dev_id, rev); - switch (dev_id) { + case CS530X_2CH_CODEC_DEV_ID: + cs530x->num_dacs =3D 2; + cs530x->num_adcs =3D 2; + break; + case CS530X_2CH_DAC_DEV_ID: + cs530x->num_dacs =3D 2; + break; + case CS530X_4CH_DAC_DEV_ID: + cs530x->num_dacs =3D 4; + break; + case CS530X_8CH_DAC_DEV_ID: + cs530x->num_dacs =3D 8; + break; case CS530X_2CH_ADC_DEV_ID: cs530x->num_adcs =3D 2; break; @@ -842,6 +1181,9 @@ static int cs530x_check_device_id(struct cs530x_priv *= cs530x) dev_id); } =20 + dev_dbg(dev, "Device ID 0x%x Rev ID 0x%x (%d in %d out)\n", dev_id, rev, + cs530x->num_adcs, cs530x->num_dacs); + return 0; } =20 @@ -870,6 +1212,9 @@ static int cs530x_parse_device_properties(struct cs530= x_priv *cs530x) val |=3D CS530X_IN12_HIZ; =20 return regmap_set_bits(regmap, CS530X_IN_HIZ, val); + case 0: + /* No ADCs */ + return 0; default: return dev_err_probe(dev, -EINVAL, "Invalid number of adcs %d\n", @@ -932,7 +1277,15 @@ int cs530x_probe(struct cs530x_priv *cs530x) if (ret) goto err_reset; =20 - cs530x->dev_dai->capture.channels_max =3D cs530x->num_adcs; + if (cs530x->num_adcs) { + cs530x->dev_dai->capture.channels_min =3D 2; + cs530x->dev_dai->capture.channels_max =3D cs530x->num_adcs; + } + + if (cs530x->num_dacs) { + cs530x->dev_dai->playback.channels_min =3D 2; + cs530x->dev_dai->playback.channels_max =3D cs530x->num_dacs; + } =20 ret =3D devm_snd_soc_register_component(dev, &soc_component_dev_cs530x, diff --git a/sound/soc/codecs/cs530x.h b/sound/soc/codecs/cs530x.h index cdd54bfa259f..c10a6766cc7a 100644 --- a/sound/soc/codecs/cs530x.h +++ b/sound/soc/codecs/cs530x.h @@ -15,6 +15,10 @@ #include =20 /* Devices */ +#define CS530X_2CH_CODEC_DEV_ID 0x4282 +#define CS530X_2CH_DAC_DEV_ID 0x4302 +#define CS530X_4CH_DAC_DEV_ID 0x4304 +#define CS530X_8CH_DAC_DEV_ID 0x4308 #define CS530X_2CH_ADC_DEV_ID 0x5302 #define CS530X_4CH_ADC_DEV_ID 0x5304 #define CS530X_8CH_ADC_DEV_ID 0x5308 @@ -45,6 +49,21 @@ #define CS530X_IN_VOL_CTRL4_1 0x000009E #define CS530X_IN_VOL_CTRL5 0x00000A0 =20 +#define CS530X_OUT_ENABLES 0x00000C0 +#define CS530X_OUT_RAMP_SUM 0x00000C2 +#define CS530X_OUT_DEEMPH 0x00000C4 +#define CS530X_OUT_FILTER 0x00000C6 +#define CS530X_OUT_INV 0x00000CA +#define CS530X_OUT_VOL_CTRL1_0 0x00000D0 +#define CS530X_OUT_VOL_CTRL1_1 0x00000D2 +#define CS530X_OUT_VOL_CTRL2_0 0x00000D4 +#define CS530X_OUT_VOL_CTRL2_1 0x00000D6 +#define CS530X_OUT_VOL_CTRL3_0 0x00000D8 +#define CS530X_OUT_VOL_CTRL3_1 0x00000DA +#define CS530X_OUT_VOL_CTRL4_0 0x00000DC +#define CS530X_OUT_VOL_CTRL4_1 0x00000DE +#define CS530X_OUT_VOL_CTRL5 0x00000E0 + #define CS530X_PAD_FN 0x0003D24 #define CS530X_PAD_LVL 0x0003D28 =20 @@ -124,14 +143,14 @@ #define CS530X_14_15_TDM_SLOT_MASK GENMASK(15, 14) #define CS530X_14_15_TDM_SLOT_VAL 7 =20 -/* IN_RAMP_SUM */ +/* IN_RAMP_SUM and OUT_RAMP_SUM */ #define CS530X_RAMP_RATE_INC_SHIFT 0 #define CS530X_RAMP_RATE_DEC_SHIFT 4 -#define CS530X_IN_SUM_MODE_SHIFT 13 +#define CS530X_INOUT_SUM_MODE_SHIFT 13 =20 -/* IN_FILTER */ -#define CS530X_IN_FILTER_SHIFT 8 -#define CS530X_IN_HPF_EN_SHIFT 12 +/* IN_FILTER and OUT_FILTER */ +#define CS530X_INOUT_FILTER_SHIFT 8 +#define CS530X_INOUT_HPF_EN_SHIFT 12 =20 /* IN_HIZ */ #define CS530X_IN12_HIZ BIT(0) @@ -139,21 +158,21 @@ #define CS530X_IN56_HIZ BIT(2) #define CS530X_IN78_HIZ BIT(3) =20 -/* IN_INV */ -#define CS530X_IN1_INV_SHIFT 0 -#define CS530X_IN2_INV_SHIFT 1 -#define CS530X_IN3_INV_SHIFT 2 -#define CS530X_IN4_INV_SHIFT 3 -#define CS530X_IN5_INV_SHIFT 4 -#define CS530X_IN6_INV_SHIFT 5 -#define CS530X_IN7_INV_SHIFT 6 -#define CS530X_IN8_INV_SHIFT 7 +/* IN_INV and OUT_INV */ +#define CS530X_INOUT1_INV_SHIFT 0 +#define CS530X_INOUT2_INV_SHIFT 1 +#define CS530X_INOUT3_INV_SHIFT 2 +#define CS530X_INOUT4_INV_SHIFT 3 +#define CS530X_INOUT5_INV_SHIFT 4 +#define CS530X_INOUT6_INV_SHIFT 5 +#define CS530X_INOUT7_INV_SHIFT 6 +#define CS530X_INOUT8_INV_SHIFT 7 =20 -/* IN_VOL_CTLy_z */ -#define CS530X_IN_MUTE BIT(15) +/* IN_VOL_CTLy_z and OUT_VOL_CTLy_z */ +#define CS530X_INOUT_MUTE BIT(15) =20 -/* IN_VOL_CTL5 */ -#define CS530X_IN_VU BIT(0) +/* IN_VOL_CTL5 and OUT_VOL_CTL5 */ +#define CS530X_INOUT_VU BIT(0) =20 /* System Clock Source */ #define CS530X_SYSCLK_SRC_MCLK 0 @@ -166,6 +185,10 @@ #define CS530X_NUM_SUPPLIES 2 =20 enum cs530x_type { + CS4282, + CS4302, + CS4304, + CS4308, CS5302, CS5304, CS5308, @@ -186,6 +209,7 @@ struct cs530x_priv { int tdm_width; int tdm_slots; int adc_pairs_count; + int dac_pairs_count; =20 struct gpio_desc *reset_gpio; }; --=20 2.43.0