diff --git a/glide3x/h5/minihwc/dos_mode.c b/glide3x/h5/minihwc/dos_mode.c index aaf3358..6c149cb 100644 --- a/glide3x/h5/minihwc/dos_mode.c +++ b/glide3x/h5/minihwc/dos_mode.c @@ -591,6 +591,12 @@ void hwcSetSLIAAMode(hwcBoardInfo *bInfo, /* Enable AA and/or SLI */ if(sliEnable || aaEnable) { + + /* v56k has an external clock! */ + if (bInfo->pciInfo.realNumChips == 4) { + extern unsigned long gpio_6k_clock(hwcBoardInfo *bInfo); + gpio_6k_clock(bInfo); + } /* First, init all chips */ for(chipNum = 1; chipNum < numChips; chipNum++) { diff --git a/glide3x/h5/minihwc/gpio.c b/glide3x/h5/minihwc/gpio.c new file mode 100644 index 0000000..16eb225 --- /dev/null +++ b/glide3x/h5/minihwc/gpio.c @@ -0,0 +1,451 @@ +#include /*usleep*/ + +#include "minihwc.h" +#include "h3cinitdd.h" + + + +#define USEC (1000) +#define DTIME (5*USEC) +#define MSEC (1000000) +#define D60HZ (166*MSEC) +#define DELAY(x) usleep(x) +#define CLOCK_STRETCH (1000) +#define NUM_RETRY (5) + +#define BUILD_BYTE(data, mask, position) ((unsigned char)((data & mask)<Data.dwBus = pGPIOMask->Clk.dwBus = pGPIOMask->Strobe.dwBus = dwBus; + pGPIOMask->Data.dwDevFunc = pGPIOMask->Clk.dwDevFunc = pGPIOMask->Strobe.dwDevFunc = dwDevFunc; + + pGPIOMask->Data.RN = 0xC4; + pGPIOMask->Data.dInMask = 0x0100; + pGPIOMask->Data.dInShift = 0x08; + pGPIOMask->Data.dOutMask = 0x0400; + pGPIOMask->Data.dOutShift = 0x0A; + + pGPIOMask->Clk.RN = 0xC4; + pGPIOMask->Clk.dInMask = 0x010000; + pGPIOMask->Clk.dInShift = 0x10; + pGPIOMask->Clk.dOutMask = 0x040000; + pGPIOMask->Clk.dOutShift = 0x12; + + pGPIOMask->Strobe.RN = 0xC4; + pGPIOMask->Strobe.dInMask = 0x1000; + pGPIOMask->Strobe.dInShift = 0x0C; + pGPIOMask->Strobe.dOutMask = 0x4000; + pGPIOMask->Strobe.dOutShift = 0x0E; + + pGPIOMask->HiVoltage.RN = 0xC4; + pGPIOMask->HiVoltage.dInMask = 0x100000; + pGPIOMask->HiVoltage.dInShift = 0x14; + pGPIOMask->HiVoltage.dOutMask = 0x400000; + pGPIOMask->HiVoltage.dOutShift = 0x16; + + /* Enable all GPIO as Output */ + dwData = pci_read_cfg(dwBus, dwDevFunc, 0xC4); + dwData &= 0xFF0000FF; + /* C7C6C5C4 */ + dwData |= 0x00222200; + pci_write_cfg(dwBus, dwDevFunc, 0xC4, dwData); + } + } else { + dwData = pci_read_cfg(pGPIOMask->Data.dwBus, pGPIOMask->Data.dwDevFunc, 0xC4); + dwData &= 0xFF0000FF; + /* C7C6C5C4 */ + dwData |= 0x00222200; + pci_write_cfg(pGPIOMask->Data.dwBus, pGPIOMask->Data.dwDevFunc, 0xC4, dwData); + } + + return isGPIOInit; +} + + + +/* Desc: read a dword + * + * In : + * Out : + * + * Note: dword + */ +unsigned long gpio_get (PCI_BIT *pPCI_BIT) +{ + return pci_read_cfg(pPCI_BIT->dwBus, pPCI_BIT->dwDevFunc, pPCI_BIT->RN); +} + + + +/* Desc: read a bit + * + * In : + * Out : bit + * + * Note: + */ +unsigned long gpio_get_bit (PCI_BIT *pPCI_BIT) +{ + unsigned long bData; + bData = pci_read_cfg(pPCI_BIT->dwBus, pPCI_BIT->dwDevFunc, pPCI_BIT->RN); + return (bData & pPCI_BIT->dInMask) >> pPCI_BIT->dInShift; +} + + + +/* Desc: write a bit + * + * In : + * Out : + * + * Note: + */ +unsigned long gpio_set_bit (PCI_BIT *pPCI_BIT, unsigned long dwValue) +{ + unsigned long dwReg; + + dwReg = gpio_get(pPCI_BIT); + dwReg = dwReg & ~pPCI_BIT->dOutMask; + dwReg |= ((dwValue & 0x01) << pPCI_BIT->dOutShift); + + return pci_write_cfg(pPCI_BIT->dwBus, pPCI_BIT->dwDevFunc, pPCI_BIT->RN, dwReg); +} + + + +/* Desc: read the clock + * + * In : + * Out : + * + * Note: + */ +int gpio_read_scl (GPIOMASK *pGPIOMask) +{ + return gpio_get_bit(&pGPIOMask->Clk); +} + + + +/* Desc: set the Clock to bit + * + * In : + * Out : + * + * Note: + */ +void gpio_scl (GPIOMASK *pGPIOMask, unsigned long bit) +{ + int nCount = 0; + + DELAY(DTIME); + gpio_set_bit(&pGPIOMask->Clk, bit); + DELAY(DTIME); + + if (bit) { + while (!gpio_read_scl(pGPIOMask) && (nCount++ < CLOCK_STRETCH)) { + DELAY(DTIME); + } + + if (nCount++ >= CLOCK_STRETCH) { + /*fprintf(stderr, "Slave did not respond %s %d\n", __FILE__, __LINE__);*/ + } + } +} + + + +/* Desc: set the Data to bit. + * + * In : + * Out : + * + * Note: + */ +void gpio_sda (GPIOMASK *pGPIOMask, unsigned long bit) +{ + DELAY(DTIME); + bit = bit >> 7; + gpio_set_bit(&pGPIOMask->Data, bit); + DELAY(DTIME); +} + + + +/* Desc: send the byte data + * + * In : + * Out : + * + * Note: + */ +int gpio_send_byte (GPIOMASK *pGPIOMask, + unsigned char b1, + unsigned char b2, + unsigned char b3) +{ + int i; + int nReturn = 0; + + for (i = 0; i < 8; i++) { + gpio_sda(pGPIOMask, (b1 << i) & 0x80); + gpio_scl(pGPIOMask, 1); + if (gpio_read_scl(pGPIOMask) == 0) { + /*fprintf(stderr, "nc\n");*/ + } + gpio_scl(pGPIOMask, 0); + } + + for (i = 0; i < 8; i++) { + gpio_sda(pGPIOMask, (b2 << i) & 0x80); + gpio_scl(pGPIOMask, 1); + if (gpio_read_scl(pGPIOMask) == 0) { + /*fprintf(stderr, "nc\n");*/ + } + gpio_scl(pGPIOMask, 0); + } + + for (i = 0; i < 8; i++) { + gpio_sda(pGPIOMask, (b3 << i) & 0x80); + gpio_scl(pGPIOMask, 1); + if (gpio_read_scl(pGPIOMask) == 0) { + /*fprintf(stderr, "nc\n");*/ + } + gpio_scl(pGPIOMask, 0); + } + + /* Strobe to make it happen */ + DELAY(DTIME); + gpio_set_bit(&pGPIOMask->Strobe, 1); + DELAY(DTIME); + + DELAY(DTIME); + gpio_set_bit(&pGPIOMask->Strobe, 0); + DELAY(DTIME); + + return nReturn; +} + + + +/* Desc: build and send clock + * + * In : + * Out : + * + * Note: + */ +unsigned long gpio_output_clock (hwcBoardInfo *bInfo, + unsigned long c, + unsigned long ttl, + unsigned long f, + unsigned long s, + unsigned long v, + unsigned long r) +{ + static GPIOMASK GpioMask; + + unsigned char b1, b2, b3; + + b1 = BUILD_BYTE(c, 3, 6); + b1 |= BUILD_BYTE(ttl, 1, 5); + b1 |= BUILD_BYTE(f, 3, 3); + b1 |= BUILD_BYTE(s, 7, 0); + + b2 = (unsigned char)((v & 0x1Fe) >> 1); + + b3 = BUILD_BYTE(v, 1, 7); + b3 |= BUILD_BYTE(r, 0x7F, 0); + + if (gpio_init(&GpioMask, /*pDev->dwBus*/2/*666*/)) + gpio_send_byte(&GpioMask, b1, b2, b3); + + return 0; +} + + + +/* Desc: + * + * In : + * Out : 0 for failure + * + * Note: + */ +unsigned long gpio_6k_clock (hwcBoardInfo *bInfo) +{ + static unsigned long OD[] = {2, 3, 4, 5, 6, 7, 8, 10}; + static unsigned long S2S1S0[] = {15, 15, 1, 6, 3, 4, 7, 5, 2, 15, 0}; + + double d_clk1; + double clk1; + double d_diff; + double d_partial; + unsigned long rdw; + unsigned long vdw; + unsigned long od; + unsigned long i; + unsigned long b_rdw; + unsigned long b_vdw; + unsigned long b_od; + unsigned long b_i; + unsigned long bFound; + unsigned long ic; + unsigned long pixelclock; + unsigned long n; + unsigned long m; + unsigned long k; + unsigned long kpow; + + /* Get the Clock */ + FxU32 regBase = bInfo->regInfo.ioPortBase; + pixelclock = IGET32(pllCtrl0); + n = ((pixelclock & 0xFF00) >> 8)+2; + m = ((pixelclock & 0xFC) >> 2)+2; + k = pixelclock & 0x03; + + kpow = 1; + for (i = 0; i < k; i++) { + kpow <<= 1; + } + + /* This should work to 4 GigaHertz */ + ic = 14318180 * n / m / kpow; + ic >>= 2; + + d_diff = MHz(500.0); + i = 0; + bFound = 0; + for (i = 0; i < sizeof(OD)/sizeof(unsigned long); i++) { + od = OD[i]; + for (rdw = 1; rdw < 128; rdw++) { + for (vdw = 4; vdw < 512; vdw++) { + clk1 = 14318180.0*2.0*((double)vdw+8.0)/(((double)rdw+2.0)*(double)od); + if (ABS(clk1, (double)ic) < d_diff) { + /* Some constraints on vdw & rdw + * 55 Mhz < 14318180 * 2* (vdw+8)/(rdw + 2) < 400 Mhz + */ + d_partial = 14318180.0*2.0*((double)vdw+8.0)/((double)rdw+2.0); + if ((d_partial > MHz(55)) && (d_partial < MHz(400))) { + /* Another constraints + * 200 kHz < 14318180/(rdw+2) + */ + if (14318180/(rdw+2) > kHz(200)) { + d_diff = ABS(clk1, (double)ic); + bFound = 1; + b_rdw = rdw; + b_vdw = vdw; + b_od = od; + b_i = i; + d_clk1 = clk1; + } + } + } + } + } + } + + if (bFound) { + gpio_output_clock(bInfo, 0x0, 0x1, 0x0, S2S1S0[b_od], b_vdw, b_rdw); + return ic; + } else { + return 0; + } +}