Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
0002 /*
0003  * This file is provided under a dual BSD/GPLv2 license. When using or
0004  * redistributing this file, you may do so under either license.
0005  *
0006  * Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
0007  *
0008  * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
0009  */
0010 
0011 #ifndef __AMD_ACP_H
0012 #define __AMD_ACP_H
0013 
0014 #include <sound/pcm.h>
0015 #include <sound/soc.h>
0016 #include <sound/soc-acpi.h>
0017 #include <sound/soc-dai.h>
0018 
0019 #include "chip_offset_byte.h"
0020 
0021 #define ACP3X_DEV           3
0022 #define ACP6X_DEV           6
0023 
0024 #define I2S_SP_INSTANCE         0x00
0025 #define I2S_BT_INSTANCE         0x01
0026 #define DMIC_INSTANCE           0x02
0027 #define I2S_HS_INSTANCE         0x03
0028 
0029 #define MEM_WINDOW_START        0x4080000
0030 
0031 #define ACP_I2S_REG_START       0x1242400
0032 #define ACP_I2S_REG_END         0x1242810
0033 #define ACP3x_I2STDM_REG_START      0x1242400
0034 #define ACP3x_I2STDM_REG_END        0x1242410
0035 #define ACP3x_BT_TDM_REG_START      0x1242800
0036 #define ACP3x_BT_TDM_REG_END        0x1242810
0037 
0038 #define THRESHOLD(bit, base)    ((bit) + (base))
0039 #define I2S_RX_THRESHOLD(base)  THRESHOLD(7, base)
0040 #define I2S_TX_THRESHOLD(base)  THRESHOLD(8, base)
0041 #define BT_TX_THRESHOLD(base)   THRESHOLD(6, base)
0042 #define BT_RX_THRESHOLD(base)   THRESHOLD(5, base)
0043 #define HS_TX_THRESHOLD(base)   THRESHOLD(4, base)
0044 #define HS_RX_THRESHOLD(base)   THRESHOLD(3, base)
0045 
0046 #define ACP_SRAM_SP_PB_PTE_OFFSET   0x0
0047 #define ACP_SRAM_SP_CP_PTE_OFFSET   0x100
0048 #define ACP_SRAM_BT_PB_PTE_OFFSET   0x200
0049 #define ACP_SRAM_BT_CP_PTE_OFFSET   0x300
0050 #define ACP_SRAM_PDM_PTE_OFFSET     0x400
0051 #define ACP_SRAM_HS_PB_PTE_OFFSET       0x500
0052 #define ACP_SRAM_HS_CP_PTE_OFFSET       0x600
0053 #define PAGE_SIZE_4K_ENABLE     0x2
0054 
0055 #define I2S_SP_TX_MEM_WINDOW_START  0x4000000
0056 #define I2S_SP_RX_MEM_WINDOW_START  0x4020000
0057 #define I2S_BT_TX_MEM_WINDOW_START  0x4040000
0058 #define I2S_BT_RX_MEM_WINDOW_START  0x4060000
0059 #define I2S_HS_TX_MEM_WINDOW_START      0x40A0000
0060 #define I2S_HS_RX_MEM_WINDOW_START      0x40C0000
0061 
0062 #define SP_PB_FIFO_ADDR_OFFSET      0x500
0063 #define SP_CAPT_FIFO_ADDR_OFFSET    0x700
0064 #define BT_PB_FIFO_ADDR_OFFSET      0x900
0065 #define BT_CAPT_FIFO_ADDR_OFFSET    0xB00
0066 #define HS_PB_FIFO_ADDR_OFFSET      0xD00
0067 #define HS_CAPT_FIFO_ADDR_OFFSET    0xF00
0068 #define PLAYBACK_MIN_NUM_PERIODS    2
0069 #define PLAYBACK_MAX_NUM_PERIODS    8
0070 #define PLAYBACK_MAX_PERIOD_SIZE    8192
0071 #define PLAYBACK_MIN_PERIOD_SIZE    1024
0072 #define CAPTURE_MIN_NUM_PERIODS     2
0073 #define CAPTURE_MAX_NUM_PERIODS     8
0074 #define CAPTURE_MAX_PERIOD_SIZE     8192
0075 #define CAPTURE_MIN_PERIOD_SIZE     1024
0076 
0077 #define MAX_BUFFER          65536
0078 #define MIN_BUFFER          MAX_BUFFER
0079 #define FIFO_SIZE           0x100
0080 #define DMA_SIZE            0x40
0081 #define FRM_LEN             0x100
0082 
0083 #define ACP3x_ITER_IRER_SAMP_LEN_MASK   0x38
0084 
0085 #define ACP_MAX_STREAM          8
0086 
0087 struct acp_chip_info {
0088     char *name;     /* Platform name */
0089     unsigned int acp_rev;   /* ACP Revision id */
0090     void __iomem *base; /* ACP memory PCI base */
0091 };
0092 
0093 struct acp_stream {
0094     struct snd_pcm_substream *substream;
0095     int irq_bit;
0096     int dai_id;
0097     int id;
0098     u64 bytescount;
0099     u32 reg_offset;
0100     u32 pte_offset;
0101     u32 fifo_offset;
0102 };
0103 
0104 struct acp_resource {
0105     int offset;
0106     int no_of_ctrls;
0107     int irqp_used;
0108     bool soc_mclk;
0109     u32 irq_reg_offset;
0110     u32 i2s_pin_cfg_offset;
0111     int i2s_mode;
0112     u64 scratch_reg_offset;
0113     u64 sram_pte_offset;
0114 };
0115 
0116 struct acp_dev_data {
0117     char *name;
0118     struct device *dev;
0119     void __iomem *acp_base;
0120     unsigned int i2s_irq;
0121 
0122     /* SOC specific dais */
0123     struct snd_soc_dai_driver *dai_driver;
0124     int num_dai;
0125 
0126     struct acp_stream *stream[ACP_MAX_STREAM];
0127 
0128     struct snd_soc_acpi_mach *machines;
0129     struct platform_device *mach_dev;
0130 
0131     u32 bclk_div;
0132     u32 lrclk_div;
0133 
0134     struct acp_resource *rsrc;
0135 };
0136 
0137 union acp_i2stdm_mstrclkgen {
0138     struct {
0139         u32 i2stdm_master_mode : 1;
0140         u32 i2stdm_format_mode : 1;
0141         u32 i2stdm_lrclk_div_val : 9;
0142         u32 i2stdm_bclk_div_val : 11;
0143         u32:10;
0144     } bitfields, bits;
0145     u32  u32_all;
0146 };
0147 
0148 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
0149 extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
0150 
0151 int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
0152 int acp_platform_register(struct device *dev);
0153 int acp_platform_unregister(struct device *dev);
0154 
0155 int acp_machine_select(struct acp_dev_data *adata);
0156 
0157 /* Machine configuration */
0158 int snd_amd_acp_find_config(struct pci_dev *pci);
0159 
0160 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
0161 {
0162     u64 byte_count, low = 0, high = 0;
0163 
0164     if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
0165         switch (dai_id) {
0166         case I2S_BT_INSTANCE:
0167             high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
0168             low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW);
0169             break;
0170         case I2S_SP_INSTANCE:
0171             high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
0172             low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
0173             break;
0174         case I2S_HS_INSTANCE:
0175             high = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_HIGH);
0176             low = readl(adata->acp_base + ACP_HS_TX_LINEARPOSITIONCNTR_LOW);
0177             break;
0178         default:
0179             dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
0180             return -EINVAL;
0181         }
0182     } else {
0183         switch (dai_id) {
0184         case I2S_BT_INSTANCE:
0185             high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
0186             low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW);
0187             break;
0188         case I2S_SP_INSTANCE:
0189             high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
0190             low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
0191             break;
0192         case I2S_HS_INSTANCE:
0193             high = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_HIGH);
0194             low = readl(adata->acp_base + ACP_HS_RX_LINEARPOSITIONCNTR_LOW);
0195             break;
0196         case DMIC_INSTANCE:
0197             high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
0198             low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
0199             break;
0200         default:
0201             dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
0202             return -EINVAL;
0203         }
0204     }
0205     /* Get 64 bit value from two 32 bit registers */
0206     byte_count = (high << 32) | low;
0207 
0208     return byte_count;
0209 }
0210 
0211 static inline void acp_set_i2s_clk(struct acp_dev_data *adata, int dai_id)
0212 {
0213     union acp_i2stdm_mstrclkgen mclkgen;
0214     u32 master_reg;
0215 
0216     switch (dai_id) {
0217     case I2S_SP_INSTANCE:
0218         master_reg = ACP_I2STDM0_MSTRCLKGEN;
0219         break;
0220     case I2S_BT_INSTANCE:
0221         master_reg = ACP_I2STDM1_MSTRCLKGEN;
0222         break;
0223     case I2S_HS_INSTANCE:
0224         master_reg = ACP_I2STDM2_MSTRCLKGEN;
0225         break;
0226     default:
0227         master_reg = ACP_I2STDM0_MSTRCLKGEN;
0228         break;
0229     }
0230 
0231     mclkgen.bits.i2stdm_master_mode = 0x1;
0232     mclkgen.bits.i2stdm_format_mode = 0x00;
0233 
0234     mclkgen.bits.i2stdm_bclk_div_val = adata->bclk_div;
0235     mclkgen.bits.i2stdm_lrclk_div_val = adata->lrclk_div;
0236     writel(mclkgen.u32_all, adata->acp_base + master_reg);
0237 }
0238 #endif