{"id":2233378,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2233378/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-tegra/patch/20260506102032.1644851-1-sheetal@nvidia.com/","project":{"id":21,"url":"http://patchwork.ozlabs.org/api/1.1/projects/21/?format=json","name":"Linux Tegra Development","link_name":"linux-tegra","list_id":"linux-tegra.vger.kernel.org","list_email":"linux-tegra@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260506102032.1644851-1-sheetal@nvidia.com>","date":"2026-05-06T10:20:32","name":"[v4] ASoC: tegra: Add per-stream Mixer Fade controls","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"8999c8a99577d3ca82771ed8bf772d0425d91420","submitter":{"id":87986,"url":"http://patchwork.ozlabs.org/api/1.1/people/87986/?format=json","name":"Sheetal","email":"sheetal@nvidia.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linux-tegra/patch/20260506102032.1644851-1-sheetal@nvidia.com/mbox/","series":[{"id":502954,"url":"http://patchwork.ozlabs.org/api/1.1/series/502954/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-tegra/list/?series=502954","date":"2026-05-06T10:20:32","name":"[v4] ASoC: tegra: Add per-stream Mixer Fade controls","version":4,"mbox":"http://patchwork.ozlabs.org/series/502954/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2233378/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2233378/checks/","tags":{},"headers":{"Return-Path":"\n <linux-tegra+bounces-14234-incoming=patchwork.ozlabs.org@vger.kernel.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-tegra@vger.kernel.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=Nvidia.com header.i=@Nvidia.com header.a=rsa-sha256\n header.s=selector2 header.b=HAobXIDA;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-tegra+bounces-14234-incoming=patchwork.ozlabs.org@vger.kernel.org;\n receiver=patchwork.ozlabs.org)","smtp.subspace.kernel.org;\n\tdkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com\n header.b=\"HAobXIDA\"","smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=40.93.194.49","smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=nvidia.com","smtp.subspace.kernel.org;\n spf=fail smtp.mailfrom=nvidia.com"],"Received":["from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g9Wd82YwSz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 06 May 2026 20:21:32 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id 6E60930087B1\n\tfor <incoming@patchwork.ozlabs.org>; Wed,  6 May 2026 10:21:08 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id F305A3F2115;\n\tWed,  6 May 2026 10:21:07 +0000 (UTC)","from SN4PR0501CU005.outbound.protection.outlook.com\n (mail-southcentralusazon11011049.outbound.protection.outlook.com\n [40.93.194.49])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 07BD33F65EB;\n\tWed,  6 May 2026 10:21:05 +0000 (UTC)","from BYAPR06CA0064.namprd06.prod.outlook.com (2603:10b6:a03:14b::41)\n by SA1PR12MB8920.namprd12.prod.outlook.com (2603:10b6:806:38e::20) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9891.15; Wed, 6 May\n 2026 10:20:55 +0000","from MWH0EPF000A6734.namprd04.prod.outlook.com\n (2603:10b6:a03:14b:cafe::2e) by BYAPR06CA0064.outlook.office365.com\n (2603:10b6:a03:14b::41) with Microsoft SMTP Server (version=TLS1_3,\n cipher=TLS_AES_256_GCM_SHA384) id 15.20.9870.27 via Frontend Transport; Wed,\n 6 May 2026 10:20:55 +0000","from mail.nvidia.com (216.228.118.232) by\n MWH0EPF000A6734.mail.protection.outlook.com (10.167.249.26) with Microsoft\n SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.20.9891.9 via Frontend Transport; Wed, 6 May 2026 10:20:54 +0000","from drhqmail203.nvidia.com (10.126.190.182) by mail.nvidia.com\n (10.127.129.5) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Wed, 6 May\n 2026 03:20:35 -0700","from drhqmail202.nvidia.com (10.126.190.181) by\n drhqmail203.nvidia.com (10.126.190.182) with Microsoft SMTP Server\n (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n 15.2.2562.20; Wed, 6 May 2026 03:20:35 -0700","from build-sheetal-bionic-20251202.nvidia.com (10.127.8.14) by\n mail.nvidia.com (10.126.190.181) with Microsoft SMTP Server id 15.2.2562.20\n via Frontend Transport; Wed, 6 May 2026 03:20:34 -0700"],"ARC-Seal":["i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1778062867; cv=fail;\n b=WW/R/GpkZ1bAIztw6HAE9ULfrcK2jDB5KSD7ZjvMa3AN8gppUD8LFkINp64JKcTCq6pdiopApae42+aZA+q1NcJo1TxN/9m5kAN+0f/4Fk4tI41ENEHtp26v0g0Hv30g9EXqeGcjd/iLLWwVGXOBinIpEcLsEpV17kzvgKryZuc=","i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=WZJaKDlQEpD6DvSDZu3Pw/coU3NzSXXs1i1AeEmkn/CD7DbO5O3HHo5tsNqA3yyVf8rF0JKTMe0Nv3VRHoSiju0xnSf0YP3PF3/rLZBuzaOEGGHHEKW0BVyw344jCDnRHidurV+WoQqAQRSj9rkY1aWpGsrLKyw+Q1x1iNpH10w4TzgEzWGCXGZO+LbhWW/fCy2e4FNi6BVsCZ5sW/NSVzcJI1/c3zMJFL/Au8Mg+m1ZvyAB74U8/tGjZti356U47QIvyv2gyI+boE3+FPQ8ZDX3EhvO8uzJTvm7UarVYmmIioMP8kIkAbS7sdXHKqJ3gm/T73H4Dsf1Tkp07bc4BQ=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1778062867; c=relaxed/simple;\n\tbh=goqy1OHne3CPie28bpAjYk/sz4XA2FTj9dZHY6eXnBU=;\n\th=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type;\n b=O4UvttsSQwxmxkJ3uY2Cpj9QnnKHUxvqNhtZ7cepvJNngQL/wpoU7r6tNtg2SOhTXHD20f20UFMrbUt0/KHjiS/4oQcLdvnPlascXYCuql57sGPqWEed+I+ypgt1hgCYr97vKpI+LKMh7pcLc9vPa/2X5TwQROJn84xhS9ZIQ/Q=","i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n 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;\n bh=B/3pVVlHr+MQaYlSJGsZPL91Bqc8gTzjC7ndD7k0kCw=;\n b=oH2wbjR9/cQqLDO58msglb4RlZ3RUqNIJD7O/Y3MbAEewduhe9nirMwbF1lKE4WlTDIE2WRoL/QrZ5dJr9W+0cgUPL/ihh/kEfRlltvsLZ+CP4EHLylRZIzDLYyqqx39ITUMsA3wr9o1kQ5OyHaDEWkyH0Gd0zt5Y9D3lHqkq6clIEsV4Kh+Z0mvEz7wPkErrsN5OW0rrjqZwXMu1VHskjFDbygJGnfdqJqDa6tX+4IdpFCYVgAqPJKWcW8gB3mAKbGFoN+xBRs8nTtV4qU/Emm77kI/6CWup7huLeqHPn8je92CTK37MP4shfGMuK2Dx8MCTjELXnGVKmnGjrxiSw=="],"ARC-Authentication-Results":["i=2; smtp.subspace.kernel.org;\n dmarc=pass (p=reject dis=none) header.from=nvidia.com;\n spf=fail smtp.mailfrom=nvidia.com;\n dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com\n header.b=HAobXIDA; arc=fail smtp.client-ip=40.93.194.49","i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.118.232) smtp.rcpttodomain=gmail.com smtp.mailfrom=nvidia.com;\n dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com;\n dkim=none (message not signed); arc=none (0)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com;\n s=selector2;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=B/3pVVlHr+MQaYlSJGsZPL91Bqc8gTzjC7ndD7k0kCw=;\n b=HAobXIDAS42yzcDO5QQVydx6Y4AkIPPqZS1LP76mFgrE63D/D5LL2TQm5A3oXlnpZHwKrErwq2kOFSbft84jmTx0ADM0Ch5PjAEX9X6aYAqquTjiyxEqY0fWDzIwxa6cjjkpF6aupFoCoiEjwlCR0A3K8ekT7EEd+t8A51KxdmE8x4WitWw++xIpSwG5TNH6exgFFzLiZjJNhoqrUNaPWRiDaM4ju8rsnrGLTDuhxUBmbIjLPkmPztU+064/JXb+N1CNEZnhHMRUUuAD0nuk28X1MTEUsUCHuTvdQzJVM1IBJIg9VJN2HzX8Zmzs/SlUTQPucWtoFgjeaVwsHGkqxQ==","X-MS-Exchange-Authentication-Results":"spf=pass (sender IP is 216.228.118.232)\n smtp.mailfrom=nvidia.com; dkim=none (message not signed)\n header.d=none;dmarc=pass action=none header.from=nvidia.com;","Received-SPF":"Pass (protection.outlook.com: domain of nvidia.com designates\n 216.228.118.232 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.118.232; helo=mail.nvidia.com; pr=C","From":"Sheetal <sheetal@nvidia.com>","To":"Liam Girdwood <lgirdwood@gmail.com>, Mark Brown <broonie@kernel.org>","CC":"Jaroslav Kysela <perex@perex.cz>, Takashi Iwai <tiwai@suse.com>, \"Thierry\n Reding\" <thierry.reding@kernel.org>, Jonathan Hunter <jonathanh@nvidia.com>,\n\tSameer Pujar <spujar@nvidia.com>, Mohan Kumar <mkumard@nvidia.com>, \"Kuninori\n Morimoto\" <kuninori.morimoto.gx@renesas.com>, <linux-sound@vger.kernel.org>,\n\t<linux-tegra@vger.kernel.org>, <linux-kernel@vger.kernel.org>, Sheetal\n\t<sheetal@nvidia.com>","Subject":"[PATCH v4] ASoC: tegra: Add per-stream Mixer Fade controls","Date":"Wed, 6 May 2026 10:20:32 +0000","Message-ID":"<20260506102032.1644851-1-sheetal@nvidia.com>","X-Mailer":"git-send-email 2.17.1","Precedence":"bulk","X-Mailing-List":"linux-tegra@vger.kernel.org","List-Id":"<linux-tegra.vger.kernel.org>","List-Subscribe":"<mailto:linux-tegra+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-tegra+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Type":"text/plain","X-NV-OnPremToCloud":"ExternallySecured","X-EOPAttributedMessage":"0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"MWH0EPF000A6734:EE_|SA1PR12MB8920:EE_","X-MS-Office365-Filtering-Correlation-Id":"b661ccf9-c391-49b9-6385-08deab592854","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"\n\tBCL:0;ARA:13230040|30052699003|1800799024|82310400026|376014|36860700016|18002099003|56012099003;","X-Microsoft-Antispam-Message-Info":"\n\tEtCwyFrBwUdTyPBBpkMehOqWnEJ9wmFgmSN75EBcpQefqfPDCaTd7Er6q7UsRXqOuQP13IRsukqQ8wlyMyIJR61d+lTTvNZOZxBKQfw+/C2Ho8gOvVFvW1ptnMTE3g4eakK+wHTJACr/DheEj46aFn5gCt5JWL0cDUNXdFOqLtgfqs7wBAG2WJq4OFXlemxX6KVmio5HiREzhL6tagGXZwSmz00on5oSvORkdcaMO5J+GS74Eb8L5pHV8ClEVKxZXxU1OTAICr/TVpHS/3zCJ6MULFnlw6VyTP0n7NRYmGO8pLF9oVPgF61StcTvO6imNhwk2X6F1xg9ASoPf+8wfir0//FG9ZhUJ1qyVRZYzjtDPRlVt9QGZVrgHpuqHHxdpv1FK3ObFT42PnQWLhnzz+Mh/iacnzijscKFHg3E6Ghd4iTrKUZ5ixjHJEqz/VlweCSriHBgDFrNlLR1ePEFWC9chqjKUBES1Ju5Jzqhpu6ZlQxoxVauXuCV61lGPMSxGmYIqs1Cwz5Wtjrt1fyVB+wfkY1r+XYF94WPF2vQGnD7nwbPoe3RghdyaciAUfA9a7qlUdqsA7GTwRqY8m43HDzA+XV4PYi827hz/J/+L6yB20vv8Td80leMohEUSuixT5gzONKs1o8AF7aveetk3jkJxC4dRoFNopuy6p2M7UNARuvc4xmHIBaJ1KowH+KQs8a9d/dsbIq0Lh+HirsoD7l79nX58sQJ77nVeGrmMLU=","X-Forefront-Antispam-Report":"\n\tCIP:216.228.118.232;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc7edge1.nvidia.com;CAT:NONE;SFS:(13230040)(30052699003)(1800799024)(82310400026)(376014)(36860700016)(18002099003)(56012099003);DIR:OUT;SFP:1101;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"\n\tM/RSxEDx5qs1hzPW4mMVApCAtt/hNc91wJ2MFs6n7029hvzvG3XAS63ROrJEDgHPhBaBfjhIdtvW9rkppjtxVbdVZzUbiYGTgAJkL72SIJ4xSyAAJDL9P5oC/os5H7QKwvckdwZ7icyCeuWL+JFnHuEM0puOu/INFIZr+JR3rqk9B1UmPRFK1z3GEv56j83Q/n1vhYz7x/ta+2tP1o5A5W33+sWV/PJryjpagaWbcXOwqQqztE1x4F9bCdsKq2zvubmtac/K3L7A8gNvOm+Wgp0NpmQCzuoktnXfix+Zy6/mUx/AukbhGD2IPKiAGMHwm4/0Z4izJ0sxLOJAYWlLeTMMmbtvUTxFUUwBDXFCiN0QpuCwLLeZrsVs7b2YxDIaBEv/eAG5ITP+5bh45Q+SegUYmev/d/lE5YyA9FK98kpZnMwWaW47W6F2VOuAa5nf","X-OriginatorOrg":"Nvidia.com","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"06 May 2026 10:20:54.9365\n (UTC)","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n b661ccf9-c391-49b9-6385-08deab592854","X-MS-Exchange-CrossTenant-Id":"43083d15-7273-40c1-b7db-39efd9ccc17a","X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp":"\n TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.118.232];Helo=[mail.nvidia.com]","X-MS-Exchange-CrossTenant-AuthSource":"\n\tMWH0EPF000A6734.namprd04.prod.outlook.com","X-MS-Exchange-CrossTenant-AuthAs":"Anonymous","X-MS-Exchange-CrossTenant-FromEntityHeader":"HybridOnPrem","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"SA1PR12MB8920"},"content":"Add per-stream fade controls for the Tegra mixer to allow\nindependently configuring target gain and fade duration for each of\nthe 10 input streams (RX1 through RX10).\n\nThe following controls are added per stream:\n  \"RXn Fade Duration\" - fade duration in samples (N3 parameter)\n  \"RXn Fade Gain\"     - target gain level for fade\n\nA strobe control commits all pending fade configurations:\n  \"Fade Switch\"       - 1 = apply staged gain/duration and start fades\n                        0 = disable sample count for all fading streams\n\nA read-only status control reports per-stream fade state:\n  \"Fade Status\"       - per-stream state for all 10 RX inputs\n                        0 = idle, 1 = active\n\nUsage example (fade 2 streams simultaneously):\n  amixer -c <card> cset name=\"RX1 Fade Duration\" 1024\n  amixer -c <card> cset name=\"RX1 Fade Gain\" 12000\n  amixer -c <card> cset name=\"RX2 Fade Duration\" 2048\n  amixer -c <card> cset name=\"RX2 Fade Gain\" 15000\n  amixer -c <card> cset name=\"Fade Switch\" 1\n\nSigned-off-by: Sheetal <sheetal@nvidia.com>\n---\nChanges in v4:\n  - Make get_fade_status purely read-only (no hardware writes or\n    in_fade modifications); in_fade managed exclusively by\n    put_fade_switch\n  - Add explicit validation for gain and duration in put callbacks\n\n sound/soc/tegra/tegra210_mixer.c | 266 ++++++++++++++++++++++++++++++-\n sound/soc/tegra/tegra210_mixer.h |  19 ++-\n 2 files changed, 278 insertions(+), 7 deletions(-)","diff":"diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c\nindex ce44117a0b9c..f05617b5f433 100644\n--- a/sound/soc/tegra/tegra210_mixer.c\n+++ b/sound/soc/tegra/tegra210_mixer.c\n@@ -151,10 +151,17 @@ static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt,\n \tfor (i = 0; i < NUM_DURATION_PARMS; i++) {\n \t\tint val;\n \n-\t\tif (instant_gain)\n+\t\tif (instant_gain) {\n \t\t\tval = 1;\n-\t\telse\n-\t\t\tval = gain_params.duration[i];\n+\t\t} else {\n+\t\t\tif (i == DURATION_N3_ID)\n+\t\t\t\tval = mixer->duration[id];\n+\t\t\telse if (i == DURATION_INV_N3_ID)\n+\t\t\t\tval = (u32)(BIT_ULL(31 + TEGRA210_MIXER_PRESCALAR) /\n+\t\t\t\t\t    mixer->duration[id]);\n+\t\t\telse\n+\t\t\t\tval = gain_params.duration[i];\n+\t\t}\n \n \t\terr = tegra210_mixer_write_ram(mixer,\n \t\t\t\t\t       REG_DURATION_PARAM(reg, i),\n@@ -173,6 +180,204 @@ static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt,\n \treturn err;\n }\n \n+static int tegra210_mixer_get_fade_duration(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t    struct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct soc_mixer_control *mc =\n+\t\t(struct soc_mixer_control *)kcontrol->private_value;\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\n+\tucontrol->value.integer.value[0] = mixer->duration[mc->reg];\n+\n+\treturn 0;\n+}\n+\n+static int tegra210_mixer_put_fade_duration(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t    struct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct soc_mixer_control *mc =\n+\t\t(struct soc_mixer_control *)kcontrol->private_value;\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\tunsigned int id = mc->reg;\n+\tu32 duration = ucontrol->value.integer.value[0];\n+\n+\tif (duration == 0 || duration > TEGRA210_MIXER_FADE_DURATION_MAX)\n+\t\treturn -EINVAL;\n+\n+\tif (mixer->duration[id] == duration)\n+\t\treturn 0;\n+\n+\tmixer->duration[id] = duration;\n+\tmixer->fade_pending[id] = true;\n+\n+\treturn 1;\n+}\n+\n+static int tegra210_mixer_get_fade_gain(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\tstruct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct soc_mixer_control *mc =\n+\t\t(struct soc_mixer_control *)kcontrol->private_value;\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\n+\tucontrol->value.integer.value[0] = mixer->fade_gain[mc->reg];\n+\n+\treturn 0;\n+}\n+\n+static int tegra210_mixer_put_fade_gain(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\tstruct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct soc_mixer_control *mc =\n+\t\t(struct soc_mixer_control *)kcontrol->private_value;\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\tunsigned int id = mc->reg;\n+\n+\tif (ucontrol->value.integer.value[0] < 0 ||\n+\t    ucontrol->value.integer.value[0] > TEGRA210_MIXER_GAIN_MAX)\n+\t\treturn -EINVAL;\n+\n+\tif (mixer->fade_gain[id] == ucontrol->value.integer.value[0])\n+\t\treturn 0;\n+\n+\tmixer->fade_gain[id] = ucontrol->value.integer.value[0];\n+\tmixer->fade_pending[id] = true;\n+\n+\treturn 1;\n+}\n+\n+static int tegra210_mixer_get_fade_switch(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t  struct snd_ctl_elem_value *ucontrol)\n+{\n+\tucontrol->value.integer.value[0] = 0;\n+\n+\treturn 0;\n+}\n+\n+static int tegra210_mixer_put_fade_switch(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t  struct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\tint id, err, changed = 0;\n+\n+\terr = pm_runtime_resume_and_get(cmpnt->dev);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\t/* Switch off: disable sample count for all active fades */\n+\tif (!ucontrol->value.integer.value[0]) {\n+\t\tfor (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {\n+\t\t\tif (!mixer->in_fade[id])\n+\t\t\t\tcontinue;\n+\n+\t\t\tregmap_update_bits(mixer->regmap,\n+\t\t\t\t\t   MIXER_REG(TEGRA210_MIXER_RX1_CTRL,\n+\t\t\t\t\t\t     id),\n+\t\t\t\t\t   TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,\n+\t\t\t\t\t   0);\n+\t\t\tmixer->in_fade[id] = false;\n+\t\t\tchanged = 1;\n+\t\t}\n+\n+\t\tpm_runtime_put(cmpnt->dev);\n+\t\treturn changed;\n+\t}\n+\n+\t/* Stop active fades on pending streams before reconfiguring */\n+\tfor (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {\n+\t\tif (!mixer->fade_pending[id])\n+\t\t\tcontinue;\n+\n+\t\tif (mixer->in_fade[id]) {\n+\t\t\tregmap_update_bits(mixer->regmap,\n+\t\t\t\t\t   MIXER_REG(TEGRA210_MIXER_RX1_CTRL,\n+\t\t\t\t\t\t     id),\n+\t\t\t\t\t   TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,\n+\t\t\t\t\t   0);\n+\t\t\tmixer->in_fade[id] = false;\n+\t\t}\n+\n+\t\tmixer->gain_value[id] = mixer->fade_gain[id];\n+\t\terr = tegra210_mixer_configure_gain(cmpnt, id, false);\n+\t\tif (err) {\n+\t\t\tdev_err(cmpnt->dev,\n+\t\t\t\t\"Failed to configure fade for RX%d\\n\", id + 1);\n+\t\t\tpm_runtime_put(cmpnt->dev);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\tchanged = 1;\n+\t}\n+\n+\tif (!changed) {\n+\t\tpm_runtime_put(cmpnt->dev);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Enable sample count for all pending streams */\n+\tfor (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {\n+\t\tif (!mixer->fade_pending[id])\n+\t\t\tcontinue;\n+\n+\t\terr = regmap_update_bits(mixer->regmap,\n+\t\t\t\t\t MIXER_REG(TEGRA210_MIXER_RX1_CTRL, id),\n+\t\t\t\t\t TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,\n+\t\t\t\t\t TEGRA210_MIXER_SAMPLE_COUNT_ENABLE);\n+\t\tif (err) {\n+\t\t\tdev_err(cmpnt->dev,\n+\t\t\t\t\"Failed to enable sample count for RX%d\\n\",\n+\t\t\t\tid + 1);\n+\t\t\tpm_runtime_put(cmpnt->dev);\n+\t\t\treturn err;\n+\t\t}\n+\n+\t\tmixer->in_fade[id] = true;\n+\t\tmixer->fade_pending[id] = false;\n+\t}\n+\n+\tpm_runtime_put(cmpnt->dev);\n+\n+\treturn 1;\n+}\n+\n+static int tegra210_mixer_get_fade_status(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t  struct snd_ctl_elem_value *ucontrol)\n+{\n+\tstruct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);\n+\tstruct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);\n+\tu32 count;\n+\tint id, err;\n+\n+\terr = pm_runtime_resume_and_get(cmpnt->dev);\n+\tif (err < 0)\n+\t\treturn err;\n+\n+\tfor (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {\n+\t\tif (!mixer->in_fade[id]) {\n+\t\t\tucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tregmap_read(mixer->regmap,\n+\t\t\t    MIXER_REG(TEGRA210_MIXER_RX1_SAMPLE_COUNT, id),\n+\t\t\t    &count);\n+\n+\t\tif (count >= mixer->duration[id])\n+\t\t\tucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE;\n+\t\telse\n+\t\t\tucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_ACTIVE;\n+\t}\n+\n+\tpm_runtime_put(cmpnt->dev);\n+\n+\treturn 0;\n+}\n+\n static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol,\n \t\t\t\t   struct snd_ctl_elem_value *ucontrol)\n {\n@@ -396,14 +601,37 @@ ADDER_CTRL_DECL(adder3, TEGRA210_MIXER_TX3_ADDER_CONFIG);\n ADDER_CTRL_DECL(adder4, TEGRA210_MIXER_TX4_ADDER_CONFIG);\n ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG);\n \n+static int tegra210_mixer_fade_status_info(struct snd_kcontrol *kcontrol,\n+\t\t\t\t\t   struct snd_ctl_elem_info *uinfo)\n+{\n+\tuinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;\n+\tuinfo->count = TEGRA210_MIXER_RX_MAX;\n+\tuinfo->value.integer.min = TEGRA210_MIXER_FADE_IDLE;\n+\tuinfo->value.integer.max = TEGRA210_MIXER_FADE_ACTIVE;\n+\n+\treturn 0;\n+}\n+\n+#define FADE_CTRL(id)\t\t\t\t\t\t\t\\\n+\tSOC_SINGLE_EXT(\"RX\" #id \" Fade Duration\", (id) - 1, 0,\t\t\\\n+\t\t       TEGRA210_MIXER_FADE_DURATION_MAX, 0,\t\t\\\n+\t\t       tegra210_mixer_get_fade_duration,\t\t\t\\\n+\t\t       tegra210_mixer_put_fade_duration),\t\t\\\n+\tSOC_SINGLE_EXT(\"RX\" #id \" Fade Gain\", (id) - 1, 0,\t\t\\\n+\t\t       TEGRA210_MIXER_GAIN_MAX, 0,\t\t\t\\\n+\t\t       tegra210_mixer_get_fade_gain,\t\t\t\\\n+\t\t       tegra210_mixer_put_fade_gain),\n+\n #define GAIN_CTRL(id)\t\\\n \tSOC_SINGLE_EXT(\"RX\" #id \" Gain Volume\",\t\t\t\\\n \t\t       MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0,\t\\\n-\t\t       0x20000, 0, tegra210_mixer_get_gain,\t\\\n+\t\t       TEGRA210_MIXER_GAIN_MAX, 0,\t\t\\\n+\t\t       tegra210_mixer_get_gain,\t\t\t\\\n \t\t       tegra210_mixer_put_gain),\t\t\\\n \tSOC_SINGLE_EXT(\"RX\" #id \" Instant Gain Volume\",\t\t\\\n \t\t       MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0,\t\\\n-\t\t       0x20000, 0, tegra210_mixer_get_gain,\t\\\n+\t\t       TEGRA210_MIXER_GAIN_MAX, 0,\t\t\\\n+\t\t       tegra210_mixer_get_gain,\t\t\t\\\n \t\t       tegra210_mixer_put_instant_gain),\n \n /* Volume controls for all MIXER inputs */\n@@ -418,6 +646,28 @@ static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = {\n \tGAIN_CTRL(8)\n \tGAIN_CTRL(9)\n \tGAIN_CTRL(10)\n+\n+\tFADE_CTRL(1)\n+\tFADE_CTRL(2)\n+\tFADE_CTRL(3)\n+\tFADE_CTRL(4)\n+\tFADE_CTRL(5)\n+\tFADE_CTRL(6)\n+\tFADE_CTRL(7)\n+\tFADE_CTRL(8)\n+\tFADE_CTRL(9)\n+\tFADE_CTRL(10)\n+\tSOC_SINGLE_EXT(\"Fade Switch\", SND_SOC_NOPM, 0, 1, 0,\n+\t\t       tegra210_mixer_get_fade_switch,\n+\t\t       tegra210_mixer_put_fade_switch),\n+\t{\n+\t\t.iface = SNDRV_CTL_ELEM_IFACE_MIXER,\n+\t\t.name = \"Fade Status\",\n+\t\t.info = tegra210_mixer_fade_status_info,\n+\t\t.access = SNDRV_CTL_ELEM_ACCESS_READ |\n+\t\t\t  SNDRV_CTL_ELEM_ACCESS_VOLATILE,\n+\t\t.get = tegra210_mixer_get_fade_status,\n+\t},\n };\n \n static const struct snd_soc_dapm_widget tegra210_mixer_widgets[] = {\n@@ -579,6 +829,7 @@ static bool tegra210_mixer_volatile_reg(struct device *dev,\n \tcase TEGRA210_MIXER_GAIN_CFG_RAM_DATA:\n \tcase TEGRA210_MIXER_PEAKM_RAM_CTRL:\n \tcase TEGRA210_MIXER_PEAKM_RAM_DATA:\n+\tcase TEGRA210_MIXER_RX1_SAMPLE_COUNT:\n \t\treturn true;\n \tdefault:\n \t\treturn false;\n@@ -632,8 +883,11 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev)\n \tdev_set_drvdata(dev, mixer);\n \n \t/* Use default gain value for all MIXER inputs */\n-\tfor (i = 0; i < TEGRA210_MIXER_RX_MAX; i++)\n+\tfor (i = 0; i < TEGRA210_MIXER_RX_MAX; i++) {\n \t\tmixer->gain_value[i] = gain_params.gain_value;\n+\t\tmixer->fade_gain[i] = gain_params.gain_value;\n+\t\tmixer->duration[i] = gain_params.duration[DURATION_N3_ID];\n+\t}\n \n \tregs = devm_platform_ioremap_resource(pdev, 0);\n \tif (IS_ERR(regs))\ndiff --git a/sound/soc/tegra/tegra210_mixer.h b/sound/soc/tegra/tegra210_mixer.h\nindex a330530fbc61..bcbad08cbb9d 100644\n--- a/sound/soc/tegra/tegra210_mixer.h\n+++ b/sound/soc/tegra/tegra210_mixer.h\n@@ -79,12 +79,25 @@\n #define TEGRA210_MIXER_RX_LIMIT\t\t(TEGRA210_MIXER_RX_MAX * TEGRA210_MIXER_REG_STRIDE)\n #define TEGRA210_MIXER_TX_MAX\t\t5\n #define TEGRA210_MIXER_TX_LIMIT\t\t(TEGRA210_MIXER_RX_LIMIT + (TEGRA210_MIXER_TX_MAX * TEGRA210_MIXER_REG_STRIDE))\n+#define TEGRA210_MIXER_SAMPLE_COUNT_SHIFT\t24\n+#define TEGRA210_MIXER_SAMPLE_COUNT_ENABLE\tBIT(TEGRA210_MIXER_SAMPLE_COUNT_SHIFT)\n \n #define REG_CFG_DONE_TRIGGER\t0xf\n #define VAL_CFG_DONE_TRIGGER\t0x1\n \n #define NUM_GAIN_POLY_COEFFS 9\n-#define NUM_DURATION_PARMS 4\n+#define TEGRA210_MIXER_GAIN_MAX\t\t\t0x20000\n+#define TEGRA210_MIXER_FADE_DURATION_MAX\t0x7fffffff\n+\n+#define TEGRA210_MIXER_PRESCALAR\t    6\n+#define TEGRA210_MIXER_FADE_IDLE\t    0\n+#define TEGRA210_MIXER_FADE_ACTIVE\t  1\n+\n+enum {\n+\tDURATION_N3_ID = 2,\n+\tDURATION_INV_N3_ID,\n+\tNUM_DURATION_PARMS,\n+};\n \n struct tegra210_mixer_gain_params {\n \tint poly_coeff[NUM_GAIN_POLY_COEFFS];\n@@ -94,6 +107,10 @@ struct tegra210_mixer_gain_params {\n \n struct tegra210_mixer {\n \tint gain_value[TEGRA210_MIXER_RX_MAX];\n+\tint fade_gain[TEGRA210_MIXER_RX_MAX];\n+\tu32 duration[TEGRA210_MIXER_RX_MAX];\n+\tbool in_fade[TEGRA210_MIXER_RX_MAX];\n+\tbool fade_pending[TEGRA210_MIXER_RX_MAX];\n \tstruct regmap *regmap;\n };\n \n","prefixes":["v4"]}