225 lines · c
1/* SPDX-License-Identifier: GPL-2.0+ */2/*3 * AMD ALSA SoC PCM Driver4 *5 * Copyright (C) 2021 Advanced Micro Devices, Inc. All rights reserved.6 */7 8#include "vg_chip_offset_byte.h"9#include <sound/pcm.h>10 11#define ACP5x_PHY_BASE_ADDRESS 0x124000012#define ACP_DEVICE_ID 0x15E213#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x0001000114 15#define ACP_PGFSM_CNTL_POWER_ON_MASK 0x0116#define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x0017#define ACP_PGFSM_STATUS_MASK 0x0318#define ACP_POWERED_ON 0x0019#define ACP_POWER_ON_IN_PROGRESS 0x0120#define ACP_POWERED_OFF 0x0221#define ACP_POWER_OFF_IN_PROGRESS 0x0322 23#define ACP_ERR_INTR_MASK 0x2000000024#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF25 26#define ACP5x_DEVS 427#define ACP5x_REG_START 0x124000028#define ACP5x_REG_END 0x125020029#define ACP5x_I2STDM_REG_START 0x124240030#define ACP5x_I2STDM_REG_END 0x124241031#define ACP5x_HS_TDM_REG_START 0x124281432#define ACP5x_HS_TDM_REG_END 0x124282433#define I2S_MODE 034#define ACP5x_I2S_MODE 135#define ACP5x_RES 436#define I2S_RX_THRESHOLD 2737#define I2S_TX_THRESHOLD 2838#define HS_TX_THRESHOLD 2439#define HS_RX_THRESHOLD 2340 41#define I2S_SP_INSTANCE 142#define I2S_HS_INSTANCE 243 44#define ACP_SRAM_PTE_OFFSET 0x0205000045#define ACP_SRAM_SP_PB_PTE_OFFSET 0x046#define ACP_SRAM_SP_CP_PTE_OFFSET 0x10047#define ACP_SRAM_HS_PB_PTE_OFFSET 0x20048#define ACP_SRAM_HS_CP_PTE_OFFSET 0x30049#define PAGE_SIZE_4K_ENABLE 0x250#define I2S_SP_TX_MEM_WINDOW_START 0x400000051#define I2S_SP_RX_MEM_WINDOW_START 0x402000052#define I2S_HS_TX_MEM_WINDOW_START 0x404000053#define I2S_HS_RX_MEM_WINDOW_START 0x406000054 55#define SP_PB_FIFO_ADDR_OFFSET 0x50056#define SP_CAPT_FIFO_ADDR_OFFSET 0x70057#define HS_PB_FIFO_ADDR_OFFSET 0x90058#define HS_CAPT_FIFO_ADDR_OFFSET 0xB0059#define PLAYBACK_MIN_NUM_PERIODS 260#define PLAYBACK_MAX_NUM_PERIODS 861#define PLAYBACK_MAX_PERIOD_SIZE 819262#define PLAYBACK_MIN_PERIOD_SIZE 102463#define CAPTURE_MIN_NUM_PERIODS 264#define CAPTURE_MAX_NUM_PERIODS 865#define CAPTURE_MAX_PERIOD_SIZE 819266#define CAPTURE_MIN_PERIOD_SIZE 102467 68#define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS)69#define MIN_BUFFER MAX_BUFFER70#define FIFO_SIZE 0x10071#define DMA_SIZE 0x4072#define FRM_LEN 0x10073 74#define I2S_MASTER_MODE_ENABLE 175#define I2S_MASTER_MODE_DISABLE 076 77#define SLOT_WIDTH_8 878#define SLOT_WIDTH_16 1679#define SLOT_WIDTH_24 2480#define SLOT_WIDTH_32 3281#define TDM_ENABLE 182#define TDM_DISABLE 083#define ACP5x_ITER_IRER_SAMP_LEN_MASK 0x3884 85struct i2s_dev_data {86 bool tdm_mode;87 bool master_mode;88 int i2s_irq;89 u16 i2s_instance;90 u32 tdm_fmt;91 void __iomem *acp5x_base;92 struct snd_pcm_substream *play_stream;93 struct snd_pcm_substream *capture_stream;94 struct snd_pcm_substream *i2ssp_play_stream;95 struct snd_pcm_substream *i2ssp_capture_stream;96};97 98struct i2s_stream_instance {99 u16 num_pages;100 u16 i2s_instance;101 u16 direction;102 u16 channels;103 u32 xfer_resolution;104 u32 val;105 dma_addr_t dma_addr;106 u64 bytescount;107 void __iomem *acp5x_base;108 u32 lrclk_div;109 u32 bclk_div;110};111 112union acp_dma_count {113 struct {114 u32 low;115 u32 high;116 } bcount;117 u64 bytescount;118};119 120struct acp5x_platform_info {121 u16 play_i2s_instance;122 u16 cap_i2s_instance;123};124 125union acp_i2stdm_mstrclkgen {126 struct {127 u32 i2stdm_master_mode : 1;128 u32 i2stdm_format_mode : 1;129 u32 i2stdm_lrclk_div_val : 9;130 u32 i2stdm_bclk_div_val : 11;131 u32:10;132 } bitfields, bits;133 u32 u32_all;134};135 136/* common header file uses exact offset rather than relative137 * offset which requires subtraction logic from base_addr138 * for accessing ACP5x MMIO space registers139 */140static inline u32 acp_readl(void __iomem *base_addr)141{142 return readl(base_addr - ACP5x_PHY_BASE_ADDRESS);143}144 145static inline void acp_writel(u32 val, void __iomem *base_addr)146{147 writel(val, base_addr - ACP5x_PHY_BASE_ADDRESS);148}149 150int snd_amd_acp_find_config(struct pci_dev *pci);151 152static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd,153 int direction)154{155 union acp_dma_count byte_count;156 157 if (direction == SNDRV_PCM_STREAM_PLAYBACK) {158 switch (rtd->i2s_instance) {159 case I2S_HS_INSTANCE:160 byte_count.bcount.high =161 acp_readl(rtd->acp5x_base +162 ACP_HS_TX_LINEARPOSCNTR_HIGH);163 byte_count.bcount.low =164 acp_readl(rtd->acp5x_base +165 ACP_HS_TX_LINEARPOSCNTR_LOW);166 break;167 case I2S_SP_INSTANCE:168 default:169 byte_count.bcount.high =170 acp_readl(rtd->acp5x_base +171 ACP_I2S_TX_LINEARPOSCNTR_HIGH);172 byte_count.bcount.low =173 acp_readl(rtd->acp5x_base +174 ACP_I2S_TX_LINEARPOSCNTR_LOW);175 }176 } else {177 switch (rtd->i2s_instance) {178 case I2S_HS_INSTANCE:179 byte_count.bcount.high =180 acp_readl(rtd->acp5x_base +181 ACP_HS_RX_LINEARPOSCNTR_HIGH);182 byte_count.bcount.low =183 acp_readl(rtd->acp5x_base +184 ACP_HS_RX_LINEARPOSCNTR_LOW);185 break;186 case I2S_SP_INSTANCE:187 default:188 byte_count.bcount.high =189 acp_readl(rtd->acp5x_base +190 ACP_I2S_RX_LINEARPOSCNTR_HIGH);191 byte_count.bcount.low =192 acp_readl(rtd->acp5x_base +193 ACP_I2S_RX_LINEARPOSCNTR_LOW);194 }195 }196 return byte_count.bytescount;197}198 199static inline void acp5x_set_i2s_clk(struct i2s_dev_data *adata,200 struct i2s_stream_instance *rtd)201{202 union acp_i2stdm_mstrclkgen mclkgen;203 u32 master_reg;204 205 switch (rtd->i2s_instance) {206 case I2S_HS_INSTANCE:207 master_reg = ACP_I2STDM2_MSTRCLKGEN;208 break;209 case I2S_SP_INSTANCE:210 default:211 master_reg = ACP_I2STDM0_MSTRCLKGEN;212 break;213 }214 215 mclkgen.bits.i2stdm_master_mode = 0x1;216 if (adata->tdm_mode)217 mclkgen.bits.i2stdm_format_mode = 0x01;218 else219 mclkgen.bits.i2stdm_format_mode = 0x00;220 221 mclkgen.bits.i2stdm_bclk_div_val = rtd->bclk_div;222 mclkgen.bits.i2stdm_lrclk_div_val = rtd->lrclk_div;223 acp_writel(mclkgen.u32_all, rtd->acp5x_base + master_reg);224}225