2 **********************************************************************
3 * hwaccess.c -- Hardware access layer
4 * Copyright 1999, 2000 Creative Labs, Inc.
6 **********************************************************************
8 * Date Author Summary of changes
9 * ---- ------ ------------------
10 * October 20, 1999 Bertrand Lee base code release
11 * December 9, 1999 Jon Taylor rewrote the I/O subsystem
13 **********************************************************************
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License as
17 * published by the Free Software Foundation; either version 2 of
18 * the License, or (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
25 * You should have received a copy of the GNU General Public
26 * License along with this program; if not, write to the Free
27 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
30 **********************************************************************
38 #include <proto/exec.h>
39 #include <proto/ahi_sub.h>
40 #include <utility/hooks.h>
46 #include "linuxsupport.h"
49 #include "pci_wrapper.h"
51 /* uncomment next line to use midi port on Audigy drive */
52 //#define USE_AUDIGY_DRIVE_MIDI
54 #ifdef USE_AUDIGY_DRIVE_MIDI
55 #define A_MUDATA A_MUDATA2
56 #define A_MUCMD A_MUCMD2
57 #define A_MUSTAT A_MUCMD2
58 #define A_IPR_MIDITRANSBUFEMPTY A_IPR_MIDITRANSBUFEMPTY2
59 #define A_IPR_MIDIRECVBUFEMPTY A_IPR_MIDIRECVBUFEMPTY2
60 #define A_INTE_MIDITXENABLE A_INTE_MIDITXENABLE2
61 #define A_INTE_MIDIRXENABLE A_INTE_MIDIRXENABLE2
63 #define A_MUDATA A_MUDATA1
64 #define A_MUCMD A_MUCMD1
65 #define A_MUSTAT A_MUCMD1
66 #define A_IPR_MIDITRANSBUFEMPTY A_IPR_MIDITRANSBUFEMPTY1
67 #define A_IPR_MIDIRECVBUFEMPTY A_IPR_MIDIRECVBUFEMPTY1
68 #define A_INTE_MIDITXENABLE A_INTE_MIDITXENABLE1
69 #define A_INTE_MIDIRXENABLE A_INTE_MIDIRXENABLE1
72 #define inb(port) (unsigned short)ahi_pci_inb(port, card->pci_dev)
73 #define inw(port) (unsigned short)ahi_pci_inw(port, card->pci_dev)
74 #define inl(port) (unsigned int)ahi_pci_inl(port, card->pci_dev)
75 #define outb(value,port) ahi_pci_outb(value, port, card->pci_dev)
76 #define outw(value,port) ahi_pci_outw(value, port, card->pci_dev)
77 #define outl(value,port) ahi_pci_outl(value, port, card->pci_dev)
90 /*************************************************************************
91 * Function : srToPitch *
92 * Input : sampleRate - sampling rate *
93 * Return : pitch value *
94 * About : convert sampling rate to pitch *
95 * Note : for 8010, sampling rate is at 48kHz, this function should *
97 *************************************************************************/
98 u32
srToPitch(u32 sampleRate
)
102 /* FIXME: These tables should be defined in a headerfile */
103 static u32 logMagTable
[128] = {
104 0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
105 0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
106 0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
107 0x3f782, 0x41e42, 0x444c1, 0x46b01, 0x49101, 0x4b6c4, 0x4dc49, 0x50191,
108 0x5269e, 0x54b6f, 0x57006, 0x59463, 0x5b888, 0x5dc74, 0x60029, 0x623a7,
109 0x646ee, 0x66a00, 0x68cdd, 0x6af86, 0x6d1fa, 0x6f43c, 0x7164b, 0x73829,
110 0x759d4, 0x77b4f, 0x79c9a, 0x7bdb5, 0x7dea1, 0x7ff5e, 0x81fed, 0x8404e,
111 0x86082, 0x88089, 0x8a064, 0x8c014, 0x8df98, 0x8fef1, 0x91e20, 0x93d26,
112 0x95c01, 0x97ab4, 0x9993e, 0x9b79f, 0x9d5d9, 0x9f3ec, 0xa11d8, 0xa2f9d,
113 0xa4d3c, 0xa6ab5, 0xa8808, 0xaa537, 0xac241, 0xadf26, 0xafbe7, 0xb1885,
114 0xb3500, 0xb5157, 0xb6d8c, 0xb899f, 0xba58f, 0xbc15e, 0xbdd0c, 0xbf899,
115 0xc1404, 0xc2f50, 0xc4a7b, 0xc6587, 0xc8073, 0xc9b3f, 0xcb5ed, 0xcd07c,
116 0xceaec, 0xd053f, 0xd1f73, 0xd398a, 0xd5384, 0xd6d60, 0xd8720, 0xda0c3,
117 0xdba4a, 0xdd3b4, 0xded03, 0xe0636, 0xe1f4e, 0xe384a, 0xe512c, 0xe69f3,
118 0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
119 0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
122 static char logSlopeTable
[128] = {
123 0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
124 0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
125 0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
126 0x4e, 0x4d, 0x4d, 0x4d, 0x4c, 0x4c, 0x4b, 0x4b,
127 0x4a, 0x4a, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47,
128 0x47, 0x46, 0x46, 0x45, 0x45, 0x45, 0x44, 0x44,
129 0x43, 0x43, 0x43, 0x42, 0x42, 0x42, 0x41, 0x41,
130 0x41, 0x40, 0x40, 0x40, 0x3f, 0x3f, 0x3f, 0x3e,
131 0x3e, 0x3e, 0x3d, 0x3d, 0x3d, 0x3c, 0x3c, 0x3c,
132 0x3b, 0x3b, 0x3b, 0x3b, 0x3a, 0x3a, 0x3a, 0x39,
133 0x39, 0x39, 0x39, 0x38, 0x38, 0x38, 0x38, 0x37,
134 0x37, 0x37, 0x37, 0x36, 0x36, 0x36, 0x36, 0x35,
135 0x35, 0x35, 0x35, 0x34, 0x34, 0x34, 0x34, 0x34,
136 0x33, 0x33, 0x33, 0x33, 0x32, 0x32, 0x32, 0x32,
137 0x32, 0x31, 0x31, 0x31, 0x31, 0x31, 0x30, 0x30,
138 0x30, 0x30, 0x30, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f
142 return 0; /* Bail out if no leading "1" */
144 sampleRate
*= 11185; /* Scale 48000 to 0x20002380 */
146 for (i
= 31; i
> 0; i
--) {
147 if (sampleRate
& 0x80000000) { /* Detect leading "1" */
148 return (u32
) (((s32
) (i
- 15) << 20) +
149 logMagTable
[0x7f & (sampleRate
>> 24)] +
150 (0x7f & (sampleRate
>> 17)) * logSlopeTable
[0x7f & (sampleRate
>> 24)]);
152 sampleRate
= sampleRate
<< 1;
155 DPF(2, "srToPitch: BUG!\n");
156 return 0; /* Should never reach this point */
159 /* Returns an attenuation based upon a cumulative volume value */
161 /* Algorithm calculates 0x200 - 0x10 log2 (input) */
162 u8
sumVolumeToAttenuation(u32 value
)
170 /* Find first SET bit. This is the integer part of the value */
171 while ((value
& 0x10000) == 0) {
176 /* The REST of the data is the fractional part. */
177 ans
= (s16
) (0x110 - ((count
<< 4) + ((value
& 0x0FFFFL
) >> 12)));
184 /*******************************************
185 * write/read PCI function 0 registers *
186 ********************************************/
187 void emu10k1_writefn0(struct emu10k1_card
*card
, u32 reg
, u32 data
)
193 if (reg
& 0xff000000) {
197 size
= (reg
>> 24) & 0x3f;
198 offset
= (reg
>> 16) & 0x1f;
199 mask
= ((1 << size
) - 1) << offset
;
200 data
= (data
<< offset
) & mask
;
203 spin_lock_irqsave(&card
->lock
, flags
);
204 data
|= inl(card
->iobase
+ reg
) & ~mask
;
205 outl(data
, card
->iobase
+ reg
);
206 spin_unlock_irqrestore(&card
->lock
, flags
);
208 spin_lock_irqsave(&card
->lock
, flags
);
209 outl(data
, card
->iobase
+ reg
);
210 spin_unlock_irqrestore(&card
->lock
, flags
);
216 void emu10k1_writefn0_2(struct emu10k1_card
*card
, u32 reg
, u32 data
, int size
)
222 spin_lock_irqsave(&card
->lock
, flags
);
225 outl(data
, card
->iobase
+ (reg
& 0x1F));
227 outw(data
, card
->iobase
+ (reg
& 0x1F));
229 outb(data
, card
->iobase
+ (reg
& 0x1F));
231 spin_unlock_irqrestore(&card
->lock
, flags
);
236 u32
emu10k1_readfn0(struct emu10k1_card
* card
, u32 reg
)
243 if (reg
& 0xff000000) {
247 size
= (reg
>> 24) & 0x3f;
248 offset
= (reg
>> 16) & 0x1f;
249 mask
= ((1 << size
) - 1) << offset
;
252 spin_lock_irqsave(&card
->lock
, flags
);
253 val
= inl(card
->iobase
+ reg
);
254 spin_unlock_irqrestore(&card
->lock
, flags
);
256 return (val
& mask
) >> offset
;
258 spin_lock_irqsave(&card
->lock
, flags
);
259 val
= inl(card
->iobase
+ reg
);
260 spin_unlock_irqrestore(&card
->lock
, flags
);
265 void emu10k1_timer_set(struct emu10k1_card
* card
, u16 data
)
271 spin_lock_irqsave(&card
->lock
, flags
);
272 outw(data
& TIMER_RATE_MASK
, card
->iobase
+ TIMER
);
273 spin_unlock_irqrestore(&card
->lock
, flags
);
277 /************************************************************************
278 * write/read Emu10k1 pointer-offset register set, accessed through *
279 * the PTR and DATA registers *
280 *************************************************************************/
281 #define A_PTR_ADDRESS_MASK 0x0fff0000
282 void sblive_writeptr(struct emu10k1_card
*card
, u32 reg
, u32 channel
, u32 data
)
289 regptr
= ((reg
<< 16) & A_PTR_ADDRESS_MASK
) | (channel
& PTR_CHANNELNUM_MASK
);
291 if (reg
& 0xff000000) {
295 size
= (reg
>> 24) & 0x3f;
296 offset
= (reg
>> 16) & 0x1f;
297 mask
= ((1 << size
) - 1) << offset
;
298 data
= (data
<< offset
) & mask
;
300 spin_lock_irqsave(&card
->lock
, flags
);
301 outl(regptr
, card
->iobase
+ PTR
);
302 data
|= inl(card
->iobase
+ DATA
) & ~mask
;
303 outl(data
, card
->iobase
+ DATA
);
304 spin_unlock_irqrestore(&card
->lock
, flags
);
306 spin_lock_irqsave(&card
->lock
, flags
);
307 outl(regptr
, card
->iobase
+ PTR
);
308 outl(data
, card
->iobase
+ DATA
);
309 spin_unlock_irqrestore(&card
->lock
, flags
);
313 /* ... : data, reg, ... , TAGLIST_END */
314 void sblive_writeptr_tag(struct emu10k1_card
*card
, u32 channel
, ...)
323 va_start(args
, channel
);
325 spin_lock_irqsave(&card
->lock
, flags
);
326 while ((reg
= va_arg(args
, u32
)) != TAGLIST_END
) {
327 u32 data
= va_arg(args
, u32
);
328 u32 regptr
= (((reg
<< 16) & A_PTR_ADDRESS_MASK
)
329 | (channel
& PTR_CHANNELNUM_MASK
));
330 outl(regptr
, card
->iobase
+ PTR
);
331 if (reg
& 0xff000000) {
332 int size
= (reg
>> 24) & 0x3f;
333 int offset
= (reg
>> 16) & 0x1f;
334 u32 mask
= ((1 << size
) - 1) << offset
;
335 data
= (data
<< offset
) & mask
;
337 data
|= inl(card
->iobase
+ DATA
) & ~mask
;
339 outl(data
, card
->iobase
+ DATA
);
341 spin_unlock_irqrestore(&card
->lock
, flags
);
348 u32
sblive_readptr(struct emu10k1_card
* card
, u32 reg
, u32 channel
)
355 regptr
= ((reg
<< 16) & A_PTR_ADDRESS_MASK
) | (channel
& PTR_CHANNELNUM_MASK
);
357 if (reg
& 0xff000000) {
361 size
= (reg
>> 24) & 0x3f;
362 offset
= (reg
>> 16) & 0x1f;
363 mask
= ((1 << size
) - 1) << offset
;
365 spin_lock_irqsave(&card
->lock
, flags
);
366 outl(regptr
, card
->iobase
+ PTR
);
367 val
= inl(card
->iobase
+ DATA
);
368 spin_unlock_irqrestore(&card
->lock
, flags
);
370 return (val
& mask
) >> offset
;
372 spin_lock_irqsave(&card
->lock
, flags
);
373 outl(regptr
, card
->iobase
+ PTR
);
374 val
= inl(card
->iobase
+ DATA
);
375 spin_unlock_irqrestore(&card
->lock
, flags
);
381 void emu10k1_irq_enable(struct emu10k1_card
*card
, u32 irq_mask
)
388 DPF(2,"emu10k1_irq_enable()\n");
390 spin_lock_irqsave(&card
->lock
, flags
);
391 val
= inl(card
->iobase
+ INTE
) | irq_mask
;
392 outl(val
, card
->iobase
+ INTE
);
393 spin_unlock_irqrestore(&card
->lock
, flags
);
397 void emu10k1_irq_disable(struct emu10k1_card
*card
, u32 irq_mask
)
404 DPF(2,"emu10k1_irq_disable()\n");
406 spin_lock_irqsave(&card
->lock
, flags
);
407 val
= inl(card
->iobase
+ INTE
) & ~irq_mask
;
408 outl(val
, card
->iobase
+ INTE
);
409 spin_unlock_irqrestore(&card
->lock
, flags
);
413 void emu10k1_set_stop_on_loop(struct emu10k1_card
*card
, u32 voicenum
)
415 /* Voice interrupt */
417 sblive_writeptr(card
, SOLEH
| ((0x0100 | (voicenum
- 32)) << 16), 0, 1);
419 sblive_writeptr(card
, SOLEL
| ((0x0100 | voicenum
) << 16), 0, 1);
424 void emu10k1_clear_stop_on_loop(struct emu10k1_card
*card
, u32 voicenum
)
426 /* Voice interrupt */
428 sblive_writeptr(card
, SOLEH
| ((0x0100 | (voicenum
- 32)) << 16), 0, 0);
430 sblive_writeptr(card
, SOLEL
| ((0x0100 | voicenum
) << 16), 0, 0);
435 static void sblive_wcwait(struct emu10k1_card
*card
, u32 wait
)
437 volatile unsigned uCount
;
438 u32 newtime
= 0, curtime
;
440 curtime
= emu10k1_readfn0(card
, WC_SAMPLECOUNTER
);
443 while (uCount
++ < TIMEOUT
) {
444 newtime
= emu10k1_readfn0(card
, WC_SAMPLECOUNTER
);
445 if (newtime
!= curtime
)
449 if (uCount
>= TIMEOUT
)
457 u16
emu10k1_ac97_read(struct ac97_codec
*codec
, u8 reg
)
459 struct emu10k1_card
*card
= codec
->private_data
;
465 spin_lock_irqsave(&card
->lock
, flags
);
467 outb(reg
, card
->iobase
+ AC97ADDRESS
);
468 data
= inw(card
->iobase
+ AC97DATA
);
470 spin_unlock_irqrestore(&card
->lock
, flags
);
472 printk( "emu10k1_ac97_read %02x->%08x\n", reg
, data
);
476 void emu10k1_ac97_write(struct ac97_codec
*codec
, u8 reg
, u16 value
)
478 struct emu10k1_card
*card
= codec
->private_data
;
481 spin_lock_irqsave(&card
->lock
, flags
);
483 outb(reg
, card
->iobase
+ AC97ADDRESS
);
484 outw(value
, card
->iobase
+ AC97DATA
);
485 outb( AC97_EXTENDED_ID
, card
->iobase
+ AC97ADDRESS
);
487 spin_unlock_irqrestore(&card
->lock
, flags
);
488 printk( "emu10k1_ac97_write %02x, %08x\n", reg
, value
);
493 u16
emu10k1_readac97(struct emu10k1_card
*card
, u8 reg
)
500 spin_lock_irqsave(&card
->lock
, flags
);
502 outb(reg
, card
->iobase
+ AC97ADDRESS
);
503 data
= inw(card
->iobase
+ AC97DATA
);
505 spin_unlock_irqrestore(&card
->lock
, flags
);
510 void emu10k1_writeac97(struct emu10k1_card
*card
, u8 reg
, u16 value
)
516 spin_lock_irqsave(&card
->lock
, flags
);
518 outb(reg
, card
->iobase
+ AC97ADDRESS
);
519 outw(value
, card
->iobase
+ AC97DATA
);
521 spin_unlock_irqrestore(&card
->lock
, flags
);
527 /*********************************************************
528 * MPU access functions *
529 **********************************************************/
531 int emu10k1_mpu_write_data(struct emu10k1_card
*card
, u8 data
)
538 if (card
->is_audigy
) {
539 if ((sblive_readptr(card
, A_MUSTAT
,0) & MUSTAT_ORDYN
) == 0) {
540 sblive_writeptr(card
, A_MUDATA
, 0, data
);
545 spin_lock_irqsave(&card
->lock
, flags
);
547 if ((inb(card
->iobase
+ MUSTAT
) & MUSTAT_ORDYN
) == 0) {
548 outb(data
, card
->iobase
+ MUDATA
);
553 spin_unlock_irqrestore(&card
->lock
, flags
);
559 int emu10k1_mpu_read_data(struct emu10k1_card
*card
, u8
* data
)
566 if (card
->is_audigy
) {
567 if ((sblive_readptr(card
, A_MUSTAT
,0) & MUSTAT_IRDYN
) == 0) {
568 *data
= sblive_readptr(card
, A_MUDATA
,0);
573 spin_lock_irqsave(&card
->lock
, flags
);
575 if ((inb(card
->iobase
+ MUSTAT
) & MUSTAT_IRDYN
) == 0) {
576 *data
= inb(card
->iobase
+ MUDATA
);
581 spin_unlock_irqrestore(&card
->lock
, flags
);
587 int emu10k1_mpu_reset(struct emu10k1_card
*card
)
594 DPF(2, "emu10k1_mpu_reset()\n");
595 if (card
->is_audigy
) {
597 if (card
->mpuacqcount
== 0) {
599 sblive_writeptr(card
, A_MUCMD
, 0, MUCMD_RESET
);
600 sblive_wcwait(card
, 8);
601 sblive_writeptr(card
, A_MUCMD
, 0, MUCMD_RESET
);
602 sblive_wcwait(card
, 8);
603 sblive_writeptr(card
, A_MUCMD
, 0, MUCMD_ENTERUARTMODE
);
604 sblive_wcwait(card
, 8);
605 status
= sblive_readptr(card
, A_MUDATA
, 0);
617 if (card
->mpuacqcount
== 0) {
619 spin_lock_irqsave(&card
->lock
, flags
);
620 outb(MUCMD_RESET
, card
->iobase
+ MUCMD
);
621 spin_unlock_irqrestore(&card
->lock
, flags
);
623 sblive_wcwait(card
, 8);
625 spin_lock_irqsave(&card
->lock
, flags
);
626 outb(MUCMD_RESET
, card
->iobase
+ MUCMD
);
627 spin_unlock_irqrestore(&card
->lock
, flags
);
629 sblive_wcwait(card
, 8);
631 spin_lock_irqsave(&card
->lock
, flags
);
632 outb(MUCMD_ENTERUARTMODE
, card
->iobase
+ MUCMD
);
633 spin_unlock_irqrestore(&card
->lock
, flags
);
635 sblive_wcwait(card
, 8);
637 spin_lock_irqsave(&card
->lock
, flags
);
638 status
= inb(card
->iobase
+ MUDATA
);
639 spin_unlock_irqrestore(&card
->lock
, flags
);
653 int emu10k1_mpu_acquire(struct emu10k1_card
*card
)
655 /* FIXME: This should be a macro */
661 int emu10k1_mpu_release(struct emu10k1_card
*card
)
663 /* FIXME: this should be a macro */