s3_IBMRGB.c revision b27e1915
1340e3fbdSmrg/* 2340e3fbdSmrg * Copyright 2001 Ani Joshi <ajoshi@unixbox.com> 3340e3fbdSmrg * 4340e3fbdSmrg * XFree86 4.x driver for S3 chipsets 5340e3fbdSmrg * 6340e3fbdSmrg * 7340e3fbdSmrg * Permission to use, copy, modify, distribute, and sell this software and its 8340e3fbdSmrg * documentation for any purpose is hereby granted without fee, provided that 9340e3fbdSmrg * the above copyright notice appear in all copies and that both that copyright 10340e3fbdSmrg * notice and this permission notice appear in supporting documentation and 11340e3fbdSmrg * that the name of Ani Joshi not be used in advertising or 12340e3fbdSmrg * publicity pertaining to distribution of the software without specific, 13340e3fbdSmrg * written prior permission. Ani Joshi makes no representations 14340e3fbdSmrg * about the suitability of this software for any purpose. It is provided 15340e3fbdSmrg * "as-is" without express or implied warranty. 16340e3fbdSmrg * 17340e3fbdSmrg * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18340e3fbdSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19340e3fbdSmrg * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20340e3fbdSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21340e3fbdSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22340e3fbdSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23340e3fbdSmrg * PERFORMANCE OF THIS SOFTWARE. 24340e3fbdSmrg * 25340e3fbdSmrg * 26340e3fbdSmrg */ 27340e3fbdSmrg 28340e3fbdSmrg#ifdef HAVE_CONFIG_H 29340e3fbdSmrg#include "config.h" 30340e3fbdSmrg#endif 31340e3fbdSmrg 32340e3fbdSmrg#include "xf86.h" 33340e3fbdSmrg#include "xf86_OSproc.h" 34340e3fbdSmrg 35340e3fbdSmrg#include "compiler.h" 36340e3fbdSmrg 37340e3fbdSmrg#include "IBM.h" 38340e3fbdSmrg 39340e3fbdSmrg#include "s3.h" 40340e3fbdSmrg 41340e3fbdSmrg 42340e3fbdSmrg#define IBMRGB_WRITE_ADDR 0x3C8 /* CR55 low bit == 0 */ 43340e3fbdSmrg#define IBMRGB_RAMDAC_DATA 0x3C9 /* CR55 low bit == 0 */ 44340e3fbdSmrg#define IBMRGB_PIXEL_MASK 0x3C6 /* CR55 low bit == 0 */ 45340e3fbdSmrg#define IBMRGB_READ_ADDR 0x3C7 /* CR55 low bit == 0 */ 46340e3fbdSmrg#define IBMRGB_INDEX_LOW 0x3C8 /* CR55 low bit == 1 */ 47340e3fbdSmrg#define IBMRGB_INDEX_HIGH 0x3C9 /* CR55 low bit == 1 */ 48340e3fbdSmrg#define IBMRGB_INDEX_DATA 0x3C6 /* CR55 low bit == 1 */ 49340e3fbdSmrg#define IBMRGB_INDEX_CONTROL 0x3C7 /* CR55 low bit == 1 */ 50340e3fbdSmrg 51340e3fbdSmrg 52340e3fbdSmrgstatic void S3OutIBMRGBIndReg(ScrnInfoPtr pScrn, CARD32 reg, 53340e3fbdSmrg unsigned char mask, unsigned char data) 54340e3fbdSmrg{ 55340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 56340e3fbdSmrg unsigned char tmp, tmp2 = 0x00; 57340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 58340e3fbdSmrg 59340e3fbdSmrg outb(vgaCRIndex, 0x55); 60340e3fbdSmrg tmp = inb(vgaCRReg) & 0xfc; 61340e3fbdSmrg outb(vgaCRReg, tmp | 0x01); 62340e3fbdSmrg 63340e3fbdSmrg outb(IBMRGB_INDEX_LOW, reg); 64340e3fbdSmrg 65340e3fbdSmrg if (mask != 0x00) 66340e3fbdSmrg tmp2 = inb(IBMRGB_INDEX_DATA) & mask; 67340e3fbdSmrg outb(IBMRGB_INDEX_DATA, tmp2 | data); 68340e3fbdSmrg 69340e3fbdSmrg outb(vgaCRIndex, 0x55); 70340e3fbdSmrg outb(vgaCRReg, tmp); 71340e3fbdSmrg} 72340e3fbdSmrg 73340e3fbdSmrg 74340e3fbdSmrgstatic unsigned char S3InIBMRGBIndReg(ScrnInfoPtr pScrn, CARD32 reg) 75340e3fbdSmrg{ 76340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 77340e3fbdSmrg unsigned char tmp, ret; 78340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 79340e3fbdSmrg 80340e3fbdSmrg outb(vgaCRIndex, 0x55); 81340e3fbdSmrg tmp = inb(vgaCRReg) & 0xfc; 82340e3fbdSmrg outb(vgaCRReg, tmp | 0x01); 83340e3fbdSmrg 84340e3fbdSmrg outb(IBMRGB_INDEX_LOW, reg); 85340e3fbdSmrg ret = inb(IBMRGB_INDEX_DATA); 86340e3fbdSmrg 87340e3fbdSmrg outb(vgaCRIndex, 0x55); 88340e3fbdSmrg outb(vgaCRReg, tmp); 89340e3fbdSmrg 90340e3fbdSmrg return ret; 91340e3fbdSmrg} 92340e3fbdSmrg 93340e3fbdSmrg 94340e3fbdSmrgstatic void S3IBMWriteAddress(ScrnInfoPtr pScrn, CARD32 index) 95340e3fbdSmrg{ 96340e3fbdSmrg outb(IBMRGB_WRITE_ADDR, index); 97340e3fbdSmrg} 98340e3fbdSmrg 99340e3fbdSmrgstatic void S3IBMWriteData(ScrnInfoPtr pScrn, unsigned char data) 100340e3fbdSmrg{ 101340e3fbdSmrg outb(IBMRGB_INDEX_DATA, data); 102340e3fbdSmrg} 103340e3fbdSmrg 104340e3fbdSmrgstatic void S3IBMReadAddress(ScrnInfoPtr pScrn, CARD32 index) 105340e3fbdSmrg{ 106340e3fbdSmrg outb(IBMRGB_READ_ADDR, index); 107340e3fbdSmrg} 108340e3fbdSmrg 109340e3fbdSmrgstatic unsigned char S3IBMReadData(ScrnInfoPtr pScrn) 110340e3fbdSmrg{ 111340e3fbdSmrg return inb(IBMRGB_RAMDAC_DATA); 112340e3fbdSmrg} 113340e3fbdSmrg 114340e3fbdSmrg 115340e3fbdSmrgBool S3ProbeIBMramdac(ScrnInfoPtr pScrn) 116340e3fbdSmrg{ 117340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 118340e3fbdSmrg 119340e3fbdSmrg if (pS3->Chipset != PCI_CHIP_968) 120340e3fbdSmrg return FALSE; 121340e3fbdSmrg 122340e3fbdSmrg pS3->RamDacRec = RamDacCreateInfoRec(); 123340e3fbdSmrg pS3->RamDacRec->ReadDAC = S3InIBMRGBIndReg; 124340e3fbdSmrg pS3->RamDacRec->WriteDAC = S3OutIBMRGBIndReg; 125340e3fbdSmrg pS3->RamDacRec->ReadAddress = S3IBMReadAddress; 126340e3fbdSmrg pS3->RamDacRec->WriteAddress = S3IBMWriteAddress; 127340e3fbdSmrg pS3->RamDacRec->ReadData = S3IBMReadData; 128340e3fbdSmrg pS3->RamDacRec->WriteData = S3IBMWriteData; 129340e3fbdSmrg pS3->RamDacRec->LoadPalette = NULL; 130340e3fbdSmrg 131340e3fbdSmrg if (!RamDacInit(pScrn, pS3->RamDacRec)) { 132340e3fbdSmrg RamDacDestroyInfoRec(pS3->RamDacRec); 133340e3fbdSmrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RamDacInit failed\n"); 134340e3fbdSmrg return FALSE; 135340e3fbdSmrg } 136340e3fbdSmrg 137340e3fbdSmrg pS3->RamDac = IBMramdacProbe(pScrn, S3IBMRamdacs); 138340e3fbdSmrg if (pS3->RamDac) 139340e3fbdSmrg return TRUE; 140340e3fbdSmrg 141340e3fbdSmrg return FALSE; 142340e3fbdSmrg} 143340e3fbdSmrg 144340e3fbdSmrgstatic void S3ProgramIBMRGBClock(ScrnInfoPtr pScrn, int clk, unsigned char m, 145340e3fbdSmrg unsigned char n, unsigned char df) 146340e3fbdSmrg{ 147340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_misc_clock, ~1, 1); 148340e3fbdSmrg 149340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_m0+2*clk, 0, (df<<6)|(m&0x3f)); 150340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_n0+2*clk, 0, n); 151340e3fbdSmrg 152340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pll_ctrl2, 0xf0, clk); 153340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pll_ctrl1, 0xf8, 3); 154340e3fbdSmrg} 155340e3fbdSmrg 156340e3fbdSmrg 157340e3fbdSmrgstatic void S3IBMRGBSetClock(ScrnInfoPtr pScrn, long freq, int clk, long dacspeed, 158340e3fbdSmrg long fref) 159340e3fbdSmrg{ 160340e3fbdSmrg volatile double ffreq, fdacspeed, ffref; 161340e3fbdSmrg volatile int df, n, m, max_n, min_df; 162340e3fbdSmrg volatile int best_m=69, best_n=17, best_df=0; 163340e3fbdSmrg volatile double diff, mindiff; 164340e3fbdSmrg 165340e3fbdSmrg#define FREQ_MIN 16250 166340e3fbdSmrg#define FREQ_MAX dacspeed 167340e3fbdSmrg 168340e3fbdSmrg if (freq < FREQ_MIN) 169340e3fbdSmrg ffreq = FREQ_MIN / 1000.0; 170340e3fbdSmrg else if (freq > FREQ_MAX) 171340e3fbdSmrg ffreq = FREQ_MAX / 1000.0; 172340e3fbdSmrg else 173340e3fbdSmrg ffreq = freq / 1000.0; 174340e3fbdSmrg 175340e3fbdSmrg fdacspeed = dacspeed / 1e3; 176340e3fbdSmrg ffref = fref / 1e3; 177340e3fbdSmrg 178340e3fbdSmrg ffreq /= ffref; 179340e3fbdSmrg ffreq *= 16; 180340e3fbdSmrg mindiff = ffreq; 181340e3fbdSmrg 182340e3fbdSmrg if (freq <= dacspeed/4) 183340e3fbdSmrg min_df = 0; 184340e3fbdSmrg else if (freq <= dacspeed/2) 185340e3fbdSmrg min_df = 1; 186340e3fbdSmrg else 187340e3fbdSmrg min_df = 2; 188340e3fbdSmrg 189340e3fbdSmrg for (df=0; df<4; df++) { 190340e3fbdSmrg ffreq /= 2; 191340e3fbdSmrg mindiff /= 2; 192340e3fbdSmrg if (df < min_df) 193340e3fbdSmrg continue; 194340e3fbdSmrg 195340e3fbdSmrg if (df < 3) 196340e3fbdSmrg max_n = fref / 1000 / 2; 197340e3fbdSmrg else 198340e3fbdSmrg max_n = fref / 1000; 199340e3fbdSmrg if (max_n > 31) 200340e3fbdSmrg max_n = 31; 201340e3fbdSmrg 202340e3fbdSmrg for (n=2; n <= max_n; n++) { 203340e3fbdSmrg m = (int)(ffreq * n + 0.5) - 65; 204340e3fbdSmrg if (m < 0) 205340e3fbdSmrg m = 0; 206340e3fbdSmrg else if (m > 63) 207340e3fbdSmrg m = 63; 208340e3fbdSmrg diff = (m+65.0)/n-ffreq; 209340e3fbdSmrg if (diff < 0) 210340e3fbdSmrg diff = -diff; 211340e3fbdSmrg if (diff < mindiff) { 212340e3fbdSmrg mindiff = diff; 213340e3fbdSmrg best_n = n; 214340e3fbdSmrg best_m = m; 215340e3fbdSmrg best_df = df; 216340e3fbdSmrg } 217340e3fbdSmrg } 218340e3fbdSmrg } 219340e3fbdSmrg 220340e3fbdSmrg S3ProgramIBMRGBClock(pScrn, clk, best_m, best_n, best_df); 221340e3fbdSmrg} 222340e3fbdSmrg 223340e3fbdSmrgvoid S3IBMRGB_Restore(ScrnInfoPtr pScrn) 224340e3fbdSmrg{ 225340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 226340e3fbdSmrg S3RegPtr restore = &pS3->SavedRegs; 227340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 228340e3fbdSmrg int i; 229340e3fbdSmrg 230340e3fbdSmrg for(i=0; i<0x100; i++) 231340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, i, 0, restore->dacregs[i]); 232340e3fbdSmrg 233340e3fbdSmrg outb(vgaCRIndex, 0x22); 234340e3fbdSmrg outb(vgaCRReg, restore->dacregs[0x100]); 235340e3fbdSmrg} 236340e3fbdSmrg 237340e3fbdSmrg 238340e3fbdSmrgvoid S3IBMRGB_Save(ScrnInfoPtr pScrn) 239340e3fbdSmrg{ 240340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 241340e3fbdSmrg S3RegPtr save = &pS3->SavedRegs; 242340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 243340e3fbdSmrg int i; 244340e3fbdSmrg 245340e3fbdSmrg for (i=0; i<0x100; i++) 246340e3fbdSmrg save->dacregs[i] = S3InIBMRGBIndReg(pScrn, i); 247340e3fbdSmrg 248340e3fbdSmrg outb(vgaCRIndex, 0x22); 249340e3fbdSmrg save->dacregs[0x100] = inb(vgaCRReg); 250340e3fbdSmrg} 251340e3fbdSmrg 252340e3fbdSmrg 253340e3fbdSmrgvoid S3IBMRGB_PreInit(ScrnInfoPtr pScrn) 254340e3fbdSmrg{ 255340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 256340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 257340e3fbdSmrg unsigned char cr55, tmp; 258340e3fbdSmrg 259340e3fbdSmrg outb(vgaCRIndex, 0x43); 260340e3fbdSmrg tmp = inb(vgaCRReg); 261340e3fbdSmrg outb(vgaCRReg, tmp & ~0x02); 262340e3fbdSmrg 263340e3fbdSmrg outb(vgaCRIndex, 0x55); 264340e3fbdSmrg cr55 = inb(vgaCRReg); 265340e3fbdSmrg outb(vgaCRReg, (cr55 & ~0x03) | 0x01); /* set rs2 */ 266340e3fbdSmrg 267340e3fbdSmrg tmp = inb(IBMRGB_INDEX_CONTROL); 268340e3fbdSmrg outb(IBMRGB_INDEX_CONTROL, tmp & ~1); 269340e3fbdSmrg outb(IBMRGB_INDEX_HIGH, 0); 270340e3fbdSmrg 271340e3fbdSmrg outb(vgaCRIndex, 0x55); 272340e3fbdSmrg outb(vgaCRReg, cr55 & ~0x03); 273340e3fbdSmrg 274340e3fbdSmrg { 275340e3fbdSmrg int m, n, df, mclk=0; 276340e3fbdSmrg 277340e3fbdSmrg m = S3InIBMRGBIndReg(pScrn, IBMRGB_sysclk_vco_div); 278340e3fbdSmrg n = S3InIBMRGBIndReg(pScrn, IBMRGB_sysclk_ref_div) & 0x1f; 279340e3fbdSmrg df = m >> 6; 280340e3fbdSmrg m &= 0x3f; 281340e3fbdSmrg if (!n) { 282340e3fbdSmrg m = 0; 283340e3fbdSmrg n = 1; 284340e3fbdSmrg } 285340e3fbdSmrg mclk = ((pS3->RefClock*100 * (m+65)) / n / (8 >> df) + 50) / 100; 286340e3fbdSmrg pS3->mclk = mclk; 287340e3fbdSmrg xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f MHz\n", 288340e3fbdSmrg mclk / 1000.0); 289340e3fbdSmrg } 290340e3fbdSmrg} 291340e3fbdSmrg 292340e3fbdSmrg 293340e3fbdSmrgvoid S3IBMRGB_Init(ScrnInfoPtr pScrn, DisplayModePtr mode) 294340e3fbdSmrg{ 295340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 296340e3fbdSmrg unsigned char tmp, blank; 297340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 298340e3fbdSmrg 299340e3fbdSmrg S3IBMRGBSetClock(pScrn, mode->Clock, 2, pS3->MaxClock, 300340e3fbdSmrg pS3->RefClock); 301340e3fbdSmrg 302340e3fbdSmrg outb(0x3c4, 1); 303340e3fbdSmrg blank = inb(0x3c5); 304340e3fbdSmrg outb(0x3c5, blank | 0x20); 305340e3fbdSmrg 306340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_misc_clock, 0xf0, 0x03); 307340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_sync, 0, 0); 308340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_hsync_pos, 0, 0); 309340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pwr_mgmt, 0, 0); 310340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_dac_op, ~8, 0); 311340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_dac_op, ~2, 2); 312340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pal_ctrl, 0, 0); 313340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_misc1, ~0x43, 1); 314340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_misc2, 0, 0x47); 315340e3fbdSmrg 316340e3fbdSmrg outb(vgaCRIndex, 0x22); 317340e3fbdSmrg tmp = inb(vgaCRReg); 318340e3fbdSmrg if (pS3->s3Bpp == 1) 319340e3fbdSmrg outb(vgaCRReg, tmp | 8); 320340e3fbdSmrg else 321340e3fbdSmrg outb(vgaCRReg, tmp & ~8); 322340e3fbdSmrg 323340e3fbdSmrg outb(vgaCRIndex, 0x65); 324340e3fbdSmrg outb(vgaCRReg, 0x00); /* ! 528 */ 325340e3fbdSmrg 326340e3fbdSmrg outb(vgaCRIndex, 0x40); 327340e3fbdSmrg outb(vgaCRReg, 0x11); 328340e3fbdSmrg outb(vgaCRIndex, 0x55); 329340e3fbdSmrg outb(vgaCRReg, 0x00); 330340e3fbdSmrg 331340e3fbdSmrg switch (pScrn->depth) { 332340e3fbdSmrg case 8: 333340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 3); 334340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_8bpp, 0, 0); 335340e3fbdSmrg break; 336340e3fbdSmrg case 15: 337340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 4); 338340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_16bpp, 0, 0xc0); 339340e3fbdSmrg break; 340340e3fbdSmrg case 16: 341340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_pix_fmt, 0xf8, 4); 342340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_16bpp, 0, 0xc2); 343340e3fbdSmrg break; 344340e3fbdSmrg } 345340e3fbdSmrg 346340e3fbdSmrg outb(vgaCRIndex, 0x66); 347340e3fbdSmrg tmp = inb(vgaCRReg) & 0xf8; 348340e3fbdSmrg outb(vgaCRReg, tmp); 349340e3fbdSmrg 350340e3fbdSmrg outb(vgaCRIndex, 0x58); 351340e3fbdSmrg tmp = (inb(vgaCRReg) & 0xbf) | 0x40; 352340e3fbdSmrg outb(vgaCRReg, tmp); 353340e3fbdSmrg 354340e3fbdSmrg outb(vgaCRIndex, 0x67); 355340e3fbdSmrg outb(vgaCRReg, 0x11); 356340e3fbdSmrg 357340e3fbdSmrg switch (pScrn->bitsPerPixel) { 358340e3fbdSmrg case 8: 359340e3fbdSmrg tmp = 0x21; 360340e3fbdSmrg break; 361340e3fbdSmrg case 16: 362340e3fbdSmrg tmp = 0x10; 363340e3fbdSmrg break; 364340e3fbdSmrg } 365340e3fbdSmrg outb(vgaCRIndex, 0x6d); 366340e3fbdSmrg outb(vgaCRReg, tmp); 367340e3fbdSmrg 368340e3fbdSmrg outb(0x3c4, 1); 369340e3fbdSmrg outb(0x3c5, blank); 370340e3fbdSmrg} 371340e3fbdSmrg 372340e3fbdSmrg 373340e3fbdSmrg/* hardware cursor */ 374340e3fbdSmrg 375340e3fbdSmrgstatic void S3IBMRGBSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 376340e3fbdSmrg{ 377340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 378340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 379340e3fbdSmrg unsigned char tmp; 380340e3fbdSmrg 381340e3fbdSmrg /* unlock sys regs */ 382340e3fbdSmrg outb(vgaCRIndex, 0x39); 383340e3fbdSmrg outb(vgaCRReg, 0xa5); 384340e3fbdSmrg 385340e3fbdSmrg outb(vgaCRIndex, 0x55); 386340e3fbdSmrg tmp = inb(vgaCRReg) & 0xfc; 387340e3fbdSmrg outb(vgaCRReg, tmp | 0x01); 388340e3fbdSmrg 389340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_r); 390340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (bg & 0x00ff0000) >> 16); 391340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_g); 392340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (bg & 0x0000ff00) >> 8); 393340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col1_b); 394340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (bg & 0x000000ff)); 395340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_r); 396340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (fg & 0x00ff0000) >> 16); 397340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_g); 398340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (fg & 0x0000ff00) >> 8); 399340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_col2_b); 400340e3fbdSmrg outb(IBMRGB_INDEX_DATA, (fg & 0x000000ff)); 401340e3fbdSmrg 402340e3fbdSmrg outb(vgaCRReg, tmp); 403340e3fbdSmrg} 404340e3fbdSmrg 405340e3fbdSmrg 406340e3fbdSmrgstatic void S3IBMRGBSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 407340e3fbdSmrg{ 408340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 409340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 410340e3fbdSmrg unsigned char tmp; 411340e3fbdSmrg 412340e3fbdSmrg /* unlock sys regs */ 413340e3fbdSmrg outb(vgaCRIndex, 0x39); 414340e3fbdSmrg outb(vgaCRReg, 0xa5); 415340e3fbdSmrg 416340e3fbdSmrg outb(vgaCRIndex, 0x55); 417340e3fbdSmrg tmp = inb(vgaCRReg) & 0xfc; 418340e3fbdSmrg outb(vgaCRReg, tmp | 0x01); 419340e3fbdSmrg 420340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xl); 421340e3fbdSmrg outb(IBMRGB_INDEX_DATA, x); 422340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xh); 423340e3fbdSmrg outb(IBMRGB_INDEX_DATA, x >> 8); 424340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yl); 425340e3fbdSmrg outb(IBMRGB_INDEX_DATA, y); 426340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yh); 427340e3fbdSmrg outb(IBMRGB_INDEX_DATA, y >> 8); 428340e3fbdSmrg 429340e3fbdSmrg outb(vgaCRReg, tmp); 430340e3fbdSmrg} 431340e3fbdSmrg 432340e3fbdSmrg 433340e3fbdSmrgstatic void S3IBMRGBHideCursor(ScrnInfoPtr pScrn) 434340e3fbdSmrg{ 435340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 436340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 437340e3fbdSmrg 438340e3fbdSmrg /* unlock sys regs */ 439340e3fbdSmrg outb(vgaCRIndex, 0x39); 440340e3fbdSmrg outb(vgaCRReg, 0xa5); 441340e3fbdSmrg 442340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_curs, ~3, 0x00); 443340e3fbdSmrg} 444340e3fbdSmrg 445340e3fbdSmrg 446340e3fbdSmrgstatic void S3IBMRGBShowCursor(ScrnInfoPtr pScrn) 447340e3fbdSmrg{ 448340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 449340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 450340e3fbdSmrg unsigned char tmp; 451340e3fbdSmrg 452340e3fbdSmrg /* unlock sys regs */ 453340e3fbdSmrg outb(vgaCRIndex, 0x39); 454340e3fbdSmrg outb(vgaCRReg, 0xa5); 455340e3fbdSmrg 456340e3fbdSmrg outb(vgaCRIndex, 0x55); 457340e3fbdSmrg tmp = (inb(vgaCRReg) & 0xdf) | 0x20; 458340e3fbdSmrg outb(vgaCRReg, tmp); 459340e3fbdSmrg 460340e3fbdSmrg outb(vgaCRIndex, 0x45); 461340e3fbdSmrg tmp = inb(vgaCRReg) & ~0x20; 462340e3fbdSmrg outb(vgaCRReg, tmp); 463340e3fbdSmrg 464340e3fbdSmrg S3OutIBMRGBIndReg(pScrn, IBMRGB_curs, 0, 0x27); 465340e3fbdSmrg} 466340e3fbdSmrg 467340e3fbdSmrg 468340e3fbdSmrgstatic void S3IBMRGBLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image) 469340e3fbdSmrg{ 470340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 471340e3fbdSmrg int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg; 472340e3fbdSmrg unsigned char tmp, tmp2; 473340e3fbdSmrg register int i; 474340e3fbdSmrg 475340e3fbdSmrg /* unlock sys regs */ 476340e3fbdSmrg outb(vgaCRIndex, 0x39); 477340e3fbdSmrg outb(vgaCRReg, 0xa5); 478340e3fbdSmrg 479340e3fbdSmrg outb(vgaCRIndex, 0x55); 480340e3fbdSmrg tmp = inb(vgaCRReg) & 0xfc; 481340e3fbdSmrg outb(vgaCRReg, tmp | 0x01); 482340e3fbdSmrg 483340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_hot_x); 484340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0); 485340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_hot_y); 486340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0); 487340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xl); 488340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0xff); 489340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_xh); 490340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0x7f); 491340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yl); 492340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0xff); 493340e3fbdSmrg outb(IBMRGB_INDEX_LOW, IBMRGB_curs_yh); 494340e3fbdSmrg outb(IBMRGB_INDEX_DATA, 0x7f); 495340e3fbdSmrg 496340e3fbdSmrg tmp2 = inb(IBMRGB_INDEX_CONTROL) & 0xfe; 497340e3fbdSmrg outb(IBMRGB_INDEX_CONTROL, tmp2 | 1); /* enable auto increment */ 498340e3fbdSmrg 499340e3fbdSmrg outb(IBMRGB_INDEX_HIGH, (unsigned char) (IBMRGB_curs_array >> 8)); 500340e3fbdSmrg outb(IBMRGB_INDEX_LOW, (unsigned char) (IBMRGB_curs_array)); 501340e3fbdSmrg 502340e3fbdSmrg for (i=0; i<1024; i++) 503340e3fbdSmrg outb(IBMRGB_INDEX_DATA, *image++); 504340e3fbdSmrg 505340e3fbdSmrg outb(IBMRGB_INDEX_HIGH, 0); 506340e3fbdSmrg outb(IBMRGB_INDEX_CONTROL, tmp2); /* disable auto increment */ 507340e3fbdSmrg outb(vgaCRIndex, 0x55); 508340e3fbdSmrg outb(vgaCRReg, tmp); 509340e3fbdSmrg} 510340e3fbdSmrg 511340e3fbdSmrg 512340e3fbdSmrgstatic Bool S3IBMRGBUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 513340e3fbdSmrg{ 514b27e1915Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 515340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 516340e3fbdSmrg return (pS3->hwCursor); 517340e3fbdSmrg} 518340e3fbdSmrg 519340e3fbdSmrg 520340e3fbdSmrgBool S3IBMRGB_CursorInit(ScreenPtr pScreen) 521340e3fbdSmrg{ 522b27e1915Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 523340e3fbdSmrg S3Ptr pS3 = S3PTR(pScrn); 524340e3fbdSmrg xf86CursorInfoPtr pCurs; 525340e3fbdSmrg 526340e3fbdSmrg if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec())) 527340e3fbdSmrg return FALSE; 528340e3fbdSmrg 529340e3fbdSmrg pCurs->MaxWidth = 64; 530340e3fbdSmrg pCurs->MaxHeight = 64; 531340e3fbdSmrg pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | 532340e3fbdSmrg HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | 533340e3fbdSmrg HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | 534340e3fbdSmrg HARDWARE_CURSOR_NIBBLE_SWAPPED | 535340e3fbdSmrg HARDWARE_CURSOR_BIT_ORDER_MSBFIRST; 536340e3fbdSmrg 537340e3fbdSmrg pCurs->SetCursorColors = S3IBMRGBSetCursorColors; 538340e3fbdSmrg pCurs->SetCursorPosition = S3IBMRGBSetCursorPosition; 539340e3fbdSmrg pCurs->LoadCursorImage = S3IBMRGBLoadCursorImage; 540340e3fbdSmrg pCurs->HideCursor = S3IBMRGBHideCursor; 541340e3fbdSmrg pCurs->ShowCursor = S3IBMRGBShowCursor; 542340e3fbdSmrg pCurs->UseHWCursor = S3IBMRGBUseHWCursor; 543340e3fbdSmrg 544340e3fbdSmrg return xf86InitCursor(pScreen, pCurs); 545340e3fbdSmrg} 546340e3fbdSmrg 547340e3fbdSmrg 548