2 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
4 * Routines for control of EMU10K1 chips
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.
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.
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
28 #include <linux/time.h>
29 #include <sound/core.h>
30 #include <sound/emu10k1.h>
31 #include <linux/delay.h>
32 #include <linux/export.h>
35 unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1
* emu
, unsigned int reg
, unsigned int chn
)
38 unsigned int regptr
, val
;
41 mask
= emu
->audigy
? A_PTR_ADDRESS_MASK
: PTR_ADDRESS_MASK
;
42 regptr
= ((reg
<< 16) & mask
) | (chn
& PTR_CHANNELNUM_MASK
);
44 if (reg
& 0xff000000) {
45 unsigned char size
, offset
;
47 size
= (reg
>> 24) & 0x3f;
48 offset
= (reg
>> 16) & 0x1f;
49 mask
= ((1 << size
) - 1) << offset
;
51 spin_lock_irqsave(&emu
->emu_lock
, flags
);
52 outl(regptr
, emu
->port
+ PTR
);
53 val
= inl(emu
->port
+ DATA
);
54 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
56 return (val
& mask
) >> offset
;
58 spin_lock_irqsave(&emu
->emu_lock
, flags
);
59 outl(regptr
, emu
->port
+ PTR
);
60 val
= inl(emu
->port
+ DATA
);
61 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
66 EXPORT_SYMBOL(snd_emu10k1_ptr_read
);
68 void snd_emu10k1_ptr_write(struct snd_emu10k1
*emu
, unsigned int reg
, unsigned int chn
, unsigned int data
)
75 snd_printk(KERN_ERR
"ptr_write: emu is null!\n");
79 mask
= emu
->audigy
? A_PTR_ADDRESS_MASK
: PTR_ADDRESS_MASK
;
80 regptr
= ((reg
<< 16) & mask
) | (chn
& PTR_CHANNELNUM_MASK
);
82 if (reg
& 0xff000000) {
83 unsigned char size
, offset
;
85 size
= (reg
>> 24) & 0x3f;
86 offset
= (reg
>> 16) & 0x1f;
87 mask
= ((1 << size
) - 1) << offset
;
88 data
= (data
<< offset
) & mask
;
90 spin_lock_irqsave(&emu
->emu_lock
, flags
);
91 outl(regptr
, emu
->port
+ PTR
);
92 data
|= inl(emu
->port
+ DATA
) & ~mask
;
93 outl(data
, emu
->port
+ DATA
);
94 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
96 spin_lock_irqsave(&emu
->emu_lock
, flags
);
97 outl(regptr
, emu
->port
+ PTR
);
98 outl(data
, emu
->port
+ DATA
);
99 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
103 EXPORT_SYMBOL(snd_emu10k1_ptr_write
);
105 unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1
* emu
,
110 unsigned int regptr
, val
;
112 regptr
= (reg
<< 16) | chn
;
114 spin_lock_irqsave(&emu
->emu_lock
, flags
);
115 outl(regptr
, emu
->port
+ 0x20 + PTR
);
116 val
= inl(emu
->port
+ 0x20 + DATA
);
117 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
121 void snd_emu10k1_ptr20_write(struct snd_emu10k1
*emu
,
129 regptr
= (reg
<< 16) | chn
;
131 spin_lock_irqsave(&emu
->emu_lock
, flags
);
132 outl(regptr
, emu
->port
+ 0x20 + PTR
);
133 outl(data
, emu
->port
+ 0x20 + DATA
);
134 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
137 int snd_emu10k1_spi_write(struct snd_emu10k1
* emu
,
140 unsigned int reset
, set
;
141 unsigned int reg
, tmp
;
145 /* This function is not re-entrant, so protect against it. */
146 spin_lock(&emu
->spi_lock
);
147 if (emu
->card_capabilities
->ca0108_chip
)
148 reg
= 0x3c; /* PTR20, reg 0x3c */
150 /* For other chip types the SPI register
151 * is currently unknown. */
156 /* Only 16bit values allowed */
161 tmp
= snd_emu10k1_ptr20_read(emu
, reg
, 0);
162 reset
= (tmp
& ~0x3ffff) | 0x20000; /* Set xxx20000 */
163 set
= reset
| 0x10000; /* Set xxx1xxxx */
164 snd_emu10k1_ptr20_write(emu
, reg
, 0, reset
| data
);
165 tmp
= snd_emu10k1_ptr20_read(emu
, reg
, 0); /* write post */
166 snd_emu10k1_ptr20_write(emu
, reg
, 0, set
| data
);
168 /* Wait for status bit to return to 0 */
169 for (n
= 0; n
< 100; n
++) {
171 tmp
= snd_emu10k1_ptr20_read(emu
, reg
, 0);
172 if (!(tmp
& 0x10000)) {
182 snd_emu10k1_ptr20_write(emu
, reg
, 0, reset
| data
);
183 tmp
= snd_emu10k1_ptr20_read(emu
, reg
, 0); /* Write post */
186 spin_unlock(&emu
->spi_lock
);
190 /* The ADC does not support i2c read, so only write is implemented */
191 int snd_emu10k1_i2c_write(struct snd_emu10k1
*emu
,
201 if ((reg
> 0x7f) || (value
> 0x1ff)) {
202 snd_printk(KERN_ERR
"i2c_write: invalid values.\n");
206 /* This function is not re-entrant, so protect against it. */
207 spin_lock(&emu
->i2c_lock
);
209 tmp
= reg
<< 25 | value
<< 16;
211 /* This controls the I2C connected to the WM8775 ADC Codec */
212 snd_emu10k1_ptr20_write(emu
, P17V_I2C_1
, 0, tmp
);
213 tmp
= snd_emu10k1_ptr20_read(emu
, P17V_I2C_1
, 0); /* write post */
215 for (retry
= 0; retry
< 10; retry
++) {
216 /* Send the data to i2c */
218 tmp
= tmp
| (I2C_A_ADC_LAST
|I2C_A_ADC_START
|I2C_A_ADC_ADD
);
219 snd_emu10k1_ptr20_write(emu
, P17V_I2C_ADDR
, 0, tmp
);
221 /* Wait till the transaction ends */
224 status
= snd_emu10k1_ptr20_read(emu
, P17V_I2C_ADDR
, 0);
226 if ((status
& I2C_A_ADC_START
) == 0)
229 if (timeout
> 1000) {
230 snd_printk(KERN_WARNING
231 "emu10k1:I2C:timeout status=0x%x\n",
236 //Read back and see if the transaction is successful
237 if ((status
& I2C_A_ADC_ABORT
) == 0)
242 snd_printk(KERN_ERR
"Writing to ADC failed!\n");
243 snd_printk(KERN_ERR
"status=0x%x, reg=%d, value=%d\n",
249 spin_unlock(&emu
->i2c_lock
);
253 int snd_emu1010_fpga_write(struct snd_emu10k1
* emu
, u32 reg
, u32 value
)
259 reg
+= 0x40; /* 0x40 upwards are registers. */
260 if (value
> 0x3f) /* 0 to 0x3f are values */
262 spin_lock_irqsave(&emu
->emu_lock
, flags
);
263 outl(reg
, emu
->port
+ A_IOCFG
);
265 outl(reg
| 0x80, emu
->port
+ A_IOCFG
); /* High bit clocks the value into the fpga. */
267 outl(value
, emu
->port
+ A_IOCFG
);
269 outl(value
| 0x80 , emu
->port
+ A_IOCFG
); /* High bit clocks the value into the fpga. */
270 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
275 int snd_emu1010_fpga_read(struct snd_emu10k1
* emu
, u32 reg
, u32
*value
)
280 reg
+= 0x40; /* 0x40 upwards are registers. */
281 spin_lock_irqsave(&emu
->emu_lock
, flags
);
282 outl(reg
, emu
->port
+ A_IOCFG
);
284 outl(reg
| 0x80, emu
->port
+ A_IOCFG
); /* High bit clocks the value into the fpga. */
286 *value
= ((inl(emu
->port
+ A_IOCFG
) >> 8) & 0x7f);
287 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
292 /* Each Destination has one and only one Source,
293 * but one Source can feed any number of Destinations simultaneously.
295 int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1
* emu
, u32 dst
, u32 src
)
297 snd_emu1010_fpga_write(emu
, 0x00, ((dst
>> 8) & 0x3f) );
298 snd_emu1010_fpga_write(emu
, 0x01, (dst
& 0x3f) );
299 snd_emu1010_fpga_write(emu
, 0x02, ((src
>> 8) & 0x3f) );
300 snd_emu1010_fpga_write(emu
, 0x03, (src
& 0x3f) );
305 void snd_emu10k1_intr_enable(struct snd_emu10k1
*emu
, unsigned int intrenb
)
310 spin_lock_irqsave(&emu
->emu_lock
, flags
);
311 enable
= inl(emu
->port
+ INTE
) | intrenb
;
312 outl(enable
, emu
->port
+ INTE
);
313 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
316 void snd_emu10k1_intr_disable(struct snd_emu10k1
*emu
, unsigned int intrenb
)
321 spin_lock_irqsave(&emu
->emu_lock
, flags
);
322 enable
= inl(emu
->port
+ INTE
) & ~intrenb
;
323 outl(enable
, emu
->port
+ INTE
);
324 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
327 void snd_emu10k1_voice_intr_enable(struct snd_emu10k1
*emu
, unsigned int voicenum
)
332 spin_lock_irqsave(&emu
->emu_lock
, flags
);
333 /* voice interrupt */
334 if (voicenum
>= 32) {
335 outl(CLIEH
<< 16, emu
->port
+ PTR
);
336 val
= inl(emu
->port
+ DATA
);
337 val
|= 1 << (voicenum
- 32);
339 outl(CLIEL
<< 16, emu
->port
+ PTR
);
340 val
= inl(emu
->port
+ DATA
);
341 val
|= 1 << voicenum
;
343 outl(val
, emu
->port
+ DATA
);
344 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
347 void snd_emu10k1_voice_intr_disable(struct snd_emu10k1
*emu
, unsigned int voicenum
)
352 spin_lock_irqsave(&emu
->emu_lock
, flags
);
353 /* voice interrupt */
354 if (voicenum
>= 32) {
355 outl(CLIEH
<< 16, emu
->port
+ PTR
);
356 val
= inl(emu
->port
+ DATA
);
357 val
&= ~(1 << (voicenum
- 32));
359 outl(CLIEL
<< 16, emu
->port
+ PTR
);
360 val
= inl(emu
->port
+ DATA
);
361 val
&= ~(1 << voicenum
);
363 outl(val
, emu
->port
+ DATA
);
364 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
367 void snd_emu10k1_voice_intr_ack(struct snd_emu10k1
*emu
, unsigned int voicenum
)
371 spin_lock_irqsave(&emu
->emu_lock
, flags
);
372 /* voice interrupt */
373 if (voicenum
>= 32) {
374 outl(CLIPH
<< 16, emu
->port
+ PTR
);
375 voicenum
= 1 << (voicenum
- 32);
377 outl(CLIPL
<< 16, emu
->port
+ PTR
);
378 voicenum
= 1 << voicenum
;
380 outl(voicenum
, emu
->port
+ DATA
);
381 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
384 void snd_emu10k1_voice_half_loop_intr_enable(struct snd_emu10k1
*emu
, unsigned int voicenum
)
389 spin_lock_irqsave(&emu
->emu_lock
, flags
);
390 /* voice interrupt */
391 if (voicenum
>= 32) {
392 outl(HLIEH
<< 16, emu
->port
+ PTR
);
393 val
= inl(emu
->port
+ DATA
);
394 val
|= 1 << (voicenum
- 32);
396 outl(HLIEL
<< 16, emu
->port
+ PTR
);
397 val
= inl(emu
->port
+ DATA
);
398 val
|= 1 << voicenum
;
400 outl(val
, emu
->port
+ DATA
);
401 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
404 void snd_emu10k1_voice_half_loop_intr_disable(struct snd_emu10k1
*emu
, unsigned int voicenum
)
409 spin_lock_irqsave(&emu
->emu_lock
, flags
);
410 /* voice interrupt */
411 if (voicenum
>= 32) {
412 outl(HLIEH
<< 16, emu
->port
+ PTR
);
413 val
= inl(emu
->port
+ DATA
);
414 val
&= ~(1 << (voicenum
- 32));
416 outl(HLIEL
<< 16, emu
->port
+ PTR
);
417 val
= inl(emu
->port
+ DATA
);
418 val
&= ~(1 << voicenum
);
420 outl(val
, emu
->port
+ DATA
);
421 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
424 void snd_emu10k1_voice_half_loop_intr_ack(struct snd_emu10k1
*emu
, unsigned int voicenum
)
428 spin_lock_irqsave(&emu
->emu_lock
, flags
);
429 /* voice interrupt */
430 if (voicenum
>= 32) {
431 outl(HLIPH
<< 16, emu
->port
+ PTR
);
432 voicenum
= 1 << (voicenum
- 32);
434 outl(HLIPL
<< 16, emu
->port
+ PTR
);
435 voicenum
= 1 << voicenum
;
437 outl(voicenum
, emu
->port
+ DATA
);
438 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
441 void snd_emu10k1_voice_set_loop_stop(struct snd_emu10k1
*emu
, unsigned int voicenum
)
446 spin_lock_irqsave(&emu
->emu_lock
, flags
);
447 /* voice interrupt */
448 if (voicenum
>= 32) {
449 outl(SOLEH
<< 16, emu
->port
+ PTR
);
450 sol
= inl(emu
->port
+ DATA
);
451 sol
|= 1 << (voicenum
- 32);
453 outl(SOLEL
<< 16, emu
->port
+ PTR
);
454 sol
= inl(emu
->port
+ DATA
);
455 sol
|= 1 << voicenum
;
457 outl(sol
, emu
->port
+ DATA
);
458 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
461 void snd_emu10k1_voice_clear_loop_stop(struct snd_emu10k1
*emu
, unsigned int voicenum
)
466 spin_lock_irqsave(&emu
->emu_lock
, flags
);
467 /* voice interrupt */
468 if (voicenum
>= 32) {
469 outl(SOLEH
<< 16, emu
->port
+ PTR
);
470 sol
= inl(emu
->port
+ DATA
);
471 sol
&= ~(1 << (voicenum
- 32));
473 outl(SOLEL
<< 16, emu
->port
+ PTR
);
474 sol
= inl(emu
->port
+ DATA
);
475 sol
&= ~(1 << voicenum
);
477 outl(sol
, emu
->port
+ DATA
);
478 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
481 void snd_emu10k1_wait(struct snd_emu10k1
*emu
, unsigned int wait
)
483 volatile unsigned count
;
484 unsigned int newtime
= 0, curtime
;
486 curtime
= inl(emu
->port
+ WC
) >> 6;
489 while (count
++ < 16384) {
490 newtime
= inl(emu
->port
+ WC
) >> 6;
491 if (newtime
!= curtime
)
500 unsigned short snd_emu10k1_ac97_read(struct snd_ac97
*ac97
, unsigned short reg
)
502 struct snd_emu10k1
*emu
= ac97
->private_data
;
506 spin_lock_irqsave(&emu
->emu_lock
, flags
);
507 outb(reg
, emu
->port
+ AC97ADDRESS
);
508 val
= inw(emu
->port
+ AC97DATA
);
509 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
513 void snd_emu10k1_ac97_write(struct snd_ac97
*ac97
, unsigned short reg
, unsigned short data
)
515 struct snd_emu10k1
*emu
= ac97
->private_data
;
518 spin_lock_irqsave(&emu
->emu_lock
, flags
);
519 outb(reg
, emu
->port
+ AC97ADDRESS
);
520 outw(data
, emu
->port
+ AC97DATA
);
521 spin_unlock_irqrestore(&emu
->emu_lock
, flags
);
525 * convert rate to pitch
528 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate
)
530 static u32 logMagTable
[128] = {
531 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
532 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
533 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
534 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
535 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
536 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
537 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
538 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
539 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
540 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
541 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
542 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
543 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
544 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
545 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
546 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
548 static char logSlopeTable
[128] = {
549 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
550 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
551 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
552 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
553 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
554 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
555 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
556 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
557 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
558 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
559 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
560 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
561 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
562 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
563 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
564 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
569 return 0; /* Bail out if no leading "1" */
570 rate
*= 11185; /* Scale 48000 to 0x20002380 */
571 for (i
= 31; i
> 0; i
--) {
572 if (rate
& 0x80000000) { /* Detect leading "1" */
573 return (((unsigned int) (i
- 15) << 20) +
574 logMagTable
[0x7f & (rate
>> 24)] +
575 (0x7f & (rate
>> 17)) *
576 logSlopeTable
[0x7f & (rate
>> 24)]);
581 return 0; /* Should never reach this point */