Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Add Pink Sardine platform ASoC driver

Merge series from Syed Saba Kareem <Syed.SabaKareem@amd.com>:

Pink Sardine platform is new APU series based on acp6.2 design.
This patch set adds an ASoC driver for the ACP (Audio CoProcessor) block
on AMD Pink Sardine APU with DMIC endpoint support.

+1455
+444
include/sound/acp62_chip_offset_byte.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * AMD ACP 6.2 Register Documentation 4 + * 5 + * Copyright 2022 Advanced Micro Devices, Inc. 6 + */ 7 + 8 + #ifndef _acp_ip_OFFSET_HEADER 9 + #define _acp_ip_OFFSET_HEADER 10 + 11 + /* Registers from ACP_DMA block */ 12 + #define ACP_DMA_CNTL_0 0x0000000 13 + #define ACP_DMA_CNTL_1 0x0000004 14 + #define ACP_DMA_CNTL_2 0x0000008 15 + #define ACP_DMA_CNTL_3 0x000000C 16 + #define ACP_DMA_CNTL_4 0x0000010 17 + #define ACP_DMA_CNTL_5 0x0000014 18 + #define ACP_DMA_CNTL_6 0x0000018 19 + #define ACP_DMA_CNTL_7 0x000001C 20 + #define ACP_DMA_DSCR_STRT_IDX_0 0x0000020 21 + #define ACP_DMA_DSCR_STRT_IDX_1 0x0000024 22 + #define ACP_DMA_DSCR_STRT_IDX_2 0x0000028 23 + #define ACP_DMA_DSCR_STRT_IDX_3 0x000002C 24 + #define ACP_DMA_DSCR_STRT_IDX_4 0x0000030 25 + #define ACP_DMA_DSCR_STRT_IDX_5 0x0000034 26 + #define ACP_DMA_DSCR_STRT_IDX_6 0x0000038 27 + #define ACP_DMA_DSCR_STRT_IDX_7 0x000003C 28 + #define ACP_DMA_DSCR_CNT_0 0x0000040 29 + #define ACP_DMA_DSCR_CNT_1 0x0000044 30 + #define ACP_DMA_DSCR_CNT_2 0x0000048 31 + #define ACP_DMA_DSCR_CNT_3 0x000004C 32 + #define ACP_DMA_DSCR_CNT_4 0x0000050 33 + #define ACP_DMA_DSCR_CNT_5 0x0000054 34 + #define ACP_DMA_DSCR_CNT_6 0x0000058 35 + #define ACP_DMA_DSCR_CNT_7 0x000005C 36 + #define ACP_DMA_PRIO_0 0x0000060 37 + #define ACP_DMA_PRIO_1 0x0000064 38 + #define ACP_DMA_PRIO_2 0x0000068 39 + #define ACP_DMA_PRIO_3 0x000006C 40 + #define ACP_DMA_PRIO_4 0x0000070 41 + #define ACP_DMA_PRIO_5 0x0000074 42 + #define ACP_DMA_PRIO_6 0x0000078 43 + #define ACP_DMA_PRIO_7 0x000007C 44 + #define ACP_DMA_CUR_DSCR_0 0x0000080 45 + #define ACP_DMA_CUR_DSCR_1 0x0000084 46 + #define ACP_DMA_CUR_DSCR_2 0x0000088 47 + #define ACP_DMA_CUR_DSCR_3 0x000008C 48 + #define ACP_DMA_CUR_DSCR_4 0x0000090 49 + #define ACP_DMA_CUR_DSCR_5 0x0000094 50 + #define ACP_DMA_CUR_DSCR_6 0x0000098 51 + #define ACP_DMA_CUR_DSCR_7 0x000009C 52 + #define ACP_DMA_CUR_TRANS_CNT_0 0x00000A0 53 + #define ACP_DMA_CUR_TRANS_CNT_1 0x00000A4 54 + #define ACP_DMA_CUR_TRANS_CNT_2 0x00000A8 55 + #define ACP_DMA_CUR_TRANS_CNT_3 0x00000AC 56 + #define ACP_DMA_CUR_TRANS_CNT_4 0x00000B0 57 + #define ACP_DMA_CUR_TRANS_CNT_5 0x00000B4 58 + #define ACP_DMA_CUR_TRANS_CNT_6 0x00000B8 59 + #define ACP_DMA_CUR_TRANS_CNT_7 0x00000BC 60 + #define ACP_DMA_ERR_STS_0 0x00000C0 61 + #define ACP_DMA_ERR_STS_1 0x00000C4 62 + #define ACP_DMA_ERR_STS_2 0x00000C8 63 + #define ACP_DMA_ERR_STS_3 0x00000CC 64 + #define ACP_DMA_ERR_STS_4 0x00000D0 65 + #define ACP_DMA_ERR_STS_5 0x00000D4 66 + #define ACP_DMA_ERR_STS_6 0x00000D8 67 + #define ACP_DMA_ERR_STS_7 0x00000DC 68 + #define ACP_DMA_DESC_BASE_ADDR 0x00000E0 69 + #define ACP_DMA_DESC_MAX_NUM_DSCR 0x00000E4 70 + #define ACP_DMA_CH_STS 0x00000E8 71 + #define ACP_DMA_CH_GROUP 0x00000EC 72 + #define ACP_DMA_CH_RST_STS 0x00000F0 73 + 74 + /* Registers from ACP_AXI2AXIATU block */ 75 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1 0x0000C00 76 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_1 0x0000C04 77 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_2 0x0000C08 78 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_2 0x0000C0C 79 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_3 0x0000C10 80 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_3 0x0000C14 81 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_4 0x0000C18 82 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_4 0x0000C1C 83 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_5 0x0000C20 84 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_5 0x0000C24 85 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_6 0x0000C28 86 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_6 0x0000C2C 87 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_7 0x0000C30 88 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_7 0x0000C34 89 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_8 0x0000C38 90 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_8 0x0000C3C 91 + #define ACPAXI2AXI_ATU_CTRL 0x0000C40 92 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_9 0x0000C44 93 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_9 0x0000C48 94 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_10 0x0000C4C 95 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_10 0x0000C50 96 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_11 0x0000C54 97 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_11 0x0000C58 98 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_12 0x0000C5C 99 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_12 0x0000C60 100 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_13 0x0000C64 101 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_13 0x0000C68 102 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_14 0x0000C6C 103 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_14 0x0000C70 104 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_15 0x0000C74 105 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_15 0x0000C78 106 + #define ACPAXI2AXI_ATU_PAGE_SIZE_GRP_16 0x0000C7C 107 + #define ACPAXI2AXI_ATU_BASE_ADDR_GRP_16 0x0000C80 108 + 109 + /* Registers from ACP_CLKRST block */ 110 + #define ACP_SOFT_RESET 0x0001000 111 + #define ACP_CONTROL 0x0001004 112 + #define ACP_STATUS 0x0001008 113 + #define ACP_DYNAMIC_CG_MASTER_CONTROL 0x0001010 114 + #define ACP_ZSC_DSP_CTRL 0x0001014 115 + #define ACP_ZSC_STS 0x0001018 116 + #define ACP_PGFSM_CONTROL 0x0001024 117 + #define ACP_PGFSM_STATUS 0x0001028 118 + #define ACP_CLKMUX_SEL 0x000102C 119 + 120 + /* Registers from ACP_AON block */ 121 + #define ACP_PME_EN 0x0001400 122 + #define ACP_DEVICE_STATE 0x0001404 123 + #define AZ_DEVICE_STATE 0x0001408 124 + #define ACP_PIN_CONFIG 0x0001440 125 + #define ACP_PAD_PULLUP_CTRL 0x0001444 126 + #define ACP_PAD_PULLDOWN_CTRL 0x0001448 127 + #define ACP_PAD_DRIVE_STRENGTH_CTRL 0x000144C 128 + #define ACP_PAD_SCHMEN_CTRL 0x0001450 129 + #define ACP_SW_PAD_KEEPER_EN 0x0001454 130 + #define ACP_SW_WAKE_EN 0x0001458 131 + #define ACP_I2S_WAKE_EN 0x000145C 132 + #define ACP_SW1_WAKE_EN 0x0001460 133 + 134 + /* Registers from ACP_P1_MISC block */ 135 + #define ACP_EXTERNAL_INTR_ENB 0x0001A00 136 + #define ACP_EXTERNAL_INTR_CNTL 0x0001A04 137 + #define ACP_EXTERNAL_INTR_CNTL1 0x0001A08 138 + #define ACP_EXTERNAL_INTR_STAT 0x0001A0C 139 + #define ACP_EXTERNAL_INTR_STAT1 0x0001A10 140 + #define ACP_ERROR_STATUS 0x0001A4C 141 + #define ACP_P1_SW_I2S_ERROR_REASON 0x0001A50 142 + #define ACP_P1_SW_POS_TRACK_I2S_TX_CTRL 0x0001A6C 143 + #define ACP_P1_SW_I2S_TX_DMA_POS 0x0001A70 144 + #define ACP_P1_SW_POS_TRACK_I2S_RX_CTRL 0x0001A74 145 + #define ACP_P1_SW_I2S_RX_DMA_POS 0x0001A78 146 + #define ACP_P1_DMIC_I2S_GPIO_INTR_CTRL 0x0001A7C 147 + #define ACP_P1_DMIC_I2S_GPIO_INTR_STATUS 0x0001A80 148 + #define ACP_SCRATCH_REG_BASE_ADDR 0x0001A84 149 + #define ACP_P1_SW_POS_TRACK_BT_TX_CTRL 0x0001A88 150 + #define ACP_P1_SW_BT_TX_DMA_POS 0x0001A8C 151 + #define ACP_P1_SW_POS_TRACK_HS_TX_CTRL 0x0001A90 152 + #define ACP_P1_SW_HS_TX_DMA_POS 0x0001A94 153 + #define ACP_P1_SW_POS_TRACK_BT_RX_CTRL 0x0001A98 154 + #define ACP_P1_SW_BT_RX_DMA_POS 0x0001A9C 155 + #define ACP_P1_SW_POS_TRACK_HS_RX_CTRL 0x0001AA0 156 + #define ACP_P1_SW_HS_RX_DMA_POS 0x0001AA4 157 + 158 + /* Registers from ACP_AUDIO_BUFFERS block */ 159 + #define ACP_I2S_RX_RINGBUFADDR 0x0002000 160 + #define ACP_I2S_RX_RINGBUFSIZE 0x0002004 161 + #define ACP_I2S_RX_LINKPOSITIONCNTR 0x0002008 162 + #define ACP_I2S_RX_FIFOADDR 0x000200C 163 + #define ACP_I2S_RX_FIFOSIZE 0x0002010 164 + #define ACP_I2S_RX_DMA_SIZE 0x0002014 165 + #define ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0002018 166 + #define ACP_I2S_RX_LINEARPOSITIONCNTR_LOW 0x000201C 167 + #define ACP_I2S_RX_INTR_WATERMARK_SIZE 0x0002020 168 + #define ACP_I2S_TX_RINGBUFADDR 0x0002024 169 + #define ACP_I2S_TX_RINGBUFSIZE 0x0002028 170 + #define ACP_I2S_TX_LINKPOSITIONCNTR 0x000202C 171 + #define ACP_I2S_TX_FIFOADDR 0x0002030 172 + #define ACP_I2S_TX_FIFOSIZE 0x0002034 173 + #define ACP_I2S_TX_DMA_SIZE 0x0002038 174 + #define ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x000203C 175 + #define ACP_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0002040 176 + #define ACP_I2S_TX_INTR_WATERMARK_SIZE 0x0002044 177 + #define ACP_BT_RX_RINGBUFADDR 0x0002048 178 + #define ACP_BT_RX_RINGBUFSIZE 0x000204C 179 + #define ACP_BT_RX_LINKPOSITIONCNTR 0x0002050 180 + #define ACP_BT_RX_FIFOADDR 0x0002054 181 + #define ACP_BT_RX_FIFOSIZE 0x0002058 182 + #define ACP_BT_RX_DMA_SIZE 0x000205C 183 + #define ACP_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0002060 184 + #define ACP_BT_RX_LINEARPOSITIONCNTR_LOW 0x0002064 185 + #define ACP_BT_RX_INTR_WATERMARK_SIZE 0x0002068 186 + #define ACP_BT_TX_RINGBUFADDR 0x000206C 187 + #define ACP_BT_TX_RINGBUFSIZE 0x0002070 188 + #define ACP_BT_TX_LINKPOSITIONCNTR 0x0002074 189 + #define ACP_BT_TX_FIFOADDR 0x0002078 190 + #define ACP_BT_TX_FIFOSIZE 0x000207C 191 + #define ACP_BT_TX_DMA_SIZE 0x0002080 192 + #define ACP_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0002084 193 + #define ACP_BT_TX_LINEARPOSITIONCNTR_LOW 0x0002088 194 + #define ACP_BT_TX_INTR_WATERMARK_SIZE 0x000208C 195 + #define ACP_HS_RX_RINGBUFADDR 0x0002090 196 + #define ACP_HS_RX_RINGBUFSIZE 0x0002094 197 + #define ACP_HS_RX_LINKPOSITIONCNTR 0x0002098 198 + #define ACP_HS_RX_FIFOADDR 0x000209C 199 + #define ACP_HS_RX_FIFOSIZE 0x00020A0 200 + #define ACP_HS_RX_DMA_SIZE 0x00020A4 201 + #define ACP_HS_RX_LINEARPOSITIONCNTR_HIGH 0x00020A8 202 + #define ACP_HS_RX_LINEARPOSITIONCNTR_LOW 0x00020AC 203 + #define ACP_HS_RX_INTR_WATERMARK_SIZE 0x00020B0 204 + #define ACP_HS_TX_RINGBUFADDR 0x00020B4 205 + #define ACP_HS_TX_RINGBUFSIZE 0x00020B8 206 + #define ACP_HS_TX_LINKPOSITIONCNTR 0x00020BC 207 + #define ACP_HS_TX_FIFOADDR 0x00020C0 208 + #define ACP_HS_TX_FIFOSIZE 0x00020C4 209 + #define ACP_HS_TX_DMA_SIZE 0x00020C8 210 + #define ACP_HS_TX_LINEARPOSITIONCNTR_HIGH 0x00020CC 211 + #define ACP_HS_TX_LINEARPOSITIONCNTR_LOW 0x00020D0 212 + #define ACP_HS_TX_INTR_WATERMARK_SIZE 0x00020D4 213 + 214 + /* Registers from ACP_I2S_TDM block */ 215 + #define ACP_I2STDM_IER 0x0002400 216 + #define ACP_I2STDM_IRER 0x0002404 217 + #define ACP_I2STDM_RXFRMT 0x0002408 218 + #define ACP_I2STDM_ITER 0x000240C 219 + #define ACP_I2STDM_TXFRMT 0x0002410 220 + #define ACP_I2STDM0_MSTRCLKGEN 0x0002414 221 + #define ACP_I2STDM1_MSTRCLKGEN 0x0002418 222 + #define ACP_I2STDM2_MSTRCLKGEN 0x000241C 223 + #define ACP_I2STDM_REFCLKGEN 0x0002420 224 + 225 + /* Registers from ACP_BT_TDM block */ 226 + #define ACP_BTTDM_IER 0x0002800 227 + #define ACP_BTTDM_IRER 0x0002804 228 + #define ACP_BTTDM_RXFRMT 0x0002808 229 + #define ACP_BTTDM_ITER 0x000280C 230 + #define ACP_BTTDM_TXFRMT 0x0002810 231 + #define ACP_HSTDM_IER 0x0002814 232 + #define ACP_HSTDM_IRER 0x0002818 233 + #define ACP_HSTDM_RXFRMT 0x000281C 234 + #define ACP_HSTDM_ITER 0x0002820 235 + #define ACP_HSTDM_TXFRMT 0x0002824 236 + 237 + /* Registers from ACP_WOV block */ 238 + #define ACP_WOV_PDM_ENABLE 0x0002C04 239 + #define ACP_WOV_PDM_DMA_ENABLE 0x0002C08 240 + #define ACP_WOV_RX_RINGBUFADDR 0x0002C0C 241 + #define ACP_WOV_RX_RINGBUFSIZE 0x0002C10 242 + #define ACP_WOV_RX_LINKPOSITIONCNTR 0x0002C14 243 + #define ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH 0x0002C18 244 + #define ACP_WOV_RX_LINEARPOSITIONCNTR_LOW 0x0002C1C 245 + #define ACP_WOV_RX_INTR_WATERMARK_SIZE 0x0002C20 246 + #define ACP_WOV_PDM_FIFO_FLUSH 0x0002C24 247 + #define ACP_WOV_PDM_NO_OF_CHANNELS 0x0002C28 248 + #define ACP_WOV_PDM_DECIMATION_FACTOR 0x0002C2C 249 + #define ACP_WOV_PDM_VAD_CTRL 0x0002C30 250 + #define ACP_WOV_WAKE 0x0002C54 251 + #define ACP_WOV_BUFFER_STATUS 0x0002C58 252 + #define ACP_WOV_MISC_CTRL 0x0002C5C 253 + #define ACP_WOV_CLK_CTRL 0x0002C60 254 + #define ACP_PDM_VAD_DYNAMIC_CLK_GATING_EN 0x0002C64 255 + #define ACP_WOV_ERROR_STATUS_REGISTER 0x0002C68 256 + #define ACP_PDM_CLKDIV 0x0002C6C 257 + 258 + /* Registers from ACP_P1_AUDIO_BUFFERS block */ 259 + #define ACP_P1_I2S_RX_RINGBUFADDR 0x0003A00 260 + #define ACP_P1_I2S_RX_RINGBUFSIZE 0x0003A04 261 + #define ACP_P1_I2S_RX_LINKPOSITIONCNTR 0x0003A08 262 + #define ACP_P1_I2S_RX_FIFOADDR 0x0003A0C 263 + #define ACP_P1_I2S_RX_FIFOSIZE 0x0003A10 264 + #define ACP_P1_I2S_RX_DMA_SIZE 0x0003A14 265 + #define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_HIGH 0x0003A18 266 + #define ACP_P1_I2S_RX_LINEARPOSITIONCNTR_LOW 0x0003A1C 267 + #define ACP_P1_I2S_RX_INTR_WATERMARK_SIZE 0x0003A20 268 + #define ACP_P1_I2S_TX_RINGBUFADDR 0x0003A24 269 + #define ACP_P1_I2S_TX_RINGBUFSIZE 0x0003A28 270 + #define ACP_P1_I2S_TX_LINKPOSITIONCNTR 0x0003A2C 271 + #define ACP_P1_I2S_TX_FIFOADDR 0x0003A30 272 + #define ACP_P1_I2S_TX_FIFOSIZE 0x0003A34 273 + #define ACP_P1_I2S_TX_DMA_SIZE 0x0003A38 274 + #define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_HIGH 0x0003A3C 275 + #define ACP_P1_I2S_TX_LINEARPOSITIONCNTR_LOW 0x0003A40 276 + #define ACP_P1_I2S_TX_INTR_WATERMARK_SIZE 0x0003A44 277 + #define ACP_P1_BT_RX_RINGBUFADDR 0x0003A48 278 + #define ACP_P1_BT_RX_RINGBUFSIZE 0x0003A4C 279 + #define ACP_P1_BT_RX_LINKPOSITIONCNTR 0x0003A50 280 + #define ACP_P1_BT_RX_FIFOADDR 0x0003A54 281 + #define ACP_P1_BT_RX_FIFOSIZE 0x0003A58 282 + #define ACP_P1_BT_RX_DMA_SIZE 0x0003A5C 283 + #define ACP_P1_BT_RX_LINEARPOSITIONCNTR_HIGH 0x0003A60 284 + #define ACP_P1_BT_RX_LINEARPOSITIONCNTR_LOW 0x0003A64 285 + #define ACP_P1_BT_RX_INTR_WATERMARK_SIZE 0x0003A68 286 + #define ACP_P1_BT_TX_RINGBUFADDR 0x0003A6C 287 + #define ACP_P1_BT_TX_RINGBUFSIZE 0x0003A70 288 + #define ACP_P1_BT_TX_LINKPOSITIONCNTR 0x0003A74 289 + #define ACP_P1_BT_TX_FIFOADDR 0x0003A78 290 + #define ACP_P1_BT_TX_FIFOSIZE 0x0003A7C 291 + #define ACP_P1_BT_TX_DMA_SIZE 0x0003A80 292 + #define ACP_P1_BT_TX_LINEARPOSITIONCNTR_HIGH 0x0003A84 293 + #define ACP_P1_BT_TX_LINEARPOSITIONCNTR_LOW 0x0003A88 294 + #define ACP_P1_BT_TX_INTR_WATERMARK_SIZE 0x0003A8C 295 + #define ACP_P1_HS_RX_RINGBUFADDR 0x0003A90 296 + #define ACP_P1_HS_RX_RINGBUFSIZE 0x0003A94 297 + #define ACP_P1_HS_RX_LINKPOSITIONCNTR 0x0003A98 298 + #define ACP_P1_HS_RX_FIFOADDR 0x0003A9C 299 + #define ACP_P1_HS_RX_FIFOSIZE 0x0003AA0 300 + #define ACP_P1_HS_RX_DMA_SIZE 0x0003AA4 301 + #define ACP_P1_HS_RX_LINEARPOSITIONCNTR_HIGH 0x0003AA8 302 + #define ACP_P1_HS_RX_LINEARPOSITIONCNTR_LOW 0x0003AAC 303 + #define ACP_P1_HS_RX_INTR_WATERMARK_SIZE 0x0003AB0 304 + #define ACP_P1_HS_TX_RINGBUFADDR 0x0003AB4 305 + #define ACP_P1_HS_TX_RINGBUFSIZE 0x0003AB8 306 + #define ACP_P1_HS_TX_LINKPOSITIONCNTR 0x0003ABC 307 + #define ACP_P1_HS_TX_FIFOADDR 0x0003AC0 308 + #define ACP_P1_HS_TX_FIFOSIZE 0x0003AC4 309 + #define ACP_P1_HS_TX_DMA_SIZE 0x0003AC8 310 + #define ACP_P1_HS_TX_LINEARPOSITIONCNTR_HIGH 0x0003ACC 311 + #define ACP_P1_HS_TX_LINEARPOSITIONCNTR_LOW 0x0003AD0 312 + #define ACP_P1_HS_TX_INTR_WATERMARK_SIZE 0x0003AD4 313 + 314 + /* Registers from ACP_SCRATCH block */ 315 + #define ACP_SCRATCH_REG_0 0x0010000 316 + #define ACP_SCRATCH_REG_1 0x0010004 317 + #define ACP_SCRATCH_REG_2 0x0010008 318 + #define ACP_SCRATCH_REG_3 0x001000C 319 + #define ACP_SCRATCH_REG_4 0x0010010 320 + #define ACP_SCRATCH_REG_5 0x0010014 321 + #define ACP_SCRATCH_REG_6 0x0010018 322 + #define ACP_SCRATCH_REG_7 0x001001C 323 + #define ACP_SCRATCH_REG_8 0x0010020 324 + #define ACP_SCRATCH_REG_9 0x0010024 325 + #define ACP_SCRATCH_REG_10 0x0010028 326 + #define ACP_SCRATCH_REG_11 0x001002C 327 + #define ACP_SCRATCH_REG_12 0x0010030 328 + #define ACP_SCRATCH_REG_13 0x0010034 329 + #define ACP_SCRATCH_REG_14 0x0010038 330 + #define ACP_SCRATCH_REG_15 0x001003C 331 + #define ACP_SCRATCH_REG_16 0x0010040 332 + #define ACP_SCRATCH_REG_17 0x0010044 333 + #define ACP_SCRATCH_REG_18 0x0010048 334 + #define ACP_SCRATCH_REG_19 0x001004C 335 + #define ACP_SCRATCH_REG_20 0x0010050 336 + #define ACP_SCRATCH_REG_21 0x0010054 337 + #define ACP_SCRATCH_REG_22 0x0010058 338 + #define ACP_SCRATCH_REG_23 0x001005C 339 + #define ACP_SCRATCH_REG_24 0x0010060 340 + #define ACP_SCRATCH_REG_25 0x0010064 341 + #define ACP_SCRATCH_REG_26 0x0010068 342 + #define ACP_SCRATCH_REG_27 0x001006C 343 + #define ACP_SCRATCH_REG_28 0x0010070 344 + #define ACP_SCRATCH_REG_29 0x0010074 345 + #define ACP_SCRATCH_REG_30 0x0010078 346 + #define ACP_SCRATCH_REG_31 0x001007C 347 + #define ACP_SCRATCH_REG_32 0x0010080 348 + #define ACP_SCRATCH_REG_33 0x0010084 349 + #define ACP_SCRATCH_REG_34 0x0010088 350 + #define ACP_SCRATCH_REG_35 0x001008C 351 + #define ACP_SCRATCH_REG_36 0x0010090 352 + #define ACP_SCRATCH_REG_37 0x0010094 353 + #define ACP_SCRATCH_REG_38 0x0010098 354 + #define ACP_SCRATCH_REG_39 0x001009C 355 + #define ACP_SCRATCH_REG_40 0x00100A0 356 + #define ACP_SCRATCH_REG_41 0x00100A4 357 + #define ACP_SCRATCH_REG_42 0x00100A8 358 + #define ACP_SCRATCH_REG_43 0x00100AC 359 + #define ACP_SCRATCH_REG_44 0x00100B0 360 + #define ACP_SCRATCH_REG_45 0x00100B4 361 + #define ACP_SCRATCH_REG_46 0x00100B8 362 + #define ACP_SCRATCH_REG_47 0x00100BC 363 + #define ACP_SCRATCH_REG_48 0x00100C0 364 + #define ACP_SCRATCH_REG_49 0x00100C4 365 + #define ACP_SCRATCH_REG_50 0x00100C8 366 + #define ACP_SCRATCH_REG_51 0x00100CC 367 + #define ACP_SCRATCH_REG_52 0x00100D0 368 + #define ACP_SCRATCH_REG_53 0x00100D4 369 + #define ACP_SCRATCH_REG_54 0x00100D8 370 + #define ACP_SCRATCH_REG_55 0x00100DC 371 + #define ACP_SCRATCH_REG_56 0x00100E0 372 + #define ACP_SCRATCH_REG_57 0x00100E4 373 + #define ACP_SCRATCH_REG_58 0x00100E8 374 + #define ACP_SCRATCH_REG_59 0x00100EC 375 + #define ACP_SCRATCH_REG_60 0x00100F0 376 + #define ACP_SCRATCH_REG_61 0x00100F4 377 + #define ACP_SCRATCH_REG_62 0x00100F8 378 + #define ACP_SCRATCH_REG_63 0x00100FC 379 + #define ACP_SCRATCH_REG_64 0x0010100 380 + #define ACP_SCRATCH_REG_65 0x0010104 381 + #define ACP_SCRATCH_REG_66 0x0010108 382 + #define ACP_SCRATCH_REG_67 0x001010C 383 + #define ACP_SCRATCH_REG_68 0x0010110 384 + #define ACP_SCRATCH_REG_69 0x0010114 385 + #define ACP_SCRATCH_REG_70 0x0010118 386 + #define ACP_SCRATCH_REG_71 0x001011C 387 + #define ACP_SCRATCH_REG_72 0x0010120 388 + #define ACP_SCRATCH_REG_73 0x0010124 389 + #define ACP_SCRATCH_REG_74 0x0010128 390 + #define ACP_SCRATCH_REG_75 0x001012C 391 + #define ACP_SCRATCH_REG_76 0x0010130 392 + #define ACP_SCRATCH_REG_77 0x0010134 393 + #define ACP_SCRATCH_REG_78 0x0010138 394 + #define ACP_SCRATCH_REG_79 0x001013C 395 + #define ACP_SCRATCH_REG_80 0x0010140 396 + #define ACP_SCRATCH_REG_81 0x0010144 397 + #define ACP_SCRATCH_REG_82 0x0010148 398 + #define ACP_SCRATCH_REG_83 0x001014C 399 + #define ACP_SCRATCH_REG_84 0x0010150 400 + #define ACP_SCRATCH_REG_85 0x0010154 401 + #define ACP_SCRATCH_REG_86 0x0010158 402 + #define ACP_SCRATCH_REG_87 0x001015C 403 + #define ACP_SCRATCH_REG_88 0x0010160 404 + #define ACP_SCRATCH_REG_89 0x0010164 405 + #define ACP_SCRATCH_REG_90 0x0010168 406 + #define ACP_SCRATCH_REG_91 0x001016C 407 + #define ACP_SCRATCH_REG_92 0x0010170 408 + #define ACP_SCRATCH_REG_93 0x0010174 409 + #define ACP_SCRATCH_REG_94 0x0010178 410 + #define ACP_SCRATCH_REG_95 0x001017C 411 + #define ACP_SCRATCH_REG_96 0x0010180 412 + #define ACP_SCRATCH_REG_97 0x0010184 413 + #define ACP_SCRATCH_REG_98 0x0010188 414 + #define ACP_SCRATCH_REG_99 0x001018C 415 + #define ACP_SCRATCH_REG_100 0x0010190 416 + #define ACP_SCRATCH_REG_101 0x0010194 417 + #define ACP_SCRATCH_REG_102 0x0010198 418 + #define ACP_SCRATCH_REG_103 0x001019C 419 + #define ACP_SCRATCH_REG_104 0x00101A0 420 + #define ACP_SCRATCH_REG_105 0x00101A4 421 + #define ACP_SCRATCH_REG_106 0x00101A8 422 + #define ACP_SCRATCH_REG_107 0x00101AC 423 + #define ACP_SCRATCH_REG_108 0x00101B0 424 + #define ACP_SCRATCH_REG_109 0x00101B4 425 + #define ACP_SCRATCH_REG_110 0x00101B8 426 + #define ACP_SCRATCH_REG_111 0x00101BC 427 + #define ACP_SCRATCH_REG_112 0x00101C0 428 + #define ACP_SCRATCH_REG_113 0x00101C4 429 + #define ACP_SCRATCH_REG_114 0x00101C8 430 + #define ACP_SCRATCH_REG_115 0x00101CC 431 + #define ACP_SCRATCH_REG_116 0x00101D0 432 + #define ACP_SCRATCH_REG_117 0x00101D4 433 + #define ACP_SCRATCH_REG_118 0x00101D8 434 + #define ACP_SCRATCH_REG_119 0x00101DC 435 + #define ACP_SCRATCH_REG_120 0x00101E0 436 + #define ACP_SCRATCH_REG_121 0x00101E4 437 + #define ACP_SCRATCH_REG_122 0x00101E8 438 + #define ACP_SCRATCH_REG_123 0x00101EC 439 + #define ACP_SCRATCH_REG_124 0x00101F0 440 + #define ACP_SCRATCH_REG_125 0x00101F4 441 + #define ACP_SCRATCH_REG_126 0x00101F8 442 + #define ACP_SCRATCH_REG_127 0x00101FC 443 + #define ACP_SCRATCH_REG_128 0x0010200 444 + #endif
+21
sound/soc/amd/Kconfig
··· 127 127 triggered for ACP PCI driver. 128 128 Say m if you have such a device. 129 129 If unsure select "N". 130 + 131 + config SND_SOC_AMD_PS 132 + tristate "AMD Audio Coprocessor-v6.2 Pink Sardine support" 133 + depends on X86 && PCI && ACPI 134 + help 135 + This option enables Audio Coprocessor i.e ACP v6.2 support on 136 + AMD Pink sardine platform. By enabling this flag build will be 137 + triggered for ACP PCI driver, ACP PDM DMA driver. 138 + Say m if you have such a device. 139 + If unsure select "N". 140 + 141 + config SND_SOC_AMD_PS_MACH 142 + tristate "AMD PINK SARDINE support for DMIC" 143 + select SND_SOC_DMIC 144 + depends on SND_SOC_AMD_PS 145 + help 146 + This option enables machine driver for Pink Sardine platform 147 + using dmic. ACP IP has PDM Decoder block with DMA controller. 148 + DMIC can be connected directly to ACP IP. 149 + Say m if you have such a device. 150 + If unsure select "N".
+1
sound/soc/amd/Makefile
··· 18 18 obj-$(CONFIG_SND_SOC_AMD_ACP_COMMON) += acp/ 19 19 obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o 20 20 obj-$(CONFIG_SND_SOC_AMD_RPL_ACP6x) += rpl/ 21 + obj-$(CONFIG_SND_SOC_AMD_PS) += ps/
+9
sound/soc/amd/ps/Makefile
··· 1 + # SPDX-License-Identifier: GPL-2.0+ 2 + # Pink Sardine platform Support 3 + snd-pci-ps-objs := pci-ps.o 4 + snd-ps-pdm-dma-objs := ps-pdm-dma.o 5 + snd-soc-ps-mach-objs := ps-mach.o 6 + 7 + obj-$(CONFIG_SND_SOC_AMD_PS) += snd-pci-ps.o 8 + obj-$(CONFIG_SND_SOC_AMD_PS) += snd-ps-pdm-dma.o 9 + obj-$(CONFIG_SND_SOC_AMD_PS_MACH) += snd-soc-ps-mach.o
+98
sound/soc/amd/ps/acp62.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * AMD ALSA SoC PDM Driver 4 + * 5 + * Copyright (C) 2022 Advanced Micro Devices, Inc. All rights reserved. 6 + */ 7 + 8 + #include <sound/acp62_chip_offset_byte.h> 9 + 10 + #define ACP_DEVICE_ID 0x15E2 11 + #define ACP6x_REG_START 0x1240000 12 + #define ACP6x_REG_END 0x1250200 13 + #define ACP6x_DEVS 3 14 + #define ACP6x_PDM_MODE 1 15 + 16 + #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 17 + #define ACP_PGFSM_CNTL_POWER_ON_MASK 1 18 + #define ACP_PGFSM_CNTL_POWER_OFF_MASK 0 19 + #define ACP_PGFSM_STATUS_MASK 3 20 + #define ACP_POWERED_ON 0 21 + #define ACP_POWER_ON_IN_PROGRESS 1 22 + #define ACP_POWERED_OFF 2 23 + #define ACP_POWER_OFF_IN_PROGRESS 3 24 + 25 + #define ACP_ERROR_MASK 0x20000000 26 + #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF 27 + #define PDM_DMA_STAT 0x10 28 + 29 + #define PDM_DMA_INTR_MASK 0x10000 30 + #define ACP_ERROR_STAT 29 31 + #define PDM_DECIMATION_FACTOR 2 32 + #define ACP_PDM_CLK_FREQ_MASK 7 33 + #define ACP_WOV_MISC_CTRL_MASK 0x10 34 + #define ACP_PDM_ENABLE 1 35 + #define ACP_PDM_DISABLE 0 36 + #define ACP_PDM_DMA_EN_STATUS 2 37 + #define TWO_CH 2 38 + #define DELAY_US 5 39 + #define ACP_COUNTER 20000 40 + 41 + #define ACP_SRAM_PTE_OFFSET 0x03800000 42 + #define PAGE_SIZE_4K_ENABLE 2 43 + #define PDM_PTE_OFFSET 0 44 + #define PDM_MEM_WINDOW_START 0x4000000 45 + 46 + #define CAPTURE_MIN_NUM_PERIODS 4 47 + #define CAPTURE_MAX_NUM_PERIODS 4 48 + #define CAPTURE_MAX_PERIOD_SIZE 8192 49 + #define CAPTURE_MIN_PERIOD_SIZE 4096 50 + 51 + #define MAX_BUFFER (CAPTURE_MAX_PERIOD_SIZE * CAPTURE_MAX_NUM_PERIODS) 52 + #define MIN_BUFFER MAX_BUFFER 53 + 54 + /* time in ms for runtime suspend delay */ 55 + #define ACP_SUSPEND_DELAY_MS 2000 56 + 57 + enum acp_config { 58 + ACP_CONFIG_0 = 0, 59 + ACP_CONFIG_1, 60 + ACP_CONFIG_2, 61 + ACP_CONFIG_3, 62 + ACP_CONFIG_4, 63 + ACP_CONFIG_5, 64 + ACP_CONFIG_6, 65 + ACP_CONFIG_7, 66 + ACP_CONFIG_8, 67 + ACP_CONFIG_9, 68 + ACP_CONFIG_10, 69 + ACP_CONFIG_11, 70 + ACP_CONFIG_12, 71 + ACP_CONFIG_13, 72 + ACP_CONFIG_14, 73 + ACP_CONFIG_15, 74 + }; 75 + 76 + struct pdm_stream_instance { 77 + u16 num_pages; 78 + u16 channels; 79 + dma_addr_t dma_addr; 80 + u64 bytescount; 81 + void __iomem *acp62_base; 82 + }; 83 + 84 + struct pdm_dev_data { 85 + u32 pdm_irq; 86 + void __iomem *acp62_base; 87 + struct snd_pcm_substream *capture_stream; 88 + }; 89 + 90 + static inline u32 acp62_readl(void __iomem *base_addr) 91 + { 92 + return readl(base_addr); 93 + } 94 + 95 + static inline void acp62_writel(u32 val, void __iomem *base_addr) 96 + { 97 + writel(val, base_addr); 98 + }
+351
sound/soc/amd/ps/pci-ps.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * AMD Pink Sardine ACP PCI Driver 4 + * 5 + * Copyright 2022 Advanced Micro Devices, Inc. 6 + */ 7 + 8 + #include <linux/pci.h> 9 + #include <linux/module.h> 10 + #include <linux/io.h> 11 + #include <linux/delay.h> 12 + #include <linux/platform_device.h> 13 + #include <linux/acpi.h> 14 + #include <linux/interrupt.h> 15 + #include <sound/pcm_params.h> 16 + #include <linux/pm_runtime.h> 17 + 18 + #include "acp62.h" 19 + 20 + struct acp62_dev_data { 21 + void __iomem *acp62_base; 22 + struct resource *res; 23 + bool acp62_audio_mode; 24 + struct platform_device *pdev[ACP6x_DEVS]; 25 + }; 26 + 27 + static int acp62_power_on(void __iomem *acp_base) 28 + { 29 + u32 val; 30 + int timeout; 31 + 32 + val = acp62_readl(acp_base + ACP_PGFSM_STATUS); 33 + 34 + if (!val) 35 + return val; 36 + 37 + if ((val & ACP_PGFSM_STATUS_MASK) != ACP_POWER_ON_IN_PROGRESS) 38 + acp62_writel(ACP_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL); 39 + timeout = 0; 40 + while (++timeout < 500) { 41 + val = acp62_readl(acp_base + ACP_PGFSM_STATUS); 42 + if (!val) 43 + return 0; 44 + udelay(1); 45 + } 46 + return -ETIMEDOUT; 47 + } 48 + 49 + static int acp62_reset(void __iomem *acp_base) 50 + { 51 + u32 val; 52 + int timeout; 53 + 54 + acp62_writel(1, acp_base + ACP_SOFT_RESET); 55 + timeout = 0; 56 + while (++timeout < 500) { 57 + val = acp62_readl(acp_base + ACP_SOFT_RESET); 58 + if (val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK) 59 + break; 60 + cpu_relax(); 61 + } 62 + acp62_writel(0, acp_base + ACP_SOFT_RESET); 63 + timeout = 0; 64 + while (++timeout < 500) { 65 + val = acp62_readl(acp_base + ACP_SOFT_RESET); 66 + if (!val) 67 + return 0; 68 + cpu_relax(); 69 + } 70 + return -ETIMEDOUT; 71 + } 72 + 73 + static void acp62_enable_interrupts(void __iomem *acp_base) 74 + { 75 + acp62_writel(1, acp_base + ACP_EXTERNAL_INTR_ENB); 76 + } 77 + 78 + static void acp62_disable_interrupts(void __iomem *acp_base) 79 + { 80 + acp62_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base + 81 + ACP_EXTERNAL_INTR_STAT); 82 + acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_CNTL); 83 + acp62_writel(0, acp_base + ACP_EXTERNAL_INTR_ENB); 84 + } 85 + 86 + static int acp62_init(void __iomem *acp_base, struct device *dev) 87 + { 88 + int ret; 89 + 90 + ret = acp62_power_on(acp_base); 91 + if (ret) { 92 + dev_err(dev, "ACP power on failed\n"); 93 + return ret; 94 + } 95 + acp62_writel(0x01, acp_base + ACP_CONTROL); 96 + ret = acp62_reset(acp_base); 97 + if (ret) { 98 + dev_err(dev, "ACP reset failed\n"); 99 + return ret; 100 + } 101 + acp62_writel(0x03, acp_base + ACP_CLKMUX_SEL); 102 + acp62_enable_interrupts(acp_base); 103 + return 0; 104 + } 105 + 106 + static int acp62_deinit(void __iomem *acp_base, struct device *dev) 107 + { 108 + int ret; 109 + 110 + acp62_disable_interrupts(acp_base); 111 + ret = acp62_reset(acp_base); 112 + if (ret) { 113 + dev_err(dev, "ACP reset failed\n"); 114 + return ret; 115 + } 116 + acp62_writel(0, acp_base + ACP_CLKMUX_SEL); 117 + acp62_writel(0, acp_base + ACP_CONTROL); 118 + return 0; 119 + } 120 + 121 + static irqreturn_t acp62_irq_handler(int irq, void *dev_id) 122 + { 123 + struct acp62_dev_data *adata; 124 + struct pdm_dev_data *ps_pdm_data; 125 + u32 val; 126 + 127 + adata = dev_id; 128 + if (!adata) 129 + return IRQ_NONE; 130 + 131 + val = acp62_readl(adata->acp62_base + ACP_EXTERNAL_INTR_STAT); 132 + if (val & BIT(PDM_DMA_STAT)) { 133 + ps_pdm_data = dev_get_drvdata(&adata->pdev[0]->dev); 134 + acp62_writel(BIT(PDM_DMA_STAT), adata->acp62_base + ACP_EXTERNAL_INTR_STAT); 135 + if (ps_pdm_data->capture_stream) 136 + snd_pcm_period_elapsed(ps_pdm_data->capture_stream); 137 + return IRQ_HANDLED; 138 + } 139 + return IRQ_NONE; 140 + } 141 + 142 + static int snd_acp62_probe(struct pci_dev *pci, 143 + const struct pci_device_id *pci_id) 144 + { 145 + struct acp62_dev_data *adata; 146 + struct platform_device_info pdevinfo[ACP6x_DEVS]; 147 + int index, ret; 148 + int val = 0x00; 149 + struct acpi_device *adev; 150 + const union acpi_object *obj; 151 + u32 addr; 152 + unsigned int irqflags; 153 + 154 + irqflags = IRQF_SHARED; 155 + /* Pink Sardine device check */ 156 + switch (pci->revision) { 157 + case 0x63: 158 + break; 159 + default: 160 + dev_dbg(&pci->dev, "acp62 pci device not found\n"); 161 + return -ENODEV; 162 + } 163 + if (pci_enable_device(pci)) { 164 + dev_err(&pci->dev, "pci_enable_device failed\n"); 165 + return -ENODEV; 166 + } 167 + 168 + ret = pci_request_regions(pci, "AMD ACP6.2 audio"); 169 + if (ret < 0) { 170 + dev_err(&pci->dev, "pci_request_regions failed\n"); 171 + goto disable_pci; 172 + } 173 + adata = devm_kzalloc(&pci->dev, sizeof(struct acp62_dev_data), 174 + GFP_KERNEL); 175 + if (!adata) { 176 + ret = -ENOMEM; 177 + goto release_regions; 178 + } 179 + 180 + addr = pci_resource_start(pci, 0); 181 + adata->acp62_base = devm_ioremap(&pci->dev, addr, 182 + pci_resource_len(pci, 0)); 183 + if (!adata->acp62_base) { 184 + ret = -ENOMEM; 185 + goto release_regions; 186 + } 187 + pci_set_master(pci); 188 + pci_set_drvdata(pci, adata); 189 + ret = acp62_init(adata->acp62_base, &pci->dev); 190 + if (ret) 191 + goto release_regions; 192 + val = acp62_readl(adata->acp62_base + ACP_PIN_CONFIG); 193 + switch (val) { 194 + case ACP_CONFIG_0: 195 + case ACP_CONFIG_1: 196 + case ACP_CONFIG_2: 197 + case ACP_CONFIG_3: 198 + case ACP_CONFIG_9: 199 + case ACP_CONFIG_15: 200 + dev_info(&pci->dev, "Audio Mode %d\n", val); 201 + break; 202 + default: 203 + 204 + /* Checking DMIC hardware*/ 205 + adev = acpi_find_child_device(ACPI_COMPANION(&pci->dev), 0x02, 0); 206 + 207 + if (!adev) 208 + break; 209 + 210 + if (!acpi_dev_get_property(adev, "acp-audio-device-type", 211 + ACPI_TYPE_INTEGER, &obj) && 212 + obj->integer.value == 2) { 213 + adata->res = devm_kzalloc(&pci->dev, sizeof(struct resource), GFP_KERNEL); 214 + if (!adata->res) { 215 + ret = -ENOMEM; 216 + goto de_init; 217 + } 218 + 219 + adata->res->name = "acp_iomem"; 220 + adata->res->flags = IORESOURCE_MEM; 221 + adata->res->start = addr; 222 + adata->res->end = addr + (ACP6x_REG_END - ACP6x_REG_START); 223 + adata->acp62_audio_mode = ACP6x_PDM_MODE; 224 + 225 + memset(&pdevinfo, 0, sizeof(pdevinfo)); 226 + pdevinfo[0].name = "acp_ps_pdm_dma"; 227 + pdevinfo[0].id = 0; 228 + pdevinfo[0].parent = &pci->dev; 229 + pdevinfo[0].num_res = 1; 230 + pdevinfo[0].res = adata->res; 231 + 232 + pdevinfo[1].name = "dmic-codec"; 233 + pdevinfo[1].id = 0; 234 + pdevinfo[1].parent = &pci->dev; 235 + 236 + pdevinfo[2].name = "acp_ps_mach"; 237 + pdevinfo[2].id = 0; 238 + pdevinfo[2].parent = &pci->dev; 239 + 240 + for (index = 0; index < ACP6x_DEVS; index++) { 241 + adata->pdev[index] = 242 + platform_device_register_full(&pdevinfo[index]); 243 + 244 + if (IS_ERR(adata->pdev[index])) { 245 + dev_err(&pci->dev, 246 + "cannot register %s device\n", 247 + pdevinfo[index].name); 248 + ret = PTR_ERR(adata->pdev[index]); 249 + goto unregister_devs; 250 + } 251 + ret = devm_request_irq(&pci->dev, pci->irq, acp62_irq_handler, 252 + irqflags, "ACP_PCI_IRQ", adata); 253 + if (ret) { 254 + dev_err(&pci->dev, "ACP PCI IRQ request failed\n"); 255 + goto unregister_devs; 256 + } 257 + } 258 + } 259 + break; 260 + } 261 + pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS); 262 + pm_runtime_use_autosuspend(&pci->dev); 263 + pm_runtime_put_noidle(&pci->dev); 264 + pm_runtime_allow(&pci->dev); 265 + return 0; 266 + unregister_devs: 267 + for (--index; index >= 0; index--) 268 + platform_device_unregister(adata->pdev[index]); 269 + de_init: 270 + if (acp62_deinit(adata->acp62_base, &pci->dev)) 271 + dev_err(&pci->dev, "ACP de-init failed\n"); 272 + release_regions: 273 + pci_release_regions(pci); 274 + disable_pci: 275 + pci_disable_device(pci); 276 + 277 + return ret; 278 + } 279 + 280 + static int __maybe_unused snd_acp62_suspend(struct device *dev) 281 + { 282 + struct acp62_dev_data *adata; 283 + int ret; 284 + 285 + adata = dev_get_drvdata(dev); 286 + ret = acp62_deinit(adata->acp62_base, dev); 287 + if (ret) 288 + dev_err(dev, "ACP de-init failed\n"); 289 + return ret; 290 + } 291 + 292 + static int __maybe_unused snd_acp62_resume(struct device *dev) 293 + { 294 + struct acp62_dev_data *adata; 295 + int ret; 296 + 297 + adata = dev_get_drvdata(dev); 298 + ret = acp62_init(adata->acp62_base, dev); 299 + if (ret) 300 + dev_err(dev, "ACP init failed\n"); 301 + return ret; 302 + } 303 + 304 + static const struct dev_pm_ops acp62_pm_ops = { 305 + SET_RUNTIME_PM_OPS(snd_acp62_suspend, snd_acp62_resume, NULL) 306 + SET_SYSTEM_SLEEP_PM_OPS(snd_acp62_suspend, snd_acp62_resume) 307 + }; 308 + 309 + static void snd_acp62_remove(struct pci_dev *pci) 310 + { 311 + struct acp62_dev_data *adata; 312 + int ret, index; 313 + 314 + adata = pci_get_drvdata(pci); 315 + if (adata->acp62_audio_mode == ACP6x_PDM_MODE) { 316 + for (index = 0; index < ACP6x_DEVS; index++) 317 + platform_device_unregister(adata->pdev[index]); 318 + } 319 + ret = acp62_deinit(adata->acp62_base, &pci->dev); 320 + if (ret) 321 + dev_err(&pci->dev, "ACP de-init failed\n"); 322 + pm_runtime_forbid(&pci->dev); 323 + pm_runtime_get_noresume(&pci->dev); 324 + pci_release_regions(pci); 325 + pci_disable_device(pci); 326 + } 327 + 328 + static const struct pci_device_id snd_acp62_ids[] = { 329 + { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID), 330 + .class = PCI_CLASS_MULTIMEDIA_OTHER << 8, 331 + .class_mask = 0xffffff }, 332 + { 0, }, 333 + }; 334 + MODULE_DEVICE_TABLE(pci, snd_acp62_ids); 335 + 336 + static struct pci_driver ps_acp62_driver = { 337 + .name = KBUILD_MODNAME, 338 + .id_table = snd_acp62_ids, 339 + .probe = snd_acp62_probe, 340 + .remove = snd_acp62_remove, 341 + .driver = { 342 + .pm = &acp62_pm_ops, 343 + } 344 + }; 345 + 346 + module_pci_driver(ps_acp62_driver); 347 + 348 + MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); 349 + MODULE_AUTHOR("Syed.SabaKareem@amd.com"); 350 + MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver"); 351 + MODULE_LICENSE("GPL v2");
+79
sound/soc/amd/ps/ps-mach.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Machine driver for AMD Pink Sardine platform using DMIC 4 + * 5 + * Copyright 2022 Advanced Micro Devices, Inc. 6 + */ 7 + 8 + #include <sound/soc.h> 9 + #include <sound/soc-dapm.h> 10 + #include <linux/module.h> 11 + #include <sound/pcm.h> 12 + #include <sound/pcm_params.h> 13 + #include <linux/io.h> 14 + #include <linux/dmi.h> 15 + 16 + #include "acp62.h" 17 + 18 + #define DRV_NAME "acp_ps_mach" 19 + 20 + SND_SOC_DAILINK_DEF(acp62_pdm, 21 + DAILINK_COMP_ARRAY(COMP_CPU("acp_ps_pdm_dma.0"))); 22 + 23 + SND_SOC_DAILINK_DEF(dmic_codec, 24 + DAILINK_COMP_ARRAY(COMP_CODEC("dmic-codec.0", 25 + "dmic-hifi"))); 26 + 27 + SND_SOC_DAILINK_DEF(pdm_platform, 28 + DAILINK_COMP_ARRAY(COMP_PLATFORM("acp_ps_pdm_dma.0"))); 29 + 30 + static struct snd_soc_dai_link acp62_dai_pdm[] = { 31 + { 32 + .name = "acp62-dmic-capture", 33 + .stream_name = "DMIC capture", 34 + .capture_only = 1, 35 + SND_SOC_DAILINK_REG(acp62_pdm, dmic_codec, pdm_platform), 36 + }, 37 + }; 38 + 39 + static struct snd_soc_card acp62_card = { 40 + .name = "acp62", 41 + .owner = THIS_MODULE, 42 + .dai_link = acp62_dai_pdm, 43 + .num_links = 1, 44 + }; 45 + 46 + static int acp62_probe(struct platform_device *pdev) 47 + { 48 + struct acp62_pdm *machine = NULL; 49 + struct snd_soc_card *card; 50 + int ret; 51 + 52 + platform_set_drvdata(pdev, &acp62_card); 53 + card = platform_get_drvdata(pdev); 54 + acp62_card.dev = &pdev->dev; 55 + 56 + snd_soc_card_set_drvdata(card, machine); 57 + ret = devm_snd_soc_register_card(&pdev->dev, card); 58 + if (ret) { 59 + return dev_err_probe(&pdev->dev, ret, 60 + "snd_soc_register_card(%s) failed\n", 61 + card->name); 62 + } 63 + 64 + return 0; 65 + } 66 + 67 + static struct platform_driver acp62_mach_driver = { 68 + .driver = { 69 + .name = "acp_ps_mach", 70 + .pm = &snd_soc_pm_ops, 71 + }, 72 + .probe = acp62_probe, 73 + }; 74 + 75 + module_platform_driver(acp62_mach_driver); 76 + 77 + MODULE_AUTHOR("Syed.SabaKareem@amd.com"); 78 + MODULE_LICENSE("GPL v2"); 79 + MODULE_ALIAS("platform:" DRV_NAME);
+452
sound/soc/amd/ps/ps-pdm-dma.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * AMD ALSA SoC Pink Sardine PDM Driver 4 + * 5 + * Copyright 2022 Advanced Micro Devices, Inc. 6 + */ 7 + 8 + #include <linux/platform_device.h> 9 + #include <linux/module.h> 10 + #include <linux/err.h> 11 + #include <linux/io.h> 12 + #include <sound/pcm_params.h> 13 + #include <sound/soc.h> 14 + #include <sound/soc-dai.h> 15 + #include <linux/pm_runtime.h> 16 + 17 + #include "acp62.h" 18 + 19 + #define DRV_NAME "acp_ps_pdm_dma" 20 + 21 + static const struct snd_pcm_hardware acp62_pdm_hardware_capture = { 22 + .info = SNDRV_PCM_INFO_INTERLEAVED | 23 + SNDRV_PCM_INFO_BLOCK_TRANSFER | 24 + SNDRV_PCM_INFO_MMAP | 25 + SNDRV_PCM_INFO_MMAP_VALID | 26 + SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, 27 + .formats = SNDRV_PCM_FMTBIT_S32_LE, 28 + .channels_min = 2, 29 + .channels_max = 2, 30 + .rates = SNDRV_PCM_RATE_48000, 31 + .rate_min = 48000, 32 + .rate_max = 48000, 33 + .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE, 34 + .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE, 35 + .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE, 36 + .periods_min = CAPTURE_MIN_NUM_PERIODS, 37 + .periods_max = CAPTURE_MAX_NUM_PERIODS, 38 + }; 39 + 40 + static void acp62_init_pdm_ring_buffer(u32 physical_addr, u32 buffer_size, 41 + u32 watermark_size, void __iomem *acp_base) 42 + { 43 + acp62_writel(physical_addr, acp_base + ACP_WOV_RX_RINGBUFADDR); 44 + acp62_writel(buffer_size, acp_base + ACP_WOV_RX_RINGBUFSIZE); 45 + acp62_writel(watermark_size, acp_base + ACP_WOV_RX_INTR_WATERMARK_SIZE); 46 + acp62_writel(0x01, acp_base + ACPAXI2AXI_ATU_CTRL); 47 + } 48 + 49 + static void acp62_enable_pdm_clock(void __iomem *acp_base) 50 + { 51 + u32 pdm_clk_enable, pdm_ctrl; 52 + 53 + pdm_clk_enable = ACP_PDM_CLK_FREQ_MASK; 54 + pdm_ctrl = 0x00; 55 + 56 + acp62_writel(pdm_clk_enable, acp_base + ACP_WOV_CLK_CTRL); 57 + pdm_ctrl = acp62_readl(acp_base + ACP_WOV_MISC_CTRL); 58 + pdm_ctrl |= ACP_WOV_MISC_CTRL_MASK; 59 + acp62_writel(pdm_ctrl, acp_base + ACP_WOV_MISC_CTRL); 60 + } 61 + 62 + static void acp62_enable_pdm_interrupts(void __iomem *acp_base) 63 + { 64 + u32 ext_int_ctrl; 65 + 66 + ext_int_ctrl = acp62_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); 67 + ext_int_ctrl |= PDM_DMA_INTR_MASK; 68 + acp62_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); 69 + } 70 + 71 + static void acp62_disable_pdm_interrupts(void __iomem *acp_base) 72 + { 73 + u32 ext_int_ctrl; 74 + 75 + ext_int_ctrl = acp62_readl(acp_base + ACP_EXTERNAL_INTR_CNTL); 76 + ext_int_ctrl &= ~PDM_DMA_INTR_MASK; 77 + acp62_writel(ext_int_ctrl, acp_base + ACP_EXTERNAL_INTR_CNTL); 78 + } 79 + 80 + static bool acp62_check_pdm_dma_status(void __iomem *acp_base) 81 + { 82 + bool pdm_dma_status; 83 + u32 pdm_enable, pdm_dma_enable; 84 + 85 + pdm_dma_status = false; 86 + pdm_enable = acp62_readl(acp_base + ACP_WOV_PDM_ENABLE); 87 + pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); 88 + if ((pdm_enable & ACP_PDM_ENABLE) && (pdm_dma_enable & ACP_PDM_DMA_EN_STATUS)) 89 + pdm_dma_status = true; 90 + 91 + return pdm_dma_status; 92 + } 93 + 94 + static int acp62_start_pdm_dma(void __iomem *acp_base) 95 + { 96 + u32 pdm_enable; 97 + u32 pdm_dma_enable; 98 + int timeout; 99 + 100 + pdm_enable = 0x01; 101 + pdm_dma_enable = 0x01; 102 + 103 + acp62_enable_pdm_clock(acp_base); 104 + acp62_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); 105 + acp62_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); 106 + timeout = 0; 107 + while (++timeout < ACP_COUNTER) { 108 + pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); 109 + if ((pdm_dma_enable & 0x02) == ACP_PDM_DMA_EN_STATUS) 110 + return 0; 111 + udelay(DELAY_US); 112 + } 113 + return -ETIMEDOUT; 114 + } 115 + 116 + static int acp62_stop_pdm_dma(void __iomem *acp_base) 117 + { 118 + u32 pdm_enable, pdm_dma_enable; 119 + int timeout; 120 + 121 + pdm_enable = 0x00; 122 + pdm_dma_enable = 0x00; 123 + 124 + pdm_enable = acp62_readl(acp_base + ACP_WOV_PDM_ENABLE); 125 + pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); 126 + if (pdm_dma_enable & 0x01) { 127 + pdm_dma_enable = 0x02; 128 + acp62_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); 129 + timeout = 0; 130 + while (++timeout < ACP_COUNTER) { 131 + pdm_dma_enable = acp62_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); 132 + if ((pdm_dma_enable & 0x02) == 0x00) 133 + break; 134 + udelay(DELAY_US); 135 + } 136 + if (timeout == ACP_COUNTER) 137 + return -ETIMEDOUT; 138 + } 139 + if (pdm_enable == ACP_PDM_ENABLE) { 140 + pdm_enable = ACP_PDM_DISABLE; 141 + acp62_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); 142 + } 143 + acp62_writel(0x01, acp_base + ACP_WOV_PDM_FIFO_FLUSH); 144 + return 0; 145 + } 146 + 147 + static void acp62_config_dma(struct pdm_stream_instance *rtd, int direction) 148 + { 149 + u16 page_idx; 150 + u32 low, high, val; 151 + dma_addr_t addr; 152 + 153 + addr = rtd->dma_addr; 154 + val = PDM_PTE_OFFSET; 155 + 156 + /* Group Enable */ 157 + acp62_writel(ACP_SRAM_PTE_OFFSET | BIT(31), rtd->acp62_base + 158 + ACPAXI2AXI_ATU_BASE_ADDR_GRP_1); 159 + acp62_writel(PAGE_SIZE_4K_ENABLE, rtd->acp62_base + 160 + ACPAXI2AXI_ATU_PAGE_SIZE_GRP_1); 161 + for (page_idx = 0; page_idx < rtd->num_pages; page_idx++) { 162 + /* Load the low address of page int ACP SRAM through SRBM */ 163 + low = lower_32_bits(addr); 164 + high = upper_32_bits(addr); 165 + 166 + acp62_writel(low, rtd->acp62_base + ACP_SCRATCH_REG_0 + val); 167 + high |= BIT(31); 168 + acp62_writel(high, rtd->acp62_base + ACP_SCRATCH_REG_0 + val + 4); 169 + val += 8; 170 + addr += PAGE_SIZE; 171 + } 172 + } 173 + 174 + static int acp62_pdm_dma_open(struct snd_soc_component *component, 175 + struct snd_pcm_substream *substream) 176 + { 177 + struct snd_pcm_runtime *runtime; 178 + struct pdm_dev_data *adata; 179 + struct pdm_stream_instance *pdm_data; 180 + int ret; 181 + 182 + runtime = substream->runtime; 183 + adata = dev_get_drvdata(component->dev); 184 + pdm_data = kzalloc(sizeof(*pdm_data), GFP_KERNEL); 185 + if (!pdm_data) 186 + return -EINVAL; 187 + 188 + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 189 + runtime->hw = acp62_pdm_hardware_capture; 190 + 191 + ret = snd_pcm_hw_constraint_integer(runtime, 192 + SNDRV_PCM_HW_PARAM_PERIODS); 193 + if (ret < 0) { 194 + dev_err(component->dev, "set integer constraint failed\n"); 195 + kfree(pdm_data); 196 + return ret; 197 + } 198 + 199 + acp62_enable_pdm_interrupts(adata->acp62_base); 200 + 201 + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) 202 + adata->capture_stream = substream; 203 + 204 + pdm_data->acp62_base = adata->acp62_base; 205 + runtime->private_data = pdm_data; 206 + return ret; 207 + } 208 + 209 + static int acp62_pdm_dma_hw_params(struct snd_soc_component *component, 210 + struct snd_pcm_substream *substream, 211 + struct snd_pcm_hw_params *params) 212 + { 213 + struct pdm_stream_instance *rtd; 214 + size_t size, period_bytes; 215 + 216 + rtd = substream->runtime->private_data; 217 + if (!rtd) 218 + return -EINVAL; 219 + size = params_buffer_bytes(params); 220 + period_bytes = params_period_bytes(params); 221 + rtd->dma_addr = substream->runtime->dma_addr; 222 + rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT); 223 + acp62_config_dma(rtd, substream->stream); 224 + acp62_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, size, 225 + period_bytes, rtd->acp62_base); 226 + return 0; 227 + } 228 + 229 + static u64 acp62_pdm_get_byte_count(struct pdm_stream_instance *rtd, 230 + int direction) 231 + { 232 + u32 high, low; 233 + u64 byte_count; 234 + 235 + high = acp62_readl(rtd->acp62_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH); 236 + byte_count = high; 237 + low = acp62_readl(rtd->acp62_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW); 238 + byte_count = (byte_count << 32) | low; 239 + return byte_count; 240 + } 241 + 242 + static snd_pcm_uframes_t acp62_pdm_dma_pointer(struct snd_soc_component *comp, 243 + struct snd_pcm_substream *stream) 244 + { 245 + struct pdm_stream_instance *rtd; 246 + u32 pos, buffersize; 247 + u64 bytescount; 248 + 249 + rtd = stream->runtime->private_data; 250 + buffersize = frames_to_bytes(stream->runtime, 251 + stream->runtime->buffer_size); 252 + bytescount = acp62_pdm_get_byte_count(rtd, stream->stream); 253 + if (bytescount > rtd->bytescount) 254 + bytescount -= rtd->bytescount; 255 + pos = do_div(bytescount, buffersize); 256 + return bytes_to_frames(stream->runtime, pos); 257 + } 258 + 259 + static int acp62_pdm_dma_new(struct snd_soc_component *component, 260 + struct snd_soc_pcm_runtime *rtd) 261 + { 262 + struct device *parent = component->dev->parent; 263 + 264 + snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, 265 + parent, MIN_BUFFER, MAX_BUFFER); 266 + return 0; 267 + } 268 + 269 + static int acp62_pdm_dma_close(struct snd_soc_component *component, 270 + struct snd_pcm_substream *substream) 271 + { 272 + struct pdm_dev_data *adata = dev_get_drvdata(component->dev); 273 + struct snd_pcm_runtime *runtime = substream->runtime; 274 + 275 + acp62_disable_pdm_interrupts(adata->acp62_base); 276 + adata->capture_stream = NULL; 277 + kfree(runtime->private_data); 278 + return 0; 279 + } 280 + 281 + static int acp62_pdm_dai_trigger(struct snd_pcm_substream *substream, 282 + int cmd, struct snd_soc_dai *dai) 283 + { 284 + struct pdm_stream_instance *rtd; 285 + int ret; 286 + bool pdm_status; 287 + unsigned int ch_mask; 288 + 289 + rtd = substream->runtime->private_data; 290 + ret = 0; 291 + switch (substream->runtime->channels) { 292 + case TWO_CH: 293 + ch_mask = 0x00; 294 + break; 295 + default: 296 + return -EINVAL; 297 + } 298 + switch (cmd) { 299 + case SNDRV_PCM_TRIGGER_START: 300 + case SNDRV_PCM_TRIGGER_RESUME: 301 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 302 + acp62_writel(ch_mask, rtd->acp62_base + ACP_WOV_PDM_NO_OF_CHANNELS); 303 + acp62_writel(PDM_DECIMATION_FACTOR, rtd->acp62_base + 304 + ACP_WOV_PDM_DECIMATION_FACTOR); 305 + rtd->bytescount = acp62_pdm_get_byte_count(rtd, substream->stream); 306 + pdm_status = acp62_check_pdm_dma_status(rtd->acp62_base); 307 + if (!pdm_status) 308 + ret = acp62_start_pdm_dma(rtd->acp62_base); 309 + break; 310 + case SNDRV_PCM_TRIGGER_STOP: 311 + case SNDRV_PCM_TRIGGER_SUSPEND: 312 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 313 + pdm_status = acp62_check_pdm_dma_status(rtd->acp62_base); 314 + if (pdm_status) 315 + ret = acp62_stop_pdm_dma(rtd->acp62_base); 316 + break; 317 + default: 318 + ret = -EINVAL; 319 + break; 320 + } 321 + return ret; 322 + } 323 + 324 + static const struct snd_soc_dai_ops acp62_pdm_dai_ops = { 325 + .trigger = acp62_pdm_dai_trigger, 326 + }; 327 + 328 + static struct snd_soc_dai_driver acp62_pdm_dai_driver = { 329 + .name = "acp_ps_pdm_dma.0", 330 + .capture = { 331 + .rates = SNDRV_PCM_RATE_48000, 332 + .formats = SNDRV_PCM_FMTBIT_S32_LE, 333 + .channels_min = 2, 334 + .channels_max = 2, 335 + .rate_min = 48000, 336 + .rate_max = 48000, 337 + }, 338 + .ops = &acp62_pdm_dai_ops, 339 + }; 340 + 341 + static const struct snd_soc_component_driver acp62_pdm_component = { 342 + .name = DRV_NAME, 343 + .open = acp62_pdm_dma_open, 344 + .close = acp62_pdm_dma_close, 345 + .hw_params = acp62_pdm_dma_hw_params, 346 + .pointer = acp62_pdm_dma_pointer, 347 + .pcm_construct = acp62_pdm_dma_new, 348 + }; 349 + 350 + static int acp62_pdm_audio_probe(struct platform_device *pdev) 351 + { 352 + struct resource *res; 353 + struct pdm_dev_data *adata; 354 + int status; 355 + 356 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 357 + if (!res) { 358 + dev_err(&pdev->dev, "IORESOURCE_MEM FAILED\n"); 359 + return -ENODEV; 360 + } 361 + 362 + adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL); 363 + if (!adata) 364 + return -ENOMEM; 365 + 366 + adata->acp62_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); 367 + if (!adata->acp62_base) 368 + return -ENOMEM; 369 + 370 + adata->capture_stream = NULL; 371 + 372 + dev_set_drvdata(&pdev->dev, adata); 373 + status = devm_snd_soc_register_component(&pdev->dev, 374 + &acp62_pdm_component, 375 + &acp62_pdm_dai_driver, 1); 376 + if (status) { 377 + dev_err(&pdev->dev, "Fail to register acp pdm dai\n"); 378 + 379 + return -ENODEV; 380 + } 381 + pm_runtime_set_autosuspend_delay(&pdev->dev, ACP_SUSPEND_DELAY_MS); 382 + pm_runtime_use_autosuspend(&pdev->dev); 383 + pm_runtime_enable(&pdev->dev); 384 + pm_runtime_allow(&pdev->dev); 385 + return 0; 386 + } 387 + 388 + static int acp62_pdm_audio_remove(struct platform_device *pdev) 389 + { 390 + pm_runtime_disable(&pdev->dev); 391 + return 0; 392 + } 393 + 394 + static int __maybe_unused acp62_pdm_resume(struct device *dev) 395 + { 396 + struct pdm_dev_data *adata; 397 + struct snd_pcm_runtime *runtime; 398 + struct pdm_stream_instance *rtd; 399 + u32 period_bytes, buffer_len; 400 + 401 + adata = dev_get_drvdata(dev); 402 + if (adata->capture_stream && adata->capture_stream->runtime) { 403 + runtime = adata->capture_stream->runtime; 404 + rtd = runtime->private_data; 405 + period_bytes = frames_to_bytes(runtime, runtime->period_size); 406 + buffer_len = frames_to_bytes(runtime, runtime->buffer_size); 407 + acp62_config_dma(rtd, SNDRV_PCM_STREAM_CAPTURE); 408 + acp62_init_pdm_ring_buffer(PDM_MEM_WINDOW_START, buffer_len, 409 + period_bytes, adata->acp62_base); 410 + } 411 + acp62_enable_pdm_interrupts(adata->acp62_base); 412 + return 0; 413 + } 414 + 415 + static int __maybe_unused acp62_pdm_suspend(struct device *dev) 416 + { 417 + struct pdm_dev_data *adata; 418 + 419 + adata = dev_get_drvdata(dev); 420 + acp62_disable_pdm_interrupts(adata->acp62_base); 421 + return 0; 422 + } 423 + 424 + static int __maybe_unused acp62_pdm_runtime_resume(struct device *dev) 425 + { 426 + struct pdm_dev_data *adata; 427 + 428 + adata = dev_get_drvdata(dev); 429 + acp62_enable_pdm_interrupts(adata->acp62_base); 430 + return 0; 431 + } 432 + 433 + static const struct dev_pm_ops acp62_pdm_pm_ops = { 434 + SET_RUNTIME_PM_OPS(acp62_pdm_suspend, acp62_pdm_runtime_resume, NULL) 435 + SET_SYSTEM_SLEEP_PM_OPS(acp62_pdm_suspend, acp62_pdm_resume) 436 + }; 437 + 438 + static struct platform_driver acp62_pdm_dma_driver = { 439 + .probe = acp62_pdm_audio_probe, 440 + .remove = acp62_pdm_audio_remove, 441 + .driver = { 442 + .name = "acp_ps_pdm_dma", 443 + .pm = &acp62_pdm_pm_ops, 444 + }, 445 + }; 446 + 447 + module_platform_driver(acp62_pdm_dma_driver); 448 + 449 + MODULE_AUTHOR("Syed.SabaKareem@amd.com"); 450 + MODULE_DESCRIPTION("AMD PINK SARDINE PDM Driver"); 451 + MODULE_LICENSE("GPL v2"); 452 + MODULE_ALIAS("platform:" DRV_NAME);