summaryrefslogtreecommitdiff
path: root/xc/programs/Xserver/hw/xfree86/accel/p9000
diff options
context:
space:
mode:
authorkaleb <empty>1995-01-26 15:21:11 +0000
committerkaleb <empty>1995-01-26 15:21:11 +0000
commitd3e4486f59d44f06fbac9dc111f1fafd6f9a0d89 (patch)
treeb183f6f5e73e48bb394ba56aa556d89166b2e851 /xc/programs/Xserver/hw/xfree86/accel/p9000
parent60adac2a4cdaee5c8d1dc598aea13f456ca21fd6 (diff)
Initial revision
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86/accel/p9000')
-rw-r--r--xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Acal.c245
-rw-r--r--xc/programs/Xserver/hw/xfree86/accel/p9000/I2061Aset.c161
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
+ }
+}
+
+
+
+
+
+
+
+