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 26832a5cd2SVijendar Mukunda #define ACP5x_DEVS 4 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 77b80556adSVijendar Mukunda #define SLOT_WIDTH_8 8 78b80556adSVijendar Mukunda #define SLOT_WIDTH_16 16 79b80556adSVijendar Mukunda #define SLOT_WIDTH_24 24 80b80556adSVijendar Mukunda #define SLOT_WIDTH_32 32 81b80556adSVijendar Mukunda #define TDM_ENABLE 1 82b80556adSVijendar Mukunda #define TDM_DISABLE 0 83b80556adSVijendar Mukunda #define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x38 84b80556adSVijendar Mukunda 8577f61444SVijendar Mukunda struct i2s_dev_data { 86b80556adSVijendar Mukunda bool tdm_mode; 87e550339eSVijendar Mukunda bool master_mode; 88fc2c8067SVijendar Mukunda unsigned int i2s_irq; 89b80556adSVijendar Mukunda u16 i2s_instance; 90b80556adSVijendar 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; 108*5ca4cf2cSVijendar Mukunda u32 lrclk_div; 109*5ca4cf2cSVijendar Mukunda u32 bclk_div; 110cab396d8SVijendar Mukunda }; 111cab396d8SVijendar Mukunda 112cab396d8SVijendar Mukunda union acp_dma_count { 113cab396d8SVijendar Mukunda struct { 114cab396d8SVijendar Mukunda u32 low; 115cab396d8SVijendar Mukunda u32 high; 116cab396d8SVijendar Mukunda } bcount; 117cab396d8SVijendar Mukunda u64 bytescount; 118cab396d8SVijendar Mukunda }; 119cab396d8SVijendar Mukunda 120cab396d8SVijendar Mukunda struct acp5x_platform_info { 121cab396d8SVijendar Mukunda u16 play_i2s_instance; 122cab396d8SVijendar Mukunda u16 cap_i2s_instance; 123cab396d8SVijendar Mukunda }; 124cab396d8SVijendar Mukunda 125b80556adSVijendar Mukunda union acp_i2stdm_mstrclkgen { 126b80556adSVijendar Mukunda struct { 127b80556adSVijendar Mukunda u32 i2stdm_master_mode : 1; 128b80556adSVijendar Mukunda u32 i2stdm_format_mode : 1; 129b80556adSVijendar Mukunda u32 i2stdm_lrclk_div_val : 9; 130b80556adSVijendar Mukunda u32 i2stdm_bclk_div_val : 11; 131b80556adSVijendar Mukunda u32:10; 132b80556adSVijendar Mukunda } bitfields, bits; 133b80556adSVijendar Mukunda u32 u32_all; 134b80556adSVijendar Mukunda }; 135b80556adSVijendar Mukunda 1364a7151c9SVijendar Mukunda /* common header file uses exact offset rather than relative 1374a7151c9SVijendar Mukunda * offset which requires subtraction logic from base_addr 1384a7151c9SVijendar Mukunda * for accessing ACP5x MMIO space registers 1394a7151c9SVijendar Mukunda */ 1404a7151c9SVijendar Mukunda static inline u32 acp_readl(void __iomem *base_addr) 1414a7151c9SVijendar Mukunda { 1424a7151c9SVijendar Mukunda return readl(base_addr - ACP5x_PHY_BASE_ADDRESS); 1434a7151c9SVijendar Mukunda } 1444a7151c9SVijendar Mukunda 1454a7151c9SVijendar Mukunda static inline void acp_writel(u32 val, void __iomem *base_addr) 1464a7151c9SVijendar Mukunda { 1474a7151c9SVijendar Mukunda writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS); 1484a7151c9SVijendar Mukunda } 149cab396d8SVijendar Mukunda 150cab396d8SVijendar Mukunda static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, 151cab396d8SVijendar Mukunda int direction) 152cab396d8SVijendar Mukunda { 153cab396d8SVijendar Mukunda union acp_dma_count byte_count; 154cab396d8SVijendar Mukunda 155cab396d8SVijendar Mukunda if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 156cab396d8SVijendar Mukunda switch (rtd->i2s_instance) { 157cab396d8SVijendar Mukunda case I2S_HS_INSTANCE: 158cab396d8SVijendar Mukunda byte_count.bcount.high = 159cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 160cab396d8SVijendar Mukunda ACP_HS_TX_LINEARPOSCNTR_HIGH); 161cab396d8SVijendar Mukunda byte_count.bcount.low = 162cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 163cab396d8SVijendar Mukunda ACP_HS_TX_LINEARPOSCNTR_LOW); 164cab396d8SVijendar Mukunda break; 165cab396d8SVijendar Mukunda case I2S_SP_INSTANCE: 166cab396d8SVijendar Mukunda default: 167cab396d8SVijendar Mukunda byte_count.bcount.high = 168cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 169cab396d8SVijendar Mukunda ACP_I2S_TX_LINEARPOSCNTR_HIGH); 170cab396d8SVijendar Mukunda byte_count.bcount.low = 171cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 172cab396d8SVijendar Mukunda ACP_I2S_TX_LINEARPOSCNTR_LOW); 173cab396d8SVijendar Mukunda } 174cab396d8SVijendar Mukunda } else { 175cab396d8SVijendar Mukunda switch (rtd->i2s_instance) { 176cab396d8SVijendar Mukunda case I2S_HS_INSTANCE: 177cab396d8SVijendar Mukunda byte_count.bcount.high = 178cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 179cab396d8SVijendar Mukunda ACP_HS_RX_LINEARPOSCNTR_HIGH); 180cab396d8SVijendar Mukunda byte_count.bcount.low = 181cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 182cab396d8SVijendar Mukunda ACP_HS_RX_LINEARPOSCNTR_LOW); 183cab396d8SVijendar Mukunda break; 184cab396d8SVijendar Mukunda case I2S_SP_INSTANCE: 185cab396d8SVijendar Mukunda default: 186cab396d8SVijendar Mukunda byte_count.bcount.high = 187cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 188cab396d8SVijendar Mukunda ACP_I2S_RX_LINEARPOSCNTR_HIGH); 189cab396d8SVijendar Mukunda byte_count.bcount.low = 190cab396d8SVijendar Mukunda acp_readl(rtd->acp5x_base + 191cab396d8SVijendar Mukunda ACP_I2S_RX_LINEARPOSCNTR_LOW); 192cab396d8SVijendar Mukunda } 193cab396d8SVijendar Mukunda } 194cab396d8SVijendar Mukunda return byte_count.bytescount; 195cab396d8SVijendar Mukunda } 196*5ca4cf2cSVijendar Mukunda 197*5ca4cf2cSVijendar Mukunda static inline void acp5x_set_i2s_clk(struct i2s_dev_data *adata, 198*5ca4cf2cSVijendar Mukunda struct i2s_stream_instance *rtd) 199*5ca4cf2cSVijendar Mukunda { 200*5ca4cf2cSVijendar Mukunda union acp_i2stdm_mstrclkgen mclkgen; 201*5ca4cf2cSVijendar Mukunda u32 master_reg; 202*5ca4cf2cSVijendar Mukunda 203*5ca4cf2cSVijendar Mukunda switch (rtd->i2s_instance) { 204*5ca4cf2cSVijendar Mukunda case I2S_HS_INSTANCE: 205*5ca4cf2cSVijendar Mukunda master_reg = ACP_I2STDM2_MSTRCLKGEN; 206*5ca4cf2cSVijendar Mukunda break; 207*5ca4cf2cSVijendar Mukunda case I2S_SP_INSTANCE: 208*5ca4cf2cSVijendar Mukunda default: 209*5ca4cf2cSVijendar Mukunda master_reg = ACP_I2STDM0_MSTRCLKGEN; 210*5ca4cf2cSVijendar Mukunda break; 211*5ca4cf2cSVijendar Mukunda } 212*5ca4cf2cSVijendar Mukunda 213*5ca4cf2cSVijendar Mukunda mclkgen.bits.i2stdm_master_mode = 0x1; 214*5ca4cf2cSVijendar Mukunda if (adata->tdm_mode) 215*5ca4cf2cSVijendar Mukunda mclkgen.bits.i2stdm_format_mode = 0x01; 216*5ca4cf2cSVijendar Mukunda else 217*5ca4cf2cSVijendar Mukunda mclkgen.bits.i2stdm_format_mode = 0x00; 218*5ca4cf2cSVijendar Mukunda 219*5ca4cf2cSVijendar Mukunda mclkgen.bits.i2stdm_bclk_div_val = rtd->bclk_div; 220*5ca4cf2cSVijendar Mukunda mclkgen.bits.i2stdm_lrclk_div_val = rtd->lrclk_div; 221*5ca4cf2cSVijendar Mukunda acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg); 222*5ca4cf2cSVijendar Mukunda } 223