Files
linux/sound/soc/tegra/tegra210_adx.h
Piyush Patle 0c1f5e6e7b ASoC: tegra210_adx: simplify byte map get/put logic
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 buffer is allocated in probe() using devm_kcalloc()
with soc_data->byte_mask_size, so it scales to any SoC variant
without depending on chip-specific constants. It is zeroed and
recomputed each time write_map_ram() is called.

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 <linux/bits.h> 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 <piyushpatle228@gmail.com>
Link: https://patch.msgid.link/20260410200530.171323-2-piyushpatle228@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-04-27 08:34:32 +09:00

100 lines
3.2 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION. All rights reserved.
*
* tegra210_adx.h - Definitions for Tegra210 ADX driver
*
*/
#ifndef __TEGRA210_ADX_H__
#define __TEGRA210_ADX_H__
#include <linux/types.h>
/* Register offsets from TEGRA210_ADX*_BASE */
#define TEGRA210_ADX_RX_STATUS 0x0c
#define TEGRA210_ADX_RX_INT_STATUS 0x10
#define TEGRA210_ADX_RX_INT_MASK 0x14
#define TEGRA210_ADX_RX_INT_SET 0x18
#define TEGRA210_ADX_RX_INT_CLEAR 0x1c
#define TEGRA210_ADX_RX_CIF_CTRL 0x20
#define TEGRA210_ADX_TX_STATUS 0x4c
#define TEGRA210_ADX_TX_INT_STATUS 0x50
#define TEGRA210_ADX_TX_INT_MASK 0x54
#define TEGRA210_ADX_TX_INT_SET 0x58
#define TEGRA210_ADX_TX_INT_CLEAR 0x5c
#define TEGRA210_ADX_TX1_CIF_CTRL 0x60
#define TEGRA210_ADX_TX2_CIF_CTRL 0x64
#define TEGRA210_ADX_TX3_CIF_CTRL 0x68
#define TEGRA210_ADX_TX4_CIF_CTRL 0x6c
#define TEGRA210_ADX_ENABLE 0x80
#define TEGRA210_ADX_SOFT_RESET 0x84
#define TEGRA210_ADX_CG 0x88
#define TEGRA210_ADX_STATUS 0x8c
#define TEGRA210_ADX_INT_STATUS 0x90
#define TEGRA210_ADX_CTRL 0xa4
#define TEGRA210_ADX_IN_BYTE_EN0 0xa8
#define TEGRA210_ADX_IN_BYTE_EN1 0xac
#define TEGRA210_ADX_CFG_RAM_CTRL 0xb8
#define TEGRA210_ADX_CFG_RAM_DATA 0xbc
#define TEGRA264_ADX_CYA 0xb8
#define TEGRA264_ADX_CFG_RAM_CTRL 0xc0
#define TEGRA264_ADX_CFG_RAM_DATA 0xc4
/* Fields in TEGRA210_ADX_ENABLE */
#define TEGRA210_ADX_ENABLE_SHIFT 0
/* Fields in TEGRA210_ADX_CFG_RAM_CTRL */
#define TEGRA210_ADX_CFG_RAM_CTRL_RAM_ADDR_SHIFT 0
#define TEGRA210_ADX_CFG_RAM_CTRL_RW_SHIFT 14
#define TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE (1 << TEGRA210_ADX_CFG_RAM_CTRL_RW_SHIFT)
#define TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT 13
#define TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN (1 << TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT)
#define TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT 12
#define TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN (1 << TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT)
/* Fields in TEGRA210_ADX_SOFT_RESET */
#define TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT 0
#define TEGRA210_ADX_SOFT_RESET_SOFT_RESET_MASK (1 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
#define TEGRA210_ADX_SOFT_RESET_SOFT_EN (1 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
#define TEGRA210_ADX_SOFT_RESET_SOFT_DEFAULT (0 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
#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
#define TEGRA210_ADX_MAP_BYTE_NUMBER_SHIFT 0
#define TEGRA210_ADX_BYTE_MASK_COUNT 2
#define TEGRA210_ADX_MAX_CHANNEL 16
#define TEGRA210_ADX_CYA_OFFSET 0
#define TEGRA264_ADX_RAM_DEPTH 32
#define TEGRA264_ADX_BYTE_MASK_COUNT 4
#define TEGRA264_ADX_MAX_CHANNEL 32
#define TEGRA264_ADX_CYA_OFFSET 8
#define TEGRA_ADX_IN_DAI_ID 4
struct tegra210_adx_soc_data {
const struct regmap_config *regmap_conf;
const struct snd_kcontrol_new *controls;
unsigned int num_controls;
unsigned int max_ch;
unsigned int ram_depth;
unsigned int byte_mask_size;
unsigned int cya_offset;
};
struct tegra210_adx {
struct regmap *regmap;
unsigned int *byte_mask;
u16 *map;
const struct tegra210_adx_soc_data *soc_data;
};
#endif