1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* |
3 | * C-Media CMI8788 driver - helper functions |
4 | * |
5 | * Copyright (c) Clemens Ladisch <clemens@ladisch.de> |
6 | */ |
7 | |
8 | #include <linux/delay.h> |
9 | #include <linux/sched.h> |
10 | #include <linux/export.h> |
11 | #include <linux/io.h> |
12 | #include <sound/core.h> |
13 | #include <sound/mpu401.h> |
14 | #include "oxygen.h" |
15 | |
16 | u8 oxygen_read8(struct oxygen *chip, unsigned int reg) |
17 | { |
18 | return inb(port: chip->addr + reg); |
19 | } |
20 | EXPORT_SYMBOL(oxygen_read8); |
21 | |
22 | u16 oxygen_read16(struct oxygen *chip, unsigned int reg) |
23 | { |
24 | return inw(port: chip->addr + reg); |
25 | } |
26 | EXPORT_SYMBOL(oxygen_read16); |
27 | |
28 | u32 oxygen_read32(struct oxygen *chip, unsigned int reg) |
29 | { |
30 | return inl(port: chip->addr + reg); |
31 | } |
32 | EXPORT_SYMBOL(oxygen_read32); |
33 | |
34 | void oxygen_write8(struct oxygen *chip, unsigned int reg, u8 value) |
35 | { |
36 | outb(value, port: chip->addr + reg); |
37 | chip->saved_registers._8[reg] = value; |
38 | } |
39 | EXPORT_SYMBOL(oxygen_write8); |
40 | |
41 | void oxygen_write16(struct oxygen *chip, unsigned int reg, u16 value) |
42 | { |
43 | outw(value, port: chip->addr + reg); |
44 | chip->saved_registers._16[reg / 2] = cpu_to_le16(value); |
45 | } |
46 | EXPORT_SYMBOL(oxygen_write16); |
47 | |
48 | void oxygen_write32(struct oxygen *chip, unsigned int reg, u32 value) |
49 | { |
50 | outl(value, port: chip->addr + reg); |
51 | chip->saved_registers._32[reg / 4] = cpu_to_le32(value); |
52 | } |
53 | EXPORT_SYMBOL(oxygen_write32); |
54 | |
55 | void oxygen_write8_masked(struct oxygen *chip, unsigned int reg, |
56 | u8 value, u8 mask) |
57 | { |
58 | u8 tmp = inb(port: chip->addr + reg); |
59 | tmp &= ~mask; |
60 | tmp |= value & mask; |
61 | outb(value: tmp, port: chip->addr + reg); |
62 | chip->saved_registers._8[reg] = tmp; |
63 | } |
64 | EXPORT_SYMBOL(oxygen_write8_masked); |
65 | |
66 | void oxygen_write16_masked(struct oxygen *chip, unsigned int reg, |
67 | u16 value, u16 mask) |
68 | { |
69 | u16 tmp = inw(port: chip->addr + reg); |
70 | tmp &= ~mask; |
71 | tmp |= value & mask; |
72 | outw(value: tmp, port: chip->addr + reg); |
73 | chip->saved_registers._16[reg / 2] = cpu_to_le16(tmp); |
74 | } |
75 | EXPORT_SYMBOL(oxygen_write16_masked); |
76 | |
77 | void oxygen_write32_masked(struct oxygen *chip, unsigned int reg, |
78 | u32 value, u32 mask) |
79 | { |
80 | u32 tmp = inl(port: chip->addr + reg); |
81 | tmp &= ~mask; |
82 | tmp |= value & mask; |
83 | outl(value: tmp, port: chip->addr + reg); |
84 | chip->saved_registers._32[reg / 4] = cpu_to_le32(tmp); |
85 | } |
86 | EXPORT_SYMBOL(oxygen_write32_masked); |
87 | |
88 | static int oxygen_ac97_wait(struct oxygen *chip, unsigned int mask) |
89 | { |
90 | u8 status = 0; |
91 | |
92 | /* |
93 | * Reading the status register also clears the bits, so we have to save |
94 | * the read bits in status. |
95 | */ |
96 | wait_event_timeout(chip->ac97_waitqueue, |
97 | ({ status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); |
98 | status & mask; }), |
99 | msecs_to_jiffies(1) + 1); |
100 | /* |
101 | * Check even after a timeout because this function should not require |
102 | * the AC'97 interrupt to be enabled. |
103 | */ |
104 | status |= oxygen_read8(chip, OXYGEN_AC97_INTERRUPT_STATUS); |
105 | return status & mask ? 0 : -EIO; |
106 | } |
107 | |
108 | /* |
109 | * About 10% of AC'97 register reads or writes fail to complete, but even those |
110 | * where the controller indicates completion aren't guaranteed to have actually |
111 | * happened. |
112 | * |
113 | * It's hard to assign blame to either the controller or the codec because both |
114 | * were made by C-Media ... |
115 | */ |
116 | |
117 | void oxygen_write_ac97(struct oxygen *chip, unsigned int codec, |
118 | unsigned int index, u16 data) |
119 | { |
120 | unsigned int count, succeeded; |
121 | u32 reg; |
122 | |
123 | reg = data; |
124 | reg |= index << OXYGEN_AC97_REG_ADDR_SHIFT; |
125 | reg |= OXYGEN_AC97_REG_DIR_WRITE; |
126 | reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; |
127 | succeeded = 0; |
128 | for (count = 5; count > 0; --count) { |
129 | udelay(5); |
130 | oxygen_write32(chip, OXYGEN_AC97_REGS, reg); |
131 | /* require two "completed" writes, just to be sure */ |
132 | if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_WRITE_DONE) >= 0 && |
133 | ++succeeded >= 2) { |
134 | chip->saved_ac97_registers[codec][index / 2] = data; |
135 | return; |
136 | } |
137 | } |
138 | dev_err(chip->card->dev, "AC'97 write timeout\n" ); |
139 | } |
140 | EXPORT_SYMBOL(oxygen_write_ac97); |
141 | |
142 | u16 oxygen_read_ac97(struct oxygen *chip, unsigned int codec, |
143 | unsigned int index) |
144 | { |
145 | unsigned int count; |
146 | unsigned int last_read = UINT_MAX; |
147 | u32 reg; |
148 | |
149 | reg = index << OXYGEN_AC97_REG_ADDR_SHIFT; |
150 | reg |= OXYGEN_AC97_REG_DIR_READ; |
151 | reg |= codec << OXYGEN_AC97_REG_CODEC_SHIFT; |
152 | for (count = 5; count > 0; --count) { |
153 | udelay(5); |
154 | oxygen_write32(chip, OXYGEN_AC97_REGS, reg); |
155 | udelay(10); |
156 | if (oxygen_ac97_wait(chip, OXYGEN_AC97_INT_READ_DONE) >= 0) { |
157 | u16 value = oxygen_read16(chip, OXYGEN_AC97_REGS); |
158 | /* we require two consecutive reads of the same value */ |
159 | if (value == last_read) |
160 | return value; |
161 | last_read = value; |
162 | /* |
163 | * Invert the register value bits to make sure that two |
164 | * consecutive unsuccessful reads do not return the same |
165 | * value. |
166 | */ |
167 | reg ^= 0xffff; |
168 | } |
169 | } |
170 | dev_err(chip->card->dev, "AC'97 read timeout on codec %u\n" , codec); |
171 | return 0; |
172 | } |
173 | EXPORT_SYMBOL(oxygen_read_ac97); |
174 | |
175 | void oxygen_write_ac97_masked(struct oxygen *chip, unsigned int codec, |
176 | unsigned int index, u16 data, u16 mask) |
177 | { |
178 | u16 value = oxygen_read_ac97(chip, codec, index); |
179 | value &= ~mask; |
180 | value |= data & mask; |
181 | oxygen_write_ac97(chip, codec, index, value); |
182 | } |
183 | EXPORT_SYMBOL(oxygen_write_ac97_masked); |
184 | |
185 | static int oxygen_wait_spi(struct oxygen *chip) |
186 | { |
187 | unsigned int count; |
188 | |
189 | /* |
190 | * Higher timeout to be sure: 200 us; |
191 | * actual transaction should not need more than 40 us. |
192 | */ |
193 | for (count = 50; count > 0; count--) { |
194 | udelay(4); |
195 | if ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & |
196 | OXYGEN_SPI_BUSY) == 0) |
197 | return 0; |
198 | } |
199 | dev_err(chip->card->dev, "oxygen: SPI wait timeout\n" ); |
200 | return -EIO; |
201 | } |
202 | |
203 | int oxygen_write_spi(struct oxygen *chip, u8 control, unsigned int data) |
204 | { |
205 | /* |
206 | * We need to wait AFTER initiating the SPI transaction, |
207 | * otherwise read operations will not work. |
208 | */ |
209 | oxygen_write8(chip, OXYGEN_SPI_DATA1, data); |
210 | oxygen_write8(chip, OXYGEN_SPI_DATA2, data >> 8); |
211 | if (control & OXYGEN_SPI_DATA_LENGTH_3) |
212 | oxygen_write8(chip, OXYGEN_SPI_DATA3, data >> 16); |
213 | oxygen_write8(chip, OXYGEN_SPI_CONTROL, control); |
214 | return oxygen_wait_spi(chip); |
215 | } |
216 | EXPORT_SYMBOL(oxygen_write_spi); |
217 | |
218 | void oxygen_write_i2c(struct oxygen *chip, u8 device, u8 map, u8 data) |
219 | { |
220 | /* should not need more than about 300 us */ |
221 | msleep(msecs: 1); |
222 | |
223 | oxygen_write8(chip, OXYGEN_2WIRE_MAP, map); |
224 | oxygen_write8(chip, OXYGEN_2WIRE_DATA, data); |
225 | oxygen_write8(chip, OXYGEN_2WIRE_CONTROL, |
226 | device | OXYGEN_2WIRE_DIR_WRITE); |
227 | } |
228 | EXPORT_SYMBOL(oxygen_write_i2c); |
229 | |
230 | static void _write_uart(struct oxygen *chip, unsigned int port, u8 data) |
231 | { |
232 | if (oxygen_read8(chip, OXYGEN_MPU401 + 1) & MPU401_TX_FULL) |
233 | msleep(msecs: 1); |
234 | oxygen_write8(chip, OXYGEN_MPU401 + port, data); |
235 | } |
236 | |
237 | void oxygen_reset_uart(struct oxygen *chip) |
238 | { |
239 | _write_uart(chip, port: 1, MPU401_RESET); |
240 | msleep(msecs: 1); /* wait for ACK */ |
241 | _write_uart(chip, port: 1, MPU401_ENTER_UART); |
242 | } |
243 | EXPORT_SYMBOL(oxygen_reset_uart); |
244 | |
245 | void oxygen_write_uart(struct oxygen *chip, u8 data) |
246 | { |
247 | _write_uart(chip, port: 0, data); |
248 | } |
249 | EXPORT_SYMBOL(oxygen_write_uart); |
250 | |
251 | u16 oxygen_read_eeprom(struct oxygen *chip, unsigned int index) |
252 | { |
253 | unsigned int timeout; |
254 | |
255 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, |
256 | index | OXYGEN_EEPROM_DIR_READ); |
257 | for (timeout = 0; timeout < 100; ++timeout) { |
258 | udelay(1); |
259 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) |
260 | & OXYGEN_EEPROM_BUSY)) |
261 | break; |
262 | } |
263 | return oxygen_read16(chip, OXYGEN_EEPROM_DATA); |
264 | } |
265 | |
266 | void oxygen_write_eeprom(struct oxygen *chip, unsigned int index, u16 value) |
267 | { |
268 | unsigned int timeout; |
269 | |
270 | oxygen_write16(chip, OXYGEN_EEPROM_DATA, value); |
271 | oxygen_write8(chip, OXYGEN_EEPROM_CONTROL, |
272 | index | OXYGEN_EEPROM_DIR_WRITE); |
273 | for (timeout = 0; timeout < 10; ++timeout) { |
274 | msleep(msecs: 1); |
275 | if (!(oxygen_read8(chip, OXYGEN_EEPROM_STATUS) |
276 | & OXYGEN_EEPROM_BUSY)) |
277 | return; |
278 | } |
279 | dev_err(chip->card->dev, "EEPROM write timeout\n" ); |
280 | } |
281 | |