1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
---|---|
2 | /* |
3 | * AMD ALSA SoC PCM Driver |
4 | * |
5 | * Copyright 2016 Advanced Micro Devices, Inc. |
6 | */ |
7 | |
8 | #include "chip_offset_byte.h" |
9 | #include <sound/pcm.h> |
10 | #define I2S_SP_INSTANCE 0x01 |
11 | #define I2S_BT_INSTANCE 0x02 |
12 | |
13 | #define TDM_ENABLE 1 |
14 | #define TDM_DISABLE 0 |
15 | |
16 | #define ACP3x_DEVS 4 |
17 | #define ACP3x_PHY_BASE_ADDRESS 0x1240000 |
18 | #define ACP3x_I2S_MODE 0 |
19 | #define ACP3x_REG_START 0x1240000 |
20 | #define ACP3x_REG_END 0x1250200 |
21 | #define ACP3x_I2STDM_REG_START 0x1242400 |
22 | #define ACP3x_I2STDM_REG_END 0x1242410 |
23 | #define ACP3x_BT_TDM_REG_START 0x1242800 |
24 | #define ACP3x_BT_TDM_REG_END 0x1242810 |
25 | #define I2S_MODE 0x04 |
26 | #define I2S_RX_THRESHOLD 27 |
27 | #define I2S_TX_THRESHOLD 28 |
28 | #define BT_TX_THRESHOLD 26 |
29 | #define BT_RX_THRESHOLD 25 |
30 | #define ACP_ERR_INTR_MASK 29 |
31 | #define ACP3x_POWER_ON 0x00 |
32 | #define ACP3x_POWER_ON_IN_PROGRESS 0x01 |
33 | #define ACP3x_POWER_OFF 0x02 |
34 | #define ACP3x_POWER_OFF_IN_PROGRESS 0x03 |
35 | #define ACP3x_SOFT_RESET__SoftResetAudDone_MASK 0x00010001 |
36 | |
37 | #define ACP_SRAM_PTE_OFFSET 0x02050000 |
38 | #define ACP_SRAM_SP_PB_PTE_OFFSET 0x0 |
39 | #define ACP_SRAM_SP_CP_PTE_OFFSET 0x100 |
40 | #define ACP_SRAM_BT_PB_PTE_OFFSET 0x200 |
41 | #define ACP_SRAM_BT_CP_PTE_OFFSET 0x300 |
42 | #define PAGE_SIZE_4K_ENABLE 0x2 |
43 | #define I2S_SP_TX_MEM_WINDOW_START 0x4000000 |
44 | #define I2S_SP_RX_MEM_WINDOW_START 0x4020000 |
45 | #define I2S_BT_TX_MEM_WINDOW_START 0x4040000 |
46 | #define I2S_BT_RX_MEM_WINDOW_START 0x4060000 |
47 | |
48 | #define SP_PB_FIFO_ADDR_OFFSET 0x500 |
49 | #define SP_CAPT_FIFO_ADDR_OFFSET 0x700 |
50 | #define BT_PB_FIFO_ADDR_OFFSET 0x900 |
51 | #define BT_CAPT_FIFO_ADDR_OFFSET 0xB00 |
52 | #define PLAYBACK_MIN_NUM_PERIODS 2 |
53 | #define PLAYBACK_MAX_NUM_PERIODS 8 |
54 | #define PLAYBACK_MAX_PERIOD_SIZE 8192 |
55 | #define PLAYBACK_MIN_PERIOD_SIZE 1024 |
56 | #define CAPTURE_MIN_NUM_PERIODS 2 |
57 | #define CAPTURE_MAX_NUM_PERIODS 8 |
58 | #define CAPTURE_MAX_PERIOD_SIZE 8192 |
59 | #define CAPTURE_MIN_PERIOD_SIZE 1024 |
60 | |
61 | #define MAX_BUFFER (PLAYBACK_MAX_PERIOD_SIZE * PLAYBACK_MAX_NUM_PERIODS) |
62 | #define MIN_BUFFER MAX_BUFFER |
63 | #define FIFO_SIZE 0x100 |
64 | #define DMA_SIZE 0x40 |
65 | #define FRM_LEN 0x100 |
66 | |
67 | #define SLOT_WIDTH_8 0x08 |
68 | #define SLOT_WIDTH_16 0x10 |
69 | #define SLOT_WIDTH_24 0x18 |
70 | #define SLOT_WIDTH_32 0x20 |
71 | #define ACP_PGFSM_CNTL_POWER_ON_MASK 0x01 |
72 | #define ACP_PGFSM_CNTL_POWER_OFF_MASK 0x00 |
73 | #define ACP_PGFSM_STATUS_MASK 0x03 |
74 | #define ACP_POWERED_ON 0x00 |
75 | #define ACP_POWER_ON_IN_PROGRESS 0x01 |
76 | #define ACP_POWERED_OFF 0x02 |
77 | #define ACP_POWER_OFF_IN_PROGRESS 0x03 |
78 | |
79 | #define ACP3x_ITER_IRER_SAMP_LEN_MASK 0x38 |
80 | #define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF |
81 | |
82 | struct acp3x_platform_info { |
83 | u16 play_i2s_instance; |
84 | u16 cap_i2s_instance; |
85 | u16 capture_channel; |
86 | }; |
87 | |
88 | struct i2s_dev_data { |
89 | bool tdm_mode; |
90 | int i2s_irq; |
91 | u16 i2s_instance; |
92 | u32 tdm_fmt; |
93 | u32 substream_type; |
94 | void __iomem *acp3x_base; |
95 | struct snd_pcm_substream *play_stream; |
96 | struct snd_pcm_substream *capture_stream; |
97 | struct snd_pcm_substream *i2ssp_play_stream; |
98 | struct snd_pcm_substream *i2ssp_capture_stream; |
99 | }; |
100 | |
101 | struct i2s_stream_instance { |
102 | u16 num_pages; |
103 | u16 i2s_instance; |
104 | u16 capture_channel; |
105 | u16 direction; |
106 | u16 channels; |
107 | u32 xfer_resolution; |
108 | u32 val; |
109 | dma_addr_t dma_addr; |
110 | u64 bytescount; |
111 | void __iomem *acp3x_base; |
112 | }; |
113 | |
114 | static inline u32 rv_readl(void __iomem *base_addr) |
115 | { |
116 | return readl(addr: base_addr - ACP3x_PHY_BASE_ADDRESS); |
117 | } |
118 | |
119 | static inline void rv_writel(u32 val, void __iomem *base_addr) |
120 | { |
121 | writel(val, addr: base_addr - ACP3x_PHY_BASE_ADDRESS); |
122 | } |
123 | |
124 | static inline u64 acp_get_byte_count(struct i2s_stream_instance *rtd, |
125 | int direction) |
126 | { |
127 | u64 byte_count; |
128 | |
129 | if (direction == SNDRV_PCM_STREAM_PLAYBACK) { |
130 | switch (rtd->i2s_instance) { |
131 | case I2S_BT_INSTANCE: |
132 | byte_count = rv_readl(base_addr: rtd->acp3x_base + |
133 | mmACP_BT_TX_LINEARPOSITIONCNTR_HIGH); |
134 | byte_count |= rv_readl(base_addr: rtd->acp3x_base + |
135 | mmACP_BT_TX_LINEARPOSITIONCNTR_LOW); |
136 | break; |
137 | case I2S_SP_INSTANCE: |
138 | default: |
139 | byte_count = rv_readl(base_addr: rtd->acp3x_base + |
140 | mmACP_I2S_TX_LINEARPOSITIONCNTR_HIGH); |
141 | byte_count |= rv_readl(base_addr: rtd->acp3x_base + |
142 | mmACP_I2S_TX_LINEARPOSITIONCNTR_LOW); |
143 | } |
144 | |
145 | } else { |
146 | switch (rtd->i2s_instance) { |
147 | case I2S_BT_INSTANCE: |
148 | byte_count = rv_readl(base_addr: rtd->acp3x_base + |
149 | mmACP_BT_RX_LINEARPOSITIONCNTR_HIGH); |
150 | byte_count |= rv_readl(base_addr: rtd->acp3x_base + |
151 | mmACP_BT_RX_LINEARPOSITIONCNTR_LOW); |
152 | break; |
153 | case I2S_SP_INSTANCE: |
154 | default: |
155 | byte_count = rv_readl(base_addr: rtd->acp3x_base + |
156 | mmACP_I2S_RX_LINEARPOSITIONCNTR_HIGH); |
157 | byte_count |= rv_readl(base_addr: rtd->acp3x_base + |
158 | mmACP_I2S_RX_LINEARPOSITIONCNTR_LOW); |
159 | } |
160 | } |
161 | return byte_count; |
162 | } |
163 |