1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0+ */ 2*4882a593Smuzhiyun /* 3*4882a593Smuzhiyun * AMD ALSA SoC PCM Driver 4*4882a593Smuzhiyun * 5*4882a593Smuzhiyun * Copyright 2016 Advanced Micro Devices, Inc. 6*4882a593Smuzhiyun */ 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun #include "chip_offset_byte.h" 9*4882a593Smuzhiyun #include <sound/pcm.h> 10*4882a593Smuzhiyun #define I2S_SP_INSTANCE 0x01 11*4882a593Smuzhiyun #define I2S_BT_INSTANCE 0x02 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun #define TDM_ENABLE 1 14*4882a593Smuzhiyun #define TDM_DISABLE 0 15*4882a593Smuzhiyun 16*4882a593Smuzhiyun #define ACP3x_DEVS 4 17*4882a593Smuzhiyun #define ACP3x_PHY_BASE_ADDRESS 0x1240000 18*4882a593Smuzhiyun #define ACP3x_I2S_MODE 0 19*4882a593Smuzhiyun #define ACP3x_REG_START 0x1240000 20*4882a593Smuzhiyun #define ACP3x_REG_END 0x1250200 21*4882a593Smuzhiyun #define ACP3x_I2STDM_REG_START 0x1242400 22*4882a593Smuzhiyun #define ACP3x_I2STDM_REG_END 0x1242410 23*4882a593Smuzhiyun #define ACP3x_BT_TDM_REG_START 0x1242800 24*4882a593Smuzhiyun #define ACP3x_BT_TDM_REG_END 0x1242810 25*4882a593Smuzhiyun #define I2S_MODE 0x04 26*4882a593Smuzhiyun #define I2S_RX_THRESHOLD 27 27*4882a593Smuzhiyun #define I2S_TX_THRESHOLD 28 28*4882a593Smuzhiyun #define BT_TX_THRESHOLD 26 29*4882a593Smuzhiyun #define BT_RX_THRESHOLD 25 30*4882a593Smuzhiyun #define ACP_ERR_INTR_MASK 29 31*4882a593Smuzhiyun #define ACP3x_POWER_ON 0x00 32*4882a593Smuzhiyun #define ACP3x_POWER_ON_IN_PROGRESS 0x01 33*4882a593Smuzhiyun #define ACP3x_POWER_OFF 0x02 34*4882a593Smuzhiyun #define ACP3x_POWER_OFF_IN_PROGRESS 0x03 35*4882a593Smuzhiyun #define ACP3x_SOFT_RESET__SoftResetAudDone_MASK 0x00010001 36*4882a593Smuzhiyun 37*4882a593Smuzhiyun #define ACP_SRAM_PTE_OFFSET 0x02050000 38*4882a593Smuzhiyun #define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 39*4882a593Smuzhiyun #define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 40*4882a593Smuzhiyun #define ACP_SRAM_BT_PB_PTE_OFFSET 0x200 41*4882a593Smuzhiyun #define ACP_SRAM_BT_CP_PTE_OFFSET 0x300 42*4882a593Smuzhiyun #define PAGE_SIZE_4K_ENABLE 0x2 43*4882a593Smuzhiyun #define I2S_SP_TX_MEM_WINDOW_START 0x4000000 44*4882a593Smuzhiyun #define I2S_SP_RX_MEM_WINDOW_START 0x4020000 45*4882a593Smuzhiyun #define I2S_BT_TX_MEM_WINDOW_START 0x4040000 46*4882a593Smuzhiyun #define I2S_BT_RX_MEM_WINDOW_START 0x4060000 47*4882a593Smuzhiyun 48*4882a593Smuzhiyun #define SP_PB_FIFO_ADDR_OFFSET 0x500 49*4882a593Smuzhiyun #define SP_CAPT_FIFO_ADDR_OFFSET 0x700 50*4882a593Smuzhiyun #define BT_PB_FIFO_ADDR_OFFSET 0x900 51*4882a593Smuzhiyun #define BT_CAPT_FIFO_ADDR_OFFSET 0xB00 52*4882a593Smuzhiyun #define PLAYBACK_MIN_NUM_PERIODS 2 53*4882a593Smuzhiyun #define PLAYBACK_MAX_NUM_PERIODS 8 54*4882a593Smuzhiyun #define PLAYBACK_MAX_PERIOD_SIZE 8192 55*4882a593Smuzhiyun #define PLAYBACK_MIN_PERIOD_SIZE 1024 56*4882a593Smuzhiyun #define CAPTURE_MIN_NUM_PERIODS 2 57*4882a593Smuzhiyun #define CAPTURE_MAX_NUM_PERIODS 8 58*4882a593Smuzhiyun #define CAPTURE_MAX_PERIOD_SIZE 8192 59*4882a593Smuzhiyun #define CAPTURE_MIN_PERIOD_SIZE 1024 60*4882a593Smuzhiyun 61*4882a593Smuzhiyun #define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) 62*4882a593Smuzhiyun #define MIN_BUFFER MAX_BUFFER 63*4882a593Smuzhiyun #define FIFO_SIZE 0x100 64*4882a593Smuzhiyun #define DMA_SIZE 0x40 65*4882a593Smuzhiyun #define FRM_LEN 0x100 66*4882a593Smuzhiyun 67*4882a593Smuzhiyun #define SLOT_WIDTH_8 0x08 68*4882a593Smuzhiyun #define SLOT_WIDTH_16 0x10 69*4882a593Smuzhiyun #define SLOT_WIDTH_24 0x18 70*4882a593Smuzhiyun #define SLOT_WIDTH_32 0x20 71*4882a593Smuzhiyun #define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 72*4882a593Smuzhiyun #define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 73*4882a593Smuzhiyun #define ACP_PGFSM_STATUS_MASK 0x03 74*4882a593Smuzhiyun #define ACP_POWERED_ON 0x00 75*4882a593Smuzhiyun #define ACP_POWER_ON_IN_PROGRESS 0x01 76*4882a593Smuzhiyun #define ACP_POWERED_OFF 0x02 77*4882a593Smuzhiyun #define ACP_POWER_OFF_IN_PROGRESS 0x03 78*4882a593Smuzhiyun 79*4882a593Smuzhiyun #define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38 80*4882a593Smuzhiyun #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun struct acp3x_platform_info { 83*4882a593Smuzhiyun u16 play_i2s_instance; 84*4882a593Smuzhiyun u16 cap_i2s_instance; 85*4882a593Smuzhiyun u16 capture_channel; 86*4882a593Smuzhiyun }; 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun struct i2s_dev_data { 89*4882a593Smuzhiyun bool tdm_mode; 90*4882a593Smuzhiyun unsigned int i2s_irq; 91*4882a593Smuzhiyun u16 i2s_instance; 92*4882a593Smuzhiyun u32 tdm_fmt; 93*4882a593Smuzhiyun u32 substream_type; 94*4882a593Smuzhiyun void __iomem *acp3x_base; 95*4882a593Smuzhiyun struct snd_pcm_substream *play_stream; 96*4882a593Smuzhiyun struct snd_pcm_substream *capture_stream; 97*4882a593Smuzhiyun struct snd_pcm_substream *i2ssp_play_stream; 98*4882a593Smuzhiyun struct snd_pcm_substream *i2ssp_capture_stream; 99*4882a593Smuzhiyun }; 100*4882a593Smuzhiyun 101*4882a593Smuzhiyun struct i2s_stream_instance { 102*4882a593Smuzhiyun u16 num_pages; 103*4882a593Smuzhiyun u16 i2s_instance; 104*4882a593Smuzhiyun u16 capture_channel; 105*4882a593Smuzhiyun u16 direction; 106*4882a593Smuzhiyun u16 channels; 107*4882a593Smuzhiyun u32 xfer_resolution; 108*4882a593Smuzhiyun u32 val; 109*4882a593Smuzhiyun dma_addr_t dma_addr; 110*4882a593Smuzhiyun u64 bytescount; 111*4882a593Smuzhiyun void __iomem *acp3x_base; 112*4882a593Smuzhiyun }; 113*4882a593Smuzhiyun rv_readl(void __iomem * base_addr)114*4882a593Smuzhiyunstatic inline u32 rv_readl(void __iomem *base_addr) 115*4882a593Smuzhiyun { 116*4882a593Smuzhiyun return readl(base_addr - ACP3x_PHY_BASE_ADDRESS); 117*4882a593Smuzhiyun } 118*4882a593Smuzhiyun rv_writel(u32 val,void __iomem * base_addr)119*4882a593Smuzhiyunstatic inline void rv_writel(u32 val, void __iomem *base_addr) 120*4882a593Smuzhiyun { 121*4882a593Smuzhiyun writel(val, base_addr - ACP3x_PHY_BASE_ADDRESS); 122*4882a593Smuzhiyun } 123*4882a593Smuzhiyun acp_get_byte_count(struct i2s_stream_instance * rtd,int direction)124*4882a593Smuzhiyunstatic inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, 125*4882a593Smuzhiyun int direction) 126*4882a593Smuzhiyun { 127*4882a593Smuzhiyun u64 byte_count; 128*4882a593Smuzhiyun 129*4882a593Smuzhiyun if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 130*4882a593Smuzhiyun switch (rtd->i2s_instance) { 131*4882a593Smuzhiyun case I2S_BT_INSTANCE: 132*4882a593Smuzhiyun byte_count = rv_readl(rtd->acp3x_base + 133*4882a593Smuzhiyun mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); 134*4882a593Smuzhiyun byte_count |= rv_readl(rtd->acp3x_base + 135*4882a593Smuzhiyun mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); 136*4882a593Smuzhiyun break; 137*4882a593Smuzhiyun case I2S_SP_INSTANCE: 138*4882a593Smuzhiyun default: 139*4882a593Smuzhiyun byte_count = rv_readl(rtd->acp3x_base + 140*4882a593Smuzhiyun mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); 141*4882a593Smuzhiyun byte_count |= rv_readl(rtd->acp3x_base + 142*4882a593Smuzhiyun mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW); 143*4882a593Smuzhiyun } 144*4882a593Smuzhiyun 145*4882a593Smuzhiyun } else { 146*4882a593Smuzhiyun switch (rtd->i2s_instance) { 147*4882a593Smuzhiyun case I2S_BT_INSTANCE: 148*4882a593Smuzhiyun byte_count = rv_readl(rtd->acp3x_base + 149*4882a593Smuzhiyun mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); 150*4882a593Smuzhiyun byte_count |= rv_readl(rtd->acp3x_base + 151*4882a593Smuzhiyun mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); 152*4882a593Smuzhiyun break; 153*4882a593Smuzhiyun case I2S_SP_INSTANCE: 154*4882a593Smuzhiyun default: 155*4882a593Smuzhiyun byte_count = rv_readl(rtd->acp3x_base + 156*4882a593Smuzhiyun mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); 157*4882a593Smuzhiyun byte_count |= rv_readl(rtd->acp3x_base + 158*4882a593Smuzhiyun mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW); 159*4882a593Smuzhiyun } 160*4882a593Smuzhiyun } 161*4882a593Smuzhiyun return byte_count; 162*4882a593Smuzhiyun } 163