2 Copyright © 2004-2014, Davy Wentzler. All rights reserved.
6 #include <exec/memory.h>
9 #include <proto/expansion.h>
12 #include <proto/dos.h>
16 #include "interrupt.h"
18 #include "pci_wrapper.h"
19 #include "DriverData.h"
22 #define MAUDIO_2496_ID 0x121434D6
23 #define MAUDIO_1010LT_ID 0x12143bd6
24 #define MAUDIO_DELTA44_ID 0x121433d6
25 #define MAUDIO_DELTA66_ID 0x121432d6
27 extern const UWORD InputBits
[];
29 extern struct DOSIFace
*IDOS
;
32 struct Device
*TimerBase
= NULL
;
33 struct timerequest
*TimerIO
= NULL
;
34 struct MsgPort
*replymp
;
36 /* Public functions in main.c */
37 int card_init(struct CardData
*card
, struct DriverBase
* AHIsubBase
);
38 void card_cleanup(struct CardData
*card
);
39 void AddResetHandler(struct CardData
*card
);
42 unsigned char ReadCCI(struct CardData
*card
, unsigned char address
)
44 pci_outb(address
, CCS_ENVY_INDEX
, card
);
45 return pci_inb(CCS_ENVY_DATA
, card
);
49 void WriteCCI(struct CardData
*card
, unsigned char address
, unsigned char data
)
51 pci_outb(address
, CCS_ENVY_INDEX
, card
);
52 pci_outb(data
, CCS_ENVY_DATA
, card
);
56 unsigned char GetGPIOData(struct CardData
*card
)
58 return ReadCCI(card
, CCI_GPIO_DATA
);
62 void SetGPIOData(struct CardData
*card
, unsigned char data
)
64 WriteCCI(card
, CCI_GPIO_DATA
, data
);
68 void SaveGPIOStatus(struct CardData
*card
)
70 card
->gpio_dir
= ReadCCI(card
, CCI_GPIO_DIR
);
71 card
->gpio_data
= ReadCCI(card
, CCI_GPIO_DATA
);
75 void RestoreGPIOStatus(struct CardData
*card
)
77 WriteCCI(card
, CCI_GPIO_DIR
, card
->gpio_dir
);
78 WriteCCI(card
, CCI_GPIO_DATA
, card
->gpio_data
);
82 void ClearMask8(struct CardData
*card
, unsigned char reg
, unsigned char mask
)
86 tmp
= pci_inb_mt(reg
, card
);
88 pci_outb_mt(tmp
, reg
, card
);
92 void WriteMask8(struct CardData
*card
, unsigned char reg
, unsigned char mask
)
96 tmp
= pci_inb_mt(reg
, card
);
98 pci_outb_mt(tmp
, reg
, card
);
102 static unsigned char read_i2c(struct PCIDevice
*dev
, struct CardData
*card
, unsigned char reg
)
107 pci_outb(reg
, CCS_I2C_ADDR
, card
);
108 pci_outb(0xA0, CCS_I2C_DEV_ADDRESS
, card
); // 0xA0 is eeprom device (binary: 1010000)
110 while (t
-- > 0 && (pci_inb(CCS_I2C_STATUS
, card
) & CCS_I2C_BUSY
)) ;
112 return pci_inb(CCS_I2C_DATA
, card
);
116 void MicroDelay(unsigned int val
)
118 replymp
= (struct MsgPort
*) CreateMsgPort();
121 DebugPrintF("Could not create the reply port!\n" );
125 TimerIO
= (struct timerequest
*) CreateIORequest( replymp
, sizeof( struct timerequest
) );
129 DebugPrintF( "Out of memory.\n" );
133 if( OpenDevice( "timer.device", UNIT_MICROHZ
, (struct IORequest
*) TimerIO
, 0) != 0 )
135 DebugPrintF( "Unable to open 'timer.device'.\n" );
140 TimerBase
= (struct Device
*) TimerIO
->tr_node
.io_Device
;
145 TimerIO
->tr_node
.io_Command
= TR_ADDREQUEST
; /* Add a request. */
146 TimerIO
->tr_time
.tv_secs
= 0; /* 0 seconds. */
147 TimerIO
->tr_time
.tv_micro
= val
; /* 'val' micro seconds. */
148 DoIO( (struct IORequest
*) TimerIO
);
149 CloseDevice( (struct IORequest
*) TimerIO
);
150 DeleteIORequest( (struct IORequest
*) TimerIO
);
155 DeleteMsgPort( replymp
);
158 /******************************************************************************
159 ** DriverData allocation ******************************************************
160 ******************************************************************************/
162 // This code used to be in _AHIsub_AllocAudio(), but since we're now
163 // handling CAMD support too, it needs to be done at driver loading
167 AllocDriverData( struct PCIDevice
* dev
,
168 struct DriverBase
* AHIsubBase
)
170 struct CardData
* card
;
173 card
= AllocVec( sizeof( *card
), MEMF_PUBLIC
| MEMF_CLEAR
);
177 Req( "Unable to allocate driver structure." );
181 card
->ahisubbase
= AHIsubBase
;
183 card
->interrupt
.is_Node
.ln_Type
= NT_EXTINTERRUPT
;
184 card
->interrupt
.is_Node
.ln_Pri
= 0;
185 card
->interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
186 card
->interrupt
.is_Code
= (void(*)(void)) CardInterrupt
;
187 card
->interrupt
.is_Data
= (APTR
) card
;
189 card
->playback_interrupt
.is_Node
.ln_Type
= NT_EXTINTERRUPT
;
190 card
->playback_interrupt
.is_Node
.ln_Pri
= 0;
191 card
->playback_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
192 card
->playback_interrupt
.is_Code
= (APTR
) PlaybackInterrupt
;
193 card
->playback_interrupt
.is_Data
= (APTR
) card
;
195 card
->record_interrupt
.is_Node
.ln_Type
= NT_EXTINTERRUPT
;
196 card
->record_interrupt
.is_Node
.ln_Pri
= 0;
197 card
->record_interrupt
.is_Node
.ln_Name
= (STRPTR
) LibName
;
198 card
->record_interrupt
.is_Code
= (APTR
) RecordInterrupt
;
199 card
->record_interrupt
.is_Data
= (APTR
) card
;
203 command_word
= inw_config(PCI_COMMAND
, dev
);
204 command_word
|= PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
;
205 outw_config(PCI_COMMAND
, command_word
, dev
);
207 card
->pci_master_enabled
= TRUE
;
210 //for (i = 0; i < 6; i++)
211 // DebugPrintF("BAR[%ld] = %lx\n", i, ahi_pci_get_base_address(i, dev));
213 card
->iobase
= (IPTR
)ahi_pci_get_base_address(0, dev
);
214 card
->mtbase
= (IPTR
)ahi_pci_get_base_address(3, dev
);
215 card
->chiprev
= inb_config(PCI_REVISION_ID
, dev
);
216 card
->model
= inw_config(PCI_SUBSYSTEM_ID
, dev
);
218 //DebugPrintF("---> chiprev = %u, model = %x, Vendor = %x\n", inb_config(PCI_REVISION_ID, dev), inw_config(PCI_SUBSYSTEM_ID, dev),
219 // inw_config(PCI_SUBSYSTEM_VENDOR_ID, dev));
222 /* Initialize chip */
223 if( card_init( card
, AHIsubBase
) < 0 )
225 DebugPrintF("Unable to initialize Card subsystem.");
230 card
->interrupt_added
= ahi_pci_add_intserver(&card
->interrupt
, dev
);
233 card
->card_initialized
= TRUE
;
236 card
->monitor_volume
= 0x0;
237 card
->input_gain
= 0x10000;
238 card
->output_volume
= 0x10000;
239 //SaveMixerState(card);
240 AddResetHandler(card
);
246 /******************************************************************************
247 ** DriverData deallocation ****************************************************
248 ******************************************************************************/
250 // And this code used to be in _AHIsub_FreeAudio().
253 FreeDriverData( struct CardData
* card
,
254 struct DriverBase
* AHIsubBase
)
258 if( card
->pci_dev
!= NULL
)
260 if( card
->card_initialized
)
262 card_cleanup( card
);
265 if( card
->pci_master_enabled
)
269 cmd
= inw_config(PCI_COMMAND
, card
->pci_dev
);
270 cmd
&= ~( PCI_COMMAND_IO
| PCI_COMMAND_MEMORY
| PCI_COMMAND_MASTER
);
271 outw_config(PCI_COMMAND
, cmd
, card
->pci_dev
);
275 if( card
->interrupt_added
)
277 ahi_pci_rem_intserver(&card
->interrupt
, card
->pci_dev
);
286 int card_init(struct CardData
*card
, struct DriverBase
* AHIsubBase
)
288 struct PCIDevice
*dev
= (struct PCIDevice
*) card
->pci_dev
;
290 unsigned char eeprom
[128];
292 pci_outb(CCI_PRO_POWER_DOWN
, CCS_ENVY_INDEX
, card
);
293 pci_outb(0xFF, CCS_ENVY_DATA
, card
);
294 pci_inb(CCS_ENVY_DATA
, card
); // dummy read
296 pci_outb(CCI_PRO_POWER_DOWN
, CCS_ENVY_INDEX
, card
);
297 pci_outb(0x00, CCS_ENVY_DATA
, card
);
298 pci_inb(CCS_ENVY_DATA
, card
); // dummy read
301 // set up CCS registers
303 pci_outb(CCS_RESET_ALL
| CCS_NATIVE_MODE
, CCS_CTRL
, card
);
305 pci_outb(CCS_NATIVE_MODE
, CCS_CTRL
, card
);
308 pci_outb(~CCS_ENABLE_PRO_MACRO
, CCS_INTR_MASK
, card
);
309 pci_outb(0xFF, CCS_INTR_STATUS
, card
); // clear all
311 if (pci_inb(CCS_I2C_STATUS
, card
) & 0x80)
314 unsigned long subvendor
= 0;
316 for (i
= 0; i
< 4; i
++)
318 read_i2c(dev
, card
, i
);
320 //DebugPrintF("Read I2C %ld = %x\n", i, read_i2c(dev, card, i));
323 subvendor
= read_i2c(dev
, card
, 0) |
324 (read_i2c(dev
, card
, 1) << 8) |
325 (read_i2c(dev
, card
, 2) << 16) |
326 (read_i2c(dev
, card
, 3) << 24);
330 case MAUDIO_2496_ID
: card
->SubType
= MAUDIO_2496
;
331 DebugPrintF("M-Audio Audiophile 2496 detected!\n");
334 case MAUDIO_1010LT_ID
: card
->SubType
= MAUDIO_1010LT
;
335 DebugPrintF("M-Audio Audiophile 1010LT detected!\n");
338 case MAUDIO_DELTA44_ID
: card
->SubType
= MAUDIO_DELTA44
;
339 DebugPrintF("M-Audio Delta 44 detected!\n");
342 case MAUDIO_DELTA66_ID
: card
->SubType
= MAUDIO_DELTA66
;
343 DebugPrintF("M-Audio Delta 66 detected!\n");
346 default: card
->SubType
= PHASE88
;
347 DebugPrintF("Terratec Phase88?\n");
351 size
= read_i2c(dev
, card
, 4);
352 // read_i2c(dev, card, 5);
354 //DebugPrintF("EEPROM size = %ld, version = %ld\n", size, version);
355 size
-= 6; // including bytes 0 - 5
357 for (i
= 0; i
< size
; i
++)
359 eeprom
[i
] = read_i2c(dev
, card
, i
+ 6);
360 //DebugPrintF("Read I2C %ld = %x\n", i + 6, eeprom[i]);
363 outb_config(0x60, eeprom
[0], card
->pci_dev
); // Codecs
364 outb_config(0x61, eeprom
[1], card
->pci_dev
); // AC-link
365 outb_config(0x62, eeprom
[2], card
->pci_dev
); // I2S
366 outb_config(0x63, eeprom
[3], card
->pci_dev
); // S/PDIF
368 WriteCCI(card
, CCI_GPIO_MASK
, eeprom
[4]); // GPIO MASK
369 WriteCCI(card
, CCI_GPIO_DATA
, eeprom
[5]); // GPIO STATE
370 WriteCCI(card
, CCI_GPIO_DIR
, eeprom
[6]); // GPIO DIR
375 if (card
->SubType
== PHASE88
)
377 card
->akm_type
= AKM4524
;
380 else if (card
->SubType
== MAUDIO_2496
)
382 card
->akm_type
= AKM4528
;
384 card
->codec
[0].caddr
= 2;
385 card
->codec
[0].cif
= 0;
386 card
->codec
[0].data_mask
= ICE1712_DELTA_AP_DOUT
;
387 card
->codec
[0].clk_mask
= ICE1712_DELTA_AP_CCLK
;
389 card
->codec
[0].cs_mask
= ICE1712_DELTA_AP_CS_CODEC
;
390 card
->codec
[0].cs_addr
= ICE1712_DELTA_AP_CS_CODEC
;
391 card
->codec
[0].cs_none
= 0;
393 card
->codec
[0].add_flags
= ICE1712_DELTA_AP_CS_DIGITAL
;
394 card
->codec
[0].mask_flags
= 0;
395 card
->codec
[0].type
= AKM4528
;
397 Init_akm4xxx(card
, AKM4528
, MAUDIO_2496
);
400 else if (card
->SubType
== MAUDIO_1010LT
)
403 card
->akm_type
= AKM4524
;
405 for (chip
= 0; chip
< 4; chip
++)
407 card
->codec
[chip
].caddr
= 2;
408 card
->codec
[chip
].cif
= 0;
409 card
->codec
[chip
].data_mask
= ICE1712_DELTA_1010LT_DOUT
;
410 card
->codec
[chip
].clk_mask
= ICE1712_DELTA_1010LT_CCLK
;
412 card
->codec
[chip
].cs_mask
= ICE1712_DELTA_1010LT_CS
;
415 card
->codec
[chip
].cs_addr
= ICE1712_DELTA_1010LT_CS_CHIP_A
;
417 card
->codec
[chip
].cs_addr
= ICE1712_DELTA_1010LT_CS_CHIP_B
;
419 card
->codec
[chip
].cs_addr
= ICE1712_DELTA_1010LT_CS_CHIP_C
;
421 card
->codec
[chip
].cs_addr
= ICE1712_DELTA_1010LT_CS_CHIP_D
;
423 card
->codec
[chip
].cs_none
= ICE1712_DELTA_1010LT_CS_NONE
;
424 card
->codec
[chip
].add_flags
= 0;
425 card
->codec
[chip
].mask_flags
= 0;
427 card
->codec
[chip
].type
= AKM4524
;
430 Init_akm4xxx(card
, AKM4524
, MAUDIO_1010LT
);
432 else if (card
->SubType
== MAUDIO_DELTA44
|| card
->SubType
== MAUDIO_DELTA66
)
434 card
->akm_type
= AKM4524
;
436 card
->codec
[0].caddr
= 2;
437 card
->codec
[0].cif
= 0;
438 card
->codec
[0].data_mask
= 0x10;
439 card
->codec
[0].clk_mask
= 0x20;
441 card
->codec
[0].cs_mask
= 0x80; // 2nd codec
442 card
->codec
[0].cs_addr
= 0x80;
443 card
->codec
[0].cs_none
= 0;
444 card
->codec
[0].add_flags
= 0;
445 card
->codec
[0].mask_flags
= 0;
447 card
->codec
[0].type
= AKM4524
;
449 Init_akm4xxx(card
, AKM4524
, MAUDIO_DELTA44
);
451 card
->codec
[0].cs_mask
= 0x40; // 1st codec
452 card
->codec
[0].cs_addr
= 0x40;
453 Init_akm4xxx(card
, AKM4524
, MAUDIO_DELTA44
);
456 for (i
= 0x60; i
< 0x64; i
++)
457 DebugPrintF("config %lx = %x\n", i
, inb_config(i
, card
->pci_dev
));
459 for (i
= 0x0; i
< 0x1E; i
++)
460 DebugPrintF("CCS %lx = %x\n", i
, pci_inb(i
, card
));
462 for (i
= 0x0; i
< 0x31; i
++)
463 DebugPrintF("CCI %lx = %x\n", i
, ReadCCI(card
, i
));
465 for (i
= 0x0; i
< 0x34; i
++)
466 DebugPrintF("MT %lx = %x\n", i
, pci_inb_mt(i
, card
));
472 void card_cleanup(struct CardData
*card
)
480 Linear2MixerGain( Fixed linear
,
483 static const Fixed gain
[ 33 ] =
522 while( linear
< gain
[ v
] )
529 *bits
= 0x8000; // Mute
533 *bits
= ( v
<< 8 ) | v
;
536 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
541 Linear2RecordGain( Fixed linear
,
544 static const Fixed gain
[ 17 ] =
567 while( linear
< gain
[ v
] )
574 *bits
= 0x8000; // Mute
578 *bits
= ( ( 15 - v
) << 8 ) | ( 15 - v
);
586 SamplerateToLinearPitch( ULONG samplingrate
)
588 samplingrate
= (samplingrate
<< 8) / 375;
589 return (samplingrate
>> 1) + (samplingrate
& 1);
593 #define CACHELINE_SIZE 4096
595 void *pci_alloc_consistent(size_t size
, APTR
*NonAlignedAddress
,
596 struct DriverBase
* AHIsubBase
)
602 if (OpenResource("newmemory.resource"))
605 address
= AllocVecTags(size
, AVT_Type
, MEMF_SHARED
, AVT_Contiguous
, TRUE
, AVT_Lock
, TRUE
,
606 AVT_PhysicalAlignment
, 32, AVT_Clear
, 0, TAG_DONE
);
612 address
= AllocVec(size
+ CACHELINE_SIZE
, MEMF_PUBLIC
| MEMF_CLEAR
);
614 if( address
!= NULL
)
616 a
= (unsigned long) address
;
617 a
= (a
+ CACHELINE_SIZE
- 1) & ~(CACHELINE_SIZE
- 1);
618 address
= (void *) a
;
626 void pci_free_consistent(void* addr
, struct DriverBase
* AHIsubBase
)
632 static AROS_INTH1(ResetHandler
, struct CardData
*, card
)
636 ClearMask8(card
, MT_DMA_CONTROL
, MT_PLAY_START
| MT_REC_START
);
637 WriteMask8(card
, MT_INTR_MASK_STATUS
, MT_PLAY_MASK
| MT_REC_MASK
);
644 void AddResetHandler(struct CardData
*card
)
646 static struct Interrupt interrupt
;
648 interrupt
.is_Code
= (void (*)())ResetHandler
;
649 interrupt
.is_Data
= (APTR
) card
;
650 interrupt
.is_Node
.ln_Pri
= 0;
651 interrupt
.is_Node
.ln_Type
= NT_INTERRUPT
;
652 interrupt
.is_Node
.ln_Name
= "envy24.audio";
654 AddResetCallback( &interrupt
);