Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /*
  2  * C-Media CMI8788 driver - helper functions
  3  *
  4  * Copyright (c) Clemens Ladisch <clemens@ladisch.de>
  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 7.68 us (24 * 320 ns) */
201         count = 10;
202         while ((oxygen_read8(chip, OXYGEN_SPI_CONTROL) & OXYGEN_SPI_BUSY)
203                && count > 0) {
204                 udelay(1);
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 
  This page was automatically generated by the LXR engine.