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