150806d53Smrg/* 250806d53Smrg * Copyright 1996-2000 by Robin Cutshaw <robin@XFree86.Org> 350806d53Smrg * 450806d53Smrg * Permission to use, copy, modify, distribute, and sell this software and its 550806d53Smrg * documentation for any purpose is hereby granted without fee, provided that 650806d53Smrg * the above copyright notice appear in all copies and that both that 750806d53Smrg * copyright notice and this permission notice appear in supporting 850806d53Smrg * documentation, and that the name of Robin Cutshaw not be used in 950806d53Smrg * advertising or publicity pertaining to distribution of the software without 1050806d53Smrg * specific, written prior permission. Robin Cutshaw makes no representations 1150806d53Smrg * about the suitability of this software for any purpose. It is provided 1250806d53Smrg * "as is" without express or implied warranty. 1350806d53Smrg * 1450806d53Smrg * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1550806d53Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1650806d53Smrg * EVENT SHALL ROBIN CUTSHAW BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1750806d53Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1850806d53Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 1950806d53Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 2050806d53Smrg * PERFORMANCE OF THIS SOFTWARE. 2150806d53Smrg * 2250806d53Smrg */ 2350806d53Smrg 2450806d53Smrg 2550806d53Smrg#ifdef HAVE_CONFIG_H 2650806d53Smrg#include "config.h" 2750806d53Smrg#endif 2850806d53Smrg 2950806d53Smrg#include "xf86.h" 3050806d53Smrg#include "xf86Pci.h" 3150806d53Smrg#include "cursorstr.h" 3250806d53Smrg#include "servermd.h" 3350806d53Smrg 3450806d53Smrg#include "i128.h" 3550806d53Smrg#include "i128reg.h" 3650806d53Smrg#include "IBMRGB.h" 3750806d53Smrg 387965d9acSmrg#include <unistd.h> 3950806d53Smrg 4050806d53Smrgstatic void I128IBMShowCursor(ScrnInfoPtr pScrn); 4150806d53Smrgstatic void I128IBMHideCursor(ScrnInfoPtr pScrn); 4250806d53Smrgstatic void I128IBMSetCursorPosition(ScrnInfoPtr pScrn, int x, int y); 4350806d53Smrgstatic void I128IBMSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg); 4450806d53Smrgstatic void I128IBMLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src); 4550806d53Smrgstatic Bool I128IBMUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs); 4650806d53Smrg 4750806d53Smrg 4850806d53SmrgBool 4950806d53SmrgI128IBMHWCursorInit(ScrnInfoPtr pScrn) 5050806d53Smrg{ 5150806d53Smrg xf86CursorInfoPtr infoPtr; 52a73423d7Smrg ScreenPtr pScreen = xf86ScrnToScreen(pScrn); 5350806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 5450806d53Smrg 5550806d53Smrg if (!pI128->HWCursor) 5650806d53Smrg return FALSE; 5750806d53Smrg 5850806d53Smrg infoPtr = xf86CreateCursorInfoRec(); 5950806d53Smrg if (!infoPtr) return FALSE; 6050806d53Smrg 6150806d53Smrg pI128->CursorInfoRec = infoPtr; 6250806d53Smrg infoPtr->MaxWidth = 64; 6350806d53Smrg infoPtr->MaxHeight = 64; 6450806d53Smrg infoPtr->SetCursorColors = I128IBMSetCursorColors; 6550806d53Smrg infoPtr->SetCursorPosition = I128IBMSetCursorPosition; 6650806d53Smrg infoPtr->LoadCursorImage = I128IBMLoadCursorImage; 6750806d53Smrg infoPtr->HideCursor = I128IBMHideCursor; 6850806d53Smrg infoPtr->ShowCursor = I128IBMShowCursor; 6950806d53Smrg infoPtr->UseHWCursor = I128IBMUseHWCursor; 7050806d53Smrg infoPtr->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 7150806d53Smrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 7250806d53Smrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1; 7350806d53Smrg 74af1a9c97Smrg#if X_BYTE_ORDER == X_BIG_ENDIAN 75af1a9c97Smrg infoPtr->Flags |= HARDWARE_CURSOR_NIBBLE_SWAPPED; 76af1a9c97Smrg#endif 7750806d53Smrg 78af1a9c97Smrg return(xf86InitCursor(pScreen, infoPtr)); 7950806d53Smrg} 8050806d53Smrg 8150806d53Smrg 8250806d53Smrgstatic void 8350806d53SmrgI128IBMShowCursor(ScrnInfoPtr pScrn) 8450806d53Smrg{ 8550806d53Smrg CARD32 tmpl, tmph; 8650806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 8750806d53Smrg 8850806d53Smrg /* Enable cursor - X11 mode */ 8950806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 9050806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 9150806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 0; MB; 9250806d53Smrg pI128->mem.rbase_g[IDXH_I] = 0; MB; 9350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs; MB; 9450806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x27; MB; 9550806d53Smrg 9650806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 9750806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 9850806d53Smrg 9950806d53Smrg return; 10050806d53Smrg} 10150806d53Smrg 10250806d53Smrgstatic void 10350806d53SmrgI128IBMHideCursor(ScrnInfoPtr pScrn) 10450806d53Smrg{ 10550806d53Smrg CARD32 tmpl, tmph, tmp1; 10650806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 10750806d53Smrg 10850806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 10950806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 11050806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 0; MB; 11150806d53Smrg pI128->mem.rbase_g[IDXH_I] = 0; MB; 11250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs; MB; 11350806d53Smrg tmp1 = pI128->mem.rbase_g[DATA_I] & 0xFC; 11450806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp1; MB; 11550806d53Smrg 11650806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 11750806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 11850806d53Smrg 11950806d53Smrg return; 12050806d53Smrg} 12150806d53Smrg 12250806d53Smrgstatic void 12350806d53SmrgI128IBMSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 12450806d53Smrg{ 12550806d53Smrg CARD32 tmpl, tmph; 12650806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 12750806d53Smrg 12850806d53Smrg x += 64; 12950806d53Smrg y += 64; 13050806d53Smrg 13150806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 13250806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 13350806d53Smrg 13450806d53Smrg pI128->mem.rbase_g[IDXH_I] = 0; MB; 13550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_hot_x; MB; 13650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x3F; MB; 13750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_hot_y; MB; 13850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x3F; MB; 13950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_xl; MB; 14050806d53Smrg pI128->mem.rbase_g[DATA_I] = x & 0xFF; MB; 14150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_xh; MB; 14250806d53Smrg pI128->mem.rbase_g[DATA_I] = (x >> 8) & 0x0F; MB; 14350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_yl; MB; 14450806d53Smrg pI128->mem.rbase_g[DATA_I] = y & 0xFF; MB; 14550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_yh; MB; 14650806d53Smrg pI128->mem.rbase_g[DATA_I] = (y >> 8) & 0x0F; MB; 14750806d53Smrg 14850806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 14950806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 15050806d53Smrg 15150806d53Smrg return; 15250806d53Smrg} 15350806d53Smrg 15450806d53Smrgstatic void 15550806d53SmrgI128IBMSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 15650806d53Smrg{ 15750806d53Smrg CARD32 tmp; 15850806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 15950806d53Smrg 16050806d53Smrg tmp = pI128->mem.rbase_g[IDXL_I] & 0xFF; 16150806d53Smrg 16250806d53Smrg /* Background color */ 16350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col1_r; MB; 16450806d53Smrg pI128->mem.rbase_g[DATA_I] = (bg & 0x00FF0000) >> 16; MB; 16550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col1_g; MB; 16650806d53Smrg pI128->mem.rbase_g[DATA_I] = (bg & 0x0000FF00) >> 8; MB; 16750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col1_b; MB; 16850806d53Smrg pI128->mem.rbase_g[DATA_I] = (bg & 0x000000FF); MB; 16950806d53Smrg 17050806d53Smrg /* Foreground color */ 17150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col2_r; MB; 17250806d53Smrg pI128->mem.rbase_g[DATA_I] = (fg & 0x00FF0000) >> 16; MB; 17350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col2_g; MB; 17450806d53Smrg pI128->mem.rbase_g[DATA_I] = (fg & 0x0000FF00) >> 8; MB; 17550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_col2_b; MB; 17650806d53Smrg pI128->mem.rbase_g[DATA_I] = (fg & 0x000000FF); MB; 17750806d53Smrg 17850806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmp; MB; 17950806d53Smrg 18050806d53Smrg return; 18150806d53Smrg} 18250806d53Smrg 18350806d53Smrgstatic void 18450806d53SmrgI128IBMLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 18550806d53Smrg{ 18650806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 18750806d53Smrg register int i; 18850806d53Smrg CARD32 tmph, tmpl, tmpc; 18950806d53Smrg 19050806d53Smrg tmpc = pI128->mem.rbase_g[IDXCTL_I] & 0xFF; 19150806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 19250806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 19350806d53Smrg 19450806d53Smrg pI128->BlockCursor = TRUE; 19550806d53Smrg 19650806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 0; MB; 19750806d53Smrg 19850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_hot_x; MB; 19950806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 20050806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_hot_y; MB; 20150806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 20250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_xl; MB; 20350806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xFF; MB; 20450806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_xh; MB; 20550806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x7F; MB; 20650806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_yl; MB; 20750806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xFF; MB; 20850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_yh; MB; 20950806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x7F; MB; 21050806d53Smrg 21150806d53Smrg pI128->mem.rbase_g[IDXH_I] = (IBMRGB_curs_array >> 8) & 0xFF; MB; 21250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_curs_array & 0xFF; MB; 21350806d53Smrg 21450806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 1; /* enable auto-inc */ MB; 21550806d53Smrg 21650806d53Smrg /* 21750806d53Smrg * Output the cursor data. The realize function has put the planes into 21850806d53Smrg * their correct order, so we can just blast this out. 21950806d53Smrg */ 22050806d53Smrg for (i = 0; i < 1024; i++,src++) { 22150806d53Smrg pI128->mem.rbase_g[DATA_I] = (CARD32 )*src; MB; 22250806d53Smrg } 22350806d53Smrg 22450806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = tmpc; MB; 22550806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 22650806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 22750806d53Smrg 22850806d53Smrg pI128->BlockCursor = FALSE; 22950806d53Smrg 23050806d53Smrg return; 23150806d53Smrg} 23250806d53Smrg 23350806d53Smrg 23450806d53Smrgstatic Bool 23550806d53SmrgI128IBMUseHWCursor(ScreenPtr pScrn, CursorPtr pCurs) 23650806d53Smrg{ 23750806d53Smrg if( XF86SCRNINFO(pScrn)->currentMode->Flags & V_DBLSCAN ) 23850806d53Smrg return FALSE; 23950806d53Smrg return TRUE; 24050806d53Smrg} 24150806d53Smrg 24250806d53Smrg 24350806d53SmrgBool I128TIHWCursorInit(ScrnInfoPtr pScrn) { return FALSE; } 24450806d53SmrgBool I128ProgramTi3025(ScrnInfoPtr pScrn, DisplayModePtr mode) { return FALSE; } 24550806d53Smrg 24650806d53SmrgBool 24750806d53SmrgI128ProgramIBMRGB(ScrnInfoPtr pScrn, DisplayModePtr mode) 24850806d53Smrg{ 24950806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 25050806d53Smrg unsigned char tmp2, m, n, df, best_m, best_n, best_df, max_n; 25150806d53Smrg CARD32 tmpl, tmph, tmpc; 25250806d53Smrg long f, vrf, outf, best_diff, best_outf = 0, diff; 25350806d53Smrg long requested_freq; 25450806d53Smrg int freq = mode->SynthClock; 25550806d53Smrg int flags = mode->Flags; 25650806d53Smrg 25750806d53Smrg#define REF_FREQ 25175000 25850806d53Smrg#define MAX_VREF 3380000 25950806d53Smrg/* Actually, MIN_VREF can be as low as 1000000; 26050806d53Smrg * this allows clock speeds down to 17 MHz */ 26150806d53Smrg#define MIN_VREF 1500000 26250806d53Smrg#define MAX_VCO 220000000 26350806d53Smrg#define MIN_VCO 65000000 26450806d53Smrg 26550806d53Smrg if (freq < 25000) { 26650806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 26750806d53Smrg "Specified dot clock (%.3f) too low for IBM RGB52x", 26850806d53Smrg freq / 1000.0); 26950806d53Smrg return(FALSE); 27050806d53Smrg } else if (freq > MAX_VCO) { 27150806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 27250806d53Smrg "Specified dot clock (%.3f) too high for IBM RGB52x", 27350806d53Smrg freq / 1000.0); 27450806d53Smrg return(FALSE); 27550806d53Smrg } 27650806d53Smrg 27750806d53Smrg requested_freq = freq * 1000; 27850806d53Smrg 27950806d53Smrg best_m = best_n = best_df = 0; 28050806d53Smrg best_diff = requested_freq; /* worst case */ 28150806d53Smrg 28250806d53Smrg for (df=0; df<4; df++) { 28350806d53Smrg max_n = REF_FREQ / MIN_VREF; 28450806d53Smrg if (df < 3) 28550806d53Smrg max_n >>= 1; 28650806d53Smrg for (n=2; n<max_n; n++) 28750806d53Smrg for (m=65; m<=128; m++) { 28850806d53Smrg vrf = REF_FREQ / n; 28950806d53Smrg if (df < 3) 29050806d53Smrg vrf >>= 1; 29150806d53Smrg if ((vrf > MAX_VREF) || (vrf < MIN_VREF)) 29250806d53Smrg continue; 29350806d53Smrg 29450806d53Smrg f = vrf * m; 29550806d53Smrg outf = f; 29650806d53Smrg if (df < 2) 29750806d53Smrg outf >>= 2 - df; 29850806d53Smrg if ((f > MAX_VCO) || (f < MIN_VCO)) 29950806d53Smrg continue; 30050806d53Smrg 30150806d53Smrg /* outf is a valid freq, pick the closest now */ 30250806d53Smrg 30350806d53Smrg if ((diff = (requested_freq - outf)) < 0) 30450806d53Smrg diff = -diff;; 30550806d53Smrg if (diff < best_diff) { 30650806d53Smrg best_diff = diff; 30750806d53Smrg best_m = m; 30850806d53Smrg best_n = n; 30950806d53Smrg best_df = df; 31050806d53Smrg best_outf = outf; 31150806d53Smrg } 31250806d53Smrg } 31350806d53Smrg } 31450806d53Smrg 31550806d53Smrg /* do we have an acceptably close frequency? (less than 1% diff) */ 31650806d53Smrg 31750806d53Smrg if (best_diff > (requested_freq/100)) { 31850806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 31950806d53Smrg "Specified dot clock (%.3f) too far (best %.3f) IBM RGB52x", 32050806d53Smrg requested_freq / 1000.0, best_outf / 1000.0); 32150806d53Smrg return(FALSE); 32250806d53Smrg } 32350806d53Smrg 32450806d53Smrg pI128->mem.rbase_g[PEL_MASK] = 0xFF; MB; 32550806d53Smrg 32650806d53Smrg tmpc = pI128->mem.rbase_g[IDXCTL_I] & 0xFF; 32750806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 32850806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 32950806d53Smrg 33050806d53Smrg pI128->mem.rbase_g[IDXH_I] = 0; MB; 33150806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 0; MB; 33250806d53Smrg 33350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc_clock; MB; 33450806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 33550806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x81; MB; 33650806d53Smrg 33750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0+4; MB; 33850806d53Smrg pI128->mem.rbase_g[DATA_I] = (best_df<<6) | (best_m&0x3f); MB; 33950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_n0+4; MB; 34050806d53Smrg pI128->mem.rbase_g[DATA_I] = best_n; MB; 34150806d53Smrg 34250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pll_ctrl1; MB; 34350806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 34450806d53Smrg pI128->mem.rbase_g[DATA_I] = (tmp2&0xf8) | 3; /* 8 M/N pairs in PLL */ MB; 34550806d53Smrg 34650806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pll_ctrl2; MB; 34750806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 34850806d53Smrg pI128->mem.rbase_g[DATA_I] = (tmp2&0xf0) | 2; /* clock number 2 */ MB; 34950806d53Smrg 35050806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc_clock; MB; 35150806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf0; 35250806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | ((flags & V_DBLCLK) ? 0x03 : 0x01); MB; 35350806d53Smrg 35450806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sync; MB; 35550806d53Smrg pI128->mem.rbase_g[DATA_I] = ((flags & V_PHSYNC) ? 0x10 : 0x00) 35650806d53Smrg | ((flags & V_PVSYNC) ? 0x20 : 0x00); MB; 35750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_hsync_pos; MB; 35850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x01; /* Delay syncs by 1 pclock */ MB; 35950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pwr_mgmt; MB; 36050806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 36150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_dac_op; MB; 36250806d53Smrg tmp2 = (pI128->RamdacType == IBM528_DAC) ? 0x02 : 0x00; /* fast slew */ 36350806d53Smrg if (pI128->DACSyncOnGreen) tmp2 |= 0x08; 36450806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2; MB; 36550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pal_ctrl; MB; 36650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 36750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk; MB; 36850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x01; MB; 36950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc1; MB; 37050806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xbc; 37150806d53Smrg tmp2 |= 0x20; 37250806d53Smrg if ((pI128->MemoryType != I128_MEMORY_DRAM) && 37350806d53Smrg (pI128->MemoryType != I128_MEMORY_SGRAM)) 37450806d53Smrg tmp2 |= (pI128->RamdacType == IBM528_DAC) ? 3 : 1; 37550806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2; MB; 37650806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc2; MB; 37750806d53Smrg tmp2 = 0x03; 37850806d53Smrg if (pI128->DAC8Bit) 37950806d53Smrg tmp2 |= 0x04; 38050806d53Smrg if (!((pI128->MemoryType == I128_MEMORY_DRAM) && 38150806d53Smrg (pI128->bitsPerPixel > 16))) 38250806d53Smrg tmp2 |= 0x40; 38350806d53Smrg if ((pI128->MemoryType == I128_MEMORY_SGRAM) && 38450806d53Smrg (pI128->bitsPerPixel > 16) && 38550806d53Smrg (pI128->RamdacType != SILVER_HAMMER_DAC) ) 38650806d53Smrg tmp2 &= 0x3F; 38750806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2; MB; 38850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc3; MB; 38950806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 39050806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc4; MB; 39150806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 39250806d53Smrg 39350806d53Smrg /* ?? There is no write to cursor control register */ 39450806d53Smrg 39550806d53Smrg if (pI128->RamdacType == IBM526_DAC) { 39650806d53Smrg if (pI128->MemoryType == I128_MEMORY_SGRAM) { 39750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_ref_div; MB; 39850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x09; MB; 39950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_vco_div; MB; 40050806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x83; MB; 40150806d53Smrg } else { 40250806d53Smrg /* program mclock to 52MHz */ 40350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_ref_div; MB; 40450806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x08; MB; 40550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_vco_div; MB; 40650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x41; MB; 40750806d53Smrg } 40850806d53Smrg /* should delay at least a millisec so we'll wait 50 */ 40950806d53Smrg usleep(50000); 41050806d53Smrg } 41150806d53Smrg 41250806d53Smrg switch (pI128->depth) { 41350806d53Smrg case 24: /* 32 bit */ 41450806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 41550806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 41650806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x06; MB; 41750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_32bpp; MB; 41850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x03; MB; 41950806d53Smrg break; 42050806d53Smrg case 16: 42150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 42250806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 42350806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x04; MB; 42450806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_16bpp; MB; 42550806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xC7; MB; 42650806d53Smrg break; 42750806d53Smrg case 15: 42850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 42950806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 43050806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x04; MB; 43150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_16bpp; MB; 43250806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xC5; MB; 43350806d53Smrg break; 43450806d53Smrg default: /* 8 bit */ 43550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 43650806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 43750806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x03; MB; 43850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_8bpp; MB; 43950806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 44050806d53Smrg break; 44150806d53Smrg } 44250806d53Smrg 44350806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = tmpc; MB; 44450806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 44550806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 44650806d53Smrg 44750806d53Smrg return(TRUE); 44850806d53Smrg} 44950806d53Smrg 45050806d53Smrg 45150806d53SmrgBool 45250806d53SmrgI128ProgramSilverHammer(ScrnInfoPtr pScrn, DisplayModePtr mode) 45350806d53Smrg{ 45450806d53Smrg /* The SilverHammer DAC is essentially the same as the IBMRGBxxx DACs, 45550806d53Smrg * but with fewer options and a different reference frequency. 45650806d53Smrg */ 45750806d53Smrg 45850806d53Smrg I128Ptr pI128 = I128PTR(pScrn); 45950806d53Smrg unsigned char tmp2, m, n, df, best_m, best_n, best_df, max_n; 46050806d53Smrg CARD32 tmpl, tmph, tmpc; 46150806d53Smrg long f, vrf, outf, best_diff, best_outf = 0, diff; 46250806d53Smrg long requested_freq; 46350806d53Smrg int freq = mode->SynthClock; 46450806d53Smrg int flags = mode->Flags; 46550806d53Smrg int skew = mode->HSkew; 46650806d53Smrg 46750806d53Smrg#undef REF_FREQ 46850806d53Smrg#define REF_FREQ 37500000 46950806d53Smrg#undef MAX_VREF 47050806d53Smrg#define MAX_VREF 9000000 47150806d53Smrg#define MIN_VREF 1500000 47250806d53Smrg#undef MAX_VCO 47350806d53Smrg#define MAX_VCO 270000000 47450806d53Smrg#define MIN_VCO 65000000 47550806d53Smrg 47650806d53Smrg if (freq < 25000) { 47750806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 47850806d53Smrg "Specified dot clock (%.3f) too low for SilverHammer", 47950806d53Smrg freq / 1000.0); 48050806d53Smrg return(FALSE); 48150806d53Smrg } else if (freq > MAX_VCO) { 48250806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 48350806d53Smrg "Specified dot clock (%.3f) too high for SilverHammer", 48450806d53Smrg freq / 1000.0); 48550806d53Smrg return(FALSE); 48650806d53Smrg } 48750806d53Smrg 48850806d53Smrg requested_freq = freq * 1000; 48950806d53Smrg 49050806d53Smrg best_m = best_n = best_df = 0; 49150806d53Smrg best_diff = requested_freq; /* worst case */ 49250806d53Smrg 49350806d53Smrg for (df=0; df<4; df++) { 49450806d53Smrg max_n = REF_FREQ / MIN_VREF; 49550806d53Smrg if (df < 3) 49650806d53Smrg max_n >>= 1; 49750806d53Smrg for (n=2; n<max_n; n++) 49850806d53Smrg for (m=65; m<=128; m++) { 49950806d53Smrg vrf = REF_FREQ / n; 50050806d53Smrg if (df < 3) 50150806d53Smrg vrf >>= 1; 50250806d53Smrg if ((vrf > MAX_VREF) || (vrf < MIN_VREF)) 50350806d53Smrg continue; 50450806d53Smrg 50550806d53Smrg f = vrf * m; 50650806d53Smrg outf = f; 50750806d53Smrg if (df < 2) 50850806d53Smrg outf >>= 2 - df; 50950806d53Smrg if ((f > MAX_VCO) || (f < MIN_VCO)) 51050806d53Smrg continue; 51150806d53Smrg 51250806d53Smrg /* outf is a valid freq, pick the closest now */ 51350806d53Smrg 51450806d53Smrg if ((diff = (requested_freq - outf)) < 0) 51550806d53Smrg diff = -diff;; 51650806d53Smrg if (diff < best_diff) { 51750806d53Smrg best_diff = diff; 51850806d53Smrg best_m = m; 51950806d53Smrg best_n = n; 52050806d53Smrg best_df = df; 52150806d53Smrg best_outf = outf; 52250806d53Smrg } 52350806d53Smrg } 52450806d53Smrg } 52550806d53Smrg 52650806d53Smrg /* do we have an acceptably close frequency? (less than 1% diff) */ 52750806d53Smrg 52850806d53Smrg if (best_diff > (requested_freq/100)) { 52950806d53Smrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 53050806d53Smrg "Specified dot clock (%.3f) too far (best %.3f) SilverHammer", 53150806d53Smrg requested_freq / 1000.0, best_outf / 1000.0); 53250806d53Smrg return(FALSE); 53350806d53Smrg } 53450806d53Smrg 53550806d53Smrg pI128->mem.rbase_g[PEL_MASK] = 0xFF; MB; 53650806d53Smrg 53750806d53Smrg tmpc = pI128->mem.rbase_g[IDXCTL_I] & 0xFF; 53850806d53Smrg tmph = pI128->mem.rbase_g[IDXH_I] & 0xFF; 53950806d53Smrg tmpl = pI128->mem.rbase_g[IDXL_I] & 0xFF; 54050806d53Smrg 54150806d53Smrg pI128->mem.rbase_g[IDXH_I] = 0; MB; 54250806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = 0; MB; 54350806d53Smrg 54450806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc_clock; MB; 54550806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 54650806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x81; MB; 54750806d53Smrg 54850806d53Smrg if (!pI128->Primary) { 54950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0; MB; 55050806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x15; MB; 55150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0+1; MB; 55250806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x10; MB; 55350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0+2; MB; 55450806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x2c; MB; 55550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0+3; MB; 55650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x12; MB; 55750806d53Smrg } 55850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_m0+4; MB; 55950806d53Smrg pI128->mem.rbase_g[DATA_I] = (best_df<<6) | (best_m&0x3f); MB; 56050806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_n0+4; MB; 56150806d53Smrg pI128->mem.rbase_g[DATA_I] = best_n; MB; 56250806d53Smrg 56350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pll_ctrl1; MB; 56450806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 56550806d53Smrg pI128->mem.rbase_g[DATA_I] = (tmp2&0xf8) | 3; /* 8 M/N pairs in PLL */ MB; 56650806d53Smrg 56750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pll_ctrl2; MB; 56850806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xFF; 56950806d53Smrg pI128->mem.rbase_g[DATA_I] = (tmp2&0xf0) | 2; /* clock number 2 */ MB; 57050806d53Smrg 57150806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc_clock; MB; 57250806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf0; 57350806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | ((flags & V_DBLCLK) ? 0x03 : 0x01); MB; 57450806d53Smrg 57550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sync; MB; 57650806d53Smrg pI128->mem.rbase_g[DATA_I] = ((flags & V_PHSYNC) ? 0x10 : 0x00) 57750806d53Smrg | ((flags & V_PVSYNC) ? 0x20 : 0x00); MB; 57850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_hsync_pos; MB; 57950806d53Smrg pI128->mem.rbase_g[DATA_I] = ((flags & V_HSKEW) ? skew : 0x01); MB; 58050806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pwr_mgmt; MB; 58150806d53Smrg/* Use 0x01 below with digital flat panel to conserve energy and reduce noise */ 58250806d53Smrg pI128->mem.rbase_g[DATA_I] = (pI128->FlatPanel ? 0x01 : 0x00); MB; 58350806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_dac_op; MB; 58450806d53Smrg pI128->mem.rbase_g[DATA_I] = (pI128->DACSyncOnGreen ? 0x08 : 0x00); MB; 58550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pal_ctrl; MB; 58650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 58750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk; MB; 58850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x01; MB; 58950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc1; MB; 59050806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xbc; 59150806d53Smrg if ((pI128->MemoryType != I128_MEMORY_DRAM) && 59250806d53Smrg (pI128->MemoryType != I128_MEMORY_SGRAM)) 59350806d53Smrg tmp2 |= (pI128->RamdacType == IBM528_DAC) ? 3 : 1; 59450806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2; MB; 59550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc2; MB; 59650806d53Smrg tmp2 = 0x03; 59750806d53Smrg if (pI128->DAC8Bit) 59850806d53Smrg tmp2 |= 0x04; 59950806d53Smrg if (!((pI128->MemoryType == I128_MEMORY_DRAM) && 60050806d53Smrg (pI128->bitsPerPixel > 16))) 60150806d53Smrg tmp2 |= 0x40; 60250806d53Smrg if ((pI128->MemoryType == I128_MEMORY_SGRAM) && 60350806d53Smrg (pI128->bitsPerPixel > 16) && 60450806d53Smrg (pI128->RamdacType != SILVER_HAMMER_DAC) ) 60550806d53Smrg tmp2 &= 0x3F; 60650806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2; MB; 60750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc3; MB; 60850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 60950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_misc4; MB; 61050806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 61150806d53Smrg 61250806d53Smrg /* ?? There is no write to cursor control register */ 61350806d53Smrg 61450806d53Smrg /* Set the memory clock speed to 95 MHz */ 61550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_ref_div; MB; 61650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x08; MB; 61750806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_sysclk_vco_div; MB; 61850806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x50; MB; 61950806d53Smrg 62050806d53Smrg /* should delay at least a millisec so we'll wait 50 */ 62150806d53Smrg usleep(50000); 62250806d53Smrg 62350806d53Smrg switch (pI128->depth) { 62450806d53Smrg case 24: /* 32 bit */ 62550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 62650806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 62750806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x06; MB; 62850806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_32bpp; MB; 62950806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x03; MB; 63050806d53Smrg break; 63150806d53Smrg case 16: 63250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 63350806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 63450806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x04; MB; 63550806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_16bpp; MB; 63650806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xC7; MB; 63750806d53Smrg break; 63850806d53Smrg case 15: 63950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 64050806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 64150806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x04; MB; 64250806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_16bpp; MB; 64350806d53Smrg pI128->mem.rbase_g[DATA_I] = 0xC5; MB; 64450806d53Smrg break; 64550806d53Smrg default: /* 8 bit */ 64650806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_pix_fmt; MB; 64750806d53Smrg tmp2 = pI128->mem.rbase_g[DATA_I] & 0xf8; 64850806d53Smrg pI128->mem.rbase_g[DATA_I] = tmp2 | 0x03; MB; 64950806d53Smrg pI128->mem.rbase_g[IDXL_I] = IBMRGB_8bpp; MB; 65050806d53Smrg pI128->mem.rbase_g[DATA_I] = 0x00; MB; 65150806d53Smrg break; 65250806d53Smrg } 65350806d53Smrg 65450806d53Smrg pI128->mem.rbase_g[IDXCTL_I] = tmpc; MB; 65550806d53Smrg pI128->mem.rbase_g[IDXH_I] = tmph; MB; 65650806d53Smrg pI128->mem.rbase_g[IDXL_I] = tmpl; MB; 65750806d53Smrg 65850806d53Smrg return(TRUE); 65950806d53Smrg} 660