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