Files
linux/sound/soc/tegra/tegra210_amx.h
Piyush Patle 445af52d4c ASoC: tegra210_amx: 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 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 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_AMX_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_amx_get_byte_map().

Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Link: https://patch.msgid.link/20260410200530.171323-3-piyushpatle228@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
2026-04-27 08:34:33 +09:00

117 lines
3.7 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only
* SPDX-FileCopyrightText: Copyright (c) 2021-2025 NVIDIA CORPORATION. All rights reserved.
*
* tegra210_amx.h - Definitions for Tegra210 AMX driver
*
*/
#ifndef __TEGRA210_AMX_H__
#define __TEGRA210_AMX_H__
#include <linux/types.h>
/* Register offsets from TEGRA210_AMX*_BASE */
#define TEGRA210_AMX_RX_STATUS 0x0c
#define TEGRA210_AMX_RX_INT_STATUS 0x10
#define TEGRA210_AMX_RX_INT_MASK 0x14
#define TEGRA210_AMX_RX_INT_SET 0x18
#define TEGRA210_AMX_RX_INT_CLEAR 0x1c
#define TEGRA210_AMX_RX1_CIF_CTRL 0x20
#define TEGRA210_AMX_RX2_CIF_CTRL 0x24
#define TEGRA210_AMX_RX3_CIF_CTRL 0x28
#define TEGRA210_AMX_RX4_CIF_CTRL 0x2c
#define TEGRA210_AMX_TX_STATUS 0x4c
#define TEGRA210_AMX_TX_INT_STATUS 0x50
#define TEGRA210_AMX_TX_INT_MASK 0x54
#define TEGRA210_AMX_TX_INT_SET 0x58
#define TEGRA210_AMX_TX_INT_CLEAR 0x5c
#define TEGRA210_AMX_TX_CIF_CTRL 0x60
#define TEGRA210_AMX_ENABLE 0x80
#define TEGRA210_AMX_SOFT_RESET 0x84
#define TEGRA210_AMX_CG 0x88
#define TEGRA210_AMX_STATUS 0x8c
#define TEGRA210_AMX_INT_STATUS 0x90
#define TEGRA210_AMX_CTRL 0xa4
#define TEGRA210_AMX_OUT_BYTE_EN0 0xa8
#define TEGRA210_AMX_CYA 0xb0
#define TEGRA210_AMX_CFG_RAM_CTRL 0xb8
#define TEGRA210_AMX_CFG_RAM_DATA 0xbc
#define TEGRA194_AMX_RX1_FRAME_PERIOD 0xc0
#define TEGRA194_AMX_RX4_FRAME_PERIOD 0xcc
#define TEGRA194_AMX_RX4_LAST_FRAME_PERIOD 0xdc
#define TEGRA264_AMX_STREAMS_AUTO_DISABLE 0xb8
#define TEGRA264_AMX_CFG_RAM_CTRL 0xc0
#define TEGRA264_AMX_CFG_RAM_DATA 0xc4
#define TEGRA264_AMX_RX1_FRAME_PERIOD 0xc8
#define TEGRA264_AMX_RX4_FRAME_PERIOD 0xd4
#define TEGRA264_AMX_RX4_LAST_FRAME_PERIOD 0xe4
/* Fields in TEGRA210_AMX_ENABLE */
#define TEGRA210_AMX_ENABLE_SHIFT 0
/* Fields in TEGRA210_AMX_CTRL */
#define TEGRA210_AMX_CTRL_MSTR_RX_NUM_SHIFT 14
#define TEGRA210_AMX_CTRL_MSTR_RX_NUM_MASK (3 << TEGRA210_AMX_CTRL_MSTR_RX_NUM_SHIFT)
#define TEGRA210_AMX_CTRL_RX_DEP_SHIFT 12
#define TEGRA210_AMX_CTRL_RX_DEP_MASK (3 << TEGRA210_AMX_CTRL_RX_DEP_SHIFT)
/* Fields in TEGRA210_AMX_CFG_RAM_CTRL */
#define TEGRA210_AMX_CFG_RAM_CTRL_RW_SHIFT 14
#define TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE (1 << TEGRA210_AMX_CFG_RAM_CTRL_RW_SHIFT)
#define TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT 13
#define TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN (1 << TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN_SHIFT)
#define TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT 12
#define TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN (1 << TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN_SHIFT)
#define TEGRA210_AMX_CFG_CTRL_RAM_ADDR_SHIFT 0
/* Fields in TEGRA210_AMX_SOFT_RESET */
#define TEGRA210_AMX_SOFT_RESET_SOFT_EN 1
#define TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK TEGRA210_AMX_SOFT_RESET_SOFT_EN
#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
#define TEGRA210_AMX_MAP_BYTE_NUM_SHIFT 0
#define TEGRA210_AMX_BYTE_MASK_COUNT 2
#define TEGRA210_AMX_MAX_CHANNEL 16
#define TEGRA210_AMX_AUTO_DISABLE_OFFSET 0
#define TEGRA264_AMX_RAM_DEPTH 32
#define TEGRA264_AMX_BYTE_MASK_COUNT 4
#define TEGRA264_AMX_MAX_CHANNEL 32
#define TEGRA264_AMX_AUTO_DISABLE_OFFSET 8
#define TEGRA_AMX_OUT_DAI_ID 4
enum {
TEGRA210_AMX_WAIT_ON_ALL,
TEGRA210_AMX_WAIT_ON_ANY,
};
struct tegra210_amx_soc_data {
const struct regmap_config *regmap_conf;
bool auto_disable;
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 reg_offset;
};
struct tegra210_amx {
const struct tegra210_amx_soc_data *soc_data;
unsigned int *byte_mask;
u16 *map;
struct regmap *regmap;
};
#endif