diff options
author | kaleb <empty> | 1995-01-26 15:21:11 +0000 |
---|---|---|
committer | kaleb <empty> | 1995-01-26 15:21:11 +0000 |
commit | d3e4486f59d44f06fbac9dc111f1fafd6f9a0d89 (patch) | |
tree | b183f6f5e73e48bb394ba56aa556d89166b2e851 /xc/programs/Xserver/hw/xfree86/accel/p9000 | |
parent | 60adac2a4cdaee5c8d1dc598aea13f456ca21fd6 (diff) |
Initial revision
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/accel/p9000')
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c | 245 | ||||
-rw-r--r-- | xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c | 161 |
2 files changed, 406 insertions, 0 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c b/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c new file mode 100644 index 000000000..bf4cde495 --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c @@ -0,0 +1,245 @@ +/* $XConsortium: $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c,v 3.1 1994/09/07 15:50:41 dawes Exp $ */ +/* Id: ICD2061Acal.c,v 4.0 1994/05/28 01:24:17 nygren Exp */ +/* Based on the number 9 Inc code */ +/* Copyright (c) 1992, Number Nine Computer Corp. All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Number Nine Computer Corp not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Number Nine Computer Corp + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * NUMBER NINE COMPUTER CORP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NUMBER NINE COMPUTER CORP BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Modifications - Copyright (c) 1994, Harry Langenbacher,All Rights Reserved. + * HARRY LANGENBACHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL HARRY LANGENBACHER BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation. Harry Langenbacher + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#include "X.h" +#include "input.h" +#include "xf86_OSlib.h" +#include "xf86.h" +#include "ICD2061A.h" + +#undef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#define MAX_NUMERATOR 130 +#define MAX_DENOMINATOR MIN(129, CRYSTAL_FREQUENCY / 400000) +#define MIN_DENOMINATOR MAX(3, CRYSTAL_FREQUENCY / 2000000) + +/* Index register frequency ranges for ICD2061A chip */ +/* "The Index Field is used to preset the VCO to an appropriate range." pg. 13 */ +static long vclk_range[14] = + { + 51000000, + 53200000, + 58500000, + 60700000, + 64400000, + 66800000, + 73500000, + 75600000, + 80900000, + 83200000, + 91500000, + 100000000, + 120000000, + 135000000 /* BE WARNED THIS COULD BE VERY VERY BAD (i.e. , I'm guessing)!!!!!!! */ + } ; + +unsigned long ICD2061ACalcClock + ( long frequency , int chipreg ) /* frequency in Hz */ + /* chipreg - select one of 3 registers in icd2061a to be selected + to hold new frequency parameters */ + { + int Q_Divider ; + int P_Divider ; + int Mux ; /* divider after vco */ + + register int index; + unsigned long temp; + int Best_Qdivider, Best_Pdivider; + long min_diff; + long diff; + + min_diff = 0xFFFFFFF; + Best_Pdivider = 1; + Best_Qdivider = 1; +#ifdef DEBUG + ErrorF ( "Buiding clock control word for freq=%d, chipreg=%d\n" , + frequency , chipreg ) ; +#endif + /* Calculate 17 bit ( 7 + 3 + 7 ) frequency control field */ + + /* find what post VCO divider we need */ + Mux = 0; + if (frequency < MIN_VCO_FREQUENCY) + Mux = 1; + if (frequency < MIN_VCO_FREQUENCY / 2) + Mux = 2; + if (frequency < MIN_VCO_FREQUENCY / 4) + Mux = 3; /* boy, this is a really low frequency (50Mhz/4?)*/ + + frequency <<= Mux ; /* make frequency = the VCO frequency we have to get */ + for (P_Divider = 4; P_Divider <= MAX_NUMERATOR; P_Divider++) + { + index = CRYSTAL_FREQUENCY / (frequency / P_Divider); + if (index > MAX_DENOMINATOR) + index = MAX_DENOMINATOR; + if (index < MIN_DENOMINATOR) + index = MIN_DENOMINATOR; + for (Q_Divider = index - 3; Q_Divider < index + 4; Q_Divider++) + if (Q_Divider >= MIN_DENOMINATOR && Q_Divider <= MAX_DENOMINATOR) + { + diff = (CRYSTAL_FREQUENCY / Q_Divider) * P_Divider - frequency; + if (diff < 0) + diff = -diff; + if ( Best_Qdivider * ICD2061AGCD(Q_Divider, P_Divider) / + ICD2061AGCD(Best_Qdivider, Best_Pdivider) == Q_Divider + && + Best_Pdivider * ICD2061AGCD(Q_Divider, P_Divider) / + ICD2061AGCD(Best_Qdivider, Best_Pdivider) == P_Divider ) + { + if (diff > min_diff) + diff = min_diff; + } + if (diff <= min_diff) + { + min_diff = diff; + Best_Qdivider = Q_Divider; + Best_Pdivider = P_Divider; + } + } + } + Q_Divider = Best_Qdivider; + P_Divider = Best_Pdivider; + + /* Calculate the resultant VCO frequency */ + temp = CalcVCOfreq ( Q_Divider , P_Divider ) ; + + /* look up the index field value appropriate for this vco freq */ + index = 0 ; + while ( ( vclk_range [ index ] < temp ) && ( index < 14 ) ) + index ++ ; + + if ( index == 14 ) /* vco freq too high */ + { + ErrorF ("\a\aProgram error - vco freq too high !\n" ) ; + } + + /* Pack the control word for the frequency snthesizer , + packed into bits 0-23, not 1-24 like before */ + + temp = ( (long) chipreg << 21 ) | + ( (long) index << 17 ) | + ( (long) ( P_Divider - 3 ) << 10 ) | + ( (long) Mux << 7 ) | + ( Q_Divider - 2 ) ; + +#ifdef DEBUG + ErrorF ("Clock Control Word is 0x%06X\n" , temp ) ; +#endif + + return temp; +} + +/* Number theoretic function - GCD (Greatest Common Divisor) */ +int ICD2061AGCD ( int number1 , int number2 ) + { + register int remainder = number1 % number2 ; + while ( remainder ) + { + number1 = number2 ; + number2 = remainder ; + remainder = number1 % number2 ; + } + return number2 ; + } + +unsigned int ICD2061AGetClock ( unsigned long control_word ) + /* value now in bits 0-23 ( not 1-24 like before ) */ + { + unsigned int Q_Divider ; + unsigned int Feedback_Divider_P ; + unsigned int Post_VCO_Divider_M ; + unsigned int FinalFreq ; + unsigned int VCOFreq ; + unsigned int Index ; + unsigned int select ; + + /* Unpack the clock value */ + select = ( control_word >> 21 ) & 7 ; + Index = ( ( control_word >> 17 ) & 0x0F) ; /* P */ + Feedback_Divider_P = ( ( control_word >> 10 ) & 0x7F) + 3 ; /* P */ + Post_VCO_Divider_M = ( ( control_word >> 7 ) & 0x07) ; /* M */ + Q_Divider = ( ( control_word ) & 0x7F) + 2 ; /* Q */ + + /* f(VCO) = Prescale * f(ref) * P / Q */ + /* where Prescale is determined by a bit in the control reg, and will + be 2 or 4 , default 2 */ + /* then the VCO output is divided by 2^^M */ + + VCOFreq = CalcVCOfreq ( Q_Divider , Feedback_Divider_P ) ; + FinalFreq = VCOFreq >> Post_VCO_Divider_M ; + /* (2*f(ref)*P/Q)/2^^Post_VCO_Divider_M */ + +#ifdef DEBUG + ErrorF ("\ + register select=%d\n\ + Index Field =%d=0x%X\n\ + Feedback_Divider_P=%d=0x%X\n\ + Post_VCO_Divider_M=%d\n\ + Q_Divider=%d=0x%X\n\ + VCOFreq=%d Hz, FinalFreq=%d Hz\n" , + select , Index , Index , Feedback_Divider_P , Feedback_Divider_P , + Post_VCO_Divider_M , Q_Divider , Q_Divider , + VCOFreq , FinalFreq ) ; +#endif + + return FinalFreq ; + } + +unsigned long CalcVCOfreq + ( unsigned int Q_Divider , unsigned int Feedback_Divider_P ) + { + unsigned long VCO_Freq ; + + /* f(VCO) = Prescale * f(ref) * P / Q */ + /* where Prescale is determined by a bit in the control reg, and will + be 2 or 4 , default 2 */ + /* assume a (standard?) 14.318180 Mhz Crystal */ + VCO_Freq = ( 2 * 14318180 * Feedback_Divider_P ) / Q_Divider ; + return VCO_Freq ; + } + + + + + diff --git a/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c b/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c new file mode 100644 index 000000000..ae43bf9ac --- /dev/null +++ b/xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c @@ -0,0 +1,161 @@ +/* $XConsortium: $ */ +/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c,v 3.1 1994/09/07 15:50:42 dawes Exp $ */ +/* Id: ICD2061Aset.c,v 4.0 1994/05/28 01:24:17 nygren Exp */ +/* Based on the number 9 Inc code */ +/* Copyright (c) 1992, Number Nine Computer Corp. All Rights Reserved. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Number Nine Computer Corp not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. Number Nine Computer Corp + * makes no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * NUMBER NINE COMPUTER CORP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL NUMBER NINE COMPUTER CORP BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Modifications - Copyright (c) 1994, Harry Langenbacher,All Rights Reserved. + * HARRY LANGENBACHER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS + * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, + * IN NO EVENT SHALL HARRY LANGENBACHER BE LIABLE FOR ANY SPECIAL, + * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notices appear in all copies and that both that + * copyright notices and this permission notice appear in supporting + * documentation. Harry Langenbacher makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + */ + +#include "X.h" +#include "input.h" +#include "xf86_OSlib.h" +#include "xf86.h" +#include "ICD2061A.h" +#include "p9000reg.h" + +void ICD2061ASetClock ( unsigned long control_word ) + /* value now in bits 0-23 ( not 1-24 like #9 ) */ + { + register int index; + int savemisc ; + int select ; + + select = (control_word >> 21) & 7; /* extract register address for icd2061 */ + /* if it's not vid clk we dont need it here */ + /* 000 reg0 video clk reg 0 */ + /* 001 reg1 video clk reg 1 */ + /* 010 reg2 video clk reg 2 */ + /* 011 mreg memory clk reg */ + /* 100 pwrdwn divisor for power down mode */ + /* 110 cntl reg control reg */ + /* 111 not used */ + /* 101 reserved */ + if ( ( select == 7 ) || ( select == 5 ) ) + ErrorF("\aERROR illegal icd2061 register select=%d\n" , select ) ; + + + /* Shut off screen */ /* why bother ?? */ + /* If you want to turn off the screen it might make more sense to turn it off + for a few ms AFTER shifting out the number and setting MISCOUT - + because the icd2061 output will not change 'till ~2ms after you + quit wiggling the sel/clk/data inputs */ + + /* Set up the bits and regs for sending serial data to the icd2061 */ +#define CLOCK(xx) outb((short)MISC_OUT_REG, (char)(savemisc & 0xF3)| (xx) ) +#define C_DATA 8 +#define C_CLK 4 +#define C_BOTH 0xC +#define C_NONE 0 + + savemisc = inb ( (short) MISC_IN_REG ) ; /* read MISCOUT reg */ +#ifdef DEBUG + ErrorF("ICD2061ASetClock: Debug info: savemisc=MISC_IN_REG=0x%X\n" , (int) savemisc ) ; +#endif + + /* refer to ICD2061A data sheet, and Power 9000 EISA App. Note, pg 16 */ + /* Program the IC Designs ICD2061A frequency generator */ + /* the initial Unlock sequence consists of at least 5 low to high transitions + of CLK with DATA high, */ + + for ( index = 0 ; index < 5 ; index ++ ) + { + CLOCK(C_DATA) ; /* data held high */ + CLOCK(C_BOTH) ; /* clock goes hi while data stays hi */ + } + /* followed immediately by a single low to high transition of CLK with DATA + low */ + + CLOCK(C_NONE); /* let them both go low */ + CLOCK(C_CLK); /* clock goes high */ + CLOCK(C_NONE); /* start bit = 0 */ + CLOCK(C_CLK); /* clock the start bit */ + + /* shift in the 24 bit clock control word */ + for ( index = 1 ; index < 0x1000000 ; index <<= 1 ) + { /* march a 1-bit mask across the clock control word */ + + /* Clock in the next magic bit - manchester style ! */ + if (control_word & index ) + { /* clock in a one */ + CLOCK(C_CLK); /* with clock still high, data = ! bit */ + CLOCK(C_NONE); /* lower clock, dont change data */ + CLOCK(C_DATA); /* data = bit */ + CLOCK(C_BOTH); /* clock the bit */ + } + else + { /* clock in a zero */ + CLOCK(C_BOTH); /* with clock still high, data = ! bit */ + CLOCK(C_DATA); /* lower clock, dont change data */ + CLOCK(C_NONE); /* data = bit */ + CLOCK(C_CLK); /* clock the bit */ + } + } + + /* following the entry of the last data bit, a stop bit ... is issued */ + /* by bringing DATA high and toggling CLK high-to-low and low-to-high */ + CLOCK ( C_BOTH ) ; /* clock still high, bring data high */ + CLOCK ( C_DATA ) ; /* toggle clock low */ + CLOCK ( C_BOTH ) ; /* toggle clock hi */ + + /* Select the CLOCK in the frequency synthesizer */ + /* if we set anything but video clocks (regs 0-2) then restore clock */ + /* select bits, otherwise set new select video freq. reg. */ + + if ( ( select >= 0 ) && ( select <= 2 ) ) /* if it's a vclk reg */ + { + CLOCK ( select << 2 ) ; /* this will set SEL1 (bit 3) and SEL0 (bit 2) */ +#ifdef DEBUG + ErrorF("ICD2061ASetClock: Debug info: savemisc=MISC_IN_REG=0x%X\n" , + (int) ((savemisc & 0xF3)| (select << 2) ) ) ; +#endif + } + else + { + outb ( (short) MISC_OUT_REG , (char) savemisc ) ; /* not a vclk reg restore old select bits so that old vclk is selected */ +#ifdef DEBUG + ErrorF("ICD2061ASetClock: Debug info: MISC_OUT_REG set to=0x%X\n" , + (int) savemisc ) ; +#endif + } +} + + + + + + + + |