diff options
Diffstat (limited to 'include/sound')
66 files changed, 5071 insertions, 820 deletions
diff --git a/include/sound/acp62_chip_offset_byte.h b/include/sound/acp62_chip_offset_byte.h new file mode 100644 index 000000000000..f03992f81168 --- /dev/null +++ b/include/sound/acp62_chip_offset_byte.h @@ -0,0 +1,444 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * AMD ACP 6.2 Register Documentation + * + * Copyright 2022 Advanced Micro Devices, Inc. + */ + +#ifndef _acp_ip_OFFSET_HEADER +#define _acp_ip_OFFSET_HEADER + +/* Registers from ACP_DMA block */ +#define ACP_DMA_CNTL_0 0x0000000 +#define ACP_DMA_CNTL_1 0x0000004 +#define ACP_DMA_CNTL_2 0x0000008 +#define ACP_DMA_CNTL_3 0x000000C +#define ACP_DMA_CNTL_4 0x0000010 +#define ACP_DMA_CNTL_5 0x0000014 +#define ACP_DMA_CNTL_6 0x0000018 +#define ACP_DMA_CNTL_7 0x000001C +#define ACP_DMA_DSCR_STRT_IDX_0 0x0000020 +#define ACP_DMA_DSCR_STRT_IDX_1 0x0000024 +#define ACP_DMA_DSCR_STRT_IDX_2 0x0000028 +#define ACP_DMA_DSCR_STRT_IDX_3 0x000002C +#define ACP_DMA_DSCR_STRT_IDX_4 0x0000030 +#define ACP_DMA_DSCR_STRT_IDX_5 0x0000034 +#define ACP_DMA_DSCR_STRT_IDX_6 0x0000038 +#define ACP_DMA_DSCR_STRT_IDX_7 0x000003C +#define ACP_DMA_DSCR_CNT_0 0x0000040 +#define ACP_DMA_DSCR_CNT_1 0x0000044 +#define ACP_DMA_DSCR_CNT_2 0x0000048 +#define ACP_DMA_DSCR_CNT_3 0x000004C +#define ACP_DMA_DSCR_CNT_4 0x0000050 +#define ACP_DMA_DSCR_CNT_5 0x0000054 +#define ACP_DMA_DSCR_CNT_6 0x0000058 +#define ACP_DMA_DSCR_CNT_7 0x000005C +#define ACP_DMA_PRIO_0 0x0000060 +#define ACP_DMA_PRIO_1 0x0000064 +#define ACP_DMA_PRIO_2 0x0000068 +#define ACP_DMA_PRIO_3 0x000006C +#define ACP_DMA_PRIO_4 0x0000070 +#define ACP_DMA_PRIO_5 0x0000074 +#define ACP_DMA_PRIO_6 0x0000078 +#define ACP_DMA_PRIO_7 0x000007C +#define ACP_DMA_CUR_DSCR_0 0x0000080 +#define ACP_DMA_CUR_DSCR_1 0x0000084 +#define ACP_DMA_CUR_DSCR_2 0x0000088 +#define ACP_DMA_CUR_DSCR_3 0x000008C +#define ACP_DMA_CUR_DSCR_4 0x0000090 +#define ACP_DMA_CUR_DSCR_5 0x0000094 +#define ACP_DMA_CUR_DSCR_6 0x0000098 +#define ACP_DMA_CUR_DSCR_7 0x000009C +#define ACP_DMA_CUR_TRANS_CNT_0 0x00000A0 +#define ACP_DMA_CUR_TRANS_CNT_1 0x00000A4 +#define ACP_DMA_CUR_TRANS_CNT_2 0x00000A8 +#define ACP_DMA_CUR_TRANS_CNT_3 0x00000AC +#define ACP_DMA_CUR_TRANS_CNT_4 0x00000B0 +#define ACP_DMA_CUR_TRANS_CNT_5 0x00000B4 +#define ACP_DMA_CUR_TRANS_CNT_6 0x00000B8 +#define ACP_DMA_CUR_TRANS_CNT_7 0x00000BC +#define ACP_DMA_ERR_STS_0 0x00000C0 +#define ACP_DMA_ERR_STS_1 0x00000C4 +#define ACP_DMA_ERR_STS_2 0x00000C8 +#define ACP_DMA_ERR_STS_3 0x00000CC +#define ACP_DMA_ERR_STS_4 0x00000D0 +#define ACP_DMA_ERR_STS_5 0x00000D4 +#define ACP_DMA_ERR_STS_6 0x00000D8 +#define ACP_DMA_ERR_STS_7 0x00000DC +#define ACP_DMA_DESC_BASE_ADDR 0x00000E0 +#define ACP_DMA_DESC_MAX_NUM_DSCR 0x00000E4 +#define ACP_DMA_CH_STS 0x00000E8 +#define ACP_DMA_CH_GROUP 0x00000EC +#define ACP_DMA_CH_RST_STS 0x00000F0 + +/* Registers from ACP_AXI2AXIATU block */ +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x0000C00 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x0000C04 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x0000C08 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x0000C0C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x0000C10 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x0000C14 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x0000C18 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x0000C1C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x0000C20 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x0000C24 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x0000C28 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x0000C2C +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x0000C30 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x0000C34 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x0000C38 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x0000C3C +#define ACPAXI2AXI_ATU_CTRL 0x0000C40 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_9 0x0000C44 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_9 0x0000C48 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_10 0x0000C4C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_10 0x0000C50 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_11 0x0000C54 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_11 0x0000C58 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_12 0x0000C5C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_12 0x0000C60 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_13 0x0000C64 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_13 0x0000C68 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_14 0x0000C6C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_14 0x0000C70 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_15 0x0000C74 +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_15 0x0000C78 +#define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_16 0x0000C7C +#define ACPAXI2AXI_ATU_BASE_ADDR_GRP_16 0x0000C80 + +/* Registers from ACP_CLKRST block */ +#define ACP_SOFT_RESET 0x0001000 +#define ACP_CONTROL 0x0001004 +#define ACP_STATUS 0x0001008 +#define ACP_DYNAMIC_CG_MASTER_CONTROL 0x0001010 +#define ACP_ZSC_DSP_CTRL 0x0001014 +#define ACP_ZSC_STS 0x0001018 +#define ACP_PGFSM_CONTROL 0x0001024 +#define ACP_PGFSM_STATUS 0x0001028 +#define ACP_CLKMUX_SEL 0x000102C + +/* Registers from ACP_AON block */ +#define ACP_PME_EN 0x0001400 +#define ACP_DEVICE_STATE 0x0001404 +#define AZ_DEVICE_STATE 0x0001408 +#define ACP_PIN_CONFIG 0x0001440 +#define ACP_PAD_PULLUP_CTRL 0x0001444 +#define ACP_PAD_PULLDOWN_CTRL 0x0001448 +#define ACP_PAD_DRIVE_STRENGTH_CTRL 0x000144C +#define ACP_PAD_SCHMEN_CTRL 0x0001450 +#define ACP_SW_PAD_KEEPER_EN 0x0001454 +#define ACP_SW_WAKE_EN 0x0001458 +#define ACP_I2S_WAKE_EN 0x000145C +#define ACP_SW1_WAKE_EN 0x0001460 + +/* Registers from ACP_P1_MISC block */ +#define ACP_EXTERNAL_INTR_ENB 0x0001A00 +#define ACP_EXTERNAL_INTR_CNTL 0x0001A04 +#define ACP_EXTERNAL_INTR_CNTL1 0x0001A08 +#define ACP_EXTERNAL_INTR_STAT 0x0001A0C +#define ACP_EXTERNAL_INTR_STAT1 0x0001A10 +#define ACP_ERROR_STATUS 0x0001A4C +#define ACP_P1_SW_I2S_ERROR_REASON 0x0001A50 +#define ACP_P1_SW_POS_TRACK_I2S_TX_CTRL 0x0001A6C +#define ACP_P1_SW_I2S_TX_DMA_POS 0x0001A70 +#define ACP_P1_SW_POS_TRACK_I2S_RX_CTRL 0x0001A74 +#define ACP_P1_SW_I2S_RX_DMA_POS 0x0001A78 +#define ACP_P1_DMIC_I2S_GPIO_INTR_CTRL 0x0001A7C +#define ACP_P1_DMIC_I2S_GPIO_INTR_STATUS 0x0001A80 +#define ACP_SCRATCH_REG_BASE_ADDR 0x0001A84 +#define ACP_P1_SW_POS_TRACK_BT_TX_CTRL 0x0001A88 +#define ACP_P1_SW_BT_TX_DMA_POS 0x0001A8C +#define ACP_P1_SW_POS_TRACK_HS_TX_CTRL 0x0001A90 +#define ACP_P1_SW_HS_TX_DMA_POS 0x0001A94 +#define ACP_P1_SW_POS_TRACK_BT_RX_CTRL 0x0001A98 +#define ACP_P1_SW_BT_RX_DMA_POS 0x0001A9C +#define ACP_P1_SW_POS_TRACK_HS_RX_CTRL 0x0001AA0 +#define ACP_P1_SW_HS_RX_DMA_POS 0x0001AA4 + +/* Registers from ACP_AUDIO_BUFFERS block */ +#define ACP_I2S_RX_RINGBUFADDR 0x0002000 +#define ACP_I2S_RX_RINGBUFSIZE 0x0002004 +#define ACP_I2S_RX_LINKPOSITIONCNTR 0x0002008 +#define ACP_I2S_RX_FIFOADDR 0x000200C +#define ACP_I2S_RX_FIFOSIZE 0x0002010 +#define ACP_I2S_RX_DMA_SIZE 0x0002014 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0002018 +#define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x000201C +#define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x0002020 +#define ACP_I2S_TX_RINGBUFADDR 0x0002024 +#define ACP_I2S_TX_RINGBUFSIZE 0x0002028 +#define ACP_I2S_TX_LINKPOSITIONCNTR 0x000202C +#define ACP_I2S_TX_FIFOADDR 0x0002030 +#define ACP_I2S_TX_FIFOSIZE 0x0002034 +#define ACP_I2S_TX_DMA_SIZE 0x0002038 +#define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x000203C +#define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0002040 +#define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x0002044 +#define ACP_BT_RX_RINGBUFADDR 0x0002048 +#define ACP_BT_RX_RINGBUFSIZE 0x000204C +#define ACP_BT_RX_LINKPOSITIONCNTR 0x0002050 +#define ACP_BT_RX_FIFOADDR 0x0002054 +#define ACP_BT_RX_FIFOSIZE 0x0002058 +#define ACP_BT_RX_DMA_SIZE 0x000205C +#define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0002060 +#define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x0002064 +#define ACP_BT_RX_INTR_WATERMARK_SIZE 0x0002068 +#define ACP_BT_TX_RINGBUFADDR 0x000206C +#define ACP_BT_TX_RINGBUFSIZE 0x0002070 +#define ACP_BT_TX_LINKPOSITIONCNTR 0x0002074 +#define ACP_BT_TX_FIFOADDR 0x0002078 +#define ACP_BT_TX_FIFOSIZE 0x000207C +#define ACP_BT_TX_DMA_SIZE 0x0002080 +#define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0002084 +#define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x0002088 +#define ACP_BT_TX_INTR_WATERMARK_SIZE 0x000208C +#define ACP_HS_RX_RINGBUFADDR 0x0002090 +#define ACP_HS_RX_RINGBUFSIZE 0x0002094 +#define ACP_HS_RX_LINKPOSITIONCNTR 0x0002098 +#define ACP_HS_RX_FIFOADDR 0x000209C +#define ACP_HS_RX_FIFOSIZE 0x00020A0 +#define ACP_HS_RX_DMA_SIZE 0x00020A4 +#define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x00020A8 +#define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x00020AC +#define ACP_HS_RX_INTR_WATERMARK_SIZE 0x00020B0 +#define ACP_HS_TX_RINGBUFADDR 0x00020B4 +#define ACP_HS_TX_RINGBUFSIZE 0x00020B8 +#define ACP_HS_TX_LINKPOSITIONCNTR 0x00020BC +#define ACP_HS_TX_FIFOADDR 0x00020C0 +#define ACP_HS_TX_FIFOSIZE 0x00020C4 +#define ACP_HS_TX_DMA_SIZE 0x00020C8 +#define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x00020CC +#define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x00020D0 +#define ACP_HS_TX_INTR_WATERMARK_SIZE 0x00020D4 + +/* Registers from ACP_I2S_TDM block */ +#define ACP_I2STDM_IER 0x0002400 +#define ACP_I2STDM_IRER 0x0002404 +#define ACP_I2STDM_RXFRMT 0x0002408 +#define ACP_I2STDM_ITER 0x000240C +#define ACP_I2STDM_TXFRMT 0x0002410 +#define ACP_I2STDM0_MSTRCLKGEN 0x0002414 +#define ACP_I2STDM1_MSTRCLKGEN 0x0002418 +#define ACP_I2STDM2_MSTRCLKGEN 0x000241C +#define ACP_I2STDM_REFCLKGEN 0x0002420 + +/* Registers from ACP_BT_TDM block */ +#define ACP_BTTDM_IER 0x0002800 +#define ACP_BTTDM_IRER 0x0002804 +#define ACP_BTTDM_RXFRMT 0x0002808 +#define ACP_BTTDM_ITER 0x000280C +#define ACP_BTTDM_TXFRMT 0x0002810 +#define ACP_HSTDM_IER 0x0002814 +#define ACP_HSTDM_IRER 0x0002818 +#define ACP_HSTDM_RXFRMT 0x000281C +#define ACP_HSTDM_ITER 0x0002820 +#define ACP_HSTDM_TXFRMT 0x0002824 + +/* Registers from ACP_WOV block */ +#define ACP_WOV_PDM_ENABLE 0x0002C04 +#define ACP_WOV_PDM_DMA_ENABLE 0x0002C08 +#define ACP_WOV_RX_RINGBUFADDR 0x0002C0C +#define ACP_WOV_RX_RINGBUFSIZE 0x0002C10 +#define ACP_WOV_RX_LINKPOSITIONCNTR 0x0002C14 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x0002C18 +#define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x0002C1C +#define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x0002C20 +#define ACP_WOV_PDM_FIFO_FLUSH 0x0002C24 +#define ACP_WOV_PDM_NO_OF_CHANNELS 0x0002C28 +#define ACP_WOV_PDM_DECIMATION_FACTOR 0x0002C2C +#define ACP_WOV_PDM_VAD_CTRL 0x0002C30 +#define ACP_WOV_WAKE 0x0002C54 +#define ACP_WOV_BUFFER_STATUS 0x0002C58 +#define ACP_WOV_MISC_CTRL 0x0002C5C +#define ACP_WOV_CLK_CTRL 0x0002C60 +#define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x0002C64 +#define ACP_WOV_ERROR_STATUS_REGISTER 0x0002C68 +#define ACP_PDM_CLKDIV 0x0002C6C + +/* Registers from ACP_P1_AUDIO_BUFFERS block */ +#define ACP_P1_I2S_RX_RINGBUFADDR 0x0003A00 +#define ACP_P1_I2S_RX_RINGBUFSIZE 0x0003A04 +#define ACP_P1_I2S_RX_LINKPOSITIONCNTR 0x0003A08 +#define ACP_P1_I2S_RX_FIFOADDR 0x0003A0C +#define ACP_P1_I2S_RX_FIFOSIZE 0x0003A10 +#define ACP_P1_I2S_RX_DMA_SIZE 0x0003A14 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0003A18 +#define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x0003A1C +#define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x0003A20 +#define ACP_P1_I2S_TX_RINGBUFADDR 0x0003A24 +#define ACP_P1_I2S_TX_RINGBUFSIZE 0x0003A28 +#define ACP_P1_I2S_TX_LINKPOSITIONCNTR 0x0003A2C +#define ACP_P1_I2S_TX_FIFOADDR 0x0003A30 +#define ACP_P1_I2S_TX_FIFOSIZE 0x0003A34 +#define ACP_P1_I2S_TX_DMA_SIZE 0x0003A38 +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x0003A3C +#define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0003A40 +#define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x0003A44 +#define ACP_P1_BT_RX_RINGBUFADDR 0x0003A48 +#define ACP_P1_BT_RX_RINGBUFSIZE 0x0003A4C +#define ACP_P1_BT_RX_LINKPOSITIONCNTR 0x0003A50 +#define ACP_P1_BT_RX_FIFOADDR 0x0003A54 +#define ACP_P1_BT_RX_FIFOSIZE 0x0003A58 +#define ACP_P1_BT_RX_DMA_SIZE 0x0003A5C +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0003A60 +#define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x0003A64 +#define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x0003A68 +#define ACP_P1_BT_TX_RINGBUFADDR 0x0003A6C +#define ACP_P1_BT_TX_RINGBUFSIZE 0x0003A70 +#define ACP_P1_BT_TX_LINKPOSITIONCNTR 0x0003A74 +#define ACP_P1_BT_TX_FIFOADDR 0x0003A78 +#define ACP_P1_BT_TX_FIFOSIZE 0x0003A7C +#define ACP_P1_BT_TX_DMA_SIZE 0x0003A80 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0003A84 +#define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x0003A88 +#define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x0003A8C +#define ACP_P1_HS_RX_RINGBUFADDR 0x0003A90 +#define ACP_P1_HS_RX_RINGBUFSIZE 0x0003A94 +#define ACP_P1_HS_RX_LINKPOSITIONCNTR 0x0003A98 +#define ACP_P1_HS_RX_FIFOADDR 0x0003A9C +#define ACP_P1_HS_RX_FIFOSIZE 0x0003AA0 +#define ACP_P1_HS_RX_DMA_SIZE 0x0003AA4 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x0003AA8 +#define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x0003AAC +#define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x0003AB0 +#define ACP_P1_HS_TX_RINGBUFADDR 0x0003AB4 +#define ACP_P1_HS_TX_RINGBUFSIZE 0x0003AB8 +#define ACP_P1_HS_TX_LINKPOSITIONCNTR 0x0003ABC +#define ACP_P1_HS_TX_FIFOADDR 0x0003AC0 +#define ACP_P1_HS_TX_FIFOSIZE 0x0003AC4 +#define ACP_P1_HS_TX_DMA_SIZE 0x0003AC8 +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x0003ACC +#define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x0003AD0 +#define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x0003AD4 + +/* Registers from ACP_SCRATCH block */ +#define ACP_SCRATCH_REG_0 0x0010000 +#define ACP_SCRATCH_REG_1 0x0010004 +#define ACP_SCRATCH_REG_2 0x0010008 +#define ACP_SCRATCH_REG_3 0x001000C +#define ACP_SCRATCH_REG_4 0x0010010 +#define ACP_SCRATCH_REG_5 0x0010014 +#define ACP_SCRATCH_REG_6 0x0010018 +#define ACP_SCRATCH_REG_7 0x001001C +#define ACP_SCRATCH_REG_8 0x0010020 +#define ACP_SCRATCH_REG_9 0x0010024 +#define ACP_SCRATCH_REG_10 0x0010028 +#define ACP_SCRATCH_REG_11 0x001002C +#define ACP_SCRATCH_REG_12 0x0010030 +#define ACP_SCRATCH_REG_13 0x0010034 +#define ACP_SCRATCH_REG_14 0x0010038 +#define ACP_SCRATCH_REG_15 0x001003C +#define ACP_SCRATCH_REG_16 0x0010040 +#define ACP_SCRATCH_REG_17 0x0010044 +#define ACP_SCRATCH_REG_18 0x0010048 +#define ACP_SCRATCH_REG_19 0x001004C +#define ACP_SCRATCH_REG_20 0x0010050 +#define ACP_SCRATCH_REG_21 0x0010054 +#define ACP_SCRATCH_REG_22 0x0010058 +#define ACP_SCRATCH_REG_23 0x001005C +#define ACP_SCRATCH_REG_24 0x0010060 +#define ACP_SCRATCH_REG_25 0x0010064 +#define ACP_SCRATCH_REG_26 0x0010068 +#define ACP_SCRATCH_REG_27 0x001006C +#define ACP_SCRATCH_REG_28 0x0010070 +#define ACP_SCRATCH_REG_29 0x0010074 +#define ACP_SCRATCH_REG_30 0x0010078 +#define ACP_SCRATCH_REG_31 0x001007C +#define ACP_SCRATCH_REG_32 0x0010080 +#define ACP_SCRATCH_REG_33 0x0010084 +#define ACP_SCRATCH_REG_34 0x0010088 +#define ACP_SCRATCH_REG_35 0x001008C +#define ACP_SCRATCH_REG_36 0x0010090 +#define ACP_SCRATCH_REG_37 0x0010094 +#define ACP_SCRATCH_REG_38 0x0010098 +#define ACP_SCRATCH_REG_39 0x001009C +#define ACP_SCRATCH_REG_40 0x00100A0 +#define ACP_SCRATCH_REG_41 0x00100A4 +#define ACP_SCRATCH_REG_42 0x00100A8 +#define ACP_SCRATCH_REG_43 0x00100AC +#define ACP_SCRATCH_REG_44 0x00100B0 +#define ACP_SCRATCH_REG_45 0x00100B4 +#define ACP_SCRATCH_REG_46 0x00100B8 +#define ACP_SCRATCH_REG_47 0x00100BC +#define ACP_SCRATCH_REG_48 0x00100C0 +#define ACP_SCRATCH_REG_49 0x00100C4 +#define ACP_SCRATCH_REG_50 0x00100C8 +#define ACP_SCRATCH_REG_51 0x00100CC +#define ACP_SCRATCH_REG_52 0x00100D0 +#define ACP_SCRATCH_REG_53 0x00100D4 +#define ACP_SCRATCH_REG_54 0x00100D8 +#define ACP_SCRATCH_REG_55 0x00100DC +#define ACP_SCRATCH_REG_56 0x00100E0 +#define ACP_SCRATCH_REG_57 0x00100E4 +#define ACP_SCRATCH_REG_58 0x00100E8 +#define ACP_SCRATCH_REG_59 0x00100EC +#define ACP_SCRATCH_REG_60 0x00100F0 +#define ACP_SCRATCH_REG_61 0x00100F4 +#define ACP_SCRATCH_REG_62 0x00100F8 +#define ACP_SCRATCH_REG_63 0x00100FC +#define ACP_SCRATCH_REG_64 0x0010100 +#define ACP_SCRATCH_REG_65 0x0010104 +#define ACP_SCRATCH_REG_66 0x0010108 +#define ACP_SCRATCH_REG_67 0x001010C +#define ACP_SCRATCH_REG_68 0x0010110 +#define ACP_SCRATCH_REG_69 0x0010114 +#define ACP_SCRATCH_REG_70 0x0010118 +#define ACP_SCRATCH_REG_71 0x001011C +#define ACP_SCRATCH_REG_72 0x0010120 +#define ACP_SCRATCH_REG_73 0x0010124 +#define ACP_SCRATCH_REG_74 0x0010128 +#define ACP_SCRATCH_REG_75 0x001012C +#define ACP_SCRATCH_REG_76 0x0010130 +#define ACP_SCRATCH_REG_77 0x0010134 +#define ACP_SCRATCH_REG_78 0x0010138 +#define ACP_SCRATCH_REG_79 0x001013C +#define ACP_SCRATCH_REG_80 0x0010140 +#define ACP_SCRATCH_REG_81 0x0010144 +#define ACP_SCRATCH_REG_82 0x0010148 +#define ACP_SCRATCH_REG_83 0x001014C +#define ACP_SCRATCH_REG_84 0x0010150 +#define ACP_SCRATCH_REG_85 0x0010154 +#define ACP_SCRATCH_REG_86 0x0010158 +#define ACP_SCRATCH_REG_87 0x001015C +#define ACP_SCRATCH_REG_88 0x0010160 +#define ACP_SCRATCH_REG_89 0x0010164 +#define ACP_SCRATCH_REG_90 0x0010168 +#define ACP_SCRATCH_REG_91 0x001016C +#define ACP_SCRATCH_REG_92 0x0010170 +#define ACP_SCRATCH_REG_93 0x0010174 +#define ACP_SCRATCH_REG_94 0x0010178 +#define ACP_SCRATCH_REG_95 0x001017C +#define ACP_SCRATCH_REG_96 0x0010180 +#define ACP_SCRATCH_REG_97 0x0010184 +#define ACP_SCRATCH_REG_98 0x0010188 +#define ACP_SCRATCH_REG_99 0x001018C +#define ACP_SCRATCH_REG_100 0x0010190 +#define ACP_SCRATCH_REG_101 0x0010194 +#define ACP_SCRATCH_REG_102 0x0010198 +#define ACP_SCRATCH_REG_103 0x001019C +#define ACP_SCRATCH_REG_104 0x00101A0 +#define ACP_SCRATCH_REG_105 0x00101A4 +#define ACP_SCRATCH_REG_106 0x00101A8 +#define ACP_SCRATCH_REG_107 0x00101AC +#define ACP_SCRATCH_REG_108 0x00101B0 +#define ACP_SCRATCH_REG_109 0x00101B4 +#define ACP_SCRATCH_REG_110 0x00101B8 +#define ACP_SCRATCH_REG_111 0x00101BC +#define ACP_SCRATCH_REG_112 0x00101C0 +#define ACP_SCRATCH_REG_113 0x00101C4 +#define ACP_SCRATCH_REG_114 0x00101C8 +#define ACP_SCRATCH_REG_115 0x00101CC +#define ACP_SCRATCH_REG_116 0x00101D0 +#define ACP_SCRATCH_REG_117 0x00101D4 +#define ACP_SCRATCH_REG_118 0x00101D8 +#define ACP_SCRATCH_REG_119 0x00101DC +#define ACP_SCRATCH_REG_120 0x00101E0 +#define ACP_SCRATCH_REG_121 0x00101E4 +#define ACP_SCRATCH_REG_122 0x00101E8 +#define ACP_SCRATCH_REG_123 0x00101EC +#define ACP_SCRATCH_REG_124 0x00101F0 +#define ACP_SCRATCH_REG_125 0x00101F4 +#define ACP_SCRATCH_REG_126 0x00101F8 +#define ACP_SCRATCH_REG_127 0x00101FC +#define ACP_SCRATCH_REG_128 0x0010200 +#endif diff --git a/include/sound/compress_driver.h b/include/sound/compress_driver.h index bc88d6f964da..d91289c6f00e 100644 --- a/include/sound/compress_driver.h +++ b/include/sound/compress_driver.h @@ -23,7 +23,6 @@ struct snd_compr_ops; * struct snd_compr_runtime: runtime stream description * @state: stream state * @ops: pointer to DSP callbacks - * @dma_buffer_p: runtime dma buffer pointer * @buffer: pointer to kernel buffer, valid only when not in mmap mode or * DSP doesn't implement copy * @buffer_size: size of the above buffer @@ -34,11 +33,14 @@ struct snd_compr_ops; * @total_bytes_transferred: cumulative bytes transferred by offload DSP * @sleep: poll sleep * @private_data: driver private data pointer + * @dma_area: virtual buffer address + * @dma_addr: physical buffer address (not accessible from main CPU) + * @dma_bytes: size of DMA area + * @dma_buffer_p: runtime dma buffer pointer */ struct snd_compr_runtime { snd_pcm_state_t state; struct snd_compr_ops *ops; - struct snd_dma_buffer *dma_buffer_p; void *buffer; u64 buffer_size; u32 fragment_size; @@ -47,6 +49,11 @@ struct snd_compr_runtime { u64 total_bytes_transferred; wait_queue_head_t sleep; void *private_data; + + unsigned char *dma_area; + dma_addr_t dma_addr; + size_t dma_bytes; + struct snd_dma_buffer *dma_buffer_p; }; /** @@ -59,7 +66,10 @@ struct snd_compr_runtime { * @direction: stream direction, playback/recording * @metadata_set: metadata set flag, true when set * @next_track: has userspace signal next track transition, true when set + * @partial_drain: undergoing partial_drain for stream, true when set + * @pause_in_draining: paused during draining state, true when set * @private_data: pointer to DSP private data + * @dma_buffer: allocated buffer if any */ struct snd_compr_stream { const char *name; @@ -70,7 +80,10 @@ struct snd_compr_stream { enum snd_compr_direction direction; bool metadata_set; bool next_track; + bool partial_drain; + bool pause_in_draining; void *private_data; + struct snd_dma_buffer dma_buffer; }; /** @@ -131,6 +144,7 @@ struct snd_compr_ops { * @direction: Playback or capture direction * @lock: device lock * @device: device id + * @use_pause_in_draining: allow pause in draining, true when set */ struct snd_compr { const char *name; @@ -141,6 +155,7 @@ struct snd_compr { unsigned int direction; struct mutex lock; int device; + bool use_pause_in_draining; #ifdef CONFIG_SND_VERBOSE_PROCFS /* private: */ char id[64]; @@ -150,11 +165,21 @@ struct snd_compr { }; /* compress device register APIs */ -int snd_compress_register(struct snd_compr *device); -int snd_compress_deregister(struct snd_compr *device); int snd_compress_new(struct snd_card *card, int device, int type, const char *id, struct snd_compr *compr); +/** + * snd_compr_use_pause_in_draining - Allow pause and resume in draining state + * @substream: compress substream to set + * + * Allow pause and resume in draining state. + * Only HW driver supports this transition can call this API. + */ +static inline void snd_compr_use_pause_in_draining(struct snd_compr_stream *substream) +{ + substream->device->use_pause_in_draining = true; +} + /* dsp driver callback apis * For playback: driver should call snd_compress_fragment_elapsed() to let the * framework know that a fragment has been consumed from the ring buffer @@ -173,28 +198,47 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream) if (snd_BUG_ON(!stream)) return; - stream->runtime->state = SNDRV_PCM_STATE_SETUP; + /* for partial_drain case we are back to running state on success */ + if (stream->partial_drain) { + stream->runtime->state = SNDRV_PCM_STATE_RUNNING; + stream->partial_drain = false; /* clear this flag as well */ + } else { + stream->runtime->state = SNDRV_PCM_STATE_SETUP; + } wake_up(&stream->runtime->sleep); } /** * snd_compr_set_runtime_buffer - Set the Compress runtime buffer - * @substream: compress substream to set + * @stream: compress stream to set * @bufp: the buffer information, NULL to clear * * Copy the buffer information to runtime buffer when @bufp is non-NULL. * Otherwise it clears the current buffer information. */ -static inline void snd_compr_set_runtime_buffer( - struct snd_compr_stream *substream, - struct snd_dma_buffer *bufp) +static inline void +snd_compr_set_runtime_buffer(struct snd_compr_stream *stream, + struct snd_dma_buffer *bufp) { - struct snd_compr_runtime *runtime = substream->runtime; - - runtime->dma_buffer_p = bufp; + struct snd_compr_runtime *runtime = stream->runtime; + + if (bufp) { + runtime->dma_buffer_p = bufp; + runtime->dma_area = bufp->area; + runtime->dma_addr = bufp->addr; + runtime->dma_bytes = bufp->bytes; + } else { + runtime->dma_buffer_p = NULL; + runtime->dma_area = NULL; + runtime->dma_addr = 0; + runtime->dma_bytes = 0; + } } +int snd_compr_malloc_pages(struct snd_compr_stream *stream, size_t size); +int snd_compr_free_pages(struct snd_compr_stream *stream); + int snd_compr_stop_error(struct snd_compr_stream *stream, snd_pcm_state_t state); diff --git a/include/sound/control.h b/include/sound/control.h index 11feeee31e35..cc3dcc6cfb0f 100644 --- a/include/sound/control.h +++ b/include/sound/control.h @@ -23,8 +23,8 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, unsigned int __user *tlv); /* internal flag for skipping validations */ -#ifdef CONFIG_SND_CTL_VALIDATION -#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 27) +#ifdef CONFIG_SND_CTL_DEBUG +#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK (1 << 24) #define snd_ctl_skip_validation(info) \ ((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK) #else @@ -32,6 +32,12 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol, #define snd_ctl_skip_validation(info) true #endif +/* kernel only - LED bits */ +#define SNDRV_CTL_ELEM_ACCESS_LED_SHIFT 25 +#define SNDRV_CTL_ELEM_ACCESS_LED_MASK (7<<25) /* kernel three bits - LED group */ +#define SNDRV_CTL_ELEM_ACCESS_SPK_LED (1<<25) /* kernel speaker (output) LED flag */ +#define SNDRV_CTL_ELEM_ACCESS_MIC_LED (2<<25) /* kernel microphone (input) LED flag */ + enum { SNDRV_CTL_TLV_OP_READ = 0, SNDRV_CTL_TLV_OP_WRITE = 1, @@ -42,7 +48,7 @@ struct snd_kcontrol_new { snd_ctl_elem_iface_t iface; /* interface identifier */ unsigned int device; /* device/client number */ unsigned int subdevice; /* subdevice (substream) number */ - const unsigned char *name; /* ASCII name of item */ + const char *name; /* ASCII name of item */ unsigned int index; /* index of item */ unsigned int access; /* access rights */ unsigned int count; /* count of same elements */ @@ -75,7 +81,7 @@ struct snd_kcontrol { unsigned long private_value; void *private_data; void (*private_free)(struct snd_kcontrol *kcontrol); - struct snd_kcontrol_volatile vd[0]; /* volatile data */ + struct snd_kcontrol_volatile vd[]; /* volatile data */ }; #define snd_kcontrol(n) list_entry(n, struct snd_kcontrol, list) @@ -103,11 +109,19 @@ struct snd_ctl_file { int preferred_subdevice[SND_CTL_SUBDEV_ITEMS]; wait_queue_head_t change_sleep; spinlock_t read_lock; - struct fasync_struct *fasync; + struct snd_fasync *fasync; int subscribed; /* read interface is activated */ struct list_head events; /* waiting events for read */ }; +struct snd_ctl_layer_ops { + struct snd_ctl_layer_ops *next; + const char *module_name; + void (*lregister)(struct snd_card *card); + void (*ldisconnect)(struct snd_card *card); + void (*lnotify)(struct snd_card *card, unsigned int mask, struct snd_kcontrol *kctl, unsigned int ioff); +}; + #define snd_ctl_file(n) list_entry(n, struct snd_ctl_file, list) typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card, @@ -115,6 +129,7 @@ typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card, unsigned int cmd, unsigned long arg); void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id); +void snd_ctl_notify_one(struct snd_card * card, unsigned int mask, struct snd_kcontrol * kctl, unsigned int ioff); struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data); void snd_ctl_free_one(struct snd_kcontrol * kcontrol); @@ -123,8 +138,8 @@ int snd_ctl_remove(struct snd_card * card, struct snd_kcontrol * kcontrol); int snd_ctl_replace(struct snd_card *card, struct snd_kcontrol *kcontrol, bool add_on_replace); int snd_ctl_remove_id(struct snd_card * card, struct snd_ctl_elem_id *id); int snd_ctl_rename_id(struct snd_card * card, struct snd_ctl_elem_id *src_id, struct snd_ctl_elem_id *dst_id); -int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, - int active); +void snd_ctl_rename(struct snd_card *card, struct snd_kcontrol *kctl, const char *name); +int snd_ctl_activate_id(struct snd_card *card, struct snd_ctl_elem_id *id, int active); struct snd_kcontrol *snd_ctl_find_numid(struct snd_card * card, unsigned int numid); struct snd_kcontrol *snd_ctl_find_id(struct snd_card * card, struct snd_ctl_elem_id *id); @@ -140,6 +155,10 @@ int snd_ctl_unregister_ioctl_compat(snd_kctl_ioctl_func_t fcn); #define snd_ctl_unregister_ioctl_compat(fcn) #endif +int snd_ctl_request_layer(const char *module_name); +void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops); +void snd_ctl_disconnect_layer(struct snd_ctl_layer_ops *lops); + int snd_ctl_get_preferred_subdevice(struct snd_card *card, int type); static inline unsigned int snd_ctl_get_ioffnum(struct snd_kcontrol *kctl, struct snd_ctl_elem_id *id) @@ -188,20 +207,21 @@ int snd_ctl_enum_info(struct snd_ctl_elem_info *info, unsigned int channels, */ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name, const unsigned int *tlv); -int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, - unsigned int flags); -/* optional flags for slave */ -#define SND_CTL_SLAVE_NEED_UPDATE (1 << 0) +int _snd_ctl_add_follower(struct snd_kcontrol *master, + struct snd_kcontrol *follower, + unsigned int flags); +/* optional flags for follower */ +#define SND_CTL_FOLLOWER_NEED_UPDATE (1 << 0) /** - * snd_ctl_add_slave - Add a virtual slave control + * snd_ctl_add_follower - Add a virtual follower control * @master: vmaster element - * @slave: slave element to add + * @follower: follower element to add * - * Add a virtual slave control to the given master element created via + * Add a virtual follower control to the given master element created via * snd_ctl_create_virtual_master() beforehand. * - * All slaves must be the same type (returning the same information + * All followers must be the same type (returning the same information * via info callback). The function doesn't check it, so it's your * responsibility. * @@ -213,18 +233,18 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave, * Return: Zero if successful or a negative error code. */ static inline int -snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) +snd_ctl_add_follower(struct snd_kcontrol *master, struct snd_kcontrol *follower) { - return _snd_ctl_add_slave(master, slave, 0); + return _snd_ctl_add_follower(master, follower, 0); } /** - * snd_ctl_add_slave_uncached - Add a virtual slave control + * snd_ctl_add_follower_uncached - Add a virtual follower control * @master: vmaster element - * @slave: slave element to add + * @follower: follower element to add * - * Add a virtual slave control to the given master. - * Unlike snd_ctl_add_slave(), the element added via this function + * Add a virtual follower control to the given master. + * Unlike snd_ctl_add_follower(), the element added via this function * is supposed to have volatile values, and get callback is called * at each time queried from the master. * @@ -235,10 +255,10 @@ snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave) * Return: Zero if successful or a negative error code. */ static inline int -snd_ctl_add_slave_uncached(struct snd_kcontrol *master, - struct snd_kcontrol *slave) +snd_ctl_add_follower_uncached(struct snd_kcontrol *master, + struct snd_kcontrol *follower) { - return _snd_ctl_add_slave(master, slave, SND_CTL_SLAVE_NEED_UPDATE); + return _snd_ctl_add_follower(master, follower, SND_CTL_FOLLOWER_NEED_UPDATE); } int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, @@ -246,11 +266,22 @@ int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kctl, void *private_data); void snd_ctl_sync_vmaster(struct snd_kcontrol *kctl, bool hook_only); #define snd_ctl_sync_vmaster_hook(kctl) snd_ctl_sync_vmaster(kctl, true) -int snd_ctl_apply_vmaster_slaves(struct snd_kcontrol *kctl, - int (*func)(struct snd_kcontrol *vslave, - struct snd_kcontrol *slave, - void *arg), - void *arg); +int snd_ctl_apply_vmaster_followers(struct snd_kcontrol *kctl, + int (*func)(struct snd_kcontrol *vfollower, + struct snd_kcontrol *follower, + void *arg), + void *arg); + +/* + * Control LED trigger layer + */ +#define SND_CTL_LAYER_MODULE_LED "snd-ctl-led" + +#if IS_MODULE(CONFIG_SND_CTL_LED) +static inline int snd_ctl_led_request(void) { return snd_ctl_request_layer(SND_CTL_LAYER_MODULE_LED); } +#else +static inline int snd_ctl_led_request(void) { return 0; } +#endif /* * Helper functions for jack-detection controls diff --git a/include/sound/core.h b/include/sound/core.h index ac8b692b69b4..4365c35d038b 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -14,6 +14,7 @@ #include <linux/pm.h> /* pm_message_t */ #include <linux/stringify.h> #include <linux/printk.h> +#include <linux/xarray.h> /* number of supported soundcards */ #ifdef CONFIG_SND_DYNAMIC_MINORS @@ -100,9 +101,14 @@ struct snd_card { struct rw_semaphore controls_rwsem; /* controls list lock */ rwlock_t ctl_files_rwlock; /* ctl_files list lock */ int controls_count; /* count of all controls */ - int user_ctl_count; /* count of all user controls */ + size_t user_ctl_alloc_size; // current memory allocation by user controls. struct list_head controls; /* all controls for this card */ struct list_head ctl_files; /* active control files */ +#ifdef CONFIG_SND_CTL_FAST_LOOKUP + struct xarray ctl_numids; /* hash table for numids */ + struct xarray ctl_hash; /* hash table for ctl id matching */ + bool ctl_hash_collision; /* ctl_hash collision seen? */ +#endif struct snd_info_entry *proc_root; /* root for soundcard specific files */ struct proc_dir_entry *proc_root_link; /* number link to real id */ @@ -117,15 +123,22 @@ struct snd_card { struct device card_dev; /* cardX object for sysfs */ const struct attribute_group *dev_groups[4]; /* assigned sysfs attr */ bool registered; /* card_dev is registered? */ + bool managed; /* managed via devres */ + bool releasing; /* during card free process */ int sync_irq; /* assigned irq, used for PCM sync */ wait_queue_head_t remove_sleep; size_t total_pcm_alloc_bytes; /* total amount of allocated buffers */ struct mutex memory_mutex; /* protection for the above */ +#ifdef CONFIG_SND_DEBUG + struct dentry *debugfs_root; /* debugfs root for card */ +#endif #ifdef CONFIG_PM unsigned int power_state; /* power state */ + atomic_t power_ref; wait_queue_head_t power_sleep; + wait_queue_head_t power_ref_sleep; #endif #if IS_ENABLED(CONFIG_SND_MIXER_OSS) @@ -139,21 +152,61 @@ struct snd_card { #ifdef CONFIG_PM static inline unsigned int snd_power_get_state(struct snd_card *card) { - return card->power_state; + return READ_ONCE(card->power_state); } static inline void snd_power_change_state(struct snd_card *card, unsigned int state) { - card->power_state = state; + WRITE_ONCE(card->power_state, state); wake_up(&card->power_sleep); } +/** + * snd_power_ref - Take the reference count for power control + * @card: sound card object + * + * The power_ref reference of the card is used for managing to block + * the snd_power_sync_ref() operation. This function increments the reference. + * The counterpart snd_power_unref() has to be called appropriately later. + */ +static inline void snd_power_ref(struct snd_card *card) +{ + atomic_inc(&card->power_ref); +} + +/** + * snd_power_unref - Release the reference count for power control + * @card: sound card object + */ +static inline void snd_power_unref(struct snd_card *card) +{ + if (atomic_dec_and_test(&card->power_ref)) + wake_up(&card->power_ref_sleep); +} + +/** + * snd_power_sync_ref - wait until the card power_ref is freed + * @card: sound card object + * + * This function is used to synchronize with the pending power_ref being + * released. + */ +static inline void snd_power_sync_ref(struct snd_card *card) +{ + wait_event(card->power_ref_sleep, !atomic_read(&card->power_ref)); +} + /* init.c */ -int snd_power_wait(struct snd_card *card, unsigned int power_state); +int snd_power_wait(struct snd_card *card); +int snd_power_ref_and_wait(struct snd_card *card); #else /* ! CONFIG_PM */ -static inline int snd_power_wait(struct snd_card *card, unsigned int state) { return 0; } +static inline int snd_power_wait(struct snd_card *card) { return 0; } +static inline void snd_power_ref(struct snd_card *card) {} +static inline void snd_power_unref(struct snd_card *card) {} +static inline int snd_power_ref_and_wait(struct snd_card *card) { return 0; } +static inline void snd_power_sync_ref(struct snd_card *card) {} #define snd_power_get_state(card) ({ (void)(card); SNDRV_CTL_POWER_D0; }) #define snd_power_change_state(card, state) do { (void)(card); } while (0) @@ -180,6 +233,9 @@ static inline struct device *snd_card_get_device_link(struct snd_card *card) extern int snd_major; extern int snd_ecards_limit; extern struct class *sound_class; +#ifdef CONFIG_SND_DEBUG +extern struct dentry *sound_debugfs_root; +#endif void snd_request_card(int card); @@ -226,11 +282,15 @@ extern int (*snd_mixer_oss_notify_callback)(struct snd_card *card, int cmd); int snd_card_new(struct device *parent, int idx, const char *xid, struct module *module, int extra_size, struct snd_card **card_ret); +int snd_devm_card_new(struct device *parent, int idx, const char *xid, + struct module *module, size_t extra_size, + struct snd_card **card_ret); int snd_card_disconnect(struct snd_card *card); void snd_card_disconnect_sync(struct snd_card *card); int snd_card_free(struct snd_card *card); int snd_card_free_when_closed(struct snd_card *card); +int snd_card_free_on_error(struct device *dev, int ret); void snd_card_set_id(struct snd_card *card, const char *id); int snd_card_register(struct snd_card *card); int snd_card_info_init(void); @@ -266,6 +326,7 @@ void snd_device_disconnect(struct snd_card *card, void *device_data); void snd_device_disconnect_all(struct snd_card *card); void snd_device_free(struct snd_card *card, void *device_data); void snd_device_free_all(struct snd_card *card); +int snd_device_get_state(struct snd_card *card, void *device_data); /* isadma.c */ @@ -275,6 +336,7 @@ void snd_device_free_all(struct snd_card *card); void snd_dma_program(unsigned long dma, unsigned long addr, unsigned int size, unsigned short mode); void snd_dma_disable(unsigned long dma); unsigned int snd_dma_pointer(unsigned long dma, unsigned int size); +int snd_devm_request_dma(struct device *dev, int dma, const char *name); #endif /* misc.c */ @@ -331,7 +393,8 @@ void __snd_printk(unsigned int level, const char *file, int line, #define snd_BUG() WARN(1, "BUG?\n") /** - * Suppress high rates of output when CONFIG_SND_DEBUG is enabled. + * snd_printd_ratelimit - Suppress high rates of output when + * CONFIG_SND_DEBUG is enabled. */ #define snd_printd_ratelimit() printk_ratelimit() @@ -444,4 +507,12 @@ snd_pci_quirk_lookup_id(u16 vendor, u16 device, } #endif +/* async signal helpers */ +struct snd_fasync; + +int snd_fasync_helper(int fd, struct file *file, int on, + struct snd_fasync **fasyncp); +void snd_kill_fasync(struct snd_fasync *fasync, int signal, int poll); +void snd_fasync_free(struct snd_fasync *fasync); + #endif /* __SOUND_CORE_H */ diff --git a/include/sound/cs35l41.h b/include/sound/cs35l41.h new file mode 100644 index 000000000000..9ac5918269a5 --- /dev/null +++ b/include/sound/cs35l41.h @@ -0,0 +1,896 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * linux/sound/cs35l41.h -- Platform data for CS35L41 + * + * Copyright (c) 2017-2021 Cirrus Logic Inc. + * + * Author: David Rhodes <david.rhodes@cirrus.com> + */ + +#ifndef __CS35L41_H +#define __CS35L41_H + +#include <linux/regmap.h> +#include <linux/firmware/cirrus/cs_dsp.h> + +#define CS35L41_FIRSTREG 0x00000000 +#define CS35L41_LASTREG 0x03804FE8 +#define CS35L41_DEVID 0x00000000 +#define CS35L41_REVID 0x00000004 +#define CS35L41_FABID 0x00000008 +#define CS35L41_RELID 0x0000000C +#define CS35L41_OTPID 0x00000010 +#define CS35L41_SFT_RESET 0x00000020 +#define CS35L41_TEST_KEY_CTL 0x00000040 +#define CS35L41_USER_KEY_CTL 0x00000044 +#define CS35L41_OTP_MEM0 0x00000400 +#define CS35L41_OTP_MEM31 0x0000047C +#define CS35L41_OTP_CTRL0 0x00000500 +#define CS35L41_OTP_CTRL1 0x00000504 +#define CS35L41_OTP_CTRL3 0x00000508 +#define CS35L41_OTP_CTRL4 0x0000050C +#define CS35L41_OTP_CTRL5 0x00000510 +#define CS35L41_OTP_CTRL6 0x00000514 +#define CS35L41_OTP_CTRL7 0x00000518 +#define CS35L41_OTP_CTRL8 0x0000051C +#define CS35L41_PWR_CTRL1 0x00002014 +#define CS35L41_PWR_CTRL2 0x00002018 +#define CS35L41_PWR_CTRL3 0x0000201C +#define CS35L41_CTRL_OVRRIDE 0x00002020 +#define CS35L41_AMP_OUT_MUTE 0x00002024 +#define CS35L41_PROTECT_REL_ERR_IGN 0x00002034 +#define CS35L41_GPIO_PAD_CONTROL 0x0000242C +#define CS35L41_JTAG_CONTROL 0x00002438 +#define CS35L41_PWRMGT_CTL 0x00002900 +#define CS35L41_WAKESRC_CTL 0x00002904 +#define CS35L41_PWRMGT_STS 0x00002908 +#define CS35L41_PLL_CLK_CTRL 0x00002C04 +#define CS35L41_DSP_CLK_CTRL 0x00002C08 +#define CS35L41_GLOBAL_CLK_CTRL 0x00002C0C +#define CS35L41_DATA_FS_SEL 0x00002C10 +#define CS35L41_TST_FS_MON0 0x00002D10 +#define CS35L41_MDSYNC_EN 0x00003400 +#define CS35L41_MDSYNC_TX_ID 0x00003408 +#define CS35L41_MDSYNC_PWR_CTRL 0x0000340C +#define CS35L41_MDSYNC_DATA_TX 0x00003410 +#define CS35L41_MDSYNC_TX_STATUS 0x00003414 +#define CS35L41_MDSYNC_DATA_RX 0x0000341C +#define CS35L41_MDSYNC_RX_STATUS 0x00003420 +#define CS35L41_MDSYNC_ERR_STATUS 0x00003424 +#define CS35L41_MDSYNC_SYNC_PTE2 0x00003528 +#define CS35L41_MDSYNC_SYNC_PTE3 0x0000352C +#define CS35L41_MDSYNC_SYNC_MSM_STATUS 0x0000353C +#define CS35L41_BSTCVRT_VCTRL1 0x00003800 +#define CS35L41_BSTCVRT_VCTRL2 0x00003804 +#define CS35L41_BSTCVRT_PEAK_CUR 0x00003808 +#define CS35L41_BSTCVRT_SFT_RAMP 0x0000380C +#define CS35L41_BSTCVRT_COEFF 0x00003810 +#define CS35L41_BSTCVRT_SLOPE_LBST 0x00003814 +#define CS35L41_BSTCVRT_SW_FREQ 0x00003818 +#define CS35L41_BSTCVRT_DCM_CTRL 0x0000381C +#define CS35L41_BSTCVRT_DCM_MODE_FORCE 0x00003820 +#define CS35L41_BSTCVRT_OVERVOLT_CTRL 0x00003830 +#define CS35L41_VI_VOL_POL 0x00004000 +#define CS35L41_VIMON_SPKMON_RESYNC 0x00004100 +#define CS35L41_DTEMP_WARN_THLD 0x00004220 +#define CS35L41_DTEMP_CFG 0x00004224 +#define CS35L41_DTEMP_EN 0x00004308 +#define CS35L41_VPVBST_FS_SEL 0x00004400 +#define CS35L41_SP_ENABLES 0x00004800 +#define CS35L41_SP_RATE_CTRL 0x00004804 +#define CS35L41_SP_FORMAT 0x00004808 +#define CS35L41_SP_HIZ_CTRL 0x0000480C +#define CS35L41_SP_FRAME_TX_SLOT 0x00004810 +#define CS35L41_SP_FRAME_RX_SLOT 0x00004820 +#define CS35L41_SP_TX_WL 0x00004830 +#define CS35L41_SP_RX_WL 0x00004840 +#define CS35L41_ASP_CONTROL4 0x00004854 +#define CS35L41_DAC_PCM1_SRC 0x00004C00 +#define CS35L41_ASP_TX1_SRC 0x00004C20 +#define CS35L41_ASP_TX2_SRC 0x00004C24 +#define CS35L41_ASP_TX3_SRC 0x00004C28 +#define CS35L41_ASP_TX4_SRC 0x00004C2C +#define CS35L41_DSP1_RX1_SRC 0x00004C40 +#define CS35L41_DSP1_RX2_SRC 0x00004C44 +#define CS35L41_DSP1_RX3_SRC 0x00004C48 +#define CS35L41_DSP1_RX4_SRC 0x00004C4C +#define CS35L41_DSP1_RX5_SRC 0x00004C50 +#define CS35L41_DSP1_RX6_SRC 0x00004C54 +#define CS35L41_DSP1_RX7_SRC 0x00004C58 +#define CS35L41_DSP1_RX8_SRC 0x00004C5C +#define CS35L41_NGATE1_SRC 0x00004C60 +#define CS35L41_NGATE2_SRC 0x00004C64 +#define CS35L41_AMP_DIG_VOL_CTRL 0x00006000 +#define CS35L41_VPBR_CFG 0x00006404 +#define CS35L41_VBBR_CFG 0x00006408 +#define CS35L41_VPBR_STATUS 0x0000640C +#define CS35L41_VBBR_STATUS 0x00006410 +#define CS35L41_OVERTEMP_CFG 0x00006414 +#define CS35L41_AMP_ERR_VOL 0x00006418 +#define CS35L41_VOL_STATUS_TO_DSP 0x00006450 +#define CS35L41_CLASSH_CFG 0x00006800 +#define CS35L41_WKFET_CFG 0x00006804 +#define CS35L41_NG_CFG 0x00006808 +#define CS35L41_AMP_GAIN_CTRL 0x00006C04 +#define CS35L41_DAC_MSM_CFG 0x00007400 +#define CS35L41_IRQ1_CFG 0x00010000 +#define CS35L41_IRQ1_STATUS 0x00010004 +#define CS35L41_IRQ1_STATUS1 0x00010010 +#define CS35L41_IRQ1_STATUS2 0x00010014 +#define CS35L41_IRQ1_STATUS3 0x00010018 +#define CS35L41_IRQ1_STATUS4 0x0001001C +#define CS35L41_IRQ1_RAW_STATUS1 0x00010090 +#define CS35L41_IRQ1_RAW_STATUS2 0x00010094 +#define CS35L41_IRQ1_RAW_STATUS3 0x00010098 +#define CS35L41_IRQ1_RAW_STATUS4 0x0001009C +#define CS35L41_IRQ1_MASK1 0x00010110 +#define CS35L41_IRQ1_MASK2 0x00010114 +#define CS35L41_IRQ1_MASK3 0x00010118 +#define CS35L41_IRQ1_MASK4 0x0001011C +#define CS35L41_IRQ1_FRC1 0x00010190 +#define CS35L41_IRQ1_FRC2 0x00010194 +#define CS35L41_IRQ1_FRC3 0x00010198 +#define CS35L41_IRQ1_FRC4 0x0001019C +#define CS35L41_IRQ1_EDGE1 0x00010210 +#define CS35L41_IRQ1_EDGE4 0x0001021C +#define CS35L41_IRQ1_POL1 0x00010290 +#define CS35L41_IRQ1_POL2 0x00010294 +#define CS35L41_IRQ1_POL3 0x00010298 +#define CS35L41_IRQ1_POL4 0x0001029C +#define CS35L41_IRQ1_DB3 0x00010318 +#define CS35L41_IRQ2_CFG 0x00010800 +#define CS35L41_IRQ2_STATUS 0x00010804 +#define CS35L41_IRQ2_STATUS1 0x00010810 +#define CS35L41_IRQ2_STATUS2 0x00010814 +#define CS35L41_IRQ2_STATUS3 0x00010818 +#define CS35L41_IRQ2_STATUS4 0x0001081C +#define CS35L41_IRQ2_RAW_STATUS1 0x00010890 +#define CS35L41_IRQ2_RAW_STATUS2 0x00010894 +#define CS35L41_IRQ2_RAW_STATUS3 0x00010898 +#define CS35L41_IRQ2_RAW_STATUS4 0x0001089C +#define CS35L41_IRQ2_MASK1 0x00010910 +#define CS35L41_IRQ2_MASK2 0x00010914 +#define CS35L41_IRQ2_MASK3 0x00010918 +#define CS35L41_IRQ2_MASK4 0x0001091C +#define CS35L41_IRQ2_FRC1 0x00010990 +#define CS35L41_IRQ2_FRC2 0x00010994 +#define CS35L41_IRQ2_FRC3 0x00010998 +#define CS35L41_IRQ2_FRC4 0x0001099C +#define CS35L41_IRQ2_EDGE1 0x00010A10 +#define CS35L41_IRQ2_EDGE4 0x00010A1C +#define CS35L41_IRQ2_POL1 0x00010A90 +#define CS35L41_IRQ2_POL2 0x00010A94 +#define CS35L41_IRQ2_POL3 0x00010A98 +#define CS35L41_IRQ2_POL4 0x00010A9C +#define CS35L41_IRQ2_DB3 0x00010B18 +#define CS35L41_GPIO_STATUS1 0x00011000 +#define CS35L41_GPIO1_CTRL1 0x00011008 +#define CS35L41_GPIO2_CTRL1 0x0001100C +#define CS35L41_MIXER_NGATE_CFG 0x00012000 +#define CS35L41_MIXER_NGATE_CH1_CFG 0x00012004 +#define CS35L41_MIXER_NGATE_CH2_CFG 0x00012008 +#define CS35L41_DSP_MBOX_1 0x00013000 +#define CS35L41_DSP_MBOX_2 0x00013004 +#define CS35L41_DSP_MBOX_3 0x00013008 +#define CS35L41_DSP_MBOX_4 0x0001300C +#define CS35L41_DSP_MBOX_5 0x00013010 +#define CS35L41_DSP_MBOX_6 0x00013014 +#define CS35L41_DSP_MBOX_7 0x00013018 +#define CS35L41_DSP_MBOX_8 0x0001301C +#define CS35L41_DSP_VIRT1_MBOX_1 0x00013020 +#define CS35L41_DSP_VIRT1_MBOX_2 0x00013024 +#define CS35L41_DSP_VIRT1_MBOX_3 0x00013028 +#define CS35L41_DSP_VIRT1_MBOX_4 0x0001302C +#define CS35L41_DSP_VIRT1_MBOX_5 0x00013030 +#define CS35L41_DSP_VIRT1_MBOX_6 0x00013034 +#define CS35L41_DSP_VIRT1_MBOX_7 0x00013038 +#define CS35L41_DSP_VIRT1_MBOX_8 0x0001303C +#define CS35L41_DSP_VIRT2_MBOX_1 0x00013040 +#define CS35L41_DSP_VIRT2_MBOX_2 0x00013044 +#define CS35L41_DSP_VIRT2_MBOX_3 0x00013048 +#define CS35L41_DSP_VIRT2_MBOX_4 0x0001304C +#define CS35L41_DSP_VIRT2_MBOX_5 0x00013050 +#define CS35L41_DSP_VIRT2_MBOX_6 0x00013054 +#define CS35L41_DSP_VIRT2_MBOX_7 0x00013058 +#define CS35L41_DSP_VIRT2_MBOX_8 0x0001305C +#define CS35L41_CLOCK_DETECT_1 0x00014000 +#define CS35L41_TIMER1_CONTROL 0x00015000 +#define CS35L41_TIMER1_COUNT_PRESET 0x00015004 +#define CS35L41_TIMER1_START_STOP 0x0001500C +#define CS35L41_TIMER1_STATUS 0x00015010 +#define CS35L41_TIMER1_COUNT_READBACK 0x00015014 +#define CS35L41_TIMER1_DSP_CLK_CFG 0x00015018 +#define CS35L41_TIMER1_DSP_CLK_STATUS 0x0001501C +#define CS35L41_TIMER2_CONTROL 0x00015100 +#define CS35L41_TIMER2_COUNT_PRESET 0x00015104 +#define CS35L41_TIMER2_START_STOP 0x0001510C +#define CS35L41_TIMER2_STATUS 0x00015110 +#define CS35L41_TIMER2_COUNT_READBACK 0x00015114 +#define CS35L41_TIMER2_DSP_CLK_CFG 0x00015118 +#define CS35L41_TIMER2_DSP_CLK_STATUS 0x0001511C +#define CS35L41_DFT_JTAG_CONTROL 0x00016000 +#define CS35L41_DIE_STS1 0x00017040 +#define CS35L41_DIE_STS2 0x00017044 +#define CS35L41_TEMP_CAL1 0x00017048 +#define CS35L41_TEMP_CAL2 0x0001704C +#define CS35L41_DSP1_XMEM_PACK_0 0x02000000 +#define CS35L41_DSP1_XMEM_PACK_3068 0x02002FF0 +#define CS35L41_DSP1_XMEM_UNPACK32_0 0x02400000 +#define CS35L41_DSP1_XMEM_UNPACK32_2046 0x02401FF8 +#define CS35L41_DSP1_TIMESTAMP_COUNT 0x025C0800 +#define CS35L41_DSP1_SYS_ID 0x025E0000 +#define CS35L41_DSP1_SYS_VERSION 0x025E0004 +#define CS35L41_DSP1_SYS_CORE_ID 0x025E0008 +#define CS35L41_DSP1_SYS_AHB_ADDR 0x025E000C +#define CS35L41_DSP1_SYS_XSRAM_SIZE 0x025E0010 +#define CS35L41_DSP1_SYS_YSRAM_SIZE 0x025E0018 +#define CS35L41_DSP1_SYS_PSRAM_SIZE 0x025E0020 +#define CS35L41_DSP1_SYS_PM_BOOT_SIZE 0x025E0028 +#define CS35L41_DSP1_SYS_FEATURES 0x025E002C +#define CS35L41_DSP1_SYS_FIR_FILTERS 0x025E0030 +#define CS35L41_DSP1_SYS_LMS_FILTERS 0x025E0034 +#define CS35L41_DSP1_SYS_XM_BANK_SIZE 0x025E0038 +#define CS35L41_DSP1_SYS_YM_BANK_SIZE 0x025E003C +#define CS35L41_DSP1_SYS_PM_BANK_SIZE 0x025E0040 +#define CS35L41_DSP1_AHBM_WIN0_CTRL0 0x025E2000 +#define CS35L41_DSP1_AHBM_WIN0_CTRL1 0x025E2004 +#define CS35L41_DSP1_AHBM_WIN1_CTRL0 0x025E2008 +#define CS35L41_DSP1_AHBM_WIN1_CTRL1 0x025E200C +#define CS35L41_DSP1_AHBM_WIN2_CTRL0 0x025E2010 +#define CS35L41_DSP1_AHBM_WIN2_CTRL1 0x025E2014 +#define CS35L41_DSP1_AHBM_WIN3_CTRL0 0x025E2018 +#define CS35L41_DSP1_AHBM_WIN3_CTRL1 0x025E201C +#define CS35L41_DSP1_AHBM_WIN4_CTRL0 0x025E2020 +#define CS35L41_DSP1_AHBM_WIN4_CTRL1 0x025E2024 +#define CS35L41_DSP1_AHBM_WIN5_CTRL0 0x025E2028 +#define CS35L41_DSP1_AHBM_WIN5_CTRL1 0x025E202C +#define CS35L41_DSP1_AHBM_WIN6_CTRL0 0x025E2030 +#define CS35L41_DSP1_AHBM_WIN6_CTRL1 0x025E2034 +#define CS35L41_DSP1_AHBM_WIN7_CTRL0 0x025E2038 +#define CS35L41_DSP1_AHBM_WIN7_CTRL1 0x025E203C +#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL0 0x025E2040 +#define CS35L41_DSP1_AHBM_WIN_DBG_CTRL1 0x025E2044 +#define CS35L41_DSP1_XMEM_UNPACK24_0 0x02800000 +#define CS35L41_DSP1_XMEM_UNPACK24_4093 0x02803FF4 +#define CS35L41_DSP1_CTRL_BASE 0x02B80000 +#define CS35L41_DSP1_CORE_SOFT_RESET 0x02B80010 +#define CS35L41_DSP1_DEBUG 0x02B80040 +#define CS35L41_DSP1_TIMER_CTRL 0x02B80048 +#define CS35L41_DSP1_STREAM_ARB_CTRL 0x02B80050 +#define CS35L41_DSP1_RX1_RATE 0x02B80080 +#define CS35L41_DSP1_RX2_RATE 0x02B80088 +#define CS35L41_DSP1_RX3_RATE 0x02B80090 +#define CS35L41_DSP1_RX4_RATE 0x02B80098 +#define CS35L41_DSP1_RX5_RATE 0x02B800A0 +#define CS35L41_DSP1_RX6_RATE 0x02B800A8 +#define CS35L41_DSP1_RX7_RATE 0x02B800B0 +#define CS35L41_DSP1_RX8_RATE 0x02B800B8 +#define CS35L41_DSP1_TX1_RATE 0x02B80280 +#define CS35L41_DSP1_TX2_RATE 0x02B80288 +#define CS35L41_DSP1_TX3_RATE 0x02B80290 +#define CS35L41_DSP1_TX4_RATE 0x02B80298 +#define CS35L41_DSP1_TX5_RATE 0x02B802A0 +#define CS35L41_DSP1_TX6_RATE 0x02B802A8 +#define CS35L41_DSP1_TX7_RATE 0x02B802B0 +#define CS35L41_DSP1_TX8_RATE 0x02B802B8 +#define CS35L41_DSP1_NMI_CTRL1 0x02B80480 +#define CS35L41_DSP1_NMI_CTRL2 0x02B80488 +#define CS35L41_DSP1_NMI_CTRL3 0x02B80490 +#define CS35L41_DSP1_NMI_CTRL4 0x02B80498 +#define CS35L41_DSP1_NMI_CTRL5 0x02B804A0 +#define CS35L41_DSP1_NMI_CTRL6 0x02B804A8 +#define CS35L41_DSP1_NMI_CTRL7 0x02B804B0 +#define CS35L41_DSP1_NMI_CTRL8 0x02B804B8 +#define CS35L41_DSP1_RESUME_CTRL 0x02B80500 +#define CS35L41_DSP1_IRQ1_CTRL 0x02B80508 +#define CS35L41_DSP1_IRQ2_CTRL 0x02B80510 +#define CS35L41_DSP1_IRQ3_CTRL 0x02B80518 +#define CS35L41_DSP1_IRQ4_CTRL 0x02B80520 +#define CS35L41_DSP1_IRQ5_CTRL 0x02B80528 +#define CS35L41_DSP1_IRQ6_CTRL 0x02B80530 +#define CS35L41_DSP1_IRQ7_CTRL 0x02B80538 +#define CS35L41_DSP1_IRQ8_CTRL 0x02B80540 +#define CS35L41_DSP1_IRQ9_CTRL 0x02B80548 +#define CS35L41_DSP1_IRQ10_CTRL 0x02B80550 +#define CS35L41_DSP1_IRQ11_CTRL 0x02B80558 +#define CS35L41_DSP1_IRQ12_CTRL 0x02B80560 +#define CS35L41_DSP1_IRQ13_CTRL 0x02B80568 +#define CS35L41_DSP1_IRQ14_CTRL 0x02B80570 +#define CS35L41_DSP1_IRQ15_CTRL 0x02B80578 +#define CS35L41_DSP1_IRQ16_CTRL 0x02B80580 +#define CS35L41_DSP1_IRQ17_CTRL 0x02B80588 +#define CS35L41_DSP1_IRQ18_CTRL 0x02B80590 +#define CS35L41_DSP1_IRQ19_CTRL 0x02B80598 +#define CS35L41_DSP1_IRQ20_CTRL 0x02B805A0 +#define CS35L41_DSP1_IRQ21_CTRL 0x02B805A8 +#define CS35L41_DSP1_IRQ22_CTRL 0x02B805B0 +#define CS35L41_DSP1_IRQ23_CTRL 0x02B805B8 +#define CS35L41_DSP1_SCRATCH1 0x02B805C0 +#define CS35L41_DSP1_SCRATCH2 0x02B805C8 +#define CS35L41_DSP1_SCRATCH3 0x02B805D0 +#define CS35L41_DSP1_SCRATCH4 0x02B805D8 +#define CS35L41_DSP1_CCM_CORE_CTRL 0x02BC1000 +#define CS35L41_DSP1_CCM_CLK_OVERRIDE 0x02BC1008 +#define CS35L41_DSP1_XM_MSTR_EN 0x02BC2000 +#define CS35L41_DSP1_XM_CORE_PRI 0x02BC2008 +#define CS35L41_DSP1_XM_AHB_PACK_PL_PRI 0x02BC2010 +#define CS35L41_DSP1_XM_AHB_UP_PL_PRI 0x02BC2018 +#define CS35L41_DSP1_XM_ACCEL_PL0_PRI 0x02BC2020 +#define CS35L41_DSP1_XM_NPL0_PRI 0x02BC2078 +#define CS35L41_DSP1_YM_MSTR_EN 0x02BC20C0 +#define CS35L41_DSP1_YM_CORE_PRI 0x02BC20C8 +#define CS35L41_DSP1_YM_AHB_PACK_PL_PRI 0x02BC20D0 +#define CS35L41_DSP1_YM_AHB_UP_PL_PRI 0x02BC20D8 +#define CS35L41_DSP1_YM_ACCEL_PL0_PRI 0x02BC20E0 +#define CS35L41_DSP1_YM_NPL0_PRI 0x02BC2138 +#define CS35L41_DSP1_PM_MSTR_EN 0x02BC2180 +#define CS35L41_DSP1_PM_PATCH0_ADDR 0x02BC2188 +#define CS35L41_DSP1_PM_PATCH0_EN 0x02BC218C +#define CS35L41_DSP1_PM_PATCH0_DATA_LO 0x02BC2190 +#define CS35L41_DSP1_PM_PATCH0_DATA_HI 0x02BC2194 +#define CS35L41_DSP1_PM_PATCH1_ADDR 0x02BC2198 +#define CS35L41_DSP1_PM_PATCH1_EN 0x02BC219C +#define CS35L41_DSP1_PM_PATCH1_DATA_LO 0x02BC21A0 +#define CS35L41_DSP1_PM_PATCH1_DATA_HI 0x02BC21A4 +#define CS35L41_DSP1_PM_PATCH2_ADDR 0x02BC21A8 +#define CS35L41_DSP1_PM_PATCH2_EN 0x02BC21AC +#define CS35L41_DSP1_PM_PATCH2_DATA_LO 0x02BC21B0 +#define CS35L41_DSP1_PM_PATCH2_DATA_HI 0x02BC21B4 +#define CS35L41_DSP1_PM_PATCH3_ADDR 0x02BC21B8 +#define CS35L41_DSP1_PM_PATCH3_EN 0x02BC21BC +#define CS35L41_DSP1_PM_PATCH3_DATA_LO 0x02BC21C0 +#define CS35L41_DSP1_PM_PATCH3_DATA_HI 0x02BC21C4 +#define CS35L41_DSP1_PM_PATCH4_ADDR 0x02BC21C8 +#define CS35L41_DSP1_PM_PATCH4_EN 0x02BC21CC +#define CS35L41_DSP1_PM_PATCH4_DATA_LO 0x02BC21D0 +#define CS35L41_DSP1_PM_PATCH4_DATA_HI 0x02BC21D4 +#define CS35L41_DSP1_PM_PATCH5_ADDR 0x02BC21D8 +#define CS35L41_DSP1_PM_PATCH5_EN 0x02BC21DC +#define CS35L41_DSP1_PM_PATCH5_DATA_LO 0x02BC21E0 +#define CS35L41_DSP1_PM_PATCH5_DATA_HI 0x02BC21E4 +#define CS35L41_DSP1_PM_PATCH6_ADDR 0x02BC21E8 +#define CS35L41_DSP1_PM_PATCH6_EN 0x02BC21EC +#define CS35L41_DSP1_PM_PATCH6_DATA_LO 0x02BC21F0 +#define CS35L41_DSP1_PM_PATCH6_DATA_HI 0x02BC21F4 +#define CS35L41_DSP1_PM_PATCH7_ADDR 0x02BC21F8 +#define CS35L41_DSP1_PM_PATCH7_EN 0x02BC21FC +#define CS35L41_DSP1_PM_PATCH7_DATA_LO 0x02BC2200 +#define CS35L41_DSP1_PM_PATCH7_DATA_HI 0x02BC2204 +#define CS35L41_DSP1_MPU_XM_ACCESS0 0x02BC3000 +#define CS35L41_DSP1_MPU_YM_ACCESS0 0x02BC3004 +#define CS35L41_DSP1_MPU_WNDW_ACCESS0 0x02BC3008 +#define CS35L41_DSP1_MPU_XREG_ACCESS0 0x02BC300C +#define CS35L41_DSP1_MPU_YREG_ACCESS0 0x02BC3014 +#define CS35L41_DSP1_MPU_XM_ACCESS1 0x02BC3018 +#define CS35L41_DSP1_MPU_YM_ACCESS1 0x02BC301C +#define CS35L41_DSP1_MPU_WNDW_ACCESS1 0x02BC3020 +#define CS35L41_DSP1_MPU_XREG_ACCESS1 0x02BC3024 +#define CS35L41_DSP1_MPU_YREG_ACCESS1 0x02BC302C +#define CS35L41_DSP1_MPU_XM_ACCESS2 0x02BC3030 +#define CS35L41_DSP1_MPU_YM_ACCESS2 0x02BC3034 +#define CS35L41_DSP1_MPU_WNDW_ACCESS2 0x02BC3038 +#define CS35L41_DSP1_MPU_XREG_ACCESS2 0x02BC303C +#define CS35L41_DSP1_MPU_YREG_ACCESS2 0x02BC3044 +#define CS35L41_DSP1_MPU_XM_ACCESS3 0x02BC3048 +#define CS35L41_DSP1_MPU_YM_ACCESS3 0x02BC304C +#define CS35L41_DSP1_MPU_WNDW_ACCESS3 0x02BC3050 +#define CS35L41_DSP1_MPU_XREG_ACCESS3 0x02BC3054 +#define CS35L41_DSP1_MPU_YREG_ACCESS3 0x02BC305C +#define CS35L41_DSP1_MPU_XM_VIO_ADDR 0x02BC3100 +#define CS35L41_DSP1_MPU_XM_VIO_STATUS 0x02BC3104 +#define CS35L41_DSP1_MPU_YM_VIO_ADDR 0x02BC3108 +#define CS35L41_DSP1_MPU_YM_VIO_STATUS 0x02BC310C +#define CS35L41_DSP1_MPU_PM_VIO_ADDR 0x02BC3110 +#define CS35L41_DSP1_MPU_PM_VIO_STATUS 0x02BC3114 +#define CS35L41_DSP1_MPU_LOCK_CONFIG 0x02BC3140 +#define CS35L41_DSP1_MPU_WDT_RST_CTRL 0x02BC3180 +#define CS35L41_DSP1_STRMARB_MSTR0_CFG0 0x02BC5000 +#define CS35L41_DSP1_STRMARB_MSTR0_CFG1 0x02BC5004 +#define CS35L41_DSP1_STRMARB_MSTR0_CFG2 0x02BC5008 +#define CS35L41_DSP1_STRMARB_MSTR1_CFG0 0x02BC5010 +#define CS35L41_DSP1_STRMARB_MSTR1_CFG1 0x02BC5014 +#define CS35L41_DSP1_STRMARB_MSTR1_CFG2 0x02BC5018 +#define CS35L41_DSP1_STRMARB_MSTR2_CFG0 0x02BC5020 +#define CS35L41_DSP1_STRMARB_MSTR2_CFG1 0x02BC5024 +#define CS35L41_DSP1_STRMARB_MSTR2_CFG2 0x02BC5028 +#define CS35L41_DSP1_STRMARB_MSTR3_CFG0 0x02BC5030 +#define CS35L41_DSP1_STRMARB_MSTR3_CFG1 0x02BC5034 +#define CS35L41_DSP1_STRMARB_MSTR3_CFG2 0x02BC5038 +#define CS35L41_DSP1_STRMARB_MSTR4_CFG0 0x02BC5040 +#define CS35L41_DSP1_STRMARB_MSTR4_CFG1 0x02BC5044 +#define CS35L41_DSP1_STRMARB_MSTR4_CFG2 0x02BC5048 +#define CS35L41_DSP1_STRMARB_MSTR5_CFG0 0x02BC5050 +#define CS35L41_DSP1_STRMARB_MSTR5_CFG1 0x02BC5054 +#define CS35L41_DSP1_STRMARB_MSTR5_CFG2 0x02BC5058 +#define CS35L41_DSP1_STRMARB_MSTR6_CFG0 0x02BC5060 +#define CS35L41_DSP1_STRMARB_MSTR6_CFG1 0x02BC5064 +#define CS35L41_DSP1_STRMARB_MSTR6_CFG2 0x02BC5068 +#define CS35L41_DSP1_STRMARB_MSTR7_CFG0 0x02BC5070 +#define CS35L41_DSP1_STRMARB_MSTR7_CFG1 0x02BC5074 +#define CS35L41_DSP1_STRMARB_MSTR7_CFG2 0x02BC5078 +#define CS35L41_DSP1_STRMARB_TX0_CFG0 0x02BC5200 +#define CS35L41_DSP1_STRMARB_TX0_CFG1 0x02BC5204 +#define CS35L41_DSP1_STRMARB_TX1_CFG0 0x02BC5208 +#define CS35L41_DSP1_STRMARB_TX1_CFG1 0x02BC520C +#define CS35L41_DSP1_STRMARB_TX2_CFG0 0x02BC5210 +#define CS35L41_DSP1_STRMARB_TX2_CFG1 0x02BC5214 +#define CS35L41_DSP1_STRMARB_TX3_CFG0 0x02BC5218 +#define CS35L41_DSP1_STRMARB_TX3_CFG1 0x02BC521C +#define CS35L41_DSP1_STRMARB_TX4_CFG0 0x02BC5220 +#define CS35L41_DSP1_STRMARB_TX4_CFG1 0x02BC5224 +#define CS35L41_DSP1_STRMARB_TX5_CFG0 0x02BC5228 +#define CS35L41_DSP1_STRMARB_TX5_CFG1 0x02BC522C +#define CS35L41_DSP1_STRMARB_TX6_CFG0 0x02BC5230 +#define CS35L41_DSP1_STRMARB_TX6_CFG1 0x02BC5234 +#define CS35L41_DSP1_STRMARB_TX7_CFG0 0x02BC5238 +#define CS35L41_DSP1_STRMARB_TX7_CFG1 0x02BC523C +#define CS35L41_DSP1_STRMARB_RX0_CFG0 0x02BC5400 +#define CS35L41_DSP1_STRMARB_RX0_CFG1 0x02BC5404 +#define CS35L41_DSP1_STRMARB_RX1_CFG0 0x02BC5408 +#define CS35L41_DSP1_STRMARB_RX1_CFG1 0x02BC540C +#define CS35L41_DSP1_STRMARB_RX2_CFG0 0x02BC5410 +#define CS35L41_DSP1_STRMARB_RX2_CFG1 0x02BC5414 +#define CS35L41_DSP1_STRMARB_RX3_CFG0 0x02BC5418 +#define CS35L41_DSP1_STRMARB_RX3_CFG1 0x02BC541C +#define CS35L41_DSP1_STRMARB_RX4_CFG0 0x02BC5420 +#define CS35L41_DSP1_STRMARB_RX4_CFG1 0x02BC5424 +#define CS35L41_DSP1_STRMARB_RX5_CFG0 0x02BC5428 +#define CS35L41_DSP1_STRMARB_RX5_CFG1 0x02BC542C +#define CS35L41_DSP1_STRMARB_RX6_CFG0 0x02BC5430 +#define CS35L41_DSP1_STRMARB_RX6_CFG1 0x02BC5434 +#define CS35L41_DSP1_STRMARB_RX7_CFG0 0x02BC5438 +#define CS35L41_DSP1_STRMARB_RX7_CFG1 0x02BC543C +#define CS35L41_DSP1_STRMARB_IRQ0_CFG0 0x02BC5600 +#define CS35L41_DSP1_STRMARB_IRQ0_CFG1 0x02BC5604 +#define CS35L41_DSP1_STRMARB_IRQ0_CFG2 0x02BC5608 +#define CS35L41_DSP1_STRMARB_IRQ1_CFG0 0x02BC5610 +#define CS35L41_DSP1_STRMARB_IRQ1_CFG1 0x02BC5614 +#define CS35L41_DSP1_STRMARB_IRQ1_CFG2 0x02BC5618 +#define CS35L41_DSP1_STRMARB_IRQ2_CFG0 0x02BC5620 +#define CS35L41_DSP1_STRMARB_IRQ2_CFG1 0x02BC5624 +#define CS35L41_DSP1_STRMARB_IRQ2_CFG2 0x02BC5628 +#define CS35L41_DSP1_STRMARB_IRQ3_CFG0 0x02BC5630 +#define CS35L41_DSP1_STRMARB_IRQ3_CFG1 0x02BC5634 +#define CS35L41_DSP1_STRMARB_IRQ3_CFG2 0x02BC5638 +#define CS35L41_DSP1_STRMARB_IRQ4_CFG0 0x02BC5640 +#define CS35L41_DSP1_STRMARB_IRQ4_CFG1 0x02BC5644 +#define CS35L41_DSP1_STRMARB_IRQ4_CFG2 0x02BC5648 +#define CS35L41_DSP1_STRMARB_IRQ5_CFG0 0x02BC5650 +#define CS35L41_DSP1_STRMARB_IRQ5_CFG1 0x02BC5654 +#define CS35L41_DSP1_STRMARB_IRQ5_CFG2 0x02BC5658 +#define CS35L41_DSP1_STRMARB_IRQ6_CFG0 0x02BC5660 +#define CS35L41_DSP1_STRMARB_IRQ6_CFG1 0x02BC5664 +#define CS35L41_DSP1_STRMARB_IRQ6_CFG2 0x02BC5668 +#define CS35L41_DSP1_STRMARB_IRQ7_CFG0 0x02BC5670 +#define CS35L41_DSP1_STRMARB_IRQ7_CFG1 0x02BC5674 +#define CS35L41_DSP1_STRMARB_IRQ7_CFG2 0x02BC5678 +#define CS35L41_DSP1_STRMARB_RESYNC_MSK 0x02BC5A00 +#define CS35L41_DSP1_STRMARB_ERR_STATUS 0x02BC5A08 +#define CS35L41_DSP1_INTPCTL_RES_STATIC 0x02BC6000 +#define CS35L41_DSP1_INTPCTL_RES_DYN 0x02BC6004 +#define CS35L41_DSP1_INTPCTL_NMI_CTRL 0x02BC6008 +#define CS35L41_DSP1_INTPCTL_IRQ_INV 0x02BC6010 +#define CS35L41_DSP1_INTPCTL_IRQ_MODE 0x02BC6014 +#define CS35L41_DSP1_INTPCTL_IRQ_EN 0x02BC6018 +#define CS35L41_DSP1_INTPCTL_IRQ_MSK 0x02BC601C +#define CS35L41_DSP1_INTPCTL_IRQ_FLUSH 0x02BC6020 +#define CS35L41_DSP1_INTPCTL_IRQ_MSKCLR 0x02BC6024 +#define CS35L41_DSP1_INTPCTL_IRQ_FRC 0x02BC6028 +#define CS35L41_DSP1_INTPCTL_IRQ_MSKSET 0x02BC602C +#define CS35L41_DSP1_INTPCTL_IRQ_ERR 0x02BC6030 +#define CS35L41_DSP1_INTPCTL_IRQ_PEND 0x02BC6034 +#define CS35L41_DSP1_INTPCTL_IRQ_GEN 0x02BC6038 +#define CS35L41_DSP1_INTPCTL_TESTBITS 0x02BC6040 +#define CS35L41_DSP1_WDT_CONTROL 0x02BC7000 +#define CS35L41_DSP1_WDT_STATUS 0x02BC7008 +#define CS35L41_DSP1_YMEM_PACK_0 0x02C00000 +#define CS35L41_DSP1_YMEM_PACK_1532 0x02C017F0 +#define CS35L41_DSP1_YMEM_UNPACK32_0 0x03000000 +#define CS35L41_DSP1_YMEM_UNPACK32_1022 0x03000FF8 +#define CS35L41_DSP1_YMEM_UNPACK24_0 0x03400000 +#define CS35L41_DSP1_YMEM_UNPACK24_2045 0x03401FF4 +#define CS35L41_DSP1_PMEM_0 0x03800000 +#define CS35L41_DSP1_PMEM_5114 0x03804FE8 + +/*test regs for emulation bringup*/ +#define CS35L41_PLL_OVR 0x00003018 +#define CS35L41_BST_TEST_DUTY 0x00003900 +#define CS35L41_DIGPWM_IOCTRL 0x0000706C + +/*registers populated by OTP*/ +#define CS35L41_OTP_TRIM_1 0x0000208c +#define CS35L41_OTP_TRIM_2 0x00002090 +#define CS35L41_OTP_TRIM_3 0x00003010 +#define CS35L41_OTP_TRIM_4 0x0000300C +#define CS35L41_OTP_TRIM_5 0x0000394C +#define CS35L41_OTP_TRIM_6 0x00003950 +#define CS35L41_OTP_TRIM_7 0x00003954 +#define CS35L41_OTP_TRIM_8 0x00003958 +#define CS35L41_OTP_TRIM_9 0x0000395C +#define CS35L41_OTP_TRIM_10 0x0000416C +#define CS35L41_OTP_TRIM_11 0x00004160 +#define CS35L41_OTP_TRIM_12 0x00004170 +#define CS35L41_OTP_TRIM_13 0x00004360 +#define CS35L41_OTP_TRIM_14 0x00004448 +#define CS35L41_OTP_TRIM_15 0x0000444C +#define CS35L41_OTP_TRIM_16 0x00006E30 +#define CS35L41_OTP_TRIM_17 0x00006E34 +#define CS35L41_OTP_TRIM_18 0x00006E38 +#define CS35L41_OTP_TRIM_19 0x00006E3C +#define CS35L41_OTP_TRIM_20 0x00006E40 +#define CS35L41_OTP_TRIM_21 0x00006E44 +#define CS35L41_OTP_TRIM_22 0x00006E48 +#define CS35L41_OTP_TRIM_23 0x00006E4C +#define CS35L41_OTP_TRIM_24 0x00006E50 +#define CS35L41_OTP_TRIM_25 0x00006E54 +#define CS35L41_OTP_TRIM_26 0x00006E58 +#define CS35L41_OTP_TRIM_27 0x00006E5C +#define CS35L41_OTP_TRIM_28 0x00006E60 +#define CS35L41_OTP_TRIM_29 0x00006E64 +#define CS35L41_OTP_TRIM_30 0x00007418 +#define CS35L41_OTP_TRIM_31 0x0000741C +#define CS35L41_OTP_TRIM_32 0x00007434 +#define CS35L41_OTP_TRIM_33 0x00007068 +#define CS35L41_OTP_TRIM_34 0x0000410C +#define CS35L41_OTP_TRIM_35 0x0000400C +#define CS35L41_OTP_TRIM_36 0x00002030 + +#define CS35L41_MAX_CACHE_REG 36 +#define CS35L41_OTP_SIZE_WORDS 32 + +#define CS35L41_NUM_SUPPLIES 2 + +#define CS35L41_SCLK_MSTR_MASK 0x10 +#define CS35L41_SCLK_MSTR_SHIFT 4 +#define CS35L41_LRCLK_MSTR_MASK 0x01 +#define CS35L41_LRCLK_MSTR_SHIFT 0 +#define CS35L41_SCLK_INV_MASK 0x40 +#define CS35L41_SCLK_INV_SHIFT 6 +#define CS35L41_LRCLK_INV_MASK 0x04 +#define CS35L41_LRCLK_INV_SHIFT 2 +#define CS35L41_SCLK_FRC_MASK 0x20 +#define CS35L41_SCLK_FRC_SHIFT 5 +#define CS35L41_LRCLK_FRC_MASK 0x02 +#define CS35L41_LRCLK_FRC_SHIFT 1 + +#define CS35L41_AMP_GAIN_PCM_MASK 0x3E0 +#define CS35L41_AMP_GAIN_ZC_MASK 0x0400 +#define CS35L41_AMP_GAIN_ZC_SHIFT 10 + +#define CS35L41_BST_CTL_MASK 0xFF +#define CS35L41_BST_CTL_SEL_MASK 0x03 +#define CS35L41_BST_CTL_SEL_REG 0x00 +#define CS35L41_BST_CTL_SEL_CLASSH 0x01 +#define CS35L41_BST_IPK_MASK 0x7F +#define CS35L41_BST_IPK_SHIFT 0 +#define CS35L41_BST_LIM_MASK 0x4 +#define CS35L41_BST_LIM_SHIFT 2 +#define CS35L41_BST_K1_MASK 0x000000FF +#define CS35L41_BST_K1_SHIFT 0 +#define CS35L41_BST_K2_MASK 0x0000FF00 +#define CS35L41_BST_K2_SHIFT 8 +#define CS35L41_BST_SLOPE_MASK 0x0000FF00 +#define CS35L41_BST_SLOPE_SHIFT 8 +#define CS35L41_BST_LBST_VAL_MASK 0x00000003 +#define CS35L41_BST_LBST_VAL_SHIFT 0 + +#define CS35L41_TEMP_THLD_MASK 0x03 +#define CS35L41_VMON_IMON_VOL_MASK 0x07FF07FF +#define CS35L41_PDM_MODE_MASK 0x01 +#define CS35L41_PDM_MODE_SHIFT 0 + +#define CS35L41_CH_MEM_DEPTH_MASK 0x07 +#define CS35L41_CH_MEM_DEPTH_SHIFT 0 +#define CS35L41_CH_HDRM_CTL_MASK 0x007F0000 +#define CS35L41_CH_HDRM_CTL_SHIFT 16 +#define CS35L41_CH_REL_RATE_MASK 0xFF00 +#define CS35L41_CH_REL_RATE_SHIFT 8 +#define CS35L41_CH_WKFET_DLY_MASK 0x001C +#define CS35L41_CH_WKFET_DLY_SHIFT 2 +#define CS35L41_CH_WKFET_THLD_MASK 0x0F00 +#define CS35L41_CH_WKFET_THLD_SHIFT 8 + +#define CS35L41_HW_NG_SEL_MASK 0x3F00 +#define CS35L41_HW_NG_SEL_SHIFT 8 +#define CS35L41_HW_NG_DLY_MASK 0x0070 +#define CS35L41_HW_NG_DLY_SHIFT 4 +#define CS35L41_HW_NG_THLD_MASK 0x0007 +#define CS35L41_HW_NG_THLD_SHIFT 0 + +#define CS35L41_DSP_NG_ENABLE_MASK 0x00010000 +#define CS35L41_DSP_NG_ENABLE_SHIFT 16 +#define CS35L41_DSP_NG_THLD_MASK 0x7 +#define CS35L41_DSP_NG_THLD_SHIFT 0 +#define CS35L41_DSP_NG_DELAY_MASK 0x0F00 +#define CS35L41_DSP_NG_DELAY_SHIFT 8 + +#define CS35L41_ASP_FMT_MASK 0x0700 +#define CS35L41_ASP_FMT_SHIFT 8 +#define CS35L41_ASP_DOUT_HIZ_MASK 0x03 +#define CS35L41_ASP_DOUT_HIZ_SHIFT 0 +#define CS35L41_ASP_WIDTH_16 0x10 +#define CS35L41_ASP_WIDTH_24 0x18 +#define CS35L41_ASP_WIDTH_32 0x20 +#define CS35L41_ASP_WIDTH_TX_MASK 0xFF0000 +#define CS35L41_ASP_WIDTH_TX_SHIFT 16 +#define CS35L41_ASP_WIDTH_RX_MASK 0xFF000000 +#define CS35L41_ASP_WIDTH_RX_SHIFT 24 +#define CS35L41_ASP_RX1_SLOT_MASK 0x3F +#define CS35L41_ASP_RX1_SLOT_SHIFT 0 +#define CS35L41_ASP_RX2_SLOT_MASK 0x3F00 +#define CS35L41_ASP_RX2_SLOT_SHIFT 8 +#define CS35L41_ASP_RX_WL_MASK 0x3F +#define CS35L41_ASP_TX_WL_MASK 0x3F +#define CS35L41_ASP_RX_WL_SHIFT 0 +#define CS35L41_ASP_TX_WL_SHIFT 0 +#define CS35L41_ASP_SOURCE_MASK 0x7F + +#define CS35L41_INPUT_SRC_ASPRX1 0x08 +#define CS35L41_INPUT_SRC_ASPRX2 0x09 +#define CS35L41_INPUT_SRC_VMON 0x18 +#define CS35L41_INPUT_SRC_IMON 0x19 +#define CS35L41_INPUT_SRC_CLASSH 0x21 +#define CS35L41_INPUT_SRC_VPMON 0x28 +#define CS35L41_INPUT_SRC_VBSTMON 0x29 +#define CS35L41_INPUT_SRC_TEMPMON 0x3A +#define CS35L41_INPUT_SRC_RSVD 0x3B +#define CS35L41_INPUT_DSP_TX1 0x32 +#define CS35L41_INPUT_DSP_TX2 0x33 + +#define CS35L41_WR_PEND_STS_MASK 0x2 + +#define CS35L41_PLL_CLK_SEL_MASK 0x07 +#define CS35L41_PLL_CLK_SEL_SHIFT 0 +#define CS35L41_PLL_CLK_EN_MASK 0x10 +#define CS35L41_PLL_CLK_EN_SHIFT 4 +#define CS35L41_PLL_OPENLOOP_MASK 0x0800 +#define CS35L41_PLL_OPENLOOP_SHIFT 11 +#define CS35L41_PLLSRC_SCLK 0 +#define CS35L41_PLLSRC_LRCLK 1 +#define CS35L41_PLLSRC_SELF 3 +#define CS35L41_PLLSRC_PDMCLK 4 +#define CS35L41_PLLSRC_MCLK 5 +#define CS35L41_PLLSRC_SWIRE 7 +#define CS35L41_REFCLK_FREQ_MASK 0x7E0 +#define CS35L41_REFCLK_FREQ_SHIFT 5 + +#define CS35L41_GLOBAL_FS_MASK 0x1F +#define CS35L41_GLOBAL_FS_SHIFT 0 + +#define CS35L41_GLOBAL_EN_MASK 0x01 +#define CS35L41_GLOBAL_EN_SHIFT 0 +#define CS35L41_BST_EN_MASK 0x0030 +#define CS35L41_BST_EN_SHIFT 4 +#define CS35L41_BST_DIS_FET_OFF 0x00 +#define CS35L41_BST_EN_DEFAULT 0x2 +#define CS35L41_AMP_EN_SHIFT 0 +#define CS35L41_AMP_EN_MASK 1 +#define CS35L41_VMON_EN_MASK 0x1000 +#define CS35L41_VMON_EN_SHIFT 12 +#define CS35L41_IMON_EN_MASK 0x2000 +#define CS35L41_IMON_EN_SHIFT 13 + +#define CS35L41_PDN_DONE_MASK 0x00800000 +#define CS35L41_PDN_DONE_SHIFT 23 +#define CS35L41_PUP_DONE_MASK 0x01000000 +#define CS35L41_PUP_DONE_SHIFT 24 + +#define CS35L36_PUP_DONE_IRQ_UNMASK 0x5F +#define CS35L36_PUP_DONE_IRQ_MASK 0xBF + +#define CS35L41_AMP_SHORT_ERR 0x80000000 +#define CS35L41_BST_SHORT_ERR 0x0100 +#define CS35L41_TEMP_WARN 0x8000 +#define CS35L41_TEMP_ERR 0x00020000 +#define CS35L41_BST_OVP_ERR 0x40 +#define CS35L41_BST_DCM_UVP_ERR 0x80 +#define CS35L41_OTP_BOOT_DONE 0x02 +#define CS35L41_PLL_UNLOCK 0x10 +#define CS35L41_OTP_BOOT_ERR 0x80000000 + +#define CS35L41_AMP_SHORT_ERR_RLS 0x02 +#define CS35L41_BST_SHORT_ERR_RLS 0x04 +#define CS35L41_BST_OVP_ERR_RLS 0x08 +#define CS35L41_BST_UVP_ERR_RLS 0x10 +#define CS35L41_TEMP_WARN_ERR_RLS 0x20 +#define CS35L41_TEMP_ERR_RLS 0x40 + +#define CS35L41_AMP_SHORT_ERR_RLS_SHIFT 1 +#define CS35L41_BST_SHORT_ERR_RLS_SHIFT 2 +#define CS35L41_BST_OVP_ERR_RLS_SHIFT 3 +#define CS35L41_BST_UVP_ERR_RLS_SHIFT 4 +#define CS35L41_TEMP_WARN_ERR_RLS_SHIFT 5 +#define CS35L41_TEMP_ERR_RLS_SHIFT 6 + +#define CS35L41_INT1_MASK_DEFAULT 0x7FFCFE3F +#define CS35L41_INT1_UNMASK_PUP 0xFEFFFFFF +#define CS35L41_INT1_UNMASK_PDN 0xFF7FFFFF + +#define CS35L41_GPIO_DIR_MASK 0x80000000 +#define CS35L41_GPIO_DIR_SHIFT 31 +#define CS35L41_GPIO1_CTRL_MASK 0x00030000 +#define CS35L41_GPIO1_CTRL_SHIFT 16 +#define CS35L41_GPIO2_CTRL_MASK 0x07000000 +#define CS35L41_GPIO2_CTRL_SHIFT 24 +#define CS35L41_GPIO_LVL_SHIFT 15 +#define CS35L41_GPIO_LVL_MASK BIT(CS35L41_GPIO_LVL_SHIFT) +#define CS35L41_GPIO_POL_MASK 0x1000 +#define CS35L41_GPIO_POL_SHIFT 12 + +#define CS35L41_AMP_INV_PCM_SHIFT 14 +#define CS35L41_AMP_INV_PCM_MASK BIT(CS35L41_AMP_INV_PCM_SHIFT) +#define CS35L41_AMP_PCM_VOL_SHIFT 3 +#define CS35L41_AMP_PCM_VOL_MASK (0x7FF << 3) +#define CS35L41_AMP_PCM_VOL_MUTE 0x4CF + +#define CS35L41_CHIP_ID 0x35a40 +#define CS35L41R_CHIP_ID 0x35b40 +#define CS35L41_MTLREVID_MASK 0x0F +#define CS35L41_REVID_A0 0xA0 +#define CS35L41_REVID_B0 0xB0 +#define CS35L41_REVID_B2 0xB2 + +#define CS35L41_HALO_CORE_RESET 0x00000200 + +#define CS35L41_FS1_WINDOW_MASK 0x000007FF +#define CS35L41_FS2_WINDOW_MASK 0x00FFF800 +#define CS35L41_FS2_WINDOW_SHIFT 12 + +#define CS35L41_SPI_MAX_FREQ 4000000 +#define CS35L41_REGSTRIDE 4 + +enum cs35l41_boost_type { + CS35L41_INT_BOOST, + CS35L41_EXT_BOOST, + CS35L41_EXT_BOOST_NO_VSPK_SWITCH, +}; + +enum cs35l41_clk_ids { + CS35L41_CLKID_SCLK = 0, + CS35L41_CLKID_LRCLK = 1, + CS35L41_CLKID_MCLK = 4, +}; + +enum cs35l41_gpio1_func { + CS35L41_GPIO1_HIZ, + CS35L41_GPIO1_GPIO, + CS35L41_GPIO1_MDSYNC, + CS35L41_GPIO1_MCLK, + CS35L41_GPIO1_PDM_CLK, + CS35L41_GPIO1_PDM_DATA, +}; + +enum cs35l41_gpio2_func { + CS35L41_GPIO2_HIZ, + CS35L41_GPIO2_GPIO, + CS35L41_GPIO2_INT_OPEN_DRAIN, + CS35L41_GPIO2_MCLK, + CS35L41_GPIO2_INT_PUSH_PULL_LOW, + CS35L41_GPIO2_INT_PUSH_PULL_HIGH, + CS35L41_GPIO2_PDM_CLK, + CS35L41_GPIO2_PDM_DATA, +}; + +struct cs35l41_gpio_cfg { + bool valid; + bool pol_inv; + bool out_en; + unsigned int func; +}; + +struct cs35l41_hw_cfg { + bool valid; + int bst_ind; + int bst_ipk; + int bst_cap; + int dout_hiz; + struct cs35l41_gpio_cfg gpio1; + struct cs35l41_gpio_cfg gpio2; + unsigned int spk_pos; + + enum cs35l41_boost_type bst_type; +}; + +struct cs35l41_otp_packed_element_t { + u32 reg; + u8 shift; + u8 size; +}; + +struct cs35l41_otp_map_element_t { + u32 id; + u32 num_elements; + const struct cs35l41_otp_packed_element_t *map; + u32 bit_offset; + u32 word_offset; +}; + +enum cs35l41_cspl_mbox_status { + CSPL_MBOX_STS_RUNNING = 0, + CSPL_MBOX_STS_PAUSED = 1, + CSPL_MBOX_STS_RDY_FOR_REINIT = 2, +}; + +enum cs35l41_cspl_mbox_cmd { + CSPL_MBOX_CMD_NONE = 0, + CSPL_MBOX_CMD_PAUSE = 1, + CSPL_MBOX_CMD_RESUME = 2, + CSPL_MBOX_CMD_REINIT = 3, + CSPL_MBOX_CMD_STOP_PRE_REINIT = 4, + CSPL_MBOX_CMD_HIBERNATE = 5, + CSPL_MBOX_CMD_OUT_OF_HIBERNATE = 6, + CSPL_MBOX_CMD_UNKNOWN_CMD = -1, + CSPL_MBOX_CMD_INVALID_SEQUENCE = -2, +}; + +/* + * IRQs + */ +#define CS35L41_IRQ(_irq, _name, _hand) \ + { \ + .irq = CS35L41_ ## _irq ## _IRQ,\ + .name = _name, \ + .handler = _hand, \ + } + +struct cs35l41_irq { + int irq; + const char *name; + irqreturn_t (*handler)(int irq, void *data); +}; + +#define CS35L41_REG_IRQ(_reg, _irq) \ + [CS35L41_ ## _irq ## _IRQ] = { \ + .reg_offset = (CS35L41_ ## _reg) - CS35L41_IRQ1_STATUS1,\ + .mask = CS35L41_ ## _irq ## _MASK \ + } + +/* (0x0000E010) CS35L41_IRQ1_STATUS1 */ +#define CS35L41_BST_OVP_ERR_SHIFT 6 +#define CS35L41_BST_OVP_ERR_MASK BIT(CS35L41_BST_OVP_ERR_SHIFT) +#define CS35L41_BST_DCM_UVP_ERR_SHIFT 7 +#define CS35L41_BST_DCM_UVP_ERR_MASK BIT(CS35L41_BST_DCM_UVP_ERR_SHIFT) +#define CS35L41_BST_SHORT_ERR_SHIFT 8 +#define CS35L41_BST_SHORT_ERR_MASK BIT(CS35L41_BST_SHORT_ERR_SHIFT) +#define CS35L41_TEMP_WARN_SHIFT 15 +#define CS35L41_TEMP_WARN_MASK BIT(CS35L41_TEMP_WARN_SHIFT) +#define CS35L41_TEMP_ERR_SHIFT 17 +#define CS35L41_TEMP_ERR_MASK BIT(CS35L41_TEMP_ERR_SHIFT) +#define CS35L41_AMP_SHORT_ERR_SHIFT 31 +#define CS35L41_AMP_SHORT_ERR_MASK BIT(CS35L41_AMP_SHORT_ERR_SHIFT) + +enum cs35l41_irq_list { + CS35L41_BST_OVP_ERR_IRQ, + CS35L41_BST_DCM_UVP_ERR_IRQ, + CS35L41_BST_SHORT_ERR_IRQ, + CS35L41_TEMP_WARN_IRQ, + CS35L41_TEMP_ERR_IRQ, + CS35L41_AMP_SHORT_ERR_IRQ, + + CS35L41_NUM_IRQ +}; + +extern struct regmap_config cs35l41_regmap_i2c; +extern struct regmap_config cs35l41_regmap_spi; + +int cs35l41_test_key_unlock(struct device *dev, struct regmap *regmap); +int cs35l41_test_key_lock(struct device *dev, struct regmap *regmap); +int cs35l41_otp_unpack(struct device *dev, struct regmap *regmap); +int cs35l41_register_errata_patch(struct device *dev, struct regmap *reg, unsigned int reg_revid); +int cs35l41_set_channels(struct device *dev, struct regmap *reg, + unsigned int tx_num, unsigned int *tx_slot, + unsigned int rx_num, unsigned int *rx_slot); +int cs35l41_gpio_config(struct regmap *regmap, struct cs35l41_hw_cfg *hw_cfg); +void cs35l41_configure_cs_dsp(struct device *dev, struct regmap *reg, struct cs_dsp *dsp); +int cs35l41_set_cspl_mbox_cmd(struct device *dev, struct regmap *regmap, + enum cs35l41_cspl_mbox_cmd cmd); +int cs35l41_write_fs_errata(struct device *dev, struct regmap *regmap); +int cs35l41_enter_hibernate(struct device *dev, struct regmap *regmap, + enum cs35l41_boost_type b_type); +int cs35l41_exit_hibernate(struct device *dev, struct regmap *regmap); +int cs35l41_init_boost(struct device *dev, struct regmap *regmap, + struct cs35l41_hw_cfg *hw_cfg); +bool cs35l41_safe_reset(struct regmap *regmap, enum cs35l41_boost_type b_type); +int cs35l41_global_enable(struct regmap *regmap, enum cs35l41_boost_type b_type, int enable); + +#endif /* __CS35L41_H */ diff --git a/include/sound/cs42l42.h b/include/sound/cs42l42.h new file mode 100644 index 000000000000..1d1c24fdd0ca --- /dev/null +++ b/include/sound/cs42l42.h @@ -0,0 +1,811 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/sound/cs42l42.h -- Platform data for CS42L42 ALSA SoC audio driver header + * + * Copyright 2016-2022 Cirrus Logic, Inc. + * + * Author: James Schulman <james.schulman@cirrus.com> + * Author: Brian Austin <brian.austin@cirrus.com> + * Author: Michael White <michael.white@cirrus.com> + */ + +#ifndef __CS42L42_H +#define __CS42L42_H + +#define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */ +#define CS42L42_WIN_START 0x00 +#define CS42L42_WIN_LEN 0x100 +#define CS42L42_RANGE_MIN 0x00 +#define CS42L42_RANGE_MAX 0x7F + +#define CS42L42_PAGE_10 0x1000 +#define CS42L42_PAGE_11 0x1100 +#define CS42L42_PAGE_12 0x1200 +#define CS42L42_PAGE_13 0x1300 +#define CS42L42_PAGE_15 0x1500 +#define CS42L42_PAGE_19 0x1900 +#define CS42L42_PAGE_1B 0x1B00 +#define CS42L42_PAGE_1C 0x1C00 +#define CS42L42_PAGE_1D 0x1D00 +#define CS42L42_PAGE_1F 0x1F00 +#define CS42L42_PAGE_20 0x2000 +#define CS42L42_PAGE_21 0x2100 +#define CS42L42_PAGE_23 0x2300 +#define CS42L42_PAGE_24 0x2400 +#define CS42L42_PAGE_25 0x2500 +#define CS42L42_PAGE_26 0x2600 +#define CS42L42_PAGE_28 0x2800 +#define CS42L42_PAGE_29 0x2900 +#define CS42L42_PAGE_2A 0x2A00 +#define CS42L42_PAGE_30 0x3000 + +#define CS42L42_CHIP_ID 0x42A42 +#define CS42L83_CHIP_ID 0x42A83 + +/* Page 0x10 Global Registers */ +#define CS42L42_DEVID_AB (CS42L42_PAGE_10 + 0x01) +#define CS42L42_DEVID_CD (CS42L42_PAGE_10 + 0x02) +#define CS42L42_DEVID_E (CS42L42_PAGE_10 + 0x03) +#define CS42L42_FABID (CS42L42_PAGE_10 + 0x04) +#define CS42L42_REVID (CS42L42_PAGE_10 + 0x05) +#define CS42L42_FRZ_CTL (CS42L42_PAGE_10 + 0x06) + +#define CS42L42_SRC_CTL (CS42L42_PAGE_10 + 0x07) +#define CS42L42_SRC_BYPASS_DAC_SHIFT 1 +#define CS42L42_SRC_BYPASS_DAC_MASK (1 << CS42L42_SRC_BYPASS_DAC_SHIFT) + +#define CS42L42_MCLK_STATUS (CS42L42_PAGE_10 + 0x08) + +#define CS42L42_MCLK_CTL (CS42L42_PAGE_10 + 0x09) +#define CS42L42_INTERNAL_FS_SHIFT 1 +#define CS42L42_INTERNAL_FS_MASK (1 << CS42L42_INTERNAL_FS_SHIFT) + +#define CS42L42_SFTRAMP_RATE (CS42L42_PAGE_10 + 0x0A) +#define CS42L42_SLOW_START_ENABLE (CS42L42_PAGE_10 + 0x0B) +#define CS42L42_SLOW_START_EN_MASK GENMASK(6, 4) +#define CS42L42_SLOW_START_EN_SHIFT 4 +#define CS42L42_I2C_DEBOUNCE (CS42L42_PAGE_10 + 0x0E) +#define CS42L42_I2C_STRETCH (CS42L42_PAGE_10 + 0x0F) +#define CS42L42_I2C_TIMEOUT (CS42L42_PAGE_10 + 0x10) + +/* Page 0x11 Power and Headset Detect Registers */ +#define CS42L42_PWR_CTL1 (CS42L42_PAGE_11 + 0x01) +#define CS42L42_ASP_DAO_PDN_SHIFT 7 +#define CS42L42_ASP_DAO_PDN_MASK (1 << CS42L42_ASP_DAO_PDN_SHIFT) +#define CS42L42_ASP_DAI_PDN_SHIFT 6 +#define CS42L42_ASP_DAI_PDN_MASK (1 << CS42L42_ASP_DAI_PDN_SHIFT) +#define CS42L42_MIXER_PDN_SHIFT 5 +#define CS42L42_MIXER_PDN_MASK (1 << CS42L42_MIXER_PDN_SHIFT) +#define CS42L42_EQ_PDN_SHIFT 4 +#define CS42L42_EQ_PDN_MASK (1 << CS42L42_EQ_PDN_SHIFT) +#define CS42L42_HP_PDN_SHIFT 3 +#define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT) +#define CS42L42_ADC_PDN_SHIFT 2 +#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT) +#define CS42L42_PDN_ALL_SHIFT 0 +#define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT) + +#define CS42L42_PWR_CTL2 (CS42L42_PAGE_11 + 0x02) +#define CS42L42_ADC_SRC_PDNB_SHIFT 0 +#define CS42L42_ADC_SRC_PDNB_MASK (1 << CS42L42_ADC_SRC_PDNB_SHIFT) +#define CS42L42_DAC_SRC_PDNB_SHIFT 1 +#define CS42L42_DAC_SRC_PDNB_MASK (1 << CS42L42_DAC_SRC_PDNB_SHIFT) +#define CS42L42_ASP_DAI1_PDN_SHIFT 2 +#define CS42L42_ASP_DAI1_PDN_MASK (1 << CS42L42_ASP_DAI1_PDN_SHIFT) +#define CS42L42_SRC_PDN_OVERRIDE_SHIFT 3 +#define CS42L42_SRC_PDN_OVERRIDE_MASK (1 << CS42L42_SRC_PDN_OVERRIDE_SHIFT) +#define CS42L42_DISCHARGE_FILT_SHIFT 4 +#define CS42L42_DISCHARGE_FILT_MASK (1 << CS42L42_DISCHARGE_FILT_SHIFT) + +#define CS42L42_PWR_CTL3 (CS42L42_PAGE_11 + 0x03) +#define CS42L42_RING_SENSE_PDNB_SHIFT 1 +#define CS42L42_RING_SENSE_PDNB_MASK (1 << CS42L42_RING_SENSE_PDNB_SHIFT) +#define CS42L42_VPMON_PDNB_SHIFT 2 +#define CS42L42_VPMON_PDNB_MASK (1 << CS42L42_VPMON_PDNB_SHIFT) +#define CS42L42_SW_CLK_STP_STAT_SEL_SHIFT 5 +#define CS42L42_SW_CLK_STP_STAT_SEL_MASK (3 << CS42L42_SW_CLK_STP_STAT_SEL_SHIFT) + +#define CS42L42_RSENSE_CTL1 (CS42L42_PAGE_11 + 0x04) +#define CS42L42_RS_TRIM_R_SHIFT 0 +#define CS42L42_RS_TRIM_R_MASK (1 << CS42L42_RS_TRIM_R_SHIFT) +#define CS42L42_RS_TRIM_T_SHIFT 1 +#define CS42L42_RS_TRIM_T_MASK (1 << CS42L42_RS_TRIM_T_SHIFT) +#define CS42L42_HPREF_RS_SHIFT 2 +#define CS42L42_HPREF_RS_MASK (1 << CS42L42_HPREF_RS_SHIFT) +#define CS42L42_HSBIAS_FILT_REF_RS_SHIFT 3 +#define CS42L42_HSBIAS_FILT_REF_RS_MASK (1 << CS42L42_HSBIAS_FILT_REF_RS_SHIFT) +#define CS42L42_RING_SENSE_PU_HIZ_SHIFT 6 +#define CS42L42_RING_SENSE_PU_HIZ_MASK (1 << CS42L42_RING_SENSE_PU_HIZ_SHIFT) + +#define CS42L42_RSENSE_CTL2 (CS42L42_PAGE_11 + 0x05) +#define CS42L42_TS_RS_GATE_SHIFT 7 +#define CS42L42_TS_RS_GATE_MAS (1 << CS42L42_TS_RS_GATE_SHIFT) + +#define CS42L42_OSC_SWITCH (CS42L42_PAGE_11 + 0x07) +#define CS42L42_SCLK_PRESENT_SHIFT 0 +#define CS42L42_SCLK_PRESENT_MASK (1 << CS42L42_SCLK_PRESENT_SHIFT) + +#define CS42L42_OSC_SWITCH_STATUS (CS42L42_PAGE_11 + 0x09) +#define CS42L42_OSC_SW_SEL_STAT_SHIFT 0 +#define CS42L42_OSC_SW_SEL_STAT_MASK (3 << CS42L42_OSC_SW_SEL_STAT_SHIFT) +#define CS42L42_OSC_PDNB_STAT_SHIFT 2 +#define CS42L42_OSC_PDNB_STAT_MASK (1 << CS42L42_OSC_SW_SEL_STAT_SHIFT) + +#define CS42L42_RSENSE_CTL3 (CS42L42_PAGE_11 + 0x12) +#define CS42L42_RS_RISE_DBNCE_TIME_SHIFT 0 +#define CS42L42_RS_RISE_DBNCE_TIME_MASK (7 << CS42L42_RS_RISE_DBNCE_TIME_SHIFT) +#define CS42L42_RS_FALL_DBNCE_TIME_SHIFT 3 +#define CS42L42_RS_FALL_DBNCE_TIME_MASK (7 << CS42L42_RS_FALL_DBNCE_TIME_SHIFT) +#define CS42L42_RS_PU_EN_SHIFT 6 +#define CS42L42_RS_PU_EN_MASK (1 << CS42L42_RS_PU_EN_SHIFT) +#define CS42L42_RS_INV_SHIFT 7 +#define CS42L42_RS_INV_MASK (1 << CS42L42_RS_INV_SHIFT) + +#define CS42L42_TSENSE_CTL (CS42L42_PAGE_11 + 0x13) +#define CS42L42_TS_RISE_DBNCE_TIME_SHIFT 0 +#define CS42L42_TS_RISE_DBNCE_TIME_MASK (7 << CS42L42_TS_RISE_DBNCE_TIME_SHIFT) +#define CS42L42_TS_FALL_DBNCE_TIME_SHIFT 3 +#define CS42L42_TS_FALL_DBNCE_TIME_MASK (7 << CS42L42_TS_FALL_DBNCE_TIME_SHIFT) +#define CS42L42_TS_INV_SHIFT 7 +#define CS42L42_TS_INV_MASK (1 << CS42L42_TS_INV_SHIFT) + +#define CS42L42_TSRS_INT_DISABLE (CS42L42_PAGE_11 + 0x14) +#define CS42L42_D_RS_PLUG_DBNC_SHIFT 0 +#define CS42L42_D_RS_PLUG_DBNC_MASK (1 << CS42L42_D_RS_PLUG_DBNC_SHIFT) +#define CS42L42_D_RS_UNPLUG_DBNC_SHIFT 1 +#define CS42L42_D_RS_UNPLUG_DBNC_MASK (1 << CS42L42_D_RS_UNPLUG_DBNC_SHIFT) +#define CS42L42_D_TS_PLUG_DBNC_SHIFT 2 +#define CS42L42_D_TS_PLUG_DBNC_MASK (1 << CS42L42_D_TS_PLUG_DBNC_SHIFT) +#define CS42L42_D_TS_UNPLUG_DBNC_SHIFT 3 +#define CS42L42_D_TS_UNPLUG_DBNC_MASK (1 << CS42L42_D_TS_UNPLUG_DBNC_SHIFT) + +#define CS42L42_TRSENSE_STATUS (CS42L42_PAGE_11 + 0x15) +#define CS42L42_RS_PLUG_DBNC_SHIFT 0 +#define CS42L42_RS_PLUG_DBNC_MASK (1 << CS42L42_RS_PLUG_DBNC_SHIFT) +#define CS42L42_RS_UNPLUG_DBNC_SHIFT 1 +#define CS42L42_RS_UNPLUG_DBNC_MASK (1 << CS42L42_RS_UNPLUG_DBNC_SHIFT) +#define CS42L42_TS_PLUG_DBNC_SHIFT 2 +#define CS42L42_TS_PLUG_DBNC_MASK (1 << CS42L42_TS_PLUG_DBNC_SHIFT) +#define CS42L42_TS_UNPLUG_DBNC_SHIFT 3 +#define CS42L42_TS_UNPLUG_DBNC_MASK (1 << CS42L42_TS_UNPLUG_DBNC_SHIFT) + +#define CS42L42_HSDET_CTL1 (CS42L42_PAGE_11 + 0x1F) +#define CS42L42_HSDET_COMP1_LVL_SHIFT 0 +#define CS42L42_HSDET_COMP1_LVL_MASK (15 << CS42L42_HSDET_COMP1_LVL_SHIFT) +#define CS42L42_HSDET_COMP2_LVL_SHIFT 4 +#define CS42L42_HSDET_COMP2_LVL_MASK (15 << CS42L42_HSDET_COMP2_LVL_SHIFT) + +#define CS42L42_HSDET_COMP1_LVL_VAL 12 /* 1.25V Comparator */ +#define CS42L42_HSDET_COMP2_LVL_VAL 2 /* 1.75V Comparator */ +#define CS42L42_HSDET_COMP1_LVL_DEFAULT 7 /* 1V Comparator */ +#define CS42L42_HSDET_COMP2_LVL_DEFAULT 7 /* 2V Comparator */ + +#define CS42L42_HSDET_CTL2 (CS42L42_PAGE_11 + 0x20) +#define CS42L42_HSDET_AUTO_TIME_SHIFT 0 +#define CS42L42_HSDET_AUTO_TIME_MASK (3 << CS42L42_HSDET_AUTO_TIME_SHIFT) +#define CS42L42_HSBIAS_REF_SHIFT 3 +#define CS42L42_HSBIAS_REF_MASK (1 << CS42L42_HSBIAS_REF_SHIFT) +#define CS42L42_HSDET_SET_SHIFT 4 +#define CS42L42_HSDET_SET_MASK (3 << CS42L42_HSDET_SET_SHIFT) +#define CS42L42_HSDET_CTRL_SHIFT 6 +#define CS42L42_HSDET_CTRL_MASK (3 << CS42L42_HSDET_CTRL_SHIFT) + +#define CS42L42_HS_SWITCH_CTL (CS42L42_PAGE_11 + 0x21) +#define CS42L42_SW_GNDHS_HS4_SHIFT 0 +#define CS42L42_SW_GNDHS_HS4_MASK (1 << CS42L42_SW_GNDHS_HS4_SHIFT) +#define CS42L42_SW_GNDHS_HS3_SHIFT 1 +#define CS42L42_SW_GNDHS_HS3_MASK (1 << CS42L42_SW_GNDHS_HS3_SHIFT) +#define CS42L42_SW_HSB_HS4_SHIFT 2 +#define CS42L42_SW_HSB_HS4_MASK (1 << CS42L42_SW_HSB_HS4_SHIFT) +#define CS42L42_SW_HSB_HS3_SHIFT 3 +#define CS42L42_SW_HSB_HS3_MASK (1 << CS42L42_SW_HSB_HS3_SHIFT) +#define CS42L42_SW_HSB_FILT_HS4_SHIFT 4 +#define CS42L42_SW_HSB_FILT_HS4_MASK (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) +#define CS42L42_SW_HSB_FILT_HS3_SHIFT 5 +#define CS42L42_SW_HSB_FILT_HS3_MASK (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) +#define CS42L42_SW_REF_HS4_SHIFT 6 +#define CS42L42_SW_REF_HS4_MASK (1 << CS42L42_SW_REF_HS4_SHIFT) +#define CS42L42_SW_REF_HS3_SHIFT 7 +#define CS42L42_SW_REF_HS3_MASK (1 << CS42L42_SW_REF_HS3_SHIFT) + +#define CS42L42_HS_DET_STATUS (CS42L42_PAGE_11 + 0x24) +#define CS42L42_HSDET_TYPE_SHIFT 0 +#define CS42L42_HSDET_TYPE_MASK (3 << CS42L42_HSDET_TYPE_SHIFT) +#define CS42L42_HSDET_COMP1_OUT_SHIFT 6 +#define CS42L42_HSDET_COMP1_OUT_MASK (1 << CS42L42_HSDET_COMP1_OUT_SHIFT) +#define CS42L42_HSDET_COMP2_OUT_SHIFT 7 +#define CS42L42_HSDET_COMP2_OUT_MASK (1 << CS42L42_HSDET_COMP2_OUT_SHIFT) +#define CS42L42_PLUG_CTIA 0 +#define CS42L42_PLUG_OMTP 1 +#define CS42L42_PLUG_HEADPHONE 2 +#define CS42L42_PLUG_INVALID 3 + +#define CS42L42_HSDET_SW_COMP1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (0 << CS42L42_SW_REF_HS4_SHIFT) | \ + (1 << CS42L42_SW_REF_HS3_SHIFT)) +#define CS42L42_HSDET_SW_COMP2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (1 << CS42L42_SW_REF_HS4_SHIFT) | \ + (0 << CS42L42_SW_REF_HS3_SHIFT)) +#define CS42L42_HSDET_SW_TYPE1 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (0 << CS42L42_SW_REF_HS4_SHIFT) | \ + (1 << CS42L42_SW_REF_HS3_SHIFT)) +#define CS42L42_HSDET_SW_TYPE2 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (0 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (1 << CS42L42_SW_REF_HS4_SHIFT) | \ + (0 << CS42L42_SW_REF_HS3_SHIFT)) +#define CS42L42_HSDET_SW_TYPE3 ((1 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (1 << CS42L42_SW_REF_HS4_SHIFT) | \ + (1 << CS42L42_SW_REF_HS3_SHIFT)) +#define CS42L42_HSDET_SW_TYPE4 ((0 << CS42L42_SW_GNDHS_HS4_SHIFT) | \ + (1 << CS42L42_SW_GNDHS_HS3_SHIFT) | \ + (1 << CS42L42_SW_HSB_HS4_SHIFT) | \ + (0 << CS42L42_SW_HSB_HS3_SHIFT) | \ + (0 << CS42L42_SW_HSB_FILT_HS4_SHIFT) | \ + (1 << CS42L42_SW_HSB_FILT_HS3_SHIFT) | \ + (0 << CS42L42_SW_REF_HS4_SHIFT) | \ + (1 << CS42L42_SW_REF_HS3_SHIFT)) + +#define CS42L42_HSDET_COMP_TYPE1 1 +#define CS42L42_HSDET_COMP_TYPE2 2 +#define CS42L42_HSDET_COMP_TYPE3 0 +#define CS42L42_HSDET_COMP_TYPE4 3 + +#define CS42L42_HS_CLAMP_DISABLE (CS42L42_PAGE_11 + 0x29) +#define CS42L42_HS_CLAMP_DISABLE_SHIFT 0 +#define CS42L42_HS_CLAMP_DISABLE_MASK (1 << CS42L42_HS_CLAMP_DISABLE_SHIFT) + +/* Page 0x12 Clocking Registers */ +#define CS42L42_MCLK_SRC_SEL (CS42L42_PAGE_12 + 0x01) +#define CS42L42_MCLKDIV_SHIFT 1 +#define CS42L42_MCLKDIV_MASK (1 << CS42L42_MCLKDIV_SHIFT) +#define CS42L42_MCLK_SRC_SEL_SHIFT 0 +#define CS42L42_MCLK_SRC_SEL_MASK (1 << CS42L42_MCLK_SRC_SEL_SHIFT) + +#define CS42L42_SPDIF_CLK_CFG (CS42L42_PAGE_12 + 0x02) +#define CS42L42_FSYNC_PW_LOWER (CS42L42_PAGE_12 + 0x03) + +#define CS42L42_FSYNC_PW_UPPER (CS42L42_PAGE_12 + 0x04) +#define CS42L42_FSYNC_PULSE_WIDTH_SHIFT 0 +#define CS42L42_FSYNC_PULSE_WIDTH_MASK (0xff << \ + CS42L42_FSYNC_PULSE_WIDTH_SHIFT) + +#define CS42L42_FSYNC_P_LOWER (CS42L42_PAGE_12 + 0x05) + +#define CS42L42_FSYNC_P_UPPER (CS42L42_PAGE_12 + 0x06) +#define CS42L42_FSYNC_PERIOD_SHIFT 0 +#define CS42L42_FSYNC_PERIOD_MASK (0xff << CS42L42_FSYNC_PERIOD_SHIFT) + +#define CS42L42_ASP_CLK_CFG (CS42L42_PAGE_12 + 0x07) +#define CS42L42_ASP_SCLK_EN_SHIFT 5 +#define CS42L42_ASP_SCLK_EN_MASK (1 << CS42L42_ASP_SCLK_EN_SHIFT) +#define CS42L42_ASP_MASTER_MODE 0x01 +#define CS42L42_ASP_SLAVE_MODE 0x00 +#define CS42L42_ASP_MODE_SHIFT 4 +#define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT) +#define CS42L42_ASP_SCPOL_SHIFT 2 +#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT) +#define CS42L42_ASP_SCPOL_NOR 3 +#define CS42L42_ASP_LCPOL_SHIFT 0 +#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT) +#define CS42L42_ASP_LCPOL_INV 3 + +#define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08) +#define CS42L42_ASP_STP_SHIFT 4 +#define CS42L42_ASP_STP_MASK (1 << CS42L42_ASP_STP_SHIFT) +#define CS42L42_ASP_5050_SHIFT 3 +#define CS42L42_ASP_5050_MASK (1 << CS42L42_ASP_5050_SHIFT) +#define CS42L42_ASP_FSD_SHIFT 0 +#define CS42L42_ASP_FSD_MASK (7 << CS42L42_ASP_FSD_SHIFT) +#define CS42L42_ASP_FSD_0_5 1 +#define CS42L42_ASP_FSD_1_0 2 +#define CS42L42_ASP_FSD_1_5 3 +#define CS42L42_ASP_FSD_2_0 4 + +#define CS42L42_FS_RATE_EN (CS42L42_PAGE_12 + 0x09) +#define CS42L42_FS_EN_SHIFT 0 +#define CS42L42_FS_EN_MASK (0xf << CS42L42_FS_EN_SHIFT) +#define CS42L42_FS_EN_IASRC_96K 0x1 +#define CS42L42_FS_EN_OASRC_96K 0x2 + +#define CS42L42_IN_ASRC_CLK (CS42L42_PAGE_12 + 0x0A) +#define CS42L42_CLK_IASRC_SEL_SHIFT 0 +#define CS42L42_CLK_IASRC_SEL_MASK (1 << CS42L42_CLK_IASRC_SEL_SHIFT) +#define CS42L42_CLK_IASRC_SEL_6 0 +#define CS42L42_CLK_IASRC_SEL_12 1 + +#define CS42L42_OUT_ASRC_CLK (CS42L42_PAGE_12 + 0x0B) +#define CS42L42_CLK_OASRC_SEL_SHIFT 0 +#define CS42L42_CLK_OASRC_SEL_MASK (1 << CS42L42_CLK_OASRC_SEL_SHIFT) +#define CS42L42_CLK_OASRC_SEL_12 1 + +#define CS42L42_PLL_DIV_CFG1 (CS42L42_PAGE_12 + 0x0C) +#define CS42L42_SCLK_PREDIV_SHIFT 0 +#define CS42L42_SCLK_PREDIV_MASK (3 << CS42L42_SCLK_PREDIV_SHIFT) + +/* Page 0x13 Interrupt Registers */ +/* Interrupts */ +#define CS42L42_ADC_OVFL_STATUS (CS42L42_PAGE_13 + 0x01) +#define CS42L42_MIXER_STATUS (CS42L42_PAGE_13 + 0x02) +#define CS42L42_SRC_STATUS (CS42L42_PAGE_13 + 0x03) +#define CS42L42_ASP_RX_STATUS (CS42L42_PAGE_13 + 0x04) +#define CS42L42_ASP_TX_STATUS (CS42L42_PAGE_13 + 0x05) +#define CS42L42_CODEC_STATUS (CS42L42_PAGE_13 + 0x08) +#define CS42L42_DET_INT_STATUS1 (CS42L42_PAGE_13 + 0x09) +#define CS42L42_DET_INT_STATUS2 (CS42L42_PAGE_13 + 0x0A) +#define CS42L42_SRCPL_INT_STATUS (CS42L42_PAGE_13 + 0x0B) +#define CS42L42_VPMON_STATUS (CS42L42_PAGE_13 + 0x0D) +#define CS42L42_PLL_LOCK_STATUS (CS42L42_PAGE_13 + 0x0E) +#define CS42L42_TSRS_PLUG_STATUS (CS42L42_PAGE_13 + 0x0F) +/* Masks */ +#define CS42L42_ADC_OVFL_INT_MASK (CS42L42_PAGE_13 + 0x16) +#define CS42L42_ADC_OVFL_SHIFT 0 +#define CS42L42_ADC_OVFL_MASK (1 << CS42L42_ADC_OVFL_SHIFT) +#define CS42L42_ADC_OVFL_VAL_MASK CS42L42_ADC_OVFL_MASK + +#define CS42L42_MIXER_INT_MASK (CS42L42_PAGE_13 + 0x17) +#define CS42L42_MIX_CHB_OVFL_SHIFT 0 +#define CS42L42_MIX_CHB_OVFL_MASK (1 << CS42L42_MIX_CHB_OVFL_SHIFT) +#define CS42L42_MIX_CHA_OVFL_SHIFT 1 +#define CS42L42_MIX_CHA_OVFL_MASK (1 << CS42L42_MIX_CHA_OVFL_SHIFT) +#define CS42L42_EQ_OVFL_SHIFT 2 +#define CS42L42_EQ_OVFL_MASK (1 << CS42L42_EQ_OVFL_SHIFT) +#define CS42L42_EQ_BIQUAD_OVFL_SHIFT 3 +#define CS42L42_EQ_BIQUAD_OVFL_MASK (1 << CS42L42_EQ_BIQUAD_OVFL_SHIFT) +#define CS42L42_MIXER_VAL_MASK (CS42L42_MIX_CHB_OVFL_MASK | \ + CS42L42_MIX_CHA_OVFL_MASK | \ + CS42L42_EQ_OVFL_MASK | \ + CS42L42_EQ_BIQUAD_OVFL_MASK) + +#define CS42L42_SRC_INT_MASK (CS42L42_PAGE_13 + 0x18) +#define CS42L42_SRC_ILK_SHIFT 0 +#define CS42L42_SRC_ILK_MASK (1 << CS42L42_SRC_ILK_SHIFT) +#define CS42L42_SRC_OLK_SHIFT 1 +#define CS42L42_SRC_OLK_MASK (1 << CS42L42_SRC_OLK_SHIFT) +#define CS42L42_SRC_IUNLK_SHIFT 2 +#define CS42L42_SRC_IUNLK_MASK (1 << CS42L42_SRC_IUNLK_SHIFT) +#define CS42L42_SRC_OUNLK_SHIFT 3 +#define CS42L42_SRC_OUNLK_MASK (1 << CS42L42_SRC_OUNLK_SHIFT) +#define CS42L42_SRC_VAL_MASK (CS42L42_SRC_ILK_MASK | \ + CS42L42_SRC_OLK_MASK | \ + CS42L42_SRC_IUNLK_MASK | \ + CS42L42_SRC_OUNLK_MASK) + +#define CS42L42_ASP_RX_INT_MASK (CS42L42_PAGE_13 + 0x19) +#define CS42L42_ASPRX_NOLRCK_SHIFT 0 +#define CS42L42_ASPRX_NOLRCK_MASK (1 << CS42L42_ASPRX_NOLRCK_SHIFT) +#define CS42L42_ASPRX_EARLY_SHIFT 1 +#define CS42L42_ASPRX_EARLY_MASK (1 << CS42L42_ASPRX_EARLY_SHIFT) +#define CS42L42_ASPRX_LATE_SHIFT 2 +#define CS42L42_ASPRX_LATE_MASK (1 << CS42L42_ASPRX_LATE_SHIFT) +#define CS42L42_ASPRX_ERROR_SHIFT 3 +#define CS42L42_ASPRX_ERROR_MASK (1 << CS42L42_ASPRX_ERROR_SHIFT) +#define CS42L42_ASPRX_OVLD_SHIFT 4 +#define CS42L42_ASPRX_OVLD_MASK (1 << CS42L42_ASPRX_OVLD_SHIFT) +#define CS42L42_ASP_RX_VAL_MASK (CS42L42_ASPRX_NOLRCK_MASK | \ + CS42L42_ASPRX_EARLY_MASK | \ + CS42L42_ASPRX_LATE_MASK | \ + CS42L42_ASPRX_ERROR_MASK | \ + CS42L42_ASPRX_OVLD_MASK) + +#define CS42L42_ASP_TX_INT_MASK (CS42L42_PAGE_13 + 0x1A) +#define CS42L42_ASPTX_NOLRCK_SHIFT 0 +#define CS42L42_ASPTX_NOLRCK_MASK (1 << CS42L42_ASPTX_NOLRCK_SHIFT) +#define CS42L42_ASPTX_EARLY_SHIFT 1 +#define CS42L42_ASPTX_EARLY_MASK (1 << CS42L42_ASPTX_EARLY_SHIFT) +#define CS42L42_ASPTX_LATE_SHIFT 2 +#define CS42L42_ASPTX_LATE_MASK (1 << CS42L42_ASPTX_LATE_SHIFT) +#define CS42L42_ASPTX_SMERROR_SHIFT 3 +#define CS42L42_ASPTX_SMERROR_MASK (1 << CS42L42_ASPTX_SMERROR_SHIFT) +#define CS42L42_ASP_TX_VAL_MASK (CS42L42_ASPTX_NOLRCK_MASK | \ + CS42L42_ASPTX_EARLY_MASK | \ + CS42L42_ASPTX_LATE_MASK | \ + CS42L42_ASPTX_SMERROR_MASK) + +#define CS42L42_CODEC_INT_MASK (CS42L42_PAGE_13 + 0x1B) +#define CS42L42_PDN_DONE_SHIFT 0 +#define CS42L42_PDN_DONE_MASK (1 << CS42L42_PDN_DONE_SHIFT) +#define CS42L42_HSDET_AUTO_DONE_SHIFT 1 +#define CS42L42_HSDET_AUTO_DONE_MASK (1 << CS42L42_HSDET_AUTO_DONE_SHIFT) +#define CS42L42_CODEC_VAL_MASK (CS42L42_PDN_DONE_MASK | \ + CS42L42_HSDET_AUTO_DONE_MASK) + +#define CS42L42_SRCPL_INT_MASK (CS42L42_PAGE_13 + 0x1C) +#define CS42L42_SRCPL_ADC_LK_SHIFT 0 +#define CS42L42_SRCPL_ADC_LK_MASK (1 << CS42L42_SRCPL_ADC_LK_SHIFT) +#define CS42L42_SRCPL_DAC_LK_SHIFT 2 +#define CS42L42_SRCPL_DAC_LK_MASK (1 << CS42L42_SRCPL_DAC_LK_SHIFT) +#define CS42L42_SRCPL_ADC_UNLK_SHIFT 5 +#define CS42L42_SRCPL_ADC_UNLK_MASK (1 << CS42L42_SRCPL_ADC_UNLK_SHIFT) +#define CS42L42_SRCPL_DAC_UNLK_SHIFT 6 +#define CS42L42_SRCPL_DAC_UNLK_MASK (1 << CS42L42_SRCPL_DAC_UNLK_SHIFT) +#define CS42L42_SRCPL_VAL_MASK (CS42L42_SRCPL_ADC_LK_MASK | \ + CS42L42_SRCPL_DAC_LK_MASK | \ + CS42L42_SRCPL_ADC_UNLK_MASK | \ + CS42L42_SRCPL_DAC_UNLK_MASK) + +#define CS42L42_VPMON_INT_MASK (CS42L42_PAGE_13 + 0x1E) +#define CS42L42_VPMON_SHIFT 0 +#define CS42L42_VPMON_MASK (1 << CS42L42_VPMON_SHIFT) +#define CS42L42_VPMON_VAL_MASK CS42L42_VPMON_MASK + +#define CS42L42_PLL_LOCK_INT_MASK (CS42L42_PAGE_13 + 0x1F) +#define CS42L42_PLL_LOCK_SHIFT 0 +#define CS42L42_PLL_LOCK_MASK (1 << CS42L42_PLL_LOCK_SHIFT) +#define CS42L42_PLL_LOCK_VAL_MASK CS42L42_PLL_LOCK_MASK + +#define CS42L42_TSRS_PLUG_INT_MASK (CS42L42_PAGE_13 + 0x20) +#define CS42L42_RS_PLUG_SHIFT 0 +#define CS42L42_RS_PLUG_MASK (1 << CS42L42_RS_PLUG_SHIFT) +#define CS42L42_RS_UNPLUG_SHIFT 1 +#define CS42L42_RS_UNPLUG_MASK (1 << CS42L42_RS_UNPLUG_SHIFT) +#define CS42L42_TS_PLUG_SHIFT 2 +#define CS42L42_TS_PLUG_MASK (1 << CS42L42_TS_PLUG_SHIFT) +#define CS42L42_TS_UNPLUG_SHIFT 3 +#define CS42L42_TS_UNPLUG_MASK (1 << CS42L42_TS_UNPLUG_SHIFT) +#define CS42L42_TSRS_PLUG_VAL_MASK (CS42L42_RS_PLUG_MASK | \ + CS42L42_RS_UNPLUG_MASK | \ + CS42L42_TS_PLUG_MASK | \ + CS42L42_TS_UNPLUG_MASK) +#define CS42L42_TS_PLUG 3 +#define CS42L42_TS_UNPLUG 0 +#define CS42L42_TS_TRANS 1 + +/* + * NOTE: PLL_START must be 0 while both ADC_PDN=1 and HP_PDN=1. + * Otherwise it will prevent FILT+ from charging properly. + */ +#define CS42L42_PLL_CTL1 (CS42L42_PAGE_15 + 0x01) +#define CS42L42_PLL_START_SHIFT 0 +#define CS42L42_PLL_START_MASK (1 << CS42L42_PLL_START_SHIFT) + +#define CS42L42_PLL_DIV_FRAC0 (CS42L42_PAGE_15 + 0x02) +#define CS42L42_PLL_DIV_FRAC_SHIFT 0 +#define CS42L42_PLL_DIV_FRAC_MASK (0xff << CS42L42_PLL_DIV_FRAC_SHIFT) + +#define CS42L42_PLL_DIV_FRAC1 (CS42L42_PAGE_15 + 0x03) +#define CS42L42_PLL_DIV_FRAC2 (CS42L42_PAGE_15 + 0x04) + +#define CS42L42_PLL_DIV_INT (CS42L42_PAGE_15 + 0x05) +#define CS42L42_PLL_DIV_INT_SHIFT 0 +#define CS42L42_PLL_DIV_INT_MASK (0xff << CS42L42_PLL_DIV_INT_SHIFT) + +#define CS42L42_PLL_CTL3 (CS42L42_PAGE_15 + 0x08) +#define CS42L42_PLL_DIVOUT_SHIFT 0 +#define CS42L42_PLL_DIVOUT_MASK (0xff << CS42L42_PLL_DIVOUT_SHIFT) + +#define CS42L42_PLL_CAL_RATIO (CS42L42_PAGE_15 + 0x0A) +#define CS42L42_PLL_CAL_RATIO_SHIFT 0 +#define CS42L42_PLL_CAL_RATIO_MASK (0xff << CS42L42_PLL_CAL_RATIO_SHIFT) + +#define CS42L42_PLL_CTL4 (CS42L42_PAGE_15 + 0x1B) +#define CS42L42_PLL_MODE_SHIFT 0 +#define CS42L42_PLL_MODE_MASK (3 << CS42L42_PLL_MODE_SHIFT) + +/* Page 0x19 HP Load Detect Registers */ +#define CS42L42_LOAD_DET_RCSTAT (CS42L42_PAGE_19 + 0x25) +#define CS42L42_RLA_STAT_SHIFT 0 +#define CS42L42_RLA_STAT_MASK (3 << CS42L42_RLA_STAT_SHIFT) +#define CS42L42_RLA_STAT_15_OHM 0 + +#define CS42L42_LOAD_DET_DONE (CS42L42_PAGE_19 + 0x26) +#define CS42L42_HPLOAD_DET_DONE_SHIFT 0 +#define CS42L42_HPLOAD_DET_DONE_MASK (1 << CS42L42_HPLOAD_DET_DONE_SHIFT) + +#define CS42L42_LOAD_DET_EN (CS42L42_PAGE_19 + 0x27) +#define CS42L42_HP_LD_EN_SHIFT 0 +#define CS42L42_HP_LD_EN_MASK (1 << CS42L42_HP_LD_EN_SHIFT) + +/* Page 0x1B Headset Interface Registers */ +#define CS42L42_HSBIAS_SC_AUTOCTL (CS42L42_PAGE_1B + 0x70) +#define CS42L42_HSBIAS_SENSE_TRIP_SHIFT 0 +#define CS42L42_HSBIAS_SENSE_TRIP_MASK (7 << CS42L42_HSBIAS_SENSE_TRIP_SHIFT) +#define CS42L42_TIP_SENSE_EN_SHIFT 5 +#define CS42L42_TIP_SENSE_EN_MASK (1 << CS42L42_TIP_SENSE_EN_SHIFT) +#define CS42L42_AUTO_HSBIAS_HIZ_SHIFT 6 +#define CS42L42_AUTO_HSBIAS_HIZ_MASK (1 << CS42L42_AUTO_HSBIAS_HIZ_SHIFT) +#define CS42L42_HSBIAS_SENSE_EN_SHIFT 7 +#define CS42L42_HSBIAS_SENSE_EN_MASK (1 << CS42L42_HSBIAS_SENSE_EN_SHIFT) + +#define CS42L42_WAKE_CTL (CS42L42_PAGE_1B + 0x71) +#define CS42L42_WAKEB_CLEAR_SHIFT 0 +#define CS42L42_WAKEB_CLEAR_MASK (1 << CS42L42_WAKEB_CLEAR_SHIFT) +#define CS42L42_WAKEB_MODE_SHIFT 5 +#define CS42L42_WAKEB_MODE_MASK (1 << CS42L42_WAKEB_MODE_SHIFT) +#define CS42L42_M_HP_WAKE_SHIFT 6 +#define CS42L42_M_HP_WAKE_MASK (1 << CS42L42_M_HP_WAKE_SHIFT) +#define CS42L42_M_MIC_WAKE_SHIFT 7 +#define CS42L42_M_MIC_WAKE_MASK (1 << CS42L42_M_MIC_WAKE_SHIFT) + +#define CS42L42_ADC_DISABLE_MUTE (CS42L42_PAGE_1B + 0x72) +#define CS42L42_ADC_DISABLE_S0_MUTE_SHIFT 7 +#define CS42L42_ADC_DISABLE_S0_MUTE_MASK (1 << CS42L42_ADC_DISABLE_S0_MUTE_SHIFT) + +#define CS42L42_TIPSENSE_CTL (CS42L42_PAGE_1B + 0x73) +#define CS42L42_TIP_SENSE_DEBOUNCE_SHIFT 0 +#define CS42L42_TIP_SENSE_DEBOUNCE_MASK (3 << CS42L42_TIP_SENSE_DEBOUNCE_SHIFT) +#define CS42L42_TIP_SENSE_INV_SHIFT 5 +#define CS42L42_TIP_SENSE_INV_MASK (1 << CS42L42_TIP_SENSE_INV_SHIFT) +#define CS42L42_TIP_SENSE_CTRL_SHIFT 6 +#define CS42L42_TIP_SENSE_CTRL_MASK (3 << CS42L42_TIP_SENSE_CTRL_SHIFT) + +/* + * NOTE: DETECT_MODE must be 0 while both ADC_PDN=1 and HP_PDN=1. + * Otherwise it will prevent FILT+ from charging properly. + */ +#define CS42L42_MISC_DET_CTL (CS42L42_PAGE_1B + 0x74) +#define CS42L42_PDN_MIC_LVL_DET_SHIFT 0 +#define CS42L42_PDN_MIC_LVL_DET_MASK (1 << CS42L42_PDN_MIC_LVL_DET_SHIFT) +#define CS42L42_HSBIAS_CTL_SHIFT 1 +#define CS42L42_HSBIAS_CTL_MASK (3 << CS42L42_HSBIAS_CTL_SHIFT) +#define CS42L42_DETECT_MODE_SHIFT 3 +#define CS42L42_DETECT_MODE_MASK (3 << CS42L42_DETECT_MODE_SHIFT) + +#define CS42L42_MIC_DET_CTL1 (CS42L42_PAGE_1B + 0x75) +#define CS42L42_HS_DET_LEVEL_SHIFT 0 +#define CS42L42_HS_DET_LEVEL_MASK (0x3F << CS42L42_HS_DET_LEVEL_SHIFT) +#define CS42L42_EVENT_STAT_SEL_SHIFT 6 +#define CS42L42_EVENT_STAT_SEL_MASK (1 << CS42L42_EVENT_STAT_SEL_SHIFT) +#define CS42L42_LATCH_TO_VP_SHIFT 7 +#define CS42L42_LATCH_TO_VP_MASK (1 << CS42L42_LATCH_TO_VP_SHIFT) + +#define CS42L42_MIC_DET_CTL2 (CS42L42_PAGE_1B + 0x76) +#define CS42L42_DEBOUNCE_TIME_SHIFT 5 +#define CS42L42_DEBOUNCE_TIME_MASK (0x07 << CS42L42_DEBOUNCE_TIME_SHIFT) + +#define CS42L42_DET_STATUS1 (CS42L42_PAGE_1B + 0x77) +#define CS42L42_HSBIAS_HIZ_MODE_SHIFT 6 +#define CS42L42_HSBIAS_HIZ_MODE_MASK (1 << CS42L42_HSBIAS_HIZ_MODE_SHIFT) +#define CS42L42_TIP_SENSE_SHIFT 7 +#define CS42L42_TIP_SENSE_MASK (1 << CS42L42_TIP_SENSE_SHIFT) + +#define CS42L42_DET_STATUS2 (CS42L42_PAGE_1B + 0x78) +#define CS42L42_SHORT_TRUE_SHIFT 0 +#define CS42L42_SHORT_TRUE_MASK (1 << CS42L42_SHORT_TRUE_SHIFT) +#define CS42L42_HS_TRUE_SHIFT 1 +#define CS42L42_HS_TRUE_MASK (1 << CS42L42_HS_TRUE_SHIFT) + +#define CS42L42_DET_INT1_MASK (CS42L42_PAGE_1B + 0x79) +#define CS42L42_TIP_SENSE_UNPLUG_SHIFT 5 +#define CS42L42_TIP_SENSE_UNPLUG_MASK (1 << CS42L42_TIP_SENSE_UNPLUG_SHIFT) +#define CS42L42_TIP_SENSE_PLUG_SHIFT 6 +#define CS42L42_TIP_SENSE_PLUG_MASK (1 << CS42L42_TIP_SENSE_PLUG_SHIFT) +#define CS42L42_HSBIAS_SENSE_SHIFT 7 +#define CS42L42_HSBIAS_SENSE_MASK (1 << CS42L42_HSBIAS_SENSE_SHIFT) +#define CS42L42_DET_INT_VAL1_MASK (CS42L42_TIP_SENSE_UNPLUG_MASK | \ + CS42L42_TIP_SENSE_PLUG_MASK | \ + CS42L42_HSBIAS_SENSE_MASK) + +#define CS42L42_DET_INT2_MASK (CS42L42_PAGE_1B + 0x7A) +#define CS42L42_M_SHORT_DET_SHIFT 0 +#define CS42L42_M_SHORT_DET_MASK (1 << CS42L42_M_SHORT_DET_SHIFT) +#define CS42L42_M_SHORT_RLS_SHIFT 1 +#define CS42L42_M_SHORT_RLS_MASK (1 << CS42L42_M_SHORT_RLS_SHIFT) +#define CS42L42_M_HSBIAS_HIZ_SHIFT 2 +#define CS42L42_M_HSBIAS_HIZ_MASK (1 << CS42L42_M_HSBIAS_HIZ_SHIFT) +#define CS42L42_M_DETECT_FT_SHIFT 6 +#define CS42L42_M_DETECT_FT_MASK (1 << CS42L42_M_DETECT_FT_SHIFT) +#define CS42L42_M_DETECT_TF_SHIFT 7 +#define CS42L42_M_DETECT_TF_MASK (1 << CS42L42_M_DETECT_TF_SHIFT) +#define CS42L42_DET_INT_VAL2_MASK (CS42L42_M_SHORT_DET_MASK | \ + CS42L42_M_SHORT_RLS_MASK | \ + CS42L42_M_HSBIAS_HIZ_MASK | \ + CS42L42_M_DETECT_FT_MASK | \ + CS42L42_M_DETECT_TF_MASK) + +/* Page 0x1C Headset Bias Registers */ +#define CS42L42_HS_BIAS_CTL (CS42L42_PAGE_1C + 0x03) +#define CS42L42_HSBIAS_RAMP_SHIFT 0 +#define CS42L42_HSBIAS_RAMP_MASK (3 << CS42L42_HSBIAS_RAMP_SHIFT) +#define CS42L42_HSBIAS_PD_SHIFT 4 +#define CS42L42_HSBIAS_PD_MASK (1 << CS42L42_HSBIAS_PD_SHIFT) +#define CS42L42_HSBIAS_CAPLESS_SHIFT 7 +#define CS42L42_HSBIAS_CAPLESS_MASK (1 << CS42L42_HSBIAS_CAPLESS_SHIFT) + +/* Page 0x1D ADC Registers */ +#define CS42L42_ADC_CTL (CS42L42_PAGE_1D + 0x01) +#define CS42L42_ADC_NOTCH_DIS_SHIFT 5 +#define CS42L42_ADC_FORCE_WEAK_VCM_SHIFT 4 +#define CS42L42_ADC_INV_SHIFT 2 +#define CS42L42_ADC_DIG_BOOST_SHIFT 0 + +#define CS42L42_ADC_VOLUME (CS42L42_PAGE_1D + 0x03) +#define CS42L42_ADC_VOL_SHIFT 0 + +#define CS42L42_ADC_WNF_HPF_CTL (CS42L42_PAGE_1D + 0x04) +#define CS42L42_ADC_WNF_CF_SHIFT 4 +#define CS42L42_ADC_WNF_EN_SHIFT 3 +#define CS42L42_ADC_HPF_CF_SHIFT 1 +#define CS42L42_ADC_HPF_EN_SHIFT 0 + +/* Page 0x1F DAC Registers */ +#define CS42L42_DAC_CTL1 (CS42L42_PAGE_1F + 0x01) +#define CS42L42_DACB_INV_SHIFT 1 +#define CS42L42_DACA_INV_SHIFT 0 + +#define CS42L42_DAC_CTL2 (CS42L42_PAGE_1F + 0x06) +#define CS42L42_HPOUT_PULLDOWN_SHIFT 4 +#define CS42L42_HPOUT_PULLDOWN_MASK (15 << CS42L42_HPOUT_PULLDOWN_SHIFT) +#define CS42L42_HPOUT_LOAD_SHIFT 3 +#define CS42L42_HPOUT_LOAD_MASK (1 << CS42L42_HPOUT_LOAD_SHIFT) +#define CS42L42_HPOUT_CLAMP_SHIFT 2 +#define CS42L42_HPOUT_CLAMP_MASK (1 << CS42L42_HPOUT_CLAMP_SHIFT) +#define CS42L42_DAC_HPF_EN_SHIFT 1 +#define CS42L42_DAC_HPF_EN_MASK (1 << CS42L42_DAC_HPF_EN_SHIFT) +#define CS42L42_DAC_MON_EN_SHIFT 0 +#define CS42L42_DAC_MON_EN_MASK (1 << CS42L42_DAC_MON_EN_SHIFT) + +/* Page 0x20 HP CTL Registers */ +#define CS42L42_HP_CTL (CS42L42_PAGE_20 + 0x01) +#define CS42L42_HP_ANA_BMUTE_SHIFT 3 +#define CS42L42_HP_ANA_BMUTE_MASK (1 << CS42L42_HP_ANA_BMUTE_SHIFT) +#define CS42L42_HP_ANA_AMUTE_SHIFT 2 +#define CS42L42_HP_ANA_AMUTE_MASK (1 << CS42L42_HP_ANA_AMUTE_SHIFT) +#define CS42L42_HP_FULL_SCALE_VOL_SHIFT 1 +#define CS42L42_HP_FULL_SCALE_VOL_MASK (1 << CS42L42_HP_FULL_SCALE_VOL_SHIFT) + +/* Page 0x21 Class H Registers */ +#define CS42L42_CLASSH_CTL (CS42L42_PAGE_21 + 0x01) + +/* Page 0x23 Mixer Volume Registers */ +#define CS42L42_MIXER_CHA_VOL (CS42L42_PAGE_23 + 0x01) +#define CS42L42_MIXER_ADC_VOL (CS42L42_PAGE_23 + 0x02) + +#define CS42L42_MIXER_CHB_VOL (CS42L42_PAGE_23 + 0x03) +#define CS42L42_MIXER_CH_VOL_SHIFT 0 +#define CS42L42_MIXER_CH_VOL_MASK (0x3f << CS42L42_MIXER_CH_VOL_SHIFT) + +/* Page 0x24 EQ Registers */ +#define CS42L42_EQ_COEF_IN0 (CS42L42_PAGE_24 + 0x01) +#define CS42L42_EQ_COEF_IN1 (CS42L42_PAGE_24 + 0x02) +#define CS42L42_EQ_COEF_IN2 (CS42L42_PAGE_24 + 0x03) +#define CS42L42_EQ_COEF_IN3 (CS42L42_PAGE_24 + 0x04) +#define CS42L42_EQ_COEF_RW (CS42L42_PAGE_24 + 0x06) +#define CS42L42_EQ_COEF_OUT0 (CS42L42_PAGE_24 + 0x07) +#define CS42L42_EQ_COEF_OUT1 (CS42L42_PAGE_24 + 0x08) +#define CS42L42_EQ_COEF_OUT2 (CS42L42_PAGE_24 + 0x09) +#define CS42L42_EQ_COEF_OUT3 (CS42L42_PAGE_24 + 0x0A) +#define CS42L42_EQ_INIT_STAT (CS42L42_PAGE_24 + 0x0B) +#define CS42L42_EQ_START_FILT (CS42L42_PAGE_24 + 0x0C) +#define CS42L42_EQ_MUTE_CTL (CS42L42_PAGE_24 + 0x0E) + +/* Page 0x25 Audio Port Registers */ +#define CS42L42_SP_RX_CH_SEL (CS42L42_PAGE_25 + 0x01) +#define CS42L42_SP_RX_CHB_SEL_SHIFT 2 +#define CS42L42_SP_RX_CHB_SEL_MASK (3 << CS42L42_SP_RX_CHB_SEL_SHIFT) + +#define CS42L42_SP_RX_ISOC_CTL (CS42L42_PAGE_25 + 0x02) +#define CS42L42_SP_RX_RSYNC_SHIFT 6 +#define CS42L42_SP_RX_RSYNC_MASK (1 << CS42L42_SP_RX_RSYNC_SHIFT) +#define CS42L42_SP_RX_NSB_POS_SHIFT 3 +#define CS42L42_SP_RX_NSB_POS_MASK (7 << CS42L42_SP_RX_NSB_POS_SHIFT) +#define CS42L42_SP_RX_NFS_NSBB_SHIFT 2 +#define CS42L42_SP_RX_NFS_NSBB_MASK (1 << CS42L42_SP_RX_NFS_NSBB_SHIFT) +#define CS42L42_SP_RX_ISOC_MODE_SHIFT 0 +#define CS42L42_SP_RX_ISOC_MODE_MASK (3 << CS42L42_SP_RX_ISOC_MODE_SHIFT) + +#define CS42L42_SP_RX_FS (CS42L42_PAGE_25 + 0x03) +#define CS42l42_SPDIF_CH_SEL (CS42L42_PAGE_25 + 0x04) +#define CS42L42_SP_TX_ISOC_CTL (CS42L42_PAGE_25 + 0x05) +#define CS42L42_SP_TX_FS (CS42L42_PAGE_25 + 0x06) +#define CS42L42_SPDIF_SW_CTL1 (CS42L42_PAGE_25 + 0x07) + +/* Page 0x26 SRC Registers */ +#define CS42L42_SRC_SDIN_FS (CS42L42_PAGE_26 + 0x01) +#define CS42L42_SRC_SDIN_FS_SHIFT 0 +#define CS42L42_SRC_SDIN_FS_MASK (0x1f << CS42L42_SRC_SDIN_FS_SHIFT) + +#define CS42L42_SRC_SDOUT_FS (CS42L42_PAGE_26 + 0x09) + +/* Page 0x28 S/PDIF Registers */ +#define CS42L42_SPDIF_CTL1 (CS42L42_PAGE_28 + 0x01) +#define CS42L42_SPDIF_CTL2 (CS42L42_PAGE_28 + 0x02) +#define CS42L42_SPDIF_CTL3 (CS42L42_PAGE_28 + 0x03) +#define CS42L42_SPDIF_CTL4 (CS42L42_PAGE_28 + 0x04) + +/* Page 0x29 Serial Port TX Registers */ +#define CS42L42_ASP_TX_SZ_EN (CS42L42_PAGE_29 + 0x01) +#define CS42L42_ASP_TX_EN_SHIFT 0 +#define CS42L42_ASP_TX_CH_EN (CS42L42_PAGE_29 + 0x02) +#define CS42L42_ASP_TX0_CH2_SHIFT 1 +#define CS42L42_ASP_TX0_CH1_SHIFT 0 + +#define CS42L42_ASP_TX_CH_AP_RES (CS42L42_PAGE_29 + 0x03) +#define CS42L42_ASP_TX_CH1_AP_SHIFT 7 +#define CS42L42_ASP_TX_CH1_AP_MASK (1 << CS42L42_ASP_TX_CH1_AP_SHIFT) +#define CS42L42_ASP_TX_CH2_AP_SHIFT 6 +#define CS42L42_ASP_TX_CH2_AP_MASK (1 << CS42L42_ASP_TX_CH2_AP_SHIFT) +#define CS42L42_ASP_TX_CH2_RES_SHIFT 2 +#define CS42L42_ASP_TX_CH2_RES_MASK (3 << CS42L42_ASP_TX_CH2_RES_SHIFT) +#define CS42L42_ASP_TX_CH1_RES_SHIFT 0 +#define CS42L42_ASP_TX_CH1_RES_MASK (3 << CS42L42_ASP_TX_CH1_RES_SHIFT) +#define CS42L42_ASP_TX_CH1_BIT_MSB (CS42L42_PAGE_29 + 0x04) +#define CS42L42_ASP_TX_CH1_BIT_LSB (CS42L42_PAGE_29 + 0x05) +#define CS42L42_ASP_TX_HIZ_DLY_CFG (CS42L42_PAGE_29 + 0x06) +#define CS42L42_ASP_TX_CH2_BIT_MSB (CS42L42_PAGE_29 + 0x0A) +#define CS42L42_ASP_TX_CH2_BIT_LSB (CS42L42_PAGE_29 + 0x0B) + +/* Page 0x2A Serial Port RX Registers */ +#define CS42L42_ASP_RX_DAI0_EN (CS42L42_PAGE_2A + 0x01) +#define CS42L42_ASP_RX0_CH_EN_SHIFT 2 +#define CS42L42_ASP_RX0_CH_EN_MASK (0xf << CS42L42_ASP_RX0_CH_EN_SHIFT) +#define CS42L42_ASP_RX0_CH1_SHIFT 2 +#define CS42L42_ASP_RX0_CH2_SHIFT 3 +#define CS42L42_ASP_RX0_CH3_SHIFT 4 +#define CS42L42_ASP_RX0_CH4_SHIFT 5 + +#define CS42L42_ASP_RX_DAI0_CH1_AP_RES (CS42L42_PAGE_2A + 0x02) +#define CS42L42_ASP_RX_DAI0_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x03) +#define CS42L42_ASP_RX_DAI0_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x04) +#define CS42L42_ASP_RX_DAI0_CH2_AP_RES (CS42L42_PAGE_2A + 0x05) +#define CS42L42_ASP_RX_DAI0_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x06) +#define CS42L42_ASP_RX_DAI0_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x07) +#define CS42L42_ASP_RX_DAI0_CH3_AP_RES (CS42L42_PAGE_2A + 0x08) +#define CS42L42_ASP_RX_DAI0_CH3_BIT_MSB (CS42L42_PAGE_2A + 0x09) +#define CS42L42_ASP_RX_DAI0_CH3_BIT_LSB (CS42L42_PAGE_2A + 0x0A) +#define CS42L42_ASP_RX_DAI0_CH4_AP_RES (CS42L42_PAGE_2A + 0x0B) +#define CS42L42_ASP_RX_DAI0_CH4_BIT_MSB (CS42L42_PAGE_2A + 0x0C) +#define CS42L42_ASP_RX_DAI0_CH4_BIT_LSB (CS42L42_PAGE_2A + 0x0D) +#define CS42L42_ASP_RX_DAI1_CH1_AP_RES (CS42L42_PAGE_2A + 0x0E) +#define CS42L42_ASP_RX_DAI1_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x0F) +#define CS42L42_ASP_RX_DAI1_CH1_BIT_LSB (CS42L42_PAGE_2A + 0x10) +#define CS42L42_ASP_RX_DAI1_CH2_AP_RES (CS42L42_PAGE_2A + 0x11) +#define CS42L42_ASP_RX_DAI1_CH2_BIT_MSB (CS42L42_PAGE_2A + 0x12) +#define CS42L42_ASP_RX_DAI1_CH2_BIT_LSB (CS42L42_PAGE_2A + 0x13) + +#define CS42L42_ASP_RX_CH_AP_SHIFT 6 +#define CS42L42_ASP_RX_CH_AP_MASK (1 << CS42L42_ASP_RX_CH_AP_SHIFT) +#define CS42L42_ASP_RX_CH_AP_LOW 0 +#define CS42L42_ASP_RX_CH_AP_HI 1 +#define CS42L42_ASP_RX_CH_RES_SHIFT 0 +#define CS42L42_ASP_RX_CH_RES_MASK (3 << CS42L42_ASP_RX_CH_RES_SHIFT) +#define CS42L42_ASP_RX_CH_RES_32 3 +#define CS42L42_ASP_RX_CH_RES_16 1 +#define CS42L42_ASP_RX_CH_BIT_ST_SHIFT 0 +#define CS42L42_ASP_RX_CH_BIT_ST_MASK (0xff << CS42L42_ASP_RX_CH_BIT_ST_SHIFT) + +/* Page 0x30 ID Registers */ +#define CS42L42_SUB_REVID (CS42L42_PAGE_30 + 0x14) +#define CS42L42_MAX_REGISTER (CS42L42_PAGE_30 + 0x14) + +/* Defines for fracturing values spread across multiple registers */ +#define CS42L42_FRAC0_VAL(val) ((val) & 0x0000ff) +#define CS42L42_FRAC1_VAL(val) (((val) & 0x00ff00) >> 8) +#define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16) + +#define CS42L42_NUM_SUPPLIES 5 +#define CS42L42_BOOT_TIME_US 3000 +#define CS42L42_PLL_DIVOUT_TIME_US 800 +#define CS42L42_CLOCK_SWITCH_DELAY_US 150 +#define CS42L42_PLL_LOCK_POLL_US 250 +#define CS42L42_PLL_LOCK_TIMEOUT_US 1250 +#define CS42L42_HP_ADC_EN_TIME_US 20000 +#define CS42L42_PDN_DONE_POLL_US 1000 +#define CS42L42_PDN_DONE_TIMEOUT_US 200000 +#define CS42L42_PDN_DONE_TIME_MS 100 +#define CS42L42_FILT_DISCHARGE_TIME_MS 46 + +#endif /* __CS42L42_H */ diff --git a/include/sound/dmaengine_pcm.h b/include/sound/dmaengine_pcm.h index b65220685920..2df54cf02cb3 100644 --- a/include/sound/dmaengine_pcm.h +++ b/include/sound/dmaengine_pcm.h @@ -15,6 +15,8 @@ * snd_pcm_substream_to_dma_direction - Get dma_transfer_direction for a PCM * substream * @substream: PCM substream + * + * Return: DMA transfer direction */ static inline enum dma_transfer_direction snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream) @@ -60,22 +62,25 @@ struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream) * @maxburst: Maximum number of words(note: words, as in units of the * src_addr_width member, not bytes) that can be send to or received from the * DAI in one burst. - * @slave_id: Slave requester id for the DMA channel. * @filter_data: Custom DMA channel filter data, this will usually be used when * requesting the DMA channel. * @chan_name: Custom channel name to use when requesting DMA channel. * @fifo_size: FIFO size of the DAI controller in bytes * @flags: PCM_DAI flags, only SND_DMAENGINE_PCM_DAI_FLAG_PACK for now + * @peripheral_config: peripheral configuration for programming peripheral + * for dmaengine transfer + * @peripheral_size: peripheral configuration buffer size */ struct snd_dmaengine_dai_dma_data { dma_addr_t addr; enum dma_slave_buswidth addr_width; u32 maxburst; - unsigned int slave_id; void *filter_data; const char *chan_name; unsigned int fifo_size; unsigned int flags; + void *peripheral_config; + size_t peripheral_size; }; void snd_dmaengine_pcm_set_config_from_dai_data( @@ -161,4 +166,15 @@ int snd_dmaengine_pcm_prepare_slave_config(struct snd_pcm_substream *substream, #define SND_DMAENGINE_PCM_DRV_NAME "snd_dmaengine_pcm" +struct dmaengine_pcm { + struct dma_chan *chan[SNDRV_PCM_STREAM_LAST + 1]; + const struct snd_dmaengine_pcm_config *config; + struct snd_soc_component component; + unsigned int flags; +}; + +static inline struct dmaengine_pcm *soc_component_to_pcm(struct snd_soc_component *p) +{ + return container_of(p, struct dmaengine_pcm, component); +} #endif diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h index 468e38c54dd3..39787fecc8d9 100644 --- a/include/sound/emu10k1.h +++ b/include/sound/emu10k1.h @@ -1701,7 +1701,7 @@ struct snd_emu10k1 { struct snd_dma_buffer silent_page; /* silent page */ struct snd_dma_buffer ptb_pages; /* page table pages */ struct snd_dma_device p16v_dma_dev; - struct snd_dma_buffer p16v_buffer; + struct snd_dma_buffer *p16v_buffer; struct snd_util_memhdr *memhdr; /* page allocation list */ @@ -1796,14 +1796,12 @@ int snd_emu10k1_create(struct snd_card *card, unsigned short extout_mask, long max_cache_bytes, int enable_ir, - uint subsystem, - struct snd_emu10k1 ** remu); + uint subsystem); int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device); int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device); int snd_p16v_pcm(struct snd_emu10k1 *emu, int device); -int snd_p16v_free(struct snd_emu10k1 * emu); int snd_p16v_mixer(struct snd_emu10k1 * emu); int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device); int snd_emu10k1_fx8010_pcm(struct snd_emu10k1 *emu, int device); diff --git a/include/sound/emu8000.h b/include/sound/emu8000.h index ad0365d6de5e..072791bbcf5c 100644 --- a/include/sound/emu8000.h +++ b/include/sound/emu8000.h @@ -56,9 +56,6 @@ struct snd_emu8000 { unsigned long port1; /* Port usually base+0 */ unsigned long port2; /* Port usually at base+0x400 */ unsigned long port3; /* Port usually at base+0x800 */ - struct resource *res_port1; - struct resource *res_port2; - struct resource *res_port3; unsigned short last_reg;/* Last register command */ spinlock_t reg_lock; diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h new file mode 100644 index 000000000000..4c8b94c77b8e --- /dev/null +++ b/include/sound/graph_card.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * ASoC audio graph card support + * + */ + +#ifndef __GRAPH_CARD_H +#define __GRAPH_CARD_H + +#include <sound/simple_card_utils.h> + +typedef int (*GRAPH2_CUSTOM)(struct asoc_simple_priv *priv, + struct device_node *lnk, + struct link_info *li); + +struct graph2_custom_hooks { + int (*hook_pre)(struct asoc_simple_priv *priv); + int (*hook_post)(struct asoc_simple_priv *priv); + GRAPH2_CUSTOM custom_normal; + GRAPH2_CUSTOM custom_dpcm; + GRAPH2_CUSTOM custom_c2c; +}; + +int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); +int audio_graph2_parse_of(struct asoc_simple_priv *priv, struct device *dev, + struct graph2_custom_hooks *hooks); + +int audio_graph2_link_normal(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); +int audio_graph2_link_dpcm(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); +int audio_graph2_link_c2c(struct asoc_simple_priv *priv, + struct device_node *lnk, struct link_info *li); + +#endif /* __GRAPH_CARD_H */ diff --git a/include/sound/gus.h b/include/sound/gus.h index 410939ecf3a5..cd8da68cab92 100644 --- a/include/sound/gus.h +++ b/include/sound/gus.h @@ -613,4 +613,8 @@ int snd_gus_dram_write(struct snd_gus_card *gus, char __user *ptr, int snd_gus_dram_read(struct snd_gus_card *gus, char __user *ptr, unsigned int addr, unsigned int size, int rom); +/* gus_timer.c */ +void snd_gf1_timers_init(struct snd_gus_card *gus); +void snd_gf1_timers_done(struct snd_gus_card *gus); + #endif /* __SOUND_GUS_H */ diff --git a/include/sound/hda_codec.h b/include/sound/hda_codec.h index 3ee8036f5436..25ec8c181688 100644 --- a/include/sound/hda_codec.h +++ b/include/sound/hda_codec.h @@ -8,7 +8,7 @@ #ifndef __SOUND_HDA_CODEC_H #define __SOUND_HDA_CODEC_H -#include <linux/kref.h> +#include <linux/refcount.h> #include <linux/mod_devicetable.h> #include <sound/info.h> #include <sound/control.h> @@ -59,6 +59,9 @@ struct hda_bus { unsigned int no_response_fallback:1; /* don't fallback at RIRB error */ unsigned int bus_probing :1; /* during probing process */ unsigned int keep_power:1; /* keep power up for notification */ + unsigned int jackpoll_in_suspend:1; /* keep jack polling during + * runtime suspend + */ int primary_dig_out_type; /* primary digital out PCM type */ unsigned int mixer_assigned; /* codec addr for mixer name */ @@ -114,7 +117,6 @@ struct hda_codec_ops { int (*resume)(struct hda_codec *codec); int (*check_power_status)(struct hda_codec *codec, hda_nid_t nid); #endif - void (*reboot_notify)(struct hda_codec *codec); void (*stream_pm)(struct hda_codec *codec, hda_nid_t nid, bool on); }; @@ -167,8 +169,8 @@ struct hda_pcm { bool own_chmap; /* codec driver provides own channel maps */ /* private: */ struct hda_codec *codec; - struct kref kref; struct list_head list; + unsigned int disconnected:1; }; /* codec information */ @@ -188,6 +190,8 @@ struct hda_codec { /* PCM to create, set by patch_ops.build_pcms callback */ struct list_head pcm_list_head; + refcount_t pcm_ref; + wait_queue_head_t remove_sleep; /* codec specific info */ void *spec; @@ -208,7 +212,7 @@ struct hda_codec { struct mutex control_mutex; struct snd_array spdif_out; unsigned int spdif_in_enable; /* SPDIF input enable? */ - const hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */ + const hda_nid_t *follower_dig_outs; /* optional digital out follower widgets */ struct snd_array init_pins; /* initial (BIOS) pin configurations */ struct snd_array driver_pins; /* pin configs set by codec parser */ struct snd_array cvt_setups; /* audio convert setups */ @@ -225,8 +229,8 @@ struct hda_codec { #endif /* misc flags */ + unsigned int configured:1; /* codec was configured */ unsigned int in_freeing:1; /* being released */ - unsigned int registered:1; /* codec was registered */ unsigned int display_power_control:1; /* needs display power */ unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each * status change @@ -253,7 +257,7 @@ struct hda_codec { unsigned int force_pin_prefix:1; /* Add location prefix */ unsigned int link_down_at_suspend:1; /* link down at runtime suspend */ unsigned int relaxed_resume:1; /* don't resume forcibly for jack */ - unsigned int mst_no_extra_pcms:1; /* no backup PCMs for DP-MST */ + unsigned int forced_resume:1; /* forced resume for jack */ #ifdef CONFIG_PM unsigned long power_on_acct; @@ -288,6 +292,8 @@ struct hda_codec { #define dev_to_hda_codec(_dev) container_of(_dev, struct hda_codec, core.dev) #define hda_codec_dev(_dev) (&(_dev)->core.dev) +#define hdac_to_hda_codec(_hdac) container_of(_hdac, struct hda_codec, core) + #define list_for_each_codec(c, bus) \ list_for_each_entry(c, &(bus)->core.codec_list, core.list) #define list_for_each_codec_safe(c, n, bus) \ @@ -299,12 +305,19 @@ struct hda_codec { /* * constructors */ +__printf(3, 4) struct hda_codec * +snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr, + const char *fmt, ...); int snd_hda_codec_new(struct hda_bus *bus, struct snd_card *card, unsigned int codec_addr, struct hda_codec **codecp); int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card, - unsigned int codec_addr, struct hda_codec *codec); + unsigned int codec_addr, struct hda_codec *codec, + bool snddev_managed); int snd_hda_codec_configure(struct hda_codec *codec); int snd_hda_codec_update_widgets(struct hda_codec *codec); +void snd_hda_codec_register(struct hda_codec *codec); +void snd_hda_codec_unregister(struct hda_codec *codec); +void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); /* * low level functions @@ -339,7 +352,7 @@ snd_hda_get_num_conns(struct hda_codec *codec, hda_nid_t nid) #define snd_hda_get_raw_connections(codec, nid, list, max_conns) \ snd_hdac_get_connections(&(codec)->core, nid, list, max_conns) #define snd_hda_get_num_raw_conns(codec, nid) \ - snd_hdac_get_connections(&(codec)->core, nid, NULL, 0); + snd_hdac_get_connections(&(codec)->core, nid, NULL, 0) int snd_hda_get_conn_list(struct hda_codec *codec, hda_nid_t nid, const hda_nid_t **listp); @@ -362,13 +375,6 @@ struct hda_verb { void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq); -/* unsolicited event */ -static inline void -snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) -{ - snd_hdac_bus_queue_event(&bus->core, res, res_ex); -} - /* cached write */ static inline int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid, @@ -418,9 +424,11 @@ __printf(2, 3) struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec, const char *fmt, ...); +void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec); + static inline void snd_hda_codec_pcm_get(struct hda_pcm *pcm) { - kref_get(&pcm->kref); + refcount_inc(&pcm->codec->pcm_ref); } void snd_hda_codec_pcm_put(struct hda_pcm *pcm); @@ -488,12 +496,19 @@ int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) #define snd_hda_power_down(codec) snd_hdac_power_down(&(codec)->core) #define snd_hda_power_down_pm(codec) snd_hdac_power_down_pm(&(codec)->core) #ifdef CONFIG_PM +void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay); void snd_hda_set_power_save(struct hda_bus *bus, int delay); void snd_hda_update_power_acct(struct hda_codec *codec); #else +static inline void snd_hda_codec_set_power_save(struct hda_codec *codec, int delay) {} static inline void snd_hda_set_power_save(struct hda_bus *bus, int delay) {} #endif +static inline bool hda_codec_need_resume(struct hda_codec *codec) +{ + return !codec->relaxed_resume && codec->jacktbl.used; +} + #ifdef CONFIG_SND_HDA_PATCH_LOADER /* * patch firmware diff --git a/include/sound/hda_register.h b/include/sound/hda_register.h index 057d2a2d0bd0..d37cf43546eb 100644 --- a/include/sound/hda_register.h +++ b/include/sound/hda_register.h @@ -119,7 +119,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_VS_EM3U 0x103C #define AZX_REG_VS_EM4L 0x1040 #define AZX_REG_VS_EM4U 0x1044 -#define AZX_REG_VS_LTRC 0x1048 +#define AZX_REG_VS_LTRP 0x1048 #define AZX_REG_VS_D0I3C 0x104A #define AZX_REG_VS_PCE 0x104B #define AZX_REG_VS_L2MAGC 0x1050 @@ -140,8 +140,12 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define BDL_SIZE 4096 #define AZX_MAX_BDL_ENTRIES (BDL_SIZE / 16) #define AZX_MAX_FRAG 32 -/* max buffer size - no h/w limit, you can increase as you like */ -#define AZX_MAX_BUF_SIZE (1024*1024*1024) +/* + * max buffer size - artificial 4MB limit per stream to avoid big allocations + * In theory it can be really big, but as it is per stream on systems with many streams memory could + * be quickly saturated if userspace requests maximum buffer size for each of them. + */ +#define AZX_MAX_BUF_SIZE (4*1024*1024) /* RIRB int mask: overrun[2], response[0] */ #define RIRB_INT_RESPONSE 0x01 @@ -256,7 +260,18 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_ML_LCAP 0x00 #define AZX_REG_ML_LCTL 0x04 + +#define AZX_ML_LCTL_CPA BIT(23) +#define AZX_ML_LCTL_CPA_SHIFT 23 +#define AZX_ML_LCTL_SPA BIT(16) +#define AZX_ML_LCTL_SPA_SHIFT 16 +#define AZX_ML_LCTL_SCF GENMASK(3, 0) + #define AZX_REG_ML_LOSIDV 0x08 + +/* bit0 is reserved, with BIT(1) mapping to stream1 */ +#define AZX_ML_LOSIDV_STREAM_MASK 0xFFFE + #define AZX_REG_ML_LSDIID 0x0C #define AZX_REG_ML_LPSOO 0x10 #define AZX_REG_ML_LPSIO 0x12 @@ -264,15 +279,6 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 }; #define AZX_REG_ML_LOUTPAY 0x20 #define AZX_REG_ML_LINPAY 0x30 -/* bit0 is reserved, with BIT(1) mapping to stream1 */ -#define ML_LOSIDV_STREAM_MASK 0xFFFE - -#define ML_LCTL_SCF_MASK 0xF -#define AZX_MLCTL_SPA (0x1 << 16) -#define AZX_MLCTL_CPA (0x1 << 23) -#define AZX_MLCTL_SPA_SHIFT 16 -#define AZX_MLCTL_CPA_SHIFT 23 - /* registers for DMA Resume Capability Structure */ #define AZX_DRSM_CAP_ID 0x5 #define AZX_REG_DRSM_CTL 0x4 diff --git a/include/sound/hda_verbs.h b/include/sound/hda_verbs.h index e36b77531c5c..006d358acce2 100644 --- a/include/sound/hda_verbs.h +++ b/include/sound/hda_verbs.h @@ -461,7 +461,7 @@ enum { #define AC_DE_ELDV (1<<1) #define AC_DE_IA (1<<2) -/* device device types (0x0-0xf) */ +/* device types (0x0-0xf) */ enum { AC_JACK_LINE_OUT, AC_JACK_SPEAKER, diff --git a/include/sound/hdaudio.h b/include/sound/hdaudio.h index d4299e146d95..35778f953a3f 100644 --- a/include/sound/hdaudio.h +++ b/include/sound/hdaudio.h @@ -9,6 +9,8 @@ #include <linux/device.h> #include <linux/interrupt.h> #include <linux/io.h> +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/iopoll.h> #include <linux/pm_runtime.h> #include <linux/timecounter.h> #include <sound/core.h> @@ -92,6 +94,7 @@ struct hdac_device { bool lazy_cache:1; /* don't wake up for writes */ bool caps_overwriting:1; /* caps overwrite being in process */ bool cache_coef:1; /* cache COEF read/write too */ + unsigned int registered:1; /* codec was registered */ }; /* device/driver type used for matching */ @@ -207,8 +210,8 @@ static inline int snd_hdac_power_down_pm(struct hdac_device *codec) { return 0; static inline int snd_hdac_keep_power_up(struct hdac_device *codec) { return 0; } static inline void snd_hdac_enter_pm(struct hdac_device *codec) {} static inline void snd_hdac_leave_pm(struct hdac_device *codec) {} -static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return 0; } -static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return 1; } +static inline bool snd_hdac_is_in_pm(struct hdac_device *codec) { return false; } +static inline bool snd_hdac_is_power_on(struct hdac_device *codec) { return true; } #endif /* @@ -241,6 +244,8 @@ struct hdac_bus_ops { /* get a response from the last command */ int (*get_response)(struct hdac_bus *bus, unsigned int addr, unsigned int *res); + /* notify of codec link power-up/down */ + void (*link_power)(struct hdac_device *hdev, bool enable); }; /* @@ -347,6 +352,9 @@ struct hdac_bus { int bdl_pos_adj; /* BDL position adjustment */ + /* delay time in us for dma stop */ + unsigned int dma_stop_delay; + /* locks */ spinlock_t reg_lock; struct mutex cmd_mutex; @@ -364,26 +372,19 @@ struct hdac_bus { /* link management */ struct list_head hlink_list; bool cmd_dma_state; + + /* factor used to derive STRIPE control value */ + unsigned int sdo_limit; }; int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_bus_ops *ops); void snd_hdac_bus_exit(struct hdac_bus *bus); -int snd_hdac_bus_exec_verb(struct hdac_bus *bus, unsigned int addr, - unsigned int cmd, unsigned int *res); int snd_hdac_bus_exec_verb_unlocked(struct hdac_bus *bus, unsigned int addr, unsigned int cmd, unsigned int *res); -void snd_hdac_bus_queue_event(struct hdac_bus *bus, u32 res, u32 res_ex); -static inline void snd_hdac_codec_link_up(struct hdac_device *codec) -{ - set_bit(codec->addr, &codec->bus->codec_powered); -} - -static inline void snd_hdac_codec_link_down(struct hdac_device *codec) -{ - clear_bit(codec->addr, &codec->bus->codec_powered); -} +void snd_hdac_codec_link_up(struct hdac_device *codec); +void snd_hdac_codec_link_down(struct hdac_device *codec); int snd_hdac_bus_send_cmd(struct hdac_bus *bus, unsigned int val); int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr, @@ -397,6 +398,7 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus); void snd_hdac_bus_enter_link_reset(struct hdac_bus *bus); void snd_hdac_bus_exit_link_reset(struct hdac_bus *bus); int snd_hdac_bus_reset_link(struct hdac_bus *bus, bool full_reset); +void snd_hdac_bus_link_power(struct hdac_device *hdev, bool enable); void snd_hdac_bus_update_rirb(struct hdac_bus *bus); int snd_hdac_bus_handle_stream_irq(struct hdac_bus *bus, unsigned int status, @@ -449,6 +451,8 @@ static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr) #define snd_hdac_reg_writel(bus, addr, val) writel(val, addr) #define snd_hdac_reg_readl(bus, addr) readl(addr) +#define snd_hdac_reg_writeq(bus, addr, val) writeq(val, addr) +#define snd_hdac_reg_readq(bus, addr) readq(addr) /* * macros for easy use @@ -513,6 +517,7 @@ struct hdac_stream { struct snd_pcm_substream *substream; /* assigned substream, * set in PCM open */ + struct snd_compr_stream *cstream; unsigned int format_val; /* format value to be set in the * controller and the codec */ @@ -527,6 +532,7 @@ struct hdac_stream { bool locked:1; bool stripe:1; /* apply stripe control */ + u64 curr_pos; /* timestamp */ unsigned long start_wallclk; /* start + minimum wallclk */ unsigned long period_wallclk; /* wallclk for period */ @@ -545,6 +551,7 @@ void snd_hdac_stream_init(struct hdac_bus *bus, struct hdac_stream *azx_dev, int idx, int direction, int tag); struct hdac_stream *snd_hdac_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream); +void snd_hdac_stream_release_locked(struct hdac_stream *azx_dev); void snd_hdac_stream_release(struct hdac_stream *azx_dev); struct hdac_stream *snd_hdac_get_stream(struct hdac_bus *bus, int dir, int stream_tag); @@ -555,8 +562,9 @@ int snd_hdac_stream_setup_periods(struct hdac_stream *azx_dev); int snd_hdac_stream_set_params(struct hdac_stream *azx_dev, unsigned int format_val); void snd_hdac_stream_start(struct hdac_stream *azx_dev, bool fresh_start); -void snd_hdac_stream_clear(struct hdac_stream *azx_dev); void snd_hdac_stream_stop(struct hdac_stream *azx_dev); +void snd_hdac_stop_streams(struct hdac_bus *bus); +void snd_hdac_stop_streams_and_chip(struct hdac_bus *bus); void snd_hdac_stream_reset(struct hdac_stream *azx_dev); void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set, unsigned int streams, unsigned int reg); @@ -583,6 +591,12 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus, snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) #define snd_hdac_stream_readb(dev, reg) \ snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) +#define snd_hdac_stream_readb_poll(dev, reg, val, cond, delay_us, timeout_us) \ + read_poll_timeout_atomic(snd_hdac_reg_readb, val, cond, delay_us, timeout_us, \ + false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) +#define snd_hdac_stream_readl_poll(dev, reg, val, cond, delay_us, timeout_us) \ + read_poll_timeout_atomic(snd_hdac_reg_readl, val, cond, delay_us, timeout_us, \ + false, (dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg) /* update a register, pass without AZX_REG_ prefix */ #define snd_hdac_stream_updatel(dev, reg, mask, val) \ diff --git a/include/sound/hdaudio_ext.h b/include/sound/hdaudio_ext.h index ef88b20c7b0a..83aed26ab143 100644 --- a/include/sound/hdaudio_ext.h +++ b/include/sound/hdaudio_ext.h @@ -2,6 +2,8 @@ #ifndef __SOUND_HDAUDIO_EXT_H #define __SOUND_HDAUDIO_EXT_H +#include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/iopoll.h> #include <sound/hdaudio.h> int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, @@ -9,9 +11,6 @@ int snd_hdac_ext_bus_init(struct hdac_bus *bus, struct device *dev, const struct hdac_ext_bus_ops *ext_ops); void snd_hdac_ext_bus_exit(struct hdac_bus *bus); -int snd_hdac_ext_bus_device_init(struct hdac_bus *bus, int addr, - struct hdac_device *hdev); -void snd_hdac_ext_bus_device_exit(struct hdac_device *hdev); void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus); #define HDA_CODEC_REV_EXT_ENTRY(_vid, _rev, _name, drv_data) \ @@ -28,6 +27,7 @@ void snd_hdac_ext_stream_spbcap_enable(struct hdac_bus *chip, bool enable, int index); int snd_hdac_ext_bus_get_ml_capabilities(struct hdac_bus *bus); +struct hdac_ext_link *snd_hdac_ext_bus_link_at(struct hdac_bus *bus, int addr); struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus, const char *codec_name); @@ -51,7 +51,7 @@ enum hdac_ext_stream_type { * @decoupled: stream host and link is decoupled * @link_locked: link is locked * @link_prepared: link is prepared - * link_substream: link substream + * @link_substream: link substream */ struct hdac_ext_stream { struct hdac_stream hstream; @@ -77,35 +77,33 @@ struct hdac_ext_stream { #define stream_to_hdac_ext_stream(s) \ container_of(s, struct hdac_ext_stream, hstream) -void snd_hdac_ext_stream_init(struct hdac_bus *bus, - struct hdac_ext_stream *stream, int idx, - int direction, int tag); int snd_hdac_ext_stream_init_all(struct hdac_bus *bus, int start_idx, - int num_stream, int dir); -void snd_hdac_stream_free_all(struct hdac_bus *bus); + int num_stream, int dir); +void snd_hdac_ext_stream_free_all(struct hdac_bus *bus); void snd_hdac_link_free_all(struct hdac_bus *bus); struct hdac_ext_stream *snd_hdac_ext_stream_assign(struct hdac_bus *bus, struct snd_pcm_substream *substream, int type); -void snd_hdac_ext_stream_release(struct hdac_ext_stream *azx_dev, int type); +void snd_hdac_ext_stream_release(struct hdac_ext_stream *hext_stream, int type); +void snd_hdac_ext_stream_decouple_locked(struct hdac_bus *bus, + struct hdac_ext_stream *hext_stream, bool decouple); void snd_hdac_ext_stream_decouple(struct hdac_bus *bus, struct hdac_ext_stream *azx_dev, bool decouple); -void snd_hdac_ext_stop_streams(struct hdac_bus *bus); int snd_hdac_ext_stream_set_spib(struct hdac_bus *bus, - struct hdac_ext_stream *stream, u32 value); + struct hdac_ext_stream *hext_stream, u32 value); int snd_hdac_ext_stream_get_spbmaxfifo(struct hdac_bus *bus, - struct hdac_ext_stream *stream); + struct hdac_ext_stream *hext_stream); void snd_hdac_ext_stream_drsm_enable(struct hdac_bus *bus, bool enable, int index); int snd_hdac_ext_stream_set_dpibr(struct hdac_bus *bus, - struct hdac_ext_stream *stream, u32 value); -int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *stream, u32 value); + struct hdac_ext_stream *hext_stream, u32 value); +int snd_hdac_ext_stream_set_lpib(struct hdac_ext_stream *hext_stream, u32 value); -void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hstream); -void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hstream); -void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hstream); -int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *stream, int fmt); +void snd_hdac_ext_link_stream_start(struct hdac_ext_stream *hext_stream); +void snd_hdac_ext_link_stream_clear(struct hdac_ext_stream *hext_stream); +void snd_hdac_ext_link_stream_reset(struct hdac_ext_stream *hext_stream); +int snd_hdac_ext_link_stream_setup(struct hdac_ext_stream *hext_stream, int fmt); struct hdac_ext_link { struct hdac_bus *bus; @@ -131,6 +129,8 @@ void snd_hdac_ext_link_clear_stream_id(struct hdac_ext_link *link, int snd_hdac_ext_bus_link_get(struct hdac_bus *bus, struct hdac_ext_link *link); int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link); +void snd_hdac_ext_bus_link_power(struct hdac_device *codec, bool enable); + /* update register macro */ #define snd_hdac_updatel(addr, reg, mask, val) \ writel(((readl(addr + reg) & ~(mask)) | (val)), \ @@ -140,6 +140,48 @@ int snd_hdac_ext_bus_link_put(struct hdac_bus *bus, struct hdac_ext_link *link); writew(((readw(addr + reg) & ~(mask)) | (val)), \ addr + reg) +#define snd_hdac_adsp_writeb(chip, reg, value) \ + snd_hdac_reg_writeb(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readb(chip, reg) \ + snd_hdac_reg_readb(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writew(chip, reg, value) \ + snd_hdac_reg_writew(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readw(chip, reg) \ + snd_hdac_reg_readw(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writel(chip, reg, value) \ + snd_hdac_reg_writel(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readl(chip, reg) \ + snd_hdac_reg_readl(chip, (chip)->dsp_ba + (reg)) +#define snd_hdac_adsp_writeq(chip, reg, value) \ + snd_hdac_reg_writeq(chip, (chip)->dsp_ba + (reg), value) +#define snd_hdac_adsp_readq(chip, reg) \ + snd_hdac_reg_readq(chip, (chip)->dsp_ba + (reg)) + +#define snd_hdac_adsp_updateb(chip, reg, mask, val) \ + snd_hdac_adsp_writeb(chip, reg, \ + (snd_hdac_adsp_readb(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updatew(chip, reg, mask, val) \ + snd_hdac_adsp_writew(chip, reg, \ + (snd_hdac_adsp_readw(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updatel(chip, reg, mask, val) \ + snd_hdac_adsp_writel(chip, reg, \ + (snd_hdac_adsp_readl(chip, reg) & ~(mask)) | (val)) +#define snd_hdac_adsp_updateq(chip, reg, mask, val) \ + snd_hdac_adsp_writeq(chip, reg, \ + (snd_hdac_adsp_readq(chip, reg) & ~(mask)) | (val)) + +#define snd_hdac_adsp_readb_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readb_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readw_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readw_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readl_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readl_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) +#define snd_hdac_adsp_readq_poll(chip, reg, val, cond, delay_us, timeout_us) \ + readq_poll_timeout((chip)->dsp_ba + (reg), val, cond, \ + delay_us, timeout_us) struct hdac_ext_device; diff --git a/include/sound/hdmi-codec.h b/include/sound/hdmi-codec.h index 83b17682e01c..48ad33aba393 100644 --- a/include/sound/hdmi-codec.h +++ b/include/sound/hdmi-codec.h @@ -2,7 +2,7 @@ /* * hdmi-codec.h - HDMI Codec driver API * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha <jsarha@ti.com> */ @@ -32,8 +32,13 @@ struct hdmi_codec_daifmt { } fmt; unsigned int bit_clk_inv:1; unsigned int frame_clk_inv:1; - unsigned int bit_clk_master:1; - unsigned int frame_clk_master:1; + unsigned int bit_clk_provider:1; + unsigned int frame_clk_provider:1; + /* bit_fmt could be standard PCM format or + * IEC958 encoded format. ALSA IEC958 plugin will pass + * IEC958_SUBFRAME format to the underneath driver. + */ + snd_pcm_format_t bit_fmt; }; /* @@ -60,13 +65,23 @@ struct hdmi_codec_ops { /* * Configures HDMI-encoder for audio stream. - * Mandatory + * Having either prepare or hw_params is mandatory. */ int (*hw_params)(struct device *dev, void *data, struct hdmi_codec_daifmt *fmt, struct hdmi_codec_params *hparms); /* + * Configures HDMI-encoder for audio stream. Can be called + * multiple times for each setup. + * + * Having either prepare or hw_params is mandatory. + */ + int (*prepare)(struct device *dev, void *data, + struct hdmi_codec_daifmt *fmt, + struct hdmi_codec_params *hparms); + + /* * Shuts down the audio stream. * Mandatory */ @@ -76,7 +91,8 @@ struct hdmi_codec_ops { * Mute/unmute HDMI audio stream. * Optional */ - int (*digital_mute)(struct device *dev, void *data, bool enable); + int (*mute_stream)(struct device *dev, void *data, + bool enable, int direction); /* * Provides EDID-Like-Data from connected HDMI device. @@ -99,6 +115,9 @@ struct hdmi_codec_ops { int (*hook_plugged_cb)(struct device *dev, void *data, hdmi_codec_plugged_cb fn, struct device *codec_dev); + + /* bit field */ + unsigned int no_capture_mute:1; }; /* HDMI codec initalization data */ @@ -113,9 +132,6 @@ struct hdmi_codec_pdata { struct snd_soc_component; struct snd_soc_jack; -int hdmi_codec_set_jack_detect(struct snd_soc_component *component, - struct snd_soc_jack *jack); - #define HDMI_CODEC_DRV_NAME "hdmi-audio-codec" #endif /* __HDMI_CODEC_H__ */ diff --git a/include/sound/intel-dsp-config.h b/include/sound/intel-dsp-config.h index c36622bee3f8..34c975910574 100644 --- a/include/sound/intel-dsp-config.h +++ b/include/sound/intel-dsp-config.h @@ -15,12 +15,14 @@ enum { SND_INTEL_DSP_DRIVER_LEGACY, SND_INTEL_DSP_DRIVER_SST, SND_INTEL_DSP_DRIVER_SOF, - SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_SOF + SND_INTEL_DSP_DRIVER_AVS, + SND_INTEL_DSP_DRIVER_LAST = SND_INTEL_DSP_DRIVER_AVS }; #if IS_ENABLED(CONFIG_SND_INTEL_DSP_CONFIG) int snd_intel_dsp_driver_probe(struct pci_dev *pci); +int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]); #else @@ -29,6 +31,12 @@ static inline int snd_intel_dsp_driver_probe(struct pci_dev *pci) return SND_INTEL_DSP_DRIVER_ANY; } +static inline +int snd_intel_acpi_dsp_driver_probe(struct device *dev, const u8 acpi_hid[ACPI_ID_LEN]) +{ + return SND_INTEL_DSP_DRIVER_ANY; +} + #endif #endif diff --git a/include/sound/intel-nhlt.h b/include/sound/intel-nhlt.h index f657fd8fc0ad..53470d6a28d6 100644 --- a/include/sound/intel-nhlt.h +++ b/include/sound/intel-nhlt.h @@ -10,7 +10,20 @@ #include <linux/acpi.h> -#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) +enum nhlt_link_type { + NHLT_LINK_HDA = 0, + NHLT_LINK_DSP = 1, + NHLT_LINK_DMIC = 2, + NHLT_LINK_SSP = 3, + NHLT_LINK_INVALID +}; + +enum nhlt_device_type { + NHLT_DEVICE_BT = 0, + NHLT_DEVICE_DMIC = 1, + NHLT_DEVICE_I2S = 4, + NHLT_DEVICE_INVALID +}; struct wav_fmt { u16 fmt_tag; @@ -33,24 +46,9 @@ struct wav_fmt_ext { u8 sub_fmt[16]; } __packed; -enum nhlt_link_type { - NHLT_LINK_HDA = 0, - NHLT_LINK_DSP = 1, - NHLT_LINK_DMIC = 2, - NHLT_LINK_SSP = 3, - NHLT_LINK_INVALID -}; - -enum nhlt_device_type { - NHLT_DEVICE_BT = 0, - NHLT_DEVICE_DMIC = 1, - NHLT_DEVICE_I2S = 4, - NHLT_DEVICE_INVALID -}; - struct nhlt_specific_cfg { u32 size; - u8 caps[0]; + u8 caps[]; } __packed; struct nhlt_fmt_cfg { @@ -60,7 +58,7 @@ struct nhlt_fmt_cfg { struct nhlt_fmt { u8 fmt_count; - struct nhlt_fmt_cfg fmt_config[0]; + struct nhlt_fmt_cfg fmt_config[]; } __packed; struct nhlt_endpoint { @@ -80,7 +78,7 @@ struct nhlt_endpoint { struct nhlt_acpi_table { struct acpi_table_header header; u8 endpoint_count; - struct nhlt_endpoint desc[0]; + struct nhlt_endpoint desc[]; } __packed; struct nhlt_resource_desc { @@ -113,6 +111,11 @@ struct nhlt_vendor_dmic_array_config { } __packed; enum { + NHLT_CONFIG_TYPE_GENERIC = 0, + NHLT_CONFIG_TYPE_MIC_ARRAY = 1 +}; + +enum { NHLT_MIC_ARRAY_2CH_SMALL = 0xa, NHLT_MIC_ARRAY_2CH_BIG = 0xb, NHLT_MIC_ARRAY_4CH_1ST_GEOM = 0xc, @@ -121,15 +124,26 @@ enum { NHLT_MIC_ARRAY_VENDOR_DEFINED = 0xf, }; +#if IS_ENABLED(CONFIG_ACPI) && IS_ENABLED(CONFIG_SND_INTEL_NHLT) + struct nhlt_acpi_table *intel_nhlt_init(struct device *dev); void intel_nhlt_free(struct nhlt_acpi_table *addr); int intel_nhlt_get_dmic_geo(struct device *dev, struct nhlt_acpi_table *nhlt); -#else +bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, u8 link_type); + +int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type); -struct nhlt_acpi_table; +int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num); + +struct nhlt_specific_cfg * +intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, + u32 bus_id, u8 link_type, u8 vbps, u8 bps, + u8 num_ch, u32 rate, u8 dir, u8 dev_type); + +#else static inline struct nhlt_acpi_table *intel_nhlt_init(struct device *dev) { @@ -145,6 +159,31 @@ static inline int intel_nhlt_get_dmic_geo(struct device *dev, { return 0; } + +static inline bool intel_nhlt_has_endpoint_type(struct nhlt_acpi_table *nhlt, + u8 link_type) +{ + return false; +} + +static inline int intel_nhlt_ssp_endpoint_mask(struct nhlt_acpi_table *nhlt, u8 device_type) +{ + return 0; +} + +static inline int intel_nhlt_ssp_mclk_mask(struct nhlt_acpi_table *nhlt, int ssp_num) +{ + return 0; +} + +static inline struct nhlt_specific_cfg * +intel_nhlt_get_endpoint_blob(struct device *dev, struct nhlt_acpi_table *nhlt, + u32 bus_id, u8 link_type, u8 vbps, u8 bps, + u8 num_ch, u32 rate, u8 dir, u8 dev_type) +{ + return NULL; +} + #endif #endif diff --git a/include/sound/jack.h b/include/sound/jack.h index 9eb2b5ec1ec4..1ed90e2109e9 100644 --- a/include/sound/jack.h +++ b/include/sound/jack.h @@ -62,11 +62,13 @@ struct snd_jack { const char *id; #ifdef CONFIG_SND_JACK_INPUT_DEV struct input_dev *input_dev; + struct mutex input_dev_lock; int registered; int type; char name[100]; unsigned int key[6]; /* Keep in sync with definitions above */ #endif /* CONFIG_SND_JACK_INPUT_DEV */ + int hw_status_cache; void *private_data; void (*private_free)(struct snd_jack *); }; diff --git a/include/sound/madera-pdata.h b/include/sound/madera-pdata.h index e3060f48f108..58398d80c3de 100644 --- a/include/sound/madera-pdata.h +++ b/include/sound/madera-pdata.h @@ -9,7 +9,7 @@ #ifndef MADERA_CODEC_PDATA_H #define MADERA_CODEC_PDATA_H -#include <linux/kernel.h> +#include <linux/types.h> #define MADERA_MAX_INPUT 6 #define MADERA_MAX_MUXED_CHANNELS 4 diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index 3b47832b1c1f..43d524580bd2 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h @@ -9,41 +9,50 @@ #ifndef __SOUND_MEMALLOC_H #define __SOUND_MEMALLOC_H +#include <linux/dma-direction.h> #include <asm/page.h> struct device; +struct vm_area_struct; +struct sg_table; /* * buffer device info */ struct snd_dma_device { int type; /* SNDRV_DMA_TYPE_XXX */ + enum dma_data_direction dir; /* DMA direction */ + bool need_sync; /* explicit sync needed? */ struct device *dev; /* generic device */ }; -#define snd_dma_continuous_data(x) ((struct device *)(__force unsigned long)(x)) - - /* * buffer types */ #define SNDRV_DMA_TYPE_UNKNOWN 0 /* not defined */ #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ -#define SNDRV_DMA_TYPE_DEV_UC 5 /* continuous non-cahced */ -#ifdef CONFIG_SND_DMA_SGBUF -#define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ -#define SNDRV_DMA_TYPE_DEV_UC_SG 6 /* SG non-cached */ -#else -#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ -#define SNDRV_DMA_TYPE_DEV_UC_SG SNDRV_DMA_TYPE_DEV_UC -#endif +#define SNDRV_DMA_TYPE_DEV_WC 5 /* continuous write-combined */ #ifdef CONFIG_GENERIC_ALLOCATOR #define SNDRV_DMA_TYPE_DEV_IRAM 4 /* generic device iram-buffer */ #else #define SNDRV_DMA_TYPE_DEV_IRAM SNDRV_DMA_TYPE_DEV #endif #define SNDRV_DMA_TYPE_VMALLOC 7 /* vmalloc'ed buffer */ +#define SNDRV_DMA_TYPE_NONCONTIG 8 /* non-coherent SG buffer */ +#define SNDRV_DMA_TYPE_NONCOHERENT 9 /* non-coherent buffer */ +#ifdef CONFIG_SND_DMA_SGBUF +#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_NONCONTIG +#define SNDRV_DMA_TYPE_DEV_WC_SG 6 /* SG write-combined */ +#else +#define SNDRV_DMA_TYPE_DEV_SG SNDRV_DMA_TYPE_DEV /* no SG-buf support */ +#define SNDRV_DMA_TYPE_DEV_WC_SG SNDRV_DMA_TYPE_DEV_WC +#endif +/* fallback types, don't use those directly */ +#ifdef CONFIG_SND_DMA_SGBUF +#define SNDRV_DMA_TYPE_DEV_SG_FALLBACK 10 +#define SNDRV_DMA_TYPE_DEV_WC_SG_FALLBACK 11 +#endif /* * info for buffer allocation @@ -64,77 +73,53 @@ static inline unsigned int snd_sgbuf_aligned_pages(size_t size) return (size + PAGE_SIZE - 1) >> PAGE_SHIFT; } -#ifdef CONFIG_SND_DMA_SGBUF -/* - * Scatter-Gather generic device pages - */ -void *snd_malloc_sgbuf_pages(struct device *device, - size_t size, struct snd_dma_buffer *dmab, - size_t *res_size); -int snd_free_sgbuf_pages(struct snd_dma_buffer *dmab); - -struct snd_sg_page { - void *buf; - dma_addr_t addr; -}; - -struct snd_sg_buf { - int size; /* allocated byte size */ - int pages; /* allocated pages */ - int tblsize; /* allocated table size */ - struct snd_sg_page *table; /* address table */ - struct page **page_table; /* page table (for vmap/vunmap) */ - struct device *dev; -}; +/* allocate/release a buffer */ +int snd_dma_alloc_dir_pages(int type, struct device *dev, + enum dma_data_direction dir, size_t size, + struct snd_dma_buffer *dmab); -/* - * return the physical address at the corresponding offset - */ -static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, - size_t offset) +static inline int snd_dma_alloc_pages(int type, struct device *dev, + size_t size, struct snd_dma_buffer *dmab) { - struct snd_sg_buf *sgbuf = dmab->private_data; - dma_addr_t addr = sgbuf->table[offset >> PAGE_SHIFT].addr; - addr &= ~((dma_addr_t)PAGE_SIZE - 1); - return addr + offset % PAGE_SIZE; + return snd_dma_alloc_dir_pages(type, dev, DMA_BIDIRECTIONAL, size, dmab); } -/* - * return the virtual address at the corresponding offset - */ -static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, - size_t offset) -{ - struct snd_sg_buf *sgbuf = dmab->private_data; - return sgbuf->table[offset >> PAGE_SHIFT].buf + offset % PAGE_SIZE; -} +int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size, + struct snd_dma_buffer *dmab); +void snd_dma_free_pages(struct snd_dma_buffer *dmab); +int snd_dma_buffer_mmap(struct snd_dma_buffer *dmab, + struct vm_area_struct *area); + +enum snd_dma_sync_mode { SNDRV_DMA_SYNC_CPU, SNDRV_DMA_SYNC_DEVICE }; +#ifdef CONFIG_HAS_DMA +void snd_dma_buffer_sync(struct snd_dma_buffer *dmab, + enum snd_dma_sync_mode mode); +#else +static inline void snd_dma_buffer_sync(struct snd_dma_buffer *dmab, + enum snd_dma_sync_mode mode) {} +#endif +dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, size_t offset); +struct page *snd_sgbuf_get_page(struct snd_dma_buffer *dmab, size_t offset); unsigned int snd_sgbuf_get_chunk_size(struct snd_dma_buffer *dmab, unsigned int ofs, unsigned int size); -#else -/* non-SG versions */ -static inline dma_addr_t snd_sgbuf_get_addr(struct snd_dma_buffer *dmab, - size_t offset) + +/* device-managed memory allocator */ +struct snd_dma_buffer *snd_devm_alloc_dir_pages(struct device *dev, int type, + enum dma_data_direction dir, + size_t size); + +static inline struct snd_dma_buffer * +snd_devm_alloc_pages(struct device *dev, int type, size_t size) { - return dmab->addr + offset; + return snd_devm_alloc_dir_pages(dev, type, DMA_BIDIRECTIONAL, size); } -static inline void *snd_sgbuf_get_ptr(struct snd_dma_buffer *dmab, - size_t offset) +static inline struct sg_table * +snd_dma_noncontig_sg_table(struct snd_dma_buffer *dmab) { - return dmab->area + offset; + return dmab->private_data; } -#define snd_sgbuf_get_chunk_size(dmab, ofs, size) (size) - -#endif /* CONFIG_SND_DMA_SGBUF */ - -/* allocate/release a buffer */ -int snd_dma_alloc_pages(int type, struct device *dev, size_t size, - struct snd_dma_buffer *dmab); -int snd_dma_alloc_pages_fallback(int type, struct device *dev, size_t size, - struct snd_dma_buffer *dmab); -void snd_dma_free_pages(struct snd_dma_buffer *dmab); - #endif /* __SOUND_MEMALLOC_H */ diff --git a/include/sound/omap-hdmi-audio.h b/include/sound/omap-hdmi-audio.h index 16c007b651f4..e5f82044a404 100644 --- a/include/sound/omap-hdmi-audio.h +++ b/include/sound/omap-hdmi-audio.h @@ -2,7 +2,7 @@ /* * hdmi-audio.c -- OMAP4+ DSS HDMI audio support library * - * Copyright (C) 2014 Texas Instruments Incorporated - http://www.ti.com + * Copyright (C) 2014 Texas Instruments Incorporated - https://www.ti.com * * Author: Jyri Sarha <jsarha@ti.com> */ diff --git a/include/sound/pcm.h b/include/sound/pcm.h index f657ff08f317..7b1a022910e8 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -147,6 +147,9 @@ struct snd_pcm_ops { #define SNDRV_PCM_FMTBIT_S24_BE _SNDRV_PCM_FMTBIT(S24_BE) #define SNDRV_PCM_FMTBIT_U24_LE _SNDRV_PCM_FMTBIT(U24_LE) #define SNDRV_PCM_FMTBIT_U24_BE _SNDRV_PCM_FMTBIT(U24_BE) +// For S32/U32 formats, 'msbits' hardware parameter is often used to deliver information about the +// available bit count in most significant bit. It's for the case of so-called 'left-justified' or +// `right-padding` sample which has less width than 32 bit. #define SNDRV_PCM_FMTBIT_S32_LE _SNDRV_PCM_FMTBIT(S32_LE) #define SNDRV_PCM_FMTBIT_S32_BE _SNDRV_PCM_FMTBIT(S32_BE) #define SNDRV_PCM_FMTBIT_U32_LE _SNDRV_PCM_FMTBIT(U32_LE) @@ -229,7 +232,7 @@ typedef int (*snd_pcm_hw_rule_func_t)(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule { unsigned int cond; int var; - int deps[4]; + int deps[5]; snd_pcm_hw_rule_func_t func; void *private; @@ -343,6 +346,8 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy struct snd_pcm_runtime { /* -- Status -- */ + snd_pcm_state_t state; /* stream state */ + snd_pcm_state_t suspended_state; /* suspended stream state */ struct snd_pcm_substream *trigger_master; struct timespec64 trigger_tstamp; /* trigger timestamp */ bool trigger_tstamp_latched; /* trigger timestamp latched in low-level driver/hardware */ @@ -396,8 +401,10 @@ struct snd_pcm_runtime { snd_pcm_uframes_t twake; /* do transfer (!poll) wakeup if non-zero */ wait_queue_head_t sleep; /* poll sleep */ wait_queue_head_t tsleep; /* transfer sleep */ - struct fasync_struct *fasync; + struct snd_fasync *fasync; bool stop_operating; /* sync_stop will be called */ + struct mutex buffer_mutex; /* protect for buffer changes */ + atomic_t buffer_accessing; /* >0: in r/w operation, <0: blocked */ /* -- private section -- */ void *private_data; @@ -602,7 +609,7 @@ snd_pcm_debug_name(struct snd_pcm_substream *substream, char *buf, size_t size) * snd_pcm_stream_linked - Check whether the substream is linked with others * @substream: substream to check * - * Returns true if the given substream is being linked with others. + * Return: true if the given substream is being linked with others */ static inline int snd_pcm_stream_linked(struct snd_pcm_substream *substream) { @@ -614,6 +621,7 @@ void snd_pcm_stream_unlock(struct snd_pcm_substream *substream); void snd_pcm_stream_lock_irq(struct snd_pcm_substream *substream); void snd_pcm_stream_unlock_irq(struct snd_pcm_substream *substream); unsigned long _snd_pcm_stream_lock_irqsave(struct snd_pcm_substream *substream); +unsigned long _snd_pcm_stream_lock_irqsave_nested(struct snd_pcm_substream *substream); /** * snd_pcm_stream_lock_irqsave - Lock the PCM stream @@ -633,6 +641,20 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, unsigned long flags); /** + * snd_pcm_stream_lock_irqsave_nested - Single-nested PCM stream locking + * @substream: PCM substream + * @flags: irq flags + * + * This locks the PCM stream like snd_pcm_stream_lock_irqsave() but with + * the single-depth lockdep subclass. + */ +#define snd_pcm_stream_lock_irqsave_nested(substream, flags) \ + do { \ + typecheck(unsigned long, flags); \ + flags = _snd_pcm_stream_lock_irqsave_nested(substream); \ + } while (0) + +/** * snd_pcm_group_for_each_entry - iterate over the linked substreams * @s: the iterator * @substream: the substream @@ -644,24 +666,45 @@ void snd_pcm_stream_unlock_irqrestore(struct snd_pcm_substream *substream, #define snd_pcm_group_for_each_entry(s, substream) \ list_for_each_entry(s, &substream->group->substreams, link_list) +#define for_each_pcm_streams(stream) \ + for (stream = SNDRV_PCM_STREAM_PLAYBACK; \ + stream <= SNDRV_PCM_STREAM_LAST; \ + stream++) + /** * snd_pcm_running - Check whether the substream is in a running state * @substream: substream to check * - * Returns true if the given substream is in the state RUNNING, or in the + * Return: true if the given substream is in the state RUNNING, or in the * state DRAINING for playback. */ static inline int snd_pcm_running(struct snd_pcm_substream *substream) { - return (substream->runtime->status->state == SNDRV_PCM_STATE_RUNNING || - (substream->runtime->status->state == SNDRV_PCM_STATE_DRAINING && + return (substream->runtime->state == SNDRV_PCM_STATE_RUNNING || + (substream->runtime->state == SNDRV_PCM_STATE_DRAINING && substream->stream == SNDRV_PCM_STREAM_PLAYBACK)); } /** + * __snd_pcm_set_state - Change the current PCM state + * @runtime: PCM runtime to set + * @state: the current state to set + * + * Call within the stream lock + */ +static inline void __snd_pcm_set_state(struct snd_pcm_runtime *runtime, + snd_pcm_state_t state) +{ + runtime->state = state; + runtime->status->state = state; /* copy for mmap */ +} + +/** * bytes_to_samples - Unit conversion of the size from bytes to samples * @runtime: PCM runtime instance * @size: size in bytes + * + * Return: the size in samples */ static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t size) { @@ -672,6 +715,8 @@ static inline ssize_t bytes_to_samples(struct snd_pcm_runtime *runtime, ssize_t * bytes_to_frames - Unit conversion of the size from bytes to frames * @runtime: PCM runtime instance * @size: size in bytes + * + * Return: the size in frames */ static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, ssize_t size) { @@ -682,6 +727,8 @@ static inline snd_pcm_sframes_t bytes_to_frames(struct snd_pcm_runtime *runtime, * samples_to_bytes - Unit conversion of the size from samples to bytes * @runtime: PCM runtime instance * @size: size in samples + * + * Return: the byte size */ static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t size) { @@ -692,6 +739,8 @@ static inline ssize_t samples_to_bytes(struct snd_pcm_runtime *runtime, ssize_t * frames_to_bytes - Unit conversion of the size from frames to bytes * @runtime: PCM runtime instance * @size: size in frames + * + * Return: the byte size */ static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_sframes_t size) { @@ -702,6 +751,8 @@ static inline ssize_t frames_to_bytes(struct snd_pcm_runtime *runtime, snd_pcm_s * frame_aligned - Check whether the byte size is aligned to frames * @runtime: PCM runtime instance * @bytes: size in bytes + * + * Return: true if aligned, or false if not */ static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes) { @@ -711,6 +762,8 @@ static inline int frame_aligned(struct snd_pcm_runtime *runtime, ssize_t bytes) /** * snd_pcm_lib_buffer_bytes - Get the buffer size of the current PCM in bytes * @substream: PCM substream + * + * Return: buffer byte size */ static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substream) { @@ -721,6 +774,8 @@ static inline size_t snd_pcm_lib_buffer_bytes(struct snd_pcm_substream *substrea /** * snd_pcm_lib_period_bytes - Get the period size of the current PCM in bytes * @substream: PCM substream + * + * Return: period byte size */ static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substream) { @@ -733,6 +788,8 @@ static inline size_t snd_pcm_lib_period_bytes(struct snd_pcm_substream *substrea * @runtime: PCM runtime instance * * Result is between 0 ... (boundary - 1) + * + * Return: available frame size */ static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *runtime) { @@ -749,6 +806,8 @@ static inline snd_pcm_uframes_t snd_pcm_playback_avail(struct snd_pcm_runtime *r * @runtime: PCM runtime instance * * Result is between 0 ... (boundary - 1) + * + * Return: available frame size */ static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *runtime) { @@ -761,6 +820,8 @@ static inline snd_pcm_uframes_t snd_pcm_capture_avail(struct snd_pcm_runtime *ru /** * snd_pcm_playback_hw_avail - Get the queued space for playback * @runtime: PCM runtime instance + * + * Return: available frame size */ static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime *runtime) { @@ -770,6 +831,8 @@ static inline snd_pcm_sframes_t snd_pcm_playback_hw_avail(struct snd_pcm_runtime /** * snd_pcm_capture_hw_avail - Get the free space for capture * @runtime: PCM runtime instance + * + * Return: available frame size */ static inline snd_pcm_sframes_t snd_pcm_capture_hw_avail(struct snd_pcm_runtime *runtime) { @@ -909,6 +972,8 @@ static inline const struct snd_interval *hw_param_interval_c(const struct snd_pc /** * params_channels - Get the number of channels from the hw params * @p: hw params + * + * Return: the number of channels */ static inline unsigned int params_channels(const struct snd_pcm_hw_params *p) { @@ -918,6 +983,8 @@ static inline unsigned int params_channels(const struct snd_pcm_hw_params *p) /** * params_rate - Get the sample rate from the hw params * @p: hw params + * + * Return: the sample rate */ static inline unsigned int params_rate(const struct snd_pcm_hw_params *p) { @@ -927,6 +994,8 @@ static inline unsigned int params_rate(const struct snd_pcm_hw_params *p) /** * params_period_size - Get the period size (in frames) from the hw params * @p: hw params + * + * Return: the period size in frames */ static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p) { @@ -936,6 +1005,8 @@ static inline unsigned int params_period_size(const struct snd_pcm_hw_params *p) /** * params_periods - Get the number of periods from the hw params * @p: hw params + * + * Return: the number of periods */ static inline unsigned int params_periods(const struct snd_pcm_hw_params *p) { @@ -945,6 +1016,8 @@ static inline unsigned int params_periods(const struct snd_pcm_hw_params *p) /** * params_buffer_size - Get the buffer size (in frames) from the hw params * @p: hw params + * + * Return: the buffer size in frames */ static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p) { @@ -954,6 +1027,8 @@ static inline unsigned int params_buffer_size(const struct snd_pcm_hw_params *p) /** * params_buffer_bytes - Get the buffer size (in bytes) from the hw params * @p: hw params + * + * Return: the buffer size in bytes */ static inline unsigned int params_buffer_bytes(const struct snd_pcm_hw_params *p) { @@ -1061,6 +1136,7 @@ void snd_pcm_set_ops(struct snd_pcm * pcm, int direction, void snd_pcm_set_sync(struct snd_pcm_substream *substream); int snd_pcm_lib_ioctl(struct snd_pcm_substream *substream, unsigned int cmd, void *arg); +void snd_pcm_period_elapsed_under_stream_lock(struct snd_pcm_substream *substream); void snd_pcm_period_elapsed(struct snd_pcm_substream *substream); snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream, void *buf, bool interleaved, @@ -1122,7 +1198,14 @@ snd_pcm_kernel_readv(struct snd_pcm_substream *substream, return __snd_pcm_lib_xfer(substream, bufs, false, frames, true); } -int snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime); +int snd_pcm_hw_limit_rates(struct snd_pcm_hardware *hw); + +static inline int +snd_pcm_limit_hw_rates(struct snd_pcm_runtime *runtime) +{ + return snd_pcm_hw_limit_rates(&runtime->hw); +} + unsigned int snd_pcm_rate_to_rate_bit(unsigned int rate); unsigned int snd_pcm_rate_bit_to_rate(unsigned int rate_bit); unsigned int snd_pcm_rate_mask_intersect(unsigned int rates_a, @@ -1191,11 +1274,52 @@ void snd_pcm_lib_preallocate_pages_for_all(struct snd_pcm *pcm, int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size); int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream); -void snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type, - struct device *data, size_t size, size_t max); -void snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type, - struct device *data, - size_t size, size_t max); +int snd_pcm_set_managed_buffer(struct snd_pcm_substream *substream, int type, + struct device *data, size_t size, size_t max); +int snd_pcm_set_managed_buffer_all(struct snd_pcm *pcm, int type, + struct device *data, + size_t size, size_t max); + +/** + * snd_pcm_set_fixed_buffer - Preallocate and set up the fixed size PCM buffer + * @substream: the pcm substream instance + * @type: DMA type (SNDRV_DMA_TYPE_*) + * @data: DMA type dependent data + * @size: the requested pre-allocation size in bytes + * + * This is a variant of snd_pcm_set_managed_buffer(), but this pre-allocates + * only the given sized buffer and doesn't allow re-allocation nor dynamic + * allocation of a larger buffer unlike the standard one. + * The function may return -ENOMEM error, hence the caller must check it. + * + * Return: zero if successful, or a negative error code + */ +static inline int __must_check +snd_pcm_set_fixed_buffer(struct snd_pcm_substream *substream, int type, + struct device *data, size_t size) +{ + return snd_pcm_set_managed_buffer(substream, type, data, size, 0); +} + +/** + * snd_pcm_set_fixed_buffer_all - Preallocate and set up the fixed size PCM buffer + * @pcm: the pcm instance + * @type: DMA type (SNDRV_DMA_TYPE_*) + * @data: DMA type dependent data + * @size: the requested pre-allocation size in bytes + * + * Apply the set up of the fixed buffer via snd_pcm_set_fixed_buffer() for + * all substream. If any of allocation fails, it returns -ENOMEM, hence the + * caller must check the return value. + * + * Return: zero if successful, or a negative error code + */ +static inline int __must_check +snd_pcm_set_fixed_buffer_all(struct snd_pcm *pcm, int type, + struct device *data, size_t size) +{ + return snd_pcm_set_managed_buffer_all(pcm, type, data, size, 0); +} int _snd_pcm_lib_alloc_vmalloc_buffer(struct snd_pcm_substream *substream, size_t size, gfp_t gfp_flags); @@ -1241,18 +1365,12 @@ static inline int snd_pcm_lib_alloc_vmalloc_32_buffer #define snd_pcm_get_dma_buf(substream) ((substream)->runtime->dma_buffer_p) -#ifdef CONFIG_SND_DMA_SGBUF -/* - * SG-buffer handling - */ -#define snd_pcm_substream_sgbuf(substream) \ - snd_pcm_get_dma_buf(substream)->private_data -#endif /* SND_DMA_SGBUF */ - /** * snd_pcm_sgbuf_get_addr - Get the DMA address at the corresponding offset * @substream: PCM substream * @ofs: byte offset + * + * Return: DMA address */ static inline dma_addr_t snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) @@ -1261,22 +1379,13 @@ snd_pcm_sgbuf_get_addr(struct snd_pcm_substream *substream, unsigned int ofs) } /** - * snd_pcm_sgbuf_get_ptr - Get the virtual address at the corresponding offset - * @substream: PCM substream - * @ofs: byte offset - */ -static inline void * -snd_pcm_sgbuf_get_ptr(struct snd_pcm_substream *substream, unsigned int ofs) -{ - return snd_sgbuf_get_ptr(snd_pcm_get_dma_buf(substream), ofs); -} - -/** - * snd_pcm_sgbuf_chunk_size - Compute the max size that fits within the contig. - * page from the given size + * snd_pcm_sgbuf_get_chunk_size - Compute the max size that fits within the + * contig. page from the given size * @substream: PCM substream * @ofs: byte offset * @size: byte size to examine + * + * Return: chunk size */ static inline unsigned int snd_pcm_sgbuf_get_chunk_size(struct snd_pcm_substream *substream, @@ -1342,6 +1451,20 @@ static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max) const char *snd_pcm_format_name(snd_pcm_format_t format); /** + * snd_pcm_direction_name - Get a string naming the direction of a stream + * @direction: Stream's direction, one of SNDRV_PCM_STREAM_XXX + * + * Returns a string naming the direction of the stream. + */ +static inline const char *snd_pcm_direction_name(int direction) +{ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + return "Playback"; + else + return "Capture"; +} + +/** * snd_pcm_stream_str - Get a string naming the direction of a stream * @substream: the pcm substream instance * @@ -1349,10 +1472,7 @@ const char *snd_pcm_format_name(snd_pcm_format_t format); */ static inline const char *snd_pcm_stream_str(struct snd_pcm_substream *substream) { - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) - return "Playback"; - else - return "Capture"; + return snd_pcm_direction_name(substream->stream); } /* @@ -1379,6 +1499,8 @@ struct snd_pcm_chmap { * snd_pcm_chmap_substream - get the PCM substream assigned to the given chmap info * @info: chmap information * @idx: the substream number index + * + * Return: the matched PCM substream, or NULL if not found */ static inline struct snd_pcm_substream * snd_pcm_chmap_substream(struct snd_pcm_chmap *info, unsigned int idx) @@ -1409,12 +1531,23 @@ int snd_pcm_add_chmap_ctls(struct snd_pcm *pcm, int stream, /** * pcm_format_to_bits - Strong-typed conversion of pcm_format to bitwise * @pcm_format: PCM format + * + * Return: 64bit mask corresponding to the given PCM format */ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format) { return 1ULL << (__force int) pcm_format; } +/** + * pcm_for_each_format - helper to iterate for each format type + * @f: the iterator variable in snd_pcm_format_t type + */ +#define pcm_for_each_format(f) \ + for ((f) = SNDRV_PCM_FORMAT_FIRST; \ + (__force int)(f) <= (__force int)SNDRV_PCM_FORMAT_LAST; \ + (f) = (__force snd_pcm_format_t)((__force int)(f) + 1)) + /* printk helpers */ #define pcm_err(pcm, fmt, args...) \ dev_err((pcm)->card->dev, fmt, ##args) diff --git a/include/sound/pcm_iec958.h b/include/sound/pcm_iec958.h index 0939aa45e2fe..64e84441cde1 100644 --- a/include/sound/pcm_iec958.h +++ b/include/sound/pcm_iec958.h @@ -4,6 +4,14 @@ #include <linux/types.h> +int snd_pcm_create_iec958_consumer_default(u8 *cs, size_t len); + +int snd_pcm_fill_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, + size_t len); + +int snd_pcm_fill_iec958_consumer_hw_params(struct snd_pcm_hw_params *params, + u8 *cs, size_t len); + int snd_pcm_create_iec958_consumer(struct snd_pcm_runtime *runtime, u8 *cs, size_t len); diff --git a/include/sound/pcm_params.h b/include/sound/pcm_params.h index 661450a2095b..ba184f49f7e1 100644 --- a/include/sound/pcm_params.h +++ b/include/sound/pcm_params.h @@ -23,11 +23,6 @@ int snd_pcm_hw_param_value(const struct snd_pcm_hw_params *params, #define MASK_OFS(i) ((i) >> 5) #define MASK_BIT(i) (1U << ((i) & 31)) -static inline size_t snd_mask_sizeof(void) -{ - return sizeof(struct snd_mask); -} - static inline void snd_mask_none(struct snd_mask *mask) { memset(mask, 0, sizeof(*mask)); @@ -133,6 +128,13 @@ static inline int snd_mask_test(const struct snd_mask *mask, unsigned int val) return mask->bits[MASK_OFS(val)] & MASK_BIT(val); } +/* Most of drivers need only this one */ +static inline int snd_mask_test_format(const struct snd_mask *mask, + snd_pcm_format_t format) +{ + return snd_mask_test(mask, (__force unsigned int)format); +} + static inline int snd_mask_single(const struct snd_mask *mask) { int i, c = 0; diff --git a/include/sound/pxa2xx-lib.h b/include/sound/pxa2xx-lib.h index 0feaf16e6ac0..0a6f8dabf8c4 100644 --- a/include/sound/pxa2xx-lib.h +++ b/include/sound/pxa2xx-lib.h @@ -14,18 +14,12 @@ struct snd_soc_component; extern int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -extern int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream); extern int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd); extern snd_pcm_uframes_t pxa2xx_pcm_pointer(struct snd_pcm_substream *substream); extern int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream); extern int pxa2xx_pcm_open(struct snd_pcm_substream *substream); extern int pxa2xx_pcm_close(struct snd_pcm_substream *substream); -extern int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream, - struct vm_area_struct *vma); -extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream); -extern void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm); -extern void pxa2xx_soc_pcm_free(struct snd_soc_component *component, - struct snd_pcm *pcm); +extern int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm); extern int pxa2xx_soc_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd); extern int pxa2xx_soc_pcm_open(struct snd_soc_component *component, @@ -35,8 +29,6 @@ extern int pxa2xx_soc_pcm_close(struct snd_soc_component *component, extern int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); -extern int pxa2xx_soc_pcm_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream); extern int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component, struct snd_pcm_substream *substream); extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component, @@ -44,9 +36,6 @@ extern int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component, extern snd_pcm_uframes_t pxa2xx_soc_pcm_pointer(struct snd_soc_component *component, struct snd_pcm_substream *substream); -extern int pxa2xx_soc_pcm_mmap(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct vm_area_struct *vma); /* AC97 */ @@ -63,4 +52,8 @@ extern int pxa2xx_ac97_hw_resume(void); extern int pxa2xx_ac97_hw_probe(struct platform_device *dev); extern void pxa2xx_ac97_hw_remove(struct platform_device *dev); +/* modem registers, used by touchscreen driver */ +u32 pxa2xx_ac97_read_modr(void); +u32 pxa2xx_ac97_read_misr(void); + #endif diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h index a36b7227a15a..e1f59b2940af 100644 --- a/include/sound/rawmidi.h +++ b/include/sound/rawmidi.h @@ -61,8 +61,8 @@ struct snd_rawmidi_runtime { size_t avail_min; /* min avail for wakeup */ size_t avail; /* max used buffer for wakeup */ size_t xruns; /* over/underruns counter */ + int buffer_ref; /* buffer reference count */ /* misc */ - spinlock_t lock; wait_queue_head_t sleep; /* event handler (new bytes, input only) */ void (*event)(struct snd_rawmidi_substream *substream); @@ -80,8 +80,11 @@ struct snd_rawmidi_substream { bool opened; /* open flag */ bool append; /* append flag (merge more streams) */ bool active_sensing; /* send active sensing when close */ + unsigned int framing; /* whether to frame input data */ + unsigned int clock_type; /* clock source to use for input framing */ int use_count; /* use counter (for output) */ size_t bytes; + spinlock_t lock; struct snd_rawmidi *rmidi; struct snd_rawmidi_str *pstr; char name[32]; @@ -95,6 +98,7 @@ struct snd_rawmidi_file { struct snd_rawmidi *rmidi; struct snd_rawmidi_substream *input; struct snd_rawmidi_substream *output; + unsigned int user_pversion; /* supported protocol version */ }; struct snd_rawmidi_str { @@ -152,10 +156,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count); int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream, unsigned char *buffer, int count); -int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream, - unsigned char *buffer, int count); -int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, - int count); int snd_rawmidi_proceed(struct snd_rawmidi_substream *substream); /* main midi functions */ diff --git a/include/sound/rt1015.h b/include/sound/rt1015.h new file mode 100644 index 000000000000..70a7538d4c89 --- /dev/null +++ b/include/sound/rt1015.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/sound/rt1015.h -- Platform data for RT1015 + * + * Copyright 2020 Realtek Microelectronics + */ + +#ifndef __LINUX_SND_RT1015_H +#define __LINUX_SND_RT1015_H + +struct rt1015_platform_data { + unsigned int power_up_delay_ms; +}; + +#endif diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h deleted file mode 100644 index 39a77c7cea36..000000000000 --- a/include/sound/rt5645.h +++ /dev/null @@ -1,30 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/rt5645.h -- Platform data for RT5645 - * - * Copyright 2013 Realtek Microelectronics - */ - -#ifndef __LINUX_SND_RT5645_H -#define __LINUX_SND_RT5645_H - -struct rt5645_platform_data { - /* IN2 can optionally be differential */ - bool in2_diff; - - unsigned int dmic1_data_pin; - /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ - unsigned int dmic2_data_pin; - /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ - - unsigned int jd_mode; - /* Use level triggered irq */ - bool level_trigger_irq; - /* Invert JD1_1 status polarity */ - bool inv_jd1_1; - - /* Value to asign to snd_soc_card.long_name */ - const char *long_name; -}; - -#endif diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h deleted file mode 100644 index f9024c7a1600..000000000000 --- a/include/sound/rt5670.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/rt5670.h -- Platform data for RT5670 - * - * Copyright 2014 Realtek Microelectronics - */ - -#ifndef __LINUX_SND_RT5670_H -#define __LINUX_SND_RT5670_H - -struct rt5670_platform_data { - int jd_mode; - bool in2_diff; - bool dev_gpio; - - bool dmic_en; - unsigned int dmic1_data_pin; - /* 0 = GPIO6; 1 = IN2P; 3 = GPIO7*/ - unsigned int dmic2_data_pin; - /* 0 = GPIO8; 1 = IN3N; */ - unsigned int dmic3_data_pin; - /* 0 = GPIO9; 1 = GPIO10; 2 = GPIO5*/ -}; - -#endif diff --git a/include/sound/rt5682.h b/include/sound/rt5682.h index bc2c31734df1..3900a07e3935 100644 --- a/include/sound/rt5682.h +++ b/include/sound/rt5682.h @@ -24,6 +24,12 @@ enum rt5682_jd_src { RT5682_JD1, }; +enum rt5682_dai_clks { + RT5682_DAI_WCLK_IDX, + RT5682_DAI_BCLK_IDX, + RT5682_DAI_NUM_CLKS, +}; + struct rt5682_platform_data { int ldo1_en; /* GPIO for LDO1_EN */ @@ -32,6 +38,11 @@ struct rt5682_platform_data { enum rt5682_dmic1_clk_pin dmic1_clk_pin; enum rt5682_jd_src jd_src; unsigned int btndet_delay; + unsigned int dmic_clk_rate; + unsigned int dmic_delay; + bool dmic_clk_driving_high; + + const char *dai_clk_names[RT5682_DAI_NUM_CLKS]; }; #endif diff --git a/include/sound/rt5682s.h b/include/sound/rt5682s.h new file mode 100644 index 000000000000..f18d91308b9a --- /dev/null +++ b/include/sound/rt5682s.h @@ -0,0 +1,49 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * linux/sound/rt5682s.h -- Platform data for RT5682I-VS + * + * Copyright 2021 Realtek Microelectronics + */ + +#ifndef __LINUX_SND_RT5682S_H +#define __LINUX_SND_RT5682S_H + +enum rt5682s_dmic1_data_pin { + RT5682S_DMIC1_DATA_NULL, + RT5682S_DMIC1_DATA_GPIO2, + RT5682S_DMIC1_DATA_GPIO5, +}; + +enum rt5682s_dmic1_clk_pin { + RT5682S_DMIC1_CLK_NULL, + RT5682S_DMIC1_CLK_GPIO1, + RT5682S_DMIC1_CLK_GPIO3, +}; + +enum rt5682s_jd_src { + RT5682S_JD_NULL, + RT5682S_JD1, +}; + +enum rt5682s_dai_clks { + RT5682S_DAI_WCLK_IDX, + RT5682S_DAI_BCLK_IDX, + RT5682S_DAI_NUM_CLKS, +}; + +struct rt5682s_platform_data { + + int ldo1_en; /* GPIO for LDO1_EN */ + + enum rt5682s_dmic1_data_pin dmic1_data_pin; + enum rt5682s_dmic1_clk_pin dmic1_clk_pin; + enum rt5682s_jd_src jd_src; + unsigned int dmic_clk_rate; + unsigned int dmic_delay; + unsigned int amic_delay; + bool dmic_clk_driving_high; + + const char *dai_clk_names[RT5682S_DAI_NUM_CLKS]; +}; + +#endif diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index bbdd1542d6f1..25e049f44178 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -12,9 +12,15 @@ #include <sound/soc.h> #define asoc_simple_init_hp(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 1, prefix) + asoc_simple_init_jack(card, sjack, 1, prefix, NULL) #define asoc_simple_init_mic(card, sjack, prefix) \ - asoc_simple_init_jack(card, sjack, 0, prefix) + asoc_simple_init_jack(card, sjack, 0, prefix, NULL) + +struct asoc_simple_tdm_width_map { + u8 sample_bits; + u8 slot_count; + u16 slot_width; +}; struct asoc_simple_dai { const char *name; @@ -25,11 +31,15 @@ struct asoc_simple_dai { unsigned int tx_slot_mask; unsigned int rx_slot_mask; struct clk *clk; + bool clk_fixed; + struct asoc_simple_tdm_width_map *tdm_width_map; + int n_tdm_widths; }; struct asoc_simple_data { u32 convert_rate; u32 convert_channels; + const char *convert_sample_format; }; struct asoc_simple_jack { @@ -38,35 +48,89 @@ struct asoc_simple_jack { struct snd_soc_jack_gpio gpio; }; +struct prop_nums { + int cpus; + int codecs; + int platforms; +}; + struct asoc_simple_priv { struct snd_soc_card snd_card; struct simple_dai_props { struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; - struct snd_soc_dai_link_component cpus; /* single cpu */ - struct snd_soc_dai_link_component codecs; /* single codec */ - struct snd_soc_dai_link_component platforms; + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; + struct prop_nums num; unsigned int mclk_fs; } *dai_props; struct asoc_simple_jack hp_jack; struct asoc_simple_jack mic_jack; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; + struct snd_soc_dai_link_component *dlcs; + struct snd_soc_dai_link_component dummy; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; + const struct snd_soc_ops *ops; + unsigned int dpcm_selectable:1; + unsigned int force_dpcm:1; }; #define simple_priv_to_card(priv) (&(priv)->snd_card) #define simple_priv_to_props(priv, i) ((priv)->dai_props + (i)) #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev) #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i)) +#define simple_props_to_dlc_cpu(props, i) ((props)->cpus + i) +#define simple_props_to_dlc_codec(props, i) ((props)->codecs + i) +#define simple_props_to_dlc_platform(props, i) ((props)->platforms + i) + +#define simple_props_to_dai_cpu(props, i) ((props)->cpu_dai + i) +#define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i) +#define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i) + +#define for_each_prop_dlc_cpus(props, i, cpu) \ + for ((i) = 0; \ + ((i) < (props)->num.cpus) && \ + ((cpu) = simple_props_to_dlc_cpu(props, i)); \ + (i)++) +#define for_each_prop_dlc_codecs(props, i, codec) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && \ + ((codec) = simple_props_to_dlc_codec(props, i)); \ + (i)++) +#define for_each_prop_dlc_platforms(props, i, platform) \ + for ((i) = 0; \ + ((i) < (props)->num.platforms) && \ + ((platform) = simple_props_to_dlc_platform(props, i)); \ + (i)++) +#define for_each_prop_codec_conf(props, i, conf) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && \ + (props)->codec_conf && \ + ((conf) = simple_props_to_codec_conf(props, i)); \ + (i)++) + +#define for_each_prop_dai_cpu(props, i, cpu) \ + for ((i) = 0; \ + ((i) < (props)->num.cpus) && \ + ((cpu) = simple_props_to_dai_cpu(props, i)); \ + (i)++) +#define for_each_prop_dai_codec(props, i, codec) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && \ + ((codec) = simple_props_to_dai_codec(props, i)); \ + (i)++) + +#define SNDRV_MAX_LINKS 512 + struct link_info { - int dais; /* number of dai */ int link; /* number of link */ - int conf; /* number of codec_conf */ int cpu; /* turn for CPU / Codec */ + struct prop_nums num[SNDRV_MAX_LINKS]; }; int asoc_simple_parse_daifmt(struct device *dev, @@ -74,6 +138,9 @@ int asoc_simple_parse_daifmt(struct device *dev, struct device_node *codec, char *prefix, unsigned int *retfmt); +int asoc_simple_parse_tdm_width_map(struct device *dev, struct device_node *np, + struct asoc_simple_dai *dai); + __printf(3, 4) int asoc_simple_set_dailink_name(struct device *dev, struct snd_soc_dai_link *dai_link, @@ -81,10 +148,6 @@ int asoc_simple_set_dailink_name(struct device *dev, int asoc_simple_parse_card_name(struct snd_soc_card *card, char *prefix); -#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus) -#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs) int asoc_simple_parse_clk(struct device *dev, struct device_node *node, struct asoc_simple_dai *simple_dai, @@ -97,30 +160,24 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd); int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); -#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \ - asoc_simple_parse_dai(node, dai_link->cpus, is_single_link) -#define asoc_simple_parse_codec(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->codecs, NULL) -#define asoc_simple_parse_platform(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->platforms, NULL) - #define asoc_simple_parse_tdm(np, dai) \ snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \ &(dai)->rx_slot_mask, \ &(dai)->slots, \ &(dai)->slot_width); -void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link); -void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link, - int is_single_links); +void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus); +void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, + int is_single_links); -int asoc_simple_clean_reference(struct snd_soc_card *card); +void asoc_simple_clean_reference(struct snd_soc_card *card); void asoc_simple_convert_fixup(struct asoc_simple_data *data, struct snd_pcm_hw_params *params); -void asoc_simple_parse_convert(struct device *dev, - struct device_node *np, char *prefix, +void asoc_simple_parse_convert(struct device_node *np, char *prefix, struct asoc_simple_data *data); +bool asoc_simple_is_convert_required(const struct asoc_simple_data *data); int asoc_simple_parse_routing(struct snd_soc_card *card, char *prefix); @@ -131,9 +188,13 @@ int asoc_simple_parse_pin_switches(struct snd_soc_card *card, int asoc_simple_init_jack(struct snd_soc_card *card, struct asoc_simple_jack *sjack, - int is_hp, char *prefix); + int is_hp, char *prefix, char *pin); int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct link_info *li); +int asoc_simple_remove(struct platform_device *pdev); + +int asoc_graph_card_probe(struct snd_soc_card *card); +int asoc_graph_is_ports0(struct device_node *port); #ifdef DEBUG static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, @@ -149,12 +210,6 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, if (dai->name) dev_dbg(dev, "%s dai name = %s\n", name, dai->name); - if (dai->sysclk) - dev_dbg(dev, "%s sysclk = %d\n", - name, dai->sysclk); - - dev_dbg(dev, "%s direction = %s\n", - name, dai->clk_direction ? "OUT" : "IN"); if (dai->slots) dev_dbg(dev, "%s slots = %d\n", name, dai->slots); @@ -166,6 +221,12 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask); if (dai->clk) dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk)); + if (dai->sysclk) + dev_dbg(dev, "%s sysclk = %dHz\n", + name, dai->sysclk); + if (dai->clk || dai->sysclk) + dev_dbg(dev, "%s direction = %s\n", + name, dai->clk_direction ? "OUT" : "IN"); } static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) @@ -181,29 +242,32 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) for (i = 0; i < card->num_links; i++) { struct simple_dai_props *props = simple_priv_to_props(priv, i); struct snd_soc_dai_link *link = simple_priv_to_link(priv, i); + struct asoc_simple_dai *dai; + struct snd_soc_codec_conf *cnf; + int j; dev_dbg(dev, "DAI%d\n", i); - asoc_simple_debug_dai(priv, "cpu", props->cpu_dai); - asoc_simple_debug_dai(priv, "codec", props->codec_dai); + dev_dbg(dev, "cpu num = %d\n", link->num_cpus); + for_each_prop_dai_cpu(props, j, dai) + asoc_simple_debug_dai(priv, "cpu", dai); + dev_dbg(dev, "codec num = %d\n", link->num_codecs); + for_each_prop_dai_codec(props, j, dai) + asoc_simple_debug_dai(priv, "codec", dai); if (link->name) dev_dbg(dev, "dai name = %s\n", link->name); - - dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); - + if (link->dai_fmt) + dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); if (props->adata.convert_rate) - dev_dbg(dev, "convert_rate = %d\n", - props->adata.convert_rate); + dev_dbg(dev, "convert_rate = %d\n", props->adata.convert_rate); if (props->adata.convert_channels) - dev_dbg(dev, "convert_channels = %d\n", - props->adata.convert_channels); - if (props->codec_conf && props->codec_conf->name_prefix) - dev_dbg(dev, "name prefix = %s\n", - props->codec_conf->name_prefix); + dev_dbg(dev, "convert_channels = %d\n", props->adata.convert_channels); + for_each_prop_codec_conf(props, j, cnf) + if (cnf->name_prefix) + dev_dbg(dev, "name prefix = %s\n", cnf->name_prefix); if (props->mclk_fs) - dev_dbg(dev, "mclk-fs = %d\n", - props->mclk_fs); + dev_dbg(dev, "mclk-fs = %d\n", props->mclk_fs); } } #else diff --git a/include/sound/soc-acpi-intel-match.h b/include/sound/soc-acpi-intel-match.h index ab6f75a86611..82a7db23db69 100644 --- a/include/sound/soc-acpi-intel-match.h +++ b/include/sound/soc-acpi-intel-match.h @@ -14,9 +14,7 @@ * these tables are not constants, some fields can be used for * pdata or machine ops */ -extern struct snd_soc_acpi_mach snd_soc_acpi_intel_haswell_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_broadwell_machines[]; -extern struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_legacy_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_baytrail_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cherrytrail_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_skl_machines[]; @@ -30,12 +28,18 @@ extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_ehl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cnl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cfl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_icl_sdw_machines[]; extern struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_rpl_sdw_machines[]; +extern struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[]; /* * generic table used for HDA codec-based platforms, possibly with diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index a217a87cae86..b38fd25c5729 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 +/* SPDX-License-Identifier: GPL-2.0-only * * Copyright (C) 2013-15, Intel Corporation. All rights reserved. */ @@ -58,11 +58,15 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * snd_soc_acpi_mach_params: interface for machine driver configuration * * @acpi_ipc_irq_index: used for BYT-CR detection - * @platform: string used for HDaudio codec support + * @platform: string used for HDAudio codec support * @codec_mask: used for HDAudio support + * @dmic_num: number of SoC- or chipset-attached PDM digital microphones * @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver - * @link_mask: links enabled on the board - * @links: array of link _ADR descriptors, null terminated + * @link_mask: SoundWire links enabled on the board + * @links: array of SoundWire link _ADR descriptors, null terminated + * @i2s_link_mask: I2S/TDM links enabled on the board + * @num_dai_drivers: number of elements in @dai_drivers + * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode */ struct snd_soc_acpi_mach_params { u32 acpi_ipc_irq_index; @@ -72,23 +76,73 @@ struct snd_soc_acpi_mach_params { bool common_hdmi_codec_drv; u32 link_mask; const struct snd_soc_acpi_link_adr *links; + u32 i2s_link_mask; + u32 num_dai_drivers; + struct snd_soc_dai_driver *dai_drivers; }; /** - * snd_soc_acpi_link_adr: ACPI-based list of _ADR, with a variable - * number of devices per link - * + * snd_soc_acpi_endpoint - endpoint descriptor + * @num: endpoint number (mandatory, unique per device) + * @aggregated: 0 (independent) or 1 (logically grouped) + * @group_position: zero-based order (only when @aggregated is 1) + * @group_id: platform-unique group identifier (only when @aggregrated is 1) + */ +struct snd_soc_acpi_endpoint { + u8 num; + u8 aggregated; + u8 group_position; + u8 group_id; +}; + +/** + * snd_soc_acpi_adr_device - descriptor for _ADR-enumerated device + * @adr: 64 bit ACPI _ADR value + * @num_endpoints: number of endpoints for this device + * @endpoints: array of endpoints + * @name_prefix: string used for codec controls + */ +struct snd_soc_acpi_adr_device { + const u64 adr; + const u8 num_endpoints; + const struct snd_soc_acpi_endpoint *endpoints; + const char *name_prefix; +}; + +/** + * snd_soc_acpi_link_adr - ACPI-based list of _ADR enumerated devices * @mask: one bit set indicates the link this list applies to - * @num_adr: ARRAY_SIZE of adr - * @adr: array of _ADR (represented as u64). + * @num_adr: ARRAY_SIZE of devices + * @adr_d: array of devices + * + * The number of devices per link can be more than 1, e.g. in SoundWire + * multi-drop configurations. */ struct snd_soc_acpi_link_adr { const u32 mask; const u32 num_adr; - const u64 *adr; + const struct snd_soc_acpi_adr_device *adr_d; }; +/* + * when set the topology uses the -ssp<N> suffix, where N is determined based on + * BIOS or DMI information + */ +#define SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER BIT(0) + +/* + * when more than one SSP is reported in the link mask, use the most significant. + * This choice was found to be valid on platforms with ES8336 codecs. + */ +#define SND_SOC_ACPI_TPLG_INTEL_SSP_MSB BIT(1) + +/* + * when set the topology uses the -dmic<N>ch suffix, where N is determined based on + * BIOS or DMI information + */ +#define SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER BIT(2) + /** * snd_soc_acpi_mach: ACPI-based machine descriptor. Most of the fields are * related to the hardware, except for the firmware and topology file names. @@ -96,10 +150,13 @@ struct snd_soc_acpi_link_adr { * all firmware/topology related fields. * * @id: ACPI ID (usually the codec's) used to find a matching machine driver. + * @comp_ids: list of compatible audio codecs using the same machine driver, + * firmware and topology * @link_mask: describes required board layout, e.g. for SoundWire. * @links: array of link _ADR descriptors, null terminated. * @drv_name: machine driver name * @fw_filename: firmware file name. Used when SOF is not enabled. + * @tplg_filename: topology file name. Used when SOF is not enabled. * @board: board name * @machine_quirk: pointer to quirk, usually based on DMI information when * ACPI ID alone is not sufficient, wrong or misleading @@ -107,23 +164,25 @@ struct snd_soc_acpi_link_adr { * audio codecs whose presence if checked with ACPI * @pdata: intended for platform data or machine specific-ops. This structure * is not constant since this field may be updated at run-time - * @sof_fw_filename: Sound Open Firmware file name, if enabled * @sof_tplg_filename: Sound Open Firmware topology file name, if enabled + * @tplg_quirk_mask: quirks to select different topology files dynamically */ /* Descriptor for SST ASoC machine driver */ struct snd_soc_acpi_mach { - const u8 id[ACPI_ID_LEN]; + u8 id[ACPI_ID_LEN]; + const struct snd_soc_acpi_codecs *comp_ids; const u32 link_mask; const struct snd_soc_acpi_link_adr *links; const char *drv_name; const char *fw_filename; + const char *tplg_filename; const char *board; struct snd_soc_acpi_mach * (*machine_quirk)(void *arg); const void *quirk_data; void *pdata; struct snd_soc_acpi_mach_params mach_params; - const char *sof_fw_filename; const char *sof_tplg_filename; + const u32 tplg_quirk_mask; }; #define SND_SOC_ACPI_MAX_CODECS 3 @@ -142,4 +201,10 @@ struct snd_soc_acpi_codecs { u8 codecs[SND_SOC_ACPI_MAX_CODECS][ACPI_ID_LEN]; }; +static inline bool snd_soc_acpi_sof_parent(struct device *dev) +{ + return dev->parent && dev->parent->driver && dev->parent->driver->name && + !strncmp(dev->parent->driver->name, "sof-audio-acpi", strlen("sof-audio-acpi")); +} + #endif diff --git a/include/sound/soc-card.h b/include/sound/soc-card.h new file mode 100644 index 000000000000..9d31a5c0db33 --- /dev/null +++ b/include/sound/soc-card.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-card.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + */ +#ifndef __SOC_CARD_H +#define __SOC_CARD_H + +enum snd_soc_card_subclass { + SND_SOC_CARD_CLASS_INIT = 0, + SND_SOC_CARD_CLASS_RUNTIME = 1, +}; + +struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, + const char *name); +int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, + struct snd_soc_jack *jack); +int snd_soc_card_jack_new_pins(struct snd_soc_card *card, const char *id, + int type, struct snd_soc_jack *jack, + struct snd_soc_jack_pin *pins, + unsigned int num_pins); + +int snd_soc_card_suspend_pre(struct snd_soc_card *card); +int snd_soc_card_suspend_post(struct snd_soc_card *card); +int snd_soc_card_resume_pre(struct snd_soc_card *card); +int snd_soc_card_resume_post(struct snd_soc_card *card); + +int snd_soc_card_probe(struct snd_soc_card *card); +int snd_soc_card_late_probe(struct snd_soc_card *card); +void snd_soc_card_fixup_controls(struct snd_soc_card *card); +int snd_soc_card_remove(struct snd_soc_card *card); + +int snd_soc_card_set_bias_level(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); +int snd_soc_card_set_bias_level_post(struct snd_soc_card *card, + struct snd_soc_dapm_context *dapm, + enum snd_soc_bias_level level); + +int snd_soc_card_add_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); +void snd_soc_card_remove_dai_link(struct snd_soc_card *card, + struct snd_soc_dai_link *dai_link); + +/* device driver data */ +static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, + void *data) +{ + card->drvdata = data; +} + +static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) +{ + return card->drvdata; +} + +static inline +struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, + const char *dai_name) +{ + struct snd_soc_pcm_runtime *rtd; + + for_each_card_rtds(card, rtd) { + if (!strcmp(asoc_rtd_to_codec(rtd, 0)->name, dai_name)) + return asoc_rtd_to_codec(rtd, 0); + } + + return NULL; +} + +#endif /* __SOC_CARD_H */ diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 154d02fbbfed..c26ffb033777 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -2,7 +2,8 @@ * * soc-component.h * - * Copyright (c) 2019 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> */ #ifndef __SOC_COMPONENT_H #define __SOC_COMPONENT_H @@ -25,6 +26,44 @@ order++) /* component interface */ +struct snd_compress_ops { + int (*open)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*free)(struct snd_soc_component *component, + struct snd_compr_stream *stream); + int (*set_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_params *params); + int (*get_params)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_codec *params); + int (*set_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*get_metadata)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_metadata *metadata); + int (*trigger)(struct snd_soc_component *component, + struct snd_compr_stream *stream, int cmd); + int (*pointer)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_tstamp *tstamp); + int (*copy)(struct snd_soc_component *component, + struct snd_compr_stream *stream, char __user *buf, + size_t count); + int (*mmap)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct vm_area_struct *vma); + int (*ack)(struct snd_soc_component *component, + struct snd_compr_stream *stream, size_t bytes); + int (*get_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_caps *caps); + int (*get_codec_caps)(struct snd_soc_component *component, + struct snd_compr_stream *stream, + struct snd_compr_codec_caps *codec); +}; + struct snd_soc_component_driver { const char *name; @@ -62,7 +101,7 @@ struct snd_soc_component_driver { /* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name); int (*of_xlate_dai_id)(struct snd_soc_component *comment, struct device_node *endpoint); @@ -107,8 +146,12 @@ struct snd_soc_component_driver { int (*mmap)(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct vm_area_struct *vma); + int (*ack)(struct snd_soc_component *component, + struct snd_pcm_substream *substream); + snd_pcm_sframes_t (*delay)(struct snd_soc_component *component, + struct snd_pcm_substream *substream); - const struct snd_compr_ops *compr_ops; + const struct snd_compress_ops *compress_ops; /* probe ordering - for components with runtime dependencies */ int probe_order; @@ -126,8 +169,17 @@ struct snd_soc_component_driver { unsigned int idle_bias_on:1; unsigned int suspend_bias_off:1; unsigned int use_pmdown_time:1; /* care pmdown_time at stop */ + /* + * Indicates that the component does not care about the endianness of + * PCM audio data and the core will ensure that both LE and BE variants + * of each used format are present. Typically this is because the + * component sits behind a bus that abstracts away the endian of the + * original data, ie. one for which the transmission endian is defined + * (I2S/SLIMbus/SoundWire), or the concept of endian doesn't exist (PDM, + * analogue). + */ unsigned int endianness:1; - unsigned int non_legacy_dai_naming:1; + unsigned int legacy_dai_naming:1; /* this component uses topology and ignore machine driver FEs */ const char *ignore_machine; @@ -136,6 +188,10 @@ struct snd_soc_component_driver { struct snd_pcm_hw_params *params); bool use_dai_pcm_id; /* use DAI link PCM ID as PCM device number */ int be_pcm_base; /* base device ID for all BE PCMs */ + +#ifdef CONFIG_DEBUG_FS + const char *debugfs_prefix; +#endif }; struct snd_soc_component { @@ -178,10 +234,16 @@ struct snd_soc_component { /* machine specific init */ int (*init)(struct snd_soc_component *component); -#ifdef CONFIG_DEBUG_FS + /* function mark */ + void *mark_module; + struct snd_pcm_substream *mark_open; + struct snd_pcm_substream *mark_hw_params; + struct snd_pcm_substream *mark_trigger; + struct snd_compr_stream *mark_compr_open; + void *mark_pm; + struct dentry *debugfs_root; const char *debugfs_prefix; -#endif }; #define for_each_component_dais(component, dai)\ @@ -286,10 +348,13 @@ static inline int snd_soc_component_cache_sync( return regcache_sync(component->regmap); } +void snd_soc_component_set_aux(struct snd_soc_component *component, + struct snd_soc_aux_dev *aux); +int snd_soc_component_init(struct snd_soc_component *component); +int snd_soc_component_is_dummy(struct snd_soc_component *component); + /* component IO */ -int snd_soc_component_read(struct snd_soc_component *component, - unsigned int reg, unsigned int *val); -unsigned int snd_soc_component_read32(struct snd_soc_component *component, +unsigned int snd_soc_component_read(struct snd_soc_component *component, unsigned int reg); int snd_soc_component_write(struct snd_soc_component *component, unsigned int reg, unsigned int val); @@ -304,6 +369,12 @@ int snd_soc_component_test_bits(struct snd_soc_component *component, unsigned int reg, unsigned int mask, unsigned int value); +unsigned int snd_soc_component_read_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask); +int snd_soc_component_write_field(struct snd_soc_component *component, + unsigned int reg, unsigned int mask, + unsigned int val); + /* component wide operations */ int snd_soc_component_set_sysclk(struct snd_soc_component *component, int clk_id, int source, @@ -321,6 +392,7 @@ int snd_soc_component_stream_event(struct snd_soc_component *component, int snd_soc_component_set_bias_level(struct snd_soc_component *component, enum snd_soc_bias_level level); +void snd_soc_component_setup_regmap(struct snd_soc_component *component); #ifdef CONFIG_REGMAP void snd_soc_component_init_regmap(struct snd_soc_component *component, struct regmap *regmap); @@ -328,17 +400,17 @@ void snd_soc_component_exit_regmap(struct snd_soc_component *component); #endif #define snd_soc_component_module_get_when_probe(component)\ - snd_soc_component_module_get(component, 0) -#define snd_soc_component_module_get_when_open(component) \ - snd_soc_component_module_get(component, 1) + snd_soc_component_module_get(component, NULL, 0) +#define snd_soc_component_module_get_when_open(component, substream) \ + snd_soc_component_module_get(component, substream, 1) int snd_soc_component_module_get(struct snd_soc_component *component, - int upon_open); + void *mark, int upon_open); #define snd_soc_component_module_put_when_remove(component) \ - snd_soc_component_module_put(component, 0) -#define snd_soc_component_module_put_when_close(component) \ - snd_soc_component_module_put(component, 1) + snd_soc_component_module_put(component, NULL, 0, 0) +#define snd_soc_component_module_put_when_close(component, substream, rollback) \ + snd_soc_component_module_put(component, substream, 1, rollback) void snd_soc_component_module_put(struct snd_soc_component *component, - int upon_open); + void *mark, int upon_open, int rollback); static inline void snd_soc_component_set_drvdata(struct snd_soc_component *c, void *data) @@ -351,10 +423,10 @@ static inline void *snd_soc_component_get_drvdata(struct snd_soc_component *c) return dev_get_drvdata(c->dev); } -static inline bool snd_soc_component_is_active( - struct snd_soc_component *component) +static inline unsigned int +snd_soc_component_active(struct snd_soc_component *component) { - return component->active != 0; + return component->active; } /* component pin */ @@ -382,17 +454,8 @@ int snd_soc_component_force_enable_pin_unlocked( int snd_soc_component_open(struct snd_soc_component *component, struct snd_pcm_substream *substream); int snd_soc_component_close(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_prepare(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_hw_params(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - struct snd_pcm_hw_params *params); -int snd_soc_component_hw_free(struct snd_soc_component *component, - struct snd_pcm_substream *substream); -int snd_soc_component_trigger(struct snd_soc_component *component, - struct snd_pcm_substream *substream, - int cmd); + struct snd_pcm_substream *substream, + int rollback); void snd_soc_component_suspend(struct snd_soc_component *component); void snd_soc_component_resume(struct snd_soc_component *component); int snd_soc_component_is_suspended(struct snd_soc_component *component); @@ -401,8 +464,31 @@ void snd_soc_component_remove(struct snd_soc_component *component); int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep); int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name); +int snd_soc_component_compr_open(struct snd_soc_component *component, + struct snd_compr_stream *cstream); +void snd_soc_component_compr_free(struct snd_soc_component *component, + struct snd_compr_stream *cstream, + int rollback); +int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd); +int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream, + struct snd_compr_params *params); +int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream, + struct snd_codec *params); +int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream, + struct snd_compr_caps *caps); +int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream, + struct snd_compr_codec_caps *codec); +int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes); +int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp); +int snd_soc_component_compr_copy(struct snd_compr_stream *cstream, + char __user *buf, size_t count); +int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); +int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); int snd_soc_pcm_component_pointer(struct snd_pcm_substream *substream); int snd_soc_pcm_component_ioctl(struct snd_pcm_substream *substream, @@ -417,5 +503,19 @@ int snd_soc_pcm_component_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma); int snd_soc_pcm_component_new(struct snd_soc_pcm_runtime *rtd); void snd_soc_pcm_component_free(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream, + int rollback); +int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream, + int cmd, int rollback); +int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, + void *stream); +void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, + void *stream, int rollback); +int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream); +void snd_soc_pcm_component_delay(struct snd_pcm_substream *substream, + snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay); #endif /* __SOC_COMPONENT_H */ diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index eaaeb00e9e84..ea7509672086 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -36,15 +36,42 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J #define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J +/* Describes the possible PCM format */ +/* + * use SND_SOC_DAI_FORMAT_xx as eash shift. + * see + * snd_soc_runtime_get_dai_fmt() + */ +#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT 0 +#define SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_FORMAT_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_I2S (1 << SND_SOC_DAI_FORMAT_I2S) +#define SND_SOC_POSSIBLE_DAIFMT_RIGHT_J (1 << SND_SOC_DAI_FORMAT_RIGHT_J) +#define SND_SOC_POSSIBLE_DAIFMT_LEFT_J (1 << SND_SOC_DAI_FORMAT_LEFT_J) +#define SND_SOC_POSSIBLE_DAIFMT_DSP_A (1 << SND_SOC_DAI_FORMAT_DSP_A) +#define SND_SOC_POSSIBLE_DAIFMT_DSP_B (1 << SND_SOC_DAI_FORMAT_DSP_B) +#define SND_SOC_POSSIBLE_DAIFMT_AC97 (1 << SND_SOC_DAI_FORMAT_AC97) +#define SND_SOC_POSSIBLE_DAIFMT_PDM (1 << SND_SOC_DAI_FORMAT_PDM) + /* * DAI Clock gating. * - * DAI bit clocks can be be gated (disabled) when the DAI is not + * DAI bit clocks can be gated (disabled) when the DAI is not * sending or receiving PCM data in a frame. This can be used to save power. */ #define SND_SOC_DAIFMT_CONT (1 << 4) /* continuous clock */ #define SND_SOC_DAIFMT_GATED (0 << 4) /* clock is gated */ +/* Describes the possible PCM format */ +/* + * define GATED -> CONT. GATED will be selected if both are selected. + * see + * snd_soc_runtime_get_dai_fmt() + */ +#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT 16 +#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK (0xFFFF << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_GATED (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CONT (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_SHIFT) + /* * DAI hardware signal polarity. * @@ -71,22 +98,52 @@ struct snd_compr_stream; #define SND_SOC_DAIFMT_IB_NF (3 << 8) /* invert BCLK + nor FRM */ #define SND_SOC_DAIFMT_IB_IF (4 << 8) /* invert BCLK + FRM */ +/* Describes the possible PCM format */ +#define SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT 32 +#define SND_SOC_POSSIBLE_DAIFMT_INV_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_NB_NF (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_NB_IF (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_IB_NF (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_IB_IF (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_INV_SHIFT) + /* - * DAI hardware clock masters. + * DAI hardware clock providers/consumers * * This is wrt the codec, the inverse is true for the interface - * i.e. if the codec is clk and FRM master then the interface is - * clk and frame slave. + * i.e. if the codec is clk and FRM provider then the interface is + * clk and frame consumer. */ -#define SND_SOC_DAIFMT_CBM_CFM (1 << 12) /* codec clk & FRM master */ -#define SND_SOC_DAIFMT_CBS_CFM (2 << 12) /* codec clk slave & FRM master */ -#define SND_SOC_DAIFMT_CBM_CFS (3 << 12) /* codec clk master & frame slave */ -#define SND_SOC_DAIFMT_CBS_CFS (4 << 12) /* codec clk & FRM slave */ - -#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f -#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 -#define SND_SOC_DAIFMT_INV_MASK 0x0f00 -#define SND_SOC_DAIFMT_MASTER_MASK 0xf000 +#define SND_SOC_DAIFMT_CBP_CFP (1 << 12) /* codec clk provider & frame provider */ +#define SND_SOC_DAIFMT_CBC_CFP (2 << 12) /* codec clk consumer & frame provider */ +#define SND_SOC_DAIFMT_CBP_CFC (3 << 12) /* codec clk provider & frame consumer */ +#define SND_SOC_DAIFMT_CBC_CFC (4 << 12) /* codec clk consumer & frame consumer */ + +/* previous definitions kept for backwards-compatibility, do not use in new contributions */ +#define SND_SOC_DAIFMT_CBM_CFM SND_SOC_DAIFMT_CBP_CFP +#define SND_SOC_DAIFMT_CBS_CFM SND_SOC_DAIFMT_CBC_CFP +#define SND_SOC_DAIFMT_CBM_CFS SND_SOC_DAIFMT_CBP_CFC +#define SND_SOC_DAIFMT_CBS_CFS SND_SOC_DAIFMT_CBC_CFC + +/* when passed to set_fmt directly indicate if the device is provider or consumer */ +#define SND_SOC_DAIFMT_BP_FP SND_SOC_DAIFMT_CBP_CFP +#define SND_SOC_DAIFMT_BC_FP SND_SOC_DAIFMT_CBC_CFP +#define SND_SOC_DAIFMT_BP_FC SND_SOC_DAIFMT_CBP_CFC +#define SND_SOC_DAIFMT_BC_FC SND_SOC_DAIFMT_CBC_CFC + +/* Describes the possible PCM format */ +#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT 48 +#define SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_MASK (0xFFFFULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFP (0x1ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFP (0x2ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CBP_CFC (0x4ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) +#define SND_SOC_POSSIBLE_DAIFMT_CBC_CFC (0x8ULL << SND_SOC_POSSIBLE_DAIFMT_CLOCK_PROVIDER_SHIFT) + +#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f +#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0 +#define SND_SOC_DAIFMT_INV_MASK 0x0f00 +#define SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK 0xf000 + +#define SND_SOC_DAIFMT_MASTER_MASK SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK /* * Master Clock Directions @@ -123,6 +180,8 @@ int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio); /* Digital Audio interface formatting */ +int snd_soc_dai_get_fmt_max_priority(struct snd_soc_pcm_runtime *rtd); +u64 snd_soc_dai_get_fmt(struct snd_soc_dai *dai, int priority); int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt); int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, @@ -149,26 +208,68 @@ int snd_soc_dai_hw_params(struct snd_soc_dai *dai, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params); void snd_soc_dai_hw_free(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); + struct snd_pcm_substream *substream, + int rollback); int snd_soc_dai_startup(struct snd_soc_dai *dai, struct snd_pcm_substream *substream); void snd_soc_dai_shutdown(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); -int snd_soc_dai_prepare(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); -int snd_soc_dai_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); -int snd_soc_dai_bespoke_trigger(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream, int cmd); -snd_pcm_sframes_t snd_soc_dai_delay(struct snd_soc_dai *dai, - struct snd_pcm_substream *substream); + struct snd_pcm_substream *substream, int rollback); void snd_soc_dai_suspend(struct snd_soc_dai *dai); void snd_soc_dai_resume(struct snd_soc_dai *dai); -int snd_soc_dai_probe(struct snd_soc_dai *dai); -int snd_soc_dai_remove(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link); +void snd_soc_dai_action(struct snd_soc_dai *dai, + int stream, int action); +static inline void snd_soc_dai_activate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, 1); +} +static inline void snd_soc_dai_deactivate(struct snd_soc_dai *dai, + int stream) +{ + snd_soc_dai_action(dai, stream, -1); +} +int snd_soc_dai_active(struct snd_soc_dai *dai); + +int snd_soc_pcm_dai_probe(struct snd_soc_pcm_runtime *rtd, int order); +int snd_soc_pcm_dai_remove(struct snd_soc_pcm_runtime *rtd, int order); +int snd_soc_pcm_dai_new(struct snd_soc_pcm_runtime *rtd); +int snd_soc_pcm_dai_prepare(struct snd_pcm_substream *substream); +int snd_soc_pcm_dai_trigger(struct snd_pcm_substream *substream, int cmd, + int rollback); +int snd_soc_pcm_dai_bespoke_trigger(struct snd_pcm_substream *substream, + int cmd); +void snd_soc_pcm_dai_delay(struct snd_pcm_substream *substream, + snd_pcm_sframes_t *cpu_delay, snd_pcm_sframes_t *codec_delay); + +int snd_soc_dai_compr_startup(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream); +void snd_soc_dai_compr_shutdown(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + int rollback); +int snd_soc_dai_compr_trigger(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, int cmd); +int snd_soc_dai_compr_set_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_params *params); +int snd_soc_dai_compr_get_params(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_codec *params); +int snd_soc_dai_compr_ack(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + size_t bytes); +int snd_soc_dai_compr_pointer(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_tstamp *tstamp); +int snd_soc_dai_compr_set_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); +int snd_soc_dai_compr_get_metadata(struct snd_soc_dai *dai, + struct snd_compr_stream *cstream, + struct snd_compr_metadata *metadata); struct snd_soc_dai_ops { /* @@ -200,13 +301,14 @@ struct snd_soc_dai_ops { unsigned int *rx_num, unsigned int *rx_slot); int (*set_tristate)(struct snd_soc_dai *dai, int tristate); - int (*set_sdw_stream)(struct snd_soc_dai *dai, - void *stream, int direction); + int (*set_stream)(struct snd_soc_dai *dai, + void *stream, int direction); + void *(*get_stream)(struct snd_soc_dai *dai, int direction); + /* * DAI digital mute - optional. * Called by soc-core to minimise any pops. */ - int (*digital_mute)(struct snd_soc_dai *dai, int mute); int (*mute_stream)(struct snd_soc_dai *dai, int mute, int stream); /* @@ -240,6 +342,19 @@ struct snd_soc_dai_ops { */ snd_pcm_sframes_t (*delay)(struct snd_pcm_substream *, struct snd_soc_dai *); + + /* + * Format list for auto selection. + * Format will be increased if priority format was + * not selected. + * see + * snd_soc_dai_get_fmt() + */ + u64 *auto_selectable_formats; + int num_auto_selectable_formats; + + /* bit field */ + unsigned int no_capture_mute:1; }; struct snd_soc_cdai_ops { @@ -299,9 +414,9 @@ struct snd_soc_dai_driver { /* DAI capabilities */ struct snd_soc_pcm_stream capture; struct snd_soc_pcm_stream playback; - unsigned int symmetric_rates:1; + unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; + unsigned int symmetric_sample_bits:1; /* probe ordering - for components with runtime dependencies */ int probe_order; @@ -322,11 +437,7 @@ struct snd_soc_dai { struct snd_soc_dai_driver *driver; /* DAI runtime info */ - unsigned int capture_active; /* stream usage count */ - unsigned int playback_active; /* stream usage count */ - unsigned int probed:1; - - unsigned int active; + unsigned int stream_active[SNDRV_PCM_STREAM_LAST + 1]; /* usage count */ struct snd_soc_dapm_widget *playback_widget; struct snd_soc_dapm_widget *capture_widget; @@ -348,8 +459,32 @@ struct snd_soc_dai { unsigned int rx_mask; struct list_head list; + + /* function mark */ + struct snd_pcm_substream *mark_startup; + struct snd_pcm_substream *mark_hw_params; + struct snd_pcm_substream *mark_trigger; + struct snd_compr_stream *mark_compr_startup; + + /* bit field */ + unsigned int probed:1; }; +static inline struct snd_soc_pcm_stream * +snd_soc_dai_get_pcm_stream(const struct snd_soc_dai *dai, int stream) +{ + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? + &dai->driver->playback : &dai->driver->capture; +} + +static inline +struct snd_soc_dapm_widget *snd_soc_dai_get_widget( + struct snd_soc_dai *dai, int stream) +{ + return (stream == SNDRV_PCM_STREAM_PLAYBACK) ? + dai->playback_widget : dai->capture_widget; +} + static inline void *snd_soc_dai_get_dma_data(const struct snd_soc_dai *dai, const struct snd_pcm_substream *ss) { @@ -386,24 +521,50 @@ static inline void *snd_soc_dai_get_drvdata(struct snd_soc_dai *dai) } /** - * snd_soc_dai_set_sdw_stream() - Configures a DAI for SDW stream operation + * snd_soc_dai_set_stream() - Configures a DAI for stream operation * @dai: DAI - * @stream: STREAM + * @stream: STREAM (opaque structure depending on DAI type) * @direction: Stream direction(Playback/Capture) - * SoundWire subsystem doesn't have a notion of direction and we reuse + * Some subsystems, such as SoundWire, don't have a notion of direction and we reuse * the ASoC stream direction to configure sink/source ports. * Playback maps to source ports and Capture for sink ports. * * This should be invoked with NULL to clear the stream set previously. * Returns 0 on success, a negative error code otherwise. */ -static inline int snd_soc_dai_set_sdw_stream(struct snd_soc_dai *dai, - void *stream, int direction) +static inline int snd_soc_dai_set_stream(struct snd_soc_dai *dai, + void *stream, int direction) { - if (dai->driver->ops->set_sdw_stream) - return dai->driver->ops->set_sdw_stream(dai, stream, direction); + if (dai->driver->ops->set_stream) + return dai->driver->ops->set_stream(dai, stream, direction); else return -ENOTSUPP; } +/** + * snd_soc_dai_get_stream() - Retrieves stream from DAI + * @dai: DAI + * @direction: Stream direction(Playback/Capture) + * + * This routine only retrieves that was previously configured + * with snd_soc_dai_get_stream() + * + * Returns pointer to stream or an ERR_PTR value, e.g. + * ERR_PTR(-ENOTSUPP) if callback is not supported; + */ +static inline void *snd_soc_dai_get_stream(struct snd_soc_dai *dai, + int direction) +{ + if (dai->driver->ops->get_stream) + return dai->driver->ops->get_stream(dai, direction); + else + return ERR_PTR(-ENOTSUPP); +} + +static inline unsigned int +snd_soc_dai_stream_active(struct snd_soc_dai *dai, int stream) +{ + return dai->stream_active[stream]; +} + #endif diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 1b6afbc1a4ed..ebb8e7a7fc29 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h @@ -16,6 +16,8 @@ #include <sound/asoc.h> struct device; +struct snd_soc_pcm_runtime; +struct soc_enum; /* widget has no PM register bit */ #define SND_SOC_NOPM -1 @@ -376,6 +378,24 @@ struct snd_soc_dapm_widget_list; struct snd_soc_dapm_update; enum snd_soc_dapm_direction; +/* + * Bias levels + * + * @ON: Bias is fully on for audio playback and capture operations. + * @PREPARE: Prepare for audio operations. Called before DAPM switching for + * stream start and stop operations. + * @STANDBY: Low power standby state when no playback/capture operations are + * in progress. NOTE: The transition time between STANDBY and ON + * should be as fast as possible and no longer than 10ms. + * @OFF: Power Off. No restrictions on transition times. + */ +enum snd_soc_bias_level { + SND_SOC_BIAS_OFF = 0, + SND_SOC_BIAS_STANDBY = 1, + SND_SOC_BIAS_PREPARE = 2, + SND_SOC_BIAS_ON = 3, +}; + int dapm_regulator_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event); int dapm_clock_event(struct snd_soc_dapm_widget *w, @@ -409,6 +429,7 @@ struct snd_soc_dapm_widget *snd_soc_dapm_new_control_unlocked( const struct snd_soc_dapm_widget *widget); int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm, struct snd_soc_dai *dai); +void snd_soc_dapm_free_widget(struct snd_soc_dapm_widget *w); int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card); void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card); @@ -482,6 +503,7 @@ int snd_soc_dapm_dai_get_connected_widgets(struct snd_soc_dai *dai, int stream, struct snd_soc_dapm_widget_list **list, bool (*custom_stop_condition)(struct snd_soc_dapm_widget *, enum snd_soc_dapm_direction)); +void snd_soc_dapm_dai_free_widgets(struct snd_soc_dapm_widget_list **list); struct snd_soc_dapm_context *snd_soc_dapm_kcontrol_dapm( struct snd_kcontrol *kcontrol); @@ -688,9 +710,14 @@ struct snd_soc_dapm_context { /* A list of widgets associated with an object, typically a snd_kcontrol */ struct snd_soc_dapm_widget_list { int num_widgets; - struct snd_soc_dapm_widget *widgets[0]; + struct snd_soc_dapm_widget *widgets[]; }; +#define for_each_dapm_widgets(list, i, widget) \ + for ((i) = 0; \ + (i) < list->num_widgets && (widget = list->widgets[i]); \ + (i)++) + struct snd_soc_dapm_stats { int power_checks; int path_checks; diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index b654ebfc8766..5b689c663290 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -101,6 +101,10 @@ struct snd_soc_dpcm_runtime { enum snd_soc_dpcm_state state; int trigger_pending; /* trigger cmd + 1 if pending, 0 if not */ + + int be_start; /* refcount protected by BE stream pcm lock */ + int be_pause; /* refcount protected by BE stream pcm lock */ + bool fe_pause; /* used to track STOP after PAUSE */ }; #define for_each_dpcm_fe(be, stream, _dpcm) \ @@ -132,17 +136,8 @@ int snd_soc_dpcm_be_can_update(struct snd_soc_pcm_runtime *fe, struct snd_pcm_substream * snd_soc_dpcm_get_substream(struct snd_soc_pcm_runtime *be, int stream); -/* get the BE runtime state */ -enum snd_soc_dpcm_state - snd_soc_dpcm_be_get_state(struct snd_soc_pcm_runtime *be, int stream); - -/* set the BE runtime state */ -void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream, - enum snd_soc_dpcm_state state); - -/* internal use only */ -int soc_dpcm_be_digital_mute(struct snd_soc_pcm_runtime *fe, int mute); -int soc_dpcm_runtime_update(struct snd_soc_card *); +/* update audio routing between PCMs and any DAI links */ +int snd_soc_dpcm_runtime_update(struct snd_soc_card *card); #ifdef CONFIG_DEBUG_FS void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd); @@ -154,23 +149,25 @@ static inline void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) int dpcm_path_get(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list_); +void dpcm_path_put(struct snd_soc_dapm_widget_list **list); int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list, int new); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream); +void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, + int do_hw_free, struct snd_soc_dpcm *last); void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); +void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream); int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd); int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event); +bool dpcm_end_walk_at_be(struct snd_soc_dapm_widget *widget, enum snd_soc_dapm_direction dir); -static inline void dpcm_path_put(struct snd_soc_dapm_widget_list **list) -{ - kfree(*list); -} - +#define dpcm_be_dai_startup_rollback(fe, stream, last) \ + dpcm_be_dai_stop(fe, stream, 0, last) +#define dpcm_be_dai_startup_unwind(fe, stream) dpcm_be_dai_stop(fe, stream, 0, NULL) +#define dpcm_be_dai_shutdown(fe, stream) dpcm_be_dai_stop(fe, stream, 1, NULL) #endif diff --git a/include/sound/soc-jack.h b/include/sound/soc-jack.h new file mode 100644 index 000000000000..a0abb1ee5110 --- /dev/null +++ b/include/sound/soc-jack.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-jack.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + */ +#ifndef __SOC_JACK_H +#define __SOC_JACK_H + +/** + * struct snd_soc_jack_pin - Describes a pin to update based on jack detection + * + * @pin: name of the pin to update + * @mask: bits to check for in reported jack status + * @invert: if non-zero then pin is enabled when status is not reported + * @list: internal list entry + */ +struct snd_soc_jack_pin { + struct list_head list; + const char *pin; + int mask; + bool invert; +}; + +/** + * struct snd_soc_jack_zone - Describes voltage zones of jack detection + * + * @min_mv: start voltage in mv + * @max_mv: end voltage in mv + * @jack_type: type of jack that is expected for this voltage + * @debounce_time: debounce_time for jack, codec driver should wait for this + * duration before reading the adc for voltages + * @list: internal list entry + */ +struct snd_soc_jack_zone { + unsigned int min_mv; + unsigned int max_mv; + unsigned int jack_type; + unsigned int debounce_time; + struct list_head list; +}; + +/** + * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection + * + * @gpio: legacy gpio number + * @idx: gpio descriptor index within the function of the GPIO + * consumer device + * @gpiod_dev: GPIO consumer device + * @name: gpio name. Also as connection ID for the GPIO consumer + * device function name lookup + * @report: value to report when jack detected + * @invert: report presence in low state + * @debounce_time: debounce time in ms + * @wake: enable as wake source + * @jack_status_check: callback function which overrides the detection + * to provide more complex checks (eg, reading an + * ADC). + */ +struct snd_soc_jack_gpio { + unsigned int gpio; + unsigned int idx; + struct device *gpiod_dev; + const char *name; + int report; + int invert; + int debounce_time; + bool wake; + + /* private: */ + struct snd_soc_jack *jack; + struct delayed_work work; + struct notifier_block pm_notifier; + struct gpio_desc *desc; + + void *data; + /* public: */ + int (*jack_status_check)(void *data); +}; + +struct snd_soc_jack { + struct mutex mutex; + struct snd_jack *jack; + struct snd_soc_card *card; + struct list_head pins; + int status; + struct blocking_notifier_head notifier; + struct list_head jack_zones; +}; + +/* Jack reporting */ +void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); +int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_pin *pins); +void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, + struct notifier_block *nb); +void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, + struct notifier_block *nb); +int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_zone *zones); +int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage); +#ifdef CONFIG_GPIOLIB +int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_gpio *gpios); +int snd_soc_jack_add_gpiods(struct device *gpiod_dev, + struct snd_soc_jack *jack, + int count, struct snd_soc_jack_gpio *gpios); +void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_gpio *gpios); +#else +static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_gpio *gpios) +{ + return 0; +} + +static inline int snd_soc_jack_add_gpiods(struct device *gpiod_dev, + struct snd_soc_jack *jack, + int count, + struct snd_soc_jack_gpio *gpios) +{ + return 0; +} + +static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, + struct snd_soc_jack_gpio *gpios) +{ +} +#endif + +#endif /* __SOC_JACK_H */ diff --git a/include/sound/soc-link.h b/include/sound/soc-link.h new file mode 100644 index 000000000000..9314cde1756b --- /dev/null +++ b/include/sound/soc-link.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * soc-link.h + * + * Copyright (C) 2019 Renesas Electronics Corp. + * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> + */ +#ifndef __SOC_LINK_H +#define __SOC_LINK_H + +int snd_soc_link_init(struct snd_soc_pcm_runtime *rtd); +void snd_soc_link_exit(struct snd_soc_pcm_runtime *rtd); +int snd_soc_link_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params); + +int snd_soc_link_startup(struct snd_pcm_substream *substream); +void snd_soc_link_shutdown(struct snd_pcm_substream *substream, + int rollback); +int snd_soc_link_prepare(struct snd_pcm_substream *substream); +int snd_soc_link_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params); +void snd_soc_link_hw_free(struct snd_pcm_substream *substream, + int rollback); + +int snd_soc_link_trigger(struct snd_pcm_substream *substream, int cmd, + int rollback); +int snd_soc_link_compr_startup(struct snd_compr_stream *cstream); +void snd_soc_link_compr_shutdown(struct snd_compr_stream *cstream, + int rollback); +int snd_soc_link_compr_set_params(struct snd_compr_stream *cstream); + +#endif /* __SOC_LINK_H */ diff --git a/include/sound/soc-topology.h b/include/sound/soc-topology.h index 5223896de26f..b4b896f83b94 100644 --- a/include/sound/soc-topology.h +++ b/include/sound/soc-topology.h @@ -31,9 +31,6 @@ struct snd_soc_dai_driver; struct snd_soc_dai; struct snd_soc_dapm_route; -/* object scan be loaded and unloaded in groups with identfying indexes */ -#define SND_SOC_TPLG_INDEX_ALL 0 /* ID that matches all FW objects */ - /* dynamic object type */ enum snd_soc_dobj_type { SND_SOC_DOBJ_NONE = 0, /* object is not dynamic */ @@ -57,7 +54,7 @@ struct snd_soc_dobj_control { /* dynamic widget object */ struct snd_soc_dobj_widget { - unsigned int kcontrol_type; /* kcontrol type: mixer, enum, bytes */ + unsigned int *kcontrol_type; /* kcontrol type: mixer, enum, bytes */ }; /* generic dynamic object - all dynamic objects belong to this struct */ @@ -154,7 +151,7 @@ struct snd_soc_tplg_ops { struct snd_soc_tplg_hdr *); /* completion - called at completion of firmware loading */ - void (*complete)(struct snd_soc_component *); + int (*complete)(struct snd_soc_component *comp); /* manifest - optional to inform component of manifest */ int (*manifest)(struct snd_soc_component *, int index, @@ -181,14 +178,8 @@ static inline const void *snd_soc_tplg_get_data(struct snd_soc_tplg_hdr *hdr) /* Dynamic Object loading and removal for component drivers */ int snd_soc_tplg_component_load(struct snd_soc_component *comp, - struct snd_soc_tplg_ops *ops, const struct firmware *fw, - u32 index); -int snd_soc_tplg_component_remove(struct snd_soc_component *comp, u32 index); - -/* Widget removal - widgets also removed wth component API */ -void snd_soc_tplg_widget_remove(struct snd_soc_dapm_widget *w); -void snd_soc_tplg_widget_remove_all(struct snd_soc_dapm_context *dapm, - u32 index); + struct snd_soc_tplg_ops *ops, const struct firmware *fw); +int snd_soc_tplg_component_remove(struct snd_soc_component *comp); /* Binds event handlers to dynamic widgets */ int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, @@ -197,8 +188,7 @@ int snd_soc_tplg_widget_bind_event(struct snd_soc_dapm_widget *w, #else -static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp, - u32 index) +static inline int snd_soc_tplg_component_remove(struct snd_soc_component *comp) { return 0; } diff --git a/include/sound/soc.h b/include/sound/soc.h index 8a2266676b2d..37bbfc8b45cb 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -31,31 +31,31 @@ #define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert, xautodisable) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .max = xmax, .platform_max = xmax, \ + .rshift = shift_right, .max = xmax, \ .invert = xinvert, .autodisable = xautodisable}) #define SOC_DOUBLE_S_VALUE(xreg, shift_left, shift_right, xmin, xmax, xsign_bit, xinvert, xautodisable) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = shift_left, \ - .rshift = shift_right, .min = xmin, .max = xmax, .platform_max = xmax, \ + .rshift = shift_right, .min = xmin, .max = xmax, \ .sign_bit = xsign_bit, .invert = xinvert, .autodisable = xautodisable}) #define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert, xautodisable) \ SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert, xautodisable) #define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ - {.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert}) + {.reg = xreg, .max = xmax, .invert = xinvert}) #define SOC_DOUBLE_R_VALUE(xlreg, xrreg, xshift, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .max = xmax, .platform_max = xmax, .invert = xinvert}) + .max = xmax, .invert = xinvert}) #define SOC_DOUBLE_R_S_VALUE(xlreg, xrreg, xshift, xmin, xmax, xsign_bit, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .max = xmax, .min = xmin, .platform_max = xmax, .sign_bit = xsign_bit, \ + .max = xmax, .min = xmin, .sign_bit = xsign_bit, \ .invert = xinvert}) #define SOC_DOUBLE_R_RANGE_VALUE(xlreg, xrreg, xshift, xmin, xmax, xinvert) \ ((unsigned long)&(struct soc_mixer_control) \ {.reg = xlreg, .rreg = xrreg, .shift = xshift, .rshift = xshift, \ - .min = xmin, .max = xmax, .platform_max = xmax, .invert = xinvert}) + .min = xmin, .max = xmax, .invert = xinvert}) #define SOC_SINGLE(xname, reg, shift, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ @@ -68,7 +68,7 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = xshift, \ .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .invert = xinvert} } #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -99,7 +99,7 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = xshift, \ .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .invert = xinvert} } #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ @@ -136,6 +136,18 @@ .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \ max, invert, 0) } +#define SOC_DOUBLE_SX_TLV(xname, xreg, shift_left, shift_right, xmin, xmax, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw_sx, \ + .get = snd_soc_get_volsw_sx, \ + .put = snd_soc_put_volsw_sx, \ + .private_value = (unsigned long)&(struct soc_mixer_control) \ + {.reg = xreg, .rreg = xreg, \ + .shift = shift_left, .rshift = shift_right, \ + .max = xmax, .min = xmin} } #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ @@ -176,6 +188,8 @@ .get = snd_soc_get_volsw, .put = snd_soc_put_volsw, \ .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ xmin, xmax, xsign_bit, xinvert) } +#define SOC_SINGLE_S_TLV(xname, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) \ + SOC_DOUBLE_R_S_TLV(xname, xreg, xreg, xshift, xmin, xmax, xsign_bit, xinvert, tlv_array) #define SOC_SINGLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ @@ -185,7 +199,7 @@ .put = snd_soc_put_volsw, \ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, \ - .min = xmin, .max = xmax, .platform_max = xmax, \ + .min = xmin, .max = xmax, \ .sign_bit = 7,} } #define SOC_DOUBLE_S8_TLV(xname, xreg, xmin, xmax, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -259,7 +273,7 @@ .private_value = (unsigned long)&(struct soc_mixer_control) \ {.reg = xreg, .rreg = xreg, .shift = xshift, \ .rshift = xshift, .min = xmin, .max = xmax, \ - .platform_max = xmax, .invert = xinvert} } + .invert = xinvert} } #define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\ xhandler_get, xhandler_put, tlv_array) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -280,6 +294,23 @@ .get = xhandler_get, .put = xhandler_put, \ .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } +#define SOC_DOUBLE_R_S_EXT_TLV(xname, reg_left, reg_right, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = snd_soc_info_volsw, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = SOC_DOUBLE_R_S_VALUE(reg_left, reg_right, xshift, \ + xmin, xmax, xsign_bit, xinvert) } +#define SOC_SINGLE_S_EXT_TLV(xname, xreg, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + tlv_array) \ + SOC_DOUBLE_R_S_EXT_TLV(xname, xreg, xreg, xshift, xmin, xmax, \ + xsign_bit, xinvert, xhandler_get, xhandler_put, \ + tlv_array) #define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ .info = snd_soc_info_bool_ext, \ @@ -368,24 +399,6 @@ #define SOC_ENUM_SINGLE_VIRT_DECL(name, xtexts) \ const struct soc_enum name = SOC_ENUM_SINGLE_VIRT(ARRAY_SIZE(xtexts), xtexts) -/* - * Bias levels - * - * @ON: Bias is fully on for audio playback and capture operations. - * @PREPARE: Prepare for audio operations. Called before DAPM switching for - * stream start and stop operations. - * @STANDBY: Low power standby state when no playback/capture operations are - * in progress. NOTE: The transition time between STANDBY and ON - * should be as fast as possible and no longer than 10ms. - * @OFF: Power Off. No restrictions on transition times. - */ -enum snd_soc_bias_level { - SND_SOC_BIAS_OFF = 0, - SND_SOC_BIAS_STANDBY = 1, - SND_SOC_BIAS_PREPARE = 2, - SND_SOC_BIAS_ON = 3, -}; - struct device_node; struct snd_jack; struct snd_soc_card; @@ -407,20 +420,13 @@ struct snd_soc_jack_pin; struct snd_soc_jack_gpio; -typedef int (*hw_write_t)(void *,const char* ,int); - enum snd_soc_pcm_subclass { SND_SOC_PCM_CLASS_PCM = 0, SND_SOC_PCM_CLASS_BE = 1, }; -enum snd_soc_card_subclass { - SND_SOC_CARD_CLASS_INIT = 0, - SND_SOC_CARD_CLASS_RUNTIME = 1, -}; - int snd_soc_register_card(struct snd_soc_card *card); -int snd_soc_unregister_card(struct snd_soc_card *card); +void snd_soc_unregister_card(struct snd_soc_card *card); int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card); #ifdef CONFIG_PM_SLEEP int snd_soc_suspend(struct device *dev); @@ -437,11 +443,12 @@ static inline int snd_soc_resume(struct device *dev) } #endif int snd_soc_poweroff(struct device *dev); -int snd_soc_add_component(struct device *dev, - struct snd_soc_component *component, - const struct snd_soc_component_driver *component_driver, - struct snd_soc_dai_driver *dai_drv, - int num_dai); +int snd_soc_component_initialize(struct snd_soc_component *component, + const struct snd_soc_component_driver *driver, + struct device *dev); +int snd_soc_add_component(struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + int num_dai); int snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); @@ -449,6 +456,10 @@ int devm_snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); void snd_soc_unregister_component(struct device *dev); +void snd_soc_unregister_component_by_driver(struct device *dev, + const struct snd_soc_component_driver *component_driver); +struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, + const char *driver_name); struct snd_soc_component *snd_soc_lookup_component(struct device *dev, const char *driver_name); @@ -468,8 +479,22 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd); -void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, int stream); -void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, int stream); + +void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, + int stream, int action); +static inline void snd_soc_runtime_activate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, 1); +} +static inline void snd_soc_runtime_deactivate(struct snd_soc_pcm_runtime *rtd, + int stream) +{ + snd_soc_runtime_action(rtd, stream, -1); +} + +int snd_soc_runtime_calc_hw(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hardware *hw, int stream); int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, unsigned int dai_fmt); @@ -489,55 +514,13 @@ int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots); int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params); int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots); int snd_soc_params_to_bclk(struct snd_pcm_hw_params *parms); +int snd_soc_tdm_params_to_bclk(struct snd_pcm_hw_params *params, + int tdm_width, int tdm_slots, int slot_multiple); /* set runtime hw params */ int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw); -/* Jack reporting */ -int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, - struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, - unsigned int num_pins); - -void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask); -int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_pin *pins); -void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, - struct notifier_block *nb); -void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, - struct notifier_block *nb); -int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_zone *zones); -int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage); -#ifdef CONFIG_GPIOLIB -int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -int snd_soc_jack_add_gpiods(struct device *gpiod_dev, - struct snd_soc_jack *jack, - int count, struct snd_soc_jack_gpio *gpios); -void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios); -#else -static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) -{ - return 0; -} - -static inline int snd_soc_jack_add_gpiods(struct device *gpiod_dev, - struct snd_soc_jack *jack, - int count, - struct snd_soc_jack_gpio *gpios) -{ - return 0; -} - -static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, - struct snd_soc_jack_gpio *gpios) -{ -} -#endif - struct snd_ac97 *snd_soc_alloc_ac97_component(struct snd_soc_component *component); struct snd_ac97 *snd_soc_new_ac97_component(struct snd_soc_component *component, unsigned int id, unsigned int id_mask); @@ -568,8 +551,6 @@ static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, void *data, const char *long_name, const char *prefix); -struct snd_kcontrol *snd_soc_card_get_kcontrol(struct snd_soc_card *soc_card, - const char *name); int snd_soc_add_component_controls(struct snd_soc_component *component, const struct snd_kcontrol_new *controls, unsigned int num_controls); int snd_soc_add_card_controls(struct snd_soc_card *soc_card, @@ -626,87 +607,6 @@ int snd_soc_get_strobe(struct snd_kcontrol *kcontrol, int snd_soc_put_strobe(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); -/** - * struct snd_soc_jack_pin - Describes a pin to update based on jack detection - * - * @pin: name of the pin to update - * @mask: bits to check for in reported jack status - * @invert: if non-zero then pin is enabled when status is not reported - * @list: internal list entry - */ -struct snd_soc_jack_pin { - struct list_head list; - const char *pin; - int mask; - bool invert; -}; - -/** - * struct snd_soc_jack_zone - Describes voltage zones of jack detection - * - * @min_mv: start voltage in mv - * @max_mv: end voltage in mv - * @jack_type: type of jack that is expected for this voltage - * @debounce_time: debounce_time for jack, codec driver should wait for this - * duration before reading the adc for voltages - * @list: internal list entry - */ -struct snd_soc_jack_zone { - unsigned int min_mv; - unsigned int max_mv; - unsigned int jack_type; - unsigned int debounce_time; - struct list_head list; -}; - -/** - * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection - * - * @gpio: legacy gpio number - * @idx: gpio descriptor index within the function of the GPIO - * consumer device - * @gpiod_dev: GPIO consumer device - * @name: gpio name. Also as connection ID for the GPIO consumer - * device function name lookup - * @report: value to report when jack detected - * @invert: report presence in low state - * @debounce_time: debounce time in ms - * @wake: enable as wake source - * @jack_status_check: callback function which overrides the detection - * to provide more complex checks (eg, reading an - * ADC). - */ -struct snd_soc_jack_gpio { - unsigned int gpio; - unsigned int idx; - struct device *gpiod_dev; - const char *name; - int report; - int invert; - int debounce_time; - bool wake; - - /* private: */ - struct snd_soc_jack *jack; - struct delayed_work work; - struct notifier_block pm_notifier; - struct gpio_desc *desc; - - void *data; - /* public: */ - int (*jack_status_check)(void *data); -}; - -struct snd_soc_jack { - struct mutex mutex; - struct snd_jack *jack; - struct snd_soc_card *card; - struct list_head pins; - int status; - struct blocking_notifier_head notifier; - struct list_head jack_zones; -}; - /* SoC PCM stream information */ struct snd_soc_pcm_stream { const char *stream_name; @@ -794,6 +694,9 @@ struct snd_soc_dai_link { /* codec/machine specific init - e.g. add machine controls */ int (*init)(struct snd_soc_pcm_runtime *rtd); + /* codec/machine specific exit - dual of init() */ + void (*exit)(struct snd_soc_pcm_runtime *rtd); + /* optional hw_params re-writing for BE and FE sync */ int (*be_hw_params_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); @@ -803,7 +706,7 @@ struct snd_soc_dai_link { const struct snd_soc_compr_ops *compr_ops; /* Mark this pcm with non atomic ops */ - bool nonatomic; + unsigned int nonatomic:1; /* For unidirectional dai links */ unsigned int playback_only:1; @@ -813,9 +716,9 @@ struct snd_soc_dai_link { unsigned int ignore_suspend:1; /* Symmetry requirements */ - unsigned int symmetric_rates:1; + unsigned int symmetric_rate:1; unsigned int symmetric_channels:1; - unsigned int symmetric_samplebits:1; + unsigned int symmetric_sample_bits:1; /* Do not create a PCM for this DAI link (Backend link) */ unsigned int no_pcm:1; @@ -840,19 +743,48 @@ struct snd_soc_dai_link { /* Do not create a PCM for this DAI link (Backend link) */ unsigned int ignore:1; + /* This flag will reorder stop sequence. By enabling this flag + * DMA controller stop sequence will be invoked first followed by + * CPU DAI driver stop sequence + */ + unsigned int stop_dma_first:1; + #ifdef CONFIG_SND_SOC_TOPOLOGY struct snd_soc_dobj dobj; /* For topology */ #endif }; + +static inline struct snd_soc_dai_link_component* +asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) { + return &(link)->cpus[n]; +} + +static inline struct snd_soc_dai_link_component* +asoc_link_to_codec(struct snd_soc_dai_link *link, int n) { + return &(link)->codecs[n]; +} + +static inline struct snd_soc_dai_link_component* +asoc_link_to_platform(struct snd_soc_dai_link *link, int n) { + return &(link)->platforms[n]; +} + #define for_each_link_codecs(link, i, codec) \ for ((i) = 0; \ - ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ + ((i) < link->num_codecs) && \ + ((codec) = asoc_link_to_codec(link, i)); \ (i)++) #define for_each_link_platforms(link, i, platform) \ for ((i) = 0; \ ((i) < link->num_platforms) && \ - ((platform) = &link->platforms[i]); \ + ((platform) = asoc_link_to_platform(link, i)); \ + (i)++) + +#define for_each_link_cpus(link, i, cpu) \ + for ((i) = 0; \ + ((i) < link->num_cpus) && \ + ((cpu) = asoc_link_to_cpu(link, i)); \ (i)++) /* @@ -992,13 +924,9 @@ struct snd_soc_card { struct mutex pcm_mutex; enum snd_soc_pcm_subclass pcm_subclass; - spinlock_t dpcm_lock; - - bool instantiated; - bool topology_shortname_created; - int (*probe)(struct snd_soc_card *card); int (*late_probe)(struct snd_soc_card *card); + void (*fixup_controls)(struct snd_soc_card *card); int (*remove)(struct snd_soc_card *card); /* the pre and post PM functions are used to do any PM work before and @@ -1057,7 +985,6 @@ struct snd_soc_card { int num_of_dapm_widgets; const struct snd_soc_dapm_route *of_dapm_routes; int num_of_dapm_routes; - bool fully_routed; /* lists of probed devices belonging to this card */ struct list_head component_dev_list; @@ -1084,6 +1011,14 @@ struct snd_soc_card { #endif u32 pop_time; + /* bit field */ + unsigned int instantiated:1; + unsigned int topology_shortname_created:1; + unsigned int fully_routed:1; + unsigned int disable_route_checks:1; + unsigned int probed:1; + unsigned int component_chaining:1; + void *drvdata; }; #define for_each_card_prelinks(card, i, link) \ @@ -1109,6 +1044,14 @@ struct snd_soc_card { #define for_each_card_components(card, component) \ list_for_each_entry(component, &(card)->component_dev_list, card_list) +#define for_each_card_dapms(card, dapm) \ + list_for_each_entry(dapm, &card->dapm_list, list) + +#define for_each_card_widgets(card, w)\ + list_for_each_entry(w, &card->widgets, list) +#define for_each_card_widgets_safe(card, w, _w) \ + list_for_each_entry_safe(w, _w, &card->widgets, list) + /* SoC machine DAI configuration, glues a codec and cpu DAI together */ struct snd_soc_pcm_runtime { struct device *dev; @@ -1119,18 +1062,23 @@ struct snd_soc_pcm_runtime { unsigned int params_select; /* currently selected param for dai link */ /* Dynamic PCM BE runtime data */ - struct snd_soc_dpcm_runtime dpcm[2]; + struct snd_soc_dpcm_runtime dpcm[SNDRV_PCM_STREAM_LAST + 1]; + struct snd_soc_dapm_widget *c2c_widget[SNDRV_PCM_STREAM_LAST + 1]; long pmdown_time; /* runtime devices */ struct snd_pcm *pcm; struct snd_compr *compr; - struct snd_soc_dai *codec_dai; - struct snd_soc_dai *cpu_dai; - struct snd_soc_dai **codec_dais; - unsigned int num_codecs; + /* + * dais = cpu_dai + codec_dai + * see + * soc_new_pcm_runtime() + * asoc_rtd_to_cpu() + * asoc_rtd_to_codec() + */ + struct snd_soc_dai **dais; struct delayed_work delayed_work; void (*close_delayed_work_func)(struct snd_soc_pcm_runtime *rtd); @@ -1141,23 +1089,42 @@ struct snd_soc_pcm_runtime { unsigned int num; /* 0-based and monotonic increasing */ struct list_head list; /* rtd list of the soc card */ + /* function mark */ + struct snd_pcm_substream *mark_startup; + struct snd_pcm_substream *mark_hw_params; + struct snd_pcm_substream *mark_trigger; + struct snd_compr_stream *mark_compr_startup; + /* bit field */ unsigned int pop_wait:1; unsigned int fe_compr:1; /* for Dynamic PCM */ int num_components; - struct snd_soc_component *components[0]; /* CPU/Codec/Platform */ + struct snd_soc_component *components[]; /* CPU/Codec/Platform */ }; +/* see soc_new_pcm_runtime() */ +#define asoc_rtd_to_cpu(rtd, n) (rtd)->dais[n] +#define asoc_rtd_to_codec(rtd, n) (rtd)->dais[n + (rtd)->dai_link->num_cpus] +#define asoc_substream_to_rtd(substream) \ + (struct snd_soc_pcm_runtime *)snd_pcm_substream_chip(substream) + #define for_each_rtd_components(rtd, i, component) \ - for ((i) = 0; \ + for ((i) = 0, component = NULL; \ ((i) < rtd->num_components) && ((component) = rtd->components[i]);\ (i)++) -#define for_each_rtd_codec_dai(rtd, i, dai)\ - for ((i) = 0; \ - ((i) < rtd->num_codecs) && ((dai) = rtd->codec_dais[i]); \ +#define for_each_rtd_cpu_dais(rtd, i, dai) \ + for ((i) = 0; \ + ((i) < rtd->dai_link->num_cpus) && ((dai) = asoc_rtd_to_cpu(rtd, i)); \ + (i)++) +#define for_each_rtd_codec_dais(rtd, i, dai) \ + for ((i) = 0; \ + ((i) < rtd->dai_link->num_codecs) && ((dai) = asoc_rtd_to_codec(rtd, i)); \ + (i)++) +#define for_each_rtd_dais(rtd, i, dai) \ + for ((i) = 0; \ + ((i) < (rtd)->dai_link->num_cpus + (rtd)->dai_link->num_codecs) && \ + ((dai) = (rtd)->dais[i]); \ (i)++) -#define for_each_rtd_codec_dai_rollback(rtd, i, dai) \ - for (; (--(i) >= 0) && ((dai) = rtd->codec_dais[i]);) void snd_soc_close_delayed_work(struct snd_soc_pcm_runtime *rtd); @@ -1213,29 +1180,16 @@ struct soc_enum { #endif }; -/* device driver data */ - -static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, - void *data) -{ - card->drvdata = data; -} - -static inline void *snd_soc_card_get_drvdata(struct snd_soc_card *card) -{ - return card->drvdata; -} - static inline bool snd_soc_volsw_is_stereo(struct soc_mixer_control *mc) { if (mc->reg == mc->rreg && mc->shift == mc->rshift) - return 0; + return false; /* * mc->reg == mc->rreg && mc->shift != mc->rshift, or * mc->reg != mc->rreg means that the control is * stereo (bits in one register or in two registers) */ - return 1; + return true; } static inline unsigned int snd_soc_enum_val_to_item(struct soc_enum *e, @@ -1285,6 +1239,7 @@ int snd_soc_of_parse_card_name(struct snd_soc_card *card, const char *propname); int snd_soc_of_parse_audio_simple_widgets(struct snd_soc_card *card, const char *propname); +int snd_soc_of_parse_pin_switches(struct snd_soc_card *card, const char *prop); int snd_soc_of_get_slot_mask(struct device_node *np, const char *prop_name, unsigned int *mask); @@ -1309,12 +1264,26 @@ void snd_soc_of_parse_audio_prefix(struct snd_soc_card *card, int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, const char *propname); -unsigned int snd_soc_of_parse_daifmt(struct device_node *np, - const char *prefix, - struct device_node **bitclkmaster, - struct device_node **framemaster); +int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname); + +unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt); +unsigned int snd_soc_daifmt_clock_provider_from_bitmap(unsigned int bit_frame); + +unsigned int snd_soc_daifmt_parse_format(struct device_node *np, const char *prefix); +unsigned int snd_soc_daifmt_parse_clock_provider_raw(struct device_node *np, + const char *prefix, + struct device_node **bitclkmaster, + struct device_node **framemaster); +#define snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix) \ + snd_soc_daifmt_parse_clock_provider_raw(np, prefix, NULL, NULL) +#define snd_soc_daifmt_parse_clock_provider_as_phandle \ + snd_soc_daifmt_parse_clock_provider_raw +#define snd_soc_daifmt_parse_clock_provider_as_flag(np, prefix) \ + snd_soc_daifmt_clock_provider_from_bitmap( \ + snd_soc_daifmt_parse_clock_provider_as_bitmap(np, prefix)) + int snd_soc_get_dai_id(struct device_node *ep); -int snd_soc_get_dai_name(struct of_phandle_args *args, +int snd_soc_get_dai_name(const struct of_phandle_args *args, const char **dai_name); int snd_soc_of_get_dai_name(struct device_node *of_node, const char **dai_name); @@ -1322,6 +1291,10 @@ int snd_soc_of_get_dai_link_codecs(struct device *dev, struct device_node *of_node, struct snd_soc_dai_link *dai_link); void snd_soc_of_put_dai_link_codecs(struct snd_soc_dai_link *dai_link); +int snd_soc_of_get_dai_link_cpus(struct device *dev, + struct device_node *of_node, + struct snd_soc_dai_link *dai_link); +void snd_soc_of_put_dai_link_cpus(struct snd_soc_dai_link *dai_link); int snd_soc_add_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link); @@ -1331,28 +1304,20 @@ void snd_soc_remove_pcm_runtime(struct snd_soc_card *card, struct snd_soc_dai *snd_soc_register_dai(struct snd_soc_component *component, struct snd_soc_dai_driver *dai_drv, bool legacy_dai_naming); +struct snd_soc_dai *devm_snd_soc_register_dai(struct device *dev, + struct snd_soc_component *component, + struct snd_soc_dai_driver *dai_drv, + bool legacy_dai_naming); void snd_soc_unregister_dai(struct snd_soc_dai *dai); struct snd_soc_dai *snd_soc_find_dai( const struct snd_soc_dai_link_component *dlc); +struct snd_soc_dai *snd_soc_find_dai_with_mutex( + const struct snd_soc_dai_link_component *dlc); #include <sound/soc-dai.h> static inline -struct snd_soc_dai *snd_soc_card_get_codec_dai(struct snd_soc_card *card, - const char *dai_name) -{ - struct snd_soc_pcm_runtime *rtd; - - list_for_each_entry(rtd, &card->rtd_list, list) { - if (!strcmp(rtd->codec_dai->name, dai_name)) - return rtd->codec_dai; - } - - return NULL; -} - -static inline int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, const char *platform_name) { @@ -1365,13 +1330,17 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, /* set platform name for each dailink */ for_each_card_prelinks(card, i, dai_link) { - name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL); - if (!name) - return -ENOMEM; + /* only single platform is supported for now */ + if (dai_link->num_platforms != 1) + return -EINVAL; if (!dai_link->platforms) return -EINVAL; + name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL); + if (!name) + return -ENOMEM; + /* only single platform is supported for now */ dai_link->platforms->name = name; } @@ -1397,5 +1366,7 @@ static inline void snd_soc_dapm_mutex_unlock(struct snd_soc_dapm_context *dapm) } #include <sound/soc-component.h> +#include <sound/soc-card.h> +#include <sound/soc-jack.h> #endif diff --git a/include/sound/sof.h b/include/sound/sof.h index a0cbca021230..341fef19e612 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -16,6 +16,44 @@ #include <sound/soc-acpi.h> struct snd_sof_dsp_ops; +struct snd_sof_dev; + +/** + * enum sof_fw_state - DSP firmware state definitions + * @SOF_FW_BOOT_NOT_STARTED: firmware boot is not yet started + * @SOF_FW_BOOT_PREPARE: preparing for boot (firmware loading for exaqmple) + * @SOF_FW_BOOT_IN_PROGRESS: firmware boot is in progress + * @SOF_FW_BOOT_FAILED: firmware boot failed + * @SOF_FW_BOOT_READY_FAILED: firmware booted but fw_ready op failed + * @SOF_FW_BOOT_READY_OK: firmware booted and fw_ready op passed + * @SOF_FW_BOOT_COMPLETE: firmware is booted up and functional + * @SOF_FW_CRASHED: firmware crashed after successful boot + */ +enum sof_fw_state { + SOF_FW_BOOT_NOT_STARTED = 0, + SOF_FW_BOOT_PREPARE, + SOF_FW_BOOT_IN_PROGRESS, + SOF_FW_BOOT_FAILED, + SOF_FW_BOOT_READY_FAILED, + SOF_FW_BOOT_READY_OK, + SOF_FW_BOOT_COMPLETE, + SOF_FW_CRASHED, +}; + +/* DSP power states */ +enum sof_dsp_power_states { + SOF_DSP_PM_D0, + SOF_DSP_PM_D1, + SOF_DSP_PM_D2, + SOF_DSP_PM_D3, +}; + +/* Definitions for multiple IPCs */ +enum sof_ipc_type { + SOF_IPC, + SOF_INTEL_IPC4, + SOF_IPC_TYPE_COUNT +}; /* * SOF Platform data. @@ -27,6 +65,9 @@ struct snd_sof_pdata { struct device *dev; + /* indicate how many first bytes shouldn't be loaded into DSP memory. */ + size_t fw_offset; + /* * notification callback used if the hardware initialization * can take time or is handled in a workqueue. This callback @@ -48,8 +89,11 @@ struct snd_sof_pdata { /* machine */ struct platform_device *pdev_mach; const struct snd_soc_acpi_mach *machine; + const struct snd_sof_of_mach *of_machine; void *hw_pdata; + + enum sof_ipc_type ipc_type; }; /* @@ -59,21 +103,19 @@ struct snd_sof_pdata { struct sof_dev_desc { /* list of machines using this configuration */ struct snd_soc_acpi_mach *machines; + struct snd_sof_of_mach *of_machines; /* alternate list of machines using this configuration */ struct snd_soc_acpi_mach *alt_machines; + bool use_acpi_target_states; + /* Platform resource indexes in BAR / ACPI resources. */ /* Must set to -1 if not used - add new items to end */ int resindex_lpe_base; int resindex_pcicfg_base; int resindex_imr_base; int irqindex_host_ipc; - int resindex_dma_base; - - /* DMA only valid when resindex_dma_base != -1*/ - int dma_engine; - int dma_size; /* IPC timeouts in ms */ int ipc_timeout; @@ -85,16 +127,23 @@ struct sof_dev_desc { /* defaults for no codec mode */ const char *nocodec_tplg_filename; + /* information on supported IPCs */ + unsigned int ipc_supported_mask; + enum sof_ipc_type ipc_default; + /* defaults paths for firmware and topology files */ - const char *default_fw_path; - const char *default_tplg_path; + const char *default_fw_path[SOF_IPC_TYPE_COUNT]; + const char *default_tplg_path[SOF_IPC_TYPE_COUNT]; /* default firmware name */ - const char *default_fw_filename; + const char *default_fw_filename[SOF_IPC_TYPE_COUNT]; - const struct snd_sof_dsp_ops *ops; + struct snd_sof_dsp_ops *ops; + int (*ops_init)(struct snd_sof_dev *sdev); + void (*ops_free)(struct snd_sof_dev *sdev); }; -int sof_nocodec_setup(struct device *dev, - const struct snd_sof_dsp_ops *ops); +int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd); +int sof_dai_get_bclk(struct snd_soc_pcm_runtime *rtd); + #endif diff --git a/include/sound/sof/channel_map.h b/include/sound/sof/channel_map.h index 21044eb5f377..d363f0ca6979 100644 --- a/include/sound/sof/channel_map.h +++ b/include/sound/sof/channel_map.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -39,7 +39,7 @@ struct sof_ipc_channel_map { uint32_t ext_id; uint32_t ch_mask; uint32_t reserved; - int32_t ch_coeffs[0]; + int32_t ch_coeffs[]; } __packed; /** @@ -55,7 +55,7 @@ struct sof_ipc_stream_map { struct sof_ipc_cmd_hdr hdr; uint32_t num_ch_map; uint32_t reserved[3]; - struct sof_ipc_channel_map ch_map[0]; + struct sof_ipc_channel_map ch_map[]; } __packed; #endif /* __IPC_CHANNEL_MAP_H__ */ diff --git a/include/sound/sof/control.h b/include/sound/sof/control.h index 6080ea0facd7..983d374fe511 100644 --- a/include/sound/sof/control.h +++ b/include/sound/sof/control.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -117,11 +117,11 @@ struct sof_ipc_ctrl_data { /* control data - add new types if needed */ union { /* channel values can be used by volume type controls */ - struct sof_ipc_ctrl_value_chan chanv[0]; + DECLARE_FLEX_ARRAY(struct sof_ipc_ctrl_value_chan, chanv); /* component values used by routing controls like mux, mixer */ - struct sof_ipc_ctrl_value_comp compv[0]; + DECLARE_FLEX_ARRAY(struct sof_ipc_ctrl_value_comp, compv); /* data can be used by binary controls */ - struct sof_abi_hdr data[0]; + DECLARE_FLEX_ARRAY(struct sof_abi_hdr, data); }; } __packed; diff --git a/include/sound/sof/dai-amd.h b/include/sound/sof/dai-amd.h new file mode 100644 index 000000000000..92f45c180b7c --- /dev/null +++ b/include/sound/sof/dai-amd.h @@ -0,0 +1,28 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2021 Advanced Micro Devices, Inc.. All rights reserved. + */ + +#ifndef __INCLUDE_SOUND_SOF_DAI_AMD_H__ +#define __INCLUDE_SOUND_SOF_DAI_AMD_H__ + +#include <sound/sof/header.h> + +/* ACP Configuration Request - SOF_IPC_DAI_AMD_CONFIG */ +struct sof_ipc_dai_acp_params { + struct sof_ipc_hdr hdr; + + uint32_t fsync_rate; /* FSYNC frequency in Hz */ + uint32_t tdm_slots; +} __packed; + +/* ACPDMIC Configuration Request - SOF_IPC_DAI_AMD_CONFIG */ +struct sof_ipc_dai_acpdmic_params { + uint32_t pdm_rate; + uint32_t pdm_ch; +} __packed; + +#endif diff --git a/include/sound/sof/dai-imx.h b/include/sound/sof/dai-imx.h index ff9088dcc6f2..ca8325353d41 100644 --- a/include/sound/sof/dai-imx.h +++ b/include/sound/sof/dai-imx.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * Copyright 2019 NXP * diff --git a/include/sound/sof/dai-intel.h b/include/sound/sof/dai-intel.h index 5f1ef5565be6..5b93b7292f5e 100644 --- a/include/sound/sof/dai-intel.h +++ b/include/sound/sof/dai-intel.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -48,6 +48,15 @@ #define SOF_DAI_INTEL_SSP_CLKCTRL_FS_KA BIT(4) /* bclk idle */ #define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_IDLE_HIGH BIT(5) +/* mclk early start */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_ES BIT(6) +/* bclk early start */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_BCLK_ES BIT(7) +/* mclk always on */ +#define SOF_DAI_INTEL_SSP_CLKCTRL_MCLK_AON BIT(8) + +/* DMIC max. four controllers for eight microphone channels */ +#define SOF_DAI_INTEL_DMIC_NUM_CTRL 4 /* SSP Configuration Request - SOF_IPC_DAI_SSP_CONFIG */ struct sof_ipc_dai_ssp_params { @@ -85,6 +94,19 @@ struct sof_ipc_dai_ssp_params { struct sof_ipc_dai_hda_params { struct sof_ipc_hdr hdr; uint32_t link_dma_ch; + uint32_t rate; + uint32_t channels; +} __packed; + +/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ +struct sof_ipc_dai_alh_params { + struct sof_ipc_hdr hdr; + uint32_t stream_id; + uint32_t rate; + uint32_t channels; + + /* reserved for future use */ + uint32_t reserved[13]; } __packed; /* DMIC Configuration Request - SOF_IPC_DAI_DMIC_CONFIG */ @@ -126,7 +148,7 @@ struct sof_ipc_dai_dmic_pdm_ctrl { * version number used in configuration data is checked vs. version used by * device driver src/drivers/dmic.c need to match. It is incremented from * initial value 1 if updates done for the to driver would alter the operation - * of the microhone. + * of the microphone. * * Note: The microphone clock (pdmclk_min, pdmclk_max, duty_min, duty_max) * parameters need to be set as defined in microphone data sheet. E.g. clock @@ -161,12 +183,13 @@ struct sof_ipc_dai_dmic_params { uint32_t fifo_fs; /**< FIFO sample rate in Hz (8000..96000) */ uint32_t reserved_1; /**< Reserved */ uint16_t fifo_bits; /**< FIFO word length (16 or 32) */ - uint16_t reserved_2; /**< Reserved */ + uint16_t fifo_bits_b; /**< Deprecated since firmware ABI 3.0.1 */ uint16_t duty_min; /**< Min. mic clock duty cycle in % (20..80) */ uint16_t duty_max; /**< Max. mic clock duty cycle in % (min..80) */ - uint32_t num_pdm_active; /**< Number of active pdm controllers */ + uint32_t num_pdm_active; /**< Number of active pdm controllers. */ + /**< Range is 1..SOF_DAI_INTEL_DMIC_NUM_CTRL */ uint32_t wake_up_time; /**< Time from clock start to data (us) */ uint32_t min_clock_on_time; /**< Min. time that clk is kept on (us) */ @@ -175,17 +198,8 @@ struct sof_ipc_dai_dmic_params { /* reserved for future use */ uint32_t reserved[5]; - /**< variable number of pdm controller config */ - struct sof_ipc_dai_dmic_pdm_ctrl pdm[0]; -} __packed; - -/* ALH Configuration Request - SOF_IPC_DAI_ALH_CONFIG */ -struct sof_ipc_dai_alh_params { - struct sof_ipc_hdr hdr; - uint32_t stream_id; - - /* reserved for future use */ - uint32_t reserved[15]; + /**< PDM controllers configuration */ + struct sof_ipc_dai_dmic_pdm_ctrl pdm[SOF_DAI_INTEL_DMIC_NUM_CTRL]; } __packed; #endif diff --git a/include/sound/sof/dai-mediatek.h b/include/sound/sof/dai-mediatek.h new file mode 100644 index 000000000000..62dd4720558d --- /dev/null +++ b/include/sound/sof/dai-mediatek.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * Copyright(c) 2021 Mediatek Corporation. All rights reserved. + * + * Author: Bo Pan <bo.pan@mediatek.com> + */ + +#ifndef __INCLUDE_SOUND_SOF_DAI_MEDIATEK_H__ +#define __INCLUDE_SOUND_SOF_DAI_MEDIATEK_H__ + +#include <sound/sof/header.h> + +struct sof_ipc_dai_mtk_afe_params { + struct sof_ipc_hdr hdr; + u32 channels; + u32 rate; + u32 format; + u32 stream_id; + u32 reserved[4]; /* reserve for future */ +} __packed; + +#endif + diff --git a/include/sound/sof/dai.h b/include/sound/sof/dai.h index 2565edd336f1..83fd81c82e4c 100644 --- a/include/sound/sof/dai.h +++ b/include/sound/sof/dai.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -12,6 +12,8 @@ #include <sound/sof/header.h> #include <sound/sof/dai-intel.h> #include <sound/sof/dai-imx.h> +#include <sound/sof/dai-amd.h> +#include <sound/sof/dai-mediatek.h> /* * DAI Configuration. @@ -34,15 +36,41 @@ #define SOF_DAI_FMT_IB_NF (3 << 8) /**< invert BCLK + nor FRM */ #define SOF_DAI_FMT_IB_IF (4 << 8) /**< invert BCLK + FRM */ -#define SOF_DAI_FMT_CBM_CFM (0 << 12) /**< codec clk & FRM master */ -#define SOF_DAI_FMT_CBS_CFM (2 << 12) /**< codec clk slave & FRM master */ -#define SOF_DAI_FMT_CBM_CFS (3 << 12) /**< codec clk master & frame slave */ -#define SOF_DAI_FMT_CBS_CFS (4 << 12) /**< codec clk & FRM slave */ +#define SOF_DAI_FMT_CBP_CFP (0 << 12) /**< codec bclk provider & frame provider */ +#define SOF_DAI_FMT_CBC_CFP (2 << 12) /**< codec bclk consumer & frame provider */ +#define SOF_DAI_FMT_CBP_CFC (3 << 12) /**< codec bclk provider & frame consumer */ +#define SOF_DAI_FMT_CBC_CFC (4 << 12) /**< codec bclk consumer & frame consumer */ + +/* keep old definitions for backwards compatibility */ +#define SOF_DAI_FMT_CBM_CFM SOF_DAI_FMT_CBP_CFP +#define SOF_DAI_FMT_CBS_CFM SOF_DAI_FMT_CBC_CFP +#define SOF_DAI_FMT_CBM_CFS SOF_DAI_FMT_CBP_CFC +#define SOF_DAI_FMT_CBS_CFS SOF_DAI_FMT_CBC_CFC #define SOF_DAI_FMT_FORMAT_MASK 0x000f #define SOF_DAI_FMT_CLOCK_MASK 0x00f0 #define SOF_DAI_FMT_INV_MASK 0x0f00 -#define SOF_DAI_FMT_MASTER_MASK 0xf000 +#define SOF_DAI_FMT_CLOCK_PROVIDER_MASK 0xf000 + +/* + * DAI_CONFIG flags. The 4 LSB bits are used for the commands, HW_PARAMS, HW_FREE and PAUSE + * representing when the IPC is sent. The 4 MSB bits are used to add quirks along with the above + * commands. + */ +#define SOF_DAI_CONFIG_FLAGS_CMD_MASK 0xF +#define SOF_DAI_CONFIG_FLAGS_NONE 0 /**< DAI_CONFIG sent without stage information */ +#define SOF_DAI_CONFIG_FLAGS_HW_PARAMS BIT(0) /**< DAI_CONFIG sent during hw_params stage */ +#define SOF_DAI_CONFIG_FLAGS_HW_FREE BIT(1) /**< DAI_CONFIG sent during hw_free stage */ +/**< DAI_CONFIG sent during pause trigger. Only available ABI 3.20 onwards */ +#define SOF_DAI_CONFIG_FLAGS_PAUSE BIT(2) +#define SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT 4 +#define SOF_DAI_CONFIG_FLAGS_QUIRK_MASK (0xF << SOF_DAI_CONFIG_FLAGS_QUIRK_SHIFT) +/* + * This should be used along with the SOF_DAI_CONFIG_FLAGS_HW_PARAMS to indicate that pipeline + * stop/pause and DAI DMA stop/pause should happen in two steps. This change is only available + * ABI 3.20 onwards. + */ +#define SOF_DAI_CONFIG_FLAGS_2_STEP_STOP BIT(0) /** \brief Types of DAI */ enum sof_ipc_dai_type { @@ -53,6 +81,11 @@ enum sof_ipc_dai_type { SOF_DAI_INTEL_ALH, /**< Intel ALH */ SOF_DAI_IMX_SAI, /**< i.MX SAI */ SOF_DAI_IMX_ESAI, /**< i.MX ESAI */ + SOF_DAI_AMD_BT, /**< AMD ACP BT*/ + SOF_DAI_AMD_SP, /**< AMD ACP SP */ + SOF_DAI_AMD_DMIC, /**< AMD ACP DMIC */ + SOF_DAI_AMD_HS, /**< Amd HS */ + SOF_DAI_MEDIATEK_AFE, /**< Mediatek AFE */ }; /* general purpose DAI configuration */ @@ -63,7 +96,8 @@ struct sof_ipc_dai_config { /* physical protocol and clocking */ uint16_t format; /**< SOF_DAI_FMT_ */ - uint16_t reserved16; /**< alignment */ + uint8_t group_id; /**< group ID, 0 means no group (ABI 3.17) */ + uint8_t flags; /**< SOF_DAI_CONFIG_FLAGS_ (ABI 3.19) */ /* reserved for future use */ uint32_t reserved[8]; @@ -76,7 +110,17 @@ struct sof_ipc_dai_config { struct sof_ipc_dai_alh_params alh; struct sof_ipc_dai_esai_params esai; struct sof_ipc_dai_sai_params sai; + struct sof_ipc_dai_acp_params acpbt; + struct sof_ipc_dai_acp_params acpsp; + struct sof_ipc_dai_acpdmic_params acpdmic; + struct sof_ipc_dai_acp_params acphs; + struct sof_ipc_dai_mtk_afe_params afe; }; } __packed; +struct sof_dai_private_data { + struct sof_ipc_comp_dai *comp_dai; + struct sof_ipc_dai_config *dai_config; +}; + #endif diff --git a/include/sound/sof/debug.h b/include/sound/sof/debug.h new file mode 100644 index 000000000000..38693e3fb514 --- /dev/null +++ b/include/sound/sof/debug.h @@ -0,0 +1,43 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + * + * Author: Karol Trzcinski <karolx.trzcinski@linux.intel.com> + */ + +#ifndef __INCLUDE_SOUND_SOF_DEBUG_H__ +#define __INCLUDE_SOUND_SOF_DEBUG_H__ + +#include <sound/sof/header.h> + +/** ABI3.18 */ +enum sof_ipc_dbg_mem_zone { + SOF_IPC_MEM_ZONE_SYS = 0, /**< System zone */ + SOF_IPC_MEM_ZONE_SYS_RUNTIME = 1, /**< System-runtime zone */ + SOF_IPC_MEM_ZONE_RUNTIME = 2, /**< Runtime zone */ + SOF_IPC_MEM_ZONE_BUFFER = 3, /**< Buffer zone */ + SOF_IPC_MEM_ZONE_RUNTIME_SHARED = 4, /**< System runtime zone */ + SOF_IPC_MEM_ZONE_SYS_SHARED = 5, /**< System shared zone */ +}; + +/** ABI3.18 */ +struct sof_ipc_dbg_mem_usage_elem { + uint32_t zone; /**< see sof_ipc_dbg_mem_zone */ + uint32_t id; /**< heap index within zone */ + uint32_t used; /**< number of bytes used in zone */ + uint32_t free; /**< number of bytes free to use within zone */ + uint32_t reserved; /**< for future use */ +} __packed; + +/** ABI3.18 */ +struct sof_ipc_dbg_mem_usage { + struct sof_ipc_reply rhdr; /**< generic IPC reply header */ + uint32_t reserved[4]; /**< reserved for future use */ + uint32_t num_elems; /**< elems[] counter */ + struct sof_ipc_dbg_mem_usage_elem elems[]; /**< memory usage information */ +} __packed; + +#endif diff --git a/include/sound/sof/ext_manifest.h b/include/sound/sof/ext_manifest.h new file mode 100644 index 000000000000..2a7e055584f9 --- /dev/null +++ b/include/sound/sof/ext_manifest.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2020 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST_H__ + +#include <linux/bits.h> +#include <linux/compiler.h> +#include <linux/types.h> +#include <sound/sof/info.h> + +/* In ASCII `XMan` */ +#define SOF_EXT_MAN_MAGIC_NUMBER 0x6e614d58 + +/* Build u32 number in format MMmmmppp */ +#define SOF_EXT_MAN_BUILD_VERSION(MAJOR, MINOR, PATH) ((uint32_t)( \ + ((MAJOR) << 24) | \ + ((MINOR) << 12) | \ + (PATH))) + +/* check extended manifest version consistency */ +#define SOF_EXT_MAN_VERSION_INCOMPATIBLE(host_ver, cli_ver) ( \ + ((host_ver) & GENMASK(31, 24)) != \ + ((cli_ver) & GENMASK(31, 24))) + +/* used extended manifest header version */ +#define SOF_EXT_MAN_VERSION SOF_EXT_MAN_BUILD_VERSION(1, 0, 0) + +/* extended manifest header, deleting any field breaks backward compatibility */ +struct sof_ext_man_header { + uint32_t magic; /*< identification number, */ + /*< EXT_MAN_MAGIC_NUMBER */ + uint32_t full_size; /*< [bytes] full size of ext_man, */ + /*< (header + content + padding) */ + uint32_t header_size; /*< [bytes] makes header extensionable, */ + /*< after append new field to ext_man header */ + /*< then backward compatible won't be lost */ + uint32_t header_version; /*< value of EXT_MAN_VERSION */ + /*< not related with following content */ + + /* just after this header should be list of ext_man_elem_* elements */ +} __packed; + +/* Now define extended manifest elements */ + +/* Extended manifest elements types */ +enum sof_ext_man_elem_type { + SOF_EXT_MAN_ELEM_FW_VERSION = 0, + SOF_EXT_MAN_ELEM_WINDOW = 1, + SOF_EXT_MAN_ELEM_CC_VERSION = 2, + SOF_EXT_MAN_ELEM_DBG_ABI = 4, + SOF_EXT_MAN_ELEM_CONFIG_DATA = 5, /**< ABI3.17 */ + SOF_EXT_MAN_ELEM_PLATFORM_CONFIG_DATA = 6, +}; + +/* extended manifest element header */ +struct sof_ext_man_elem_header { + uint32_t type; /*< SOF_EXT_MAN_ELEM_ */ + uint32_t size; /*< in bytes, including header size */ + + /* just after this header should be type dependent content */ +} __packed; + +/* FW version */ +struct sof_ext_man_fw_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_fw_version version; + uint32_t flags; +} __packed; + +/* extended data memory windows for IPC, trace and debug */ +struct sof_ext_man_window { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_window ipc_window; +} __packed; + +/* Used C compiler description */ +struct sof_ext_man_cc_version { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_cc_version cc_version; +} __packed; + +struct ext_man_dbg_abi { + struct sof_ext_man_elem_header hdr; + /* use sof_ipc struct because of code re-use */ + struct sof_ipc_user_abi_version dbg_abi; +} __packed; + +/* EXT_MAN_ELEM_CONFIG_DATA elements identificators, ABI3.17 */ +enum config_elem_type { + SOF_EXT_MAN_CONFIG_EMPTY = 0, + SOF_EXT_MAN_CONFIG_IPC_MSG_SIZE = 1, + SOF_EXT_MAN_CONFIG_MEMORY_USAGE_SCAN = 2, /**< ABI 3.18 */ +}; + +struct sof_config_elem { + uint32_t token; + uint32_t value; +} __packed; + +/* firmware configuration information */ +struct sof_ext_man_config_data { + struct sof_ext_man_elem_header hdr; + + struct sof_config_elem elems[]; +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST_H__ */ diff --git a/include/sound/sof/ext_manifest4.h b/include/sound/sof/ext_manifest4.h new file mode 100644 index 000000000000..ec97edcbbfc3 --- /dev/null +++ b/include/sound/sof/ext_manifest4.h @@ -0,0 +1,119 @@ +/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +/* + * Extended manifest is a place to store metadata about firmware, known during + * compilation time - for example firmware version or used compiler. + * Given information are read on host side before firmware startup. + * This part of output binary is not signed. + */ + +#ifndef __SOF_FIRMWARE_EXT_MANIFEST4_H__ +#define __SOF_FIRMWARE_EXT_MANIFEST4_H__ + +#include <linux/uuid.h> + +/* In ASCII $AE1 */ +#define SOF_EXT_MAN4_MAGIC_NUMBER 0x31454124 + +#define MAX_MODULE_NAME_LEN 8 +#define MAX_FW_BINARY_NAME 8 +#define DEFAULT_HASH_SHA256_LEN 32 +#define SOF_MAN4_FW_HDR_OFFSET 0x2000 +#define SOF_MAN4_FW_HDR_OFFSET_CAVS_1_5 0x284 + +/********************************************************************* + * extended manifest (struct sof_ext_manifest4_hdr) + *------------------- + * css_manifest hdr + *------------------- + * offset reserved for future + *------------------- + * fw_hdr (struct sof_man4_fw_binary_header) + *------------------- + * module_entry[0] (struct sof_man4_module) + *------------------- + * module_entry[1] + *------------------- + * ... + *------------------- + * module_entry[n] + *------------------- + * module_config[0] (struct sof_man4_module_config) + *------------------- + * module_config[1] + *------------------- + * ... + *------------------- + * module_config[m] + *------------------- + * FW content + *------------------- + *********************************************************************/ + +struct sof_ext_manifest4_hdr { + uint32_t id; + uint32_t len; /* length of extension manifest */ + uint16_t version_major; /* header version */ + uint16_t version_minor; + uint32_t num_module_entries; +} __packed; + +struct sof_man4_fw_binary_header { + /* This part must be unchanged to be backward compatible with SPT-LP ROM */ + uint32_t id; + uint32_t len; /* sizeof(sof_man4_fw_binary_header) in bytes */ + uint8_t name[MAX_FW_BINARY_NAME]; + uint32_t preload_page_count; /* number of pages of preloaded image */ + uint32_t fw_image_flags; + uint32_t feature_mask; + uint16_t major_version; /* Firmware version */ + uint16_t minor_version; + uint16_t hotfix_version; + uint16_t build_version; + uint32_t num_module_entries; + + /* This part may change to contain any additional data for BaseFw that is skipped by ROM */ + uint32_t hw_buf_base_addr; + uint32_t hw_buf_length; + uint32_t load_offset; /* This value is used by ROM */ +} __packed; + +struct sof_man4_segment_desc { + uint32_t flags; + uint32_t v_base_addr; + uint32_t file_offset; +} __packed; + +struct sof_man4_module { + uint32_t id; + uint8_t name[MAX_MODULE_NAME_LEN]; + guid_t uuid; + uint32_t type; + uint8_t hash[DEFAULT_HASH_SHA256_LEN]; + uint32_t entry_point; + uint16_t cfg_offset; + uint16_t cfg_count; + uint32_t affinity_mask; + uint16_t instance_max_count; + uint16_t instance_stack_size; + struct sof_man4_segment_desc segments[3]; +} __packed; + +struct sof_man4_module_config { + uint32_t par[4]; /* module parameters */ + uint32_t is_bytes; /* actual size of instance .bss (bytes) */ + uint32_t cps; /* cycles per second */ + uint32_t ibs; /* input buffer size (bytes) */ + uint32_t obs; /* output buffer size (bytes) */ + uint32_t module_flags; /* flags, reserved for future use */ + uint32_t cpc; /* cycles per single run */ + uint32_t obls; /* output block size, reserved for future use */ +} __packed; + +#endif /* __SOF_FIRMWARE_EXT_MANIFEST4_H__ */ diff --git a/include/sound/sof/header.h b/include/sound/sof/header.h index bf3edd9c08b4..b22e925c70e2 100644 --- a/include/sound/sof/header.h +++ b/include/sound/sof/header.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -31,12 +31,12 @@ /* Global Message - Generic */ #define SOF_GLB_TYPE_SHIFT 28 -#define SOF_GLB_TYPE_MASK (0xf << SOF_GLB_TYPE_SHIFT) +#define SOF_GLB_TYPE_MASK (0xfUL << SOF_GLB_TYPE_SHIFT) #define SOF_GLB_TYPE(x) ((x) << SOF_GLB_TYPE_SHIFT) /* Command Message - Generic */ #define SOF_CMD_TYPE_SHIFT 16 -#define SOF_CMD_TYPE_MASK (0xfff << SOF_CMD_TYPE_SHIFT) +#define SOF_CMD_TYPE_MASK (0xfffL << SOF_CMD_TYPE_SHIFT) #define SOF_CMD_TYPE(x) ((x) << SOF_CMD_TYPE_SHIFT) /* Global Message Types */ @@ -49,8 +49,10 @@ #define SOF_IPC_FW_READY SOF_GLB_TYPE(0x7U) #define SOF_IPC_GLB_DAI_MSG SOF_GLB_TYPE(0x8U) #define SOF_IPC_GLB_TRACE_MSG SOF_GLB_TYPE(0x9U) -#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU) +#define SOF_IPC_GLB_GDB_DEBUG SOF_GLB_TYPE(0xAU) #define SOF_IPC_GLB_TEST_MSG SOF_GLB_TYPE(0xBU) +#define SOF_IPC_GLB_PROBE SOF_GLB_TYPE(0xCU) +#define SOF_IPC_GLB_DEBUG SOF_GLB_TYPE(0xDU) /* * DSP Command Message Types @@ -102,13 +104,28 @@ #define SOF_IPC_STREAM_VORBIS_PARAMS SOF_CMD_TYPE(0x010) #define SOF_IPC_STREAM_VORBIS_FREE SOF_CMD_TYPE(0x011) +/* probe */ +#define SOF_IPC_PROBE_INIT SOF_CMD_TYPE(0x001) +#define SOF_IPC_PROBE_DEINIT SOF_CMD_TYPE(0x002) +#define SOF_IPC_PROBE_DMA_ADD SOF_CMD_TYPE(0x003) +#define SOF_IPC_PROBE_DMA_INFO SOF_CMD_TYPE(0x004) +#define SOF_IPC_PROBE_DMA_REMOVE SOF_CMD_TYPE(0x005) +#define SOF_IPC_PROBE_POINT_ADD SOF_CMD_TYPE(0x006) +#define SOF_IPC_PROBE_POINT_INFO SOF_CMD_TYPE(0x007) +#define SOF_IPC_PROBE_POINT_REMOVE SOF_CMD_TYPE(0x008) + /* trace */ #define SOF_IPC_TRACE_DMA_PARAMS SOF_CMD_TYPE(0x001) #define SOF_IPC_TRACE_DMA_POSITION SOF_CMD_TYPE(0x002) #define SOF_IPC_TRACE_DMA_PARAMS_EXT SOF_CMD_TYPE(0x003) +#define SOF_IPC_TRACE_FILTER_UPDATE SOF_CMD_TYPE(0x004) /**< ABI3.17 */ +#define SOF_IPC_TRACE_DMA_FREE SOF_CMD_TYPE(0x005) /**< ABI3.20 */ /* debug */ -#define SOF_IPC_TEST_IPC_FLOOD SOF_CMD_TYPE(0x001) +#define SOF_IPC_DEBUG_MEM_USAGE SOF_CMD_TYPE(0x001) + +/* test */ +#define SOF_IPC_TEST_IPC_FLOOD SOF_CMD_TYPE(0x001) /* Get message component id */ #define SOF_IPC_MESSAGE_ID(x) ((x) & 0xffff) diff --git a/include/sound/sof/info.h b/include/sound/sof/info.h index 1c560144996c..65e86e4e9fd8 100644 --- a/include/sound/sof/info.h +++ b/include/sound/sof/info.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -25,12 +25,15 @@ #define SOF_IPC_INFO_LOCKS BIT(1) #define SOF_IPC_INFO_LOCKSV BIT(2) #define SOF_IPC_INFO_GDB BIT(3) +#define SOF_IPC_INFO_D3_PERSISTENT BIT(4) /* extended data types that can be appended onto end of sof_ipc_fw_ready */ enum sof_ipc_ext_data { - SOF_IPC_EXT_DMA_BUFFER = 0, - SOF_IPC_EXT_WINDOW, - SOF_IPC_EXT_CC_INFO, + SOF_IPC_EXT_UNUSED = 0, + SOF_IPC_EXT_WINDOW = 1, + SOF_IPC_EXT_CC_INFO = 2, + SOF_IPC_EXT_PROBE_INFO = 3, + SOF_IPC_EXT_USER_ABI_INFO = 4, }; /* FW version - SOF_IPC_GLB_VERSION */ @@ -44,9 +47,11 @@ struct sof_ipc_fw_version { uint8_t time[10]; uint8_t tag[6]; uint32_t abi_version; + /* used to check FW and ldc file compatibility, reproducible value */ + uint32_t src_hash; /* reserved for future use */ - uint32_t reserved[4]; + uint32_t reserved[3]; } __packed; /* FW ready Message - sent by firmware when boot has completed */ @@ -83,22 +88,6 @@ struct sof_ipc_ext_data_hdr { uint32_t type; /**< SOF_IPC_EXT_ */ } __packed; -struct sof_ipc_dma_buffer_elem { - struct sof_ipc_hdr hdr; - uint32_t type; /**< SOF_IPC_REGION_ */ - uint32_t id; /**< platform specific - used to map to host memory */ - struct sof_ipc_host_buffer buffer; -} __packed; - -/* extended data DMA buffers for IPC, trace and debug */ -struct sof_ipc_dma_buffer_data { - struct sof_ipc_ext_data_hdr ext_hdr; - uint32_t num_buffers; - - /* host files in buffer[n].buffer */ - struct sof_ipc_dma_buffer_elem buffer[]; -} __packed; - struct sof_ipc_window_elem { struct sof_ipc_hdr hdr; uint32_t type; /**< SOF_IPC_REGION_ */ @@ -113,7 +102,7 @@ struct sof_ipc_window_elem { struct sof_ipc_window { struct sof_ipc_ext_data_hdr ext_hdr; uint32_t num_windows; - struct sof_ipc_window_elem window[]; + struct sof_ipc_window_elem window[SOF_IPC_MAX_ELEMS]; } __packed; struct sof_ipc_cc_version { @@ -125,9 +114,27 @@ struct sof_ipc_cc_version { /* reserved for future use */ uint32_t reserved[4]; - char name[16]; /* null terminated compiler name */ - char optim[4]; /* null terminated compiler -O flag value */ - char desc[]; /* null terminated compiler description */ + uint8_t name[16]; /* null terminated compiler name */ + uint8_t optim[4]; /* null terminated compiler -O flag value */ + uint8_t desc[32]; /* null terminated compiler description */ } __packed; +/* extended data: Probe setup */ +struct sof_ipc_probe_support { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t probe_points_max; + uint32_t injection_dmas_max; + + /* reserved for future use */ + uint32_t reserved[2]; +} __packed; + +/* extended data: user abi version(s) */ +struct sof_ipc_user_abi_version { + struct sof_ipc_ext_data_hdr ext_hdr; + + uint32_t abi_dbg_version; +} __packed; + #endif diff --git a/include/sound/sof/ipc4/header.h b/include/sound/sof/ipc4/header.h new file mode 100644 index 000000000000..99efe0ef1784 --- /dev/null +++ b/include/sound/sof/ipc4/header.h @@ -0,0 +1,473 @@ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ +/* + * This file is provided under a dual BSD/GPLv2 license. When using or + * redistributing this file, you may do so under either license. + * + * Copyright(c) 2022 Intel Corporation. All rights reserved. + */ + +#ifndef __INCLUDE_SOUND_SOF_IPC4_HEADER_H__ +#define __INCLUDE_SOUND_SOF_IPC4_HEADER_H__ + +#include <linux/types.h> +#include <uapi/sound/sof/abi.h> + +/* maximum message size for mailbox Tx/Rx */ +#define SOF_IPC4_MSG_MAX_SIZE 4096 + +/** \addtogroup sof_uapi uAPI + * SOF uAPI specification. + * @{ + */ + +/** + * struct sof_ipc4_msg - Placeholder of an IPC4 message + * @header_u64: IPC4 header as single u64 number + * @primary: Primary, mandatory part of the header + * @extension: Extended part of the header, if not used it should be + * set to 0 + * @data_size: Size of data in bytes pointed by @data_ptr + * @data_ptr: Pointer to the optional payload of a message + */ +struct sof_ipc4_msg { + union { + u64 header_u64; + struct { + u32 primary; + u32 extension; + }; + }; + + size_t data_size; + void *data_ptr; +}; + +/** + * struct sof_ipc4_tuple - Generic type/ID and parameter tuple + * @type: type/ID + * @size: size of the @value array in bytes + * @value: value for the given type + */ +struct sof_ipc4_tuple { + uint32_t type; + uint32_t size; + uint32_t value[]; +} __packed; + +/* + * IPC4 messages have two 32 bit identifier made up as follows :- + * + * header - msg type, msg id, msg direction ... + * extension - extra params such as msg data size in mailbox + * + * These are sent at the start of the IPC message in the mailbox. Messages + * should not be sent in the doorbell (special exceptions for firmware). + */ + +/* + * IPC4 primary header bit allocation for messages + * bit 0-23: message type specific + * bit 24-28: type: enum sof_ipc4_global_msg if target is SOF_IPC4_FW_GEN_MSG + * enum sof_ipc4_module_type if target is SOF_IPC4_MODULE_MSG + * bit 29: response - sof_ipc4_msg_dir + * bit 30: target - enum sof_ipc4_msg_target + * bit 31: reserved, unused + */ + +/* Value of target field - must fit into 1 bit */ +enum sof_ipc4_msg_target { + /* Global FW message */ + SOF_IPC4_FW_GEN_MSG, + + /* Module message */ + SOF_IPC4_MODULE_MSG +}; + +/* Value of type field - must fit into 5 bits */ +enum sof_ipc4_global_msg { + SOF_IPC4_GLB_BOOT_CONFIG, + SOF_IPC4_GLB_ROM_CONTROL, + SOF_IPC4_GLB_IPCGATEWAY_CMD, + + /* 3 .. 12: RESERVED - do not use */ + + SOF_IPC4_GLB_PERF_MEASUREMENTS_CMD = 13, + SOF_IPC4_GLB_CHAIN_DMA, + + SOF_IPC4_GLB_LOAD_MULTIPLE_MODULES, + SOF_IPC4_GLB_UNLOAD_MULTIPLE_MODULES, + + /* pipeline settings */ + SOF_IPC4_GLB_CREATE_PIPELINE, + SOF_IPC4_GLB_DELETE_PIPELINE, + SOF_IPC4_GLB_SET_PIPELINE_STATE, + SOF_IPC4_GLB_GET_PIPELINE_STATE, + SOF_IPC4_GLB_GET_PIPELINE_CONTEXT_SIZE, + SOF_IPC4_GLB_SAVE_PIPELINE, + SOF_IPC4_GLB_RESTORE_PIPELINE, + + /* Loads library (using Code Load or HD/A Host Output DMA) */ + SOF_IPC4_GLB_LOAD_LIBRARY, + + /* 25: RESERVED - do not use */ + + SOF_IPC4_GLB_INTERNAL_MESSAGE = 26, + + /* Notification (FW to SW driver) */ + SOF_IPC4_GLB_NOTIFICATION, + + /* 28 .. 31: RESERVED - do not use */ + + SOF_IPC4_GLB_TYPE_LAST, +}; + +/* Value of response field - must fit into 1 bit */ +enum sof_ipc4_msg_dir { + SOF_IPC4_MSG_REQUEST, + SOF_IPC4_MSG_REPLY, +}; + +enum sof_ipc4_pipeline_state { + SOF_IPC4_PIPE_INVALID_STATE, + SOF_IPC4_PIPE_UNINITIALIZED, + SOF_IPC4_PIPE_RESET, + SOF_IPC4_PIPE_PAUSED, + SOF_IPC4_PIPE_RUNNING, + SOF_IPC4_PIPE_EOS +}; + +/* Generic message fields (bit 24-30) */ + +/* encoded to header's msg_tgt field */ +#define SOF_IPC4_MSG_TARGET_SHIFT 30 +#define SOF_IPC4_MSG_TARGET_MASK BIT(30) +#define SOF_IPC4_MSG_TARGET(x) ((x) << SOF_IPC4_MSG_TARGET_SHIFT) +#define SOF_IPC4_MSG_IS_MODULE_MSG(x) ((x) & SOF_IPC4_MSG_TARGET_MASK ? 1 : 0) + +/* encoded to header's rsp field */ +#define SOF_IPC4_MSG_DIR_SHIFT 29 +#define SOF_IPC4_MSG_DIR_MASK BIT(29) +#define SOF_IPC4_MSG_DIR(x) ((x) << SOF_IPC4_MSG_DIR_SHIFT) + +/* encoded to header's type field */ +#define SOF_IPC4_MSG_TYPE_SHIFT 24 +#define SOF_IPC4_MSG_TYPE_MASK GENMASK(28, 24) +#define SOF_IPC4_MSG_TYPE_SET(x) (((x) << SOF_IPC4_MSG_TYPE_SHIFT) & \ + SOF_IPC4_MSG_TYPE_MASK) +#define SOF_IPC4_MSG_TYPE_GET(x) (((x) & SOF_IPC4_MSG_TYPE_MASK) >> \ + SOF_IPC4_MSG_TYPE_SHIFT) + +/* Global message type specific field definitions */ + +/* pipeline creation ipc msg */ +#define SOF_IPC4_GLB_PIPE_INSTANCE_SHIFT 16 +#define SOF_IPC4_GLB_PIPE_INSTANCE_MASK GENMASK(23, 16) +#define SOF_IPC4_GLB_PIPE_INSTANCE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_INSTANCE_SHIFT) + +#define SOF_IPC4_GLB_PIPE_PRIORITY_SHIFT 11 +#define SOF_IPC4_GLB_PIPE_PRIORITY_MASK GENMASK(15, 11) +#define SOF_IPC4_GLB_PIPE_PRIORITY(x) ((x) << SOF_IPC4_GLB_PIPE_PRIORITY_SHIFT) + +#define SOF_IPC4_GLB_PIPE_MEM_SIZE_SHIFT 0 +#define SOF_IPC4_GLB_PIPE_MEM_SIZE_MASK GENMASK(10, 0) +#define SOF_IPC4_GLB_PIPE_MEM_SIZE(x) ((x) << SOF_IPC4_GLB_PIPE_MEM_SIZE_SHIFT) + +#define SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT 0 +#define SOF_IPC4_GLB_PIPE_EXT_LP_MASK BIT(0) +#define SOF_IPC4_GLB_PIPE_EXT_LP(x) ((x) << SOF_IPC4_GLB_PIPE_EXT_LP_SHIFT) + +/* pipeline set state ipc msg */ +#define SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT 16 +#define SOF_IPC4_GLB_PIPE_STATE_ID_MASK GENMASK(23, 16) +#define SOF_IPC4_GLB_PIPE_STATE_ID(x) ((x) << SOF_IPC4_GLB_PIPE_STATE_ID_SHIFT) + +#define SOF_IPC4_GLB_PIPE_STATE_SHIFT 0 +#define SOF_IPC4_GLB_PIPE_STATE_MASK GENMASK(15, 0) +#define SOF_IPC4_GLB_PIPE_STATE(x) ((x) << SOF_IPC4_GLB_PIPE_STATE_SHIFT) + +enum sof_ipc4_channel_config { + /* one channel only. */ + SOF_IPC4_CHANNEL_CONFIG_MONO, + /* L & R. */ + SOF_IPC4_CHANNEL_CONFIG_STEREO, + /* L, R & LFE; PCM only. */ + SOF_IPC4_CHANNEL_CONFIG_2_POINT_1, + /* L, C & R; MP3 & AAC only. */ + SOF_IPC4_CHANNEL_CONFIG_3_POINT_0, + /* L, C, R & LFE; PCM only. */ + SOF_IPC4_CHANNEL_CONFIG_3_POINT_1, + /* L, R, Ls & Rs; PCM only. */ + SOF_IPC4_CHANNEL_CONFIG_QUATRO, + /* L, C, R & Cs; MP3 & AAC only. */ + SOF_IPC4_CHANNEL_CONFIG_4_POINT_0, + /* L, C, R, Ls & Rs. */ + SOF_IPC4_CHANNEL_CONFIG_5_POINT_0, + /* L, C, R, Ls, Rs & LFE. */ + SOF_IPC4_CHANNEL_CONFIG_5_POINT_1, + /* one channel replicated in two. */ + SOF_IPC4_CHANNEL_CONFIG_DUAL_MONO, + /* Stereo (L,R) in 4 slots, 1st stream: [ L, R, -, - ] */ + SOF_IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_0, + /* Stereo (L,R) in 4 slots, 2nd stream: [ -, -, L, R ] */ + SOF_IPC4_CHANNEL_CONFIG_I2S_DUAL_STEREO_1, + /* L, C, R, Ls, Rs & LFE., LS, RS */ + SOF_IPC4_CHANNEL_CONFIG_7_POINT_1, +}; + +enum sof_ipc4_interleaved_style { + SOF_IPC4_CHANNELS_INTERLEAVED, + SOF_IPC4_CHANNELS_NONINTERLEAVED, +}; + +enum sof_ipc4_sample_type { + SOF_IPC4_MSB_INTEGER, /* integer with Most Significant Byte first */ + SOF_IPC4_LSB_INTEGER, /* integer with Least Significant Byte first */ +}; + +struct sof_ipc4_audio_format { + uint32_t sampling_frequency; + uint32_t bit_depth; + uint32_t ch_map; + uint32_t ch_cfg; /* sof_ipc4_channel_config */ + uint32_t interleaving_style; + uint32_t fmt_cfg; /* channels_count valid_bit_depth s_type */ +} __packed __aligned(4); + +#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_SHIFT 0 +#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_MASK GENMASK(7, 0) +#define SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(x) \ + ((x) & SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT_MASK) +#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_SHIFT 8 +#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_MASK GENMASK(15, 8) +#define SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(x) \ + (((x) & SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_MASK) >> \ + SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH_SHIFT) +#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_SHIFT 16 +#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_MASK GENMASK(23, 16) +#define SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(x) \ + (((x) & SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_MASK) >> \ + SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE_SHIFT) + +/* Module message type specific field definitions */ + +enum sof_ipc4_module_type { + SOF_IPC4_MOD_INIT_INSTANCE, + SOF_IPC4_MOD_CONFIG_GET, + SOF_IPC4_MOD_CONFIG_SET, + SOF_IPC4_MOD_LARGE_CONFIG_GET, + SOF_IPC4_MOD_LARGE_CONFIG_SET, + SOF_IPC4_MOD_BIND, + SOF_IPC4_MOD_UNBIND, + SOF_IPC4_MOD_SET_DX, + SOF_IPC4_MOD_SET_D0IX, + SOF_IPC4_MOD_ENTER_MODULE_RESTORE, + SOF_IPC4_MOD_EXIT_MODULE_RESTORE, + SOF_IPC4_MOD_DELETE_INSTANCE, + + SOF_IPC4_MOD_TYPE_LAST, +}; + +struct sof_ipc4_base_module_cfg { + uint32_t cpc; /* the max count of Cycles Per Chunk processing */ + uint32_t ibs; /* input Buffer Size (in bytes) */ + uint32_t obs; /* output Buffer Size (in bytes) */ + uint32_t is_pages; /* number of physical pages used */ + struct sof_ipc4_audio_format audio_fmt; +} __packed __aligned(4); + +/* common module ipc msg */ +#define SOF_IPC4_MOD_INSTANCE_SHIFT 16 +#define SOF_IPC4_MOD_INSTANCE_MASK GENMASK(23, 16) +#define SOF_IPC4_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_INSTANCE_SHIFT) + +#define SOF_IPC4_MOD_ID_SHIFT 0 +#define SOF_IPC4_MOD_ID_MASK GENMASK(15, 0) +#define SOF_IPC4_MOD_ID(x) ((x) << SOF_IPC4_MOD_ID_SHIFT) + +/* init module ipc msg */ +#define SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT 0 +#define SOF_IPC4_MOD_EXT_PARAM_SIZE_MASK GENMASK(15, 0) +#define SOF_IPC4_MOD_EXT_PARAM_SIZE(x) ((x) << SOF_IPC4_MOD_EXT_PARAM_SIZE_SHIFT) + +#define SOF_IPC4_MOD_EXT_PPL_ID_SHIFT 16 +#define SOF_IPC4_MOD_EXT_PPL_ID_MASK GENMASK(23, 16) +#define SOF_IPC4_MOD_EXT_PPL_ID(x) ((x) << SOF_IPC4_MOD_EXT_PPL_ID_SHIFT) + +#define SOF_IPC4_MOD_EXT_CORE_ID_SHIFT 24 +#define SOF_IPC4_MOD_EXT_CORE_ID_MASK GENMASK(27, 24) +#define SOF_IPC4_MOD_EXT_CORE_ID(x) ((x) << SOF_IPC4_MOD_EXT_CORE_ID_SHIFT) + +#define SOF_IPC4_MOD_EXT_DOMAIN_SHIFT 28 +#define SOF_IPC4_MOD_EXT_DOMAIN_MASK BIT(28) +#define SOF_IPC4_MOD_EXT_DOMAIN(x) ((x) << SOF_IPC4_MOD_EXT_DOMAIN_SHIFT) + +/* bind/unbind module ipc msg */ +#define SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT 0 +#define SOF_IPC4_MOD_EXT_DST_MOD_ID_MASK GENMASK(15, 0) +#define SOF_IPC4_MOD_EXT_DST_MOD_ID(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_ID_SHIFT) + +#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_SHIFT 16 +#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_MASK GENMASK(23, 16) +#define SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_INSTANCE_SHIFT) + +#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_SHIFT 24 +#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_MASK GENMASK(26, 24) +#define SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID(x) ((x) << SOF_IPC4_MOD_EXT_DST_MOD_QUEUE_ID_SHIFT) + +#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_SHIFT 27 +#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_MASK GENMASK(29, 27) +#define SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID(x) ((x) << SOF_IPC4_MOD_EXT_SRC_MOD_QUEUE_ID_SHIFT) + +#define MOD_ENABLE_LOG 6 +#define MOD_SYSTEM_TIME 20 + +/* set module large config */ +#define SOF_IPC4_MOD_EXT_MSG_SIZE_SHIFT 0 +#define SOF_IPC4_MOD_EXT_MSG_SIZE_MASK GENMASK(19, 0) +#define SOF_IPC4_MOD_EXT_MSG_SIZE(x) ((x) << SOF_IPC4_MOD_EXT_MSG_SIZE_SHIFT) + +#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT 20 +#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID_MASK GENMASK(27, 20) +#define SOF_IPC4_MOD_EXT_MSG_PARAM_ID(x) ((x) << SOF_IPC4_MOD_EXT_MSG_PARAM_ID_SHIFT) + +#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_SHIFT 28 +#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_MASK BIT(28) +#define SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK(x) ((x) << SOF_IPC4_MOD_EXT_MSG_LAST_BLOCK_SHIFT) + +#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_SHIFT 29 +#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_MASK BIT(29) +#define SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK(x) ((x) << SOF_IPC4_MOD_EXT_MSG_FIRST_BLOCK_SHIFT) + +/* Init instance messagees */ +#define SOF_IPC4_MOD_INIT_BASEFW_MOD_ID 0 +#define SOF_IPC4_MOD_INIT_BASEFW_INSTANCE_ID 0 + +enum sof_ipc4_base_fw_params { + SOF_IPC4_FW_PARAM_ENABLE_LOGS = 6, + SOF_IPC4_FW_PARAM_FW_CONFIG, + SOF_IPC4_FW_PARAM_HW_CONFIG_GET, + SOF_IPC4_FW_PARAM_MODULES_INFO_GET, + SOF_IPC4_FW_PARAM_LIBRARIES_INFO_GET = 16, + SOF_IPC4_FW_PARAM_SYSTEM_TIME = 20, +}; + +enum sof_ipc4_fw_config_params { + SOF_IPC4_FW_CFG_FW_VERSION, + SOF_IPC4_FW_CFG_MEMORY_RECLAIMED, + SOF_IPC4_FW_CFG_SLOW_CLOCK_FREQ_HZ, + SOF_IPC4_FW_CFG_FAST_CLOCK_FREQ_HZ, + SOF_IPC4_FW_CFG_DMA_BUFFER_CONFIG, + SOF_IPC4_FW_CFG_ALH_SUPPORT_LEVEL, + SOF_IPC4_FW_CFG_DL_MAILBOX_BYTES, + SOF_IPC4_FW_CFG_UL_MAILBOX_BYTES, + SOF_IPC4_FW_CFG_TRACE_LOG_BYTES, + SOF_IPC4_FW_CFG_MAX_PPL_COUNT, + SOF_IPC4_FW_CFG_MAX_ASTATE_COUNT, + SOF_IPC4_FW_CFG_MAX_MODULE_PIN_COUNT, + SOF_IPC4_FW_CFG_MODULES_COUNT, + SOF_IPC4_FW_CFG_MAX_MOD_INST_COUNT, + SOF_IPC4_FW_CFG_MAX_LL_TASKS_PER_PRI_COUNT, + SOF_IPC4_FW_CFG_LL_PRI_COUNT, + SOF_IPC4_FW_CFG_MAX_DP_TASKS_COUNT, + SOF_IPC4_FW_CFG_MAX_LIBS_COUNT, + SOF_IPC4_FW_CFG_SCHEDULER_CONFIG, + SOF_IPC4_FW_CFG_XTAL_FREQ_HZ, + SOF_IPC4_FW_CFG_CLOCKS_CONFIG, + SOF_IPC4_FW_CFG_RESERVED, + SOF_IPC4_FW_CFG_POWER_GATING_POLICY, + SOF_IPC4_FW_CFG_ASSERT_MODE, +}; + +struct sof_ipc4_fw_version { + uint16_t major; + uint16_t minor; + uint16_t hotfix; + uint16_t build; +} __packed; + +/* Payload data for SOF_IPC4_MOD_SET_DX */ +struct sof_ipc4_dx_state_info { + /* core(s) to apply the change */ + uint32_t core_mask; + /* core state: 0: put core_id to D3; 1: put core_id to D0 */ + uint32_t dx_mask; +} __packed __aligned(4); + +/* Reply messages */ + +/* + * IPC4 primary header bit allocation for replies + * bit 0-23: status + * bit 24-28: type: enum sof_ipc4_global_msg if target is SOF_IPC4_FW_GEN_MSG + * enum sof_ipc4_module_type if target is SOF_IPC4_MODULE_MSG + * bit 29: response - sof_ipc4_msg_dir + * bit 30: target - enum sof_ipc4_msg_target + * bit 31: reserved, unused + */ + +#define SOF_IPC4_REPLY_STATUS GENMASK(23, 0) + +/* Notification messages */ + +/* + * IPC4 primary header bit allocation for notifications + * bit 0-15: notification type specific + * bit 16-23: enum sof_ipc4_notification_type + * bit 24-28: SOF_IPC4_GLB_NOTIFICATION + * bit 29: response - sof_ipc4_msg_dir + * bit 30: target - enum sof_ipc4_msg_target + * bit 31: reserved, unused + */ + +#define SOF_IPC4_MSG_IS_NOTIFICATION(x) (SOF_IPC4_MSG_TYPE_GET(x) == \ + SOF_IPC4_GLB_NOTIFICATION) + +#define SOF_IPC4_NOTIFICATION_TYPE_SHIFT 16 +#define SOF_IPC4_NOTIFICATION_TYPE_MASK GENMASK(23, 16) +#define SOF_IPC4_NOTIFICATION_TYPE_GET(x) (((x) & SOF_IPC4_NOTIFICATION_TYPE_MASK) >> \ + SOF_IPC4_NOTIFICATION_TYPE_SHIFT) + +#define SOF_IPC4_LOG_CORE_SHIFT 12 +#define SOF_IPC4_LOG_CORE_MASK GENMASK(15, 12) +#define SOF_IPC4_LOG_CORE_GET(x) (((x) & SOF_IPC4_LOG_CORE_MASK) >> \ + SOF_IPC4_LOG_CORE_SHIFT) + +/* Value of notification type field - must fit into 8 bits */ +enum sof_ipc4_notification_type { + /* Phrase detected (notification from WoV module) */ + SOF_IPC4_NOTIFY_PHRASE_DETECTED = 4, + /* Event from a resource (pipeline or module instance) */ + SOF_IPC4_NOTIFY_RESOURCE_EVENT, + /* Debug log buffer status changed */ + SOF_IPC4_NOTIFY_LOG_BUFFER_STATUS, + /* Timestamp captured at the link */ + SOF_IPC4_NOTIFY_TIMESTAMP_CAPTURED, + /* FW complete initialization */ + SOF_IPC4_NOTIFY_FW_READY, + /* Audio classifier result (ACA) */ + SOF_IPC4_NOTIFY_FW_AUD_CLASS_RESULT, + /* Exception caught by DSP FW */ + SOF_IPC4_NOTIFY_EXCEPTION_CAUGHT, + /* 11 is skipped by the existing cavs firmware */ + /* Custom module notification */ + SOF_IPC4_NOTIFY_MODULE_NOTIFICATION = 12, + /* 13 is reserved - do not use */ + /* Probe notify data available */ + SOF_IPC4_NOTIFY_PROBE_DATA_AVAILABLE = 14, + /* AM module notifications */ + SOF_IPC4_NOTIFY_ASYNC_MSG_SRVC_MESSAGE, + + SOF_IPC4_NOTIFY_TYPE_LAST, +}; + +struct sof_ipc4_notify_resource_data { + uint32_t resource_type; + uint32_t resource_id; + uint32_t event_type; + uint32_t reserved; + uint32_t data[6]; +} __packed __aligned(4); + +/** @}*/ + +#endif diff --git a/include/sound/sof/pm.h b/include/sound/sof/pm.h index 3cf2e0f39d94..366aa6ec442b 100644 --- a/include/sound/sof/pm.h +++ b/include/sound/sof/pm.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/sof/stream.h b/include/sound/sof/stream.h index 7facefb541b3..9377113f13e4 100644 --- a/include/sound/sof/stream.h +++ b/include/sound/sof/stream.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -85,9 +85,12 @@ struct sof_ipc_stream_params { uint32_t host_period_bytes; uint16_t no_stream_position; /**< 1 means don't send stream position */ - - uint16_t reserved[3]; + uint8_t cont_update_posn; /**< 1 means continuous update stream position */ + uint8_t reserved0; + int16_t ext_data_length; /**< 0, means no extended data */ + uint8_t reserved[2]; uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */ + uint8_t ext_data[]; /**< extended data */ } __packed; /* PCM params info - SOF_IPC_STREAM_PCM_PARAMS */ diff --git a/include/sound/sof/topology.h b/include/sound/sof/topology.h index 8e76178fedf0..88560281d420 100644 --- a/include/sound/sof/topology.h +++ b/include/sound/sof/topology.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -37,6 +37,8 @@ enum sof_comp_type { SOF_COMP_SELECTOR, /**< channel selector component */ SOF_COMP_DEMUX, SOF_COMP_ASRC, /**< Asynchronous sample rate converter */ + SOF_COMP_DCBLOCK, + SOF_COMP_SMART_AMP, /**< smart amplifier component */ /* keep FILEREAD/FILEWRITE as the last ones */ SOF_COMP_FILEREAD = 10000, /**< host test based file IO */ SOF_COMP_FILEWRITE = 10001, /**< host test based file IO */ @@ -53,9 +55,10 @@ struct sof_ipc_comp { uint32_t id; enum sof_comp_type type; uint32_t pipeline_id; + uint32_t core; - /* reserved for future use */ - uint32_t reserved[2]; + /* extended data length, 0 if no extended data */ + uint32_t ext_data_length; } __packed; /* @@ -74,11 +77,23 @@ struct sof_ipc_comp { #define SOF_MEM_CAPS_CACHE (1 << 6) /**< cacheable */ #define SOF_MEM_CAPS_EXEC (1 << 7) /**< executable */ +/* + * overrun will cause ring buffer overwrite, instead of XRUN. + */ +#define SOF_BUF_OVERRUN_PERMITTED BIT(0) + +/* + * underrun will cause readback of 0s, instead of XRUN. + */ +#define SOF_BUF_UNDERRUN_PERMITTED BIT(1) + /* create new component buffer - SOF_IPC_TPLG_BUFFER_NEW */ struct sof_ipc_buffer { struct sof_ipc_comp comp; uint32_t size; /**< buffer size in bytes */ uint32_t caps; /**< SOF_MEM_CAPS_ */ + uint32_t flags; /**< SOF_BUF_ flags defined above */ + uint32_t reserved; /**< reserved for future use */ } __packed; /* generic component config data - must always be after struct sof_ipc_comp */ @@ -205,6 +220,8 @@ enum sof_ipc_process_type { SOF_PROCESS_CHAN_SELECTOR, /**< Channel Selector */ SOF_PROCESS_MUX, SOF_PROCESS_DEMUX, + SOF_PROCESS_DCBLOCK, + SOF_PROCESS_SMART_AMP, /**< Smart Amplifier */ }; /* generic "effect", "codec" or proprietary processing component */ @@ -217,7 +234,7 @@ struct sof_ipc_comp_process { /* reserved for future use */ uint32_t reserved[7]; - unsigned char data[0]; + uint8_t data[]; } __packed; /* frees components, buffers and pipelines diff --git a/include/sound/sof/trace.h b/include/sound/sof/trace.h index fda6e8f6ead4..25ea99f62d37 100644 --- a/include/sound/sof/trace.h +++ b/include/sound/sof/trace.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. @@ -43,6 +43,34 @@ struct sof_ipc_dma_trace_posn { uint32_t messages; /* total trace messages */ } __packed; +/* Values used in sof_ipc_trace_filter_elem: */ + +/* bits 6..0 */ +#define SOF_IPC_TRACE_FILTER_ELEM_SET_LEVEL 0x01 /**< trace level for selected components */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_UUID 0x02 /**< filter by uuid key */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_PIPE 0x03 /**< filter by pipeline */ +#define SOF_IPC_TRACE_FILTER_ELEM_BY_COMP 0x04 /**< filter by component id */ + +/* bit 7 */ +#define SOF_IPC_TRACE_FILTER_ELEM_FIN 0x80 /**< mark last filter in set */ + +/* bits 31..8: Unused */ + +/** part of sof_ipc_trace_filter, ABI3.17 */ +struct sof_ipc_trace_filter_elem { + uint32_t key; /**< SOF_IPC_TRACE_FILTER_ELEM_ {LEVEL, UUID, COMP, PIPE} */ + uint32_t value; /**< element value */ +} __packed; + +/** Runtime tracing filtration data - SOF_IPC_TRACE_FILTER_UPDATE, ABI3.17 */ +struct sof_ipc_trace_filter { + struct sof_ipc_cmd_hdr hdr; /**< IPC command header */ + uint32_t elem_cnt; /**< number of entries in elems[] array */ + uint32_t reserved[8]; /**< reserved for future usage */ + /** variable size array with new filtering settings */ + struct sof_ipc_trace_filter_elem elems[]; +} __packed; + /* * Commom debug */ @@ -72,7 +100,7 @@ struct sof_ipc_dma_trace_posn { struct sof_ipc_panic_info { struct sof_ipc_hdr hdr; uint32_t code; /* SOF_IPC_PANIC_ */ - char filename[SOF_TRACE_FILENAME_SIZE]; + uint8_t filename[SOF_TRACE_FILENAME_SIZE]; uint32_t linenum; } __packed; diff --git a/include/sound/sof/xtensa.h b/include/sound/sof/xtensa.h index dd53d36b34e1..87a07e520415 100644 --- a/include/sound/sof/xtensa.h +++ b/include/sound/sof/xtensa.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */ /* * This file is provided under a dual BSD/GPLv2 license. When using or * redistributing this file, you may do so under either license. diff --git a/include/sound/timer.h b/include/sound/timer.h index 23e885d31525..760e132cc0cd 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -21,13 +21,13 @@ #define SNDRV_TIMER_HW_STOP 0x00000002 /* call stop before start */ #define SNDRV_TIMER_HW_SLAVE 0x00000004 /* only slave timer (variable resolution) */ #define SNDRV_TIMER_HW_FIRST 0x00000008 /* first tick can be incomplete */ -#define SNDRV_TIMER_HW_TASKLET 0x00000010 /* timer is called from tasklet */ +#define SNDRV_TIMER_HW_WORK 0x00000010 /* timer is called from work */ #define SNDRV_TIMER_IFLG_SLAVE 0x00000001 #define SNDRV_TIMER_IFLG_RUNNING 0x00000002 #define SNDRV_TIMER_IFLG_START 0x00000004 #define SNDRV_TIMER_IFLG_AUTO 0x00000008 /* auto restart */ -#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use tasklet) */ +#define SNDRV_TIMER_IFLG_FAST 0x00000010 /* fast callback (do not use work) */ #define SNDRV_TIMER_IFLG_CALLBACK 0x00000020 /* timer callback is active */ #define SNDRV_TIMER_IFLG_EXCLUSIVE 0x00000040 /* exclusive owner - no more instances */ #define SNDRV_TIMER_IFLG_EARLY_EVENT 0x00000080 /* write early event to the poll queue */ @@ -74,7 +74,7 @@ struct snd_timer { struct list_head active_list_head; struct list_head ack_list_head; struct list_head sack_list_head; /* slow ack list head */ - struct tasklet_struct task_queue; + struct work_struct task_work; int max_instances; /* upper limit of timer instances */ int num_instances; /* current number of timer instances */ }; @@ -96,7 +96,7 @@ struct snd_timer_instance { unsigned long ticks; /* auto-load ticks when expired */ unsigned long cticks; /* current ticks */ unsigned long pticks; /* accumulated ticks for callback */ - unsigned long resolution; /* current resolution for tasklet */ + unsigned long resolution; /* current resolution for work */ unsigned long lost; /* lost ticks */ int slave_class; unsigned int slave_id; diff --git a/include/sound/wm8960.h b/include/sound/wm8960.h index d22e84805025..275fd5b201ce 100644 --- a/include/sound/wm8960.h +++ b/include/sound/wm8960.h @@ -16,6 +16,23 @@ struct wm8960_data { bool capless; /* Headphone outputs configured in capless mode */ bool shared_lrclk; /* DAC and ADC LRCLKs are wired together */ + + /* + * Setup for headphone detection + * + * hp_cfg[0]: HPSEL[1:0] of R48 (Additional Control 4) + * hp_cfg[1]: {HPSWEN:HPSWPOL} of R24 (Additional Control 2). + * hp_cfg[2]: {TOCLKSEL:TOEN} of R23 (Additional Control 1). + */ + u32 hp_cfg[3]; + + /* + * Setup for gpio configuration + * + * gpio_cfg[0]: ALRCGPIO of R9 (Audio interface) + * gpio_cfg[1]: {GPIOPOL:GPIOSEL[2:0]} of R48 (Additional Control 4). + */ + u32 gpio_cfg[2]; }; #endif |