]> err.no Git - linux-2.6/blob - sound/pci/emu10k1/io.c
[ALSA] Remove sound/driver.h
[linux-2.6] / sound / pci / emu10k1 / io.c
1 /*
2  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
3  *                   Creative Labs, Inc.
4  *  Routines for control of EMU10K1 chips
5  *
6  *  BUGS:
7  *    --
8  *
9  *  TODO:
10  *    --
11  *
12  *   This program is free software; you can redistribute it and/or modify
13  *   it under the terms of the GNU General Public License as published by
14  *   the Free Software Foundation; either version 2 of the License, or
15  *   (at your option) any later version.
16  *
17  *   This program is distributed in the hope that it will be useful,
18  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *   GNU General Public License for more details.
21  *
22  *   You should have received a copy of the GNU General Public License
23  *   along with this program; if not, write to the Free Software
24  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
25  *
26  */
27
28 #include <linux/time.h>
29 #include <sound/core.h>
30 #include <sound/emu10k1.h>
31 #include <linux/delay.h>
32 #include "p17v.h"
33
34 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
35 {
36         unsigned long flags;
37         unsigned int regptr, val;
38         unsigned int mask;
39
40         mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
41         regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
42
43         if (reg & 0xff000000) {
44                 unsigned char size, offset;
45                 
46                 size = (reg >> 24) & 0x3f;
47                 offset = (reg >> 16) & 0x1f;
48                 mask = ((1 << size) - 1) << offset;
49                 
50                 spin_lock_irqsave(&emu->emu_lock, flags);
51                 outl(regptr, emu->port + PTR);
52                 val = inl(emu->port + DATA);
53                 spin_unlock_irqrestore(&emu->emu_lock, flags);
54                 
55                 return (val & mask) >> offset;
56         } else {
57                 spin_lock_irqsave(&emu->emu_lock, flags);
58                 outl(regptr, emu->port + PTR);
59                 val = inl(emu->port + DATA);
60                 spin_unlock_irqrestore(&emu->emu_lock, flags);
61                 return val;
62         }
63 }
64
65 EXPORT_SYMBOL(snd_emu10k1_ptr_read);
66
67 void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data)
68 {
69         unsigned int regptr;
70         unsigned long flags;
71         unsigned int mask;
72
73         mask = emu->audigy ? A_PTR_ADDRESS_MASK : PTR_ADDRESS_MASK;
74         regptr = ((reg << 16) & mask) | (chn & PTR_CHANNELNUM_MASK);
75
76         if (reg & 0xff000000) {
77                 unsigned char size, offset;
78
79                 size = (reg >> 24) & 0x3f;
80                 offset = (reg >> 16) & 0x1f;
81                 mask = ((1 << size) - 1) << offset;
82                 data = (data << offset) & mask;
83
84                 spin_lock_irqsave(&emu->emu_lock, flags);
85                 outl(regptr, emu->port + PTR);
86                 data |= inl(emu->port + DATA) & ~mask;
87                 outl(data, emu->port + DATA);
88                 spin_unlock_irqrestore(&emu->emu_lock, flags);          
89         } else {
90                 spin_lock_irqsave(&emu->emu_lock, flags);
91                 outl(regptr, emu->port + PTR);
92                 outl(data, emu->port + DATA);
93                 spin_unlock_irqrestore(&emu->emu_lock, flags);
94         }
95 }
96
97 EXPORT_SYMBOL(snd_emu10k1_ptr_write);
98
99 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, 
100                                           unsigned int reg, 
101                                           unsigned int chn)
102 {
103         unsigned long flags;
104         unsigned int regptr, val;
105   
106         regptr = (reg << 16) | chn;
107
108         spin_lock_irqsave(&emu->emu_lock, flags);
109         outl(regptr, emu->port + 0x20 + PTR);
110         val = inl(emu->port + 0x20 + DATA);
111         spin_unlock_irqrestore(&emu->emu_lock, flags);
112         return val;
113 }
114
115 void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, 
116                                    unsigned int reg, 
117                                    unsigned int chn, 
118                                    unsigned int data)
119 {
120         unsigned int regptr;
121         unsigned long flags;
122
123         regptr = (reg << 16) | chn;
124
125         spin_lock_irqsave(&emu->emu_lock, flags);
126         outl(regptr, emu->port + 0x20 + PTR);
127         outl(data, emu->port + 0x20 + DATA);
128         spin_unlock_irqrestore(&emu->emu_lock, flags);
129 }
130
131 int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
132                                    unsigned int data)
133 {
134         unsigned int reset, set;
135         unsigned int reg, tmp;
136         int n, result;
137         if (emu->card_capabilities->ca0108_chip)
138                 reg = 0x3c; /* PTR20, reg 0x3c */
139         else {
140                 /* For other chip types the SPI register
141                  * is currently unknown. */
142                 return 1;
143         }
144         if (data > 0xffff) /* Only 16bit values allowed */
145                 return 1;
146
147         tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
148         reset = (tmp & ~0x3ffff) | 0x20000; /* Set xxx20000 */
149         set = reset | 0x10000; /* Set xxx1xxxx */
150         snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
151         tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* write post */
152         snd_emu10k1_ptr20_write(emu, reg, 0, set | data);
153         result = 1;
154         /* Wait for status bit to return to 0 */
155         for (n = 0; n < 100; n++) {
156                 udelay(10);
157                 tmp = snd_emu10k1_ptr20_read(emu, reg, 0);
158                 if (!(tmp & 0x10000)) {
159                         result = 0;
160                         break;
161                 }
162         }
163         if (result) /* Timed out */
164                 return 1;
165         snd_emu10k1_ptr20_write(emu, reg, 0, reset | data);
166         tmp = snd_emu10k1_ptr20_read(emu, reg, 0); /* Write post */
167         return 0;
168 }
169
170 /* The ADC does not support i2c read, so only write is implemented */
171 int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
172                                 u32 reg,
173                                 u32 value)
174 {
175         u32 tmp;
176         int timeout = 0;
177         int status;
178         int retry;
179         if ((reg > 0x7f) || (value > 0x1ff)) {
180                 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
181                 return -EINVAL;
182         }
183
184         tmp = reg << 25 | value << 16;
185         // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
186         /* Not sure what this I2C channel controls. */
187         /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
188
189         /* This controls the I2C connected to the WM8775 ADC Codec */
190         snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
191         tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
192
193         for (retry = 0; retry < 10; retry++) {
194                 /* Send the data to i2c */
195                 //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
196                 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
197                 tmp = 0;
198                 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
199                 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
200
201                 /* Wait till the transaction ends */
202                 while (1) {
203                         udelay(10);
204                         status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
205                         // snd_printk("I2C:status=0x%x\n", status);
206                         timeout++;
207                         if ((status & I2C_A_ADC_START) == 0)
208                                 break;
209
210                         if (timeout > 1000) {
211                                 snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
212                                 break;
213                         }
214                 }
215                 //Read back and see if the transaction is successful
216                 if ((status & I2C_A_ADC_ABORT) == 0)
217                         break;
218         }
219
220         if (retry == 10) {
221                 snd_printk(KERN_ERR "Writing to ADC failed!\n");
222                 return -EINVAL;
223         }
224     
225         return 0;
226 }
227
228 int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, u32 reg, u32 value)
229 {
230         if (reg > 0x3f)
231                 return 1;
232         reg += 0x40; /* 0x40 upwards are registers. */
233         if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
234                 return 1;
235         outl(reg, emu->port + A_IOCFG);
236         udelay(10);
237         outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
238         udelay(10);
239         outl(value, emu->port + A_IOCFG);
240         udelay(10);
241         outl(value | 0x80 , emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
242
243         return 0;
244 }
245
246 int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, u32 reg, u32 *value)
247 {
248         if (reg > 0x3f)
249                 return 1;
250         reg += 0x40; /* 0x40 upwards are registers. */
251         outl(reg, emu->port + A_IOCFG);
252         udelay(10);
253         outl(reg | 0x80, emu->port + A_IOCFG);  /* High bit clocks the value into the fpga. */
254         udelay(10);
255         *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
256
257         return 0;
258 }
259
260 /* Each Destination has one and only one Source,
261  * but one Source can feed any number of Destinations simultaneously.
262  */
263 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, u32 dst, u32 src)
264 {
265         snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
266         snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
267         snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
268         snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
269
270         return 0;
271 }
272
273 void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
274 {
275         unsigned long flags;
276         unsigned int enable;
277
278         spin_lock_irqsave(&emu->emu_lock, flags);
279         enable = inl(emu->port + INTE) | intrenb;
280         outl(enable, emu->port + INTE);
281         spin_unlock_irqrestore(&emu->emu_lock, flags);
282 }
283
284 void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb)
285 {
286         unsigned long flags;
287         unsigned int enable;
288
289         spin_lock_irqsave(&emu->emu_lock, flags);
290         enable = inl(emu->port + INTE) & ~intrenb;
291         outl(enable, emu->port + INTE);
292         spin_unlock_irqrestore(&emu->emu_lock, flags);
293 }
294
295 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
296 {
297         unsigned long flags;
298         unsigned int val;
299
300         spin_lock_irqsave(&emu->emu_lock, flags);
301         /* voice interrupt */
302         if (voicenum >= 32) {
303                 outl(CLIEH << 16, emu->port + PTR);
304                 val = inl(emu->port + DATA);
305                 val |= 1 << (voicenum - 32);
306         } else {
307                 outl(CLIEL << 16, emu->port + PTR);
308                 val = inl(emu->port + DATA);
309                 val |= 1 << voicenum;
310         }
311         outl(val, emu->port + DATA);
312         spin_unlock_irqrestore(&emu->emu_lock, flags);
313 }
314
315 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
316 {
317         unsigned long flags;
318         unsigned int val;
319
320         spin_lock_irqsave(&emu->emu_lock, flags);
321         /* voice interrupt */
322         if (voicenum >= 32) {
323                 outl(CLIEH << 16, emu->port + PTR);
324                 val = inl(emu->port + DATA);
325                 val &= ~(1 << (voicenum - 32));
326         } else {
327                 outl(CLIEL << 16, emu->port + PTR);
328                 val = inl(emu->port + DATA);
329                 val &= ~(1 << voicenum);
330         }
331         outl(val, emu->port + DATA);
332         spin_unlock_irqrestore(&emu->emu_lock, flags);
333 }
334
335 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
336 {
337         unsigned long flags;
338
339         spin_lock_irqsave(&emu->emu_lock, flags);
340         /* voice interrupt */
341         if (voicenum >= 32) {
342                 outl(CLIPH << 16, emu->port + PTR);
343                 voicenum = 1 << (voicenum - 32);
344         } else {
345                 outl(CLIPL << 16, emu->port + PTR);
346                 voicenum = 1 << voicenum;
347         }
348         outl(voicenum, emu->port + DATA);
349         spin_unlock_irqrestore(&emu->emu_lock, flags);
350 }
351
352 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1 *emu, unsigned int voicenum)
353 {
354         unsigned long flags;
355         unsigned int val;
356
357         spin_lock_irqsave(&emu->emu_lock, flags);
358         /* voice interrupt */
359         if (voicenum >= 32) {
360                 outl(HLIEH << 16, emu->port + PTR);
361                 val = inl(emu->port + DATA);
362                 val |= 1 << (voicenum - 32);
363         } else {
364                 outl(HLIEL << 16, emu->port + PTR);
365                 val = inl(emu->port + DATA);
366                 val |= 1 << voicenum;
367         }
368         outl(val, emu->port + DATA);
369         spin_unlock_irqrestore(&emu->emu_lock, flags);
370 }
371
372 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1 *emu, unsigned int voicenum)
373 {
374         unsigned long flags;
375         unsigned int val;
376
377         spin_lock_irqsave(&emu->emu_lock, flags);
378         /* voice interrupt */
379         if (voicenum >= 32) {
380                 outl(HLIEH << 16, emu->port + PTR);
381                 val = inl(emu->port + DATA);
382                 val &= ~(1 << (voicenum - 32));
383         } else {
384                 outl(HLIEL << 16, emu->port + PTR);
385                 val = inl(emu->port + DATA);
386                 val &= ~(1 << voicenum);
387         }
388         outl(val, emu->port + DATA);
389         spin_unlock_irqrestore(&emu->emu_lock, flags);
390 }
391
392 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1 *emu, unsigned int voicenum)
393 {
394         unsigned long flags;
395
396         spin_lock_irqsave(&emu->emu_lock, flags);
397         /* voice interrupt */
398         if (voicenum >= 32) {
399                 outl(HLIPH << 16, emu->port + PTR);
400                 voicenum = 1 << (voicenum - 32);
401         } else {
402                 outl(HLIPL << 16, emu->port + PTR);
403                 voicenum = 1 << voicenum;
404         }
405         outl(voicenum, emu->port + DATA);
406         spin_unlock_irqrestore(&emu->emu_lock, flags);
407 }
408
409 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
410 {
411         unsigned long flags;
412         unsigned int sol;
413
414         spin_lock_irqsave(&emu->emu_lock, flags);
415         /* voice interrupt */
416         if (voicenum >= 32) {
417                 outl(SOLEH << 16, emu->port + PTR);
418                 sol = inl(emu->port + DATA);
419                 sol |= 1 << (voicenum - 32);
420         } else {
421                 outl(SOLEL << 16, emu->port + PTR);
422                 sol = inl(emu->port + DATA);
423                 sol |= 1 << voicenum;
424         }
425         outl(sol, emu->port + DATA);
426         spin_unlock_irqrestore(&emu->emu_lock, flags);
427 }
428
429 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1 *emu, unsigned int voicenum)
430 {
431         unsigned long flags;
432         unsigned int sol;
433
434         spin_lock_irqsave(&emu->emu_lock, flags);
435         /* voice interrupt */
436         if (voicenum >= 32) {
437                 outl(SOLEH << 16, emu->port + PTR);
438                 sol = inl(emu->port + DATA);
439                 sol &= ~(1 << (voicenum - 32));
440         } else {
441                 outl(SOLEL << 16, emu->port + PTR);
442                 sol = inl(emu->port + DATA);
443                 sol &= ~(1 << voicenum);
444         }
445         outl(sol, emu->port + DATA);
446         spin_unlock_irqrestore(&emu->emu_lock, flags);
447 }
448
449 void snd_emu10k1_wait(struct snd_emu10k1 *emu, unsigned int wait)
450 {
451         volatile unsigned count;
452         unsigned int newtime = 0, curtime;
453
454         curtime = inl(emu->port + WC) >> 6;
455         while (wait-- > 0) {
456                 count = 0;
457                 while (count++ < 16384) {
458                         newtime = inl(emu->port + WC) >> 6;
459                         if (newtime != curtime)
460                                 break;
461                 }
462                 if (count >= 16384)
463                         break;
464                 curtime = newtime;
465         }
466 }
467
468 unsigned short snd_emu10k1_ac97_read(struct snd_ac97 *ac97, unsigned short reg)
469 {
470         struct snd_emu10k1 *emu = ac97->private_data;
471         unsigned long flags;
472         unsigned short val;
473
474         spin_lock_irqsave(&emu->emu_lock, flags);
475         outb(reg, emu->port + AC97ADDRESS);
476         val = inw(emu->port + AC97DATA);
477         spin_unlock_irqrestore(&emu->emu_lock, flags);
478         return val;
479 }
480
481 void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned short data)
482 {
483         struct snd_emu10k1 *emu = ac97->private_data;
484         unsigned long flags;
485
486         spin_lock_irqsave(&emu->emu_lock, flags);
487         outb(reg, emu->port + AC97ADDRESS);
488         outw(data, emu->port + AC97DATA);
489         spin_unlock_irqrestore(&emu->emu_lock, flags);
490 }
491
492 /*
493  *  convert rate to pitch
494  */
495
496 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
497 {
498         static u32 logMagTable[128] = {
499                 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
500                 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
501                 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
502                 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
503                 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
504                 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
505                 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
506                 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
507                 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
508                 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
509                 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
510                 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
511                 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
512                 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
513                 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
514                 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
515         };
516         static char logSlopeTable[128] = {
517                 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
518                 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
519                 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
520                 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
521                 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
522                 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
523                 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
524                 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
525                 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
526                 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
527                 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
528                 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
529                 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
530                 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
531                 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
532                 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
533         };
534         int i;
535
536         if (rate == 0)
537                 return 0;       /* Bail out if no leading "1" */
538         rate *= 11185;          /* Scale 48000 to 0x20002380 */
539         for (i = 31; i > 0; i--) {
540                 if (rate & 0x80000000) {        /* Detect leading "1" */
541                         return (((unsigned int) (i - 15) << 20) +
542                                logMagTable[0x7f & (rate >> 24)] +
543                                         (0x7f & (rate >> 17)) *
544                                         logSlopeTable[0x7f & (rate >> 24)]);
545                 }
546                 rate <<= 1;
547         }
548
549         return 0;               /* Should never reach this point */
550 }
551