From nobody Mon Jun 15 02:47:42 2026 Received: from mail-pf1-f178.google.com (mail-pf1-f178.google.com [209.85.210.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 86C323D3487 for ; Wed, 8 Apr 2026 17:08:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.178 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775668120; cv=none; b=qtmx6oWZSPAaQFoGEtikjTNh24sGwmkquhN9Cz15td3fuyxJvsRdWKQV109myVpT+NRhN025Bca59gicRzE9idYg7B1WX6p4/5zn1rfFCJtWAJe9KCugz6fmKoM8xYnserx/tqVF4x+bWdBA+BjQA1f18yQYuBs6Q0KdQ6feW00= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775668120; c=relaxed/simple; bh=YZg75ezqJIP+f+P7cP0wDeFjr2y4+3ycZAwHZbKERNc=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=dES1miYVo4dNg4J/fU3s8TmzFC60fQmduAt5hG0zJr+fNXHSJwkjlk+HugThZfMW/pDaHmac0EY5jOo2VCpw5tog8G3WSgzuZahW1wefiNc2PtpOowHOQ15mT2jLbt6fePBWubfpJmz1TfrGoZgpTEpTz9ISUqck0JdIJBtb2d0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=f3n9uX2l; arc=none smtp.client-ip=209.85.210.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="f3n9uX2l" Received: by mail-pf1-f178.google.com with SMTP id d2e1a72fcca58-82cebbdab08so7621b3a.2 for ; Wed, 08 Apr 2026 10:08:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775668117; x=1776272917; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QM4n0gqKs7WW6dxpr3AefN9VBR+orpZRM4Lpqp05uEE=; b=f3n9uX2l7Ly34I3YONmVugZtmUDhZ66OuRtD9SGfYKAueZrGrCDJBBfjBOS2JouI1I jfKEEjvSh4P4KOb+HoMDXXSNZ50KLk3fEWBg8SPftHWyzdd6tJYYuQN3jsSBCO8BqHhW 8ZZGyHgv0uDXeun12opL0/WSV1orFqMfWR+Q/79gtQrDwXwMeTtCuKCa/I+gI35d0dET Pi5BbmdZ2X6AZ/aHEbO2oG6LTs1hwXr7oF3rdPqIG/N5fkB0kPYoq4oHzRfCdnPCZ03X MQNYVXaVoC6VR5Em/NL3sZbWNpTok3MISa+MCLNEpxvLLulRwHvwroFiCLKU2Jrv0haw BoUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775668117; x=1776272917; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=QM4n0gqKs7WW6dxpr3AefN9VBR+orpZRM4Lpqp05uEE=; b=I/Sr8M+iCBICFteK10H9W4WzcoHyZn2ANEQ9BNcyO+nLi0cU/KwfQ+fgF0o65Qdhmm 9h2i9rlu8YpuTvkiAgE1BsKmLjOro8+RESt8fpjW5jgEfs/eTxbasj0CA6pK6108FMnp 0zb/nwASuOdAm5Y3Qd3v5X1NK5C55/Vgjbun67pPRPBt9ljTuhCTKh10KT+8i5zcJb5B kH/DTX12eq2K5HiGRMACRg7E7yNPpZMeEN4NQXranTF4Ic55oahOf/uM7fo2tvOk6jbf 5BqF/8MuqpP3xD8gsVOK6hMI8sKF0rq/67fCMOjw+UGRNYtIFy0crR49jGZCFfagN3nR ppRA== X-Forwarded-Encrypted: i=1; AJvYcCWSVqMSWyF6foOM7tzZpWWHlXxUG7R+rOxGB27OOt6pKLLJqLhbl84tRLD7OKdM3hNdFYDgjO0fzP9NBtk=@vger.kernel.org X-Gm-Message-State: AOJu0Yx+7lGmdGV/Ci/bwV/MVJAKdQm972FmWhAhYY4Q6sEz7JcMzmz0 bJq7oDWmYxeK5dTrK1gbjZDjxlcB9C4NMJSw+s+ePpb9PYgAWoqbanIa X-Gm-Gg: AeBDievthqFCWF2Vd1cK2wrGu3QiC/LbzPDQpKcZRDAa27nwX/SwPUs46m4mLvLIwtZ CS+6hyHn8Nu/VTSDiXhs0qEv/ok33MszgJMy3rsuf6OAOfqGVuKZPU0fQwC3KzjKrGrJAYVuaou ZaNFUgxONVAgUx0c2Pse+DUEHSWxJt4ksBlqHEU3urKpokoKmluAhOxOGy7qARZXQQb9onLmzmV WfGg4ekfW5NYr00PVndR6UetvUzlgnJzZQ5VFV+V6iuT/w8vql/czkEWNLfRaDL0jXuYlQ/z12M NEAOikzfpYRL/WfSB+Eot/8SXVQwrZeh5gCWiY2N30jI+vZEg+5g8NMf1wFzKh5/LCtCpf0cdLF RtxQcgOia734BxPYG/WNAFpu0qriNeVa5JXXtMlLp6muKWmawBJqV5kndZghBHD/OcHUHp6Oz06 7K0VhqqtEDqyE/2MXyGGpQKhr1BCa5Tzjy3Y02w2FB8Wfszi6qlsEk+/dqkmT9JvO2KKOd1x33k QBpB0UMqmW1rzdFfiq7OO2koxB9j6/Z8mzVya/ucJ6HEClVPn+vFrmPcQ== X-Received: by 2002:a05:6a00:2351:b0:823:1252:9428 with SMTP id d2e1a72fcca58-82dd8992eb1mr330936b3a.9.1775668116584; Wed, 08 Apr 2026 10:08:36 -0700 (PDT) Received: from lorddaniel-VivoBook-ASUSLaptop-K3502ZA-S3502ZA.www.tendawifi.com ([14.139.108.62]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9b2694csm21775091b3a.2.2026.04.08.10.08.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 10:08:36 -0700 (PDT) From: Piyush Patle To: Mark Brown Cc: Sheetal , Jonathan Hunter , Thierry Reding , Liam Girdwood , Jaroslav Kysela , Takashi Iwai , Kuninori Morimoto , linux-sound@vger.kernel.org, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/2] ASoC: tegra210_adx: simplify byte map get/put logic Date: Wed, 8 Apr 2026 22:38:17 +0530 Message-Id: <20260408170818.70322-2-piyushpatle228@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260408170818.70322-1-piyushpatle228@gmail.com> References: <20260407170308.100238-3-piyushpatle228@gmail.com> <20260408170818.70322-1-piyushpatle228@gmail.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 Content-Type: text/plain; charset="utf-8" The byte-map controls ("Byte Map N") already expose a value range of [0, 256] to userspace via SOC_SINGLE_EXT(), where 256 is the "disabled" sentinel. The driver stored this state as a byte-packed u32 map[] array plus a separate byte_mask[] bitmap tracking which slots were enabled, because 256 does not fit in a byte. As a result get_byte_map() had to consult byte_mask[] to decide whether to report the stored byte or 256, and put_byte_map() had to keep the two arrays in sync on every write. Store each slot as a u16 holding the control value directly (0..255 enabled, 256 disabled). This is the native representation for what userspace already sees, so get_byte_map() becomes a direct return and put_byte_map() becomes a compare-and-store. The hardware-facing packed RAM word and the IN_BYTE_EN mask are now derived on the fly inside tegra210_adx_write_map_ram() from the slot array, which is the only place that needs to know about the hardware layout. The byte_mask scratch buffer is allocated dynamically using kcalloc() based on soc_data->byte_mask_size, removing dependency on SoC-specific constants. The byte_mask field is dropped from struct tegra210_adx. A new TEGRA_ADX_SLOTS_PER_WORD constant replaces the literal '4' used for byte slots per RAM word, and BITS_PER_BYTE / BITS_PER_TYPE() from replace the literal '8' and '32' shifts. Slots are initialised to 256 in probe() so the default reported value stays "disabled", matching previous behaviour. Values written from userspace that fall outside [0, 255] are clamped to 256 ("disabled") exactly as before -- no userspace-visible change. As a side effect this also fixes a latent bug in the previous put_byte_map(): because it compared the enable mask rather than the stored byte, changing a slot from one enabled value to another enabled value (e.g. 42 -> 99) would early-return without persisting the new value, and the next CFG_RAM flush would still program the old byte. The new implementation compares the stored value itself, so this case is now handled correctly. Addresses TODO left in tegra210_adx_get_byte_map(). Signed-off-by: Piyush Patle --- Changes since v1: - Allocate byte_mask[] dynamically using kcalloc() - Propagate -ENOMEM from write_map_ram() - Replace magic numbers with TEGRA_ADX_SLOTS_PER_WORD - Use BITS_PER_BYTE and BITS_PER_TYPE() - Add and sound/soc/tegra/tegra210_adx.c | 99 ++++++++++++++++++---------------- sound/soc/tegra/tegra210_adx.h | 6 ++- 2 files changed, 56 insertions(+), 49 deletions(-) diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c index 95875c75ddf8..2a2f7e9e90ca 100644 --- a/sound/soc/tegra/tegra210_adx.c +++ b/sound/soc/tegra/tegra210_adx.c @@ -4,6 +4,7 @@ // // tegra210_adx.c - Tegra210 ADX driver =20 +#include #include #include #include @@ -13,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -45,25 +47,49 @@ static const struct reg_default tegra264_adx_reg_defaul= ts[] =3D { { TEGRA264_ADX_CFG_RAM_CTRL, 0x00004000}, }; =20 -static void tegra210_adx_write_map_ram(struct tegra210_adx *adx) +static int tegra210_adx_write_map_ram(struct tegra210_adx *adx) { + const unsigned int bits_per_mask =3D BITS_PER_TYPE(*adx->map) * BITS_PER_= BYTE; + unsigned int *byte_mask; int i; =20 + byte_mask =3D kcalloc(adx->soc_data->byte_mask_size, sizeof(*byte_mask), + GFP_KERNEL); + if (!byte_mask) + return -ENOMEM; + regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL + adx->soc_data->cya_offset, TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN | TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN | TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE); =20 - for (i =3D 0; i < adx->soc_data->ram_depth; i++) + for (i =3D 0; i < adx->soc_data->ram_depth; i++) { + u32 word =3D 0; + int b; + + for (b =3D 0; b < TEGRA_ADX_SLOTS_PER_WORD; b++) { + unsigned int slot =3D i * TEGRA_ADX_SLOTS_PER_WORD + b; + u16 val =3D adx->map[slot]; + + if (val >=3D 256) + continue; + + word |=3D (u32)val << (b * BITS_PER_BYTE); + byte_mask[slot / bits_per_mask] |=3D 1U << (slot % bits_per_mask); + } regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA + - adx->soc_data->cya_offset, - adx->map[i]); + adx->soc_data->cya_offset, word); + } =20 for (i =3D 0; i < adx->soc_data->byte_mask_size; i++) regmap_write(adx->regmap, TEGRA210_ADX_IN_BYTE_EN0 + (i * TEGRA210_ADX_AUDIOCIF_CH_STRIDE), - adx->byte_mask[i]); + byte_mask[i]); + + kfree(byte_mask); + + return 0; } =20 static int tegra210_adx_startup(struct snd_pcm_substream *substream, @@ -118,9 +144,7 @@ static int tegra210_adx_runtime_resume(struct device *d= ev) regcache_cache_only(adx->regmap, false); regcache_sync(adx->regmap); =20 - tegra210_adx_write_map_ram(adx); - - return 0; + return tegra210_adx_write_map_ram(adx); } =20 static int tegra210_adx_set_audio_cif(struct snd_soc_dai *dai, @@ -188,27 +212,10 @@ static int tegra210_adx_get_byte_map(struct snd_kcont= rol *kcontrol, { struct snd_soc_component *cmpnt =3D snd_kcontrol_chip(kcontrol); struct tegra210_adx *adx =3D snd_soc_component_get_drvdata(cmpnt); - struct soc_mixer_control *mc; - unsigned char *bytes_map =3D (unsigned char *)adx->map; - int enabled; - - mc =3D (struct soc_mixer_control *)kcontrol->private_value; - enabled =3D adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32)); + struct soc_mixer_control *mc =3D + (struct soc_mixer_control *)kcontrol->private_value; =20 - /* - * TODO: Simplify this logic to just return from bytes_map[] - * - * Presently below is required since bytes_map[] is - * tightly packed and cannot store the control value of 256. - * Byte mask state is used to know if 256 needs to be returned. - * Note that for control value of 256, the put() call stores 0 - * in the bytes_map[] and disables the corresponding bit in - * byte_mask[]. - */ - if (enabled) - ucontrol->value.integer.value[0] =3D bytes_map[mc->reg]; - else - ucontrol->value.integer.value[0] =3D 256; + ucontrol->value.integer.value[0] =3D adx->map[mc->reg]; =20 return 0; } @@ -218,23 +225,22 @@ static int tegra210_adx_put_byte_map(struct snd_kcont= rol *kcontrol, { struct snd_soc_component *cmpnt =3D snd_kcontrol_chip(kcontrol); struct tegra210_adx *adx =3D snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map =3D (unsigned char *)adx->map; - int value =3D ucontrol->value.integer.value[0]; struct soc_mixer_control *mc =3D (struct soc_mixer_control *)kcontrol->private_value; - unsigned int mask_val =3D adx->byte_mask[mc->reg / 32]; + unsigned int value =3D ucontrol->value.integer.value[0]; =20 - if (value >=3D 0 && value <=3D 255) - mask_val |=3D (1 << (mc->reg % 32)); - else - mask_val &=3D ~(1 << (mc->reg % 32)); + /* + * Match the previous behaviour: any value outside [0, 255] is + * treated as the "disabled" sentinel (256). Negative values from + * userspace fold in through the unsigned cast and are caught here. + */ + if (value > 255) + value =3D 256; =20 - if (mask_val =3D=3D adx->byte_mask[mc->reg / 32]) + if (adx->map[mc->reg] =3D=3D value) return 0; =20 - /* Update byte map and slot */ - bytes_map[mc->reg] =3D value % 256; - adx->byte_mask[mc->reg / 32] =3D mask_val; + adx->map[mc->reg] =3D value; =20 return 1; } @@ -675,7 +681,7 @@ static int tegra210_adx_platform_probe(struct platform_= device *pdev) const struct of_device_id *match; struct tegra210_adx_soc_data *soc_data; void __iomem *regs; - int err; + int err, i; =20 adx =3D devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL); if (!adx) @@ -700,16 +706,15 @@ static int tegra210_adx_platform_probe(struct platfor= m_device *pdev) =20 regcache_cache_only(adx->regmap, true); =20 - adx->map =3D devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map), - GFP_KERNEL); + adx->map =3D devm_kcalloc(dev, + soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD, + sizeof(*adx->map), GFP_KERNEL); if (!adx->map) return -ENOMEM; =20 - adx->byte_mask =3D devm_kzalloc(dev, - soc_data->byte_mask_size * sizeof(*adx->byte_mask), - GFP_KERNEL); - if (!adx->byte_mask) - return -ENOMEM; + /* Initialise all byte map slots as disabled (value 256). */ + for (i =3D 0; i < soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD; i++) + adx->map[i] =3D 256; =20 tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max =3D adx->soc_data->max_ch; diff --git a/sound/soc/tegra/tegra210_adx.h b/sound/soc/tegra/tegra210_adx.h index 176a4e40de0a..7ea623b4183b 100644 --- a/sound/soc/tegra/tegra210_adx.h +++ b/sound/soc/tegra/tegra210_adx.h @@ -8,6 +8,8 @@ #ifndef __TEGRA210_ADX_H__ #define __TEGRA210_ADX_H__ =20 +#include + /* Register offsets from TEGRA210_ADX*_BASE */ #define TEGRA210_ADX_RX_STATUS 0x0c #define TEGRA210_ADX_RX_INT_STATUS 0x10 @@ -61,6 +63,7 @@ #define TEGRA210_ADX_SOFT_RESET_SOFT_DEFAULT (0 << TEGRA210_ADX_SOFT_RESE= T_SOFT_RESET_SHIFT) =20 #define TEGRA210_ADX_AUDIOCIF_CH_STRIDE 4 +#define TEGRA_ADX_SLOTS_PER_WORD 4 #define TEGRA210_ADX_RAM_DEPTH 16 #define TEGRA210_ADX_MAP_STREAM_NUMBER_SHIFT 6 #define TEGRA210_ADX_MAP_WORD_NUMBER_SHIFT 2 @@ -88,8 +91,7 @@ struct tegra210_adx_soc_data { =20 struct tegra210_adx { struct regmap *regmap; - unsigned int *map; - unsigned int *byte_mask; + u16 *map; const struct tegra210_adx_soc_data *soc_data; }; =20 --=20 2.34.1 From nobody Mon Jun 15 02:47:42 2026 Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1FB8C3B19AB for ; Wed, 8 Apr 2026 17:08:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.176 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775668124; cv=none; b=Lq2wHwulppEUPvLktE6tEXL64OYZLRbEE/8Kv9KivsUR5avFG2H1p1eGk7eH5lxJLYXTgfEeYuRv85pjr8bueT7KEv8eEOAfBBdxvFu8l+dnhW/U1PPB68klcIN7WVRAW619xEbBNwmD/dW8JfJEF97XqHw4mJdWNN3hxyg+a6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1775668124; c=relaxed/simple; bh=rcpwryuEThlZF4upS3cCoE0WjIeBtxUV+f2V6hrTY+o=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=oUQQidCPbAg1hVgsrHwUoBbMWSRn0PjnMm36nPNLAETTKXEBTM0vxOdLQKiDbhMfB+U9RzVVeOFatv74XgXJTmvAxUzRUbBX7VAVOsJSAobMJKhOHA8lASjk+8A6G+nlA6oH6VKwjlKku83jFihh0pydhC9vj4NEDkWtkOqXJVM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=TSNtX1w2; arc=none smtp.client-ip=209.85.210.176 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="TSNtX1w2" Received: by mail-pf1-f176.google.com with SMTP id d2e1a72fcca58-82c68339cf0so663120b3a.0 for ; Wed, 08 Apr 2026 10:08:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1775668122; x=1776272922; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=EKkzFs5JDjxn2dtILtgHOZXS7Y3HfRJU6U7EopQqpaY=; b=TSNtX1w214BSPl2VezCLMReh0SPW51z2diyAm29o8Ep9aiW+L/845QVwAXWdCIJ4wY c0ixJQh075X3z6Kv17aZ9i/f4/TN3SKHbCmJcHF3LcmmOuq5CoWgne3kOA4LZN/Yi/i4 9mF8Al5LfLw+3ssk7x5+nzUvMkHqcJl/YLKMAfyMxnbhKDDveuV35LgirEjfYo5Rqagl rI8z4DfHUGtOzn9CO+tyTmY5WrVTjdjj+tZkpWC3O/9Wk32SIgTjZoB83egpmQa4TpGD 003bZZPJ646t6NGFRPd0HKlf4ZrV9B1Xv4jVjI1GSZNmuMGnasH1qE4PFa9MW5oaU5j7 u3fg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1775668122; x=1776272922; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=EKkzFs5JDjxn2dtILtgHOZXS7Y3HfRJU6U7EopQqpaY=; b=ohyPc49aeYnHv7SciF2HQK/p+4TBmZT0Y014MiEFMJ57b22gTevb24wb55FppX3gtS Zmo/xTI8MsdYduUM3TZg98tDFGMwGZ1CcXVQ5e07FHBIm5GZUenurP1R4QCJKRAYY2G4 0IP3ij5TmoA5h5Ul6dcfk3udhRXvLdMDdfBaPwNjKQrvYyMRs6Hf92Ah/vVJ7eOs/vhj y3AuivspKz3UKekuRDCCZ2UfyF3dDaLmppqPl3InCjpdAVKhoULmf+MFeEAISsxoc8kB 3holohsOTpWJPZZ4444hfEPG/QG1QWNsIWV6/YpxY5oWrZ3h1PhjwVHAgnJNYYkmJ5RX vwRg== X-Forwarded-Encrypted: i=1; AJvYcCUsJqHE9O/Jvf1JarkYNXIX2r3Lqrg6oT2/ALu3iTEmAaLrwjHMCU6m4awYwQvd1NuwJ38TYldZGMSSLik=@vger.kernel.org X-Gm-Message-State: AOJu0Yw0fPhAKiuEKq/ObrcIdiJh3rH2AOW2rulYGfJ73/sb99HvrfA9 f13cFnhFbj96GlHhPJcyjJ2s8c5G3V3lYS/tc5alqNgtabSMYq/xnfyF X-Gm-Gg: AeBDievEmua0Pw3Zb790jv5/H01KCx3b39wBvUDw4bIfXO5bCJ+g9I+rRwm+s3IrOKJ 49mPnb7o8WStQIXwThOt5DNPJlayPDkvFVd1sG2B7CN7meOi7qhVbYcm3awvx8TIUPd8aA4GksG /yFVLq09YpVliZIOPuzRzrS9MBTVBdmAsfk55TSbPrDbe+OM3fDd12gloKlsqRUYgwdTscPkOo8 j6+XfYbWk1SCwlYJXDHZ4O6Luh4Gye0UWIf0kMPEQoSv25gZggKUGV+Q8i4xxHxua5E1m8FJsF1 1fc6ZktzLg14heP8TpCcuSRaiT+llCYR57UdgVfWLAO5qJtUL7FxxW5V9T8VKqfUn5PD3LoAfIP C0fyA2ZwbuOCwiIaDHJt4SZP16pVmapwsKOzrBMBh/pOHJYOluHchyWKYhsW6ENtOrnCPejRnMX 08gzupSqMjnEQXe5WdlhiaMZWe7jqxM7ulXFC0zeOSLRqniaCU3hWPAbV6KHcgop7JD1WZFJdx+ 9b4WQHu5TQ1tvDUQj6Kmb8ib9M+tOd1ojOP/5SkM4SbQocKv7MawVuyXg== X-Received: by 2002:a05:6a20:918b:b0:398:71f2:59dd with SMTP id adf61e73a8af0-39fc936e551mr285412637.9.1775668122444; Wed, 08 Apr 2026 10:08:42 -0700 (PDT) Received: from lorddaniel-VivoBook-ASUSLaptop-K3502ZA-S3502ZA.www.tendawifi.com ([14.139.108.62]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-82cf9b2694csm21775091b3a.2.2026.04.08.10.08.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Apr 2026 10:08:41 -0700 (PDT) From: Piyush Patle To: Mark Brown Cc: Sheetal , Jonathan Hunter , Thierry Reding , Liam Girdwood , Jaroslav Kysela , Takashi Iwai , Kuninori Morimoto , linux-sound@vger.kernel.org, linux-tegra@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 2/2] ASoC: tegra210_amx: simplify byte map get/put logic Date: Wed, 8 Apr 2026 22:38:18 +0530 Message-Id: <20260408170818.70322-3-piyushpatle228@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260408170818.70322-1-piyushpatle228@gmail.com> References: <20260407170308.100238-3-piyushpatle228@gmail.com> <20260408170818.70322-1-piyushpatle228@gmail.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 Content-Type: text/plain; charset="utf-8" The byte-map controls ("Byte Map N") already expose a value range of [0, 256] to userspace via SOC_SINGLE_EXT(), where 256 is the "disabled" sentinel. The driver stored this state as a byte-packed u32 map[] array plus a separate byte_mask[] bitmap tracking which slots were enabled, because 256 does not fit in a byte. As a result get_byte_map() had to consult byte_mask[] to decide whether to report the stored byte or 256, and put_byte_map() had to keep the two arrays in sync on every write. Store each slot as a u16 holding the control value directly (0..255 enabled, 256 disabled). This is the native representation for what userspace already sees, so get_byte_map() becomes a direct return and put_byte_map() becomes a compare-and-store. The hardware-facing packed RAM word and the OUT_BYTE_EN mask are now derived on the fly inside tegra210_amx_write_map_ram() from the slot array, which is the only place that needs to know about the hardware layout. The byte_mask scratch buffer is allocated dynamically using kcalloc() based on soc_data->byte_mask_size, removing dependency on SoC-specific constants. The byte_mask field is dropped from struct tegra210_amx. A new TEGRA_AMX_SLOTS_PER_WORD constant replaces the literal '4' used for byte slots per RAM word, and BITS_PER_BYTE / BITS_PER_TYPE() from replace the literal '8' and '32' shifts. Slots are initialised to 256 in probe() so the default reported value stays "disabled", matching previous behaviour. Values written from userspace that fall outside [0, 255] are clamped to 256 ("disabled") exactly as before -- no userspace-visible change. As a side effect this also fixes a latent bug in the previous put_byte_map(): because it compared the enable mask rather than the stored byte, changing a slot from one enabled value to another enabled value (e.g. 42 -> 99) would early-return without persisting the new value, and the next CFG_RAM flush would still program the old byte. The new implementation compares the stored value itself, so this case is now handled correctly. Addresses TODO left in tegra210_amx_get_byte_map(). Signed-off-by: Piyush Patle --- Changes since v1: - Allocate byte_mask[] dynamically using kcalloc() - Propagate -ENOMEM from write_map_ram() - Replace magic numbers with TEGRA_AMX_SLOTS_PER_WORD - Use BITS_PER_BYTE and BITS_PER_TYPE() - Add and sound/soc/tegra/tegra210_amx.c | 96 ++++++++++++++++++---------------- sound/soc/tegra/tegra210_amx.h | 6 ++- 2 files changed, 54 insertions(+), 48 deletions(-) diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c index bfda82505298..bc808fabe171 100644 --- a/sound/soc/tegra/tegra210_amx.c +++ b/sound/soc/tegra/tegra210_amx.c @@ -4,6 +4,7 @@ // // tegra210_amx.c - Tegra210 AMX driver =20 +#include #include #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -58,23 +60,48 @@ static const struct reg_default tegra264_amx_reg_defaul= ts[] =3D { { TEGRA264_AMX_CFG_RAM_CTRL, 0x00004000}, }; =20 -static void tegra210_amx_write_map_ram(struct tegra210_amx *amx) +static int tegra210_amx_write_map_ram(struct tegra210_amx *amx) { + const unsigned int bits_per_mask =3D BITS_PER_TYPE(*amx->map) * BITS_PER_= BYTE; + unsigned int *byte_mask; int i; =20 + byte_mask =3D kcalloc(amx->soc_data->byte_mask_size, sizeof(*byte_mask), + GFP_KERNEL); + if (!byte_mask) + return -ENOMEM; + regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL + amx->soc_data->reg_= offset, TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN | TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN | TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE); =20 - for (i =3D 0; i < amx->soc_data->ram_depth; i++) + for (i =3D 0; i < amx->soc_data->ram_depth; i++) { + u32 word =3D 0; + int b; + + for (b =3D 0; b < TEGRA_AMX_SLOTS_PER_WORD; b++) { + unsigned int slot =3D i * TEGRA_AMX_SLOTS_PER_WORD + b; + u16 val =3D amx->map[slot]; + + if (val >=3D 256) + continue; + + word |=3D (u32)val << (b * BITS_PER_BYTE); + byte_mask[slot / bits_per_mask] |=3D 1U << (slot % bits_per_mask); + } regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA + amx->soc_data->reg= _offset, - amx->map[i]); + word); + } =20 for (i =3D 0; i < amx->soc_data->byte_mask_size; i++) regmap_write(amx->regmap, TEGRA210_AMX_OUT_BYTE_EN0 + (i * TEGRA210_AMX_AUDIOCIF_CH_STRIDE), - amx->byte_mask[i]); + byte_mask[i]); + + kfree(byte_mask); + + return 0; } =20 static int tegra210_amx_startup(struct snd_pcm_substream *substream, @@ -134,9 +161,7 @@ static int tegra210_amx_runtime_resume(struct device *d= ev) TEGRA210_AMX_CTRL_RX_DEP_MASK, TEGRA210_AMX_WAIT_ON_ANY << TEGRA210_AMX_CTRL_RX_DEP_SHIFT); =20 - tegra210_amx_write_map_ram(amx); - - return 0; + return tegra210_amx_write_map_ram(amx); } =20 static int tegra210_amx_set_audio_cif(struct snd_soc_dai *dai, @@ -212,26 +237,8 @@ static int tegra210_amx_get_byte_map(struct snd_kcontr= ol *kcontrol, struct soc_mixer_control *mc =3D (struct soc_mixer_control *)kcontrol->private_value; struct tegra210_amx *amx =3D snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map =3D (unsigned char *)amx->map; - int reg =3D mc->reg; - int enabled; - - enabled =3D amx->byte_mask[reg / 32] & (1 << (reg % 32)); =20 - /* - * TODO: Simplify this logic to just return from bytes_map[] - * - * Presently below is required since bytes_map[] is - * tightly packed and cannot store the control value of 256. - * Byte mask state is used to know if 256 needs to be returned. - * Note that for control value of 256, the put() call stores 0 - * in the bytes_map[] and disables the corresponding bit in - * byte_mask[]. - */ - if (enabled) - ucontrol->value.integer.value[0] =3D bytes_map[reg]; - else - ucontrol->value.integer.value[0] =3D 256; + ucontrol->value.integer.value[0] =3D amx->map[mc->reg]; =20 return 0; } @@ -243,22 +250,20 @@ static int tegra210_amx_put_byte_map(struct snd_kcont= rol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct snd_soc_component *cmpnt =3D snd_kcontrol_chip(kcontrol); struct tegra210_amx *amx =3D snd_soc_component_get_drvdata(cmpnt); - unsigned char *bytes_map =3D (unsigned char *)amx->map; - int reg =3D mc->reg; - int value =3D ucontrol->value.integer.value[0]; - unsigned int mask_val =3D amx->byte_mask[reg / 32]; + unsigned int value =3D ucontrol->value.integer.value[0]; =20 - if (value >=3D 0 && value <=3D 255) - mask_val |=3D (1 << (reg % 32)); - else - mask_val &=3D ~(1 << (reg % 32)); + /* + * Match the previous behaviour: any value outside [0, 255] is + * treated as the "disabled" sentinel (256). Negative values from + * userspace fold in through the unsigned cast and are caught here. + */ + if (value > 255) + value =3D 256; =20 - if (mask_val =3D=3D amx->byte_mask[reg / 32]) + if (amx->map[mc->reg] =3D=3D value) return 0; =20 - /* Update byte map and slot */ - bytes_map[reg] =3D value % 256; - amx->byte_mask[reg / 32] =3D mask_val; + amx->map[mc->reg] =3D value; =20 return 1; } @@ -727,7 +732,7 @@ static int tegra210_amx_platform_probe(struct platform_= device *pdev) struct device *dev =3D &pdev->dev; struct tegra210_amx *amx; void __iomem *regs; - int err; + int err, i; =20 amx =3D devm_kzalloc(dev, sizeof(*amx), GFP_KERNEL); if (!amx) @@ -750,16 +755,15 @@ static int tegra210_amx_platform_probe(struct platfor= m_device *pdev) =20 regcache_cache_only(amx->regmap, true); =20 - amx->map =3D devm_kzalloc(dev, amx->soc_data->ram_depth * sizeof(*amx->ma= p), - GFP_KERNEL); + amx->map =3D devm_kcalloc(dev, + amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD, + sizeof(*amx->map), GFP_KERNEL); if (!amx->map) return -ENOMEM; =20 - amx->byte_mask =3D devm_kzalloc(dev, - amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask), - GFP_KERNEL); - if (!amx->byte_mask) - return -ENOMEM; + /* Initialise all byte map slots as disabled (value 256). */ + for (i =3D 0; i < amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD; i+= +) + amx->map[i] =3D 256; =20 tegra210_amx_dais[TEGRA_AMX_OUT_DAI_ID].capture.channels_max =3D amx->soc_data->max_ch; diff --git a/sound/soc/tegra/tegra210_amx.h b/sound/soc/tegra/tegra210_amx.h index 50a237b197ba..2c125a191a1a 100644 --- a/sound/soc/tegra/tegra210_amx.h +++ b/sound/soc/tegra/tegra210_amx.h @@ -8,6 +8,8 @@ #ifndef __TEGRA210_AMX_H__ #define __TEGRA210_AMX_H__ =20 +#include + /* Register offsets from TEGRA210_AMX*_BASE */ #define TEGRA210_AMX_RX_STATUS 0x0c #define TEGRA210_AMX_RX_INT_STATUS 0x10 @@ -73,6 +75,7 @@ #define TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK TEGRA210_AMX_SOFT_RESET_S= OFT_EN =20 #define TEGRA210_AMX_AUDIOCIF_CH_STRIDE 4 +#define TEGRA_AMX_SLOTS_PER_WORD 4 #define TEGRA210_AMX_RAM_DEPTH 16 #define TEGRA210_AMX_MAP_STREAM_NUM_SHIFT 6 #define TEGRA210_AMX_MAP_WORD_NUM_SHIFT 2 @@ -105,8 +108,7 @@ struct tegra210_amx_soc_data { =20 struct tegra210_amx { const struct tegra210_amx_soc_data *soc_data; - unsigned int *map; - unsigned int *byte_mask; + u16 *map; struct regmap *regmap; }; =20 --=20 2.34.1