14a7151c9SVijendar Mukunda /* SPDX-License-Identifier: GPL-2.0+ */ 24a7151c9SVijendar Mukunda /* 34a7151c9SVijendar Mukunda * AMD ALSA SoC PCM Driver 44a7151c9SVijendar Mukunda * 54a7151c9SVijendar Mukunda * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved. 64a7151c9SVijendar Mukunda */ 74a7151c9SVijendar Mukunda 84a7151c9SVijendar Mukunda #include "vg_chip_offset_byte.h" 9cab396d8SVijendar Mukunda #include <sound/pcm.h> 104a7151c9SVijendar Mukunda 114a7151c9SVijendar Mukunda #define ACP5x_PHY_BASE_ADDRESS 0x1240000 124a7151c9SVijendar Mukunda #define ACP_DEVICE_ID 0x15E2 135d9ee88aSVijendar Mukunda #define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001 145d9ee88aSVijendar Mukunda 155d9ee88aSVijendar Mukunda #define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 165d9ee88aSVijendar Mukunda #define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 175d9ee88aSVijendar Mukunda #define ACP_PGFSM_STATUS_MASK 0x03 185d9ee88aSVijendar Mukunda #define ACP_POWERED_ON 0x00 195d9ee88aSVijendar Mukunda #define ACP_POWER_ON_IN_PROGRESS 0x01 205d9ee88aSVijendar Mukunda #define ACP_POWERED_OFF 0x02 215d9ee88aSVijendar Mukunda #define ACP_POWER_OFF_IN_PROGRESS 0x03 225d9ee88aSVijendar Mukunda 235d9ee88aSVijendar Mukunda #define ACP_ERR_INTR_MASK 0x20000000 245d9ee88aSVijendar Mukunda #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF 254a7151c9SVijendar Mukunda 26603f2dedSVijendar Mukunda #define ACP5x_DEVS 3 27603f2dedSVijendar Mukunda #define ACP5x_REG_START 0x1240000 28603f2dedSVijendar Mukunda #define ACP5x_REG_END 0x1250200 29603f2dedSVijendar Mukunda #define ACP5x_I2STDM_REG_START 0x1242400 30603f2dedSVijendar Mukunda #define ACP5x_I2STDM_REG_END 0x1242410 31603f2dedSVijendar Mukunda #define ACP5x_HS_TDM_REG_START 0x1242814 32603f2dedSVijendar Mukunda #define ACP5x_HS_TDM_REG_END 0x1242824 33603f2dedSVijendar Mukunda #define I2S_MODE 0 34603f2dedSVijendar Mukunda #define ACP5x_I2S_MODE 1 35603f2dedSVijendar Mukunda #define ACP5x_RES 4 36fc2c8067SVijendar Mukunda #define I2S_RX_THRESHOLD 27 37fc2c8067SVijendar Mukunda #define I2S_TX_THRESHOLD 28 38fc2c8067SVijendar Mukunda #define HS_TX_THRESHOLD 24 39fc2c8067SVijendar Mukunda #define HS_RX_THRESHOLD 23 40603f2dedSVijendar Mukunda 41cab396d8SVijendar Mukunda #define I2S_SP_INSTANCE 1 42cab396d8SVijendar Mukunda #define I2S_HS_INSTANCE 2 43cab396d8SVijendar Mukunda 44cab396d8SVijendar Mukunda #define ACP_SRAM_PTE_OFFSET 0x02050000 45cab396d8SVijendar Mukunda #define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 46cab396d8SVijendar Mukunda #define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 47cab396d8SVijendar Mukunda #define ACP_SRAM_HS_PB_PTE_OFFSET 0x200 48cab396d8SVijendar Mukunda #define ACP_SRAM_HS_CP_PTE_OFFSET 0x300 49cab396d8SVijendar Mukunda #define PAGE_SIZE_4K_ENABLE 0x2 50cab396d8SVijendar Mukunda #define I2S_SP_TX_MEM_WINDOW_START 0x4000000 51cab396d8SVijendar Mukunda #define I2S_SP_RX_MEM_WINDOW_START 0x4020000 52cab396d8SVijendar Mukunda #define I2S_HS_TX_MEM_WINDOW_START 0x4040000 53cab396d8SVijendar Mukunda #define I2S_HS_RX_MEM_WINDOW_START 0x4060000 54cab396d8SVijendar Mukunda 55cab396d8SVijendar Mukunda #define SP_PB_FIFO_ADDR_OFFSET 0x500 56cab396d8SVijendar Mukunda #define SP_CAPT_FIFO_ADDR_OFFSET 0x700 57cab396d8SVijendar Mukunda #define HS_PB_FIFO_ADDR_OFFSET 0x900 58cab396d8SVijendar Mukunda #define HS_CAPT_FIFO_ADDR_OFFSET 0xB00 59cab396d8SVijendar Mukunda #define PLAYBACK_MIN_NUM_PERIODS 2 60cab396d8SVijendar Mukunda #define PLAYBACK_MAX_NUM_PERIODS 8 61cab396d8SVijendar Mukunda #define PLAYBACK_MAX_PERIOD_SIZE 8192 62cab396d8SVijendar Mukunda #define PLAYBACK_MIN_PERIOD_SIZE 1024 63cab396d8SVijendar Mukunda #define CAPTURE_MIN_NUM_PERIODS 2 64cab396d8SVijendar Mukunda #define CAPTURE_MAX_NUM_PERIODS 8 65cab396d8SVijendar Mukunda #define CAPTURE_MAX_PERIOD_SIZE 8192 66cab396d8SVijendar Mukunda #define CAPTURE_MIN_PERIOD_SIZE 1024 67cab396d8SVijendar Mukunda 68cab396d8SVijendar Mukunda #define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) 69cab396d8SVijendar Mukunda #define MIN_BUFFER MAX_BUFFER 70cab396d8SVijendar Mukunda #define FIFO_SIZE 0x100 71cab396d8SVijendar Mukunda #define DMA_SIZE 0x40 72cab396d8SVijendar Mukunda #define FRM_LEN 0x100 73cab396d8SVijendar Mukunda 74e550339eSVijendar Mukunda #define I2S_MASTER_MODE_ENABLE 1 75e550339eSVijendar Mukunda #define I2S_MASTER_MODE_DISABLE 0 76e550339eSVijendar Mukunda 77*b80556adSVijendar Mukunda #define SLOT_WIDTH_8 8 78*b80556adSVijendar Mukunda #define SLOT_WIDTH_16 16 79*b80556adSVijendar Mukunda #define SLOT_WIDTH_24 24 80*b80556adSVijendar Mukunda #define SLOT_WIDTH_32 32 81*b80556adSVijendar Mukunda #define TDM_ENABLE 1 82*b80556adSVijendar Mukunda #define TDM_DISABLE 0 83*b80556adSVijendar Mukunda #define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38 84*b80556adSVijendar Mukunda 8577f61444SVijendar Mukunda struct i2s_dev_data { 86*b80556adSVijendar Mukunda bool tdm_mode; 87e550339eSVijendar Mukunda bool master_mode; 88fc2c8067SVijendar Mukunda unsigned int i2s_irq; 89*b80556adSVijendar Mukunda u16 i2s_instance; 90*b80556adSVijendar Mukunda u32 tdm_fmt; 9177f61444SVijendar Mukunda void __iomem *acp5x_base; 92fc2c8067SVijendar Mukunda struct snd_pcm_substream *play_stream; 93fc2c8067SVijendar Mukunda struct snd_pcm_substream *capture_stream; 94fc2c8067SVijendar Mukunda struct snd_pcm_substream *i2ssp_play_stream; 95fc2c8067SVijendar Mukunda struct snd_pcm_substream *i2ssp_capture_stream; 9677f61444SVijendar Mukunda }; 9777f61444SVijendar Mukunda 98cab396d8SVijendar Mukunda struct i2s_stream_instance { 99cab396d8SVijendar Mukunda u16 num_pages; 100cab396d8SVijendar Mukunda u16 i2s_instance; 101cab396d8SVijendar Mukunda u16 direction; 102cab396d8SVijendar Mukunda u16 channels; 103cab396d8SVijendar Mukunda u32 xfer_resolution; 104cab396d8SVijendar Mukunda u32 val; 105cab396d8SVijendar Mukunda dma_addr_t dma_addr; 106cab396d8SVijendar Mukunda u64 bytescount; 107cab396d8SVijendar Mukunda void __iomem *acp5x_base; 108cab396d8SVijendar Mukunda }; 109cab396d8SVijendar Mukunda 110cab396d8SVijendar Mukunda union acp_dma_count { 111cab396d8SVijendar Mukunda struct { 112cab396d8SVijendar Mukunda u32 low; 113cab396d8SVijendar Mukunda u32 high; 114cab396d8SVijendar Mukunda } bcount; 115cab396d8SVijendar Mukunda u64 bytescount; 116cab396d8SVijendar Mukunda }; 117cab396d8SVijendar Mukunda 118cab396d8SVijendar Mukunda struct acp5x_platform_info { 119cab396d8SVijendar Mukunda u16 play_i2s_instance; 120cab396d8SVijendar Mukunda u16 cap_i2s_instance; 121cab396d8SVijendar Mukunda }; 122cab396d8SVijendar Mukunda 123*b80556adSVijendar Mukunda union acp_i2stdm_mstrclkgen { 124*b80556adSVijendar Mukunda struct { 125*b80556adSVijendar Mukunda u32 i2stdm_master_mode : 1; 126*b80556adSVijendar Mukunda u32 i2stdm_format_mode : 1; 127*b80556adSVijendar Mukunda u32 i2stdm_lrclk_div_val : 9; 128*b80556adSVijendar Mukunda u32 i2stdm_bclk_div_val : 11; 129*b80556adSVijendar Mukunda u32:10; 130*b80556adSVijendar Mukunda } bitfields, bits; 131*b80556adSVijendar Mukunda u32 u32_all; 132*b80556adSVijendar Mukunda }; 133*b80556adSVijendar Mukunda 1344a7151c9SVijendar Mukunda /* common header file uses exact offset rather than relative 1354a7151c9SVijendar Mukunda * offset which requires subtraction logic from base_addr 1364a7151c9SVijendar Mukunda * for accessing ACP5x MMIO space registers 1374a7151c9SVijendar Mukunda */ 1384a7151c9SVijendar Mukunda static inline u32 acp_readl(void __iomem *base_addr) 1394a7151c9SVijendar Mukunda { 1404a7151c9SVijendar Mukunda return readl(base_addr - ACP5x_PHY_BASE_ADDRESS); 1414a7151c9SVijendar Mukunda } 1424a7151c9SVijendar Mukunda 1434a7151c9SVijendar Mukunda static inline void acp_writel(u32 val, void __iomem *base_addr) 1444a7151c9SVijendar Mukunda { 1454a7151c9SVijendar Mukunda writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS); 1464a7151c9SVijendar Mukunda } 147cab396d8SVijendar Mukunda 148cab396d8SVijendar Mukunda static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, 149cab396d8SVijendar Mukunda int direction) 150cab396d8SVijendar Mukunda { 151cab396d8SVijendar Mukunda union acp_dma_count byte_count; 152cab396d8SVijendar Mukunda 153cab396d8SVijendar Mukunda if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 154cab396d8SVijendar Mukunda switch (rtd->i2s_instance) { 155cab396d8SVijendar Mukunda case I2S_HS_INSTANCE: 156cab396d8SVijendar Mukunda byte_count.bcount.high = 157cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 158cab396d8SVijendar Mukunda ACP_HS_TX_LINEARPOSCNTR_HIGH); 159cab396d8SVijendar Mukunda byte_count.bcount.low = 160cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 161cab396d8SVijendar Mukunda ACP_HS_TX_LINEARPOSCNTR_LOW); 162cab396d8SVijendar Mukunda break; 163cab396d8SVijendar Mukunda case I2S_SP_INSTANCE: 164cab396d8SVijendar Mukunda default: 165cab396d8SVijendar Mukunda byte_count.bcount.high = 166cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 167cab396d8SVijendar Mukunda ACP_I2S_TX_LINEARPOSCNTR_HIGH); 168cab396d8SVijendar Mukunda byte_count.bcount.low = 169cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 170cab396d8SVijendar Mukunda ACP_I2S_TX_LINEARPOSCNTR_LOW); 171cab396d8SVijendar Mukunda } 172cab396d8SVijendar Mukunda } else { 173cab396d8SVijendar Mukunda switch (rtd->i2s_instance) { 174cab396d8SVijendar Mukunda case I2S_HS_INSTANCE: 175cab396d8SVijendar Mukunda byte_count.bcount.high = 176cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 177cab396d8SVijendar Mukunda ACP_HS_RX_LINEARPOSCNTR_HIGH); 178cab396d8SVijendar Mukunda byte_count.bcount.low = 179cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 180cab396d8SVijendar Mukunda ACP_HS_RX_LINEARPOSCNTR_LOW); 181cab396d8SVijendar Mukunda break; 182cab396d8SVijendar Mukunda case I2S_SP_INSTANCE: 183cab396d8SVijendar Mukunda default: 184cab396d8SVijendar Mukunda byte_count.bcount.high = 185cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 186cab396d8SVijendar Mukunda ACP_I2S_RX_LINEARPOSCNTR_HIGH); 187cab396d8SVijendar Mukunda byte_count.bcount.low = 188cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 189cab396d8SVijendar Mukunda ACP_I2S_RX_LINEARPOSCNTR_LOW); 190cab396d8SVijendar Mukunda } 191cab396d8SVijendar Mukunda } 192cab396d8SVijendar Mukunda return byte_count.bytescount; 193cab396d8SVijendar Mukunda } 194