diff options
Diffstat (limited to 'attic/drv/oss_allegro/allegro_util.inc')
-rw-r--r-- | attic/drv/oss_allegro/allegro_util.inc | 1295 |
1 files changed, 1295 insertions, 0 deletions
diff --git a/attic/drv/oss_allegro/allegro_util.inc b/attic/drv/oss_allegro/allegro_util.inc new file mode 100644 index 0000000..253508d --- /dev/null +++ b/attic/drv/oss_allegro/allegro_util.inc @@ -0,0 +1,1295 @@ +/* + * allegro_util.inc -- ESS Technology allegro audio driver. + * + * Copyright (C) 1992-2000 Don Kim (don.kim@esstech.com) + * + */ + +#define DOCKF_DOCKED 0x00000001 /* Default Un-Docked */ +#define DOCKF_DEST_CODEC2 0x00000008 /* Tells VxD CODEC2 active */ +#define HW_INIT_SET_ACTIVE_ACRW 0x00000003 /* Sets the active AC Read/Write */ +#define HW_INIT_SET_ACTIVE_ACINTF 0x00000004 /* ... AC Intf (Local or Remote) */ + +VOID CodecReset (void); +void Set2Use36Mhz (void); +void HWMGR_EnableRemoteCodec (allegro_devc * devc, BOOLEAN enable); + +#ifdef later +VOID CloseModem (); +#endif +extern PHWI gphwi; +extern oss_device_t *allegro_osdev; + +#define CODEC_TYPE_AC97 1 +#define CODEC_TYPE_ESS 2 + +#define DSP33MHZ 0 +#define DSP36MHZ 1 +#define DSP49MHZ 2 + +static unsigned char bChipType; +static unsigned char fRemoteCodec; +static unsigned char bCodec; +static unsigned char gbHwVolEnabled = TRUE; +static unsigned char bEapdSupportMode; +static unsigned int wEapdGPOPolarity_Port; +static unsigned char bEnable4Speaker; +BOOL IsAC3Format = FALSE; +BOOL g4Speaker = FALSE; + +/* + * DOCK + */ +static WORD gwDockVal; +UCHAR bEnableDockDetect = TRUE; +UCHAR bDockingDetectGPIPort = 0; /* TODO: What is the right value */ +static WORD wDockedMask; +static WORD wDockedValue; +UCHAR bMonoOutputSelect = 0; +static WORD gwDefaultMonoOutVol; +int bHwVolCtrlMode = -1; +static ULONG ulCodec; +#define NEC_VENDOR_ID3 0x80F11033 +void HwRelease (allegro_devc * devc); +#define WriteLego HWMGR_WriteCodecData +PCLIENT_INST pClient_SPDIFIN = NULL; +BOOL fSPDIFOUT = FALSE; + + +#if 0 +void +dDbgOut (char *sz, ...) +{ + char buf[256]; + va_list va; + va_start (va, sz); + vsprintf (buf, sz, va); + va_end (va); + printk (buf); + printk ("\n"); +} +#endif + +void +HwSetSystemParameter (allegro_devc * devc, DWORD dwValue) +{ + switch (dwValue >> 16) + { + case HW_INIT_SET_ACTIVE_ACRW: /*3 */ + { + dprintf1 (("ACRW %x", dwValue & DOCKF_DEST_CODEC2)); + + /* + * Set the active AC out direction + */ + if ((WORD) dwValue & DOCKF_DEST_CODEC2) /* In/Out AC2 */ + HWMGR_EnableRemoteCodec (devc, TRUE); + else + HWMGR_EnableRemoteCodec (devc, FALSE); + } + break; + + case HW_INIT_SET_ACTIVE_ACINTF: /*4 */ + { + WORD wTmp; + + dprintf1 (("ACINTF %x", dwValue)); + if (!(dwValue & DOCKF_DOCKED)) /* Nothing there */ + { + /* CODEC DAC I/F set to local only */ + wTmp = inpw (devc->osdev, devc->base + 0x3a); + wTmp &= 0xFFF3; /* [3:2] = "00" */ + outpw (devc->osdev, devc->base + 0x3a, wTmp); + + /* CODEC ADC I/F set to local only */ + wTmp = inpw (devc->osdev, devc->base + 0x3c); + wTmp &= 0xFFF3; /* [3:2] = "00" */ + outpw (devc->osdev, devc->base + 0x3c, wTmp); + } + else + { /* DOCKED */ + /* CODEC DAC I/F set to local + remote */ + wTmp = inpw (devc->osdev, devc->base + 0x3a); + wTmp &= 0xFFF3; + wTmp |= 0x000C; /* [3:2] = "11" */ + outpw (devc->osdev, devc->base + 0x3a, wTmp); + + /* CODEC ADC I/F set to remote AC2 (or both??) */ + wTmp = inpw (devc->osdev, devc->base + 0x3c); + wTmp &= 0xFFF3; + wTmp |= 0x000C; /* [3:2] = "11" */ + outpw (devc->osdev, devc->base + 0x3c, wTmp); + } + } + break; + } +} + +VOID +PCIWrite (allegro_devc * devc, WORD address, ULONG value) +{ + + pci_write_config_dword (devc->osdev, address, value); + +} + +ULONG +PCIRead (allegro_devc * devc, WORD address) +{ + unsigned int dw; + pci_read_config_dword (devc->osdev, address, &dw); + return dw; +} + +#ifdef DEBUGINTERFACE +void +dumpreg (WORD programid, WORD index, WORD value, WORD * out) +{ + ULONG dwData; + + switch (programid) + { + case 1: /* aggr */ + *out = inpw (devc->osdev, devc->base + index); + break; + + case 2: /* aggw */ + outpw (devc->osdev, devc->base + index, value); + break; + + case 3: /* legor */ + HWMGR_ReadCodecData (devc, devc->osdev, index, out); + break; + + case 4: /* legow */ + HWMGR_WriteCodecData (devc, (UCHAR) index, value); + break; + + case 5: /* pciar */ + index &= ~0x1; /* make sure it's even address */ + dwData = PCIRead (devcv, index & ~0x3); + if ((index % 4) == 0) + *out = (WORD) dwData; + else + *out = (WORD) (dwData >> 16); + break; + + case 6: /* pciaw */ + index &= ~0x1; /* make sure it's even address */ + dwData = PCIRead (devc, index & ~0x3); + if ((index % 4) == 0) + { + dwData &= ~0xffff; + dwData |= value; + } + else + { + dwData &= 0xffff; + dwData |= (value << 16); + } + PCIWrite (devc, (index & ~0x3), dwData); + break; + } +} +#endif /* DEBUGINTERFACE */ + +void +DelayMillisec (int millisec) +{ + int count; + + millisec = millisec * 1000 / 50; + for (count = 0; count < millisec; count++) + KeStallExecutionProcessor (50); +} /* DelayMillisec */ + +/* -------------------------------------------------------------------------- */ + +UCHAR +HWMGR_ReadDataByte (allegro_devc * devc, UCHAR Index) +{ + return READ_PORT_UCHAR (devc->osdev, devc->base + Index); +} /* HWMGR_ReadDataByte */ + + +USHORT +HWMGR_ReadDataWord (allegro_devc * devc, UCHAR Index) +{ + return READ_PORT_USHORT (devc->osdev, devc->base + Index); +} /* HWMGR_ReadDataWord */ + + +void +HWMGR_WriteDataByte (allegro_devc * devc, UCHAR Index, UCHAR Value) +{ + WRITE_PORT_UCHAR (devc->osdev, devc->base + Index, Value); +} /* HWMGR_WriteDataByte */ + + +void +HWMGR_WriteDataWord (allegro_devc * devc, UCHAR Index, USHORT Value) +{ + WRITE_PORT_USHORT (devc->osdev, devc->base + Index, Value); +} /* HWMGR_WriteDataWord */ + + +void +HWMGR_RestoreACLink (allegro_devc * devc) +{ + int i; + USHORT wDataCodec; + USHORT wDataIn; + USHORT wDataOut; + USHORT wControl = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_A); + + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, (USHORT) (wControl & + ~SERIAL_AC_LINK_ENABLE)); + KeStallExecutionProcessor (50); + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, wControl); + + wDataCodec = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_B); + wDataIn = HWMGR_ReadDataWord (devc, SDO_IN_DEST_CTRL); + wDataOut = HWMGR_ReadDataWord (devc, SDO_OUT_DEST_CTRL); + + HWMGR_WriteDataWord (devc, SDO_OUT_DEST_CTRL, (USHORT) (wDataOut & + ~COMMAND_ADDR_OUT)); + HWMGR_WriteDataWord (devc, SDO_IN_DEST_CTRL, (USHORT) (wDataIn & + ~STATUS_ADDR_IN)); + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, (USHORT) (wDataCodec & + ~SECOND_CODEC_ID_MASK)); + + /* power down DAC to resynchronize after AC-link change */ + HWMGR_WriteDataWord (devc, CODEC_DATA, AC97_PR1); + HWMGR_WriteDataByte (devc, CODEC_COMMAND, AC97_POWER_DOWN_CTRL); + for (i = 0; i < 1000; i++) + if (!(HWMGR_ReadDataByte (devc, CODEC_STATUS) & CODEC_BUSY_B)) + break; + KeStallExecutionProcessor (1); + HWMGR_WriteDataWord (devc, CODEC_DATA, 0); + HWMGR_WriteDataByte (devc, CODEC_COMMAND, AC97_POWER_DOWN_CTRL); + for (i = 0; i < 1000; i++) + if (!(HWMGR_ReadDataByte (devc, CODEC_STATUS) & CODEC_BUSY_B)) + break; + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, wDataCodec); + HWMGR_WriteDataWord (devc, SDO_IN_DEST_CTRL, wDataIn); + HWMGR_WriteDataWord (devc, SDO_OUT_DEST_CTRL, wDataOut); +} /* HWMGR_RestoreACLink */ + +BOOLEAN +HWMGR_ReadCodecData (allegro_devc * devc, UCHAR Index, PUSHORT Value) +{ + int i; + + *Value = 0; + HWMGR_WriteDataByte (devc, CODEC_COMMAND, (UCHAR) (CODEC_READ_B | Index)); + for (i = 0; i < 1000; i++) + { + if (!(HWMGR_ReadDataByte (devc, CODEC_STATUS) & CODEC_BUSY_B)) + { + *Value = HWMGR_ReadDataWord (devc, CODEC_DATA); + return TRUE; + } + } + if (CODEC_TYPE_ESS == bCodec) + HWMGR_RestoreACLink (devc); + + return FALSE; +} /* HWMGR_ReadCodecData */ + + +BOOLEAN +HWMGR_WriteCodecData (allegro_devc * devc, UCHAR Index, USHORT Value) +{ + int i; + + HWMGR_WriteDataWord (devc, CODEC_DATA, Value); + HWMGR_WriteDataByte (devc, CODEC_COMMAND, Index); + for (i = 0; i < 1000; i++) + { + if (!(HWMGR_ReadDataByte (devc, CODEC_STATUS) & CODEC_BUSY_B)) + { + return TRUE; + } + } + if (CODEC_TYPE_ESS == bCodec) + HWMGR_RestoreACLink (devc); + return FALSE; +} /* HWMGR_WriteCodecData */ + +void +HWMGR_EnableExternalAmp (allegro_devc * devc, BOOLEAN enable) +{ + USHORT wDirection; + USHORT wGPO; + USHORT wGPO2; + USHORT wPolarity; + USHORT wPolarity2; + + /* + * by default, setup for reference board + */ + if (bEapdSupportMode == 0) + { + bEapdSupportMode = 1; + if (bChipType >= M3_1998) + wEapdGPOPolarity_Port = 0x1100; + else + { + wEapdGPOPolarity_Port = 0x1800; + if (bChipType == 2) + wEapdGPOPolarity_Port = 0x1c00; + if (bEnable4Speaker) + wEapdGPOPolarity_Port = 0x1600; + } + } + + dprintf3 (("Mode=%x PPort=%x", bEapdSupportMode, wEapdGPOPolarity_Port)); + wGPO2 = wPolarity2 = 0; + switch (bEapdSupportMode) + { + case 0: + break; + case 2: + wGPO2 = wEapdGPOPolarity_Port & 0x0F; + wPolarity2 = wEapdGPOPolarity_Port >> 4 & 0x0F; + if (enable) + wPolarity2 = !wPolarity2; + wPolarity2 = wPolarity2 << wGPO2; + wGPO2 = 1 << wGPO2; + wGPO = wEapdGPOPolarity_Port >> 8 & 0x0F; + wPolarity = wEapdGPOPolarity_Port >> 12; + if (enable) + wPolarity = !wPolarity; + wPolarity = wPolarity << wGPO; + wGPO = 1 << wGPO; + wGPO |= wGPO2; + wPolarity |= wPolarity2; + HWMGR_WriteDataWord (devc, GPIO_MASK, (USHORT) ~ wGPO); + wDirection = HWMGR_ReadDataWord (devc, GPIO_DIRECTION) | wGPO; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + HWMGR_WriteDataWord (devc, GPIO_DATA, (USHORT) (GPO_SECONDARY_AC97 | + GPO_PRIMARY_AC97 | + wPolarity)); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + break; + + case 1: + wGPO = wEapdGPOPolarity_Port >> 8 & 0x0F; + wPolarity = wEapdGPOPolarity_Port >> 12; + if (enable) + wPolarity = !wPolarity; + wPolarity = wPolarity << wGPO; + wGPO = 1 << wGPO; + wGPO |= wGPO2; + wPolarity |= wPolarity2; + HWMGR_WriteDataWord (devc, GPIO_MASK, (USHORT) ~ wGPO); + wDirection = HWMGR_ReadDataWord (devc, GPIO_DIRECTION) | wGPO; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + HWMGR_WriteDataWord (devc, GPIO_DATA, (USHORT) (GPO_SECONDARY_AC97 | + GPO_PRIMARY_AC97 | + wPolarity)); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + break; + } +} /* HWMGR_EnableExternalAmp */ + + +void +HWMGR_EnableRemoteCodec (allegro_devc * devc, BOOLEAN enable) +{ + USHORT wData; + +/* This function MUST be in a non-paged segment */ +/* PAGED_CODE(); */ + if (enable == fRemoteCodec) + return; + fRemoteCodec = enable; + if (enable) + { + + /* enable remote codec */ + wData = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_B); + wData = (wData & ~SECOND_CODEC_ID_MASK) | 1; + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, wData); + wData = HWMGR_ReadDataWord (devc, SDO_OUT_DEST_CTRL); + wData = (wData & ~COMMAND_ADDR_OUT) | 1; + HWMGR_WriteDataWord (devc, SDO_OUT_DEST_CTRL, wData); + wData = HWMGR_ReadDataWord (devc, SDO_IN_DEST_CTRL); + wData = (wData & ~STATUS_ADDR_IN) | 1; + HWMGR_WriteDataWord (devc, SDO_IN_DEST_CTRL, wData); + } + else + { + + /* disable remote codec */ + wData = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_B); + wData = wData & ~SECOND_CODEC_ID_MASK; + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, wData); + wData = HWMGR_ReadDataWord (devc, SDO_OUT_DEST_CTRL); + wData = wData & ~COMMAND_ADDR_OUT; + HWMGR_WriteDataWord (devc, SDO_OUT_DEST_CTRL, wData); + wData = HWMGR_ReadDataWord (devc, SDO_IN_DEST_CTRL); + wData = wData & ~STATUS_ADDR_IN; + HWMGR_WriteDataWord (devc, SDO_IN_DEST_CTRL, wData); + } +} /* HWMGR_EnableRemoteCodec */ + +#define AKM_CODEC 0x414B4D +#define TRA_CODEC 0x545241 +#define ESS_CODEC 0x458383 +#define STAC9721_CODEC 0x838476 +#define STAC9721_REV_C 0x09 +#define STAC9721_REV_D 0x44 + +BOOLEAN +HWMGR_ReadVendorId (allegro_devc * devc, OUT PULONG pulData, OUT PBYTE pbRev) +{ + USHORT wData; + + *pulData = 0; + if (HWMGR_ReadCodecData (devc, AC97_VENDOR_ID1, &wData)) + { + *pulData = (ULONG) wData << 16; + if (HWMGR_ReadCodecData (devc, AC97_VENDOR_ID2, &wData)) + { + *pulData |= wData; + *pbRev = (UCHAR) * pulData; + *pulData >>= 8; + return TRUE; + } + *pulData = 0; + } + return FALSE; +} /* HWMGR_ReadVendorId */ + +void +HWMGR_ResetCodec (allegro_devc * devc) +{ + ULONG ulData; + USHORT wData; + USHORT wDirection; + int delay_count; + int reset_count; + int wait_count; + int DoReset = TRUE; + BYTE bSaveCodec; + BYTE bRev; + + delay_count = reset_count = wait_count = 0; + wDirection = HWMGR_ReadDataWord (devc, GPIO_DIRECTION); + + /* not sure if this applies for Allegro-1/Maestro-3 */ + if (PCIRead (devc, PCI_USER_CONFIG) & EXT_PCI_MASTER_ENABLE) + { + + /* GPIO4 = output */ + wDirection |= 0x10; + } + + HWMGR_EnableRemoteCodec (devc, FALSE); + + /* set bCodec to undefined so that ReadCodecData will not try to restore */ + /* AC-link */ + bSaveCodec = bCodec; + bCodec = 0; + + /* If we can read codec, skip codec reset to avoid pop sound. */ + /* HP Omnibook M3 does not setup AC-link correctly */ + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, IO_SRAM_ENABLE); + + /* delay at least 20 us if disabling AC-link */ + KeStallExecutionProcessor (20); + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, + IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE); + KeStallExecutionProcessor (1); + if (HWMGR_ReadVendorId (devc, &ulData, &bRev)) + { + + dprintf1 (("codec1 id = %x", ulData)); + /* do not need to reset */ + DoReset = FALSE; + } + if (ulData != 0 && ulData != 0xFFFFFF) + { + ulCodec = ulData; + bCodec = CODEC_TYPE_AC97; + if (TRA_CODEC == ulCodec) + { + + /* fix for tritech 2.0a codec */ + HWMGR_WriteCodecData (devc, 0x2A, 0x0001); + HWMGR_WriteCodecData (devc, 0x2C, 0x0000); + HWMGR_WriteCodecData (devc, 0x2C, 0xFFFF); + } + else if (ESS_CODEC == ulCodec) + { + bCodec = CODEC_TYPE_ESS; + } + } + else + { + if (bChipType >= M3_1998) + bCodec = CODEC_TYPE_AC97; + else + bCodec = CODEC_TYPE_ESS; + } + if (bSaveCodec) + { + bCodec = bSaveCodec; + } + + dprintf1 (("reset codec1 bCodec=%d DoReset=%d", bCodec, DoReset)); + /* reset primary codec */ + if (DoReset) + { + + /* regular AC97 codec */ + if (bChipType >= M3_1998) + { + delay_count = 20; +#if CRYSTAL_CODEC_FIX + if (!ulCodec || CRY_CODEC == ulCodec) + { + wait_count = 500; + } + else + { + wait_count = 20; + } +#else + wait_count = 20; +#endif + } + else + { + delay_count = 50; + + /* delay 800 ms!? */ + wait_count = 800; + } + reset_count = 0; + + RESET_CODEC: + + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, IO_SRAM_ENABLE); + + /* delay at least 20 us if disabling AC-link */ + KeStallExecutionProcessor (20); + + /* write GPO0 */ + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, + wDirection & ~GPO_PRIMARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_MASK, (USHORT) ~ GPO_PRIMARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_DATA, 0x000); + wDirection |= GPO_PRIMARY_AC97; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + + /* delay 20 ms */ + DelayMillisec (delay_count); + HWMGR_WriteDataWord (devc, GPIO_DATA, GPO_PRIMARY_AC97); + KeStallExecutionProcessor (5); + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, + IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + + /* wait for codec to be ready */ + DelayMillisec (wait_count); + +#if defined( AC97_RESETFIX ) + /* If unable to read from Codec, perform special reset */ + if (!HWMGR_ReadCodecData (devc, AC97_VENDOR_ID1, &wData)) + { + /* Save Serial Link Configuration */ + HWMGR_ReadDataWord (devc, RING_BUS_CTRL_A, &wRingBusReg); + + /* Disable Serial AC Link and Cold Reset Codec */ + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, _AC_SDFS_ENABLE); + + /* Delay 20mS */ + for (count = 0; count < 400; count++) + KeStallExecutionProcessor (50); + + /* Enable AC Serial Link */ + HWMGR_WriteDataWord (devc, RING_BUG_CTRL_A, wRingBusReg); + + if (!HWMGR_ReadCodecData (devc, AC97_VENDOR_ID1, &wData)) + { + /* Disable Serial AC Link and Cold Reset Codec */ + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, _AC_SDFS_ENABLE); + + /* Warm Reset Codec */ + HWMGR_WriteDataByte (devc, CODEC_COMMAND, 0x00); + /* Delay 20mS */ + for (count = 0; count < 400; count++) + KeStallExecutionProcessor (50); + + /* Enable AC Serial Link */ + HWMGR_WriteDataWord (devc, RING_BUG_CTRL_A, wRingBusReg); + + /* Set AC97 PR4 26h[12] */ + HWMGR_ReadCodecData (devc, AC97_POWER_DOWN_CTRL, &wData); + HWMGR_WriteCodecData (devc, AC97_POWER_DOWN_CTRL, + wData | AC97_PR4); + + /* Warm Reset Codec */ + HWMGR_WriteDataByte (devc, CODEC_COMMAND, 0x00); + /* Delay 20mS */ + for (count = 0; count < 400; count++) + KeStallExecutionProcessor (50); + } + } +#endif + + if (!bCodec) + { + if (HWMGR_ReadVendorId (devc, &ulData, &bRev)) + { + if (ulData != 0 && ulData != 0xFFFFFF) + { + ulCodec = ulData; + bCodec = CODEC_TYPE_AC97; + if (TRA_CODEC == ulCodec) + { + + /* fix for tritech 2.0a codec */ + HWMGR_WriteCodecData (devc, 0x2A, 0x0001); + HWMGR_WriteCodecData (devc, 0x2C, 0x0000); + HWMGR_WriteCodecData (devc, 0x2C, 0xFFFF); + } + else if (ESS_CODEC == ulCodec) + { + bCodec = CODEC_TYPE_ESS; + } + } + } + else + { + if (++reset_count < 20) + { + delay_count += 10; + wait_count += 100; + goto RESET_CODEC; + } + } + if (!bCodec) + { + if (bChipType >= M3_1998) + bCodec = CODEC_TYPE_AC97; + else + bCodec = CODEC_TYPE_ESS; + } + } + } + else if ((wDirection & GPO_PRIMARY_AC97) == 0) + { + HWMGR_WriteDataWord (devc, GPIO_MASK, (USHORT) ~ GPO_PRIMARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_DATA, GPO_PRIMARY_AC97); + wDirection |= GPO_PRIMARY_AC97; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + } + + dprintf1 (("Codec:%d\n", bCodec)); + + if (CODEC_TYPE_ESS == bCodec) + { + if (HWMGR_ReadCodecData (devc, AC97_CLOCK_DELAY, &wData)) + { + wData &= ~(AC97_CLOCK_DELAY_SEL << AC97_ADC_CDS_SHIFT); + wData |= 18 << AC97_ADC_CDS_SHIFT; + HWMGR_WriteCodecData (devc, AC97_CLOCK_DELAY, wData); + } + else + { + if (++reset_count < 20) + { + delay_count += 10; + wait_count += 100; + goto RESET_CODEC; + } + } + } + + if (gwDockVal) + { + HWMGR_EnableRemoteCodec (devc, TRUE); + + wData = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_B); + wData &= ~(SECOND_AC_ENABLE | SECOND_CODEC_ID_MASK); + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, + (USHORT) (wData | SECOND_AC_ENABLE | 1)); + + /* If we can read codec, skip codec reset to avoid pop sound. */ + DoReset = TRUE; + if (HWMGR_ReadVendorId (devc, &ulData, &bRev)) + { + + dprintf1 (("Read:%x,%x\n", ulData, bRev)); + + /* do not need to reset */ + DoReset = FALSE; + } + + /* reset secondary codec */ + if (DoReset) + { + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, IO_SRAM_ENABLE); + + /* delay at least 20 us if disabling AC-link */ + KeStallExecutionProcessor (20); + + /* write GPO3 */ + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, + wDirection & ~GPO_SECONDARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_MASK, + (USHORT) ~ GPO_SECONDARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_DATA, 0x000); + wDirection |= GPO_SECONDARY_AC97; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + + /* delay 20 ms */ + DelayMillisec (20); + HWMGR_WriteDataWord (devc, GPIO_DATA, GPO_SECONDARY_AC97); + + /* delay 20 ms */ + DelayMillisec (20); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_A, + IO_SRAM_ENABLE | SERIAL_AC_LINK_ENABLE); + KeStallExecutionProcessor (1); + + /* read vendor id */ + (void) HWMGR_ReadVendorId (devc, &ulData, &bRev); + + dprintf1 (("Reset:%x,%x\n", ulData, bRev)); + } + else if ((wDirection & GPO_SECONDARY_AC97) == 0) + { + HWMGR_WriteDataWord (devc, GPIO_MASK, + (USHORT) ~ GPO_SECONDARY_AC97); + HWMGR_WriteDataWord (devc, GPIO_DATA, GPO_SECONDARY_AC97); + wDirection |= GPO_SECONDARY_AC97; + HWMGR_WriteDataWord (devc, GPIO_DIRECTION, wDirection); + HWMGR_WriteDataWord (devc, GPIO_MASK, 0xFFFF); + } + if (ulData != 0 && ulData != 0xFFFFFF) + { + if (TRA_CODEC == ulData) + { + + /* fix for tritech 2.0a codec */ + HWMGR_WriteCodecData (devc, 0x2A, 0x0001); + HWMGR_WriteCodecData (devc, 0x2C, 0x0000); + HWMGR_WriteCodecData (devc, 0x2C, 0xFFFF); + } + else if (STAC9721_CODEC == ulData) + { + USHORT wStatus; + + if (!HWMGR_ReadCodecData + (devc, AC97_POWER_DOWN_CTRL, &wStatus) || 0 == wStatus) + { + HWMGR_WriteCodecData (devc, 0x76, 0xABBA); + if (STAC9721_REV_D == bRev) + { + HWMGR_WriteCodecData (devc, 0x78, 0x2002); + KeStallExecutionProcessor (20); + HWMGR_WriteCodecData (devc, 0x78, 0x2802); + } + else + { + HWMGR_WriteCodecData (devc, 0x78, 0x3002); + KeStallExecutionProcessor (20); + HWMGR_WriteCodecData (devc, 0x78, 0x3802); + } + } + } + } + HWMGR_EnableRemoteCodec (devc, FALSE); + + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, wData); + } +} /* HWMGR_ResetCodec */ + +#if 0 +#define DSP33MHZ 0 +#define DSP36MHZ 1 +#define DSP49MHZ 2 +#endif + + +UCHAR bGray_Code[32] = { + 0x00, 0x01, 0x03, 0x02, 0x07, 0x06, 0x04, 0x05, + 0x0F, 0x0E, 0x0C, 0x0D, 0x08, 0x09, 0x0B, 0x0A, + 0x1F, 0x1E, 0x1C, 0x1D, 0x18, 0x19, 0x1B, 0x1A, + 0x10, 0x11, 0x13, 0x12, 0x17, 0x16, 0x14, 0x15 +}; + +void +HWMGR_SetClockSpeed (allegro_devc * devc, UCHAR speed) +{ + ULONG ulData; + int choice; + int mode; + UCHAR bModeValue[8]; + UCHAR bData; + UCHAR bDelta; + + HWMGR_WriteDataByte (devc, ASSP_CONTROL_B, RESET_ASSP); + + ulData = PCIRead (devc, PCI_ALLEGRO_CONFIG); + ulData &= ~INT_CLK_SELECT; + ulData &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2); + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + if (DSP36MHZ == speed) + { + ulData = PCIRead (devc, PCI_USER_CONFIG); + ulData &= ~IN_CLK_12MHZ_SELECT; + PCIWrite (devc, PCI_USER_CONFIG, ulData); + + for (mode = 0; mode < 4; mode++) + { + ulData |= INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~CLK_MULT_MODE_SELECT; + ulData |= mode << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + bModeValue[mode] = + bGray_Code[HWMGR_ReadDataWord (devc, CLK_MULT_DATA_PORT) >> 5 + & 0x1F]; + } + ulData |= CLK_MULT_MODE_SELECT_2; + for (mode = 0; mode < 4; mode++) + { + ulData |= INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~CLK_MULT_MODE_SELECT; + ulData |= mode << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + bModeValue[mode + 4] = + bGray_Code[HWMGR_ReadDataWord (devc, CLK_MULT_DATA_PORT) >> 5 + & 0x1F]; + } +#define Abs(x) ((x)<0) ? -(x) : (x) + bDelta = Abs (bModeValue[0] - 0x10); + choice = 0; + for (mode = 1; mode < 8; mode++) + { + if (bDelta > Abs (bModeValue[mode] - 0x10)) + { + bDelta = Abs (bModeValue[mode] - 0x10); + choice = mode; + } + } + +#if 0 + _Debug_Printf_Service ("mode:%d\n", choice); +#endif + ulData &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2); + if (choice > 3) + { + ulData |= CLK_MULT_MODE_SELECT_2; + choice -= 4; + } + ulData |= INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData |= choice << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~INT_CLK_MULT_RESET; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + ulData |= INT_CLK_SELECT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + } + else + { + ulData = PCIRead (devc, PCI_USER_CONFIG); + ulData |= IN_CLK_12MHZ_SELECT; + PCIWrite (devc, PCI_USER_CONFIG, ulData); + } + + bData = HWMGR_ReadDataByte (devc, ASSP_CONTROL_A); + bData &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT); + bData |= ASSP_0_WS_ENABLE; + switch (speed) + { + case DSP36MHZ: + bData |= DSP_CLK_36MHZ_SELECT; + break; + case DSP49MHZ: + bData |= ASSP_CLK_49MHZ_SELECT; + break; + } + HWMGR_WriteDataByte (devc, ASSP_CONTROL_A, bData); + + HWMGR_WriteDataByte (devc, ASSP_CONTROL_B, RUN_ASSP); +} /* HWMGR_SetClockSpeed */ + +void +HWMGR_SetM3ClockSpeed (allegro_devc * devc, UCHAR speed) +{ + ULONG ulData; + int choice; + int mode; + UCHAR bModeValue[8]; + UCHAR bData; + UCHAR bDelta; + + HWMGR_WriteDataByte (devc, ASSP_CONTROL_B, RESET_ASSP); + + ulData = PCIRead (devc, PCI_ALLEGRO_CONFIG); + if (DSP33MHZ == speed) + ulData &= ~INT_CLK_SRC_NOT_PCI; + else + ulData |= INT_CLK_SRC_NOT_PCI; + ulData &= ~(INT_CLK_MULT_ENABLE | INT_CLK_SELECT); + ulData &= ~(CLK_MULT_MODE_SELECT | CLK_MULT_MODE_SELECT_2); + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + if (DSP36MHZ == speed) + { + ulData = PCIRead (devc, PCI_USER_CONFIG); + ulData |= IN_CLK_12MHZ_SELECT; + PCIWrite (devc, PCI_USER_CONFIG, ulData); + + for (mode = 0; mode < 4; mode++) + { + ulData &= ~INT_CLK_MULT_ENABLE; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~CLK_MULT_MODE_SELECT; + ulData |= mode << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData |= INT_CLK_MULT_ENABLE; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + bModeValue[mode] = + bGray_Code[HWMGR_ReadDataWord (devc, CLK_MULT_DATA_PORT) >> 5 + & 0x1F]; + } + ulData |= CLK_MULT_MODE_SELECT_2; + for (mode = 0; mode < 4; mode++) + { + ulData &= ~INT_CLK_MULT_ENABLE; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData &= ~CLK_MULT_MODE_SELECT; + ulData |= mode << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData |= INT_CLK_MULT_ENABLE; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + READ_PORT_UCHAR (devc->osdev, 0x80); + bModeValue[mode + 4] = + bGray_Code[HWMGR_ReadDataWord (devc, CLK_MULT_DATA_PORT) >> 5 + & 0x1F]; + } + bDelta = Abs (bModeValue[0] - 0x10); + choice = 0; + for (mode = 1; mode < 8; mode++) + { + if (bDelta > Abs (bModeValue[mode] - 0x10)) + { + bDelta = Abs (bModeValue[mode] - 0x10); + choice = mode; + } + } + +#if 0 + _Debug_Printf_Service ("mode:%d\n", choice); +#endif + ulData &= ~(INT_CLK_MULT_ENABLE | CLK_MULT_MODE_SELECT | + CLK_MULT_MODE_SELECT_2); + if (choice > 3) + { + ulData |= CLK_MULT_MODE_SELECT_2; + choice -= 4; + } + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData |= choice << CLK_MULT_MODE_SHIFT; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + ulData |= INT_CLK_MULT_ENABLE; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + } + + bData = HWMGR_ReadDataByte (devc, ASSP_CONTROL_A); + bData &= ~(DSP_CLK_36MHZ_SELECT | ASSP_CLK_49MHZ_SELECT); + bData |= ASSP_0_WS_ENABLE; + switch (speed) + { + case DSP36MHZ: + bData |= DSP_CLK_36MHZ_SELECT; + break; + case DSP49MHZ: + bData |= ASSP_CLK_49MHZ_SELECT; + break; + } + HWMGR_WriteDataByte (devc, ASSP_CONTROL_A, bData); + + HWMGR_WriteDataByte (devc, ASSP_CONTROL_B, RUN_ASSP); +} /* HWMGR_SetM3ClockSpeed */ + + +BOOLEAN +HWMGR_InitKernel (allegro_devc * devc) +{ + ULONG ulData; + + ulData = PCIRead (devc, PCI_ALLEGRO_CONFIG); + ulData &= REDUCED_DEBOUNCE; + + if (gbHwVolEnabled) + { + ulData |= HV_CTRL_ENABLE; + + if (bHwVolCtrlMode == -1) + { + bHwVolCtrlMode = 0; + if (bChipType < M3_1998) + bHwVolCtrlMode = 1; + } + + if (PCIRead (devc, 0x2c) == NEC_VENDOR_ID3) + { + bHwVolCtrlMode |= (0x80 | 0x40); + } + + if (bHwVolCtrlMode & 0x80) + { + bHwVolCtrlMode &= ~0x80; + ulData |= REDUCED_DEBOUNCE; + } + + if (bHwVolCtrlMode & 0x40) + { + bHwVolCtrlMode &= ~0x40; + PCIWrite (devc, PCI_USER_CONFIG, + PCIRead (devc, PCI_USER_CONFIG) | HV_CTRL_TEST); + } + + dprintf1 (("bHwVolCtrlMode=%x", bHwVolCtrlMode)); + + /* default 53/54 pin */ + switch (bHwVolCtrlMode) + { + + /* 44/45 pin */ + case 0x01: + ulData |= HV_BUTTON_FROM_GD; + break; + +#if 0 + /* M3E */ + case 0x02: + break; + /* M3E */ + case 0x03: + break; + /* M3E */ + case 0x04: + break; +#endif + } + } + + ulData |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; + PCIWrite (devc, PCI_ALLEGRO_CONFIG, ulData); + + ulData = PCIRead (devc, PCI_USER_CONFIG); + ulData |= MIDI_1_ENABLE; + PCIWrite (devc, PCI_USER_CONFIG, ulData); + + if (bChipType >= M3_1998) + HWMGR_SetM3ClockSpeed (devc, DSP49MHZ); + else + /* new Allegro board only works with external 49 Mhz clock */ + HWMGR_SetClockSpeed (devc, DSP49MHZ); + /*ulDSPConnectIn = KCONNECT_ADC1; */ + + /* initialize the DSP kernel */ + if (kInitKernel (devc, &gphwi, 0x1978, 0x10, devc->base, 0) != + KRETURN_SUCCESS) + return FALSE; + +#ifdef later + InitModem (); +#endif + +#ifdef FIXED_MODEM + { + extern DWORD gdwESModem; + extern DWORD DisableModemClient (VOID); + if (gdwESModem) + { + if (kOpenInstance + (gphwi, CLIENT_MODEM, 0, 0x180 * 2, + &pClient_Modem) != KRETURN_SUCCESS) + return FALSE; + DisableModemClient (); + } + } +#endif + + return TRUE; +} /* HWMGR_InitKernel */ + +/* -------------------------------------------------------------------------- */ + +void +HWMGR_InitSystem (allegro_devc * devc) +{ + WORD wData; + DWORD dwVal; + +#if 0 /* this cause zip sound for Compaq. Code here is for problems for older */ + /* allegro chip, new one does not need this any more. */ + /* prevent AC-link deadlocking */ + HWMGR_WriteDataWord (devc, HOST_INT_CTRL, SOFTWARE_RESET_ENABLE); + KeStallExecutionProcessor (5); + HWMGR_WriteDataWord (devc, HOST_INT_CTRL, 0x0); +#endif + + HWMGR_InitKernel (devc); + + if (bEnableDockDetect) + { + wDockedMask = bDockingDetectGPIPort & 0x0F; + wDockedValue = (bDockingDetectGPIPort >> 4 & 0x0F) << wDockedMask; + wDockedMask = 1 << wDockedMask; + gwDockVal = + (HWMGR_ReadDataWord (devc, GPIO_DATA) & wDockedMask) == wDockedValue; + } + else + { + wDockedMask = wDockedValue = 0; + } + + /* force to set correct codec */ + fRemoteCodec = 0xFF; + + HWMGR_ResetCodec (devc); + + /* allegro codec proble from cold boot so one more resetcodec */ + HWMGR_ResetCodec (devc); + + if (CODEC_TYPE_ESS == bCodec) + { + + /* power down DAC to resynchronize after AC-link change */ + HWMGR_WriteCodecData (devc, AC97_POWER_DOWN_CTRL, AC97_PR1); + KeStallExecutionProcessor (1); + } + + /* codec not reset every time */ + HWMGR_WriteCodecData (devc, AC97_POWER_DOWN_CTRL, 0); + HWMGR_EnableExternalAmp (devc, TRUE); + if (gwDockVal) + { + wData = HWMGR_ReadDataWord (devc, RING_BUS_CTRL_B); + wData |= SECOND_AC_ENABLE; + HWMGR_WriteDataWord (devc, RING_BUS_CTRL_B, wData); + } + + HWMGR_ReadCodecData (devc, AC97_GENERAL_PURPOSE, &wData); + if (bMonoOutputSelect) + { + wData |= 0x300; + + HWMGR_WriteCodecData (devc, AC97_MASTER_MONO_VOL, gwDefaultMonoOutVol); + KeStallExecutionProcessor (100); + HWMGR_WriteCodecData (devc, AC97_MASTER_MONO_VOL, gwDefaultMonoOutVol); + } + else + wData &= ~0x300; + HWMGR_WriteCodecData (devc, AC97_GENERAL_PURPOSE, wData); + + /* fix DAC volume at 0x0808 */ + HWMGR_WriteCodecData (devc, AC97_MASTER_VOL, 0x0404); + HWMGR_WriteCodecData (devc, AC97_PCM_OUT_VOL, 0x0404); + + /* Mute the ADC */ + if (!g4Speaker) + HWMGR_WriteCodecData (devc, AC97_RECORD_GAIN, 0x8000); + + gwDSPConnectIn = KCONNECT_ADC1; + + /* + * Undock it first + */ + dwVal = HW_INIT_SET_ACTIVE_ACINTF; + dwVal <<= 16; + HwSetSystemParameter (devc, dwVal); + + /* + * Setup active I/F + */ + dwVal = HW_INIT_SET_ACTIVE_ACINTF; + dwVal <<= 16; + + HwSetSystemParameter (devc, dwVal); +} /* HWMGR_InitSystem */ + + +void +HwRelease (allegro_devc * devc) +{ +#ifdef later + CloseModem (); +#endif + + kTermKernel (devc, gphwi, devc->base); + + HWMGR_EnableExternalAmp (devc, FALSE); + + /* MUTE THE DAMN THING FIRST */ + WriteLego (devc, 0x02, 0x3F3F); /* LOUT1 Master Attenuation (-1.5dB steps: 0000 = 0dB, 3F3F = -94dB, ) */ + + WriteLego (devc, 0x04, 0x9F1F); /* Headphone */ + WriteLego (devc, 0x06, 0x9F1F); /* MonoOut */ + WriteLego (devc, 0x12, 0x9F1F); /* CD to Mixer Level (80=mute; 00=+12.0dB, 08=0.0dB, 0F = -33dB) */ + WriteLego (devc, 0x16, 0x9F1F); /* AUX to Mixer Level (80=mute; 00=+12.0dB, 08=0.0dB, 0F = -33dB) */ + WriteLego (devc, 0x0E, 0x9F1F); /* Mic to Mixer Level (80=mute; 00=+12.0dB, 08=0.0dB, 0F = -33dB) */ + WriteLego (devc, 0x18, 0x9F1F); /* DAC to Mixer Level (80=mute; 00=+12.0dB, 08=0.0dB, 0F = -33dB) */ + WriteLego (devc, 0x10, 0x9F1F); /* Line in to Mixer Level (80=mute; 00=+12.0dB, 08=0.0dB, 0F = -33dB) */ + WriteLego (devc, 0x1A, 0); /* Rec Gain */ + WriteLego (devc, 0x1C, 0x8F0F); /* Rec Gain */ +} |