{"id":2232302,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2232302/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-tegra/patch/20260504100051.3820808-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":"<20260504100051.3820808-1-sheetal@nvidia.com>","date":"2026-05-04T10:00:51","name":"[v3] ASoC: tegra: Add per-stream Mixer Fade controls","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"0f656738afdc4e5de4bb4f6b95e6ece0dd3f330b","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/20260504100051.3820808-1-sheetal@nvidia.com/mbox/","series":[{"id":502634,"url":"http://patchwork.ozlabs.org/api/1.1/series/502634/?format=json","web_url":"http://patchwork.ozlabs.org/project/linux-tegra/list/?series=502634","date":"2026-05-04T10:00:51","name":"[v3] ASoC: tegra: Add per-stream Mixer Fade controls","version":3,"mbox":"http://patchwork.ozlabs.org/series/502634/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2232302/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2232302/checks/","tags":{},"headers":{"Return-Path":"\n <linux-tegra+bounces-14152-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=koajbdzq;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=104.64.211.4; helo=sin.lore.kernel.org;\n envelope-from=linux-tegra+bounces-14152-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=\"koajbdzq\"","smtp.subspace.kernel.org;\n arc=fail smtp.client-ip=52.101.85.3","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 sin.lore.kernel.org (sin.lore.kernel.org [104.64.211.4])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g8HHM3pnsz1yJV\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 04 May 2026 20:01:51 +1000 (AEST)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sin.lore.kernel.org (Postfix) with ESMTP id 977283002B74\n\tfor <incoming@patchwork.ozlabs.org>; Mon,  4 May 2026 10:01:48 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 1BAF2378D77;\n\tMon,  4 May 2026 10:01:47 +0000 (UTC)","from BYAPR05CU005.outbound.protection.outlook.com\n (mail-westusazon11010003.outbound.protection.outlook.com [52.101.85.3])\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 F3E4530C601;\n\tMon,  4 May 2026 10:01:44 +0000 (UTC)","from DM6PR02CA0067.namprd02.prod.outlook.com (2603:10b6:5:177::44)\n by SA5PPFF3CB57EDE.namprd12.prod.outlook.com (2603:10b6:80f:fc04::8eb) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9846.26; Mon, 4 May\n 2026 10:01:34 +0000","from DS2PEPF00003448.namprd04.prod.outlook.com\n (2603:10b6:5:177:cafe::13) by DM6PR02CA0067.outlook.office365.com\n (2603:10b6:5:177::44) with Microsoft SMTP Server (version=TLS1_3,\n cipher=TLS_AES_256_GCM_SHA384) id 15.20.9870.25 via Frontend Transport; Mon,\n 4 May 2026 10:01:33 +0000","from mail.nvidia.com (216.228.117.160) by\n DS2PEPF00003448.mail.protection.outlook.com (10.167.17.75) 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; Mon, 4 May 2026 10:01:33 +0000","from rnnvmail204.nvidia.com (10.129.68.6) by mail.nvidia.com\n (10.129.200.66) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Mon, 4 May\n 2026 03:01:15 -0700","from rnnvmail204.nvidia.com (10.129.68.6) by rnnvmail204.nvidia.com\n (10.129.68.6) with Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Mon, 4 May\n 2026 03:01:14 -0700","from build-sheetal-bionic-20251202.nvidia.com (10.127.8.14) by\n mail.nvidia.com (10.129.68.6) with Microsoft SMTP Server id 15.2.2562.20 via\n Frontend Transport; Mon, 4 May 2026 03:01:13 -0700"],"ARC-Seal":["i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1777888906; cv=fail;\n b=nZZJf8r2wfbXPrT8y5tkGyqBV/ikmmxZRESIYm62uJZ1RTLVu7tN0M/Cqv4BZDY0iOS4ptBqUJRmUUQ42eQ8mpdjqhbIIMOBJ0SyGUoHn0TkRNcwHvwfPJr7aCbY6iLgjgjXvsQK0g5RgVCiqrN0t7GU27rYSYFZkMgCcEgteFA=","i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=oQWcipA1IozuW5D07PzB1RRtn3RjYY5bzB89wlfOaZ5Enk7lY1kBXWxxUwj9r2U4opj6i8IBxpQw70wTRhXFNYgZvloIUK+KmHUyA6TCE14QhhAyDBPIrbw6fBdqR9edlIe+0Zi4ZKOTGXDH5Q+SWLAmAC56Yff/qV4Oamow0Svn8Gs1U+dRSwQfXlFucrsnEkr4N8uHUAWGowzj8ocMc3LOK4zbYp5RiAefC317ue3FrpDKYksdO/BBSGoBgV8FZcbf4eIgdeR0w5tn5/7r2ue5MtzgmuDzHrobbJuUBwrJWM68ZFFH38PntjZni+/k8SR6hEP/AsfyLKN8b/IrSw=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1777888906; c=relaxed/simple;\n\tbh=iGgQ60DCZcoiQDs8HBg9ptSgfFnDp7UITbfRPYo7RAs=;\n\th=From:To:CC:Subject:Date:Message-ID:MIME-Version:Content-Type;\n b=e6ZhiL05/o9T/z1gKgbWwlMRfaJQIRoxIdBp+kDMp8uIsmrrRdNnttPKWfC4LG5G0A11Ppaijgl6H4s/MXL6c4OIU4UrwqqPFrqFg/Tdj+H0/O3Zldy9JE+1IZKYPOOCZBbBxXDLQ8rDYoInTgSKWg5g4raVTLrdTJ0NzTx9qZc=","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=UYwiVJpwz/MX1NDY4Jx1oTxPzKVBDsEUIf1yTO9SXWs=;\n b=TevYukm3wvbLa7eb3b3VC7pxt6UrhJhWjCoF6RWwAw4gzmbnYyrm4EL9xxhJbb6Ukwbtuv7tizdN5JuHDTPQFtvIjiTuXX8X1KY7Wt33hJoxPPfJqhq7YK/nVjwZS/1c6+J5bYp9navSI4h5jHoA8dLXcPORVU/mon5ArZtJarw54IA6owQKgHeR0SgNYeeoRuCyAkEIBKP+nwPmF5hOWlJsY9Yr9Eu8NljIx9UeArtCGQ+qhqVjB+hfxj8Hxp45Fnrh7vdk5EoORf+5grtqtAMHFlZW79fkljX1elXD/HdwnhV/wKtI0dbGgt1lq3QgvwylkfQpkoN2fuA2P2JwBw=="],"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=koajbdzq; arc=fail smtp.client-ip=52.101.85.3","i=1; mx.microsoft.com 1; spf=pass (sender ip is\n 216.228.117.160) 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=UYwiVJpwz/MX1NDY4Jx1oTxPzKVBDsEUIf1yTO9SXWs=;\n b=koajbdzqITUq8WR2NRhVKZ3HCdAN8pq8Lfd6IEAa6h+x6dBwwiBtWhsolF03KNQDuCwYPlKY1Md/PVu9okp6kRk7M0jf8NUA0bUuYhuZ8IW7eM2B57fa/l8b+ZTblpN8EJiTZuTYMXGlLXIHRdAO3SBArkS6OIo0kgQm2waOrpzwkQnH67VImwcS6WxiSvb7GMAf1ZbFCxJDVkZ7JCI9kBHNKUt4zjQ27tOZAHz5EP/XjcAuBZlIk5q1urfi3pi6UhXM3kUf4O7rt9kuOpnxtZ6i5DegleWRai36iRP1mPszThM5ciMqucmgjIJ+d4F0b2I1BRVvT0U2ZMl3/Gz2Mw==","X-MS-Exchange-Authentication-Results":"spf=pass (sender IP is 216.228.117.160)\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.117.160 as permitted sender) receiver=protection.outlook.com;\n client-ip=216.228.117.160; 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 v3] ASoC: tegra: Add per-stream Mixer Fade controls","Date":"Mon, 4 May 2026 10:00:51 +0000","Message-ID":"<20260504100051.3820808-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":"DS2PEPF00003448:EE_|SA5PPFF3CB57EDE:EE_","X-MS-Office365-Filtering-Correlation-Id":"a6e150b5-4b5c-4557-2712-08dea9c41f4d","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"\n\tBCL:0;ARA:13230040|1800799024|376014|36860700016|82310400026|18002099003|56012099003;","X-Microsoft-Antispam-Message-Info":"\n\tISmtJxWGQrl+R4OXDI9GcFLLTlfQkutnErdHxIUidm75LruTJ0cnpTZTAExYuKVhfPD4e4z6gCdJu1PsFXzRoisu1/DmaBtb/eKILbsqEfPh7ytwFGw/ljXVoQlfYVG2Xl2MBBCyCy8xjANL+x+DOXLqHLeVoGyHNNwd0qYz2uSGlhFOdnH+wLgTU3z9kMJFK1rfGZ6ljIR5+m43G2x/3LwcXJfY2FlT3jnCOWPgT1sIZ7IVAFBIDJAAA+yWflJPuK2KpW3D4nqkQVCoKUIh3UU9Dl/6U8JU+CeqiyZLcat+0Fmh3GBrLH4AnlE4vwKST5S7DxTqVGo2n1+qEG1AzDqNXhFIrrDxCxHfojfHvw9ftIuR303daZvzoCtPtnzWgKpe+Mh3W74Lv1tZMAjFykoORVEK0AJjoixPlVtdaZVkn1yg/ez98+fhmVDLoCb29ynTg1JFWyjK0HYL6YJ2ek/0iYHXYPdRfOrpGd1an2Kl7LnzakbScrxfCVLUMrltlT6fyvsYoEr6wFXtIHxJbLUZIFyoo6gsmpmFYUgYT1lxABdgwBVQjVRSgsWdwVgQLmbWss7n4OggxdaJBW5WQVaQhnJNoXyPD0dBv4h5EhlvMnnl+fKfM7tiNwiGjHfRWhHVUoX6Ta4xQr8YcnlU2/DNq50rqmmlTHD0MQzrUYc2wFBoNBzWEndTNAOrX3nHLyXNAQCFry7Elubd9JEguBaIsjKIuaT94zsnCNUVjSs=","X-Forefront-Antispam-Report":"\n\tCIP: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)(376014)(36860700016)(82310400026)(18002099003)(56012099003);DIR:OUT;SFP:1101;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"\n\taGvOPzOPeEuR5xqnbYnHhZdw3L82oWp/AIGhyKpH8wFbyWGWpN1ZoL3kSF3fHa+ChYhWvaCznItYUvQntQCKqkHJIxlrpd7++nSyEFThMg4dulKjm4ULhSkZu57My+87oTV006YAiRZeDpksdxhyWstmLNVduLqh1TBbeLJx+m8xEiYdhMufS0eIZuHBtjZ9Li0CnMEMSKXOhFsvAKQN6s11VzqMpGZv8uBIPeP2vEZQOZx2cwEAzI08bjg6ob1b07h1aQDTuKYrXUT5gsdCca/L2xPg3TgnO1rLJVy74Lbn32hRBJJj8QVQNGDpsv2GoQM8C/ZiLLRmwU28EojHm396DUZ9ji1lW8ccbmsNB9KisAL6U1OX6XTqUj9R3KXxlM8F1rjNNhtGe9jebcVJP0e3IMPLj8JPNLLrzhq0aLDTi9+EUjGhLuCPoqR5eR23","X-OriginatorOrg":"Nvidia.com","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"04 May 2026 10:01:33.5506\n (UTC)","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n a6e150b5-4b5c-4557-2712-08dea9c41f4d","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.117.160];Helo=[mail.nvidia.com]","X-MS-Exchange-CrossTenant-AuthSource":"\n\tDS2PEPF00003448.namprd04.prod.outlook.com","X-MS-Exchange-CrossTenant-AuthAs":"Anonymous","X-MS-Exchange-CrossTenant-FromEntityHeader":"HybridOnPrem","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"SA5PPFF3CB57EDE"},"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 atomically:\n  \"Fade Switch\"       - applies staged gain/duration for all pending\n                        streams and starts the fade\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 v3:\n- Rename \"Fade Enable\" to \"Fade Switch\" (standard ALSA naming for\n  boolean controls) and rename associated function names accordingly\n- Add separate fade_gain[] field so \"RXn Fade Gain\" and \"RXn Gain\n  Volume\" controls are independent; put_fade_switch copies fade_gain\n  to gain_value before configuring hardware\n- Make get_fade_status read-only: removed regmap writes; only\n  software-side in_fade flag is cleared on completion to prevent\n  misreads after 32-bit sample counter rollover\n- Disable sample count before re-enabling in put callback to restart\n  the counter from zero, allowing new fades to replace active ones\n- Add switch off support: writing 0 disables sample count for all\n  fading streams, writing 1 starts pending fades\n- Remove FADE_COMPLETE state; simplify to binary IDLE(0)/ACTIVE(1)\n\n sound/soc/tegra/tegra210_mixer.c | 262 ++++++++++++++++++++++++++++++-\n sound/soc/tegra/tegra210_mixer.h |  19 ++-\n 2 files changed, 274 insertions(+), 7 deletions(-)","diff":"diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c\nindex ce44117a0b9c..91eb7c4c077f 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,200 @@ 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)\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 (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, id),\n+\t\t\t\t\t   TEGRA210_MIXER_SAMPLE_COUNT_ENABLE, 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\t\tmixer->in_fade[id] = false;\n+\t\t} else {\n+\t\t\tucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_ACTIVE;\n+\t\t}\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 +597,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 +642,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 +825,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 +879,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":["v3"]}