GNU Linux-libre 5.19-rc6-gnu
[releases.git] / sound / soc / amd / acp / amd.h
1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2 /*
3  * This file is provided under a dual BSD/GPLv2 license. When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * Copyright(c) 2021 Advanced Micro Devices, Inc. All rights reserved.
7  *
8  * Author: Ajit Kumar Pandey <AjitKumar.Pandey@amd.com>
9  */
10
11 #ifndef __AMD_ACP_H
12 #define __AMD_ACP_H
13
14 #include <sound/pcm.h>
15 #include <sound/soc.h>
16 #include <sound/soc-acpi.h>
17 #include <sound/soc-dai.h>
18
19 #include "chip_offset_byte.h"
20
21 #define ACP3X_DEV                       3
22
23 #define I2S_SP_INSTANCE                 0x00
24 #define I2S_BT_INSTANCE                 0x01
25 #define DMIC_INSTANCE                   0x02
26
27 #define MEM_WINDOW_START                0x4080000
28
29 #define ACP_I2S_REG_START               0x1242400
30 #define ACP_I2S_REG_END                 0x1242810
31 #define ACP3x_I2STDM_REG_START          0x1242400
32 #define ACP3x_I2STDM_REG_END            0x1242410
33 #define ACP3x_BT_TDM_REG_START          0x1242800
34 #define ACP3x_BT_TDM_REG_END            0x1242810
35 #define I2S_MODE                        0x04
36 #define I2S_RX_THRESHOLD                27
37 #define I2S_TX_THRESHOLD                28
38 #define BT_TX_THRESHOLD                 26
39 #define BT_RX_THRESHOLD                 25
40
41 #define ACP_SRAM_PTE_OFFSET             0x02052800
42
43 #define ACP_SRAM_SP_PB_PTE_OFFSET       0x0
44 #define ACP_SRAM_SP_CP_PTE_OFFSET       0x100
45 #define ACP_SRAM_BT_PB_PTE_OFFSET       0x200
46 #define ACP_SRAM_BT_CP_PTE_OFFSET       0x300
47 #define ACP_SRAM_PDM_PTE_OFFSET         0x400
48 #define PAGE_SIZE_4K_ENABLE             0x2
49
50 #define I2S_SP_TX_MEM_WINDOW_START      0x4000000
51 #define I2S_SP_RX_MEM_WINDOW_START      0x4020000
52 #define I2S_BT_TX_MEM_WINDOW_START      0x4040000
53 #define I2S_BT_RX_MEM_WINDOW_START      0x4060000
54
55 #define SP_PB_FIFO_ADDR_OFFSET          0x500
56 #define SP_CAPT_FIFO_ADDR_OFFSET        0x700
57 #define BT_PB_FIFO_ADDR_OFFSET          0x900
58 #define BT_CAPT_FIFO_ADDR_OFFSET        0xB00
59 #define PLAYBACK_MIN_NUM_PERIODS        2
60 #define PLAYBACK_MAX_NUM_PERIODS        8
61 #define PLAYBACK_MAX_PERIOD_SIZE        8192
62 #define PLAYBACK_MIN_PERIOD_SIZE        1024
63 #define CAPTURE_MIN_NUM_PERIODS         2
64 #define CAPTURE_MAX_NUM_PERIODS         8
65 #define CAPTURE_MAX_PERIOD_SIZE         8192
66 #define CAPTURE_MIN_PERIOD_SIZE         1024
67
68 #define MAX_BUFFER                      65536
69 #define MIN_BUFFER                      MAX_BUFFER
70 #define FIFO_SIZE                       0x100
71 #define DMA_SIZE                        0x40
72 #define FRM_LEN                         0x100
73
74 #define ACP3x_ITER_IRER_SAMP_LEN_MASK   0x38
75
76 #define ACP_MAX_STREAM                  6
77
78 struct acp_chip_info {
79         char *name;             /* Platform name */
80         unsigned int acp_rev;   /* ACP Revision id */
81         void __iomem *base;     /* ACP memory PCI base */
82 };
83
84 struct acp_stream {
85         struct snd_pcm_substream *substream;
86         int irq_bit;
87         int dai_id;
88         int id;
89         u64 bytescount;
90         u32 reg_offset;
91         u32 pte_offset;
92         u32 fifo_offset;
93 };
94
95 struct acp_dev_data {
96         char *name;
97         struct device *dev;
98         void __iomem *acp_base;
99         unsigned int i2s_irq;
100
101         /* SOC specific dais */
102         struct snd_soc_dai_driver *dai_driver;
103         int num_dai;
104
105         struct acp_stream *stream[ACP_MAX_STREAM];
106
107         struct snd_soc_acpi_mach *machines;
108         struct platform_device *mach_dev;
109 };
110
111 extern const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops;
112 extern const struct snd_soc_dai_ops acp_dmic_dai_ops;
113
114 int asoc_acp_i2s_probe(struct snd_soc_dai *dai);
115 int acp_platform_register(struct device *dev);
116 int acp_platform_unregister(struct device *dev);
117
118 int acp_machine_select(struct acp_dev_data *adata);
119
120 /* Machine configuration */
121 int snd_amd_acp_find_config(struct pci_dev *pci);
122
123 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
124 {
125         u64 byte_count, low = 0, high = 0;
126
127         if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
128                 switch (dai_id) {
129                 case I2S_BT_INSTANCE:
130                         high = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_HIGH);
131                         low = readl(adata->acp_base + ACP_BT_TX_LINEARPOSITIONCNTR_LOW);
132                         break;
133                 case I2S_SP_INSTANCE:
134                         high = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_HIGH);
135                         low = readl(adata->acp_base + ACP_I2S_TX_LINEARPOSITIONCNTR_LOW);
136                         break;
137                 default:
138                         dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
139                         return -EINVAL;
140                 }
141         } else {
142                 switch (dai_id) {
143                 case I2S_BT_INSTANCE:
144                         high = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_HIGH);
145                         low = readl(adata->acp_base + ACP_BT_RX_LINEARPOSITIONCNTR_LOW);
146                         break;
147                 case I2S_SP_INSTANCE:
148                         high = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_HIGH);
149                         low = readl(adata->acp_base + ACP_I2S_RX_LINEARPOSITIONCNTR_LOW);
150                         break;
151                 case DMIC_INSTANCE:
152                         high = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_HIGH);
153                         low = readl(adata->acp_base + ACP_WOV_RX_LINEARPOSITIONCNTR_LOW);
154                         break;
155                 default:
156                         dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
157                         return -EINVAL;
158                 }
159         }
160         /* Get 64 bit value from two 32 bit registers */
161         byte_count = (high << 32) | low;
162
163         return byte_count;
164 }
165
166 #endif