mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
ASoC: tac5xx2-sdw: add soundwire based codec driver
Add codec driver for tac5xx2 family of devices. This includes the support for 1. tac5572 - DAC, PDM, UAJ and HID 2. tas2883 - Amplifier with DSP 3. tac5672 - Similar to tac5572 with feedback 4. tac5682 - Similar to tac5672 with Amplifier DSP. Signed-off-by: Niranjan H Y <niranjan.hy@ti.com> Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev> Link: https://patch.msgid.link/20260505111806.2280-3-niranjan.hy@ti.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
cdff2e6ab8
commit
38c89feded
|
|
@ -264,6 +264,7 @@ config SND_SOC_ALL_CODECS
|
|||
imply SND_SOC_STA529
|
||||
imply SND_SOC_STAC9766
|
||||
imply SND_SOC_STI_SAS
|
||||
imply SND_SOC_TAC5XX2_SDW
|
||||
imply SND_SOC_TAS2552
|
||||
imply SND_SOC_TAS2562
|
||||
imply SND_SOC_TAS2764
|
||||
|
|
@ -2140,6 +2141,16 @@ config SND_SOC_STAC9766
|
|||
config SND_SOC_STI_SAS
|
||||
tristate "codec Audio support for STI SAS codec"
|
||||
|
||||
config SND_SOC_TAC5XX2_SDW
|
||||
tristate "Texas Instruments TAC5XX2 SoundWire Smart Amplifier"
|
||||
depends on SOUNDWIRE
|
||||
depends on SND_SOC_SDCA
|
||||
help
|
||||
This option enables support for Texas Instruments TAC5XX2 family
|
||||
of SoundWire Smart Amplifiers. This includes TAC5572, TAC5672,
|
||||
TAC5682 and TAS2883. To compile this driver as a module, choose
|
||||
M here: the module will be called snd-soc-tac5xx2.
|
||||
|
||||
config SND_SOC_TAS2552
|
||||
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
|
||||
depends on I2C
|
||||
|
|
|
|||
|
|
@ -313,6 +313,7 @@ snd-soc-sta350-y := sta350.o
|
|||
snd-soc-sta529-y := sta529.o
|
||||
snd-soc-stac9766-y := stac9766.o
|
||||
snd-soc-sti-sas-y := sti-sas.o
|
||||
snd-soc-tac5xx2-sdw-y := tac5xx2-sdw.o
|
||||
snd-soc-tas5086-y := tas5086.o
|
||||
snd-soc-tas571x-y := tas571x.o
|
||||
snd-soc-tas5720-y := tas5720.o
|
||||
|
|
@ -747,6 +748,7 @@ obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
|
|||
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
|
||||
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
|
||||
obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
|
||||
obj-$(CONFIG_SND_SOC_TAC5XX2_SDW) += snd-soc-tac5xx2-sdw.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o
|
||||
obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o
|
||||
|
|
|
|||
2047
sound/soc/codecs/tac5xx2-sdw.c
Normal file
2047
sound/soc/codecs/tac5xx2-sdw.c
Normal file
File diff suppressed because it is too large
Load Diff
259
sound/soc/codecs/tac5xx2.h
Normal file
259
sound/soc/codecs/tac5xx2.h
Normal file
|
|
@ -0,0 +1,259 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0
|
||||
*
|
||||
* ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier
|
||||
*
|
||||
* Copyright (C) 2025 Texas Instruments Incorporated
|
||||
* https://www.ti.com
|
||||
*
|
||||
* This the header file for TAC5XX2 family of devices
|
||||
* which includes TAC5572, TAC5672, TAC5682 and TAS2883
|
||||
*
|
||||
* Author: Niranjan H Y <niranjanhy@ti.com>
|
||||
*/
|
||||
#ifndef __RGL_TAC5XX2_H__
|
||||
#define __RGL_TAC5XX2_H__
|
||||
|
||||
/* for soundwire */
|
||||
#define TAC_REG_SDW(book, page, reg) (((book) * 256 * 128) + \
|
||||
0x3000000 + ((page) * 128) + (reg))
|
||||
|
||||
/* page 0 registers */
|
||||
#define TAC_SW_RESET TAC_REG_SDW(0, 0, 1)
|
||||
#define TAC_SLEEP_MODEZ TAC_REG_SDW(0, 0, 2)
|
||||
#define TAC_FEATURE_PDZ TAC_REG_SDW(0, 0, 3)
|
||||
#define TAC_TX_CH_EN TAC_REG_SDW(0, 0, 4)
|
||||
#define TAC_RX_CH_PD TAC_REG_SDW(0, 0, 5)
|
||||
#define TAC_SHDNZ_CFG TAC_REG_SDW(0, 0, 6)
|
||||
#define TAC_MISC_CFG0 TAC_REG_SDW(0, 0, 7)
|
||||
#define TAC_MISC_CFG1 TAC_REG_SDW(0, 0, 8)
|
||||
#define TAC_GPIO1_CFG0 TAC_REG_SDW(0, 0, 9)
|
||||
#define TAC_GPIO2_CFG0 TAC_REG_SDW(0, 0, 10)
|
||||
#define TAC_GPIO3_CFG0 TAC_REG_SDW(0, 0, 11)
|
||||
#define TAC_GPIO4_CFG0 TAC_REG_SDW(0, 0, 12)
|
||||
#define TAC_GPIO5_CFG0 TAC_REG_SDW(0, 0, 13)
|
||||
#define TAC_GPIO6_CFG0 TAC_REG_SDW(0, 0, 14)
|
||||
#define TAC_INTF_CFG1 TAC_REG_SDW(0, 0, 15)
|
||||
#define TAC_INTF_CFG5 TAC_REG_SDW(0, 0, 16)
|
||||
#define TAC_PASI_BCLK_CFG0 TAC_REG_SDW(0, 0, 17)
|
||||
#define TAC_PASI_FSYNC_CFG0 TAC_REG_SDW(0, 0, 18)
|
||||
#define TAC_PASI_DIN1_CFG0 TAC_REG_SDW(0, 0, 19)
|
||||
#define TAC_PASI_DIN2_CFG0 TAC_REG_SDW(0, 0, 20)
|
||||
#define TAC_PDM_DIN1_CFG0 TAC_REG_SDW(0, 0, 21)
|
||||
#define TAC_PDM_DIN2_CFG0 TAC_REG_SDW(0, 0, 22)
|
||||
#define TAC_MCLK_SEL TAC_REG_SDW(0, 0, 23)
|
||||
#define TAC_I2C2_CFG0 TAC_REG_SDW(0, 0, 24)
|
||||
#define TAC_SDW_IO_CFG0 TAC_REG_SDW(0, 0, 25)
|
||||
#define TAC_SDW_CLK_CFG0 TAC_REG_SDW(0, 0, 26)
|
||||
#define TAC_PASI_CFG0 TAC_REG_SDW(0, 0, 27)
|
||||
#define TAC_PASI_CFG1 TAC_REG_SDW(0, 0, 28)
|
||||
#define TAC_PASI_TX_CFG0 TAC_REG_SDW(0, 0, 29)
|
||||
#define TAC_PASI_TX_CFG1 TAC_REG_SDW(0, 0, 30)
|
||||
#define TAC_PASI_TX_CFG2 TAC_REG_SDW(0, 0, 31)
|
||||
#define TAC_PASI_TX_CFG3 TAC_REG_SDW(0, 0, 32)
|
||||
#define TAC_PASI_TX_CH1_CFG0 TAC_REG_SDW(0, 0, 33)
|
||||
#define TAC_PASI_TX_CH2_CFG0 TAC_REG_SDW(0, 0, 34)
|
||||
#define TAC_PASI_TX_CH3_CFG0 TAC_REG_SDW(0, 0, 35)
|
||||
#define TAC_PASI_TX_CH4_CFG0 TAC_REG_SDW(0, 0, 36)
|
||||
#define TAC_PASI_TX_CH5_CFG0 TAC_REG_SDW(0, 0, 37)
|
||||
#define TAC_PASI_TX_CH6_CFG0 TAC_REG_SDW(0, 0, 38)
|
||||
#define TAC_PASI_TX_CH7_CFG0 TAC_REG_SDW(0, 0, 39)
|
||||
#define TAC_PASI_TX_CH8_CFG0 TAC_REG_SDW(0, 0, 40)
|
||||
#define TAC_PASI_RX_CFG0 TAC_REG_SDW(0, 0, 41)
|
||||
#define TAC_PASI_RX_CFG1 TAC_REG_SDW(0, 0, 42)
|
||||
#define TAC_PASI_RX_CFG2 TAC_REG_SDW(0, 0, 43)
|
||||
#define TAC_PASI_RX_CH1_CFG0 TAC_REG_SDW(0, 0, 44)
|
||||
#define TAC_PASI_RX_CH2_CFG0 TAC_REG_SDW(0, 0, 45)
|
||||
#define TAC_PASI_RX_CH3_CFG0 TAC_REG_SDW(0, 0, 46)
|
||||
#define TAC_PASI_RX_CH4_CFG0 TAC_REG_SDW(0, 0, 47)
|
||||
#define TAC_PASI_RX_CH5_CFG0 TAC_REG_SDW(0, 0, 48)
|
||||
#define TAC_PASI_RX_CH6_CFG0 TAC_REG_SDW(0, 0, 49)
|
||||
#define TAC_PASI_RX_CH7_CFG0 TAC_REG_SDW(0, 0, 50)
|
||||
#define TAC_PASI_RX_CH8_CFG0 TAC_REG_SDW(0, 0, 51)
|
||||
#define TAC_ADC_CH1_CFG0 TAC_REG_SDW(0, 0, 52)
|
||||
#define TAC_ADC_DVOL_CFG0 TAC_REG_SDW(0, 0, 53)
|
||||
#define TAC_ADC_CH1_FGAIN TAC_REG_SDW(0, 0, 54)
|
||||
#define TAC_ADC_CH1_CFG1 TAC_REG_SDW(0, 0, 55)
|
||||
#define TAC_ADC_CH2_CFG0 TAC_REG_SDW(0, 0, 57)
|
||||
#define TAC_ADC_DVOL_CFG1 TAC_REG_SDW(0, 0, 58)
|
||||
#define TAC_ADC_CH2_FGAIN TAC_REG_SDW(0, 0, 59)
|
||||
#define TAC_ADC_CH2_CFG1 TAC_REG_SDW(0, 0, 60)
|
||||
#define TAC_ADC_CFG1 TAC_REG_SDW(0, 0, 62)
|
||||
#define TAC_PDM_CH1_DVOL TAC_REG_SDW(0, 0, 63)
|
||||
#define TAC_PDM_CH1_FGAIN TAC_REG_SDW(0, 0, 64)
|
||||
#define TAC_PDM_CH1_CFG0 TAC_REG_SDW(0, 0, 65)
|
||||
#define TAC_PDM_CH2_DVOL TAC_REG_SDW(0, 0, 67)
|
||||
#define TAC_PDM_CH2_FGAIN TAC_REG_SDW(0, 0, 68)
|
||||
#define TAC_PDM_CH2_CFG2 TAC_REG_SDW(0, 0, 69)
|
||||
#define TAC_PDM_CH3_DVOL TAC_REG_SDW(0, 0, 71)
|
||||
#define TAC_PDM_CH3_FGAIN TAC_REG_SDW(0, 0, 72)
|
||||
#define TAC_PDM_CH3_CFG0 TAC_REG_SDW(0, 0, 73)
|
||||
#define TAC_PDM_CH4_DVOL TAC_REG_SDW(0, 0, 75)
|
||||
#define TAC_PDM_CH4_FGAIN TAC_REG_SDW(0, 0, 76)
|
||||
#define TAC_PDM_CH4_CFG0 TAC_REG_SDW(0, 0, 77)
|
||||
#define TAC_MICBIAS_CFG0 TAC_REG_SDW(0, 0, 79)
|
||||
#define TAC_MICPREAMP_CFG TAC_REG_SDW(0, 0, 80)
|
||||
#define TAC_MICBIAS_CFG1 TAC_REG_SDW(0, 0, 81)
|
||||
#define TAC_CLASSD_CH1_DVOL TAC_REG_SDW(0, 0, 82)
|
||||
#define TAC_CLASSD_CH1_FGAIN TAC_REG_SDW(0, 0, 83)
|
||||
#define TAC_CLASSD_CH2_DVOL TAC_REG_SDW(0, 0, 85)
|
||||
#define TAC_CLASSD_CH2_FGAIN TAC_REG_SDW(0, 0, 86)
|
||||
#define TAC_GCHP_CH1_DVOL TAC_REG_SDW(0, 0, 88)
|
||||
#define TAC_GCHP_CH1_FGAIN TAC_REG_SDW(0, 0, 89)
|
||||
#define TAC_GCHP_CH2_DVOL TAC_REG_SDW(0, 0, 91)
|
||||
#define TAC_GCHP_CH2_FGAIN TAC_REG_SDW(0, 0, 92)
|
||||
#define TAC_AMP_LVL_CFG0 TAC_REG_SDW(0, 0, 94)
|
||||
#define TAC_AMP_LVL_CFG1 TAC_REG_SDW(0, 0, 95)
|
||||
#define TAC_AMP_LVL_CFG2 TAC_REG_SDW(0, 0, 96)
|
||||
#define TAC_AMP_LVL_CFG3 TAC_REG_SDW(0, 0, 97)
|
||||
#define TAC_EFF_MODE_CFG0 TAC_REG_SDW(0, 0, 98)
|
||||
#define TAC_EFF_MODE_CFG1 TAC_REG_SDW(0, 0, 99)
|
||||
#define TAC_CLASSD_CFG0 TAC_REG_SDW(0, 0, 100)
|
||||
#define TAC_CLASSD_CFG1 TAC_REG_SDW(0, 0, 101)
|
||||
#define TAC_CLASSD_CFG3 TAC_REG_SDW(0, 0, 102)
|
||||
#define TAC_CLASSD_CFG4 TAC_REG_SDW(0, 0, 103)
|
||||
#define TAC_CLASSD_CFG5 TAC_REG_SDW(0, 0, 104)
|
||||
#define TAC_CLASSD_CFG6 TAC_REG_SDW(0, 0, 105)
|
||||
#define TAC_CLASSD_CFG8 TAC_REG_SDW(0, 0, 106)
|
||||
#define TAC_ISNS_CFG TAC_REG_SDW(0, 0, 107)
|
||||
#define TAC_DSP_CFG0 TAC_REG_SDW(0, 0, 108)
|
||||
#define TAC_DSP_CFG1 TAC_REG_SDW(0, 0, 109)
|
||||
#define TAC_DSP_CFG2 TAC_REG_SDW(0, 0, 110)
|
||||
#define TAC_DSP_CFG3 TAC_REG_SDW(0, 0, 111)
|
||||
#define TAC_JACK_DET_CFG1 TAC_REG_SDW(0, 0, 112)
|
||||
#define TAC_JACK_DET_CFG2 TAC_REG_SDW(0, 0, 113)
|
||||
#define TAC_JACK_DET_CFG3 TAC_REG_SDW(0, 0, 114)
|
||||
#define TAC_JACK_DET_CFG4 TAC_REG_SDW(0, 0, 115)
|
||||
#define TAC_JACK_DET_CFG7 TAC_REG_SDW(0, 0, 116)
|
||||
#define TAC_UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 117)
|
||||
#define TAC_UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 118)
|
||||
#define UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 119)
|
||||
#define UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 120)
|
||||
#define TAC_GP_ANA_STS TAC_REG_SDW(0, 0, 123)
|
||||
#define TAC_DEV_ID TAC_REG_SDW(0, 0, 124)
|
||||
#define TAC_REV_ID TAC_REG_SDW(0, 0, 125)
|
||||
#define TAC_I2C_CKSUM TAC_REG_SDW(0, 0, 126)
|
||||
#define TAC_BOOK TAC_REG_SDW(0, 0, 127)
|
||||
|
||||
#define TAC_INT_CFG TAC_REG_SDW(0, 2, 1)
|
||||
#define TAC_INT_CFG_CLR_REG BIT(3)
|
||||
|
||||
/* smartamp function */
|
||||
#define TAC_FUNCTION_ID_SA 0x1
|
||||
|
||||
#define TAC_SDCA_ENT_ENT0 0x0
|
||||
#define TAC_SDCA_ENT_PPU21 0x1
|
||||
#define TAC_SDCA_ENT_FU21 0x2
|
||||
#define TAC_SDCA_ENT_FU26 0x3
|
||||
#define TAC_SDCA_ENT_XU22 0x4
|
||||
#define TAC_SDCA_ENT_CS24 0x5
|
||||
#define TAC_SDCA_ENT_CS21 0x6
|
||||
#define TAC_SDCA_ENT_CS25 0x7
|
||||
#define TAC_SDCA_ENT_CS26 0x8
|
||||
#define TAC_SDCA_ENT_CS28 0x9
|
||||
#define TAC_SDCA_ENT_PPU26 0xa
|
||||
#define TAC_SDCA_ENT_FU23 0xb
|
||||
#define TAC_SDCA_ENT_PDE23 0xc
|
||||
#define TAC_SDCA_ENT_TG23 0x12
|
||||
#define TAC_SDCA_ENT_IT21 0x13
|
||||
#define TAC_SDCA_ENT_IT29 0x14
|
||||
#define TAC_SDCA_ENT_IT26 0x15
|
||||
#define TAC_SDCA_ENT_IT28 0x16
|
||||
#define TAC_SDCA_ENT_OT24 0x17
|
||||
#define TAC_SDCA_ENT_OT23 0x18
|
||||
#define TAC_SDCA_ENT_OT25 0x19
|
||||
#define TAC_SDCA_ENT_OT28 0x1a
|
||||
#define TAC_SDCA_ENT_OT27 0x1c
|
||||
#define TAC_SDCA_ENT_SPE199 0x21
|
||||
#define TAC_SDCA_ENT_OT20 0x24
|
||||
#define TAC_SDCA_ENT_FU27 0x26
|
||||
#define TAC_SDCA_ENT_FU20 0x27
|
||||
#define TAC_SDCA_ENT_PDE24 0x2e
|
||||
#define TAC_SDCA_ENT_PDE27 0x2f
|
||||
#define TAC_SDCA_ENT_PDE28 0x30
|
||||
#define TAC_SDCA_ENT_PDE20 0x31
|
||||
#define TAC_SDCA_ENT_SAPU29 0x35
|
||||
|
||||
/* Control selector definitions */
|
||||
#define TAC_SDCA_MASTER_GAIN 0x0B
|
||||
#define TAC_SDCA_MASTER_MUTE 0x01
|
||||
#define TAC_SDCA_CHANNEL_MUTE 0x01
|
||||
#define TAC_SDCA_CHANNEL_GAIN 0x02
|
||||
#define TAC_SDCA_POSTURENUMBER 0x10
|
||||
#define TAC_SDCA_REQUESTED_PS 0x01
|
||||
#define TAC_SDCA_ACTUAL_PS 0x10
|
||||
#define TAC_SDCA_CHANNEL_VOLUME 0x02
|
||||
|
||||
/* 2. smart mic function */
|
||||
#define TAC_FUNCTION_ID_SM 0x2
|
||||
|
||||
#define TAC_SDCA_ENT_IT11 0x1
|
||||
#define TAC_SDCA_ENT_OT113 0x2
|
||||
#define TAC_SDCA_ENT_CS11 0x3
|
||||
#define TAC_SDCA_ENT_CS18 0x4
|
||||
#define TAC_SDCA_ENT_FU113 0x5
|
||||
#define TAC_SDCA_ENT_FU13 0x6
|
||||
#define TAC_SDCA_ENT_FU11 0x8
|
||||
#define TAC_SDCA_ENT_XU12 0xa
|
||||
#define TAC_SDCA_ENT_CS113 0xc
|
||||
#define TAC_SDCA_ENT_CX11 0xf
|
||||
#define TAC_SDCA_ENT_PDE11 0x12
|
||||
#define TAC_SDCA_ENT_PPU11 0x9
|
||||
|
||||
/* controls */
|
||||
#define TAC_SDCA_CTL_USAGE 0x04
|
||||
#define TAC_SDCA_CTL_IT_CLUSTER 0x10
|
||||
#define TAC_SDCA_CTL_OT_DP_SEL 0x11
|
||||
#define TAC_SDCA_CTL_XU_BYPASS 0x01
|
||||
/* cx */
|
||||
#define TAC_SDCA_CTL_CX_CLK_SEL 0x01
|
||||
/* cs */
|
||||
#define TAC_SDCA_CTL_CS_CLKVLD 0x02
|
||||
#define TAC_SDCA_CTL_CS_SAMP_RATE_IDX 0x10
|
||||
/* cs113 end */
|
||||
/* ppu */
|
||||
#define TAC_SDCA_CTL_PPU_POSTURE_NUM 0x10
|
||||
|
||||
/* 3. UAJ function */
|
||||
#define TAC_FUNCTION_ID_UAJ 0x3
|
||||
#define TAC_SDCA_ENT_PDE47 0x35
|
||||
#define TAC_SDCA_ENT_PDE34 0x32
|
||||
#define TAC_SDCA_ENT_FU41 0x26 /* user */
|
||||
#define TAC_SDCA_ENT_IT41 0x07
|
||||
#define TAC_SDCA_ENT_XU42 0x2C
|
||||
#define TAC_SDCA_ENT_CS41 0x30
|
||||
#define TAC_SDCA_ENT_OT45 0x0E
|
||||
#define TAC_SDCA_ENT_IT33 0x03
|
||||
#define TAC_SDCA_ENT_OT36 0x0A
|
||||
#define TAC_SDCA_ENT_FU36 0x28
|
||||
#define TAC_SDCA_ENT_CS36 0x2E
|
||||
#define TAC_SDCA_ENT_GE35 0x3B /* 59 */
|
||||
|
||||
#define TAC_SDCA_CTL_SEL_MODE 0x1
|
||||
#define TAC_SDCA_CTL_DET_MODE 0x2
|
||||
|
||||
/* 4. HID function */
|
||||
#define TAC_FUNCTION_ID_HID 0x4
|
||||
#define TAC_SDCA_ENT_HID1 0x1
|
||||
/* HID Control Selectors */
|
||||
#define TAC_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10
|
||||
#define TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12
|
||||
#define TAC_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13
|
||||
#define TAC_SDCA_CTL_DETECTED_MODE 0x10
|
||||
#define TAC_SDCA_CTL_SELECTED_MODE 0x11
|
||||
|
||||
#define TAC_BUF_ADDR_HID1 0x44007F80
|
||||
|
||||
/* DAI interfaces */
|
||||
#define TAC5XX2_SPK 0
|
||||
#define TAC5XX2_DMIC 2
|
||||
#define TAC5XX2_UAJ 3
|
||||
|
||||
/* Port numbers for DAIs */
|
||||
#define TAC_SDW_PORT_NUM_SPK_PLAYBACK 1
|
||||
#define TAC_SDW_PORT_NUM_SPK_CAPTURE 2
|
||||
#define TAC_SDW_PORT_NUM_DMIC 3
|
||||
#define TAC_SDW_PORT_NUM_UAJ_PLAYBACK 4
|
||||
#define TAC_SDW_PORT_NUM_UAJ_CAPTURE 7
|
||||
#define TAC_SDW_PORT_NUM_IV_SENSE 8
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user