tools/adflib: build only host variant which is used by Sam440 target
[AROS.git] / workbench / devs / AHI / Drivers / Envy24 / misc.c
blob4fbf0ac872d68a23d998f83e0f2f7ba590e8b935
1 /*
2 Copyright © 2004-2014, Davy Wentzler. All rights reserved.
3 $Id$
4 */
6 #include <exec/memory.h>
7 #ifdef __AMIGAOS4__
8 #undef __USE_INLINE__
9 #include <proto/expansion.h>
10 #endif
12 #include <proto/dos.h>
14 #include "library.h"
15 #include "regs.h"
16 #include "interrupt.h"
17 #include "misc.h"
18 #include "pci_wrapper.h"
19 #include "DriverData.h"
20 #include "Phase88.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[];
28 #ifdef __AMIGAOS4__
29 extern struct DOSIFace *IDOS;
30 #endif
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)
84 UBYTE tmp;
86 tmp = pci_inb_mt(reg, card);
87 tmp &= ~mask;
88 pci_outb_mt(tmp, reg, card);
92 void WriteMask8(struct CardData *card, unsigned char reg, unsigned char mask)
94 UBYTE tmp;
96 tmp = pci_inb_mt(reg, card);
97 tmp |= mask;
98 pci_outb_mt(tmp, reg, card);
102 static unsigned char read_i2c(struct PCIDevice *dev, struct CardData *card, unsigned char reg)
104 long t = 0x10000;
106 MicroDelay(500);
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();
119 if( !replymp )
121 DebugPrintF("Could not create the reply port!\n" );
122 return;
125 TimerIO = (struct timerequest *) CreateIORequest( replymp, sizeof( struct timerequest) );
127 if( TimerIO == NULL)
129 DebugPrintF( "Out of memory.\n" );
130 return;
133 if( OpenDevice( "timer.device", UNIT_MICROHZ, (struct IORequest *) TimerIO, 0) != 0 )
135 DebugPrintF( "Unable to open 'timer.device'.\n" );
136 return;
138 else
140 TimerBase = (struct Device *) TimerIO->tr_node.io_Device;
143 if (TimerIO)
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);
151 TimerIO = NULL;
154 if( replymp )
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
164 // time.
166 struct CardData*
167 AllocDriverData( struct PCIDevice * dev,
168 struct DriverBase* AHIsubBase )
170 struct CardData* card;
171 UWORD command_word;
173 card = AllocVec( sizeof( *card ), MEMF_PUBLIC | MEMF_CLEAR );
175 if( card == NULL )
177 Req( "Unable to allocate driver structure." );
178 return NULL;
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;
201 card->pci_dev = dev;
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.");
226 return NULL;
230 card->interrupt_added = ahi_pci_add_intserver(&card->interrupt, dev);
233 card->card_initialized = TRUE;
234 card->input = 0;
235 card->output = 0;
236 card->monitor_volume = 0x0;
237 card->input_gain = 0x10000;
238 card->output_volume = 0x10000;
239 //SaveMixerState(card);
240 AddResetHandler(card);
242 return card;
246 /******************************************************************************
247 ** DriverData deallocation ****************************************************
248 ******************************************************************************/
250 // And this code used to be in _AHIsub_FreeAudio().
252 void
253 FreeDriverData( struct CardData* card,
254 struct DriverBase* AHIsubBase )
256 if( card != NULL )
258 if( card->pci_dev != NULL )
260 if( card->card_initialized )
262 card_cleanup( card );
265 if( card->pci_master_enabled )
267 UWORD cmd;
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);
280 FreeVec( card );
286 int card_init(struct CardData *card, struct DriverBase* AHIsubBase)
288 struct PCIDevice *dev = (struct PCIDevice *) card->pci_dev;
289 int i;
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
295 MicroDelay(300);
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
299 MicroDelay(300);
301 // set up CCS registers
302 // reset
303 pci_outb(CCS_RESET_ALL | CCS_NATIVE_MODE, CCS_CTRL, card);
304 MicroDelay(300);
305 pci_outb(CCS_NATIVE_MODE, CCS_CTRL, card);
306 MicroDelay(300);
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)
313 int size;
314 unsigned long subvendor = 0;
316 for (i = 0; i < 4; i++)
318 read_i2c(dev, card, i);
319 MicroDelay(500);
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);
328 switch (subvendor)
330 case MAUDIO_2496_ID: card->SubType = MAUDIO_2496;
331 DebugPrintF("M-Audio Audiophile 2496 detected!\n");
332 break;
334 case MAUDIO_1010LT_ID: card->SubType = MAUDIO_1010LT;
335 DebugPrintF("M-Audio Audiophile 1010LT detected!\n");
336 break;
338 case MAUDIO_DELTA44_ID: card->SubType = MAUDIO_DELTA44;
339 DebugPrintF("M-Audio Delta 44 detected!\n");
340 break;
342 case MAUDIO_DELTA66_ID: card->SubType = MAUDIO_DELTA66;
343 DebugPrintF("M-Audio Delta 66 detected!\n");
344 break;
346 default: card->SubType = PHASE88;
347 DebugPrintF("Terratec Phase88?\n");
348 break;
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;
378 Phase88_Init(card);
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)
402 int chip;
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;
414 if (chip == 0)
415 card->codec[chip].cs_addr = ICE1712_DELTA_1010LT_CS_CHIP_A;
416 if (chip == 1)
417 card->codec[chip].cs_addr = ICE1712_DELTA_1010LT_CS_CHIP_B;
418 if (chip == 2)
419 card->codec[chip].cs_addr = ICE1712_DELTA_1010LT_CS_CHIP_C;
420 if (chip == 3)
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));
468 return 0;
472 void card_cleanup(struct CardData *card)
479 Fixed
480 Linear2MixerGain( Fixed linear,
481 UWORD* bits )
483 static const Fixed gain[ 33 ] =
485 260904, // +12.0 dB
486 219523, // +10.5 dB
487 184706, // +9.0 dB
488 155410, // +7.5 dB
489 130762, // +6.0 dB
490 110022, // +4.5 dB
491 92572, // +3.0 dB
492 77890, // +1.5 dB
493 65536, // ±0.0 dB
494 55142, // -1.5 dB
495 46396, // -3.0 dB
496 39037, // -4.5 dB
497 32846, // -6.0 dB
498 27636, // -7.5 dB
499 23253, // -9.0 dB
500 19565, // -10.5 dB
501 16462, // -12.0 dB
502 13851, // -13.5 dB
503 11654, // -15.0 dB
504 9806, // -16.5 dB
505 8250, // -18.0 dB
506 6942, // -19.5 dB
507 5841, // -21.0 dB
508 4915, // -22.5 dB
509 4135, // -24.0 dB
510 3479, // -25.5 dB
511 2927, // -27.0 dB
512 2463, // -28.5 dB
513 2072, // -30.0 dB
514 1744, // -31.5 dB
515 1467, // -33.0 dB
516 1234, // -34.5 dB
517 0 // -oo dB
520 int v = 0;
522 while( linear < gain[ v ] )
524 ++v;
527 if( v == 32 )
529 *bits = 0x8000; // Mute
531 else
533 *bits = ( v << 8 ) | v;
536 // KPrintF( "l2mg %08lx -> %08lx (%04lx)\n", linear, gain[ v ], *bits );
537 return gain[ v ];
540 Fixed
541 Linear2RecordGain( Fixed linear,
542 UWORD* bits )
544 static const Fixed gain[ 17 ] =
546 873937, // +22.5 dB
547 735326, // +21.0 dB
548 618700, // +19.5 dB
549 520571, // +18.0 dB
550 438006, // +16.5 dB
551 368536, // +15.0 dB
552 310084, // +13.5 dB
553 260904, // +12.0 dB
554 219523, // +10.5 dB
555 184706, // +9.0 dB
556 155410, // +7.5 dB
557 130762, // +6.0 dB
558 110022, // +4.5 dB
559 92572, // +3.0 dB
560 77890, // +1.5 dB
561 65536, // ±0.0 dB
562 0 // -oo dB
565 int v = 0;
567 while( linear < gain[ v ] )
569 ++v;
572 if( v == 16 )
574 *bits = 0x8000; // Mute
576 else
578 *bits = ( ( 15 - v ) << 8 ) | ( 15 - v );
581 return gain[ v ];
585 ULONG
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)
598 void* address;
599 unsigned long a;
601 #ifdef __AMIGAOS4__
602 if (OpenResource("newmemory.resource"))
604 *NonAlignedAddress =
605 address = AllocVecTags(size, AVT_Type, MEMF_SHARED, AVT_Contiguous, TRUE, AVT_Lock, TRUE,
606 AVT_PhysicalAlignment, 32, AVT_Clear, 0, TAG_DONE);
608 else
609 #endif
611 *NonAlignedAddress =
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;
622 return address;
626 void pci_free_consistent(void* addr, struct DriverBase* AHIsubBase)
628 FreeVec( addr );
632 static AROS_INTH1(ResetHandler, struct CardData *, card)
634 AROS_INTFUNC_INIT
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);
639 return 0UL;
641 AROS_INTFUNC_EXIT
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 );