ct_driver.c revision 431a6de2
1/* 2 * Copyright 1993 by Jon Block <block@frc.com> 3 * Modified by Mike Hollick <hollick@graphics.cis.upenn.edu> 4 * Modified 1994 by Régis Cridlig <cridlig@dmi.ens.fr> 5 * 6 * Major Contributors to XFree86 3.2 7 * Modified 1995/6 by Nozomi Ytow 8 * Modified 1996 by Egbert Eich <eich@xfree86.org> 9 * Modified 1996 by David Bateman <dbateman@club-internet.fr> 10 * Modified 1996 by Xavier Ducoin <xavier@rd.lectra.fr> 11 * 12 * Contributors to XFree86 3.2 13 * Modified 1995/6 by Ken Raeburn <raeburn@raeburn.org> 14 * Modified 1996 by Shigehiro Nomura <nomura@sm.sony.co.jp> 15 * Modified 1996 by Marc de Courville <marc@courville.org> 16 * Modified 1996 by Adam Sulmicki <adam@cfar.umd.edu> 17 * Modified 1996 by Jens Maurer <jmaurer@cck.uni-kl.de> 18 * 19 * Large parts rewritten for XFree86 4.0 20 * Modified 1998 by David Bateman <dbateman@club-internet.fr> 21 * Modified 1998 by Egbert Eich <eich@xfree86.org> 22 * Modified 1998 by Nozomi Ytow 23 * 24 * Permission to use, copy, modify, distribute, and sell this software and its 25 * documentation for any purpose is hereby granted without fee, provided that 26 * the above copyright notice appear in all copies and that both that 27 * copyright notice and this permission notice appear in supporting 28 * documentation, and that the name of the authors not be used in 29 * advertising or publicity pertaining to distribution of the software without 30 * specific, written prior permission. The authors makes no representations 31 * about the suitability of this software for any purpose. It is provided 32 * "as is" without express or implied warranty. 33 * 34 * THE AUTHORS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 35 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 36 * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 37 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 38 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 39 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 40 * PERFORMANCE OF THIS SOFTWARE. 41 */ 42/* 43 * Copyright 1997 44 * Digital Equipment Corporation. All rights reserved. 45 * This software is furnished under license and may be used and copied only in 46 * accordance with the following terms and conditions. Subject to these 47 * conditions, you may download, copy, install, use, modify and distribute 48 * this software in source and/or binary form. No title or ownership is 49 * transferred hereby. 50 * 1) Any source code used, modified or distributed must reproduce and retain 51 * this copyright notice and list of conditions as they appear in the 52 * source file. 53 * 54 * 2) No right is granted to use any trade name, trademark, or logo of Digital 55 * Equipment Corporation. Neither the "Digital Equipment Corporation" name 56 * nor any trademark or logo of Digital Equipment Corporation may be used 57 * to endorse or promote products derived from this software without the 58 * prior written permission of Digital Equipment Corporation. 59 * 60 * 3) This software is provided "AS-IS" and any express or implied warranties, 61 * including but not limited to, any implied warranties of merchantability, 62 * fitness for a particular purpose, or non-infringement are disclaimed. In 63 * no event shall DIGITAL be liable for any damages whatsoever, and in 64 * particular, DIGITAL shall not be liable for special, indirect, 65 * consequential, or incidental damages or damages for lost profits, loss 66 * of revenue or loss of use, whether such damages arise in contract, 67 * negligence, tort, under statute, in equity, at law or otherwise, even if 68 * advised of the possibility of such damage. 69 */ 70 71#ifdef HAVE_CONFIG_H 72#include "config.h" 73#endif 74 75/* All drivers should typically include these */ 76#include "xf86.h" 77#include "xf86_OSproc.h" 78 79/* Everything using inb/outb, etc needs "compiler.h" */ 80#include "compiler.h" 81 82/* Drivers for PCI hardware need this */ 83#include "xf86PciInfo.h" 84 85/* Drivers that need to access the PCI config space directly need this */ 86#include "xf86Pci.h" 87 88#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 89/* Standard resources are defined here */ 90#include "xf86Resources.h" 91 92/* Needed by Resources Access Control (RAC) */ 93#include "xf86RAC.h" 94#endif 95 96/* All drivers using the vgahw module need this */ 97#include "vgaHW.h" 98 99/* All drivers initialising the SW cursor need this */ 100#include "mipointer.h" 101 102/* All drivers implementing backing store need this */ 103#include "mibstore.h" 104 105/* All drivers using the mi banking wrapper need this */ 106#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6 107#define USE_MIBANK 108#endif 109 110#ifdef USE_MIBANK 111#include "mibank.h" 112#endif 113 114/* All drivers using the mi colormap manipulation need this */ 115#include "micmap.h" 116 117#include "fb.h" 118#include "xf86Priv.h" 119 120/* Needed for the 1 and 4 bpp framebuffers */ 121#ifdef HAVE_XF1BPP 122#include "xf1bpp.h" 123#endif 124#ifdef HAVE_XF4BPP 125#include "xf4bpp.h" 126#endif 127 128/* int10 */ 129#include "xf86int10.h" 130#include "vbe.h" 131 132/* Needed by the Shadow Framebuffer */ 133#include "shadowfb.h" 134 135/* Needed for replacement LoadPalette function for Gamma Correction */ 136#include "xf86cmap.h" 137 138#include "dixstruct.h" 139 140/* Driver specific headers */ 141#include "ct_driver.h" 142 143/* Mandatory functions */ 144static const OptionInfoRec * CHIPSAvailableOptions(int chipid, int busid); 145static void CHIPSIdentify(int flags); 146static Bool CHIPSPciProbe(DriverPtr drv, int entity_num, 147 struct pci_device *dev, intptr_t match_data); 148#ifdef HAVE_ISA 149static Bool CHIPSProbe(DriverPtr drv, int flags); 150#endif 151static Bool CHIPSPreInit(ScrnInfoPtr pScrn, int flags); 152static Bool CHIPSScreenInit(int Index, ScreenPtr pScreen, int argc, 153 char **argv); 154static Bool CHIPSEnterVT(int scrnIndex, int flags); 155static void CHIPSLeaveVT(int scrnIndex, int flags); 156static Bool CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen); 157static void CHIPSFreeScreen(int scrnIndex, int flags); 158static ModeStatus CHIPSValidMode(int scrnIndex, DisplayModePtr mode, 159 Bool verbose, int flags); 160static Bool CHIPSSaveScreen(ScreenPtr pScreen, int mode); 161 162/* Internally used functions */ 163static int chipsFindIsaDevice(GDevPtr dev); 164static Bool chipsClockSelect(ScrnInfoPtr pScrn, int no); 165Bool chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode); 166static void chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, 167 CHIPSRegPtr ChipsSave); 168static void chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, 169 CHIPSRegPtr ChipsReg, Bool restoreFonts); 170static void chipsLock(ScrnInfoPtr pScrn); 171static void chipsUnlock(ScrnInfoPtr pScrn); 172static void chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); 173static void chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock); 174static Bool chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode, 175 int no, CHIPSClockPtr Clock); 176static void chipsCalcClock(ScrnInfoPtr pScrn, int Clock, 177 unsigned char *vclk); 178static int chipsGetHWClock(ScrnInfoPtr pScrn); 179static Bool chipsPreInit655xx(ScrnInfoPtr pScrn, int flags); 180static Bool chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags); 181static Bool chipsPreInitWingine(ScrnInfoPtr pScrn, int flags); 182static int chipsSetMonitor(ScrnInfoPtr pScrn); 183static Bool chipsMapMem(ScrnInfoPtr pScrn); 184static Bool chipsUnmapMem(ScrnInfoPtr pScrn); 185static void chipsProtect(ScrnInfoPtr pScrn, Bool on); 186static void chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank); 187static void chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs); 188static void chipsRestoreStretching(ScrnInfoPtr pScrn, 189 unsigned char ctHorizontalStretch, 190 unsigned char ctVerticalStretch); 191static Bool chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode); 192static Bool chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode); 193static Bool chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode); 194static int chipsVideoMode(int vgaBitsPerPixel,int displayHSize, 195 int displayVSize); 196static void chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, 197 int PowerManagementMode, int flags); 198static void chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn); 199static void chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn); 200static void chipsFixResume(ScrnInfoPtr pScrn); 201static void chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, 202 int *indices, LOCO *colors, VisualPtr pVisual); 203static void chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, 204 int *indices, LOCO *colors, VisualPtr pVisual); 205static void chipsSetPanelType(CHIPSPtr cPtr); 206static void chipsBlockHandler(int, pointer, pointer, pointer); 207 208/* 209 * This is intentionally screen-independent. It indicates the binding 210 * choice made in the first PreInit. 211 */ 212static int pix24bpp = 0; 213 214/* 215 * Index of Entity 216 */ 217static int CHIPSEntityIndex = -1; 218 219 220/* Set the non-documented SAR04 register for overlay/video */ 221#define SAR04 222 223/* 224 * Initialise some arrays that are used in multiple instances of the 225 * acceleration code. Set them up here as its a convenient place to do it. 226 */ 227/* alu to C&T conversion for use with source data */ 228int ChipsAluConv[] = 229{ 230 0x00, /* dest = 0; GXclear, 0 */ 231 0x88, /* dest &= src; GXand, 0x1 */ 232 0x44, /* dest = src & ~dest; GXandReverse, 0x2 */ 233 0xCC, /* dest = src; GXcopy, 0x3 */ 234 0x22, /* dest &= ~src; GXandInverted, 0x4 */ 235 0xAA, /* dest = dest; GXnoop, 0x5 */ 236 0x66, /* dest = ^src; GXxor, 0x6 */ 237 0xEE, /* dest |= src; GXor, 0x7 */ 238 0x11, /* dest = ~src & ~dest;GXnor, 0x8 */ 239 0x99, /* dest ^= ~src ;GXequiv, 0x9 */ 240 0x55, /* dest = ~dest; GXInvert, 0xA */ 241 0xDD, /* dest = src|~dest ;GXorReverse, 0xB */ 242 0x33, /* dest = ~src; GXcopyInverted, 0xC */ 243 0xBB, /* dest |= ~src; GXorInverted, 0xD */ 244 0x77, /* dest = ~src|~dest ;GXnand, 0xE */ 245 0xFF, /* dest = 0xFF; GXset, 0xF */ 246}; 247 248/* alu to C&T conversion for use with pattern data */ 249int ChipsAluConv2[] = 250{ 251 0x00, /* dest = 0; GXclear, 0 */ 252 0xA0, /* dest &= src; GXand, 0x1 */ 253 0x50, /* dest = src & ~dest; GXandReverse, 0x2 */ 254 0xF0, /* dest = src; GXcopy, 0x3 */ 255 0x0A, /* dest &= ~src; GXandInverted, 0x4 */ 256 0xAA, /* dest = dest; GXnoop, 0x5 */ 257 0x5A, /* dest = ^src; GXxor, 0x6 */ 258 0xFA, /* dest |= src; GXor, 0x7 */ 259 0x05, /* dest = ~src & ~dest;GXnor, 0x8 */ 260 0xA5, /* dest ^= ~src ;GXequiv, 0x9 */ 261 0x55, /* dest = ~dest; GXInvert, 0xA */ 262 0xF5, /* dest = src|~dest ;GXorReverse, 0xB */ 263 0x0F, /* dest = ~src; GXcopyInverted, 0xC */ 264 0xAF, /* dest |= ~src; GXorInverted, 0xD */ 265 0x5F, /* dest = ~src|~dest ;GXnand, 0xE */ 266 0xFF, /* dest = 0xFF; GXset, 0xF */ 267}; 268 269/* alu to C&T conversion for use with pattern data as a planemask */ 270int ChipsAluConv3[] = 271{ 272 0x0A, /* dest = 0; GXclear, 0 */ 273 0x8A, /* dest &= src; GXand, 0x1 */ 274 0x4A, /* dest = src & ~dest; GXandReverse, 0x2 */ 275 0xCA, /* dest = src; GXcopy, 0x3 */ 276 0x2A, /* dest &= ~src; GXandInverted, 0x4 */ 277 0xAA, /* dest = dest; GXnoop, 0x5 */ 278 0x6A, /* dest = ^src; GXxor, 0x6 */ 279 0xEA, /* dest |= src; GXor, 0x7 */ 280 0x1A, /* dest = ~src & ~dest;GXnor, 0x8 */ 281 0x9A, /* dest ^= ~src ;GXequiv, 0x9 */ 282 0x5A, /* dest = ~dest; GXInvert, 0xA */ 283 0xDA, /* dest = src|~dest ;GXorReverse, 0xB */ 284 0x3A, /* dest = ~src; GXcopyInverted, 0xC */ 285 0xBA, /* dest |= ~src; GXorInverted, 0xD */ 286 0x7A, /* dest = ~src|~dest ;GXnand, 0xE */ 287 0xFA, /* dest = 0xFF; GXset, 0xF */ 288}; 289 290/* The addresses of the acceleration registers */ 291unsigned int ChipsReg32HiQV[] = 292{ 293 0x00, /* BR00 Source and Destination offset register */ 294 0x04, /* BR01 Color expansion background color */ 295 0x08, /* BR02 Color expansion foreground color */ 296 0x0C, /* BR03 Monochrome source control register */ 297 0x10, /* BR04 BitBLT control register */ 298 0x14, /* BR05 Pattern address register */ 299 0x18, /* BR06 Source address register */ 300 0x1C, /* BR07 Destination address register */ 301 0x20 /* BR08 Destination width and height register */ 302}; 303 304unsigned int ChipsReg32[] = 305{ 306 /*BitBLT */ 307 0x83D0, /*DR0 src/dest offset */ 308 0x87D0, /*DR1 BitBlt. address of freeVram? */ 309 0x8BD0, /*DR2 BitBlt. paintBrush, or tile pat.*/ 310 0x8FD0, /*DR3 */ 311 0x93D0, /*DR4 BitBlt. */ 312 0x97D0, /*DR5 BitBlt. srcAddr, or 0 in VRAM */ 313 0x9BD0, /*DR6 BitBlt. dest? */ 314 0x9FD0, /*DR7 BitBlt. width << 16 | height */ 315 /*H/W cursor */ 316 0xA3D0, /*DR8 write/erase cursor */ 317 /*bit 0-1 if 0 cursor is not shown 318 * if 1 32x32 cursor 319 * if 2 64x64 cursor 320 * if 3 128x128 cursor 321 */ 322 /* bit 7 if 1 cursor is not shown */ 323 /* bit 9 cursor expansion in X */ 324 /* bit 10 cursor expansion in Y */ 325 0xA7D0, /* DR9 foreGroundCursorColor */ 326 0xABD0, /* DR0xA backGroundCursorColor */ 327 0xAFD0, /* DR0xB cursorPosition */ 328 /* bit 0-7 x coordinate */ 329 /* bit 8-14 0 */ 330 /* bit 15 x signum */ 331 /* bit 16-23 y coordinate */ 332 /* bit 24-30 0 */ 333 /* bit 31 y signum */ 334 0xB3D0, /* DR0xC address of cursor pattern */ 335}; 336 337#if defined(__arm__) && defined(__NetBSD__) 338/* 339 * Built in TV output modes: These modes have been tested on NetBSD with 340 * CT65550 and StrongARM. They give what seems to be the best output for 341 * a roughly 640x480 display. To enable one of the built in modes, add 342 * the identifier "NTSC" or "PAL" to the list of modes in the appropriate 343 * "Display" subsection of the "Screen" section in the XF86Config file. 344 * Note that the call to xf86SetTVOut(), which tells the kernel to enable 345 * TV output results in hardware specific actions. There must be code to 346 * support this in the kernel or TV output won't work. 347 */ 348static DisplayModeRec ChipsPALMode = { 349 NULL, NULL, /* prev, next */ 350 "PAL", /* identifier of this mode */ 351 MODE_OK, /* mode status */ 352 M_T_BUILTIN, /* mode type */ 353 15000, /* Clock frequency */ 354 776, /* HDisplay */ 355 800, /* HSyncStart */ 356 872, /* HSyncEnd */ 357 960, /* HTotal */ 358 0, /* HSkew */ 359 585, /* VDisplay */ 360 590, /* VSyncStart */ 361 595, /* VSyncEnd */ 362 625, /* VTotal */ 363 0, /* VScan */ 364 V_INTERLACE, /* Flags */ 365 -1, /* ClockIndex */ 366 15000, /* SynthClock */ 367 776, /* CRTC HDisplay */ 368 800, /* CRTC HBlankStart */ 369 800, /* CRTC HSyncStart */ 370 872, /* CRTC HSyncEnd */ 371 872, /* CRTC HBlankEnd */ 372 960, /* CRTC HTotal */ 373 0, /* CRTC HSkew */ 374 585, /* CRTC VDisplay */ 375 590, /* CRTC VBlankStart */ 376 590, /* CRTC VSyncStart */ 377 595, /* CRTC VSyncEnd */ 378 595, /* CRTC VBlankEnd */ 379 625, /* CRTC VTotal */ 380 FALSE, /* CrtcHAdjusted */ 381 FALSE, /* CrtcVAdjusted */ 382 0, /* PrivSize */ 383 NULL, /* Private */ 384 0.0, /* HSync */ 385 0.0 /* VRefresh */ 386}; 387 388/* 389** So far, it looks like SECAM uses the same values as PAL 390*/ 391static DisplayModeRec ChipsSECAMMode = { 392 NULL, /* prev */ 393 &ChipsPALMode, /* next */ 394 "SECAM", /* identifier of this mode */ 395 MODE_OK, /* mode status */ 396 M_T_BUILTIN, /* mode type */ 397 15000, /* Clock frequency */ 398 776, /* HDisplay */ 399 800, /* HSyncStart */ 400 872, /* HSyncEnd */ 401 960, /* HTotal */ 402 0, /* HSkew */ 403 585, /* VDisplay */ 404 590, /* VSyncStart */ 405 595, /* VSyncEnd */ 406 625, /* VTotal */ 407 0, /* VScan */ 408 V_INTERLACE, /* Flags */ 409 -1, /* ClockIndex */ 410 15000, /* SynthClock */ 411 776, /* CRTC HDisplay */ 412 800, /* CRTC HBlankStart */ 413 800, /* CRTC HSyncStart */ 414 872, /* CRTC HSyncEnd */ 415 872, /* CRTC HBlankEnd */ 416 960, /* CRTC HTotal */ 417 0, /* CRTC HSkew */ 418 585, /* CRTC VDisplay */ 419 590, /* CRTC VBlankStart */ 420 590, /* CRTC VSyncStart */ 421 595, /* CRTC VSyncEnd */ 422 595, /* CRTC VBlankEnd */ 423 625, /* CRTC VTotal */ 424 FALSE, /* CrtcHAdjusted */ 425 FALSE, /* CrtcVAdjusted */ 426 0, /* PrivSize */ 427 NULL, /* Private */ 428 0.0, /* HSync */ 429 0.0 /* VRefresh */ 430}; 431 432 433static DisplayModeRec ChipsNTSCMode = { 434 NULL, /* prev */ 435 &ChipsSECAMMode,/* next */ 436 "NTSC", /* identifier of this mode */ 437 MODE_OK, /* mode status */ 438 M_T_BUILTIN, /* mode type */ 439 11970, /* Clock frequency */ 440 584, /* HDisplay */ 441 640, /* HSyncStart */ 442 696, /* HSyncEnd */ 443 760, /* HTotal */ 444 0, /* HSkew */ 445 450, /* VDisplay */ 446 479, /* VSyncStart */ 447 485, /* VSyncEnd */ 448 525, /* VTotal */ 449 0, /* VScan */ 450 V_INTERLACE | V_NVSYNC | V_NHSYNC , /* Flags */ 451 -1, /* ClockIndex */ 452 11970, /* SynthClock */ 453 584, /* CRTC HDisplay */ 454 640, /* CRTC HBlankStart */ 455 640, /* CRTC HSyncStart */ 456 696, /* CRTC HSyncEnd */ 457 696, /* CRTC HBlankEnd */ 458 760, /* CRTC HTotal */ 459 0, /* CRTC HSkew */ 460 450, /* CRTC VDisplay */ 461 479, /* CRTC VBlankStart */ 462 479, /* CRTC VSyncStart */ 463 485, /* CRTC VSyncEnd */ 464 485, /* CRTC VBlankEnd */ 465 525, /* CRTC VTotal */ 466 FALSE, /* CrtcHAdjusted */ 467 FALSE, /* CrtcVAdjusted */ 468 0, /* PrivSize */ 469 NULL, /* Private */ 470 0.0, /* HSync */ 471 0.0 /* VRefresh */ 472}; 473#endif 474 475#define CHIPS_VERSION 4000 476#define CHIPS_NAME "CHIPS" 477#define CHIPS_DRIVER_NAME "chips" 478#define CHIPS_MAJOR_VERSION PACKAGE_VERSION_MAJOR 479#define CHIPS_MINOR_VERSION PACKAGE_VERSION_MINOR 480#define CHIPS_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 481 482 483#ifdef XSERVER_LIBPCIACCESS 484 485#define CHIPS_DEVICE_MATCH(d, i) \ 486 { PCI_VENDOR_CHIPSTECH, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) } 487 488static const struct pci_id_match chips_device_match[] = { 489 CHIPS_DEVICE_MATCH(PCI_CHIP_65545, CHIPS_CT65545), 490 CHIPS_DEVICE_MATCH(PCI_CHIP_65548, CHIPS_CT65548), 491 CHIPS_DEVICE_MATCH(PCI_CHIP_65550, CHIPS_CT65550), 492 CHIPS_DEVICE_MATCH(PCI_CHIP_65554, CHIPS_CT65554), 493 CHIPS_DEVICE_MATCH(PCI_CHIP_65555, CHIPS_CT65555), 494 CHIPS_DEVICE_MATCH(PCI_CHIP_68554, CHIPS_CT68554), 495 CHIPS_DEVICE_MATCH(PCI_CHIP_69000, CHIPS_CT69000), 496 CHIPS_DEVICE_MATCH(PCI_CHIP_69030, CHIPS_CT69030), 497 { 0, 0, 0 }, 498}; 499#endif 500 501/* 502 * This contains the functions needed by the server after loading the driver 503 * module. It must be supplied, and gets passed back by the SetupProc 504 * function in the dynamic case. In the static case, a reference to this 505 * is compiled in, and this requires that the name of this DriverRec be 506 * an upper-case version of the driver name. 507 */ 508 509_X_EXPORT DriverRec CHIPS = { 510 CHIPS_VERSION, 511 CHIPS_DRIVER_NAME, 512 CHIPSIdentify, 513#ifdef HAVE_ISA 514 CHIPSProbe, 515#else 516 NULL, 517#endif 518 CHIPSAvailableOptions, 519 NULL, 520 0, 521 NULL, 522 523#ifdef XSERVER_LIBPCIACCESS 524 chips_device_match, 525 CHIPSPciProbe, 526#endif 527}; 528 529static SymTabRec CHIPSChipsets[] = { 530 { CHIPS_CT65520, "ct65520" }, 531 { CHIPS_CT65525, "ct65525" }, 532 { CHIPS_CT65530, "ct65530" }, 533 { CHIPS_CT65535, "ct65535" }, 534 { CHIPS_CT65540, "ct65540" }, 535 { CHIPS_CT65545, "ct65545" }, 536 { CHIPS_CT65546, "ct65546" }, 537 { CHIPS_CT65548, "ct65548" }, 538 { CHIPS_CT65550, "ct65550" }, 539 { CHIPS_CT65554, "ct65554" }, 540 { CHIPS_CT65555, "ct65555" }, 541 { CHIPS_CT68554, "ct68554" }, 542 { CHIPS_CT69000, "ct69000" }, 543 { CHIPS_CT69030, "ct69030" }, 544 { CHIPS_CT64200, "ct64200" }, 545 { CHIPS_CT64300, "ct64300" }, 546 { -1, NULL } 547}; 548 549 550/* Conversion PCI ID to chipset name */ 551static PciChipsets CHIPSPCIchipsets[] = { 552 { CHIPS_CT65545, PCI_CHIP_65545, RES_SHARED_VGA }, 553 { CHIPS_CT65548, PCI_CHIP_65548, RES_SHARED_VGA }, 554 { CHIPS_CT65550, PCI_CHIP_65550, RES_SHARED_VGA }, 555 { CHIPS_CT65554, PCI_CHIP_65554, RES_SHARED_VGA }, 556 { CHIPS_CT65555, PCI_CHIP_65555, RES_SHARED_VGA }, 557 { CHIPS_CT68554, PCI_CHIP_68554, RES_SHARED_VGA }, 558 { CHIPS_CT69000, PCI_CHIP_69000, RES_SHARED_VGA }, 559 { CHIPS_CT69030, PCI_CHIP_69030, RES_SHARED_VGA }, 560 { -1, -1, RES_UNDEFINED} 561}; 562 563/* The options supported by the Chips and Technologies Driver */ 564typedef enum { 565 OPTION_LINEAR, 566 OPTION_NOACCEL, 567 OPTION_HW_CLKS, 568 OPTION_SW_CURSOR, 569 OPTION_HW_CURSOR, 570 OPTION_STN, 571 OPTION_USE_MODELINE, 572 OPTION_LCD_STRETCH, 573 OPTION_LCD_CENTER, 574 OPTION_MMIO, 575 OPTION_FULL_MMIO, 576 OPTION_SUSPEND_HACK, 577 OPTION_RGB_BITS, 578 OPTION_SYNC_ON_GREEN, 579 OPTION_PANEL_SIZE, 580 OPTION_18_BIT_BUS, 581 OPTION_SHOWCACHE, 582 OPTION_SHADOW_FB, 583 OPTION_OVERLAY, 584 OPTION_COLOR_KEY, 585 OPTION_VIDEO_KEY, 586 OPTION_FP_CLOCK_8, 587 OPTION_FP_CLOCK_16, 588 OPTION_FP_CLOCK_24, 589 OPTION_FP_CLOCK_32, 590 OPTION_SET_MCLK, 591 OPTION_ROTATE, 592 OPTION_NO_TMED, 593 OPTION_CRT2_MEM, 594 OPTION_DUAL_REFRESH, 595 OPTION_CRT_CLK_INDX, 596 OPTION_FP_CLK_INDX, 597 OPTION_FP_MODE 598} CHIPSOpts; 599 600static const OptionInfoRec Chips655xxOptions[] = { 601 { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, 602 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 603 { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, 604 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 605 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 606 { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, 607 { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, 608 { OPTION_LCD_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE }, 609 { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 610 { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, 611 { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, 612 { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, 613#if 0 614 { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, 615#endif 616 { OPTION_18_BIT_BUS, "18BitBus", OPTV_BOOLEAN, {0}, FALSE }, 617 { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 618 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 619 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 620 { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, 621 { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, 622 { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, 623 { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, 624 { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, 625 { -1, NULL, OPTV_NONE, {0}, FALSE } 626}; 627 628static const OptionInfoRec ChipsWingineOptions[] = { 629 { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, 630 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 631 { OPTION_HW_CLKS, "HWclocks", OPTV_BOOLEAN, {0}, FALSE }, 632 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 633 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 634#if 0 635 { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, 636#endif 637 { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 638 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 639 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 640 { -1, NULL, OPTV_NONE, {0}, FALSE } 641}; 642 643static const OptionInfoRec ChipsHiQVOptions[] = { 644 { OPTION_LINEAR, "Linear", OPTV_BOOLEAN, {0}, FALSE }, 645 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 646 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 647 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 648 { OPTION_STN, "STN", OPTV_BOOLEAN, {0}, FALSE }, 649 { OPTION_USE_MODELINE, "UseModeline", OPTV_BOOLEAN, {0}, FALSE }, 650 { OPTION_LCD_STRETCH, "Stretch", OPTV_BOOLEAN, {0}, FALSE }, 651 { OPTION_LCD_CENTER, "LcdCenter", OPTV_BOOLEAN, {0}, FALSE }, 652 { OPTION_MMIO, "MMIO", OPTV_BOOLEAN, {0}, FALSE }, 653 { OPTION_FULL_MMIO, "FullMMIO", OPTV_BOOLEAN, {0}, FALSE }, 654 { OPTION_SUSPEND_HACK, "SuspendHack", OPTV_BOOLEAN, {0}, FALSE }, 655 { OPTION_PANEL_SIZE, "FixPanelSize", OPTV_BOOLEAN, {0}, FALSE }, 656 { OPTION_RGB_BITS, "RGBbits", OPTV_INTEGER, {0}, FALSE }, 657 { OPTION_SYNC_ON_GREEN, "SyncOnGreen", OPTV_BOOLEAN, {0}, FALSE }, 658 { OPTION_SHOWCACHE, "ShowCache", OPTV_BOOLEAN, {0}, FALSE }, 659 { OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE }, 660 { OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE }, 661 { OPTION_OVERLAY, "Overlay", OPTV_ANYSTR, {0}, FALSE }, 662 { OPTION_COLOR_KEY, "ColorKey", OPTV_INTEGER, {0}, FALSE }, 663 { OPTION_VIDEO_KEY, "VideoKey", OPTV_INTEGER, {0}, FALSE }, 664 { OPTION_FP_CLOCK_8, "FPClock8", OPTV_FREQ, {0}, FALSE }, 665 { OPTION_FP_CLOCK_16, "FPClock16", OPTV_FREQ, {0}, FALSE }, 666 { OPTION_FP_CLOCK_24, "FPClock24", OPTV_FREQ, {0}, FALSE }, 667 { OPTION_FP_CLOCK_32, "FPClock32", OPTV_FREQ, {0}, FALSE }, 668 { OPTION_SET_MCLK, "SetMclk", OPTV_FREQ, {0}, FALSE }, 669 { OPTION_NO_TMED, "NoTMED", OPTV_BOOLEAN, {0}, FALSE }, 670 { OPTION_CRT2_MEM, "Crt2Memory", OPTV_INTEGER, {0}, FALSE }, 671 { OPTION_DUAL_REFRESH, "DualRefresh", OPTV_BOOLEAN, {0}, FALSE }, 672 { OPTION_CRT_CLK_INDX, "CrtClkIndx", OPTV_INTEGER, {0}, FALSE }, 673 { OPTION_FP_CLK_INDX, "FPClkIndx", OPTV_INTEGER, {0}, FALSE }, 674 { OPTION_FP_MODE, "FPMode", OPTV_BOOLEAN, {0}, FALSE }, 675 { -1, NULL, OPTV_NONE, {0}, FALSE } 676}; 677 678#ifdef XFree86LOADER 679 680static MODULESETUPPROTO(chipsSetup); 681 682static XF86ModuleVersionInfo chipsVersRec = 683{ 684 "chips", 685 MODULEVENDORSTRING, 686 MODINFOSTRING1, 687 MODINFOSTRING2, 688 XORG_VERSION_CURRENT, 689 CHIPS_MAJOR_VERSION, CHIPS_MINOR_VERSION, CHIPS_PATCHLEVEL, 690 ABI_CLASS_VIDEODRV, 691 ABI_VIDEODRV_VERSION, 692 MOD_CLASS_VIDEODRV, 693 {0,0,0,0} 694}; 695 696/* 697 * This is the module init data. 698 * Its name has to be the driver name followed by ModuleData 699 */ 700_X_EXPORT XF86ModuleData chipsModuleData = { &chipsVersRec, chipsSetup, NULL }; 701 702static pointer 703chipsSetup(pointer module, pointer opts, int *errmaj, int *errmin) 704{ 705 static Bool setupDone = FALSE; 706 707 if (!setupDone) { 708 setupDone = TRUE; 709 xf86AddDriver(&CHIPS, module, HaveDriverFuncs); 710 711 /* 712 * Modules that this driver always requires can be loaded here 713 * by calling LoadSubModule(). 714 */ 715 716 /* 717 * The return value must be non-NULL on success even though there 718 * is no TearDownProc. 719 */ 720 return (pointer)1; 721 } else { 722 if (errmaj) *errmaj = LDR_ONCEONLY; 723 return NULL; 724 } 725} 726 727#endif /* XFree86LOADER */ 728 729static Bool 730CHIPSGetRec(ScrnInfoPtr pScrn) 731{ 732 /* 733 * Allocate a CHIPSRec, and hook it into pScrn->driverPrivate. 734 * pScrn->driverPrivate is initialised to NULL, so we can check if 735 * the allocation has already been done. 736 */ 737 if (pScrn->driverPrivate != NULL) 738 return TRUE; 739 740 pScrn->driverPrivate = xnfcalloc(sizeof(CHIPSRec), 1); 741 742 if (pScrn->driverPrivate == NULL) 743 return FALSE; 744 745 return TRUE; 746} 747 748static void 749CHIPSFreeRec(ScrnInfoPtr pScrn) 750{ 751 if (pScrn->driverPrivate == NULL) 752 return; 753 xfree(pScrn->driverPrivate); 754 pScrn->driverPrivate = NULL; 755} 756 757/* Mandatory */ 758static void 759CHIPSIdentify(int flags) 760{ 761 xf86PrintChipsets(CHIPS_NAME, "Driver for Chips and Technologies chipsets", 762 CHIPSChipsets); 763} 764 765static const OptionInfoRec * 766CHIPSAvailableOptions(int chipid, int busid) 767{ 768 int chip = chipid & 0x0000ffff; 769 770#ifdef HAVE_ISA 771 if (busid == BUS_ISA) { 772 if ((chip == CHIPS_CT64200) || (chip == CHIPS_CT64300)) 773 return ChipsWingineOptions; 774 } 775#endif 776 if (busid == BUS_PCI) { 777 if ((chip >= CHIPS_CT65550) && (chip <= CHIPS_CT69030)) 778 return ChipsHiQVOptions; 779 } 780 return Chips655xxOptions; 781} 782 783/* Mandatory */ 784Bool 785CHIPSPciProbe(DriverPtr drv, int entity_num, struct pci_device * dev, 786 intptr_t match_data) 787{ 788 ScrnInfoPtr pScrn = NULL; 789 CHIPSPtr cPtr; 790 791 /* Allocate a ScrnInfoRec and claim the slot */ 792 pScrn = xf86ConfigPciEntity(pScrn, 0, entity_num, CHIPSPCIchipsets, NULL, 793 NULL, NULL, NULL, NULL); 794 if (pScrn != NULL) { 795 /* Fill in what we can of the ScrnInfoRec */ 796 pScrn->driverVersion = CHIPS_VERSION; 797 pScrn->driverName = CHIPS_DRIVER_NAME; 798 pScrn->name = CHIPS_NAME; 799 pScrn->Probe = NULL; 800 pScrn->PreInit = CHIPSPreInit; 801 pScrn->ScreenInit = CHIPSScreenInit; 802 pScrn->SwitchMode = CHIPSSwitchMode; 803 pScrn->AdjustFrame = CHIPSAdjustFrame; 804 pScrn->EnterVT = CHIPSEnterVT; 805 pScrn->LeaveVT = CHIPSLeaveVT; 806 pScrn->FreeScreen = CHIPSFreeScreen; 807 pScrn->ValidMode = CHIPSValidMode; 808 809 if (!CHIPSGetRec(pScrn)) { 810 return; 811 } 812 cPtr = CHIPSPTR(pScrn); 813 cPtr->Chipset = match_data; 814 /* 815 * For cards that can do dual head per entity, mark the entity 816 * as sharable. 817 */ 818 if (match_data == CHIPS_CT69030) { 819 CHIPSEntPtr cPtrEnt = NULL; 820 DevUnion *pPriv; 821 822 xf86SetEntitySharable(entity_num); 823 /* Allocate an entity private if necessary */ 824 if (CHIPSEntityIndex < 0) 825 CHIPSEntityIndex = xf86AllocateEntityPrivateIndex(); 826 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); 827 if (!pPriv->ptr) { 828 pPriv->ptr = xnfcalloc(sizeof(CHIPSEntRec), 1); 829 cPtrEnt = pPriv->ptr; 830 cPtrEnt->lastInstance = -1; 831 } else { 832 cPtrEnt = pPriv->ptr; 833 } 834 /* 835 * Set the entity instance for this instance of the driver. For 836 * dual head per card, instance 0 is the "master" instance, driving 837 * the primary head, and instance 1 is the "slave". 838 */ 839 cPtrEnt->lastInstance++; 840 xf86SetEntityInstanceForScreen(pScrn, pScrn->entityList[0], 841 cPtrEnt->lastInstance); 842 } 843 } 844 845 return (pScrn != NULL); 846} 847 848#ifdef HAVE_ISA 849static Bool 850CHIPSProbe(DriverPtr drv, int flags) 851{ 852 ScrnInfoPtr pScrn = NULL; 853 CHIPSPtr cPtr; 854 Bool foundScreen = FALSE; 855 int numDevSections, numUsed; 856 GDevPtr *devSections; 857 int *usedChips; 858 int i, chipset, entity; 859 860 /* 861 * Find the config file Device sections that match this 862 * driver, and return if there are none. 863 */ 864 if ((numDevSections = xf86MatchDevice(CHIPS_DRIVER_NAME, 865 &devSections)) <= 0) { 866 return FALSE; 867 } 868 869 /* Isa Bus */ 870 if ((numDevSections = 871 xf86MatchDevice(CHIPS_DRIVER_NAME, &devSections)) > 0) { 872 for (i = 0; i < numDevSections; i++) { 873 if ((chipset = chipsFindIsaDevice(devSections[i])) > -1) { 874 if ( xf86DoConfigure && xf86DoConfigurePass1 ) { 875 xf86AddBusDeviceToConfigure(CHIPS_DRIVER_NAME, BUS_ISA, 876 NULL, chipset); 877 } 878 if (flags & PROBE_DETECT) { 879 return TRUE; 880 } 881 if (!xf86CheckStrOption(devSections[i]->options, "BusID", 882 "ISA")) { 883 continue; 884 } 885 886 pScrn = NULL; 887 entity = xf86ClaimFbSlot(drv, 0, devSections[i], TRUE); 888 pScrn = xf86ConfigFbEntity(NULL, 0, entity, NULL, NULL, 889 NULL, NULL); 890 pScrn->driverVersion = CHIPS_VERSION; 891 pScrn->driverName = CHIPS_DRIVER_NAME; 892 pScrn->name = CHIPS_NAME; 893 pScrn->Probe = CHIPSProbe; 894 pScrn->PreInit = CHIPSPreInit; 895 pScrn->ScreenInit = CHIPSScreenInit; 896 pScrn->SwitchMode = CHIPSSwitchMode; 897 pScrn->AdjustFrame = CHIPSAdjustFrame; 898 pScrn->EnterVT = CHIPSEnterVT; 899 pScrn->LeaveVT = CHIPSLeaveVT; 900 pScrn->FreeScreen = CHIPSFreeScreen; 901 pScrn->ValidMode = CHIPSValidMode; 902 if (!CHIPSGetRec(pScrn)) { 903 return; 904 } 905 cPtr = CHIPSPTR(pScrn); 906 cPtr->Chipset = chipset; 907 } 908 } 909 } 910 911 xfree(devSections); 912 return foundScreen; 913} 914 915static int 916chipsFindIsaDevice(GDevPtr dev) 917{ 918 int found = -1; 919 unsigned char tmp; 920 921 /* 922 * This function has the only direct register access in the C&T driver. 923 * All other register access through functions to allow for full MMIO. 924 */ 925 outb(0x3D6, 0x00); 926 tmp = inb(0x3D7); 927 928 switch (tmp & 0xF0) { 929 case 0x70: /* CT65520 */ 930 found = CHIPS_CT65520; break; 931 case 0x80: /* CT65525 or CT65530 */ 932 found = CHIPS_CT65530; break; 933 case 0xA0: /* CT64200 */ 934 found = CHIPS_CT64200; break; 935 case 0xB0: /* CT64300 */ 936 found = CHIPS_CT64300; break; 937 case 0xC0: /* CT65535 */ 938 found = CHIPS_CT65535; break; 939 default: 940 switch (tmp & 0xF8) { 941 case 0xD0: /* CT65540 */ 942 found = CHIPS_CT65540; break; 943 case 0xD8: /* CT65545 or CT65546 or CT65548 */ 944 switch (tmp & 7) { 945 case 3: 946 found = CHIPS_CT65546; break; 947 case 4: 948 found = CHIPS_CT65548; break; 949 default: 950 found = CHIPS_CT65545; break; 951 952 } 953 break; 954 default: 955 if (tmp == 0x2C) { 956 outb(0x3D6, 0x01); 957 tmp = inb(0x3D7); 958 if (tmp != 0x10) break; 959 outb(0x3D6, 0x02); 960 tmp = inb(0x3D7); 961 switch (tmp) { 962 case 0xE0: /* CT65550 */ 963 found = CHIPS_CT65550; break; 964 case 0xE4: /* CT65554 */ 965 found = CHIPS_CT65554; break; 966 case 0xE5: /* CT65555 */ 967 found = CHIPS_CT65555; break; 968 case 0xF4: /* CT68554 */ 969 found = CHIPS_CT68554; break; 970 case 0xC0: /* CT69000 */ 971 found = CHIPS_CT69000; break; 972 case 0x30: /* CT69030 */ 973 outb(0x3D6, 0x03); 974 tmp = inb(0x3D7); 975 if (tmp == 0xC) 976 found = CHIPS_CT69030; 977 break; 978 default: 979 break; 980 } 981 } 982 break; 983 } 984 break; 985 } 986 /* We only want ISA/VL Bus - so check for PCI Bus */ 987 if(found > CHIPS_CT65548) { 988 outb(0x3D6, 0x08); 989 tmp = inb(0x3D7); 990 if(tmp & 0x01) found = -1; 991 } else if(found > CHIPS_CT65535) { 992 outb(0x3D6, 0x01); 993 tmp = inb(0x3D7); 994 if ((tmp & 0x07) == 0x06) found = -1; 995 } 996 return found; 997} 998#endif 999 1000/* Mandatory */ 1001Bool 1002CHIPSPreInit(ScrnInfoPtr pScrn, int flags) 1003{ 1004 pciVideoPtr pciPtr; 1005 ClockRangePtr clockRanges; 1006 int i; 1007 CHIPSPtr cPtr; 1008 Bool res = FALSE; 1009 CHIPSEntPtr cPtrEnt = NULL; 1010 1011 if (flags & PROBE_DETECT) return FALSE; 1012 1013 /* The vgahw module should be loaded here when needed */ 1014 if (!xf86LoadSubModule(pScrn, "vgahw")) 1015 return FALSE; 1016 1017 /* Allocate the ChipsRec driverPrivate */ 1018 if (!CHIPSGetRec(pScrn)) { 1019 return FALSE; 1020 } 1021 cPtr = CHIPSPTR(pScrn); 1022 1023 /* XXX Check the number of entities, and fail if it isn't one. */ 1024 if (pScrn->numEntities != 1) 1025 return FALSE; 1026 1027 /* Since the capabilities are determined by the chipset the very 1028 * first thing to do is, figure out the chipset and its capabilities 1029 */ 1030 1031 /* This is the general case */ 1032 for (i = 0; i<pScrn->numEntities; i++) { 1033 cPtr->pEnt = xf86GetEntityInfo(pScrn->entityList[i]); 1034#ifndef XSERVER_LIBPCIACCESS 1035 if (cPtr->pEnt->resources) return FALSE; 1036#endif 1037 /* If we are using libpciaccess this is already set in CHIPSPciProbe. 1038 * If we are using something else we need to set it here. 1039 */ 1040 if (!cPtr->Chipset) 1041 cPtr->Chipset = cPtr->pEnt->chipset; 1042 pScrn->chipset = (char *)xf86TokenToString(CHIPSChipsets, 1043 cPtr->pEnt->chipset); 1044 if ((cPtr->Chipset == CHIPS_CT64200) || 1045 (cPtr->Chipset == CHIPS_CT64300)) cPtr->Flags |= ChipsWingine; 1046 if ((cPtr->Chipset >= CHIPS_CT65550) && 1047 (cPtr->Chipset <= CHIPS_CT69030)) cPtr->Flags |= ChipsHiQV; 1048 1049 /* This driver can handle ISA and PCI buses */ 1050 if (cPtr->pEnt->location.type == BUS_PCI) { 1051 pciPtr = xf86GetPciInfoForEntity(cPtr->pEnt->index); 1052 cPtr->PciInfo = pciPtr; 1053#ifndef XSERVER_LIBPCIACCESS 1054 cPtr->PciTag = pciTag(cPtr->PciInfo->bus, 1055 cPtr->PciInfo->device, 1056 cPtr->PciInfo->func); 1057#endif 1058 } 1059 } 1060 /* INT10 */ 1061#if 0 1062 if (xf86LoadSubModule(pScrn, "int10")) { 1063 xf86Int10InfoPtr pInt; 1064#if 1 1065 xf86DrvMsg(pScrn->scrnIndex,X_INFO,"initializing int10\n"); 1066 pInt = xf86InitInt10(cPtr->pEnt->index); 1067 xf86FreeInt10(pInt); 1068#endif 1069 } 1070#endif 1071 1072 if (xf86LoadSubModule(pScrn, "vbe")) { 1073 cPtr->pVbe = VBEInit(NULL,cPtr->pEnt->index); 1074 } 1075 1076 /* Now that we've identified the chipset, setup the capabilities flags */ 1077 switch (cPtr->Chipset) { 1078 case CHIPS_CT69030: 1079 cPtr->Flags |= ChipsDualChannelSupport; 1080 case CHIPS_CT69000: 1081 cPtr->Flags |= ChipsFullMMIOSupport; 1082 /* Fall through */ 1083 case CHIPS_CT65555: 1084 cPtr->Flags |= ChipsImageReadSupport; /* Does the 69000 support it? */ 1085 /* Fall through */ 1086 case CHIPS_CT68554: 1087 cPtr->Flags |= ChipsTMEDSupport; 1088 /* Fall through */ 1089 case CHIPS_CT65554: 1090 case CHIPS_CT65550: 1091 cPtr->Flags |= ChipsGammaSupport; 1092 cPtr->Flags |= ChipsVideoSupport; 1093 /* Fall through */ 1094 case CHIPS_CT65548: 1095 case CHIPS_CT65546: 1096 case CHIPS_CT65545: 1097 cPtr->Flags |= ChipsMMIOSupport; 1098 /* Fall through */ 1099 case CHIPS_CT64300: 1100 cPtr->Flags |= ChipsAccelSupport; 1101 /* Fall through */ 1102 case CHIPS_CT65540: 1103 cPtr->Flags |= ChipsHDepthSupport; 1104 cPtr->Flags |= ChipsDPMSSupport; 1105 /* Fall through */ 1106 case CHIPS_CT65535: 1107 case CHIPS_CT65530: 1108 case CHIPS_CT65525: 1109 cPtr->Flags |= ChipsLinearSupport; 1110 /* Fall through */ 1111 case CHIPS_CT64200: 1112 case CHIPS_CT65520: 1113 break; 1114 } 1115 1116 /* Check for shared entities */ 1117 if (xf86IsEntityShared(pScrn->entityList[0])) { 1118 if (!(cPtr->Flags & ChipsDualChannelSupport)) 1119 return FALSE; 1120 1121 /* Make sure entity is PCI for now, though this might not be needed. */ 1122 if (cPtr->pEnt->location.type != BUS_PCI) 1123 return FALSE; 1124 1125 /* Allocate an entity private if necessary */ 1126 if (xf86IsEntityShared(pScrn->entityList[0])) { 1127 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 1128 CHIPSEntityIndex)->ptr; 1129 cPtr->entityPrivate = cPtrEnt; 1130 } 1131#if 0 1132 /* Set cPtr->device to the relevant Device section */ 1133 cPtr->device = xf86GetDevFromEntity(pScrn->entityList[0], 1134 pScrn->entityInstanceList[0]); 1135#endif 1136 } 1137 1138 /* Set the driver to use the PIO register functions by default */ 1139 CHIPSSetStdExtFuncs(cPtr); 1140 1141 /* Call the device specific PreInit */ 1142 if (IS_HiQV(cPtr)) 1143 res = chipsPreInitHiQV(pScrn, flags); 1144 else if (IS_Wingine(cPtr)) 1145 res = chipsPreInitWingine(pScrn, flags); 1146 else 1147 res = chipsPreInit655xx(pScrn, flags); 1148 1149 if (cPtr->UseFullMMIO) 1150 chipsUnmapMem(pScrn); 1151 1152 if (!res) { 1153 vbeFree(cPtr->pVbe); 1154 cPtr->pVbe = NULL; 1155 return FALSE; 1156 } 1157 1158/*********/ 1159 /* 1160 * Setup the ClockRanges, which describe what clock ranges are available, 1161 * and what sort of modes they can be used for. 1162 */ 1163 clockRanges = xnfcalloc(sizeof(ClockRange), 1); 1164 clockRanges->next = NULL; 1165 clockRanges->ClockMulFactor = cPtr->ClockMulFactor; 1166 clockRanges->minClock = cPtr->MinClock; 1167 clockRanges->maxClock = cPtr->MaxClock; 1168 clockRanges->clockIndex = -1; /* programmable */ 1169 if (cPtr->PanelType & ChipsLCD) { 1170 clockRanges->interlaceAllowed = FALSE; 1171 clockRanges->doubleScanAllowed = FALSE; 1172 } else { 1173 clockRanges->interlaceAllowed = TRUE; 1174 clockRanges->doubleScanAllowed = TRUE; 1175 } 1176 /* 1177 * Reduce the amount of video ram for the modes, so that they 1178 * don't overlap with the DSTN framebuffer 1179 */ 1180 pScrn->videoRam -= (cPtr->FrameBufferSize + 1023) / 1024; 1181 1182 cPtr->Rounding = 8 * (pScrn->bitsPerPixel <= 8 ? 8 1183 : pScrn->bitsPerPixel); 1184 1185 i = xf86ValidateModes(pScrn, pScrn->monitor->Modes, 1186 pScrn->display->modes, clockRanges, 1187 NULL, 256, 2048, cPtr->Rounding, 1188 128, 2048, pScrn->display->virtualX, 1189 pScrn->display->virtualY, cPtr->FbMapSize, 1190 LOOKUP_BEST_REFRESH); 1191 1192 if (i == -1) { 1193 vbeFree(cPtr->pVbe); 1194 cPtr->pVbe = NULL; 1195 CHIPSFreeRec(pScrn); 1196 return FALSE; 1197 } 1198 1199 /* 1200 * Put the DSTN framebuffer back into the video ram 1201 */ 1202 pScrn->videoRam += (cPtr->FrameBufferSize + 1023) / 1024; 1203 1204 /* Prune the modes marked as invalid */ 1205 xf86PruneDriverModes(pScrn); 1206 1207 if (i == 0 || pScrn->modes == NULL) { 1208 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n"); 1209 vbeFree(cPtr->pVbe); 1210 cPtr->pVbe = NULL; 1211 CHIPSFreeRec(pScrn); 1212 return FALSE; 1213 } 1214 1215 /* 1216 * Set the CRTC parameters for all of the modes based on the type 1217 * of mode, and the chipset's interlace requirements. 1218 * 1219 * Calling this is required if the mode->Crtc* values are used by the 1220 * driver and if the driver doesn't provide code to set them. They 1221 * are not pre-initialised at all. 1222 */ 1223 xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V); 1224 1225 /* Set the current mode to the first in the list */ 1226 pScrn->currentMode = pScrn->modes; 1227 1228 /* Print the list of modes being used */ 1229 xf86PrintModes(pScrn); 1230 1231 /* If monitor resolution is set on the command line, use it */ 1232 xf86SetDpi(pScrn, 0, 0); 1233 1234 /* Load bpp-specific modules */ 1235 switch (pScrn->bitsPerPixel) { 1236#ifdef HAVE_XF1BPP 1237 case 1: 1238 if (xf86LoadSubModule(pScrn, "xf1bpp") == NULL) { 1239 vbeFree(cPtr->pVbe); 1240 cPtr->pVbe = NULL; 1241 CHIPSFreeRec(pScrn); 1242 return FALSE; 1243 } 1244 break; 1245#endif 1246#ifdef HAVE_XF4BPP 1247 case 4: 1248 if (xf86LoadSubModule(pScrn, "xf4bpp") == NULL) { 1249 vbeFree(cPtr->pVbe); 1250 cPtr->pVbe = NULL; 1251 CHIPSFreeRec(pScrn); 1252 return FALSE; 1253 } 1254 break; 1255#endif 1256 case 16: 1257 if (cPtr->Flags & ChipsOverlay8plus16) { 1258 if (xf86LoadSubModule(pScrn, "xf8_16bpp") == NULL) { 1259 vbeFree(cPtr->pVbe); 1260 cPtr->pVbe = NULL; 1261 CHIPSFreeRec(pScrn); 1262 return FALSE; 1263 } 1264 break; 1265 } 1266 default: 1267 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 1268 vbeFree(cPtr->pVbe); 1269 cPtr->pVbe = NULL; 1270 CHIPSFreeRec(pScrn); 1271 return FALSE; 1272 } 1273 break; 1274 } 1275 1276 if (cPtr->Flags & ChipsAccelSupport) { 1277 if (!xf86LoadSubModule(pScrn, "xaa")) { 1278 vbeFree(cPtr->pVbe); 1279 cPtr->pVbe = NULL; 1280 CHIPSFreeRec(pScrn); 1281 return FALSE; 1282 } 1283 } 1284 1285 if (cPtr->Flags & ChipsShadowFB) { 1286 if (!xf86LoadSubModule(pScrn, "shadowfb")) { 1287 vbeFree(cPtr->pVbe); 1288 cPtr->pVbe = NULL; 1289 CHIPSFreeRec(pScrn); 1290 return FALSE; 1291 } 1292 } 1293 1294 if (cPtr->Accel.UseHWCursor) { 1295 if (!xf86LoadSubModule(pScrn, "ramdac")) { 1296 vbeFree(cPtr->pVbe); 1297 cPtr->pVbe = NULL; 1298 CHIPSFreeRec(pScrn); 1299 return FALSE; 1300 } 1301 } 1302 1303#ifndef XSERVER_LIBPCIACCESS 1304 if (cPtr->Flags & ChipsLinearSupport) 1305 xf86SetOperatingState(resVgaMem, cPtr->pEnt->index, ResDisableOpr); 1306 1307 if (cPtr->MMIOBaseVGA) 1308 xf86SetOperatingState(resVgaIo, cPtr->pEnt->index, ResDisableOpr); 1309#endif 1310 1311 vbeFree(cPtr->pVbe); 1312 cPtr->pVbe = NULL; 1313 return TRUE; 1314} 1315 1316static Bool 1317chipsPreInitHiQV(ScrnInfoPtr pScrn, int flags) 1318{ 1319 int bytesPerPixel; 1320 unsigned char tmp; 1321 MessageType from; 1322 int i; 1323 unsigned int Probed[3], FPclkI, CRTclkI; 1324 double real; 1325 int val, indx; 1326 const char *s; 1327 pointer pVbeModule = NULL; 1328 1329 vgaHWPtr hwp; 1330 CHIPSPtr cPtr = CHIPSPTR(pScrn); 1331 CHIPSEntPtr cPtrEnt = NULL; 1332 CHIPSPanelSizePtr Size = &cPtr->PanelSize; 1333 CHIPSMemClockPtr MemClk = &cPtr->MemClock; 1334 CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); 1335#ifndef XSERVER_LIBPCIACCESS 1336 resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; 1337#endif 1338 1339 /* Set pScrn->monitor */ 1340 pScrn->monitor = pScrn->confScreen->monitor; 1341 1342 /* All HiQV chips support 16/24/32 bpp */ 1343 if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb | 1344 SupportConvert32to24 | PreferConvert32to24)) 1345 return FALSE; 1346 else { 1347 /* Check that the returned depth is one we support */ 1348 switch (pScrn->depth) { 1349 case 1: 1350 case 4: 1351 case 8: 1352 case 15: 1353 case 16: 1354 case 24: 1355 case 32: 1356 /* OK */ 1357 break; 1358 default: 1359 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 1360 "Given depth (%d) is not supported by this driver\n", 1361 pScrn->depth); 1362 return FALSE; 1363 } 1364 } 1365 xf86PrintDepthBpp(pScrn); 1366 1367 /* Get the depth24 pixmap format */ 1368 if (pScrn->depth == 24 && pix24bpp == 0) 1369 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 1370 1371 /* 1372 * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp 1373 */ 1374 if (!vgaHWGetHWRec(pScrn)) 1375 return FALSE; 1376 1377 hwp = VGAHWPTR(pScrn); 1378 vgaHWGetIOBase(hwp); 1379 cPtr->PIOBase = hwp->PIOOffset; 1380 /* 1381 * Must allow ensure that storage for the 2nd set of vga registers is 1382 * allocated for dual channel cards 1383 */ 1384 if ((cPtr->Flags & ChipsDualChannelSupport) && 1385 (! xf86IsEntityShared(pScrn->entityList[0]))) 1386 vgaHWAllocDefaultRegs(&(cPtr->VgaSavedReg2)); 1387 1388 /* 1389 * This must happen after pScrn->display has been set because 1390 * xf86SetWeight references it. 1391 */ 1392 if (pScrn->depth > 8) { 1393 /* The defaults are OK for us */ 1394 rgb zeros = {0, 0, 0}; 1395 1396 if (!xf86SetWeight(pScrn, zeros, zeros)) { 1397 return FALSE; 1398 } else { 1399 /* XXX check that weight returned is supported */ 1400 ; 1401 } 1402 } 1403 1404 if (!xf86SetDefaultVisual(pScrn, -1)) 1405 return FALSE; 1406 1407 /* The gamma fields must be initialised when using the new cmap code */ 1408 if (pScrn->depth > 1) { 1409 Gamma zeros = {0.0, 0.0, 0.0}; 1410 1411 if (!xf86SetGamma(pScrn, zeros)) 1412 return FALSE; 1413 } 1414 1415 bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); 1416 1417 /* Collect all of the relevant option flags (fill in pScrn->options) */ 1418 xf86CollectOptions(pScrn, NULL); 1419 /* Process the options */ 1420 if (!(cPtr->Options = xalloc(sizeof(ChipsHiQVOptions)))) 1421 return FALSE; 1422 memcpy(cPtr->Options, ChipsHiQVOptions, sizeof(ChipsHiQVOptions)); 1423 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); 1424 1425 /* Set the bits per RGB */ 1426 if (pScrn->depth > 1) { 1427 /* Default to 6, is this right for HiQV?? */ 1428 pScrn->rgbBits = 8; 1429 if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, &val)) { 1430 if (val == 6 || val == 8) { 1431 pScrn->rgbBits = val; 1432 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to " 1433 "%d\n", pScrn->rgbBits); 1434 } else 1435 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid number of " 1436 "rgb bits %d\n", val); 1437 } 1438 } 1439 if ((cPtr->Flags & ChipsAccelSupport) && 1440 (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { 1441 cPtr->Flags &= ~ChipsAccelSupport; 1442 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 1443 } 1444 1445 from = X_DEFAULT; 1446 if (pScrn->bitsPerPixel < 8) { 1447 /* Default to SW cursor for 1/4 bpp */ 1448 cPtr->Accel.UseHWCursor = FALSE; 1449 } else { 1450 cPtr->Accel.UseHWCursor = TRUE; 1451 } 1452 if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, 1453 &cPtr->Accel.UseHWCursor)) 1454 from = X_CONFIG; 1455 if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, 1456 &cPtr->Accel.UseHWCursor)) { 1457 from = X_CONFIG; 1458 cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; 1459 } 1460 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 1461 (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); 1462 1463 /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ 1464 if (pScrn->bitsPerPixel < 8) { 1465 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { 1466 cPtr->Flags &= ~ChipsLinearSupport; 1467 from = X_CONFIG; 1468 } 1469 } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { 1470 cPtr->Flags &= ~ChipsLinearSupport; 1471 from = X_CONFIG; 1472 } 1473 1474#ifndef HAVE_ISA 1475 if (!(cPtr->Flags & ChipsLinearSupport)) { 1476 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); 1477 return FALSE; 1478 } 1479#endif 1480 1481 /* linear base */ 1482 if (cPtr->Flags & ChipsLinearSupport) { 1483 if (cPtr->pEnt->location.type == BUS_PCI) { 1484 /* Tack on 0x800000 to access the big-endian aperture? */ 1485#if X_BYTE_ORDER == X_BIG_ENDIAN 1486 if (BE_SWAP_APRETURE(pScrn,cPtr)) 1487 cPtr->FbAddress = (PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000) + 0x800000L; 1488 else 1489#endif 1490 cPtr->FbAddress = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; 1491 1492 from = X_PROBED; 1493#ifndef XSERVER_LIBPCIACCESS 1494 if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) 1495 cPtr->Flags &= ~ChipsLinearSupport; 1496#endif 1497 } else { 1498 if (cPtr->pEnt->device->MemBase) { 1499 cPtr->FbAddress = cPtr->pEnt->device->MemBase; 1500 from = X_CONFIG; 1501 } else { 1502 cPtr->FbAddress = ((unsigned int) 1503 (cPtr->readXR(cPtr, 0x06))) << 24; 1504 cPtr->FbAddress |= ((unsigned int) 1505 (0x80 & (cPtr->readXR(cPtr, 0x05)))) << 16; 1506 from = X_PROBED; 1507 } 1508#ifndef XSERVER_LIBPCIACCESS 1509 linearRes[0].rBegin = cPtr->FbAddress; 1510 linearRes[0].rEnd = cPtr->FbAddress + 0x800000; 1511 if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { 1512 cPtr->Flags &= ~ChipsLinearSupport; 1513 from = X_PROBED; 1514 } 1515#endif 1516 } 1517 } 1518 if (cPtr->Flags & ChipsLinearSupport) { 1519 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1520 "Enabling linear addressing\n"); 1521 xf86DrvMsg(pScrn->scrnIndex, from, 1522 "base address is set at 0x%lX.\n", cPtr->FbAddress); 1523#if X_BYTE_ORDER == X_BIG_ENDIAN 1524 if (BE_SWAP_APRETURE(pScrn,cPtr)) 1525 cPtr->IOAddress = cPtr->FbAddress - 0x400000L; 1526 else 1527#endif 1528 cPtr->IOAddress = cPtr->FbAddress + 0x400000L; 1529 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, 1530 "IOAddress is set at 0x%lX.\n",cPtr->IOAddress); 1531 1532 } else 1533 xf86DrvMsg(pScrn->scrnIndex, from, 1534 "Disabling linear addressing\n"); 1535 1536 if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) 1537 || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { 1538 if (!(cPtr->Flags & ChipsLinearSupport)) { 1539 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1540 "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); 1541 } else if (pScrn->depth < 8) { 1542 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1543 "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); 1544 } else { 1545 cPtr->Rotate = 0; 1546 if (s) { 1547 if(!xf86NameCmp(s, "CW")) { 1548 /* accel is disabled below for shadowFB */ 1549 cPtr->Flags |= ChipsShadowFB; 1550 cPtr->Rotate = 1; 1551 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1552 "Rotating screen clockwise\n"); 1553 } else if(!xf86NameCmp(s, "CCW")) { 1554 cPtr->Flags |= ChipsShadowFB; 1555 cPtr->Rotate = -1; 1556 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 1557 "counter clockwise\n"); 1558 } else { 1559 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 1560 "value for Option \"Rotate\"\n", s); 1561 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 1562 "Valid options are \"CW\" or \"CCW\"\n"); 1563 } 1564 } else { 1565 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1566 "Using \"Shadow Framebuffer\"\n"); 1567 cPtr->Flags |= ChipsShadowFB; 1568 } 1569 } 1570 } 1571 1572 if ((s = xf86GetOptValString(cPtr->Options, OPTION_OVERLAY))) { 1573 if (!*s || !xf86NameCmp(s, "8,16") || !xf86NameCmp(s, "16,8")) { 1574 if (pScrn->bitsPerPixel == 16) { 1575 if (cPtr->Flags & ChipsLinearSupport) { 1576 cPtr->Flags |= ChipsOverlay8plus16; 1577 if(!xf86GetOptValInteger( 1578 cPtr->Options, OPTION_COLOR_KEY, &(pScrn->colorKey))) 1579 pScrn->colorKey = TRANSPARENCY_KEY; 1580 pScrn->overlayFlags = OVERLAY_8_16_DUALFB; 1581 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1582 "PseudoColor overlay enabled.\n"); 1583 if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_STRETCH)) 1584 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1585 " - Forcing option \"Stretch\" \"ON\".\n"); 1586 if (!xf86IsOptionSet(cPtr->Options, OPTION_LCD_CENTER)) 1587 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1588 " - Forcing option \"LcdCenter\" \"OFF\".\n"); 1589 if (cPtr->Flags & ChipsShadowFB) { 1590 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1591 " - Disabling \"Shadow Framebuffer\".\n"); 1592 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1593 " Not support with option \"8Plus16\".\n"); 1594 cPtr->Flags &= ~ChipsShadowFB; 1595 cPtr->Rotate = 0; 1596 } 1597 } else { 1598 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Option \"Overlay\" ignored. Not supported without linear addressing\n"); 1599 } 1600 } else { 1601 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1602 "Option \"Overlay\" is not supported in this configuration\n"); 1603 } 1604 } else { 1605 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1606 "\"%s\" is not a valid value for Option \"Overlay\"\n", s); 1607 } 1608 } 1609 1610 if (!(cPtr->Flags & ChipsOverlay8plus16)) { 1611 if(xf86GetOptValInteger(cPtr->Options, OPTION_VIDEO_KEY, 1612 &(cPtr->videoKey))) { 1613 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n", 1614 cPtr->videoKey); 1615 } else { 1616 cPtr->videoKey = (1 << pScrn->offset.red) | 1617 (1 << pScrn->offset.green) | 1618 (((pScrn->mask.blue >> pScrn->offset.blue) - 1) 1619 << pScrn->offset.blue); 1620 } 1621 } 1622 1623 if (cPtr->Flags & ChipsShadowFB) { 1624 if (cPtr->Flags & ChipsAccelSupport) { 1625 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1626 "HW acceleration is not supported with shadow fb\n"); 1627 cPtr->Flags &= ~ChipsAccelSupport; 1628 } 1629 if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { 1630 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 1631 "HW cursor is not supported with rotate\n"); 1632 cPtr->Accel.UseHWCursor = FALSE; 1633 } 1634 } 1635 1636 if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, TRUE)) { 1637 cPtr->UseMMIO = TRUE; 1638 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1639 "Using MMIO\n"); 1640 1641 /* Are we using MMIO mapping of VGA registers */ 1642 if (xf86ReturnOptValBool(cPtr->Options, OPTION_FULL_MMIO, FALSE)) { 1643 if ((cPtr->Flags & ChipsLinearSupport) 1644 && (cPtr->Flags & ChipsFullMMIOSupport) 1645 && (cPtr->pEnt->location.type == BUS_PCI)) { 1646 1647 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1648 "Enabling Full MMIO\n"); 1649 cPtr->UseFullMMIO = TRUE; 1650 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1651 "Using Full MMIO\n"); 1652 1653 /* 1654 * We need to map the framebuffer to read/write regs. 1655 * but can't do that without the FbMapSize. So need to 1656 * fake value for PreInit. This isn't a problem as 1657 * framebuffer isn't actually used in PreInit 1658 */ 1659 cPtr->FbMapSize = 1024 * 1024; 1660 1661 /* Map the linear framebuffer */ 1662 if (!chipsMapMem(pScrn)) 1663 return FALSE; 1664 1665 /* Setup the MMIO register functions */ 1666 if (cPtr->MMIOBaseVGA) { 1667 CHIPSSetMmioExtFuncs(cPtr); 1668 CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); 1669 } 1670 } else { 1671 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1672 "FULL_MMIO option ignored\n"); 1673 } 1674 } 1675 } else { 1676 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,"Disabling MMIO: " 1677 "no acceleration, no hw_cursor\n"); 1678 cPtr->UseMMIO = FALSE; 1679 cPtr->Accel.UseHWCursor = FALSE; 1680 cPtr->Flags &= ~ChipsAccelSupport; 1681 } 1682 1683 1684 if (cPtr->Flags & ChipsDualChannelSupport) { 1685 1686 if (xf86IsEntityShared(pScrn->entityList[0])) { 1687 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 1688 CHIPSEntityIndex)->ptr; 1689#if 1 1690 /* 1691 * XXX This assumes that the lower number screen is always the 1692 * "master" head, and that the "master" is the first CRTC. This 1693 * can result in unexpected behaviour when the config file marks 1694 * the primary CRTC as the second screen. 1695 */ 1696 if (xf86IsPrimInitDone(pScrn->entityList[0])) 1697#else 1698 /* 1699 * This is an alternative version that determines which is the 1700 * secondary CRTC from the screen field in cPtr->pEnt->device. 1701 * It doesn't currently work because there are things that assume 1702 * the primary CRTC is initialised first. 1703 */ 1704 if (cPtr->pEnt->device->screen == 1) 1705 1706#endif 1707 { 1708 /* This is the second crtc */ 1709 cPtr->SecondCrtc = TRUE; 1710 cPtr->UseDualChannel = TRUE; 1711 } else 1712 cPtr->SecondCrtc = FALSE; 1713 1714 } else { 1715 if (xf86ReturnOptValBool(cPtr->Options, 1716 OPTION_DUAL_REFRESH, FALSE)) { 1717 cPtr->Flags |= ChipsDualRefresh; 1718 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1719 "Dual Refresh mode enabled\n"); 1720 cPtr->UseDualChannel = TRUE; 1721 } 1722 } 1723 1724 /* Store IOSS/MSS so that we can restore them */ 1725 cPtr->storeIOSS = cPtr->readIOSS(cPtr); 1726 cPtr->storeMSS = cPtr->readMSS(cPtr); 1727 DUALOPEN; 1728 } 1729 1730 /* memory size */ 1731 if (cPtr->pEnt->device->videoRam != 0) { 1732 pScrn->videoRam = cPtr->pEnt->device->videoRam; 1733 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", 1734 pScrn->videoRam); 1735 } else { 1736 /* not given, probe it */ 1737 switch (cPtr->Chipset) { 1738 case CHIPS_CT69030: 1739 /* The ct69030 has 4Mb of SGRAM integrated */ 1740 pScrn->videoRam = 4096; 1741 cPtr->Flags |= Chips64BitMemory; 1742 break; 1743 case CHIPS_CT69000: 1744 /* The ct69000 has 2Mb of SGRAM integrated */ 1745 pScrn->videoRam = 2048; 1746 cPtr->Flags |= Chips64BitMemory; 1747 break; 1748 case CHIPS_CT65550: 1749 /* XR43: DRAM interface */ 1750 /* bit 2-1: memory size */ 1751 /* 0: 1024 kB */ 1752 /* 1: 2048 kB */ 1753 /* 2: reserved */ 1754 /* 3: reserved */ 1755 switch (((cPtr->readXR(cPtr, 0x43)) & 0x06) >> 1) { 1756 case 0: 1757 pScrn->videoRam = 1024; 1758 break; 1759 case 1: 1760 case 2: 1761 case 3: 1762 pScrn->videoRam = 2048; 1763 break; 1764 } 1765 break; 1766 default: 1767 /* XRE0: Software reg */ 1768 /* bit 3-0: memory size */ 1769 /* 0: 512k */ 1770 /* 1: 1024k */ 1771 /* 2: 1536k(1.5M)*/ 1772 /* 3: 2048k */ 1773 /* 7: 4096k */ 1774 tmp = (cPtr->readXR(cPtr, 0xE0)) & 0xF; 1775 switch (tmp) { 1776 case 0: 1777 pScrn->videoRam = 512; 1778 break; 1779 case 1: 1780 pScrn->videoRam = 1024; 1781 break; 1782 case 2: 1783 pScrn->videoRam = 1536; 1784 break; 1785 case 3: 1786 pScrn->videoRam = 2048; 1787 break; 1788 case 7: 1789 pScrn->videoRam = 4096; 1790 break; 1791 default: 1792 pScrn->videoRam = 1024; 1793 break; 1794 } 1795 /* XR43: DRAM interface */ 1796 /* bit 4-5 mem interface width */ 1797 /* 00: 32Bit */ 1798 /* 01: 64Bit */ 1799 tmp = cPtr->readXR(cPtr, 0x43); 1800 if ((tmp & 0x10) == 0x10) 1801 cPtr->Flags |= Chips64BitMemory; 1802 break; 1803 } 1804 } 1805 1806#if X_BYTE_ORDER == X_BIG_ENDIAN 1807 if (cPtr->pEnt->chipset == CHIPS_CT69030 && ((cPtr->readXR(cPtr, 0x71) & 0x2)) == 0) /* CFG9: Pipeline variable ByteSwap mapping */ 1808 cPtr->dualEndianAp = TRUE; 1809 else /* CFG9: Pipeline A/B mapping */ 1810 cPtr->dualEndianAp = FALSE; 1811#endif 1812 1813 if ((cPtr->Flags & ChipsDualChannelSupport) && 1814 (xf86IsEntityShared(pScrn->entityList[0]))) { 1815 /* 1816 * This takes gives either half or the amount of memory specified 1817 * with the Crt2Memory option 1818 */ 1819 pScrn->memPhysBase = cPtr->FbAddress; 1820 1821 if(cPtr->SecondCrtc == FALSE) { 1822 int crt2mem = -1, adjust; 1823 1824 xf86GetOptValInteger(cPtr->Options, OPTION_CRT2_MEM, &crt2mem); 1825 if (crt2mem > 0) { 1826 adjust = crt2mem; 1827 from = X_CONFIG; 1828 } else { 1829 adjust = pScrn->videoRam / 2; 1830 from = X_DEFAULT; 1831 } 1832 xf86DrvMsg(pScrn->scrnIndex, from, 1833 "CRT2 will use %dK of VideoRam\n", 1834 adjust); 1835 1836 cPtrEnt->mastervideoRam = pScrn->videoRam - adjust; 1837 pScrn->videoRam = cPtrEnt->mastervideoRam; 1838 cPtrEnt->slavevideoRam = adjust; 1839 cPtrEnt->masterFbAddress = cPtr->FbAddress; 1840 cPtr->FbMapSize = 1841 cPtrEnt->masterFbMapSize = pScrn->videoRam * 1024; 1842 cPtrEnt->slaveFbMapSize = cPtrEnt->slavevideoRam * 1024; 1843 pScrn->fbOffset = 0; 1844 } else { 1845 cPtrEnt->slaveFbAddress = cPtr->FbAddress + 1846 cPtrEnt->masterFbMapSize; 1847 cPtr->FbMapSize = cPtrEnt->slaveFbMapSize; 1848 pScrn->videoRam = cPtrEnt->slavevideoRam; 1849 pScrn->fbOffset = cPtrEnt->masterFbMapSize; 1850 } 1851 1852 cPtrEnt->refCount++; 1853 } else { 1854 /* Normal Handling of video ram etc */ 1855 cPtr->FbMapSize = pScrn->videoRam * 1024; 1856 } 1857 1858 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", 1859 pScrn->videoRam); 1860 1861 /* Store register values that might be messed up by a suspend resume */ 1862 /* Do this early as some of the other code in PreInit relies on it */ 1863 cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); 1864 cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? 1865 0x3D0 : 0x3B0); 1866 1867 /* 1868 * Do DDC here: if VESA BIOS detects an external monitor it 1869 * might switch. SetPanelType() will detect this. 1870 */ 1871 if ((pVbeModule = xf86LoadSubModule(pScrn, "ddc"))) { 1872 Bool ddc_done = FALSE; 1873 xf86MonPtr pMon; 1874 1875 if (cPtr->pVbe) { 1876 if ((pMon 1877 = xf86PrintEDID(vbeDoEDID(cPtr->pVbe, pVbeModule))) != NULL) { 1878 ddc_done = TRUE; 1879 xf86SetDDCproperties(pScrn,pMon); 1880 } 1881 } 1882 1883 if (!ddc_done) 1884 if (xf86LoadSubModule(pScrn, "i2c")) { 1885 if (chips_i2cInit(pScrn)) { 1886 if ((pMon = xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex, 1887 cPtr->I2C))) != NULL) 1888 ddc_done = TRUE; 1889 xf86SetDDCproperties(pScrn,pMon); 1890 } 1891 } 1892 if (!ddc_done) 1893 chips_ddc1(pScrn); 1894 } 1895 1896 /*test STN / TFT */ 1897 tmp = cPtr->readFR(cPtr, 0x10); 1898 1899 /* XR51 or FR10: DISPLAY TYPE REGISTER */ 1900 /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ 1901 /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ 1902 switch (tmp & 0x3) { 1903 case 0: 1904 if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { 1905 cPtr->PanelType |= ChipsSS; 1906 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); 1907 } else { 1908 cPtr->PanelType |= ChipsTFT; 1909 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); 1910 } 1911 break; 1912 case 2: 1913 cPtr->PanelType |= ChipsDS; 1914 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); 1915 case 3: 1916 cPtr->PanelType |= ChipsDD; 1917 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); 1918 break; 1919 default: 1920 break; 1921 } 1922 1923 chipsSetPanelType(cPtr); 1924 from = X_PROBED; 1925 { 1926 Bool fp_mode; 1927 if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { 1928 if (fp_mode) { 1929 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); 1930 cPtr->PanelType |= ChipsLCD; 1931 } else { 1932 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); 1933 cPtr->PanelType = ~ChipsLCD; 1934 } 1935 from = X_CONFIG; 1936 } 1937 } 1938 if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) 1939 xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); 1940 else if (cPtr->PanelType & ChipsLCD) 1941 xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); 1942 else if (cPtr->PanelType & ChipsCRT) { 1943 xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); 1944 /* monitor info */ 1945#if 1 1946 cPtr->Monitor = chipsSetMonitor(pScrn); 1947#endif 1948 } 1949 /* screen size */ 1950 /* 1951 * In LCD mode / dual mode we want to derive the timing values from 1952 * the ones preset by bios 1953 */ 1954 if (cPtr->PanelType & ChipsLCD) { 1955 1956 /* for 65550 we only need H/VDisplay values for screen size */ 1957 unsigned char fr25, tmp1; 1958#ifdef DEBUG 1959 unsigned char fr26; 1960 char tmp2; 1961#endif 1962 fr25 = cPtr->readFR(cPtr, 0x25); 1963 tmp = cPtr->readFR(cPtr, 0x20); 1964 Size->HDisplay = ((tmp + ((fr25 & 0x0F) << 8)) + 1) << 3; 1965 tmp = cPtr->readFR(cPtr, 0x30); 1966 tmp1 = cPtr->readFR(cPtr, 0x35); 1967 Size->VDisplay = ((tmp1 & 0x0F) << 8) + tmp + 1; 1968#ifdef DEBUG 1969 tmp = cPtr->readFR(cPtr, 0x21); 1970 Size->HRetraceStart = ((tmp + ((fr25 & 0xF0) << 4)) + 1) << 3; 1971 tmp1 = cPtr->readFR(cPtr, 0x22); 1972 tmp2 = (tmp1 & 0x1F) - (tmp & 0x3F); 1973 Size->HRetraceEnd = ((((tmp2 < 0) ? (tmp2 + 0x40) : tmp2) << 3) 1974 + Size->HRetraceStart); 1975 tmp = cPtr->readFR(cPtr, 0x23); 1976 fr26 = cPtr->readFR(cPtr, 0x26); 1977 Size->HTotal = ((tmp + ((fr26 & 0x0F) << 8)) + 5) << 3; 1978 xf86ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", 1979 Size->HDisplay, Size->VDisplay, 1980 Size->HRetraceStart,Size->HRetraceEnd, 1981 Size->HTotal); 1982#endif 1983 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", 1984 Size->HDisplay, Size->VDisplay); 1985 /* Warn the user if the panel size has been overridden by 1986 * the modeline values 1987 */ 1988 if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { 1989 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 1990 "Display size overridden by modelines.\n"); 1991 } 1992 } 1993 1994 /* Frame Buffer */ /* for LCDs */ 1995 if (IS_STN(cPtr->PanelType)) { 1996 tmp = cPtr->readFR(cPtr, 0x1A); /*Frame Buffer Ctrl. */ 1997 if (tmp & 1) { 1998 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); 1999 if (!(tmp & 0x80)) { 2000 /* Formula for calculating the size of the framebuffer. 3 2001 * bits per pixel 10 pixels per 32 bit dword. If frame 2002 * acceleration is enabled the size can be halved. 2003 */ 2004 cPtr->FrameBufferSize = ( Size->HDisplay * 2005 Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); 2006 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2007 "Using embedded Frame Buffer, size %d bytes\n", 2008 cPtr->FrameBufferSize); 2009 } else 2010 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2011 "Using external Frame Buffer used\n"); 2012 } 2013 if (tmp & 2) 2014 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2015 "Frame accelerator enabled\n"); 2016 } 2017 2018 /* bus type */ 2019 tmp = (cPtr->readXR(cPtr, 0x08)) & 1; 2020 if (tmp == 1) { /*PCI */ 2021 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); 2022 cPtr->Bus = ChipsPCI; 2023 } else { /* XR08: Linear addressing base, not for PCI */ 2024 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); 2025 cPtr->Bus = ChipsVLB; 2026 } 2027 2028 /* disable acceleration for 1 and 4 bpp */ 2029 if (pScrn->bitsPerPixel < 8) { 2030 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2031 "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); 2032 cPtr->Flags &= ~ChipsAccelSupport; 2033 } 2034 2035 /* Set the flags for Colour transparency. This is dependent 2036 * on the revision on the chip. Until exactly which chips 2037 * have this bug are found, only allow 8bpp Colour transparency */ 2038 if ((pScrn->bitsPerPixel == 8) || ((cPtr->Chipset >= CHIPS_CT65555) && 2039 (pScrn->bitsPerPixel >= 8) && (pScrn->bitsPerPixel <= 24))) 2040 cPtr->Flags |= ChipsColorTransparency; 2041 else 2042 cPtr->Flags &= ~ChipsColorTransparency; 2043 2044 /* DAC info */ 2045 if (!((cPtr->readXR(cPtr, 0xD0)) & 0x01)) 2046 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); 2047 2048 /* MMIO address offset */ 2049 cPtr->Regs32 = ChipsReg32HiQV; 2050 2051 /* sync reset ignored on this chipset */ 2052 cPtr->SyncResetIgn = TRUE; /* !! */ 2053 2054 /* We use a programmable clock */ 2055 pScrn->numClocks = 26; /* Some number */ 2056 pScrn->progClock = TRUE; 2057 cPtr->ClockType = HiQV_STYLE | TYPE_PROGRAMMABLE; 2058 2059 if (cPtr->pEnt->device->textClockFreq > 0) { 2060 SaveClk->Clock = cPtr->pEnt->device->textClockFreq; 2061 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2062 "Using textclock freq: %7.3f.\n", 2063 SaveClk->Clock/1000.0); 2064 } else 2065 SaveClk->Clock = 0; 2066 2067 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); 2068 2069 /* Set the maximum memory clock. */ 2070 switch (cPtr->Chipset) { 2071 case CHIPS_CT65550: 2072 if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) 2073 MemClk->Max = 38000; /* Revision A chips */ 2074 else 2075 MemClk->Max = 50000; /* Revision B chips */ 2076 break; 2077 case CHIPS_CT65554: 2078 case CHIPS_CT65555: 2079 case CHIPS_CT68554: 2080 MemClk->Max = 55000; 2081 break; 2082 case CHIPS_CT69000: 2083 MemClk->Max = 83000; 2084 break; 2085 case CHIPS_CT69030: 2086 MemClk->Max = 100000; 2087 break; 2088 } 2089 2090 /* Probe the dot clocks */ 2091 for (i = 0; i < 3; i++) { 2092 unsigned int N,M,PSN,P,VCO_D; 2093 int offset = i * 4; 2094 2095 tmp = cPtr->readXR(cPtr,0xC2 + offset); 2096 M = (cPtr->readXR(cPtr, 0xC0 + offset) 2097 | (tmp & 0x03)) + 2; 2098 N = (cPtr->readXR(cPtr, 0xC1 + offset) 2099 | (( tmp >> 4) & 0x03)) + 2; 2100 tmp = cPtr->readXR(cPtr, 0xC3 + offset); 2101 PSN = (cPtr->Chipset == CHIPS_CT69000 || cPtr->Chipset == CHIPS_CT69030) 2102 ? 1 : (((tmp & 0x1) ? 1 : 4) * ((tmp & 0x02) ? 5 : 1)); 2103 VCO_D = ((tmp & 0x04) ? ((cPtr->Chipset == CHIPS_CT69000 || 2104 cPtr->Chipset == CHIPS_CT69030) ? 1 : 16) : 4); 2105 P = ((tmp & 0x70) >> 4); 2106 Probed[i] = VCO_D * Fref / N; 2107 Probed[i] = Probed[i] * M / (PSN * (1 << P)); 2108 Probed[i] = Probed[i] / 1000; 2109 } 2110 CRTclkI = (hwp->readMiscOut(hwp) >> 2) & 0x03; 2111 if (CRTclkI == 3) CRTclkI = 2; 2112 if (cPtr->Chipset == CHIPS_CT69030) 2113 FPclkI = (cPtr->readFR(cPtr, 0x01) >> 2) & 0x3; 2114 else 2115 FPclkI = (cPtr->readFR(cPtr, 0x03) >> 2) & 0x3; 2116 if (FPclkI == 3) FPclkI = 2; 2117 for (i = 0; i < 3; i++) { 2118 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2119 "Dot clock %i: %7.3f MHz",i, 2120 (float)(Probed[i])/1000.); 2121 if (FPclkI == i) xf86ErrorF(" FPclk"); 2122 if (CRTclkI == i) xf86ErrorF(" CRTclk"); 2123 xf86ErrorF("\n"); 2124 } 2125 cPtr->FPclock = Probed[FPclkI]; 2126 cPtr->FPclkInx = FPclkI; 2127 if (CRTclkI == FPclkI) { 2128 if (FPclkI == 2) 2129 CRTclkI = 1; 2130 else 2131 CRTclkI = 2; 2132 } 2133 cPtr->CRTclkInx = CRTclkI; 2134 2135 2136 /* 2137 * Some chips seem to dislike some clocks in one of the PLL's. Give 2138 * the user the oppurtunity to change it 2139 */ 2140 if (xf86GetOptValInteger(cPtr->Options, OPTION_CRT_CLK_INDX, &indx)) { 2141 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Force CRT Clock index to %d\n", 2142 indx); 2143 cPtr->CRTclkInx = indx; 2144 2145 if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, &indx)) { 2146 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2147 "Force FP Clock index to %d\n", indx); 2148 cPtr->FPclkInx = indx; 2149 } else { 2150 if (indx == cPtr->FPclkInx) { 2151 if (indx == 2) 2152 cPtr->FPclkInx = 1; 2153 else 2154 cPtr->FPclkInx = indx + 1; 2155 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2156 "FP Clock index forced to %d\n", cPtr->FPclkInx); 2157 } 2158 } 2159 } else if (xf86GetOptValInteger(cPtr->Options, OPTION_FP_CLK_INDX, 2160 &indx)) { 2161 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2162 "Force FP Clock index to %d\n", indx); 2163 cPtr->FPclkInx = indx; 2164 if (indx == cPtr->CRTclkInx) { 2165 if (indx == 2) 2166 cPtr->CRTclkInx = 1; 2167 else 2168 cPtr->CRTclkInx = indx + 1; 2169 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2170 "CRT Clock index forced to %d\n", cPtr->CRTclkInx); 2171 } 2172 } 2173 2174 2175 /* Probe the memory clock currently in use */ 2176 MemClk->xrCC = cPtr->readXR(cPtr, 0xCC); 2177 MemClk->M = (MemClk->xrCC & 0x7F) + 2; 2178 MemClk->xrCD = cPtr->readXR(cPtr, 0xCD); 2179 MemClk->N = (MemClk->xrCD & 0x7F) + 2; 2180 MemClk->xrCE = cPtr->readXR(cPtr, 0xCE); 2181 MemClk->PSN = (MemClk->xrCE & 0x1) ? 1 : 4; 2182 MemClk->P = ((MemClk->xrCE & 0x70) >> 4); 2183 /* Be careful with the calculation of ProbeClk as it can overflow */ 2184 MemClk->ProbedClk = 4 * Fref / MemClk->N; 2185 MemClk->ProbedClk = MemClk->ProbedClk * MemClk->M / (MemClk->PSN * 2186 (1 << MemClk->P)); 2187 MemClk->ProbedClk = MemClk->ProbedClk / 1000; 2188 MemClk->Clk = MemClk->ProbedClk; 2189 2190 if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, OPTUNITS_MHZ, &real)) { 2191 int mclk = (int)(real * 1000.0); 2192 if (mclk <= MemClk->Max) { 2193 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2194 "Using memory clock of %7.3f MHz\n", 2195 (float)(mclk/1000.)); 2196 2197 /* Only alter the memory clock if the desired memory clock differs 2198 * by 50kHz from the one currently being used. 2199 */ 2200 if (abs(mclk - MemClk->ProbedClk) > 50) { 2201 unsigned char vclk[3]; 2202 2203 MemClk->Clk = mclk; 2204 chipsCalcClock(pScrn, MemClk->Clk, vclk); 2205 MemClk->M = vclk[1] + 2; 2206 MemClk->N = vclk[2] + 2; 2207 MemClk->P = (vclk[0] & 0x70) >> 4; 2208 MemClk->PSN = (vclk[0] & 0x1) ? 1 : 4; 2209 MemClk->xrCC = vclk[1]; 2210 MemClk->xrCD = vclk[2]; 2211 MemClk->xrCE = 0x80 || vclk[0]; 2212 } 2213 } else 2214 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2215 "Memory clock of %7.3f MHz exceeds limit of %7.3f MHz\n", 2216 (float)(mclk/1000.), 2217 (float)(MemClk->Max/1000.)); 2218 } else 2219 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2220 "Probed memory clock of %7.3f MHz\n", 2221 (float)(MemClk->ProbedClk/1000.)); 2222 2223 cPtr->ClockMulFactor = 1; 2224 2225 /* Set the min/max pixel clock */ 2226 switch (cPtr->Chipset) { 2227 case CHIPS_CT69030: 2228 cPtr->MinClock = 3000; 2229 cPtr->MaxClock = 170000; 2230 break; 2231 case CHIPS_CT69000: 2232 cPtr->MinClock = 3000; 2233 cPtr->MaxClock = 135000; 2234 break; 2235 case CHIPS_CT68554: 2236 case CHIPS_CT65555: 2237 cPtr->MinClock = 1000; 2238 cPtr->MaxClock = 110000; 2239 break; 2240 case CHIPS_CT65554: 2241 cPtr->MinClock = 1000; 2242 cPtr->MaxClock = 95000; 2243 break; 2244 case CHIPS_CT65550: 2245 cPtr->MinClock = 1000; 2246 if (((cPtr->readXR(cPtr, 0x04)) & 0xF) < 6) { 2247 if ((cPtr->readFR(cPtr, 0x0A)) & 2) { 2248 /*5V Vcc */ 2249 cPtr->MaxClock = 100000; 2250 } else { 2251 /*3.3V Vcc */ 2252 cPtr->MaxClock = 80000; 2253 } 2254 } else 2255 cPtr->MaxClock = 95000; /* Revision B */ 2256 break; 2257 } 2258 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", 2259 (float)(cPtr->MinClock / 1000.)); 2260 2261 /* Check if maxClock is limited by the MemClk. Only 70% to allow for */ 2262 /* RAS/CAS. Extra byte per memory clock needed if framebuffer used */ 2263 /* Extra byte if the overlay plane is activated */ 2264 /* If flag Chips64BitMemory is set assume a 64bitmemory interface, */ 2265 /* and 32bits on the others. Thus multiply by a suitable factor */ 2266 if (cPtr->Flags & Chips64BitMemory) { 2267 if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) 2268 if (cPtr->Flags & ChipsOverlay8plus16 ) 2269 cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 4); 2270 else 2271 cPtr->MaxClock = min(cPtr->MaxClock, 2272 MemClk->Clk * 8 * 0.7 / (bytesPerPixel + 1)); 2273 else 2274 if (cPtr->Flags & ChipsOverlay8plus16) 2275 cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 8 * 0.7 / 3); 2276 else 2277 cPtr->MaxClock = min(cPtr->MaxClock, 2278 MemClk->Clk * 8 * 0.7 / bytesPerPixel); 2279 } else { 2280 if (cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) 2281 if (cPtr->Flags & ChipsOverlay8plus16 ) 2282 cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 4); 2283 else 2284 cPtr->MaxClock = min(cPtr->MaxClock, 2285 MemClk->Clk * 4 * 0.7 / (bytesPerPixel + 1)); 2286 else 2287 if (cPtr->Flags & ChipsOverlay8plus16) 2288 cPtr->MaxClock = min(cPtr->MaxClock, MemClk->Clk * 4 * 0.7 / 3); 2289 else 2290 cPtr->MaxClock = min(cPtr->MaxClock, 2291 MemClk->Clk * 4 * 0.7 / bytesPerPixel); 2292 } 2293 2294 2295 2296 if (cPtr->pEnt->device->dacSpeeds[0]) { 2297 int speed = 0; 2298 switch (pScrn->bitsPerPixel) { 2299 case 1: 2300 case 4: 2301 case 8: 2302 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; 2303 break; 2304 case 16: 2305 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; 2306 break; 2307 case 24: 2308 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; 2309 break; 2310 case 32: 2311 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP32]; 2312 break; 2313 } 2314 2315 if (speed == 0) 2316 speed = cPtr->pEnt->device->dacSpeeds[0]; 2317 from = X_CONFIG; 2318 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2319 "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", 2320 (float)(speed / 1000.), (float)(cPtr->MaxClock / 1000.)); 2321 cPtr->MaxClock = speed; 2322 } else { 2323 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2324 "Max pixel clock is %7.3f MHz\n", 2325 (float)(cPtr->MaxClock / 1000.)); 2326 } 2327 /* 2328 * Prepare the FPclock: 2329 * if FPclock <= MaxClock : don't modify the FP clock. 2330 * else set FPclock to 90% of MaxClock. 2331 */ 2332 real = 0.; 2333 switch(bytesPerPixel) { 2334 case 1: 2335 if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, OPTUNITS_MHZ, &real)) 2336 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2337 "FP clock %7.3f MHz requested\n",real); 2338 break; 2339 case 2: 2340 if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, OPTUNITS_MHZ, &real)) 2341 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2342 "FP clock %7.3f MHz requested\n",real); 2343 break; 2344 case 3: 2345 if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, OPTUNITS_MHZ, &real)) 2346 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2347 "FP clock %7.3f MHz requested\n",real); 2348 break; 2349 case 4: 2350 if (xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_32, OPTUNITS_MHZ, &real)) 2351 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2352 "FP clock %7.3f MHz requested\n",real); 2353 break; 2354 } 2355 val = (int) (real * 1000.); 2356 if (val && val >= cPtr->MinClock && val <= cPtr->MaxClock) 2357 cPtr->FPclock = val; 2358 else if (cPtr->FPclock > cPtr->MaxClock) 2359 cPtr->FPclock = (int)((float)cPtr->MaxClock * 0.9); 2360 else 2361 cPtr->FPclock = 0; /* special value */ 2362 cPtr->FPClkModified = FALSE; 2363 if (cPtr->FPclock) 2364 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2365 "FP clock set to %7.3f MHz\n", 2366 (float)(cPtr->FPclock / 1000.)); 2367 2368#if defined(__arm__) && defined(__NetBSD__) 2369 ChipsPALMode.next = pScrn->monitor->Modes; 2370 pScrn->monitor->Modes = &ChipsNTSCMode; 2371#endif 2372 2373 2374 if (cPtr->Flags & ChipsDualChannelSupport) { 2375 if (xf86IsEntityShared(pScrn->entityList[0])) { 2376 if (cPtr->SecondCrtc == TRUE) { 2377 cPtrEnt->slaveActive = FALSE; 2378 } else { 2379 cPtrEnt->masterActive = FALSE; 2380 } 2381 } 2382 /* Put IOSS/MSS back to normal */ 2383 cPtr->writeIOSS(cPtr, cPtr->storeIOSS); 2384 cPtr->writeMSS(cPtr, hwp, cPtr->storeMSS); 2385 2386 xf86SetPrimInitDone(pScrn->entityList[0]); 2387 } 2388 2389 return TRUE; 2390} 2391 2392static Bool 2393chipsPreInitWingine(ScrnInfoPtr pScrn, int flags) 2394{ 2395 int i, bytesPerPixel, NoClocks = 0; 2396 unsigned char tmp; 2397 MessageType from; 2398 vgaHWPtr hwp; 2399 CHIPSPtr cPtr = CHIPSPTR(pScrn); 2400 CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); 2401 Bool useLinear = FALSE; 2402 char *s; 2403#ifndef XSERVER_LIBPCIACCESS 2404 resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; 2405#endif 2406 2407 /* Set pScrn->monitor */ 2408 pScrn->monitor = pScrn->confScreen->monitor; 2409 2410 if (cPtr->Flags & ChipsHDepthSupport) 2411 i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | 2412 SupportConvert32to24 | PreferConvert32to24); 2413 else 2414 i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support); 2415 2416 if (!i) 2417 return FALSE; 2418 else { 2419 /* Check that the returned depth is one we support */ 2420 switch (pScrn->depth) { 2421 case 1: 2422 case 4: 2423 case 8: 2424 /* OK */ 2425 break; 2426 case 15: 2427 case 16: 2428 case 24: 2429 if (cPtr->Flags & ChipsHDepthSupport) 2430 break; /* OK */ 2431 /* fall through */ 2432 default: 2433 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2434 "Given depth (%d) is not supported by this driver\n", 2435 pScrn->depth); 2436 return FALSE; 2437 } 2438 } 2439 2440 xf86PrintDepthBpp(pScrn); 2441 2442 /* Get the depth24 pixmap format */ 2443 if (pScrn->depth == 24 && pix24bpp == 0) 2444 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 2445 2446 /* 2447 * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp 2448 */ 2449 if (!vgaHWGetHWRec(pScrn)) 2450 return FALSE; 2451 2452 hwp = VGAHWPTR(pScrn); 2453 vgaHWGetIOBase(hwp); 2454 2455 /* 2456 * This must happen after pScrn->display has been set because 2457 * xf86SetWeight references it. 2458 */ 2459 if (pScrn->depth > 8) { 2460 /* The defaults are OK for us */ 2461 rgb zeros = {0, 0, 0}; 2462 2463 if (!xf86SetWeight(pScrn, zeros, zeros)) { 2464 return FALSE; 2465 } else { 2466 /* XXX check that weight returned is supported */ 2467 ; 2468 } 2469 } 2470 2471 if (!xf86SetDefaultVisual(pScrn, -1)) 2472 return FALSE; 2473 2474 /* The gamma fields must be initialised when using the new cmap code */ 2475 if (pScrn->depth > 1) { 2476 Gamma zeros = {0.0, 0.0, 0.0}; 2477 2478 if (!xf86SetGamma(pScrn, zeros)) 2479 return FALSE; 2480 } 2481 2482 /* Store register values that might be messed up by a suspend resume */ 2483 /* Do this early as some of the other code in PreInit relies on it */ 2484 cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; 2485 cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; 2486 cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; 2487 cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); 2488 2489 cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); 2490 cPtr->IOBase = (unsigned int)(cPtr->SuspendHack.vgaIOBaseFlag ? 2491 0x3D0 : 0x3B0); 2492 2493 bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); 2494 2495 /* Collect all of the relevant option flags (fill in pScrn->options) */ 2496 xf86CollectOptions(pScrn, NULL); 2497 2498 /* Process the options */ 2499 if (!(cPtr->Options = xalloc(sizeof(ChipsWingineOptions)))) 2500 return FALSE; 2501 memcpy(cPtr->Options, ChipsWingineOptions, sizeof(ChipsWingineOptions)); 2502 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); 2503 2504 /* Set the bits per RGB */ 2505 if (pScrn->depth > 1) { 2506 /* Default to 6, is this right?? */ 2507 pScrn->rgbBits = 6; 2508#if 0 2509 if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, 2510 &pScrn->rgbBits)) { 2511 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", 2512 pScrn->rgbBits); 2513 } 2514#endif 2515 } 2516 if ((cPtr->Flags & ChipsAccelSupport) && 2517 (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { 2518 cPtr->Flags &= ~ChipsAccelSupport; 2519 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 2520 } 2521 2522 from = X_DEFAULT; 2523 if (pScrn->bitsPerPixel < 8) { 2524 /* Default to SW cursor for 1/4 bpp */ 2525 cPtr->Accel.UseHWCursor = FALSE; 2526 } else { 2527 cPtr->Accel.UseHWCursor = TRUE; 2528 } 2529 if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, 2530 &cPtr->Accel.UseHWCursor)) 2531 from = X_CONFIG; 2532 if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, 2533 &cPtr->Accel.UseHWCursor)) { 2534 from = X_CONFIG; 2535 cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; 2536 } 2537 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 2538 (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); 2539 2540 /* memory size */ 2541 if (cPtr->pEnt->device->videoRam != 0) { 2542 pScrn->videoRam = cPtr->pEnt->device->videoRam; 2543 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", 2544 pScrn->videoRam); 2545 } else { 2546 /* not given, probe it */ 2547 /* XR0F: Software flags 0 */ 2548 /* bit 1-0: memory size */ 2549 /* 0: 256 kB */ 2550 /* 1: 512 kB */ 2551 /* 2: 1024 kB */ 2552 /* 3: 1024 kB */ 2553 2554 switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { 2555 case 0: 2556 pScrn->videoRam = 256; 2557 break; 2558 case 1: 2559 pScrn->videoRam = 512; 2560 break; 2561 case 2: 2562 pScrn->videoRam = 1024; 2563 break; 2564 case 3: 2565 pScrn->videoRam = 2048; 2566 break; 2567 } 2568 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", 2569 pScrn->videoRam); 2570 } 2571 cPtr->FbMapSize = pScrn->videoRam * 1024; 2572 2573 /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ 2574 if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; 2575 if (pScrn->bitsPerPixel < 8) { 2576 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { 2577 useLinear = FALSE; 2578 from = X_CONFIG; 2579 } 2580 } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { 2581 useLinear = FALSE; 2582 from = X_CONFIG; 2583 } 2584 2585#ifndef HAVE_ISA 2586 if (!(cPtr->Flags & ChipsLinearSupport)) { 2587 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); 2588 return FALSE; 2589 } 2590#endif 2591 2592 /* linear base */ 2593 if (useLinear) { 2594 unsigned char mask = 0xF8; 2595 if (pScrn->videoRam == 1024) 2596 mask = 0xF0; 2597 else if (pScrn->videoRam == 2048) 2598 mask = 0xE0; 2599 if (cPtr->pEnt->device->MemBase) { 2600 cPtr->FbAddress = cPtr->pEnt->device->MemBase 2601 & ((0xFF << 24) | (mask << 16)); 2602 from = X_CONFIG; 2603 } else { 2604 cPtr->FbAddress = ((0xFF & (cPtr->readXR(cPtr, 0x09))) << 24); 2605 cPtr->FbAddress |= ((mask & (cPtr->readXR(cPtr, 0x08))) << 16); 2606 from = X_PROBED; 2607 } 2608#ifndef XSERVER_LIBPCIACCESS 2609 linearRes[0].rBegin = cPtr->FbAddress; 2610 linearRes[0].rEnd = cPtr->FbAddress + 0x800000; 2611 if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { 2612 useLinear = FALSE; 2613 from = X_PROBED; 2614 } 2615#endif 2616 } 2617 2618 if (useLinear) { 2619 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2620 "Enabling linear addressing\n"); 2621 xf86DrvMsg(pScrn->scrnIndex, from, 2622 "base address is set at 0x%lX.\n", cPtr->FbAddress); 2623 if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && 2624 (cPtr->Flags & ChipsMMIOSupport)) { 2625 cPtr->UseMMIO = TRUE; 2626 cPtr->IOAddress = cPtr->FbAddress + 0x200000L; 2627 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); 2628 } 2629 } else { 2630 if (cPtr->Flags & ChipsLinearSupport) 2631 xf86DrvMsg(pScrn->scrnIndex, from, 2632 "Disabling linear addressing\n"); 2633 cPtr->Flags &= ~ChipsLinearSupport; 2634 } 2635 2636 if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) 2637 || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { 2638 if (!(cPtr->Flags & ChipsLinearSupport)) { 2639 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2640 "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); 2641 } else if (pScrn->depth < 8) { 2642 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2643 "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); 2644 } else { 2645 cPtr->Rotate = 0; 2646 if (s) { 2647 if(!xf86NameCmp(s, "CW")) { 2648 /* accel is disabled below for shadowFB */ 2649 cPtr->Flags |= ChipsShadowFB; 2650 cPtr->Rotate = 1; 2651 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2652 "Rotating screen clockwise\n"); 2653 } else if(!xf86NameCmp(s, "CCW")) { 2654 cPtr->Flags |= ChipsShadowFB; 2655 cPtr->Rotate = -1; 2656 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 2657 "counter clockwise\n"); 2658 } else { 2659 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 2660 "value for Option \"Rotate\"\n", s); 2661 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 2662 "Valid options are \"CW\" or \"CCW\"\n"); 2663 } 2664 } else { 2665 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2666 "Using \"Shadow Framebuffer\"\n"); 2667 cPtr->Flags |= ChipsShadowFB; 2668 } 2669 } 2670 } 2671 if (cPtr->Flags & ChipsShadowFB) { 2672 if (cPtr->Flags & ChipsAccelSupport) { 2673 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2674 "HW acceleration is not supported with shadow fb\n"); 2675 cPtr->Flags &= ~ChipsAccelSupport; 2676 } 2677 if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { 2678 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 2679 "HW cursor is not supported with rotate\n"); 2680 cPtr->Accel.UseHWCursor = FALSE; 2681 } 2682 } 2683 2684 cPtr->PanelType |= ChipsCRT; 2685 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CRT\n"); 2686 2687 /* monitor info */ 2688 cPtr->Monitor = chipsSetMonitor(pScrn); 2689 2690 /* bus type */ 2691 tmp = cPtr->readXR(cPtr, 0x01) & 3; 2692 switch (tmp) { 2693 case 0: 2694 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); 2695 cPtr->Bus = ChipsISA; 2696 break; 2697 case 3: 2698 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); 2699 cPtr->Bus = ChipsVLB; 2700 break; 2701 default: 2702 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); 2703 cPtr->Bus = ChipsUnknown; 2704 break; 2705 } 2706 2707 /* disable acceleration for 1 and 4 bpp */ 2708 if (pScrn->bitsPerPixel < 8) { 2709 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2710 "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); 2711 cPtr->Flags &= ~ChipsAccelSupport; 2712 } 2713 2714 /* 32bit register address offsets */ 2715 if ((cPtr->Flags & ChipsAccelSupport) || 2716 (cPtr->Accel.UseHWCursor)) { 2717 cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); 2718 tmp = cPtr->readXR(cPtr, 0x07); 2719 for( i = 0; i < (sizeof(ChipsReg32) / sizeof(ChipsReg32[0])); i++) { 2720 cPtr->Regs32[i] = ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80) 2721 << 8)| ((tmp & 0x7F) << 2); 2722#ifdef DEBUG 2723 ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); 2724#endif 2725 } 2726#ifndef XSERVER_LIBPCIACCESS 2727 linearRes[0].type = ResExcIoSparse | ResBios | ResBus; 2728 linearRes[0].rBase = cPtr->Regs32[0]; 2729 linearRes[0].rMask = 0x83FC; 2730 if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { 2731 if (cPtr->Flags & ChipsAccelSupport) { 2732 cPtr->Flags &= ~ChipsAccelSupport; 2733 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2734 "Cannot allocate IO registers: " 2735 "Disabling acceleration\n"); 2736 } 2737 if (cPtr->Accel.UseHWCursor) { 2738 cPtr->Accel.UseHWCursor = FALSE; 2739 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2740 "Cannot allocate IO registers: " 2741 "Disabling HWCursor\n"); 2742 } 2743 } 2744#endif 2745 } 2746 2747 cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); 2748 if (cPtr->ClockMulFactor != 1) 2749 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2750 "Clocks scaled by %d\n", cPtr->ClockMulFactor); 2751 2752 /* Clock type */ 2753 switch (cPtr->Chipset) { 2754 case CHIPS_CT64200: 2755 NoClocks = 4; 2756 cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; 2757 break; 2758 default: 2759 if (!((cPtr->readXR(cPtr, 0x01)) & 0x10)) { 2760 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2761 "Using external clock generator\n"); 2762 NoClocks = 4; 2763 cPtr->ClockType = WINGINE_1_STYLE | TYPE_HW; 2764 } else { 2765 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2766 "Using internal clock generator\n"); 2767 if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { 2768 NoClocks = 3; 2769 cPtr->ClockType = WINGINE_2_STYLE | TYPE_HW; 2770 } else { 2771 NoClocks = 26; /* some number */ 2772 cPtr->ClockType = WINGINE_2_STYLE | TYPE_PROGRAMMABLE; 2773 pScrn->progClock = TRUE; 2774 } 2775 } 2776 } 2777 2778 if (cPtr->ClockType & TYPE_PROGRAMMABLE) { 2779 pScrn->numClocks = NoClocks; 2780 if(cPtr->pEnt->device->textClockFreq > 0) { 2781 SaveClk->Clock = cPtr->pEnt->device->textClockFreq; 2782 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2783 "Using textclock freq: %7.3f.\n", 2784 SaveClk->Clock/1000.0); 2785 } else 2786 SaveClk->Clock = CRT_TEXT_CLK_FREQ; 2787 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); 2788 } else { /* TYPE_PROGRAMMABLE */ 2789 SaveClk->Clock = chipsGetHWClock(pScrn); 2790 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", 2791 SaveClk->Clock); 2792 if (!cPtr->pEnt->device->numclocks) { 2793 pScrn->numClocks = NoClocks; 2794 xf86GetClocks(pScrn, NoClocks, chipsClockSelect, 2795 chipsProtect, chipsBlankScreen, 2796 cPtr->IOBase + 0x0A, 0x08, 1, 28322); 2797 from = X_PROBED; 2798 } else { 2799 pScrn->numClocks = cPtr->pEnt->device->numclocks; 2800 if (pScrn->numClocks > NoClocks) { 2801 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2802 "Too many Clocks specified in configuration file.\n"); 2803 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2804 "\t\tAt most %d clocks may be specified\n", NoClocks); 2805 pScrn->numClocks= NoClocks; 2806 } 2807 for (i = 0; i < pScrn->numClocks; i++) 2808 pScrn->clock[i] = cPtr->pEnt->device->clock[i]; 2809 from = X_CONFIG; 2810 } 2811 xf86ShowClocks(pScrn, from); 2812 } 2813 2814 /* Set the min pixel clock */ 2815 /* XXX Guess, need to check this */ 2816 cPtr->MinClock = 11000 / cPtr->ClockMulFactor; 2817 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", 2818 (float)(cPtr->MinClock / 1000.)); 2819 /* maximal clock */ 2820 switch (cPtr->Chipset) { 2821 case CHIPS_CT64200: 2822 cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; 2823 break; 2824 case CHIPS_CT64300: 2825 cPtr->MaxClock = 85000 / cPtr->ClockMulFactor; 2826 break; 2827 } 2828 2829 if (cPtr->pEnt->device->dacSpeeds[0]) { 2830 int speed = 0; 2831 switch (pScrn->bitsPerPixel) { 2832 case 1: 2833 case 4: 2834 case 8: 2835 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; 2836 break; 2837 case 16: 2838 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; 2839 break; 2840 case 24: 2841 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; 2842 break; 2843 } 2844 if (speed == 0) 2845 cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; 2846 from = X_CONFIG; 2847 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 2848 "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", 2849 (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); 2850 cPtr->MaxClock = speed; 2851 } else { 2852 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 2853 "Max pixel clock is %7.3f MHz\n", 2854 (float)(cPtr->MaxClock / 1000.)); 2855 } 2856 2857 if (xf86LoadSubModule(pScrn, "ddc")) { 2858 if (cPtr->pVbe) 2859 xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); 2860 } 2861 return TRUE; 2862} 2863 2864static Bool 2865chipsPreInit655xx(ScrnInfoPtr pScrn, int flags) 2866{ 2867 int i, bytesPerPixel, NoClocks = 0; 2868 unsigned char tmp; 2869 MessageType from; 2870 vgaHWPtr hwp; 2871 CHIPSPtr cPtr = CHIPSPTR(pScrn); 2872 CHIPSPanelSizePtr Size = &cPtr->PanelSize; 2873 CHIPSClockPtr SaveClk = &(cPtr->SavedReg.Clock); 2874 Bool useLinear = FALSE; 2875 char *s; 2876#ifndef XSERVER_LIBPCIACCESS 2877 resRange linearRes[] = { {ResExcMemBlock|ResBios|ResBus,0,0},_END }; 2878#endif 2879 2880 /* Set pScrn->monitor */ 2881 pScrn->monitor = pScrn->confScreen->monitor; 2882 2883 if (cPtr->Flags & ChipsHDepthSupport) 2884 i = xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | 2885 SupportConvert32to24 | PreferConvert32to24); 2886 else 2887 i = xf86SetDepthBpp(pScrn, 8, 0, 0, NoDepth24Support); 2888 2889 if (!i) 2890 return FALSE; 2891 else { 2892 /* Check that the returned depth is one we support */ 2893 switch (pScrn->depth) { 2894 case 1: 2895 case 4: 2896 case 8: 2897 /* OK */ 2898 break; 2899 case 15: 2900 case 16: 2901 case 24: 2902 if (cPtr->Flags & ChipsHDepthSupport) 2903 break; /* OK */ 2904 /* fall through */ 2905 default: 2906 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 2907 "Given depth (%d) is not supported by this driver\n", 2908 pScrn->depth); 2909 return FALSE; 2910 } 2911 } 2912 xf86PrintDepthBpp(pScrn); 2913 2914 /* Get the depth24 pixmap format */ 2915 if (pScrn->depth == 24 && pix24bpp == 0) 2916 pix24bpp = xf86GetBppFromDepth(pScrn, 24); 2917 2918 /* 2919 * Allocate a vgaHWRec, this must happen after xf86SetDepthBpp for 1bpp 2920 */ 2921 if (!vgaHWGetHWRec(pScrn)) 2922 return FALSE; 2923 2924 hwp = VGAHWPTR(pScrn); 2925 vgaHWGetIOBase(hwp); 2926 2927 /* 2928 * This must happen after pScrn->display has been set because 2929 * xf86SetWeight references it. 2930 */ 2931 if (pScrn->depth > 8) { 2932 /* The defaults are OK for us */ 2933 rgb zeros = {0, 0, 0}; 2934 2935 if (!xf86SetWeight(pScrn, zeros, zeros)) { 2936 return FALSE; 2937 } else { 2938 /* XXX check that weight returned is supported */ 2939 ; 2940 } 2941 } 2942 2943 if (!xf86SetDefaultVisual(pScrn, -1)) 2944 return FALSE; 2945 2946 /* The gamma fields must be initialised when using the new cmap code */ 2947 if (pScrn->depth > 1) { 2948 Gamma zeros = {0.0, 0.0, 0.0}; 2949 2950 if (!xf86SetGamma(pScrn, zeros)) 2951 return FALSE; 2952 } 2953 2954 /* Store register values that might be messed up by a suspend resume */ 2955 /* Do this early as some of the other code in PreInit relies on it */ 2956 cPtr->SuspendHack.xr02 = (cPtr->readXR(cPtr, 0x02)) & 0x18; 2957 cPtr->SuspendHack.xr03 = (cPtr->readXR(cPtr, 0x03)) & 0x0A; 2958 cPtr->SuspendHack.xr14 = (cPtr->readXR(cPtr, 0x14)) & 0x20; 2959 cPtr->SuspendHack.xr15 = cPtr->readXR(cPtr, 0x15); 2960 2961 cPtr->SuspendHack.vgaIOBaseFlag = ((hwp->readMiscOut(hwp)) & 0x01); 2962 cPtr->IOBase = cPtr->SuspendHack.vgaIOBaseFlag ? 0x3D0 : 0x3B0; 2963 2964 bytesPerPixel = max(1, pScrn->bitsPerPixel >> 3); 2965 2966 /* Collect all of the relevant option flags (fill in pScrn->options) */ 2967 xf86CollectOptions(pScrn, NULL); 2968 2969 /* Process the options */ 2970 if (!(cPtr->Options = xalloc(sizeof(Chips655xxOptions)))) 2971 return FALSE; 2972 memcpy(cPtr->Options, Chips655xxOptions, sizeof(Chips655xxOptions)); 2973 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, cPtr->Options); 2974 2975 /* Set the bits per RGB */ 2976 if (pScrn->depth > 1) { 2977 /* Default to 6, is this right */ 2978 pScrn->rgbBits = 6; 2979#if 0 2980 if (xf86GetOptValInteger(cPtr->Options, OPTION_RGB_BITS, 2981 &pScrn->rgbBits)) { 2982 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n", 2983 pScrn->rgbBits); 2984 } 2985#endif 2986 } 2987 if ((cPtr->Flags & ChipsAccelSupport) && 2988 (xf86ReturnOptValBool(cPtr->Options, OPTION_NOACCEL, FALSE))) { 2989 cPtr->Flags &= ~ChipsAccelSupport; 2990 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 2991 } 2992 2993 from = X_DEFAULT; 2994 if (pScrn->bitsPerPixel < 8) { 2995 /* Default to SW cursor for 1/4 bpp */ 2996 cPtr->Accel.UseHWCursor = FALSE; 2997 } else { 2998 cPtr->Accel.UseHWCursor = TRUE; 2999 } 3000 if (xf86GetOptValBool(cPtr->Options, OPTION_HW_CURSOR, 3001 &cPtr->Accel.UseHWCursor)) 3002 from = X_CONFIG; 3003 if (xf86GetOptValBool(cPtr->Options, OPTION_SW_CURSOR, 3004 &cPtr->Accel.UseHWCursor)) { 3005 from = X_CONFIG; 3006 cPtr->Accel.UseHWCursor = !cPtr->Accel.UseHWCursor; 3007 } 3008 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 3009 (cPtr->Accel.UseHWCursor) ? "HW" : "SW"); 3010 3011 /* memory size */ 3012 if (cPtr->pEnt->device->videoRam != 0) { 3013 pScrn->videoRam = cPtr->pEnt->device->videoRam; 3014 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "VideoRAM: %d kByte\n", 3015 pScrn->videoRam); 3016 } else { 3017 /* not given, probe it */ 3018 /* XR0F: Software flags 0 */ 3019 /* bit 1-0: memory size */ 3020 /* 0: 256 kB */ 3021 /* 1: 512 kB */ 3022 /* 2: 1024 kB */ 3023 /* 3: 1024 kB */ 3024 3025 switch ((cPtr->readXR(cPtr, 0x0F)) & 3) { 3026 case 0: 3027 pScrn->videoRam = 256; 3028 break; 3029 case 1: 3030 pScrn->videoRam = 512; 3031 break; 3032 case 2: 3033 case 3: 3034 pScrn->videoRam = 1024; 3035 break; 3036 } 3037 3038 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VideoRAM: %d kByte\n", 3039 pScrn->videoRam); 3040 } 3041 cPtr->FbMapSize = pScrn->videoRam * 1024; 3042 3043 /* Default to nonlinear for < 8bpp and linear for >= 8bpp. */ 3044 if (cPtr->Flags & ChipsLinearSupport) useLinear = TRUE; 3045 if (pScrn->bitsPerPixel < 8) { 3046 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) { 3047 useLinear = FALSE; 3048 from = X_CONFIG; 3049 } 3050 } else if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, TRUE)) { 3051 useLinear = FALSE; 3052 from = X_CONFIG; 3053 } 3054 3055#ifndef HAVE_ISA 3056 if (!(cPtr->Flags & ChipsLinearSupport)) { 3057 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Linear framebuffer required\n"); 3058 return FALSE; 3059 } 3060#endif 3061 3062 /* linear base */ 3063 if (useLinear) { 3064 unsigned char mask; 3065 if (cPtr->Chipset == CHIPS_CT65535) { 3066 mask = (pScrn->videoRam > 512) ? 0xF8 :0xFC; 3067 if (cPtr->Bus == ChipsISA) 3068 mask &= 0x7F; 3069 } else if (cPtr->Bus == ChipsISA) { 3070 mask = 0x0F; 3071 } else { 3072 mask = 0xFF; 3073 tmp = cPtr->readXR(cPtr, 0x01); 3074 if(tmp & 0x40) 3075 mask &= 0x3F; 3076 if(!(tmp & 0x80)) 3077 mask &= 0xCF; 3078 } 3079 if (cPtr->pEnt->location.type == BUS_PCI) { 3080 cPtr->FbAddress = PCI_REGION_BASE(cPtr->PciInfo, 0, REGION_MEM) & 0xff800000; 3081#ifndef XSERVER_LIBPCIACCESS 3082 if (xf86RegisterResources(cPtr->pEnt->index,NULL,ResNone)) { 3083 useLinear = FALSE; 3084 from = X_PROBED; 3085 } 3086#endif 3087 } else { 3088 if (cPtr->pEnt->device->MemBase) { 3089 cPtr->FbAddress = cPtr->pEnt->device->MemBase; 3090 if (cPtr->Chipset == CHIPS_CT65535) 3091 cPtr->FbAddress &= (mask << 17); 3092 else if (cPtr->Chipset > CHIPS_CT65535) 3093 cPtr->FbAddress &= (mask << 20); 3094 from = X_CONFIG; 3095 } else { 3096 if (cPtr->Chipset <= CHIPS_CT65530) { 3097 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3098 "base address assumed at 0xC00000!\n"); 3099 cPtr->FbAddress = 0xC00000; 3100 from = X_CONFIG; 3101 } else if (cPtr->Chipset == CHIPS_CT65535) { 3102 cPtr->FbAddress = 3103 ((mask & (cPtr->readXR(cPtr, 0x08))) << 17); 3104 } else { 3105 cPtr->FbAddress = 3106 ((mask & (cPtr->readXR(cPtr, 0x08))) << 20); 3107 } 3108 from = X_PROBED; 3109 } 3110#ifndef XSERVER_LIBPCIACCESS 3111 linearRes[0].rBegin = cPtr->FbAddress; 3112 linearRes[0].rEnd = cPtr->FbAddress + 0x800000; 3113 if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { 3114 useLinear = FALSE; 3115 from = X_PROBED; 3116 } 3117#endif 3118 } 3119 } 3120 3121 if (useLinear) { 3122 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3123 "Enabling linear addressing\n"); 3124 xf86DrvMsg(pScrn->scrnIndex, from, 3125 "base address is set at 0x%lX.\n", cPtr->FbAddress); 3126 if (xf86ReturnOptValBool(cPtr->Options, OPTION_MMIO, FALSE) && 3127 (cPtr->Flags & ChipsMMIOSupport)) { 3128 cPtr->UseMMIO = TRUE; 3129 cPtr->IOAddress = cPtr->FbAddress + 0x200000L; 3130 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Enabling MMIO\n"); 3131 } 3132 } else { 3133 if (cPtr->Flags & ChipsLinearSupport) 3134 xf86DrvMsg(pScrn->scrnIndex, from, 3135 "Disabling linear addressing\n"); 3136 cPtr->Flags &= ~ChipsLinearSupport; 3137 } 3138 3139 if ((s = xf86GetOptValString(cPtr->Options, OPTION_ROTATE)) 3140 || xf86ReturnOptValBool(cPtr->Options, OPTION_SHADOW_FB, FALSE)) { 3141 if (!(cPtr->Flags & ChipsLinearSupport)) { 3142 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3143 "Option \"ShadowFB\" ignored. Not supported without linear addressing\n"); 3144 } else if (pScrn->depth < 8) { 3145 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3146 "Option \"ShadowFB\" ignored. Not supported at this depth.\n"); 3147 } else { 3148 cPtr->Rotate = 0; 3149 if (s) { 3150 if(!xf86NameCmp(s, "CW")) { 3151 /* accel is disabled below for shadowFB */ 3152 cPtr->Flags |= ChipsShadowFB; 3153 cPtr->Rotate = 1; 3154 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3155 "Rotating screen clockwise\n"); 3156 } else if(!xf86NameCmp(s, "CCW")) { 3157 cPtr->Flags |= ChipsShadowFB; 3158 cPtr->Rotate = -1; 3159 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Rotating screen" 3160 "counter clockwise\n"); 3161 } else { 3162 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid" 3163 "value for Option \"Rotate\"\n", s); 3164 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3165 "Valid options are \"CW\" or \"CCW\"\n"); 3166 } 3167 } else { 3168 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3169 "Using \"Shadow Framebuffer\"\n"); 3170 cPtr->Flags |= ChipsShadowFB; 3171 } 3172 } 3173 } 3174 if (cPtr->Flags & ChipsShadowFB) { 3175 if (cPtr->Flags & ChipsAccelSupport) { 3176 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3177 "HW acceleration is not supported with shadow fb\n"); 3178 cPtr->Flags &= ~ChipsAccelSupport; 3179 } 3180 if (cPtr->Rotate && cPtr->Accel.UseHWCursor) { 3181 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3182 "HW cursor is not supported with rotate\n"); 3183 cPtr->Accel.UseHWCursor = FALSE; 3184 } 3185 } 3186 3187 /*test STN / TFT */ 3188 tmp = cPtr->readXR(cPtr, 0x51); 3189 3190 /* XR51 or FR10: DISPLAY TYPE REGISTER */ 3191 /* XR51[1-0] or FR10[1:0] for ct65550 : PanelType, */ 3192 /* 0 = Single Panel Single Drive, 3 = Dual Panel Dual Drive */ 3193 switch (tmp & 0x3) { 3194 case 0: 3195 if (xf86ReturnOptValBool(cPtr->Options, OPTION_STN, FALSE)) { 3196 cPtr->PanelType |= ChipsSS; 3197 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "SS-STN probed\n"); 3198 } else { 3199 cPtr->PanelType |= ChipsTFT; 3200 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "TFT probed\n"); 3201 } 3202 break; 3203 case 2: 3204 cPtr->PanelType |= ChipsDS; 3205 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DS-STN probed\n"); 3206 case 3: 3207 cPtr->PanelType |= ChipsDD; 3208 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "DD-STN probed\n"); 3209 break; 3210 default: 3211 break; 3212 } 3213 3214 chipsSetPanelType(cPtr); 3215 from = X_PROBED; 3216 { 3217 Bool fp_mode; 3218 if (xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_mode)) { 3219 if (fp_mode) { 3220 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode on\n"); 3221 cPtr->PanelType |= ChipsLCD; 3222 } else { 3223 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Forcing FP Mode off\n"); 3224 cPtr->PanelType = ~ChipsLCD; 3225 } 3226 from = X_CONFIG; 3227 } 3228 } 3229 if ((cPtr->PanelType & ChipsLCD) && (cPtr->PanelType & ChipsCRT)) 3230 xf86DrvMsg(pScrn->scrnIndex, from, "LCD/CRT\n"); 3231 else if (cPtr->PanelType & ChipsLCD) 3232 xf86DrvMsg(pScrn->scrnIndex, from, "LCD\n"); 3233 else if (cPtr->PanelType & ChipsCRT) { 3234 xf86DrvMsg(pScrn->scrnIndex, from, "CRT\n"); 3235 /* monitor info */ 3236 cPtr->Monitor = chipsSetMonitor(pScrn); 3237 } 3238 3239 /* screen size */ 3240 /* 3241 * In LCD mode / dual mode we want to derive the timing values from 3242 * the ones preset by bios 3243 */ 3244 if (cPtr->PanelType & ChipsLCD) { 3245 unsigned char xr17, tmp1; 3246 char tmp2; 3247 3248 xr17 = cPtr->readXR(cPtr, 0x17); 3249 tmp = cPtr->readXR(cPtr, 0x1B); 3250 Size->HTotal =((tmp + ((xr17 & 0x01) << 8)) + 5) << 3; 3251 tmp = cPtr->readXR(cPtr, 0x1C); 3252 Size->HDisplay = ((tmp + ((xr17 & 0x02) << 7)) + 1) << 3; 3253 tmp = cPtr->readXR(cPtr, 0x19); 3254 Size->HRetraceStart = ((tmp + ((xr17 & 0x04) << 9)) + 1) << 3; 3255 tmp1 = cPtr->readXR(cPtr, 0x1A); 3256 tmp2 = (tmp1 & 0x1F) + ((xr17 & 0x08) << 2) - (tmp & 0x3F); 3257 Size->HRetraceEnd = ((((tmp2 & 0x080u) ? (tmp2 + 0x40) : tmp2) << 3) 3258 + Size->HRetraceStart); 3259 tmp1 = cPtr->readXR(cPtr, 0x65); 3260 tmp = cPtr->readXR(cPtr, 0x68); 3261 Size->VDisplay = ((tmp1 & 0x02) << 7) 3262 + ((tmp1 & 0x40) << 3) + tmp + 1; 3263 tmp = cPtr->readXR(cPtr, 0x66); 3264 Size->VRetraceStart = ((tmp1 & 0x04) << 6) 3265 + ((tmp1 & 0x80) << 2) + tmp + 1; 3266 tmp = cPtr->readXR(cPtr, 0x64); 3267 Size->VTotal = ((tmp1 & 0x01) << 8) 3268 + ((tmp1 & 0x20) << 4) + tmp + 2; 3269#ifdef DEBUG 3270 ErrorF("x=%i, y=%i; xSync=%i, xSyncEnd=%i, xTotal=%i\n", 3271 Size->HDisplay, Size->VDisplay, 3272 Size->HRetraceStart, Size->HRetraceEnd, 3273 Size->HTotal); 3274#endif 3275 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Display Size: x=%i; y=%i\n", 3276 Size->HDisplay, Size->VDisplay); 3277 /* Warn the user if the panel size has been overridden by 3278 * the modeline values 3279 */ 3280 if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { 3281 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3282 "Display size overridden by modelines.\n"); 3283 } 3284 } 3285 3286 /* Frame Buffer */ /* for LCDs */ 3287 if (IS_STN(cPtr->PanelType)) { 3288 tmp = cPtr->readXR(cPtr, 0x6F); /*Frame Buffer Ctrl. */ 3289 if (tmp & 1) { 3290 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Frame Buffer used\n"); 3291 if ((cPtr->Chipset > CHIPS_CT65530) && !(tmp & 0x80)) { 3292 /* Formula for calculating the size of the framebuffer. 3 3293 * bits per pixel 10 pixels per 32 bit dword. If frame 3294 * acceleration is enabled the size can be halved. 3295 */ 3296 cPtr->FrameBufferSize = ( Size->HDisplay * 3297 Size->VDisplay / 5 ) * ((tmp & 2) ? 1 : 2); 3298 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3299 "Using embedded Frame Buffer, size %d bytes\n", 3300 cPtr->FrameBufferSize); 3301 } else 3302 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3303 "Using external Frame Buffer used\n"); 3304 } 3305 if (tmp & 2) 3306 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3307 "Frame accelerator enabled\n"); 3308 } 3309 3310 /* bus type */ 3311 if (cPtr->Chipset > CHIPS_CT65535) { 3312 tmp = (cPtr->readXR(cPtr, 0x01)) & 7; 3313 if (tmp == 6) { /*PCI */ 3314 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PCI Bus\n"); 3315 cPtr->Bus = ChipsPCI; 3316 if ((cPtr->Chipset == CHIPS_CT65545) || 3317 (cPtr->Chipset == CHIPS_CT65546)) { 3318 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3319 "32Bit IO not supported on 65545 PCI\n"); 3320 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "\tenabling MMIO\n"); 3321 cPtr->UseMMIO = TRUE; 3322 cPtr->IOAddress = cPtr->FbAddress + 0x200000L; 3323 } 3324 3325 } else { /* XR08: Linear addressing base, not for PCI */ 3326 switch (tmp) { 3327 case 3: 3328 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "CPU Direct\n"); 3329 cPtr->Bus = ChipsCPUDirect; 3330 break; 3331 case 5: 3332 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); 3333 cPtr->Bus = ChipsISA; 3334 break; 3335 case 7: 3336 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); 3337 cPtr->Bus = ChipsVLB; 3338 break; 3339 default: 3340 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Unknown Bus\n"); 3341 } 3342 } 3343 } else { 3344 tmp = (cPtr->readXR(cPtr, 0x01)) & 3; 3345 switch (tmp) { 3346 case 0: 3347 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "PI Bus\n"); 3348 cPtr->Bus = ChipsPIB; 3349 break; 3350 case 1: 3351 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MC Bus\n"); 3352 cPtr->Bus = ChipsMCB; 3353 break; 3354 case 2: 3355 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "VL Bus\n"); 3356 cPtr->Bus = ChipsVLB; 3357 break; 3358 case 3: 3359 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "ISA Bus\n"); 3360 cPtr->Bus = ChipsISA; 3361 break; 3362 } 3363 } 3364 3365 if (!(cPtr->Bus == ChipsPCI) && (cPtr->UseMMIO)) { 3366 cPtr->UseMMIO = FALSE; 3367 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3368 "MMIO only supported on PCI Bus. Disabling MMIO\n"); 3369 } 3370 3371 /* disable acceleration for 1 and 4 bpp */ 3372 if (pScrn->bitsPerPixel < 8) { 3373 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3374 "Disabling acceleration for %d bpp\n", pScrn->bitsPerPixel); 3375 cPtr->Flags &= ~ChipsAccelSupport; 3376 } 3377 3378 if ((cPtr->Chipset == CHIPS_CT65530) && 3379 (cPtr->Flags & ChipsLinearSupport)) { 3380 /* linear mode is no longer default on ct65530 since it */ 3381 /* requires additional hardware which some manufacturers*/ 3382 /* might not provide. */ 3383 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LINEAR, FALSE)) 3384 cPtr->Flags &= ~ChipsLinearSupport; 3385 3386 /* Test wether linear addressing is possible on 65530 */ 3387 /* on the 65530 only the A19 select scheme can be used*/ 3388 /* for linear addressing since MEMW is used on ISA bus*/ 3389 /* systems. */ 3390 /* A19 however is used if video memory is > 512 Mb */ 3391 if ((cPtr->Bus == ChipsISA) && (pScrn->videoRam > 512)) { 3392 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3393 "User selected linear fb not supported by HW!\n"); 3394 cPtr->Flags &= ~ChipsLinearSupport; 3395 } 3396 } 3397 3398 /* DAC info */ 3399 if ((cPtr->readXR(cPtr, 0x06)) & 0x02) 3400 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Internal DAC disabled\n"); 3401 3402 /* MMIO address offset */ 3403 if (cPtr->UseMMIO) 3404 cPtr->Regs32 = ChipsReg32; 3405 else if ((cPtr->Flags & ChipsAccelSupport) || 3406 (cPtr->Accel.UseHWCursor)) { 3407 cPtr->Regs32 = xnfalloc(sizeof(ChipsReg32)); 3408 tmp = cPtr->readXR(cPtr, 0x07); 3409 for (i = 0; i < (sizeof(ChipsReg32)/sizeof(ChipsReg32[0])); i++) { 3410 cPtr->Regs32[i] = 3411 ((ChipsReg32[i] & 0x7E03)) | ((tmp & 0x80)<< 8) 3412 | ((tmp & 0x7F) << 2); 3413#ifdef DEBUG 3414 ErrorF("DR[%X] = %X\n",i,cPtr->Regs32[i]); 3415#endif 3416 } 3417#ifndef XSERVER_LIBPCIACCESS 3418 linearRes[0].type = ResExcIoSparse | ResBios | ResBus; 3419 linearRes[0].rBase = cPtr->Regs32[0]; 3420 linearRes[0].rMask = 0x83FC; 3421 if (xf86RegisterResources(cPtr->pEnt->index,linearRes,ResNone)) { 3422 if (cPtr->Flags & ChipsAccelSupport) { 3423 cPtr->Flags &= ~ChipsAccelSupport; 3424 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3425 "Cannot allocate IO registers: " 3426 "Disabling acceleration\n"); 3427 } 3428 if (cPtr->Accel.UseHWCursor) { 3429 cPtr->Accel.UseHWCursor = FALSE; 3430 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3431 "Cannot allocate IO registers: " 3432 "Disabling HWCursor\n"); 3433 } 3434 } 3435#endif 3436 } 3437 3438 /* sync reset ignored on this chipset */ 3439 if (cPtr->Chipset > CHIPS_CT65530) { 3440 tmp = cPtr->readXR(cPtr, 0x0E); 3441 if (tmp & 0x80) 3442 cPtr->SyncResetIgn = TRUE; 3443 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3444 "Synchronous reset %signored.\n", 3445 (cPtr->SyncResetIgn ? "" : "not ")); 3446 } 3447 3448 cPtr->ClockMulFactor = ((pScrn->bitsPerPixel >= 8) ? bytesPerPixel : 1); 3449 if (cPtr->ClockMulFactor != 1) 3450 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3451 "Clocks scaled by %d\n", cPtr->ClockMulFactor); 3452 /* We use a programmable clock */ 3453 switch (cPtr->Chipset) { 3454 case CHIPS_CT65520: 3455 case CHIPS_CT65525: 3456 case CHIPS_CT65530: 3457 NoClocks = 4; /* Some number */ 3458 cPtr->ClockType = OLD_STYLE | TYPE_HW; 3459 break; 3460 default: 3461 if (xf86ReturnOptValBool(cPtr->Options, OPTION_HW_CLKS, FALSE)) { 3462 NoClocks = 5; /* Some number */ 3463 cPtr->ClockType = NEW_STYLE | TYPE_HW; 3464 } else { 3465 NoClocks = 26; /* Some number */ 3466 cPtr->ClockType = NEW_STYLE | TYPE_PROGRAMMABLE; 3467 pScrn->progClock = TRUE; 3468 } 3469 } 3470 3471 if (cPtr->ClockType & TYPE_PROGRAMMABLE) { 3472 pScrn->numClocks = NoClocks; 3473 if (cPtr->pEnt->device->textClockFreq > 0) { 3474 SaveClk->Clock = cPtr->pEnt->device->textClockFreq; 3475 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3476 "Using textclock freq: %7.3f.\n", 3477 SaveClk->Clock/1000.0); 3478 } else 3479 SaveClk->Clock = ((cPtr->PanelType & ChipsLCDProbed) ? 3480 LCD_TEXT_CLK_FREQ : CRT_TEXT_CLK_FREQ); 3481 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Using programmable clocks\n"); 3482 } else { /* TYPE_PROGRAMMABLE */ 3483 SaveClk->Clock = chipsGetHWClock(pScrn); 3484 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using textclock clock %i.\n", 3485 SaveClk->Clock); 3486 if (!cPtr->pEnt->device->numclocks) { 3487 pScrn->numClocks = NoClocks; 3488 xf86GetClocks(pScrn, NoClocks, chipsClockSelect, 3489 chipsProtect, chipsBlankScreen, 3490 cPtr->IOBase + 0x0A, 0x08, 1, 28322); 3491 from = X_PROBED; 3492 } else { 3493 pScrn->numClocks = cPtr->pEnt->device->numclocks; 3494 if (pScrn->numClocks > NoClocks) { 3495 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3496 "Too many Clocks specified in configuration file.\n"); 3497 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3498 "\t\tAt most %d clocks may be specified\n", NoClocks); 3499 pScrn->numClocks = NoClocks; 3500 } 3501 for (i = 0; i < pScrn->numClocks; i++) 3502 pScrn->clock[i] = cPtr->pEnt->device->clock[i]; 3503 from = X_CONFIG; 3504 } 3505 xf86ShowClocks(pScrn, from); 3506 } 3507 /* Set the min pixel clock */ 3508 /* XXX Guess, need to check this */ 3509 cPtr->MinClock = 11000 / cPtr->ClockMulFactor; 3510 xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %7.3f MHz\n", 3511 (float)(cPtr->MinClock / 1000.)); 3512 /* Set the max pixel clock */ 3513 switch (cPtr->Chipset) { 3514 case CHIPS_CT65546: 3515 case CHIPS_CT65548: 3516 /* max VCLK is 80 MHz, max MCLK is 75 MHz for CT65548 */ 3517 /* It is not sure for CT65546, but it works with 60 nsec EDODRAM */ 3518 cPtr->MaxClock = 80000 / cPtr->ClockMulFactor; 3519 break; 3520 default: 3521 if ((cPtr->readXR(cPtr, 0x6C)) & 2) { 3522 /*5V Vcc */ 3523 cPtr->MaxClock = 68000 / cPtr->ClockMulFactor; 3524 } else { 3525 /*3.3V Vcc */ 3526 cPtr->MaxClock = 56000 / cPtr->ClockMulFactor; 3527 } 3528 } 3529 3530 if (cPtr->pEnt->device->dacSpeeds[0]) { 3531 int speed = 0; 3532 switch (pScrn->bitsPerPixel) { 3533 case 1: 3534 case 4: 3535 case 8: 3536 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP8]; 3537 break; 3538 case 16: 3539 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP16]; 3540 break; 3541 case 24: 3542 speed = cPtr->pEnt->device->dacSpeeds[DAC_BPP24]; 3543 break; 3544 } 3545 if (speed == 0) 3546 cPtr->MaxClock = cPtr->pEnt->device->dacSpeeds[0]; 3547 from = X_CONFIG; 3548 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3549 "User max pixel clock of %7.3f MHz overrides %7.3f MHz limit\n", 3550 (float)(cPtr->MaxClock / 1000.), (float)(speed / 1000.)); 3551 cPtr->MaxClock = speed; 3552 } else { 3553 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3554 "Max pixel clock is %7.3f MHz\n", 3555 (float)(cPtr->MaxClock / 1000.)); 3556 } 3557 3558 /* FP clock */ 3559 if (cPtr->ClockType & TYPE_PROGRAMMABLE) { 3560 double real = 0; 3561 3562 switch(bytesPerPixel) { 3563 case 1: 3564 xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_8, 3565 OPTUNITS_MHZ, &real); 3566 break; 3567 case 2: 3568 xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_16, 3569 OPTUNITS_MHZ, &real); 3570 break; 3571 case 3: 3572 xf86GetOptValFreq(cPtr->Options, OPTION_FP_CLOCK_24, 3573 OPTUNITS_MHZ, &real); 3574 break; 3575 } 3576 3577 if (real > 0) { 3578 int val; 3579 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3580 "FP clock %7.3f MHz requested\n",real); 3581 val = (int) (real * 1000.); 3582 if (val && (val >= cPtr->MinClock) 3583 && (val <= cPtr->MaxClock)) 3584 cPtr->FPclock = val * cPtr->ClockMulFactor; 3585 else if (val > cPtr->MaxClock) 3586 cPtr->FPclock = (int)((float)cPtr->MaxClock 3587 * cPtr->ClockMulFactor * 0.9); 3588 else 3589 cPtr->FPclock = 0; /* special value */ 3590 } else 3591 cPtr->FPclock = 0; /* special value */ 3592 3593 if (cPtr->FPclock) 3594 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 3595 "FP clock set to %7.3f MHz\n", 3596 (float)(cPtr->FPclock / 1000.)); 3597 } else { 3598 if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) 3599 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3600 "FP clock option not supported for this chipset\n"); 3601 } 3602 3603 /* Memory Clock */ 3604 if (cPtr->ClockType & TYPE_PROGRAMMABLE) { 3605 double real; 3606 3607 switch (cPtr->Chipset) { 3608 case CHIPS_CT65546: 3609 case CHIPS_CT65548: 3610 /* max MCLK is 75 MHz for CT65548 */ 3611 cPtr->MemClock.Max = 75000; 3612 break; 3613 default: 3614 if ((cPtr->readXR(cPtr, 0x6C)) & 2) { 3615 /*5V Vcc */ 3616 cPtr->MemClock.Max = 68000; 3617 } else { 3618 /*3.3V Vcc */ 3619 cPtr->MemClock.Max = 56000; 3620 } 3621 } 3622 3623 if (xf86GetOptValFreq(cPtr->Options, OPTION_SET_MCLK, 3624 OPTUNITS_MHZ, &real)) { 3625 int mclk = (int)(real * 1000.0); 3626 if (mclk <= cPtr->MemClock.Max) { 3627 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3628 "Using memory clock of %7.3f MHz\n", 3629 (float)(mclk/1000.)); 3630 cPtr->MemClock.Clk = mclk; 3631 } else { 3632 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, 3633 "Memory clock of %7.3f MHz exceeds limit of " 3634 "%7.3f MHz\n",(float)(mclk/1000.), 3635 (float)(cPtr->MemClock.Max/1000.)); 3636 cPtr->MemClock.Clk = cPtr->MemClock.Max * 0.9; 3637 } 3638 } else 3639 cPtr->MemClock.Clk = 0; 3640 } else 3641 if (xf86IsOptionSet(cPtr->Options, OPTION_SET_MCLK)) 3642 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 3643 "Memory clock option not supported for this chipset\n"); 3644 3645 if (xf86LoadSubModule(pScrn, "ddc")) { 3646 if (cPtr->pVbe) 3647 xf86SetDDCproperties(pScrn,xf86PrintEDID(vbeDoEDID(cPtr->pVbe, NULL))); 3648 } 3649 return TRUE; 3650} 3651 3652 3653/* Mandatory */ 3654static Bool 3655CHIPSEnterVT(int scrnIndex, int flags) 3656{ 3657 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3658 CHIPSPtr cPtr = CHIPSPTR(pScrn); 3659 CHIPSEntPtr cPtrEnt; 3660 3661 if (cPtr->Flags & ChipsDualChannelSupport) { 3662 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 3663 CHIPSEntityIndex)->ptr; 3664 DUALOPEN; 3665 } 3666 /* Should we re-save the text mode on each VT enter? */ 3667 if(!chipsModeInit(pScrn, pScrn->currentMode)) 3668 return FALSE; 3669 if ((!(cPtr->Flags & ChipsOverlay8plus16)) 3670 && (cPtr->Flags & ChipsVideoSupport) 3671 && (cPtr->Flags & ChipsLinearSupport)) 3672 CHIPSResetVideo(pScrn); 3673 3674 /*usleep(50000);*/ 3675 chipsHWCursorOn(cPtr, pScrn); 3676 /* cursor settle delay */ 3677 usleep(50000); 3678 CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3679 usleep(50000); 3680 return TRUE; 3681} 3682 3683/* Mandatory */ 3684static void 3685CHIPSLeaveVT(int scrnIndex, int flags) 3686{ 3687 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 3688 CHIPSPtr cPtr = CHIPSPTR(pScrn); 3689 CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); 3690 CHIPSEntPtr cPtrEnt; 3691 3692 /* Invalidate the cached acceleration registers */ 3693 cAcl->planemask = -1; 3694 cAcl->fgColor = -1; 3695 cAcl->bgColor = -1; 3696 3697 if (cPtr->Flags & ChipsDualChannelSupport) { 3698 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 3699 CHIPSEntityIndex)->ptr; 3700 if (cPtr->UseDualChannel) 3701 DUALREOPEN; 3702 DUALCLOSE; 3703 } else { 3704 chipsHWCursorOff(cPtr, pScrn); 3705 chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, 3706 TRUE); 3707 chipsLock(pScrn); 3708 } 3709} 3710 3711 3712static void 3713chipsLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, LOCO *colors, 3714 VisualPtr pVisual) 3715{ 3716 vgaHWPtr hwp = VGAHWPTR(pScrn); 3717 CHIPSPtr cPtr = CHIPSPTR(pScrn); 3718 int i, index, shift ; 3719 CHIPSEntPtr cPtrEnt; 3720 3721 shift = ((pScrn->depth == 15) && 3722 (!(cPtr->Flags & ChipsOverlay8plus16))) ? 3 : 0; 3723 3724 if (cPtr->UseDualChannel) { 3725 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 3726 CHIPSEntityIndex)->ptr; 3727 DUALREOPEN; 3728 } 3729 3730 for (i = 0; i < numColors; i++) { 3731 index = indices[i]; 3732 hwp->writeDacWriteAddr(hwp,index << shift); 3733 DACDelay(hwp); 3734 hwp->writeDacData(hwp, colors[index].red); 3735 DACDelay(hwp); 3736 hwp->writeDacData(hwp, colors[index].green); 3737 DACDelay(hwp); 3738 hwp->writeDacData(hwp, colors[index].blue); 3739 DACDelay(hwp); 3740 } 3741 3742 if (cPtr->UseDualChannel && 3743 (! xf86IsEntityShared(pScrn->entityList[0]))) { 3744 unsigned int IOSS, MSS; 3745 IOSS = cPtr->readIOSS(cPtr); 3746 MSS = cPtr->readMSS(cPtr); 3747 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 3748 IOSS_PIPE_B)); 3749 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); 3750 3751 for (i = 0; i < numColors; i++) { 3752 index = indices[i]; 3753 hwp->writeDacWriteAddr(hwp,index << shift); 3754 DACDelay(hwp); 3755 hwp->writeDacData(hwp, colors[index].red); 3756 DACDelay(hwp); 3757 hwp->writeDacData(hwp, colors[index].green); 3758 DACDelay(hwp); 3759 hwp->writeDacData(hwp, colors[index].blue); 3760 DACDelay(hwp); 3761 } 3762 cPtr->writeIOSS(cPtr, IOSS); 3763 cPtr->writeMSS(cPtr, hwp, MSS); 3764 } 3765 3766 /* This shouldn't be necessary, but we'll play safe. */ 3767 hwp->disablePalette(hwp); 3768} 3769 3770static void 3771chipsLoadPalette16(ScrnInfoPtr pScrn, int numColors, int *indices, 3772 LOCO *colors, VisualPtr pVisual) 3773{ 3774 vgaHWPtr hwp = VGAHWPTR(pScrn); 3775 CHIPSPtr cPtr = CHIPSPTR(pScrn); 3776 CHIPSEntPtr cPtrEnt; 3777 3778 int i, index; 3779 3780 if (cPtr->UseDualChannel) { 3781 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 3782 CHIPSEntityIndex)->ptr; 3783 DUALREOPEN; 3784 } 3785 3786 for (i = 0; i < numColors; i++) { 3787 index = indices[i]; 3788 hwp->writeDacWriteAddr(hwp, index << 2); 3789 DACDelay(hwp); 3790 hwp->writeDacData(hwp, colors[index >> 1].red); 3791 DACDelay(hwp); 3792 hwp->writeDacData(hwp, colors[index].green); 3793 DACDelay(hwp); 3794 hwp->writeDacData(hwp, colors[index >> 1].blue); 3795 DACDelay(hwp); 3796 } 3797 3798 3799 if (cPtr->UseDualChannel && 3800 (! xf86IsEntityShared(pScrn->entityList[0]))) { 3801 unsigned int IOSS, MSS; 3802 IOSS = cPtr->readIOSS(cPtr); 3803 MSS = cPtr->readMSS(cPtr); 3804 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 3805 IOSS_PIPE_B)); 3806 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); 3807 3808 for (i = 0; i < numColors; i++) { 3809 index = indices[i]; 3810 hwp->writeDacWriteAddr(hwp, index << 2); 3811 DACDelay(hwp); 3812 hwp->writeDacData(hwp, colors[index >> 1].red); 3813 DACDelay(hwp); 3814 hwp->writeDacData(hwp, colors[index].green); 3815 DACDelay(hwp); 3816 hwp->writeDacData(hwp, colors[index >> 1].blue); 3817 DACDelay(hwp); 3818 } 3819 3820 cPtr->writeIOSS(cPtr, IOSS); 3821 cPtr->writeMSS(cPtr, hwp, MSS); 3822 } 3823 3824 /* This shouldn't be necessary, but we'll play safe. */ 3825 hwp->disablePalette(hwp); 3826} 3827 3828/* Mandatory */ 3829static Bool 3830CHIPSScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) 3831{ 3832 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 3833 vgaHWPtr hwp; 3834 CHIPSPtr cPtr; 3835 CHIPSACLPtr cAcl; 3836 int ret; 3837 int init_picture = 0; 3838 VisualPtr visual; 3839 int allocatebase, freespace, currentaddr; 3840 unsigned int racflag = 0; 3841 unsigned char *FBStart; 3842 int height, width, displayWidth; 3843 CHIPSEntPtr cPtrEnt = NULL; 3844#ifdef DEBUG 3845 ErrorF("CHIPSScreenInit\n"); 3846#endif 3847 3848 /* 3849 * we need to get the ScrnInfoRec for this screen, so let's allocate 3850 * one first thing 3851 */ 3852 cPtr = CHIPSPTR(pScrn); 3853 cAcl = CHIPSACLPTR(pScrn); 3854 3855 hwp = VGAHWPTR(pScrn); 3856 hwp->MapSize = 0x10000; /* Standard 64k VGA window */ 3857 3858 /* Map the VGA memory */ 3859 if (!vgaHWMapMem(pScrn)) 3860 return FALSE; 3861 3862 /* Map the Chips memory and possible MMIO areas */ 3863 if (!chipsMapMem(pScrn)) 3864 return FALSE; 3865 3866 /* Setup a pointer to the overlay if needed */ 3867 if (cPtr->Flags & ChipsOverlay8plus16) { 3868 cPtr->FbOffset16 = pScrn->displayWidth * pScrn->virtualY; 3869 cPtr->FbSize16 = (pScrn->displayWidth << 1) * pScrn->virtualY; 3870 if (cPtr->FbSize16 > (cPtr->FbMapSize - cPtr->FrameBufferSize)) { 3871 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3872 "Too little memory for overlay. Disabling.\n"); 3873 cPtr->Flags &= ~ChipsOverlay8plus16; 3874 } 3875 if ((pScrn->displayWidth > 1024) || (pScrn->virtualY > 1024)) { 3876 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3877 "Max overlay Width/Height 1024 pixels. Disabling.\n"); 3878 cPtr->Flags &= ~ChipsOverlay8plus16; 3879 } 3880 } 3881 3882 /* Setup the MMIO register access functions if need */ 3883 if (cPtr->UseFullMMIO && cPtr->MMIOBaseVGA) { 3884 CHIPSSetMmioExtFuncs(cPtr); 3885 CHIPSHWSetMmioFuncs(pScrn, cPtr->MMIOBaseVGA, 0x0); 3886 } 3887 3888 if (cPtr->Flags & ChipsDualChannelSupport) { 3889 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 3890 CHIPSEntityIndex)->ptr; 3891 DUALOPEN; 3892 } 3893 3894#if defined(__arm__) && defined(___NetBSD__) 3895 if (strcmp(pScrn->currentMode->name,"PAL") == 0) { 3896 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using built-in PAL TV mode\n"); 3897 cPtr->TVMode = XMODE_PAL; 3898 } else if (strcmp(pScrn->currentMode->name,"SECAM") == 0){ 3899 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3900 "Using built-in SECAM TV mode\n"); 3901 cPtr->TVMode = XMODE_SECAM; 3902 } else if (strcmp(pScrn->currentMode->name,"NTSC") == 0) { 3903 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, 3904 "Using built-in NTSC TV mode\n"); 3905 cPtr->TVMode = XMODE_NTSC; 3906 } else 3907 cPtr->TVMode = XMODE_RGB; 3908#endif 3909 3910 /* 3911 * next we save the current state and setup the first mode 3912 */ 3913 if ((cPtr->Flags & ChipsDualChannelSupport) && 3914 (! xf86IsEntityShared(pScrn->entityList[0]))) { 3915 unsigned int IOSS, MSS; 3916 IOSS = cPtr->readIOSS(cPtr); 3917 MSS = cPtr->readMSS(cPtr); 3918 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 3919 IOSS_PIPE_A)); 3920 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_A)); 3921 chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); 3922 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 3923 IOSS_PIPE_B)); 3924 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); 3925 chipsSave(pScrn, &cPtr->VgaSavedReg2, &cPtr->SavedReg2); 3926 cPtr->writeIOSS(cPtr, IOSS); 3927 cPtr->writeMSS(cPtr, hwp, MSS); 3928 } else 3929 chipsSave(pScrn, &hwp->SavedReg, &cPtr->SavedReg); 3930 3931 if (!chipsModeInit(pScrn,pScrn->currentMode)) 3932 return FALSE; 3933 CHIPSSaveScreen(pScreen,SCREEN_SAVER_ON); 3934 CHIPSAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); 3935 3936 /* 3937 * The next step is to setup the screen's visuals, and initialise the 3938 * framebuffer code. In cases where the framebuffer's default 3939 * choices for things like visual layouts and bits per RGB are OK, 3940 * this may be as simple as calling the framebuffer's ScreenInit() 3941 * function. If not, the visuals will need to be setup before calling 3942 * a fb ScreenInit() function and fixed up after. 3943 * 3944 * For most PC hardware at depths >= 8, the defaults that cfb uses 3945 * are not appropriate. In this driver, we fixup the visuals after. 3946 */ 3947 3948 /* 3949 * Reset visual list. 3950 */ 3951 miClearVisualTypes(); 3952 3953 /* Setup the visuals we support. */ 3954 if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)){ 3955 if (!miSetVisualTypes(8, PseudoColorMask | GrayScaleMask, 3956 pScrn->rgbBits, PseudoColor)) 3957 return FALSE; 3958 if (!miSetVisualTypes(16, TrueColorMask, pScrn->rgbBits, TrueColor)) 3959 return FALSE; 3960 } else { 3961 if (!miSetVisualTypes(pScrn->depth, 3962 miGetDefaultVisualMask(pScrn->depth), 3963 pScrn->rgbBits, pScrn->defaultVisual)) 3964 return FALSE; 3965 } 3966 miSetPixmapDepths (); 3967 3968 /* 3969 * Call the framebuffer layer's ScreenInit function, and fill in other 3970 * pScreen fields. 3971 */ 3972 if ((cPtr->Flags & ChipsShadowFB) && cPtr->Rotate) { 3973 height = pScrn->virtualX; 3974 width = pScrn->virtualY; 3975 } else { 3976 width = pScrn->virtualX; 3977 height = pScrn->virtualY; 3978 } 3979 3980 if(cPtr->Flags & ChipsShadowFB) { 3981 cPtr->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width); 3982 cPtr->ShadowPtr = xalloc(cPtr->ShadowPitch * height); 3983 displayWidth = cPtr->ShadowPitch / (pScrn->bitsPerPixel >> 3); 3984 FBStart = cPtr->ShadowPtr; 3985 } else { 3986 cPtr->ShadowPtr = NULL; 3987 displayWidth = pScrn->displayWidth; 3988 FBStart = cPtr->FbBase; 3989 } 3990 3991 switch (pScrn->bitsPerPixel) { 3992#ifdef HAVE_XF1BPP 3993 case 1: 3994 ret = xf1bppScreenInit(pScreen, FBStart, 3995 width,height, 3996 pScrn->xDpi, pScrn->yDpi, 3997 displayWidth); 3998 break; 3999#endif 4000#ifdef HAVE_XF4BPP 4001 case 4: 4002 ret = xf4bppScreenInit(pScreen, FBStart, 4003 width,height, 4004 pScrn->xDpi, pScrn->yDpi, 4005 displayWidth); 4006 break; 4007#endif 4008 case 16: 4009 if (cPtr->Flags & ChipsOverlay8plus16) { 4010 ret = cfb8_16ScreenInit(pScreen, (unsigned char *)FBStart + 4011 cPtr->FbOffset16, FBStart, width, 4012 height, pScrn->xDpi, pScrn->yDpi, 4013 displayWidth, displayWidth); 4014 break; 4015 } 4016 default: 4017 ret = fbScreenInit(pScreen, FBStart, 4018 width,height, 4019 pScrn->xDpi, pScrn->yDpi, 4020 displayWidth,pScrn->bitsPerPixel); 4021 init_picture = 1; 4022 break; 4023 } 4024 4025 if (!ret) 4026 return FALSE; 4027 4028#if X_BYTE_ORDER == X_BIG_ENDIAN 4029 /* TODO : find a better way to do this */ 4030 if (pScrn->depth == 24) { 4031 int dummy ; 4032 /* Fixup RGB ordering in 24 BPP */ 4033 dummy = pScrn->offset.red ; 4034 pScrn->offset.red = pScrn->offset.blue; 4035 pScrn->offset.blue = dummy ; 4036 4037 dummy = pScrn->mask.red ; 4038 pScrn->mask.red = pScrn->mask.blue; 4039 pScrn->mask.blue = dummy ; 4040 } 4041#endif 4042 4043 if (pScrn->depth > 8) { 4044 /* Fixup RGB ordering */ 4045 visual = pScreen->visuals + pScreen->numVisuals; 4046 while (--visual >= pScreen->visuals) { 4047 if ((visual->class | DynamicClass) == DirectColor) { 4048 visual->offsetRed = pScrn->offset.red; 4049 visual->offsetGreen = pScrn->offset.green; 4050 visual->offsetBlue = pScrn->offset.blue; 4051 visual->redMask = pScrn->mask.red; 4052 visual->greenMask = pScrn->mask.green; 4053 visual->blueMask = pScrn->mask.blue; 4054 } 4055 } 4056 } 4057 4058 /* must be after RGB ordering fixed */ 4059 if (init_picture) 4060 fbPictureInit (pScreen, 0, 0); 4061 4062 xf86SetBlackWhitePixels(pScreen); 4063 4064 cPtr->BlockHandler = pScreen->BlockHandler; 4065 pScreen->BlockHandler = chipsBlockHandler; 4066 4067 if ( (pScrn->depth >= 8)) 4068 CHIPSDGAInit(pScreen); 4069 4070 cPtr->HWCursorShown = FALSE; 4071 4072#ifdef USE_MIBANK 4073 if (!(cPtr->Flags & ChipsLinearSupport)) { 4074 miBankInfoPtr pBankInfo; 4075 4076 /* Setup the vga banking variables */ 4077 pBankInfo = (miBankInfoPtr)xnfcalloc(sizeof(miBankInfoRec),1); 4078 if (pBankInfo == NULL) 4079 return FALSE; 4080 4081#if defined(__arm__) 4082 cPtr->Bank = -1; 4083#endif 4084 pBankInfo->pBankA = hwp->Base; 4085 pBankInfo->pBankB = (unsigned char *)hwp->Base + 0x08000; 4086 pBankInfo->BankSize = 0x08000; 4087 pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth; 4088 4089 if (IS_HiQV(cPtr)) { 4090 pBankInfo->pBankB = hwp->Base; 4091 pBankInfo->BankSize = 0x10000; 4092 if (pScrn->bitsPerPixel < 8) { 4093 pBankInfo->SetSourceBank = 4094 (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; 4095 pBankInfo->SetDestinationBank = 4096 (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; 4097 pBankInfo->SetSourceAndDestinationBanks = 4098 (miBankProcPtr)CHIPSHiQVSetReadWritePlanar; 4099 } else { 4100 pBankInfo->SetSourceBank = 4101 (miBankProcPtr)CHIPSHiQVSetReadWrite; 4102 pBankInfo->SetDestinationBank = 4103 (miBankProcPtr)CHIPSHiQVSetReadWrite; 4104 pBankInfo->SetSourceAndDestinationBanks = 4105 (miBankProcPtr)CHIPSHiQVSetReadWrite; 4106 } 4107 } else { 4108 if (IS_Wingine(cPtr)) { 4109 if (pScrn->bitsPerPixel < 8) { 4110 pBankInfo->SetSourceBank = 4111 (miBankProcPtr)CHIPSWINSetReadPlanar; 4112 pBankInfo->SetDestinationBank = 4113 (miBankProcPtr)CHIPSWINSetWritePlanar; 4114 pBankInfo->SetSourceAndDestinationBanks = 4115 (miBankProcPtr)CHIPSWINSetReadWritePlanar; 4116 } else { 4117 pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSWINSetRead; 4118 pBankInfo->SetDestinationBank = 4119 (miBankProcPtr)CHIPSWINSetWrite; 4120 pBankInfo->SetSourceAndDestinationBanks = 4121 (miBankProcPtr)CHIPSWINSetReadWrite; 4122 } 4123 } else { 4124 if (pScrn->bitsPerPixel < 8) { 4125 pBankInfo->SetSourceBank = 4126 (miBankProcPtr)CHIPSSetReadPlanar; 4127 pBankInfo->SetDestinationBank = 4128 (miBankProcPtr)CHIPSSetWritePlanar; 4129 pBankInfo->SetSourceAndDestinationBanks = 4130 (miBankProcPtr)CHIPSSetReadWritePlanar; 4131 } else { 4132 pBankInfo->SetSourceBank = (miBankProcPtr)CHIPSSetRead; 4133 pBankInfo->SetDestinationBank = 4134 (miBankProcPtr)CHIPSSetWrite; 4135 pBankInfo->SetSourceAndDestinationBanks = 4136 (miBankProcPtr)CHIPSSetReadWrite; 4137 } 4138 } 4139 } 4140 if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY, 4141 pScrn->displayWidth, pBankInfo)) { 4142 xfree(pBankInfo); 4143 pBankInfo = NULL; 4144 return FALSE; 4145 } 4146 miInitializeBackingStore(pScreen); 4147 xf86SetBackingStore(pScreen); 4148 4149 /* Initialise cursor functions */ 4150 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 4151 4152 } else 4153#endif /* HAVE_ISA */ 4154 { 4155 /* !!! Only support linear addressing for now. This might change */ 4156 /* Setup pointers to free space in video ram */ 4157#define CHIPSALIGN(size, align) (currentaddr - ((currentaddr - size) & ~align)) 4158 allocatebase = (pScrn->videoRam<<10) - cPtr->FrameBufferSize; 4159 4160 if (pScrn->bitsPerPixel < 8) 4161 freespace = allocatebase - pScrn->displayWidth * 4162 pScrn->virtualY / 2; 4163 else if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)) 4164 freespace = allocatebase - pScrn->displayWidth * 4165 pScrn->virtualY - cPtr->FbSize16; 4166 else 4167 freespace = allocatebase - pScrn->displayWidth * 4168 pScrn->virtualY * (pScrn->bitsPerPixel >> 3); 4169 4170 if ((cPtr->Flags & ChipsDualChannelSupport) && 4171 (cPtr->SecondCrtc == TRUE)) { 4172 currentaddr = allocatebase + cPtrEnt->masterFbMapSize; 4173 } else 4174 currentaddr = allocatebase; 4175 if (serverGeneration == 1) 4176 xf86DrvMsg(scrnIndex, X_PROBED, 4177 "%d bytes off-screen memory available\n", freespace); 4178 4179 /* 4180 * Allocate video memory to store the hardware cursor. Allocate 1kB 4181 * vram to the cursor, with 1kB alignment for 6554x's and 4kb alignment 4182 * for 65550's. Wingine cursor is stored in registers and so no memory 4183 * is needed. 4184 */ 4185 if (cAcl->UseHWCursor) { 4186 cAcl->CursorAddress = -1; 4187 if (IS_HiQV(cPtr)) { 4188 if (CHIPSALIGN(1024, 0xFFF) <= freespace) { 4189 currentaddr -= CHIPSALIGN(1024, 0xFFF); 4190 freespace -= CHIPSALIGN(1024, 0xFFF); 4191 cAcl->CursorAddress = currentaddr; 4192 } 4193 } else if (IS_Wingine(cPtr)) { 4194 cAcl->CursorAddress = 0; 4195 } else if (CHIPSALIGN(1024, 0x3FF) <= freespace) { 4196 currentaddr -= CHIPSALIGN(1024, 0x3FF); 4197 freespace -= CHIPSALIGN(1024, 0x3FF); 4198 cAcl->CursorAddress = currentaddr; 4199 } 4200 if (cAcl->CursorAddress == -1) 4201 xf86DrvMsg(scrnIndex, X_ERROR, 4202 "Too little space for H/W cursor.\n"); 4203 } 4204 4205 cAcl->CacheEnd = currentaddr; 4206 4207 /* Setup the acceleration primitives */ 4208 /* Calculate space needed of offscreen pixmaps etc. */ 4209 if (cPtr->Flags & ChipsAccelSupport) { 4210 /* 4211 * A scratch area is now allocated in the video ram. This is used 4212 * at 8 and 16 bpp to simulate a planemask with a complex ROP, and 4213 * at 24 and 32 bpp to aid in accelerating solid fills 4214 */ 4215 cAcl->ScratchAddress = -1; 4216 switch (pScrn->bitsPerPixel) { 4217 case 8: 4218 if (CHIPSALIGN(64, 0x3F) <= freespace) { 4219 currentaddr -= CHIPSALIGN(64, 0x3F); 4220 freespace -= CHIPSALIGN(64, 0x3F); 4221 cAcl->ScratchAddress = currentaddr; 4222 } 4223 break; 4224 case 16: 4225 if (CHIPSALIGN(128, 0x7F) <= freespace) { 4226 currentaddr -= CHIPSALIGN(128, 0x7F); 4227 freespace -= CHIPSALIGN(128, 0x7F); 4228 cAcl->ScratchAddress = currentaddr; 4229 } 4230 break; 4231 case 24: 4232 /* One scanline of data used for solid fill */ 4233 if (!IS_HiQV(cPtr)) { 4234 if (CHIPSALIGN(3 * (pScrn->displayWidth + 4), 0x3) 4235 <= freespace) { 4236 currentaddr -= CHIPSALIGN(3 * (pScrn->displayWidth 4237 + 4), 0x3); 4238 freespace -= CHIPSALIGN(3 * (pScrn->displayWidth + 4), 4239 0x3); 4240 cAcl->ScratchAddress = currentaddr; 4241 } 4242 } 4243 break; 4244 case 32: 4245 /* 16bpp 8x8 mono pattern fill for solid fill. QWORD aligned */ 4246 if (IS_HiQV(cPtr)) { 4247 if (CHIPSALIGN(8, 0x7) <= freespace) { 4248 currentaddr -= CHIPSALIGN(8, 0x7); 4249 freespace -= CHIPSALIGN(8, 0x7); 4250 cAcl->ScratchAddress = currentaddr; 4251 } 4252 } 4253 break; 4254 } 4255 4256 /* Setup the boundaries of the pixmap cache */ 4257 cAcl->CacheStart = currentaddr - freespace; 4258 cAcl->CacheEnd = currentaddr; 4259 4260 if (cAcl->CacheStart >= cAcl->CacheEnd) { 4261 xf86DrvMsg(scrnIndex, X_ERROR, 4262 "Too little space for pixmap cache.\n"); 4263 cAcl->CacheStart = 0; 4264 cAcl->CacheEnd = 0; 4265 } 4266 4267 if (IS_HiQV(cPtr)) 4268 cAcl->BltDataWindow = (unsigned char *)cPtr->MMIOBase 4269 + 0x10000L; 4270 else 4271 cAcl->BltDataWindow = cPtr->FbBase; 4272 4273 } 4274 /* 4275 * Initialize FBManager: 4276 * we do even with no acceleration enabled 4277 * so that video support can allocate space. 4278 */ 4279 4280 { 4281 BoxRec AvailFBArea; 4282 AvailFBArea.x1 = 0; 4283 AvailFBArea.y1 = 0; 4284 AvailFBArea.x2 = pScrn->displayWidth; 4285 AvailFBArea.y2 = cAcl->CacheEnd / 4286 (pScrn->displayWidth * (pScrn->bitsPerPixel >> 3)); 4287 4288 if (!(cPtr->Flags & ChipsOverlay8plus16)) { 4289 xf86InitFBManager(pScreen, &AvailFBArea); 4290 } 4291 } 4292 if (cPtr->Flags & ChipsAccelSupport) { 4293 if (IS_HiQV(cPtr)) { 4294 CHIPSHiQVAccelInit(pScreen); 4295 } else if (cPtr->UseMMIO) { 4296 CHIPSMMIOAccelInit(pScreen); 4297 } else { 4298 CHIPSAccelInit(pScreen); 4299 } 4300 } 4301 4302 miInitializeBackingStore(pScreen); 4303 xf86SetBackingStore(pScreen); 4304#ifdef ENABLE_SILKEN_MOUSE 4305 xf86SetSilkenMouse(pScreen); 4306#endif 4307 4308 /* Initialise cursor functions */ 4309 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 4310 4311 if ((cAcl->UseHWCursor) && (cAcl->CursorAddress != -1)) { 4312 /* HW cursor functions */ 4313 if (!CHIPSCursorInit(pScreen)) { 4314 xf86DrvMsg(scrnIndex, X_ERROR, 4315 "Hardware cursor initialization failed\n"); 4316 return FALSE; 4317 } 4318 } 4319 } 4320 4321 if (cPtr->Flags & ChipsShadowFB) { 4322 RefreshAreaFuncPtr refreshArea = chipsRefreshArea; 4323 4324 if(cPtr->Rotate) { 4325 if (!cPtr->PointerMoved) { 4326 cPtr->PointerMoved = pScrn->PointerMoved; 4327 pScrn->PointerMoved = chipsPointerMoved; 4328 } 4329 4330 switch(pScrn->bitsPerPixel) { 4331 case 8: refreshArea = chipsRefreshArea8; break; 4332 case 16: refreshArea = chipsRefreshArea16; break; 4333 case 24: refreshArea = chipsRefreshArea24; break; 4334 case 32: refreshArea = chipsRefreshArea32; break; 4335 } 4336 } 4337 ShadowFBInit(pScreen, refreshArea); 4338 } 4339 4340 /* Initialise default colourmap */ 4341 if (!miCreateDefColormap(pScreen)) 4342 return FALSE; 4343 4344 if ((cPtr->Flags & ChipsOverlay8plus16) && (pScrn->bitsPerPixel == 16)) { 4345 if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, chipsLoadPalette, 4346 NULL, CMAP_RELOAD_ON_MODE_SWITCH)) 4347 return FALSE; 4348 } else { 4349 if(!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, 4350 (pScrn->depth == 16 ? chipsLoadPalette16 : chipsLoadPalette), 4351 NULL, CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR)) 4352 return FALSE; 4353 } 4354 4355#ifndef XSERVER_LIBPCIACCESS 4356 racflag = RAC_COLORMAP; 4357 if (cAcl->UseHWCursor) 4358 racflag |= RAC_CURSOR; 4359 racflag |= (RAC_FB | RAC_VIEWPORT); 4360 /* XXX Check if I/O and Mem flags need to be the same. */ 4361 pScrn->racIoFlags = pScrn->racMemFlags = racflag; 4362#endif 4363#ifdef ENABLE_SILKEN_MOUSE 4364 xf86SetSilkenMouse(pScreen); 4365#endif 4366 4367 if ((!(cPtr->Flags & ChipsOverlay8plus16)) 4368 && (cPtr->Flags & ChipsVideoSupport) 4369 && (cPtr->Flags & ChipsLinearSupport)) { 4370 CHIPSInitVideo(pScreen); 4371 } 4372 4373 pScreen->SaveScreen = CHIPSSaveScreen; 4374 4375 /* Setup DPMS mode */ 4376 if (cPtr->Flags & ChipsDPMSSupport) 4377 xf86DPMSInit(pScreen, (DPMSSetProcPtr)chipsDisplayPowerManagementSet, 4378 0); 4379 4380 /* Wrap the current CloseScreen function */ 4381 cPtr->CloseScreen = pScreen->CloseScreen; 4382 pScreen->CloseScreen = CHIPSCloseScreen; 4383 4384 /* Report any unused options (only for the first generation) */ 4385 if (serverGeneration == 1) { 4386 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 4387 } 4388 4389 return TRUE; 4390} 4391 4392/* Mandatory */ 4393Bool 4394CHIPSSwitchMode(int scrnIndex, DisplayModePtr mode, int flags) 4395{ 4396 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4397 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4398 CHIPSEntPtr cPtrEnt; 4399 4400#ifdef DEBUG 4401 ErrorF("CHIPSSwitchMode\n"); 4402#endif 4403 if (cPtr->UseDualChannel) { 4404 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4405 CHIPSEntityIndex)->ptr; 4406 DUALREOPEN; 4407 } 4408 4409 return chipsModeInit(xf86Screens[scrnIndex], mode); 4410} 4411 4412/* Mandatory */ 4413void 4414CHIPSAdjustFrame(int scrnIndex, int x, int y, int flags) 4415{ 4416 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4417 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4418 CHIPSEntPtr cPtrEnt; 4419 4420 int Base; 4421 vgaHWPtr hwp = VGAHWPTR(pScrn); 4422 unsigned char tmp; 4423 4424 if (xf86ReturnOptValBool(cPtr->Options, OPTION_SHOWCACHE, FALSE) && y) { 4425 int lastline = cPtr->FbMapSize / 4426 ((pScrn->displayWidth * pScrn->bitsPerPixel) / 8); 4427 lastline -= pScrn->currentMode->VDisplay; 4428 y += pScrn->virtualY - 1; 4429 if (y > lastline) y = lastline; 4430 } 4431 4432 Base = y * pScrn->displayWidth + x; 4433 4434 /* calculate base bpp dep. */ 4435 switch (pScrn->bitsPerPixel) { 4436 case 1: 4437 case 4: 4438 Base >>= 3; 4439 break; 4440 case 16: 4441 if (!(cPtr->Flags & ChipsOverlay8plus16)) 4442 Base >>= 1; 4443 else 4444 Base >>= 2; 4445 break; 4446 case 24: 4447 if (!IS_HiQV(cPtr)) 4448 Base = (Base >> 2) * 3; 4449 else 4450 Base = (Base >> 3) * 6; /* 65550 seems to need 64bit alignment */ 4451 break; 4452 case 32: 4453 break; 4454 default: /* 8bpp */ 4455 Base >>= 2; 4456 break; 4457 } 4458 4459 if (cPtr->UseDualChannel) { 4460 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4461 CHIPSEntityIndex)->ptr; 4462 DUALREOPEN; 4463 } 4464 4465 /* write base to chip */ 4466 /* 4467 * These are the generic starting address registers. 4468 */ 4469 chipsFixResume(pScrn); 4470 hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); 4471 hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); 4472 if (IS_HiQV(cPtr)) { 4473 if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) 4474 hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); 4475 } else { 4476 tmp = cPtr->readXR(cPtr, 0x0C); 4477 cPtr->writeXR(cPtr, 0x0C, ((Base & (IS_Wingine(cPtr) ? 0x0F0000 : 4478 0x030000)) >> 16) | (tmp & 0xF8)); 4479 } 4480 4481 if (cPtr->UseDualChannel && 4482 (! xf86IsEntityShared(pScrn->entityList[0]))) { 4483 unsigned int IOSS, MSS; 4484 IOSS = cPtr->readIOSS(cPtr); 4485 MSS = cPtr->readMSS(cPtr); 4486 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 4487 IOSS_PIPE_B)); 4488 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); 4489 4490 chipsFixResume(pScrn); 4491 hwp->writeCrtc(hwp, 0x0C, (Base & 0xFF00) >> 8); 4492 hwp->writeCrtc(hwp, 0x0D, Base & 0xFF); 4493 if (((cPtr->readXR(cPtr, 0x09)) & 0x1) == 0x1) 4494 hwp->writeCrtc(hwp, 0x40, ((Base & 0x0F0000) >> 16) | 0x80); 4495 4496 cPtr->writeIOSS(cPtr, IOSS); 4497 cPtr->writeMSS(cPtr, hwp, MSS); 4498 } 4499 4500 if (cPtr->Flags & ChipsOverlay8plus16) { 4501 Base = (Base << 3) & ~(unsigned long)0xF; 4502 4503 cPtr->writeMR(cPtr, 0x22, (cPtr->FbOffset16 + Base) & 0xF8); 4504 cPtr->writeMR(cPtr, 0x23, ((cPtr->FbOffset16 + Base) >> 8) & 0xFF); 4505 cPtr->writeMR(cPtr, 0x24, ((cPtr->FbOffset16 + Base) >> 16) & 0xFF); 4506 } 4507 4508} 4509 4510/* Mandatory */ 4511static Bool 4512CHIPSCloseScreen(int scrnIndex, ScreenPtr pScreen) 4513{ 4514 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4515 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4516 CHIPSEntPtr cPtrEnt; 4517 4518 if(pScrn->vtSema){ /*§§§*/ 4519 if (cPtr->Flags & ChipsDualChannelSupport) { 4520 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4521 CHIPSEntityIndex)->ptr; 4522 if (cPtr->UseDualChannel) 4523 DUALREOPEN; 4524 DUALCLOSE; 4525 } else { 4526 chipsHWCursorOff(cPtr, pScrn); 4527 chipsRestore(pScrn, &(VGAHWPTR(pScrn))->SavedReg, &cPtr->SavedReg, 4528 TRUE); 4529 chipsLock(pScrn); 4530 } 4531 chipsUnmapMem(pScrn); 4532 } 4533 4534 if (xf86IsEntityShared(pScrn->entityList[0])) { 4535 DevUnion *pPriv; 4536 pPriv = xf86GetEntityPrivate(pScrn->entityList[0], CHIPSEntityIndex); 4537 cPtrEnt = pPriv->ptr; 4538 cPtrEnt->refCount--; 4539 } 4540 if (cPtr->AccelInfoRec) 4541 XAADestroyInfoRec(cPtr->AccelInfoRec); 4542 if (cPtr->CursorInfoRec) 4543 xf86DestroyCursorInfoRec(cPtr->CursorInfoRec); 4544 if (cPtr->ShadowPtr) 4545 xfree(cPtr->ShadowPtr); 4546 if (cPtr->DGAModes) 4547 xfree(cPtr->DGAModes); 4548 pScrn->vtSema = FALSE; 4549 if(cPtr->BlockHandler) 4550 pScreen->BlockHandler = cPtr->BlockHandler; 4551 4552 pScreen->CloseScreen = cPtr->CloseScreen; /*§§§*/ 4553 xf86ClearPrimInitDone(pScrn->entityList[0]); 4554 return (*pScreen->CloseScreen)(scrnIndex, pScreen);/*§§§*/ 4555} 4556 4557/* Optional */ 4558static void 4559CHIPSFreeScreen(int scrnIndex, int flags) 4560{ 4561 if (xf86LoaderCheckSymbol("vgaHWFreeHWRec")) 4562 vgaHWFreeHWRec(xf86Screens[scrnIndex]); 4563 CHIPSFreeRec(xf86Screens[scrnIndex]); 4564} 4565 4566/* Optional */ 4567static ModeStatus 4568CHIPSValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags) 4569{ 4570 ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 4571 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4572 4573 if (flags & MODECHECK_FINAL) { 4574 /* Don't subtract FrambufferSize here as it should be subtracted already */ 4575 if ((cPtr->Flags & ChipsOverlay8plus16) 4576 && ((pScrn->videoRam<<10) - pScrn->displayWidth * 3 * pScrn->virtualY 4577 < 0)) 4578 return MODE_MEM; 4579 } 4580 /* The tests here need to be expanded */ 4581 if ((mode->Flags & V_INTERLACE) && (cPtr->PanelType & ChipsLCD)) 4582 return MODE_NO_INTERLACE; 4583 if ((cPtr->PanelType & ChipsLCD) 4584 && !xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE) 4585 && ((cPtr->PanelSize.HDisplay < mode->HDisplay) 4586 || (cPtr->PanelSize.VDisplay < mode->VDisplay))) 4587 return MODE_PANEL; 4588 4589 return MODE_OK; 4590} 4591 4592/* 4593 * DPMS Control registers 4594 * 4595 * XR73 6554x and 64300 (what about 65535?) 4596 * XR61 6555x 4597 * 0 HSync Powerdown data 4598 * 1 HSync Select 1=Powerdown 4599 * 2 VSync Powerdown data 4600 * 3 VSync Select 1=Powerdown 4601 */ 4602 4603static void 4604chipsDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, 4605 int flags) 4606{ 4607 vgaHWPtr hwp = VGAHWPTR(pScrn); 4608 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4609 CHIPSEntPtr cPtrEnt; 4610 4611 unsigned char dpmsreg, seqreg, lcdoff, tmp; 4612 4613 if (!pScrn->vtSema) 4614 return; 4615 4616#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 8 4617 xf86EnableAccess(pScrn); 4618#endif 4619 switch (PowerManagementMode) { 4620 case DPMSModeOn: 4621 /* Screen: On; HSync: On, VSync: On */ 4622 dpmsreg = 0x00; 4623 seqreg = 0x00; 4624 lcdoff = 0x0; 4625 break; 4626 case DPMSModeStandby: 4627 /* Screen: Off; HSync: Off, VSync: On */ 4628 dpmsreg = 0x02; 4629 seqreg = 0x20; 4630 lcdoff = 0x0; 4631 break; 4632 case DPMSModeSuspend: 4633 /* Screen: Off; HSync: On, VSync: Off */ 4634 dpmsreg = 0x08; 4635 seqreg = 0x20; 4636 lcdoff = 0x1; 4637 break; 4638 case DPMSModeOff: 4639 /* Screen: Off; HSync: Off, VSync: Off */ 4640 dpmsreg = 0x0A; 4641 seqreg = 0x20; 4642 lcdoff = 0x1; 4643 break; 4644 default: 4645 return; 4646 } 4647 4648 if (cPtr->UseDualChannel) { 4649 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4650 CHIPSEntityIndex)->ptr; 4651 DUALREOPEN; 4652 } 4653 4654 seqreg |= hwp->readSeq(hwp, 0x01) & ~0x20; 4655 hwp->writeSeq(hwp, 0x01, seqreg); 4656 if (IS_HiQV(cPtr)) { 4657 tmp = cPtr->readXR(cPtr, 0x61); 4658 cPtr->writeXR(cPtr, 0x61, (tmp & 0xF0) | dpmsreg); 4659 } else { 4660 tmp = cPtr->readXR(cPtr, 0x73); 4661 cPtr->writeXR(cPtr, 0x73, (tmp & 0xF0) | dpmsreg); 4662 } 4663 4664 /* Turn off the flat panel */ 4665 if (cPtr->PanelType & ChipsLCDProbed) { 4666 if (IS_HiQV(cPtr)) { 4667 if (cPtr->Chipset == CHIPS_CT69030) { 4668#if 0 4669 /* Where is this for the 69030?? */ 4670 tmp = cPtr->readFR(cPtr, 0x05); 4671 if (lcdoff) 4672 cPtr->writeFR(cPtr, 0x05, tmp | 0x08); 4673 else 4674 cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); 4675#endif 4676 } else { 4677 tmp = cPtr->readFR(cPtr, 0x05); 4678 if (lcdoff) 4679 cPtr->writeFR(cPtr, 0x05, tmp | 0x08); 4680 else 4681 cPtr->writeFR(cPtr, 0x05, tmp & 0xF7); 4682 } 4683 } else { 4684 tmp = cPtr->readXR(cPtr, 0x52); 4685 if (lcdoff) 4686 cPtr->writeXR(cPtr, 0x52, tmp | 0x08); 4687 else 4688 cPtr->writeXR(cPtr, 0x52, tmp & 0xF7); 4689 } 4690 } 4691} 4692 4693static Bool 4694CHIPSSaveScreen(ScreenPtr pScreen, int mode) 4695{ 4696 ScrnInfoPtr pScrn = NULL; /* §§§ */ 4697 Bool unblank; 4698 4699 unblank = xf86IsUnblank(mode); 4700 4701 if (pScreen != NULL) 4702 pScrn = xf86Screens[pScreen->myNum]; 4703 4704 if (unblank) 4705 SetTimeSinceLastInputEvent(); 4706 4707 if ((pScrn != NULL) && pScrn->vtSema) { /* §§§ */ 4708 chipsBlankScreen(pScrn, unblank); 4709 } 4710 return (TRUE); 4711} 4712 4713static Bool 4714chipsClockSelect(ScrnInfoPtr pScrn, int no) 4715{ 4716 CHIPSClockReg TmpClock; 4717 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4718 4719 switch (no) { 4720 case CLK_REG_SAVE: 4721 chipsClockSave(pScrn, &cPtr->SaveClock); 4722 break; 4723 4724 case CLK_REG_RESTORE: 4725 chipsClockLoad(pScrn, &cPtr->SaveClock); 4726 break; 4727 4728 default: 4729 if (!chipsClockFind(pScrn, NULL, no, &TmpClock)) 4730 return (FALSE); 4731 chipsClockLoad(pScrn, &TmpClock); 4732 } 4733 return (TRUE); 4734} 4735 4736/* 4737 * 4738 * Fout = (Fref * 4 * M) / (PSN * N * (1 << P) ) 4739 * Fvco = (Fref * 4 * M) / (PSN * N) 4740 * where 4741 * M = XR31+2 4742 * N = XR32+2 4743 * P = XR30[3:1] 4744 * PSN = XR30[0]? 1:4 4745 * 4746 * constraints: 4747 * 4 MHz <= Fref <= 20 MHz (typ. 14.31818 MHz) 4748 * 150 kHz <= Fref/(PSN * N) <= 2 MHz 4749 * 48 MHz <= Fvco <= 220 MHz 4750 * 2 < M < 128 4751 * 2 < N < 128 4752 */ 4753 4754static void 4755chipsClockSave(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) 4756{ 4757 unsigned char tmp; 4758 vgaHWPtr hwp = VGAHWPTR(pScrn); 4759 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4760 unsigned char Type = cPtr->ClockType; 4761 CHIPSEntPtr cPtrEnt; 4762 4763 Clock->msr = hwp->readMiscOut(hwp)&0xFE; /* save standard VGA clock reg */ 4764 switch (Type & GET_STYLE) { 4765 case HiQV_STYLE: 4766 /* save alternate clock select reg.*/ 4767 /* The 69030 FP clock select is at FR01 instead */ 4768 if (cPtr->UseDualChannel) { 4769 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4770 CHIPSEntityIndex)->ptr; 4771 DUALREOPEN; 4772 } 4773 4774 if (cPtr->Flags & ChipsDualChannelSupport) 4775 Clock->fr03 = cPtr->readFR(cPtr, 0x01); 4776 else 4777 Clock->fr03 = cPtr->readFR(cPtr, 0x03); 4778 if (!Clock->Clock) { /* save HiQV console clock */ 4779 tmp = cPtr->CRTclkInx << 2; 4780 cPtr->CRTClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); 4781 cPtr->CRTClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); 4782 cPtr->CRTClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); 4783 cPtr->CRTClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); 4784 tmp = cPtr->FPclkInx << 2; 4785 cPtr->FPClk[0] = cPtr->readXR(cPtr, 0xC0 + tmp); 4786 cPtr->FPClk[1] = cPtr->readXR(cPtr, 0xC1 + tmp); 4787 cPtr->FPClk[2] = cPtr->readXR(cPtr, 0xC2 + tmp); 4788 cPtr->FPClk[3] = cPtr->readXR(cPtr, 0xC3 + tmp); 4789 } 4790 break; 4791 case OLD_STYLE: 4792 Clock->fcr = hwp->readFCR(hwp); 4793 Clock->xr02 = cPtr->readXR(cPtr, 0x02); 4794 Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ 4795 break; 4796 case WINGINE_1_STYLE: 4797 case WINGINE_2_STYLE: 4798 break; 4799 case NEW_STYLE: 4800 Clock->xr54 = cPtr->readXR(cPtr, 0x54); /* save alternate clock select reg.*/ 4801 Clock->xr33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK sel reg.*/ 4802 break; 4803 } 4804#ifdef DEBUG 4805 ErrorF("saved \n"); 4806#endif 4807} 4808 4809static Bool 4810chipsClockFind(ScrnInfoPtr pScrn, DisplayModePtr mode, 4811 int no, CHIPSClockPtr Clock ) 4812{ 4813 vgaHWPtr hwp = VGAHWPTR(pScrn); 4814 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4815 unsigned char Type = cPtr->ClockType; 4816 CHIPSEntPtr cPtrEnt; 4817 4818 if (no > (pScrn->numClocks - 1)) 4819 return (FALSE); 4820 4821 if (cPtr->UseDualChannel) { 4822 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 4823 CHIPSEntityIndex)->ptr; 4824 DUALREOPEN; 4825 } 4826 4827 switch (Type & GET_STYLE) { 4828 case HiQV_STYLE: 4829 Clock->msr = cPtr->CRTclkInx << 2; 4830 Clock->fr03 = cPtr->FPclkInx << 2; 4831 Clock->Clock = mode ? mode->Clock : 0; 4832 if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { 4833 Clock->FPClock = mode ? mode->Clock : 0; 4834 } else 4835 Clock->FPClock = cPtr->FPclock; 4836 break; 4837 case NEW_STYLE: 4838 if (Type & TYPE_HW) { 4839 Clock->msr = (no == 4 ? 3 << 2: (no & 0x01) << 2); 4840 Clock->xr54 = Clock->msr; 4841 Clock->xr33 = no > 1 ? 0x80 : 0; 4842 } else { 4843 Clock->msr = 3 << 2; 4844 Clock->xr33 = 0; 4845 Clock->xr54 = Clock->msr; 4846 /* update panel type in case somebody switched. 4847 * This should be handled more generally: 4848 * On mode switch DDC should be reread, all 4849 * display dependent data should be reevaluated. 4850 * This will be built in when we start Display 4851 * HotPlug support. 4852 * Until then we have to do it here as somebody 4853 * might have switched displays on us and we only 4854 * have one programmable clock which needs to 4855 * be shared for CRT and LCD. 4856 */ 4857 chipsSetPanelType(cPtr); 4858 { 4859 Bool fp_m; 4860 if (cPtr->Options 4861 && xf86GetOptValBool(cPtr->Options, OPTION_FP_MODE, &fp_m)) { 4862 if (fp_m) 4863 cPtr->PanelType |= ChipsLCD; 4864 else 4865 cPtr->PanelType = ~ChipsLCD; 4866 } 4867 } 4868 4869 if ((cPtr->PanelType & ChipsLCD) && cPtr->FPclock) 4870 Clock->Clock = cPtr->FPclock; 4871 else 4872 Clock->Clock = mode ? mode->SynthClock : 0; 4873 } 4874 break; 4875 case OLD_STYLE: 4876 if (no > 3) { 4877 Clock->msr = 3 << 2; 4878 Clock->fcr = no & 0x03; 4879 Clock->xr02 = 0; 4880 Clock->xr54 = Clock->msr & (Clock->fcr << 4); 4881 } else { 4882 Clock->msr = (no << 2) & 0x4; 4883 Clock->fcr = 0; 4884 Clock->xr02 = no & 0x02; 4885 Clock->xr54 = Clock->msr; 4886 } 4887 break; 4888 case WINGINE_1_STYLE: 4889 Clock->msr = no << 2; 4890 case WINGINE_2_STYLE: 4891 if (Type & TYPE_HW) { 4892 Clock->msr = (no == 2 ? 3 << 2: (no & 0x01) << 2); 4893 Clock->xr33 = 0; 4894 } else { 4895 Clock->msr = 3 << 2; 4896 Clock->xr33 = 0; 4897 Clock->Clock = mode ? mode->SynthClock : 0; 4898 } 4899 break; 4900 } 4901 Clock->msr |= (hwp->readMiscOut(hwp) & 0xF2); 4902 4903#ifdef DEBUG 4904 ErrorF("found\n"); 4905#endif 4906 return (TRUE); 4907} 4908 4909 4910static int 4911chipsGetHWClock(ScrnInfoPtr pScrn) 4912{ 4913 vgaHWPtr hwp = VGAHWPTR(pScrn); 4914 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4915 unsigned char Type = cPtr->ClockType; 4916 unsigned char tmp, tmp1; 4917 4918 if (!(Type & TYPE_HW)) 4919 return 0; /* shouldn't happen */ 4920 4921 switch (Type & GET_STYLE) { 4922 case WINGINE_1_STYLE: 4923 return ((hwp->readMiscOut(hwp) & 0x0C) >> 2); 4924 case WINGINE_2_STYLE: 4925 tmp = ((hwp->readMiscOut(hwp) & 0x04) >> 2); 4926 return (tmp > 2) ? 2 : tmp; 4927 case OLD_STYLE: 4928 if (!(cPtr->PanelType & ChipsLCDProbed)) 4929 tmp = hwp->readMiscOut(hwp); 4930 else 4931 tmp = cPtr->readXR(cPtr, 0x54); 4932 if (tmp & 0x08) { 4933 if (!(cPtr->PanelType & ChipsLCDProbed)) 4934 tmp = hwp->readFCR(hwp) & 0x03; 4935 else 4936 tmp = (tmp >> 4) & 0x03; 4937 return (tmp + 4); 4938 } else { 4939 tmp = (tmp >> 2) & 0x01; 4940 tmp1 = cPtr->readXR(cPtr, 0x02); 4941 return (tmp + (tmp1 & 0x02)); 4942 } 4943 case NEW_STYLE: 4944 if (cPtr->PanelType & ChipsLCDProbed) { 4945 tmp = cPtr->readXR(cPtr, 0x54); 4946 } else 4947 tmp = hwp->readMiscOut(hwp); 4948 tmp = (tmp & 0x0C) >> 2; 4949 if (tmp > 1) return 4; 4950 tmp1 = cPtr->readXR(cPtr, 0x33); 4951 tmp1 = (tmp1 & 0x80) >> 6; /* iso mode 25.175/28.322 or 32/36 MHz */ 4952 return (tmp + tmp1); /* ^=0 ^=1 ^=4 ^=5 */ 4953 default: /* we should never get here */ 4954 return (0); 4955 } 4956} 4957 4958static void 4959chipsClockLoad(ScrnInfoPtr pScrn, CHIPSClockPtr Clock) 4960{ 4961 vgaHWPtr hwp = VGAHWPTR(pScrn); 4962 CHIPSPtr cPtr = CHIPSPTR(pScrn); 4963 unsigned char Type = cPtr->ClockType; 4964 volatile unsigned char tmp, tmpmsr, tmpfcr, tmp02; 4965 volatile unsigned char tmp33, tmp54, tmpf03; 4966 unsigned char vclk[3]; 4967 4968 tmpmsr = hwp->readMiscOut(hwp); /* read msr, needed for all styles */ 4969 4970 switch (Type & GET_STYLE) { 4971 case HiQV_STYLE: 4972 /* save alternate clock select reg. */ 4973 /* The 69030 FP clock select is at FR01 instead */ 4974 if (cPtr->Flags & ChipsDualChannelSupport) { 4975 tmpf03 = cPtr->readFR(cPtr, 0x01); 4976 } else 4977 tmpf03 = cPtr->readFR(cPtr, 0x03); 4978 /* select fixed clock 0 before tampering with VCLK select */ 4979 hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | 4980 cPtr->SuspendHack.vgaIOBaseFlag); 4981 /* The 69030 FP clock select is at FR01 instead */ 4982 if (cPtr->Flags & ChipsDualChannelSupport) { 4983 cPtr->writeFR(cPtr, 0x01, (tmpf03 & ~0x0C) | 0x04); 4984 } else 4985 cPtr->writeFR(cPtr, 0x03, (tmpf03 & ~0x0C) | 0x04); 4986 if (!Clock->Clock) { /* Hack to load saved console clock */ 4987 tmp = cPtr->CRTclkInx << 2; 4988 cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->CRTClk[0] & 0xFF)); 4989 cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->CRTClk[1] & 0xFF)); 4990 cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->CRTClk[2] & 0xFF)); 4991 cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->CRTClk[3] & 0xFF)); 4992 4993 if (cPtr->FPClkModified) { 4994 usleep(10000); /* let VCO stabilize */ 4995 tmp = cPtr->FPclkInx << 2; 4996 cPtr->writeXR(cPtr, 0xC0 + tmp, (cPtr->FPClk[0] & 0xFF)); 4997 cPtr->writeXR(cPtr, 0xC1 + tmp, (cPtr->FPClk[1] & 0xFF)); 4998 cPtr->writeXR(cPtr, 0xC2 + tmp, (cPtr->FPClk[2] & 0xFF)); 4999 cPtr->writeXR(cPtr, 0xC3 + tmp, (cPtr->FPClk[3] & 0xFF)); 5000 } 5001 } else { 5002 /* 5003 * Don't use the extra 2 bits in the M, N registers available 5004 * on the HiQV, so write zero to 0xCA 5005 */ 5006 chipsCalcClock(pScrn, Clock->Clock, vclk); 5007 tmp = cPtr->CRTclkInx << 2; 5008 cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); 5009 cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); 5010 cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); 5011 cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); 5012 if (Clock->FPClock) { 5013 usleep(10000); /* let VCO stabilize */ 5014 chipsCalcClock(pScrn, Clock->FPClock, vclk); 5015 tmp = cPtr->FPclkInx << 2; 5016 cPtr->writeXR(cPtr, 0xC0 + tmp, (vclk[1] & 0xFF)); 5017 cPtr->writeXR(cPtr, 0xC1 + tmp, (vclk[2] & 0xFF)); 5018 cPtr->writeXR(cPtr, 0xC2 + tmp, 0x0); 5019 cPtr->writeXR(cPtr, 0xC3 + tmp, (vclk[0] & 0xFF)); 5020 cPtr->FPClkModified = TRUE; 5021 } 5022 } 5023 usleep(10000); /* Let VCO stabilise */ 5024 /* The 69030 FP clock select is at FR01 instead */ 5025 if (cPtr->Flags & ChipsDualChannelSupport) { 5026 cPtr->writeFR(cPtr, 0x01, ((tmpf03 & ~0x0C) | 5027 (Clock->fr03 & 0x0C))); 5028 } else 5029 cPtr->writeFR(cPtr, 0x03, ((tmpf03 & ~0x0C) | 5030 (Clock->fr03 & 0x0C))); 5031 break; 5032 case WINGINE_1_STYLE: 5033 break; 5034 case WINGINE_2_STYLE: 5035 /* Only write to soft clock registers if we really need to */ 5036 if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { 5037 /* select fixed clock 0 before tampering with VCLK select */ 5038 hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | 5039 cPtr->SuspendHack.vgaIOBaseFlag); 5040 chipsCalcClock(pScrn, Clock->Clock, vclk); 5041 tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ 5042 cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); 5043 cPtr->writeXR(cPtr, 0x30, vclk[0]); 5044 cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ 5045 cPtr->writeXR(cPtr, 0x32, vclk[2]); 5046 /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ 5047 usleep(10000); /* Let VCO stabilise */ 5048 } 5049 break; 5050 case OLD_STYLE: 5051 tmp02 = cPtr->readXR(cPtr, 0x02); 5052 tmp54 = cPtr->readXR(cPtr, 0x54); 5053 tmpfcr = hwp->readFCR(hwp); 5054 cPtr->writeXR(cPtr, 0x02, ((tmp02 & ~0x02) | (Clock->xr02 & 0x02))); 5055 cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF0) | (Clock->xr54 & ~0xF0))); 5056 hwp->writeFCR(hwp, (tmpfcr & ~0x03) & Clock->fcr); 5057 break; 5058 case NEW_STYLE: 5059 tmp33 = cPtr->readXR(cPtr, 0x33); /* get status of MCLK/VCLK select reg */ 5060 tmp54 = cPtr->readXR(cPtr, 0x54); 5061 /* Only write to soft clock registers if we really need to */ 5062 if ((Type & GET_TYPE) == TYPE_PROGRAMMABLE) { 5063 /* select fixed clock 0 before tampering with VCLK select */ 5064 hwp->writeMiscOut(hwp, (tmpmsr & ~0x0D) | 5065 cPtr->SuspendHack.vgaIOBaseFlag); 5066 cPtr->writeXR(cPtr, 0x54, (tmp54 & 0xF3)); 5067 /* if user wants to set the memory clock, do it first */ 5068 if (cPtr->MemClock.Clk) { 5069 chipsCalcClock(pScrn, cPtr->MemClock.Clk, vclk); 5070 /* close eyes, hold breath ....*/ 5071 cPtr->writeXR(cPtr, 0x33, tmp33 | 0x20); 5072 cPtr->writeXR(cPtr, 0x30, vclk[0]); 5073 cPtr->writeXR(cPtr, 0x31, vclk[1]); 5074 cPtr->writeXR(cPtr, 0x32, vclk[2]); 5075 usleep(10000); 5076 } 5077 chipsCalcClock(pScrn, Clock->Clock, vclk); 5078 cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20); 5079 cPtr->writeXR(cPtr, 0x30, vclk[0]); 5080 cPtr->writeXR(cPtr, 0x31, vclk[1]); /* restore VCLK regs. */ 5081 cPtr->writeXR(cPtr, 0x32, vclk[2]); 5082 /* cPtr->writeXR(cPtr, 0x33, tmp33 & ~0x20);*/ 5083 usleep(10000); /* Let VCO stabilise */ 5084 } 5085 cPtr->writeXR(cPtr, 0x33, ((tmp33 & ~0x80) | (Clock->xr33 & 0x80))); 5086 cPtr->writeXR(cPtr, 0x54, ((tmp54 & 0xF3) | (Clock->xr54 & ~0xF3))); 5087 break; 5088 } 5089 hwp->writeMiscOut(hwp, (Clock->msr & 0xFE) | 5090 cPtr->SuspendHack.vgaIOBaseFlag); 5091#ifdef DEBUG 5092 ErrorF("restored\n"); 5093#endif 5094} 5095 5096/* 5097 * This is Ken Raeburn's <raeburn@raeburn.org> clock 5098 * calculation code just modified a little bit to fit in here. 5099 */ 5100 5101static void 5102chipsCalcClock(ScrnInfoPtr pScrn, int Clock, unsigned char *vclk) 5103{ 5104 CHIPSPtr cPtr = CHIPSPTR(pScrn); 5105 int M, N, P = 0, PSN = 0, PSNx = 0; 5106 5107 int bestM = 0, bestN = 0, bestP = 0, bestPSN = 0; 5108 double abest = 42; 5109#ifdef DEBUG 5110 double bestFout = 0; 5111#endif 5112 double target; 5113 5114 double Fvco, Fout; 5115 double error, aerror; 5116 5117 int M_min = 3; 5118 5119 /* Hack to deal with problem of Toshiba 720CDT clock */ 5120 int M_max = (IS_HiQV(cPtr) && cPtr->Chipset != CHIPS_CT69000 && 5121 cPtr->Chipset != CHIPS_CT69030) ? 63 : 127; 5122 5123 /* @@@ < CHIPS_CT690x0 ?? */ 5124 5125 /* Other parameters available on the 65548 but not the 65545, and 5126 * not documented in the Clock Synthesizer doc in rev 1.0 of the 5127 * 65548 datasheet: 5128 * 5129 * + XR30[4] = 0, VCO divider loop uses divide by 4 (same as 65545) 5130 * 1, VCO divider loop uses divide by 16 5131 * 5132 * + XR30[5] = 1, reference clock is divided by 5 5133 * 5134 * Other parameters available on the 65550 and not on the 65545 5135 * 5136 * + XRCB[2] = 0, VCO divider loop uses divide by 4 (same as 65545) 5137 * 1, VCO divider loop uses divide by 16 5138 * 5139 * + XRCB[1] = 1, reference clock is divided by 5 5140 * 5141 * + XRCB[7] = Vclk = Mclk 5142 * 5143 * + XRCA[0:1] = 2 MSB of a 10 bit M-Divisor 5144 * 5145 * + XRCA[4:5] = 2 MSB of a 10 bit N-Divisor 5146 * 5147 * I haven't put in any support for those here. For simplicity, 5148 * they should be set to 0 on the 65548, and left untouched on 5149 * earlier chips. 5150 * 5151 * Other parameters available on the 690x0 5152 * 5153 * + The 690x0 has no reference clock divider, so PSN must 5154 * always be 1. 5155 * XRCB[0:1] are reserved according to the data book 5156 */ 5157 5158 5159 target = Clock * 1000; 5160 5161 /* @@@ >= CHIPS_CT690x0 ?? */ 5162 for (PSNx = ((cPtr->Chipset == CHIPS_CT69000) || 5163 (cPtr->Chipset == CHIPS_CT69030)) ? 1 : 0; PSNx <= 1; PSNx++) { 5164 int low_N, high_N; 5165 double Fref4PSN; 5166 5167 PSN = PSNx ? 1 : 4; 5168 5169 low_N = 3; 5170 high_N = 127; 5171 5172 while (Fref / (PSN * low_N) > (((cPtr->Chipset == CHIPS_CT69000) || 5173 (cPtr->Chipset == CHIPS_CT69030)) ? 5.0e6 : 2.0e6)) 5174 low_N++; 5175 while (Fref / (PSN * high_N) < 150.0e3) 5176 high_N--; 5177 5178 Fref4PSN = Fref * 4 / PSN; 5179 for (N = low_N; N <= high_N; N++) { 5180 double tmp = Fref4PSN / N; 5181 5182 /* @@@ < CHIPS_CT690x0 ?? */ 5183 for (P = (IS_HiQV(cPtr) && (cPtr->Chipset != CHIPS_CT69000) && 5184 (cPtr->Chipset != CHIPS_CT69030)) ? 1 : 0; 5185 P <= 5; P++) { 5186 /* to force post divisor on Toshiba 720CDT */ 5187 double Fvco_desired = target * (1 << P); 5188 double M_desired = Fvco_desired / tmp; 5189 5190 /* Which way will M_desired be rounded? Do all three just to 5191 * be safe. */ 5192 int M_low = M_desired - 1; 5193 int M_hi = M_desired + 1; 5194 5195 if (M_hi < M_min || M_low > M_max) 5196 continue; 5197 5198 if (M_low < M_min) 5199 M_low = M_min; 5200 if (M_hi > M_max) 5201 M_hi = M_max; 5202 5203 for (M = M_low; M <= M_hi; M++) { 5204 Fvco = tmp * M; 5205 /* @@@ >= CHIPS_CT690x0 ?? */ 5206 if (Fvco <= ((cPtr->Chipset == CHIPS_CT69000 || 5207 cPtr->Chipset == CHIPS_CT69030) ? 100.0e6 : 48.0e6)) 5208 continue; 5209 if (Fvco > 220.0e6) 5210 break; 5211 5212 Fout = Fvco / (1 << P); 5213 5214 error = (target - Fout) / target; 5215 5216 aerror = (error < 0) ? -error : error; 5217 if (aerror < abest) { 5218 abest = aerror; 5219 bestM = M; 5220 bestN = N; 5221 bestP = P; 5222 bestPSN = PSN; 5223#ifdef DEBUG 5224 bestFout = Fout; 5225#endif 5226 } 5227 } 5228 } 5229 } 5230 } 5231 /* @@@ >= CHIPS_CT690x0 ?? */ 5232 vclk[0] = (bestP << (IS_HiQV(cPtr) ? 4 : 1)) + 5233 (((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) 5234 ? 0 : (bestPSN == 1)); 5235 vclk[1] = bestM - 2; 5236 vclk[2] = bestN - 2; 5237#ifdef DEBUG 5238 ErrorF("Freq. selected: %.2f MHz, vclk[0]=%X, vclk[1]=%X, vclk[2]=%X\n", 5239 (float)(Clock / 1000.), vclk[0], vclk[1], vclk[2]); 5240 ErrorF("Freq. set: %.2f MHz\n", bestFout / 1.0e6); 5241#endif 5242} 5243 5244static void 5245chipsSave(ScrnInfoPtr pScrn, vgaRegPtr VgaSave, CHIPSRegPtr ChipsSave) 5246{ 5247 vgaHWPtr hwp = VGAHWPTR(pScrn); 5248 CHIPSPtr cPtr = CHIPSPTR(pScrn); 5249 int i; 5250 unsigned char tmp; 5251#ifdef DEBUG 5252 ErrorF("chipsSave\n"); 5253#endif 5254 5255 /* set registers that we can program the controller */ 5256 /* bank 0 */ 5257 if (IS_HiQV(cPtr)) { 5258 cPtr->writeXR(cPtr, 0x0E, 0x00); 5259 } else { 5260 cPtr->writeXR(cPtr, 0x10, 0x00); 5261 cPtr->writeXR(cPtr, 0x11, 0x00); 5262 tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ 5263 cPtr->writeXR(cPtr, 0x0C, tmp); 5264 } 5265 chipsFixResume(pScrn); 5266 tmp = cPtr->readXR(cPtr, 0x02); 5267 cPtr->writeXR(cPtr, 0x02, tmp & ~0x18); 5268 /* get generic registers */ 5269 vgaHWSave(pScrn, VgaSave, VGA_SR_ALL); 5270 5271 /* save clock */ 5272 chipsClockSave(pScrn, &ChipsSave->Clock); 5273 5274 /* save extended registers */ 5275 if (IS_HiQV(cPtr)) { 5276 for (i = 0; i < 0xFF; i++) { 5277#ifdef SAR04 5278 /* Save SAR04 multimedia register correctly */ 5279 if (i == 0x4F) 5280 cPtr->writeXR(cPtr, 0x4E, 0x04); 5281#endif 5282 ChipsSave->XR[i] = cPtr->readXR(cPtr,i); 5283#ifdef DEBUG 5284 ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); 5285#endif 5286 } 5287 for (i = 0; i < 0x80; i++) { 5288 ChipsSave->FR[i] = cPtr->readFR(cPtr, i); 5289#ifdef DEBUG 5290 ErrorF("FS%X - %X\n", i, ChipsSave->FR[i]); 5291#endif 5292 } 5293 for (i = 0; i < 0x80; i++) { 5294 ChipsSave->MR[i] = cPtr->readMR(cPtr, i); 5295#ifdef DEBUG 5296 ErrorF("MS%X - %X\n", i, ChipsSave->FR[i]); 5297#endif 5298 } 5299 /* Save CR0-CR40 even though we don't use them, so they can be 5300 * printed */ 5301 for (i = 0x0; i < 0x80; i++) { 5302 ChipsSave->CR[i] = hwp->readCrtc(hwp, i); 5303#ifdef DEBUG 5304 ErrorF("CS%X - %X\n", i, ChipsSave->CR[i]); 5305#endif 5306 } 5307 } else { 5308 for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ 5309 ChipsSave->XR[i] = cPtr->readXR(cPtr, i); 5310#ifdef DEBUG 5311 ErrorF("XS%X - %X\n", i, ChipsSave->XR[i]); 5312#endif 5313 } 5314 } 5315} 5316 5317Bool 5318chipsModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 5319{ 5320 CHIPSPtr cPtr = CHIPSPTR(pScrn); 5321#ifdef DEBUG 5322 ErrorF("chipsModeInit\n"); 5323#endif 5324#if 0 5325 *(int*)0xFFFFFF0 = 0; 5326 ErrorF("done\n"); 5327#endif 5328 5329 chipsUnlock(pScrn); 5330 chipsFixResume(pScrn); 5331 5332 if (cPtr->Accel.UseHWCursor) 5333 cPtr->Flags |= ChipsHWCursor; 5334 else 5335 cPtr->Flags &= ~ChipsHWCursor; 5336 /* 5337 * We need to delay cursor loading after resetting the video mode 5338 * to give the engine a chance to recover. 5339 */ 5340 cPtr->cursorDelay = TRUE; 5341 5342 if (IS_HiQV(cPtr)) 5343 return chipsModeInitHiQV(pScrn, mode); 5344 else if (IS_Wingine(cPtr)) 5345 return chipsModeInitWingine(pScrn, mode); 5346 else 5347 return chipsModeInit655xx(pScrn, mode); 5348} 5349 5350/* 5351 * The timing register of the C&T FP chipsets are organized 5352 * as follows: 5353 * The chipsets have two sets of timing registers: 5354 * the standard horizontal and vertical timing registers for 5355 * display size, blank start, sync start, sync end, blank end 5356 * and total size at their default VGA locations and extensions 5357 * and the alternate horizontal and vertical timing registers for 5358 * display size, sync start, sync end and total size. 5359 * In LCD and mixed (LCD+CRT) mode the alternate timing registers 5360 * control the timing. The alternate horizontal and vertical display 5361 * size registers are set to the physical pixel size of the display. 5362 * Normally the alternalte registers are set by the BIOS to optimized 5363 * values. 5364 * While the horizontal an vertical refresh rates are fixed independent 5365 * of the visible display size to ensure optimal performace of both 5366 * displays they can be adapted to the screen resolution and CRT 5367 * requirements in CRT mode by programming the standard timing registers 5368 * in the VGA fashion. 5369 * In LCD and mixed mode the _standard_ horizontal and vertical display 5370 * size registers control the size of the _visible_ part of the display 5371 * in contast to the _physical_ size of the display which is specified 5372 * by the _alternate_ horizontal and vertical display size registers. 5373 * The size of the visible should always be equal or less than the 5374 * physical size. 5375 * For the 69030 chipsets, the CRT and LCD display channels are seperate 5376 * and so can be driven independently. 5377 */ 5378static Bool 5379chipsModeInitHiQV(ScrnInfoPtr pScrn, DisplayModePtr mode) 5380{ 5381 int i; 5382 int lcdHTotal, lcdHDisplay; 5383 int lcdVTotal, lcdVDisplay; 5384 int lcdHRetraceStart, lcdHRetraceEnd; 5385 int lcdVRetraceStart, lcdVRetraceEnd; 5386 int lcdHSyncStart; 5387 vgaHWPtr hwp = VGAHWPTR(pScrn); 5388 CHIPSPtr cPtr = CHIPSPTR(pScrn); 5389 CHIPSRegPtr ChipsNew; 5390 vgaRegPtr ChipsStd; 5391 unsigned int tmp; 5392 5393 ChipsNew = &cPtr->ModeReg; 5394 ChipsStd = &hwp->ModeReg; 5395 5396 5397 /* 5398 * Possibly fix up the panel size, if the manufacture is stupid 5399 * enough to set it incorrectly in text modes 5400 */ 5401 if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { 5402 cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; 5403 cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; 5404 } 5405 5406 /* generic init */ 5407 if (!vgaHWInit(pScrn, mode)) { 5408 ErrorF("bomb 1\n"); 5409 return (FALSE); 5410 } 5411 pScrn->vtSema = TRUE; 5412 5413 /* init clock */ 5414 if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { 5415 ErrorF("bomb 2\n"); 5416 return (FALSE); 5417 } 5418 5419 /* Give Warning if the dual display mode will cause problems */ 5420 /* Note 64bit wide memory bus assumed (as in 69000 and 69030 */ 5421 if (cPtr->UseDualChannel && ((cPtr->SecondCrtc == TRUE) || 5422 (cPtr->Flags & ChipsDualRefresh))) { 5423 if (((ChipsNew->Clock.FPClock + ChipsNew->Clock.Clock) * 5424 (max(1, pScrn->bitsPerPixel >> 3) + 5425 ((cPtr->FrameBufferSize && (cPtr->PanelType & ChipsLCD)) ? 5426 1 : 0)) / (8 * 0.7)) > cPtr->MemClock.Max) { 5427 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5428 "Memory bandwidth requirements exceeded by dual-channel\n"); 5429 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5430 " mode. Display might be corrupted!!!\n"); 5431 } 5432 } 5433 5434 /* get C&T Specific Registers */ 5435 for (i = 0; i < 0xFF; i++) { 5436#ifdef SAR04 5437 /* Save SAR04 multimedia register correctly */ 5438 if (i == 0x4F) 5439 cPtr->writeXR(cPtr, 0x4E, 0x04); 5440#endif 5441 ChipsNew->XR[i] = cPtr->readXR(cPtr, i); 5442 } 5443 for (i = 0; i < 0x80; i++) { 5444 ChipsNew->FR[i] = cPtr->readFR(cPtr, i); 5445 } 5446 for (i = 0; i < 0x80; i++) { 5447 ChipsNew->MR[i] = cPtr->readMR(cPtr, i); 5448 } 5449 for (i = 0x30; i < 0x80; i++) { /* These are the CT extended CRT regs */ 5450 ChipsNew->CR[i] = hwp->readCrtc(hwp, i); 5451 } 5452 5453 /* 5454 * Here all of the other fields of 'ChipsNew' get filled in, to 5455 * handle the SVGA extended registers. It is also allowable 5456 * to override generic registers whenever necessary. 5457 */ 5458 5459 /* some generic settings */ 5460 if (pScrn->depth == 1) { 5461 ChipsStd->Attribute[0x10] = 0x03; /* mode */ 5462 } else { 5463 ChipsStd->Attribute[0x10] = 0x01; /* mode */ 5464 } 5465 if ((pScrn->bitsPerPixel == 16) && (cPtr->Flags & ChipsOverlay8plus16)) { 5466 /* Make sure that the overlay isn't visible in the overscan region */ 5467 if (ChipsStd->Attribute[0x11] == pScrn->colorKey) 5468 ChipsStd->Attribute[0x11] = pScrn->colorKey - 1; 5469 } else 5470 ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ 5471 ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ 5472 ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ 5473 5474 ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ 5475 5476 /* set virtual screen width */ 5477 tmp = pScrn->displayWidth >> 3; 5478 if (pScrn->bitsPerPixel == 16) { 5479 if (!(cPtr->Flags & ChipsOverlay8plus16)) 5480 tmp <<= 1; /* double the width of the buffer */ 5481 } else if (pScrn->bitsPerPixel == 24) { 5482 tmp += tmp << 1; 5483 } else if (pScrn->bitsPerPixel == 32) { 5484 tmp <<= 2; 5485 } else if (pScrn->bitsPerPixel < 8) { 5486 tmp >>= 1; 5487 } 5488 ChipsStd->CRTC[0x13] = tmp & 0xFF; 5489 ChipsNew->CR[0x41] = (tmp >> 8) & 0x0F; 5490 5491 /* Set paging mode on the HiQV32 architecture, if required */ 5492 if (!(cPtr->Flags & ChipsLinearSupport) || (pScrn->bitsPerPixel < 8)) 5493 ChipsNew->XR[0x0A] |= 0x1; 5494 5495#if X_BYTE_ORDER == X_BIG_ENDIAN 5496 ChipsNew->XR[0x0A] &= 0xCF; 5497 if (pScrn->bitsPerPixel == 16) { 5498 if (!cPtr->dualEndianAp) 5499 ChipsNew->XR[0x0A] |= 0x10; 5500 } 5501#endif 5502 ChipsNew->XR[0x09] |= 0x1; /* Enable extended CRT registers */ 5503 ChipsNew->XR[0x0E] = 0; /* Single map */ 5504 ChipsNew->XR[0x40] |= 0x2; /* Don't wrap at 256kb */ 5505 ChipsNew->XR[0x81] &= 0xF8; 5506 if (pScrn->bitsPerPixel >= 8) { 5507 ChipsNew->XR[0x40] |= 0x1; /* High Resolution. XR40[1] reserved? */ 5508 ChipsNew->XR[0x81] |= 0x2; /* 256 Color Video */ 5509 } 5510 ChipsNew->XR[0x80] |= 0x10; /* Enable cursor output on P0 and P1 */ 5511 if (pScrn->depth > 1) { 5512 if (pScrn->rgbBits == 8) 5513 ChipsNew->XR[0x80] |= 0x80; 5514 else 5515 ChipsNew->XR[0x80] &= ~0x80; 5516 } 5517 5518 if (abs(cPtr->MemClock.Clk - cPtr->MemClock.ProbedClk) > 50) { 5519 /* set mem clk */ 5520 ChipsNew->XR[0xCC] = cPtr->MemClock.xrCC; 5521 ChipsNew->XR[0xCD] = cPtr->MemClock.xrCD; 5522 ChipsNew->XR[0xCE] = cPtr->MemClock.xrCE; 5523 } 5524 5525 /* Set the 69030 dual channel settings */ 5526 if (cPtr->Flags & ChipsDualChannelSupport) { 5527 ChipsNew->FR[0x01] &= 0xFC; 5528 if ((cPtr->SecondCrtc == FALSE) && (cPtr->PanelType & ChipsLCD)) 5529 ChipsNew->FR[0x01] |= 0x02; 5530 else 5531 ChipsNew->FR[0x01] |= 0x01; 5532 ChipsNew->FR[0x02] &= 0xCC; 5533 if ((cPtr->SecondCrtc == TRUE) || (cPtr->Flags & ChipsDualRefresh)) 5534 ChipsNew->FR[0x02] |= 0x01; /* Set DAC to pipe B */ 5535 else 5536 ChipsNew->FR[0x02] &= 0xFE; /* Set DAC to pipe A */ 5537 5538 if (cPtr->PanelType & ChipsLCD) 5539 ChipsNew->FR[0x02] |= 0x20; /* Enable the LCD output */ 5540 if (cPtr->PanelType & ChipsCRT) 5541 ChipsNew->FR[0x02] |= 0x10; /* Enable the CRT output */ 5542 } 5543 5544 /* linear specific */ 5545 if (cPtr->Flags & ChipsLinearSupport) { 5546 ChipsNew->XR[0x0A] |= 0x02; /* Linear Addressing Mode */ 5547 ChipsNew->XR[0x20] = 0x0; /*BitBLT Draw Mode for 8 */ 5548 ChipsNew->XR[0x05] = 5549 (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); 5550 ChipsNew->XR[0x06] = 5551 (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); 5552 } 5553 5554 /* panel timing */ 5555 /* By default don't set panel timings, but allow it as an option */ 5556 if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { 5557 lcdHTotal = (mode->CrtcHTotal >> 3) - 5; 5558 lcdHDisplay = (cPtr->PanelSize.HDisplay >> 3) - 1; 5559 lcdHRetraceStart = (mode->CrtcHSyncStart >> 3); 5560 lcdHRetraceEnd = (mode->CrtcHSyncEnd >> 3); 5561 lcdHSyncStart = lcdHRetraceStart - 2; 5562 5563 lcdVTotal = mode->CrtcVTotal - 2; 5564 lcdVDisplay = cPtr->PanelSize.VDisplay - 1; 5565 lcdVRetraceStart = mode->CrtcVSyncStart; 5566 lcdVRetraceEnd = mode->CrtcVSyncEnd; 5567 5568 ChipsNew->FR[0x20] = lcdHDisplay & 0xFF; 5569 ChipsNew->FR[0x21] = lcdHRetraceStart & 0xFF; 5570 ChipsNew->FR[0x25] = ((lcdHRetraceStart & 0xF00) >> 4) | 5571 ((lcdHDisplay & 0xF00) >> 8); 5572 ChipsNew->FR[0x22] = lcdHRetraceEnd & 0x1F; 5573 ChipsNew->FR[0x23] = lcdHTotal & 0xFF; 5574 ChipsNew->FR[0x24] = (lcdHSyncStart >> 3) & 0xFF; 5575 ChipsNew->FR[0x26] = (ChipsNew->FR[0x26] & ~0x1F) 5576 | ((lcdHTotal & 0xF00) >> 8) 5577 | (((lcdHSyncStart >> 3) & 0x100) >> 4); 5578 ChipsNew->FR[0x27] &= 0x7F; 5579 5580 ChipsNew->FR[0x30] = lcdVDisplay & 0xFF; 5581 ChipsNew->FR[0x31] = lcdVRetraceStart & 0xFF; 5582 ChipsNew->FR[0x35] = ((lcdVRetraceStart & 0xF00) >> 4) 5583 | ((lcdVDisplay & 0xF00) >> 8); 5584 ChipsNew->FR[0x32] = lcdVRetraceEnd & 0x0F; 5585 ChipsNew->FR[0x33] = lcdVTotal & 0xFF; 5586 ChipsNew->FR[0x34] = (lcdVTotal - lcdVRetraceStart) & 0xFF; 5587 ChipsNew->FR[0x36] = ((lcdVTotal & 0xF00) >> 8) | 5588 (((lcdVTotal - lcdVRetraceStart) & 0x700) >> 4); 5589 ChipsNew->FR[0x37] |= 0x80; 5590 } 5591 5592 /* Set up the extended CRT registers of the HiQV32 chips */ 5593 ChipsNew->CR[0x30] = ((mode->CrtcVTotal - 2) & 0xF00) >> 8; 5594 ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; 5595 ChipsNew->CR[0x32] = (mode->CrtcVSyncStart & 0xF00) >> 8; 5596 ChipsNew->CR[0x33] = (mode->CrtcVBlankStart & 0xF00) >> 8; 5597 if ((cPtr->Chipset == CHIPS_CT69000) || (cPtr->Chipset == CHIPS_CT69030)) { 5598 /* The 690xx has overflow bits for the horizontal values as well */ 5599 ChipsNew->CR[0x38] = (((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8; 5600 ChipsNew->CR[0x3C] = vgaHWHBlankKGA(mode, ChipsStd, 8, 0) << 6; 5601 } else 5602 vgaHWHBlankKGA(mode, ChipsStd, 6, 0); 5603 vgaHWVBlankKGA(mode, ChipsStd, 8, 0); 5604 5605 ChipsNew->CR[0x40] |= 0x80; 5606 5607 /* centering/stretching */ 5608 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { 5609 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) || 5610 (cPtr->Flags & ChipsOverlay8plus16)) { 5611 ChipsNew->FR[0x40] &= 0xDF; /* Disable Horizontal stretching */ 5612 ChipsNew->FR[0x48] &= 0xFB; /* Disable vertical stretching */ 5613 ChipsNew->XR[0xA0] = 0x10; /* Disable cursor stretching */ 5614 } else { 5615 ChipsNew->FR[0x40] |= 0x21; /* Enable Horizontal stretching */ 5616 ChipsNew->FR[0x48] |= 0x05; /* Enable vertical stretching */ 5617 ChipsNew->XR[0xA0] = 0x70; /* Enable cursor stretching */ 5618 if (cPtr->Accel.UseHWCursor 5619 && cPtr->PanelSize.HDisplay && cPtr->PanelSize.VDisplay 5620 && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) 5621 && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { 5622 if(cPtr->Accel.UseHWCursor) 5623 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 5624 "Disabling HW Cursor on stretched LCD\n"); 5625 cPtr->Flags &= ~ChipsHWCursor; 5626 } 5627 } 5628 } 5629 5630 if ((xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE)) 5631 || (cPtr->Flags & ChipsOverlay8plus16)) { 5632 ChipsNew->FR[0x40] |= 0x3; /* Enable Horizontal centering */ 5633 ChipsNew->FR[0x48] |= 0x3; /* Enable Vertical centering */ 5634 } else { 5635 ChipsNew->FR[0x40] &= 0xFD; /* Disable Horizontal centering */ 5636 ChipsNew->FR[0x48] &= 0xFD; /* Disable Vertical centering */ 5637 } 5638 5639 /* sync on green */ 5640 if (xf86ReturnOptValBool(cPtr->Options, OPTION_SYNC_ON_GREEN, FALSE)) 5641 ChipsNew->XR[0x82] |=0x02; 5642 5643 /* software mode flag */ 5644 ChipsNew->XR[0xE2] = chipsVideoMode(((cPtr->Flags & ChipsOverlay8plus16) ? 5645 8 : pScrn->depth), (cPtr->PanelType & ChipsLCD) ? 5646 min(mode->CrtcHDisplay, cPtr->PanelSize.HDisplay) : 5647 mode->CrtcHDisplay, mode->CrtcVDisplay); 5648#ifdef DEBUG 5649 ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0xE2]); 5650#endif 5651 5652 /* sync. polarities */ 5653 if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) 5654 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { 5655 if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { 5656 if (mode->Flags & V_PHSYNC) 5657 ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ 5658 else 5659 ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ 5660 } 5661 if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { 5662 if (mode->Flags & V_PVSYNC) 5663 ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ 5664 else 5665 ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ 5666 } 5667 } 5668 if (mode->Flags & (V_PCSYNC | V_NCSYNC)) { 5669 ChipsNew->FR[0x0B] |= 0x20; 5670 if (mode->Flags & V_PCSYNC) { 5671 ChipsNew->FR[0x08] &= 0x7F; /* Alt. CRT Vsync positive */ 5672 ChipsNew->FR[0x08] &= 0xBF; /* Alt. CRT Hsync positive */ 5673 ChipsStd->MiscOutReg &= 0x7F; 5674 ChipsStd->MiscOutReg &= 0xBF; 5675 } else { 5676 ChipsNew->FR[0x08] |= 0x80; /* Alt. CRT Vsync negative */ 5677 ChipsNew->FR[0x08] |= 0x40; /* Alt. CRT Hsync negative */ 5678 ChipsStd->MiscOutReg |= 0x40; 5679 ChipsStd->MiscOutReg |= 0x80; 5680 } 5681 } 5682 /* bpp depend */ 5683 if ((pScrn->bitsPerPixel == 16) && (!(cPtr->Flags & ChipsOverlay8plus16))) { 5684 ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x4; 5685 if (cPtr->Flags & ChipsGammaSupport) 5686 ChipsNew->XR[0x82] |= 0x0C; 5687 /* 16bpp = 5-5-5 */ 5688 ChipsNew->FR[0x10] |= 0x0C; /*Colour Panel */ 5689 ChipsNew->XR[0x20] = 0x10; /*BitBLT Draw Mode for 16 bpp */ 5690 if (pScrn->weight.green != 5) 5691 ChipsNew->XR[0x81] |= 0x01; /*16bpp */ 5692 } else if (pScrn->bitsPerPixel == 24) { 5693 ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x6; 5694 if (cPtr->Flags & ChipsGammaSupport) 5695 ChipsNew->XR[0x82] |= 0x0C; 5696 /* 24bpp colour */ 5697 ChipsNew->XR[0x20] = 0x20; /*BitBLT Draw Mode for 24 bpp */ 5698 } else if (pScrn->bitsPerPixel == 32) { 5699 ChipsNew->XR[0x81] = (ChipsNew->XR[0x81] & 0xF0) | 0x7; 5700 if (cPtr->Flags & ChipsGammaSupport) 5701 ChipsNew->XR[0x82] |= 0x0C; 5702 /* 32bpp colour */ 5703 ChipsNew->XR[0x20] = 0x10; /*BitBLT Mode for 16bpp used at 32bpp */ 5704 } 5705 5706 /*CRT only */ 5707 if (!(cPtr->PanelType & ChipsLCD)) { 5708 if (mode->Flags & V_INTERLACE) { 5709 ChipsNew->CR[0x70] = 0x80 /* set interlace */ 5710 | (((((mode->CrtcHDisplay >> 3) - 1) >> 1) - 6) & 0x7F); 5711 /* 5712 ** Double VDisplay to get back the full screen value, otherwise 5713 ** you only see half the picture. 5714 */ 5715 mode->CrtcVDisplay = mode->VDisplay; 5716 tmp = ChipsStd->CRTC[7] & ~0x42; 5717 ChipsStd->CRTC[7] = (tmp | 5718 ((((mode->CrtcVDisplay -1) & 0x100) >> 7 ) | 5719 (((mode->CrtcVDisplay -1) & 0x200) >> 3 ))); 5720 ChipsStd->CRTC[0x12] = (mode->CrtcVDisplay -1) & 0xFF; 5721 ChipsNew->CR[0x31] = ((mode->CrtcVDisplay - 1) & 0xF00) >> 8; 5722 } else { 5723 ChipsNew->CR[0x70] &= ~0x80; /* unset interlace */ 5724 } 5725 } 5726 5727#if defined(__arm__) && defined(___NetBSD__) 5728 if (cPtr->TVMode != XMODE_RGB) { 5729 /* 5730 * Put the console into TV Out mode. 5731 */ 5732 xf86SetTVOut(cPtr->TVMode); 5733 5734 ChipsNew->CR[0x72] = (mode->CrtcHTotal >> 1) >> 3;/* First horizontal 5735 * serration pulse */ 5736 ChipsNew->CR[0x73] = mode->CrtcHTotal >> 3; /* Second pulse */ 5737 ChipsNew->CR[0x74] = (((mode->HSyncEnd - mode->HSyncStart) >> 3) - 1) 5738 & 0x1F; /* equalization pulse */ 5739 5740 if (cPtr->TVMode == XMODE_PAL || cPtr->TVMode == XMODE_SECAM) { 5741 ChipsNew->CR[0x71] = 0xA0; /* PAL support with blanking delay */ 5742 } else { 5743 ChipsNew->CR[0x71] = 0x20; /* NTSC support with blanking delay */ 5744 } 5745 } else { /* XMODE_RGB */ 5746 /* 5747 * Put the console into RGB Out mode. 5748 */ 5749 xf86SetRGBOut(); 5750 } 5751#endif 5752 5753 /* STN specific */ 5754 if (IS_STN(cPtr->PanelType)) { 5755 ChipsNew->FR[0x11] &= ~0x03; /* FRC clear */ 5756 ChipsNew->FR[0x11] &= ~0x8C; /* Dither clear */ 5757 ChipsNew->FR[0x11] |= 0x01; /* 16 frame FRC */ 5758 ChipsNew->FR[0x11] |= 0x84; /* Dither */ 5759 if ((cPtr->Flags & ChipsTMEDSupport) && 5760 !xf86ReturnOptValBool(cPtr->Options, OPTION_NO_TMED, FALSE)) { 5761 ChipsNew->FR[0x73] &= 0x4F; /* Clear TMED */ 5762 ChipsNew->FR[0x73] |= 0x80; /* Enable TMED */ 5763 ChipsNew->FR[0x73] |= 0x30; /* TMED 256 Shades of RGB */ 5764 } 5765 if (cPtr->PanelType & ChipsDD) /* Shift Clock Mask. Use to get */ 5766 ChipsNew->FR[0x12] |= 0x4; /* rid of line in DSTN screens */ 5767 } 5768 5769 /* 5770 * The zero position of the overlay does not align with the zero 5771 * position of the display. The skew is dependent on the depth, 5772 * display type and refresh rate. Calculate the skew before setting 5773 * the X and Y dimensions of the overlay. These values are needed 5774 * both by the overlay and XvImages. So calculate and store them 5775 */ 5776 if (cPtr->PanelType & ChipsLCD) { 5777 cPtr->OverlaySkewX = (((ChipsNew->FR[0x23] & 0xFF) 5778 - (ChipsNew->FR[0x20] & 0xFF) + 3) << 3) 5779 - 1; 5780 cPtr->OverlaySkewY = (ChipsNew->FR[0x33] 5781 + ((ChipsNew->FR[0x36] & 0xF) << 8) 5782 - (ChipsNew->FR[0x31] & 0xF0) 5783 - (ChipsNew->FR[0x32] & 0x0F) 5784 - ((ChipsNew->FR[0x35] & 0xF0) << 4)); 5785 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, FALSE) 5786 && xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_CENTER, TRUE)) 5787 { 5788 if (cPtr->PanelSize.HDisplay > mode->CrtcHDisplay) 5789 cPtr->OverlaySkewX += (cPtr->PanelSize.HDisplay - 5790 mode->CrtcHDisplay) / 2; 5791 if (cPtr->PanelSize.VDisplay > mode->CrtcVDisplay) 5792 cPtr->OverlaySkewY += (cPtr->PanelSize.VDisplay - 5793 mode->CrtcVDisplay) / 2; 5794 } 5795 } else { 5796 cPtr->OverlaySkewX = mode->CrtcHTotal - mode->CrtcHBlankStart - 9; 5797 cPtr->OverlaySkewY = mode->CrtcVTotal - mode->CrtcVSyncEnd - 1; 5798 5799 if (mode->Flags & V_INTERLACE) { 5800 /* 5801 * This handles 1024 and 1280 interlaced modes only. Its 5802 * pretty arbitrary, but its what C&T recommends 5803 */ 5804#if 0 5805 if (mode->CrtcHDisplay == 1024) 5806 cPtr->OverlaySkewY += 5; 5807 else if (mode->CrtcHDisplay == 1280) 5808#endif 5809 cPtr->OverlaySkewY *= 2; 5810 5811 } 5812 } 5813 5814 /* mask for viewport granularity */ 5815 5816 switch (pScrn->bitsPerPixel) { 5817 case 8: 5818 cPtr->viewportMask = ~7U; 5819 break; 5820 case 16: 5821 cPtr->viewportMask = ~3U; 5822 break; 5823 case 24: 5824 cPtr->viewportMask = ~7U; 5825 break; 5826 case 32: 5827 cPtr->viewportMask = ~0U; 5828 break; 5829 default: 5830 cPtr->viewportMask = ~7U; 5831 } 5832 5833 /* Turn off multimedia by default as it degrades performance */ 5834 ChipsNew->XR[0xD0] &= 0x0f; 5835 5836 /* Setup the video/overlay */ 5837 if (cPtr->Flags & ChipsOverlay8plus16) { 5838 ChipsNew->XR[0xD0] |= 0x10; /* Force the Multimedia engine on */ 5839#ifdef SAR04 5840 ChipsNew->XR[0x4F] = 0x2A; /* SAR04 >352 pixel overlay width */ 5841#endif 5842 ChipsNew->MR[0x1E] &= 0xE0; /* Set Zoom and Direction */ 5843 if ((!(cPtr->PanelType & ChipsLCD)) && (mode->Flags & V_INTERLACE)) 5844 ChipsNew->MR[0x1E] |= 0x10; /* Interlace */ 5845 ChipsNew->MR[0x1F] &= 0x14; /* Mask reserved bits */ 5846 ChipsNew->MR[0x1F] |= 0x08; /* RGB 16bpp */ 5847 if (pScrn->weight.green == 5) 5848 ChipsNew->MR[0x1F] |= 0x01; /* RGB 15bpp */ 5849 5850 ChipsNew->MR[0x20] &= 0x03; /* Mask reserved bits */ 5851 ChipsNew->MR[0x20] |= 0x80; /* Auto Centre, Use mem ptr1 */ 5852 ChipsNew->MR[0x22] = cPtr->FbOffset16 & 0xF8; /* Setup Pointer 1 */ 5853 ChipsNew->MR[0x23] = (cPtr->FbOffset16 >> 8) & 0xFF; 5854 ChipsNew->MR[0x24] = (cPtr->FbOffset16 >> 16) & 0xFF; 5855 ChipsNew->MR[0x25] = cPtr->FbOffset16 & 0xF8; /* Setup Pointer 2 */ 5856 ChipsNew->MR[0x26] = (cPtr->FbOffset16 >> 8) & 0xFF; 5857 ChipsNew->MR[0x27] = (cPtr->FbOffset16 >> 16) & 0xFF; 5858 ChipsNew->MR[0x28] = (pScrn->displayWidth >> 2) - 1; /* Width */ 5859 ChipsNew->MR[0x34] = (pScrn->displayWidth >> 2) - 1; 5860 5861 /* Left Edge of Overlay */ 5862 ChipsNew->MR[0x2A] = cPtr->OverlaySkewX; 5863 ChipsNew->MR[0x2B] &= 0xF8; /* Mask reserved bits */ 5864 ChipsNew->MR[0x2B] |= ((cPtr->OverlaySkewX >> 8) & 0x7); 5865 /* Right Edge of Overlay */ 5866 ChipsNew->MR[0x2C] = (cPtr->OverlaySkewX + pScrn->displayWidth - 5867 1) & 0xFF; 5868 ChipsNew->MR[0x2D] &= 0xF8; /* Mask reserved bits */ 5869 ChipsNew->MR[0x2D] |= ((cPtr->OverlaySkewX + pScrn->displayWidth - 5870 1) >> 8) & 0x07; 5871 /* Top Edge of Overlay */ 5872 ChipsNew->MR[0x2E] = cPtr->OverlaySkewY; 5873 ChipsNew->MR[0x2F] &= 0xF8; 5874 ChipsNew->MR[0x2F] |= ((cPtr->OverlaySkewY >> 8) & 0x7); 5875 /* Bottom Edge of Overlay*/ 5876 ChipsNew->MR[0x30] = (cPtr->OverlaySkewY + pScrn->virtualY - 1 )& 0xFF; 5877 ChipsNew->MR[0x31] &= 0xF8; /* Mask reserved bits */ 5878 ChipsNew->MR[0x31] |= ((cPtr->OverlaySkewY + pScrn->virtualY - 5879 1 ) >> 8) & 0x07; 5880 5881 ChipsNew->MR[0x3C] &= 0x18; /* Mask reserved bits */ 5882 ChipsNew->MR[0x3C] |= 0x07; /* Enable keyed overlay window */ 5883 ChipsNew->MR[0x3D] = 0x00; 5884 ChipsNew->MR[0x3E] = 0x00; 5885 ChipsNew->MR[0x3F] = pScrn->colorKey; /* 8bpp transparency key */ 5886 ChipsNew->MR[0x40] = 0xFF; 5887 ChipsNew->MR[0x41] = 0xFF; 5888 ChipsNew->MR[0x42] = 0x00; 5889 } else if (cPtr->Flags & ChipsVideoSupport) { 5890#if 0 /* if we do this even though video isn't playing we kill performance */ 5891 ChipsNew->XR[0xD0] |= 0x10; /* Force the Multimedia engine on */ 5892#endif 5893#ifdef SAR04 5894 ChipsNew->XR[0x4F] = 0x2A; /* SAR04 >352 pixel overlay width */ 5895#endif 5896 ChipsNew->MR[0x3C] &= 0x18; /* Ensure that the overlay is off */ 5897 cPtr->VideoZoomMax = 0x100; 5898 5899 if (cPtr->Chipset == CHIPS_CT65550) { 5900 tmp = cPtr->readXR(cPtr, 0x04); 5901 if (tmp < 0x02) /* 65550 ES0 has */ 5902 cPtr->VideoZoomMax = 0x40; /* 0x40 max zoom */ 5903 } 5904 } 5905 5906 /* Program the registers */ 5907 /*vgaHWProtect(pScrn, TRUE);*/ 5908 5909 if (cPtr->Chipset <= CHIPS_CT69000) { 5910 ChipsNew->FR[0x01] &= ~0x03; 5911 if (cPtr->PanelType & ChipsLCD) 5912 ChipsNew->FR[0x01] |= 0x02; 5913 else 5914 ChipsNew->FR[0x01] |= 0x01; 5915 } 5916 if ((cPtr->Flags & ChipsDualChannelSupport) && 5917 (!xf86IsEntityShared(pScrn->entityList[0]))) { 5918 unsigned char IOSS, MSS, tmpfr01; 5919 5920 5921 IOSS = cPtr->readIOSS(cPtr); 5922 MSS = cPtr->readMSS(cPtr); 5923 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 5924 IOSS_PIPE_A)); 5925 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | 5926 MSS_PIPE_A)); 5927 chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); 5928 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 5929 IOSS_PIPE_B)); 5930 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | 5931 MSS_PIPE_B)); 5932 /* 5933 * Hack:: Force Pipe-B on for dual refresh, and off elsewise 5934 */ 5935 tmpfr01 = ChipsNew->FR[0x01]; 5936 ChipsNew->FR[0x01] &= 0xFC; 5937 if (cPtr->UseDualChannel) 5938 ChipsNew->FR[0x01] |= 0x01; 5939 chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); 5940 ChipsNew->FR[0x01] = tmpfr01; 5941 cPtr->writeIOSS(cPtr, IOSS); 5942 cPtr->writeMSS(cPtr, hwp, MSS); 5943 } else { 5944 chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); 5945 } 5946 5947 /*vgaHWProtect(pScrn, FALSE);*/ 5948 usleep(100000); /* prevents cursor corruption seen on a TECRA 510 */ 5949 5950 return(TRUE); 5951} 5952 5953static Bool 5954chipsModeInitWingine(ScrnInfoPtr pScrn, DisplayModePtr mode) 5955{ 5956 int i, bytesPerPixel; 5957 vgaHWPtr hwp = VGAHWPTR(pScrn); 5958 CHIPSPtr cPtr = CHIPSPTR(pScrn); 5959 CHIPSRegPtr ChipsNew; 5960 vgaRegPtr ChipsStd; 5961 unsigned int tmp; 5962 5963 ChipsNew = &cPtr->ModeReg; 5964 ChipsStd = &hwp->ModeReg; 5965 5966 bytesPerPixel = pScrn->bitsPerPixel >> 3; 5967 5968 /* 5969 * This chipset seems to have problems if 5970 * HBlankEnd is choosen equals HTotal 5971 */ 5972 if (!mode->CrtcHAdjusted) 5973 mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); 5974 5975 /* correct the timings for 16/24 bpp */ 5976 if (pScrn->bitsPerPixel == 16) { 5977 if (!mode->CrtcHAdjusted) { 5978 mode->CrtcHDisplay++; 5979 mode->CrtcHDisplay <<= 1; 5980 mode->CrtcHDisplay--; 5981 mode->CrtcHSyncStart <<= 1; 5982 mode->CrtcHSyncEnd <<= 1; 5983 mode->CrtcHBlankStart <<= 1; 5984 mode->CrtcHBlankEnd <<= 1; 5985 mode->CrtcHTotal <<= 1; 5986 mode->CrtcHAdjusted = TRUE; 5987 } 5988 } else if (pScrn->bitsPerPixel == 24) { 5989 if (!mode->CrtcHAdjusted) { 5990 mode->CrtcHDisplay++; 5991 mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); 5992 mode->CrtcHDisplay--; 5993 mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); 5994 mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); 5995 mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); 5996 mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); 5997 mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); 5998 mode->CrtcHAdjusted = TRUE; 5999 } 6000 } 6001 6002 /* generic init */ 6003 if (!vgaHWInit(pScrn, mode)) { 6004 ErrorF("bomb 3\n"); 6005 return (FALSE); 6006 } 6007 pScrn->vtSema = TRUE; 6008 6009 /* init clock */ 6010 if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { 6011 ErrorF("bomb 4\n"); 6012 return (FALSE); 6013 } 6014 6015 /* get C&T Specific Registers */ 6016 for (i = 0; i < 0x7D; i++) { /* don't touch XR7D and XR7F on WINGINE */ 6017 ChipsNew->XR[i] = cPtr->readXR(cPtr, i); 6018 } 6019 6020 /* some generic settings */ 6021 if (pScrn->bitsPerPixel == 1) { 6022 ChipsStd->Attribute[0x10] = 0x03; /* mode */ 6023 } else { 6024 ChipsStd->Attribute[0x10] = 0x01; /* mode */ 6025 } 6026 ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ 6027 ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ 6028 ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ 6029 6030 ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ 6031 6032 6033 /* set virtual screen width */ 6034 if (pScrn->bitsPerPixel >= 8) 6035 ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; 6036 else 6037 ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; 6038 6039 6040 /* set C&T Specific Registers */ 6041 /* set virtual screen width */ 6042 if (pScrn->bitsPerPixel >= 8) 6043 tmp = (pScrn->displayWidth >> 4) * bytesPerPixel; 6044 else 6045 tmp = (pScrn->displayWidth >> 5); 6046 ChipsNew->XR[0x0D] = (tmp & 0x80) >> 5; 6047 6048 ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ 6049 /* XR04: Memory control 1 */ 6050 /* bit 2: Memory Wraparound */ 6051 /* Enable CRTC addr counter bits 16-17 if set */ 6052 6053 ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ 6054 ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ 6055 /* XR0B: CPU paging */ 6056 /* bit 0: Memory mapping mode */ 6057 /* VGA compatible if 0 (default) */ 6058 /* Extended mode (mapping for > 256 kB mem) if 1 */ 6059 /* bit 1: CPU single/dual mapping */ 6060 /* 0, CPU uses only a single map to access (default) */ 6061 /* 1, CPU uses two maps to access */ 6062 /* bit 2: CPU address divide by 4 */ 6063 6064 ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ 6065 ChipsNew->XR[0x11] = 0; /* XR11: High map */ 6066 ChipsNew->XR[0x0C] &= ~0x50; /* MSB for XR10 & XR11 */ 6067 if (pScrn->bitsPerPixel >= 8) { 6068 ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ 6069 } else { 6070 ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ 6071 } 6072 /* set up extended display timings */ 6073 /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ 6074 ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) 6075 | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) 6076 | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) 6077 | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) 6078 | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) 6079 | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); 6080 6081 6082 ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) 6083 | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) 6084 | ((mode->CrtcVSyncStart & 0x400) >> 8 ) 6085 | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); 6086 6087 /* set video mode */ 6088 ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, mode->CrtcHDisplay, mode->CrtcVDisplay); 6089#ifdef DEBUG 6090 ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); 6091#endif 6092 6093 /* set some linear specific registers */ 6094 if (cPtr->Flags & ChipsLinearSupport) { 6095 /* enable linear addressing */ 6096 ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ 6097 ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ 6098 6099 ChipsNew->XR[0x08] = 6100 (unsigned char)((cPtr->FbAddress >> 16) & 0xFF); 6101 ChipsNew->XR[0x09] = 6102 (unsigned char)((cPtr->FbAddress >> 24) & 0xFF); 6103 6104 /* general setup */ 6105 ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ 6106 } 6107 6108 /* common general setup */ 6109 ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ 6110 ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ 6111 ChipsNew->XR[0x02] &= 0xE7; /* Attr. Cont. default access */ 6112 /* use ext. regs. for hor. in dual */ 6113 ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ 6114 6115 /* bpp depend */ 6116 /*XR06: Palette control */ 6117 /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ 6118 /* bit 1: Internal DAC disable */ 6119 /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ 6120 /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ 6121 /* bit 4: Enable PC Video Overlay on colour key */ 6122 /* bit 5: Bypass Internal VGA palette */ 6123 /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ 6124 /* 1 for Equivalent weighting, 2 for green only, */ 6125 /* 3 for Colour w/o reduction */ 6126 /* XR50 Panel Format Register 1 */ 6127 /* bit 1-0: Frame Rate Control; 00, No FRC; */ 6128 /* 01, 16-frame FRC for colour STN and monochrome */ 6129 /* 10, 2-frame FRC for colour TFT or monochrome; */ 6130 /* 11, reserved */ 6131 /* bit 3-2: Dither Enable */ 6132 /* 00, disable dithering; 01, enable dithering */ 6133 /* for 256 mode */ 6134 /* 10, enable dithering for all modes; 11, reserved */ 6135 /* bit6-4: Clock Divide (CD) */ 6136 /* 000, Shift Clock Freq = Dot Clock Freq; */ 6137 /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ 6138 /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ 6139 /* bit 7: TFT data width */ 6140 /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ 6141 if (pScrn->bitsPerPixel == 16) { 6142 ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ 6143 ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ 6144 ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ 6145 if (pScrn->weight.green != 5) 6146 ChipsNew->XR[0x06] |= 0x08; /*16bpp */ 6147 } else if (pScrn->bitsPerPixel == 24) { 6148 ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ 6149 ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ 6150 } 6151 6152 /*CRT only: interlaced mode */ 6153 if (mode->Flags & V_INTERLACE) { 6154 ChipsNew->XR[0x28] |= 0x20; /* set interlace */ 6155 /* empirical value */ 6156 tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) 6157 - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); 6158 ChipsNew->XR[0x19] = tmp & 0xFF; 6159 ChipsNew->XR[0x17] |= ((tmp & 0x100) >> 1); /* overflow */ 6160 ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ 6161 } else { 6162 ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ 6163 ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ 6164 } 6165 6166 /* Program the registers */ 6167 /*vgaHWProtect(pScrn, TRUE);*/ 6168 chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); 6169 /*vgaHWProtect(pScrn, FALSE);*/ 6170 6171 return (TRUE); 6172} 6173 6174static Bool 6175chipsModeInit655xx(ScrnInfoPtr pScrn, DisplayModePtr mode) 6176{ 6177 int i, bytesPerPixel; 6178 int lcdHTotal, lcdHDisplay; 6179 int lcdVTotal, lcdVDisplay; 6180 int lcdHRetraceStart, lcdHRetraceEnd; 6181 int lcdVRetraceStart, lcdVRetraceEnd; 6182 int HSyncStart, HDisplay; 6183 int CrtcHDisplay; 6184 vgaHWPtr hwp = VGAHWPTR(pScrn); 6185 CHIPSPtr cPtr = CHIPSPTR(pScrn); 6186 CHIPSRegPtr ChipsNew; 6187 vgaRegPtr ChipsStd; 6188 unsigned int tmp; 6189 6190 ChipsNew = &cPtr->ModeReg; 6191 ChipsStd = &hwp->ModeReg; 6192 6193 bytesPerPixel = pScrn->bitsPerPixel >> 3; 6194 6195 /* 6196 * Possibly fix up the panel size, if the manufacture is stupid 6197 * enough to set it incorrectly in text modes 6198 */ 6199 if (xf86ReturnOptValBool(cPtr->Options, OPTION_PANEL_SIZE, FALSE)) { 6200 cPtr->PanelSize.HDisplay = mode->CrtcHDisplay; 6201 cPtr->PanelSize.VDisplay = mode->CrtcVDisplay; 6202 } 6203 6204 /* 6205 * This chipset seems to have problems if 6206 * HBlankEnd is choosen equals HTotal 6207 */ 6208 if (!mode->CrtcHAdjusted) 6209 mode->CrtcHBlankEnd = min(mode->CrtcHSyncEnd, mode->CrtcHTotal - 2); 6210 6211 /* correct the timings for 16/24 bpp */ 6212 if (pScrn->bitsPerPixel == 16) { 6213 if (!mode->CrtcHAdjusted) { 6214 mode->CrtcHDisplay++; 6215 mode->CrtcHDisplay <<= 1; 6216 mode->CrtcHDisplay--; 6217 mode->CrtcHSyncStart <<= 1; 6218 mode->CrtcHSyncEnd <<= 1; 6219 mode->CrtcHBlankStart <<= 1; 6220 mode->CrtcHBlankEnd <<= 1; 6221 mode->CrtcHTotal <<= 1; 6222 mode->CrtcHAdjusted = TRUE; 6223 } 6224 } else if (pScrn->bitsPerPixel == 24) { 6225 if (!mode->CrtcHAdjusted) { 6226 mode->CrtcHDisplay++; 6227 mode->CrtcHDisplay += ((mode->CrtcHDisplay) << 1); 6228 mode->CrtcHDisplay--; 6229 mode->CrtcHSyncStart += ((mode->CrtcHSyncStart) << 1); 6230 mode->CrtcHSyncEnd += ((mode->CrtcHSyncEnd) << 1); 6231 mode->CrtcHBlankStart += ((mode->CrtcHBlankStart) << 1); 6232 mode->CrtcHBlankEnd += ((mode->CrtcHBlankEnd) << 1); 6233 mode->CrtcHTotal += ((mode->CrtcHTotal) << 1); 6234 mode->CrtcHAdjusted = TRUE; 6235 } 6236 } 6237 6238 /* store orig. HSyncStart needed for flat panel mode */ 6239 HSyncStart = mode->CrtcHSyncStart / (pScrn->bitsPerPixel >= 8 ? 6240 bytesPerPixel : 1 ) - 16; 6241 HDisplay = (mode->CrtcHDisplay + 1) / (pScrn->bitsPerPixel >= 8 ? 6242 bytesPerPixel : 1 ); 6243 6244 /* generic init */ 6245 if (!vgaHWInit(pScrn, mode)) { 6246 ErrorF("bomb 5\n"); 6247 return (FALSE); 6248 } 6249 pScrn->vtSema = TRUE; 6250 6251 /* init clock */ 6252 if (!chipsClockFind(pScrn, mode, mode->ClockIndex, &ChipsNew->Clock)) { 6253 ErrorF("bomb 6\n"); 6254 return (FALSE); 6255 } 6256 6257 /* get C&T Specific Registers */ 6258 for (i = 0; i < 0x80; i++) { 6259 ChipsNew->XR[i] = cPtr->readXR(cPtr, i); 6260 } 6261 6262 /* some generic settings */ 6263 if (pScrn->bitsPerPixel == 1) { 6264 ChipsStd->Attribute[0x10] = 0x03; /* mode */ 6265 } else { 6266 ChipsStd->Attribute[0x10] = 0x01; /* mode */ 6267 } 6268 ChipsStd->Attribute[0x11] = 0x00; /* overscan (border) color */ 6269 ChipsStd->Attribute[0x12] = 0x0F; /* enable all color planes */ 6270 ChipsStd->Attribute[0x13] = 0x00; /* horiz pixel panning 0 */ 6271 6272 ChipsStd->Graphics[0x05] = 0x00; /* normal read/write mode */ 6273 6274 /* set virtual screen width */ 6275 if (pScrn->bitsPerPixel >= 8) 6276 ChipsStd->CRTC[0x13] = (pScrn->displayWidth * bytesPerPixel) >> 3; 6277 else 6278 ChipsStd->CRTC[0x13] = pScrn->displayWidth >> 4; 6279 6280 6281 /* set C&T Specific Registers */ 6282 /* set virtual screen width */ 6283 ChipsNew->XR[0x1E] = ChipsStd->CRTC[0x13]; /* alternate offset */ 6284 /*databook is not clear about 0x1E might be needed for 65520/30 */ 6285 if (pScrn->bitsPerPixel >= 8) 6286 tmp = (pScrn->displayWidth * bytesPerPixel) >> 2; 6287 else 6288 tmp = pScrn->displayWidth >> 3; 6289 ChipsNew->XR[0x0D] = (tmp & 0x01) | ((tmp << 1) & 0x02) ; 6290 6291 ChipsNew->XR[0x04] |= 4; /* enable addr counter bits 16-17 */ 6292 /* XR04: Memory control 1 */ 6293 /* bit 2: Memory Wraparound */ 6294 /* Enable CRTC addr counter bits 16-17 if set */ 6295 6296 ChipsNew->XR[0x0B] |= 0x07; /* extended mode, dual pages enabled */ 6297 ChipsNew->XR[0x0B] &= ~0x10; /* linear mode off */ 6298 /* XR0B: CPU paging */ 6299 /* bit 0: Memory mapping mode */ 6300 /* VGA compatible if 0 (default) */ 6301 /* Extended mode (mapping for > 256 kB mem) if 1 */ 6302 /* bit 1: CPU single/dual mapping */ 6303 /* 0, CPU uses only a single map to access (default) */ 6304 /* 1, CPU uses two maps to access */ 6305 /* bit 2: CPU address divide by 4 */ 6306 6307 ChipsNew->XR[0x10] = 0; /* XR10: Single/low map */ 6308 ChipsNew->XR[0x11] = 0; /* XR11: High map */ 6309 if (pScrn->bitsPerPixel >= 8) { 6310 ChipsNew->XR[0x28] |= 0x10; /* 256-color video */ 6311 } else { 6312 ChipsNew->XR[0x28] &= 0xEF; /* 16-color video */ 6313 } 6314 /* set up extended display timings */ 6315 if (!(cPtr->PanelType & ChipsLCD)) { 6316 /* in CRTonly mode this is simple: only set overflow for CR00-CR06 */ 6317 ChipsNew->XR[0x17] = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) 6318 | ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) 6319 | ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) 6320 | ((((mode->CrtcHSyncEnd >> 3)) & 0x20) >> 2) 6321 | ((((mode->CrtcHBlankStart >> 3) - 1) & 0x100) >> 4) 6322 | ((((mode->CrtcHBlankEnd >> 3) - 1) & 0x40) >> 1); 6323 6324 ChipsNew->XR[0x16] = (((mode->CrtcVTotal -2) & 0x400) >> 10 ) 6325 | (((mode->CrtcVDisplay -1) & 0x400) >> 9 ) 6326 | ((mode->CrtcVSyncStart & 0x400) >> 8 ) 6327 | (((mode->CrtcVBlankStart) & 0x400) >> 6 ); 6328 } else { 6329 /* horizontal timing registers */ 6330 /* in LCD/dual mode use saved bios values to derive timing values if 6331 * not told otherwise */ 6332 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { 6333 lcdHTotal = cPtr->PanelSize.HTotal; 6334 lcdHRetraceStart = cPtr->PanelSize.HRetraceStart; 6335 lcdHRetraceEnd = cPtr->PanelSize.HRetraceEnd; 6336 if (pScrn->bitsPerPixel == 16) { 6337 lcdHRetraceStart <<= 1; 6338 lcdHRetraceEnd <<= 1; 6339 lcdHTotal <<= 1; 6340 } else if (pScrn->bitsPerPixel == 24) { 6341 lcdHRetraceStart += (lcdHRetraceStart << 1); 6342 lcdHRetraceEnd += (lcdHRetraceEnd << 1); 6343 lcdHTotal += (lcdHTotal << 1); 6344 } 6345 lcdHRetraceStart -=8; /* HBlank = HRetrace - 1: for */ 6346 lcdHRetraceEnd -=8; /* compatibility with vgaHW.c */ 6347 } else { 6348 /* use modeline values if bios values don't work */ 6349 lcdHTotal = mode->CrtcHTotal; 6350 lcdHRetraceStart = mode->CrtcHSyncStart; 6351 lcdHRetraceEnd = mode->CrtcHSyncEnd; 6352 } 6353 /* The chip takes the size of the visible display area from the 6354 * CRTC values. We use bios screensize for LCD in LCD/dual mode 6355 * wether or not we use modeline for LCD. This way we can specify 6356 * always specify a smaller than default display size on LCD 6357 * by writing it to the CRTC registers. */ 6358 lcdHDisplay = cPtr->PanelSize.HDisplay; 6359 if (pScrn->bitsPerPixel == 16) { 6360 lcdHDisplay++; 6361 lcdHDisplay <<= 1; 6362 lcdHDisplay--; 6363 } else if (pScrn->bitsPerPixel == 24) { 6364 lcdHDisplay++; 6365 lcdHDisplay += (lcdHDisplay << 1); 6366 lcdHDisplay--; 6367 } 6368 lcdHTotal = (lcdHTotal >> 3) - 5; 6369 lcdHDisplay = (lcdHDisplay >> 3) - 1; 6370 lcdHRetraceStart = (lcdHRetraceStart >> 3); 6371 lcdHRetraceEnd = (lcdHRetraceEnd >> 3); 6372 /* This ugly hack is needed because CR01 and XR1C share the 8th bit!*/ 6373 CrtcHDisplay = ((mode->CrtcHDisplay >> 3) - 1); 6374 if ((lcdHDisplay & 0x100) != (CrtcHDisplay & 0x100)) { 6375 xf86ErrorF("This display configuration might cause problems !\n"); 6376 lcdHDisplay = 255; 6377 } 6378 6379 /* now init register values */ 6380 ChipsNew->XR[0x17] = (((lcdHTotal) & 0x100) >> 8) 6381 | ((lcdHDisplay & 0x100) >> 7) 6382 | ((lcdHRetraceStart & 0x100) >> 6) 6383 | (((lcdHRetraceEnd) & 0x20) >> 2); 6384 6385 ChipsNew->XR[0x19] = lcdHRetraceStart & 0xFF; 6386 ChipsNew->XR[0x1A] = lcdHRetraceEnd & 0x1F; 6387 6388 /* XR1B: Alternate horizontal total */ 6389 /* used in all flat panel mode with horiz. compression disabled, */ 6390 /* CRT CGA text and graphic modes and Hercules graphics mode */ 6391 /* similar to CR00, actual value - 5 */ 6392 ChipsNew->XR[0x1B] = lcdHTotal & 0xFF; 6393 6394 /*XR1C: Alternate horizontal blank start (CRT mode) */ 6395 /* /horizontal panel size (FP mode) */ 6396 /* FP horizontal panel size (FP mode), */ 6397 /* actual value - 1 (in characters unit) */ 6398 /* CRT horizontal blank start (CRT mode) */ 6399 /* similar to CR02, actual value - 1 */ 6400 ChipsNew->XR[0x1C] = lcdHDisplay & 0xFF; 6401 6402 if (xf86ReturnOptValBool(cPtr->Options, OPTION_USE_MODELINE, FALSE)) { 6403 /* for ext. packed pixel mode on 64520/64530 */ 6404 /* no need to rescale: used only in 65530 */ 6405 ChipsNew->XR[0x21] = lcdHRetraceStart & 0xFF; 6406 ChipsNew->XR[0x22] = lcdHRetraceEnd & 0x1F; 6407 ChipsNew->XR[0x23] = lcdHTotal & 0xFF; 6408 6409 /* vertical timing registers */ 6410 lcdVTotal = mode->CrtcVTotal - 2; 6411 lcdVDisplay = cPtr->PanelSize.VDisplay - 1; 6412 lcdVRetraceStart = mode->CrtcVSyncStart; 6413 lcdVRetraceEnd = mode->CrtcVSyncEnd; 6414 6415 ChipsNew->XR[0x64] = lcdVTotal & 0xFF; 6416 ChipsNew->XR[0x66] = lcdVRetraceStart & 0xFF; 6417 ChipsNew->XR[0x67] = lcdVRetraceEnd & 0x0F; 6418 ChipsNew->XR[0x68] = lcdVDisplay & 0xFF; 6419 ChipsNew->XR[0x65] = ((lcdVTotal & 0x100) >> 8) 6420 | ((lcdVDisplay & 0x100) >> 7) 6421 | ((lcdVRetraceStart & 0x100) >> 6) 6422 | ((lcdVRetraceStart & 0x400) >> 7) 6423 | ((lcdVTotal & 0x400) >> 6) 6424 | ((lcdVTotal & 0x200) >> 4) 6425 | ((lcdVDisplay & 0x200) >> 3) 6426 | ((lcdVRetraceStart & 0x200) >> 2); 6427 6428 /* 6429 * These are important: 0x2C specifies the numbers of lines 6430 * (hsync pulses) between vertical blank start and vertical 6431 * line total, 0x2D specifies the number of clock ticks? to 6432 * horiz. blank start ( caution ! 16bpp/24bpp modes: that's 6433 * why we need HSyncStart - can't use mode->CrtcHSyncStart) 6434 */ 6435 tmp = ((cPtr->PanelType & ChipsDD) && !(ChipsNew->XR[0x6F] & 0x02)) 6436 ? 1 : 0; /* double LP delay, FLM: 2 lines iff DD+no acc*/ 6437 /* Currently we support 2 FLM schemes: #1: FLM coincides with 6438 * VTotal ie. the delay is programmed to the difference bet- 6439 * ween lctVTotal and lcdVRetraceStart. #2: FLM coincides 6440 * lcdVRetraceStart - in this case FLM delay will be turned 6441 * off. To decide which scheme to use we compare the value of 6442 * XR2C set by the bios to the two schemes. The one that fits 6443 * better will be used. 6444 */ 6445 6446 if (ChipsNew->XR[0x2C] < abs((cPtr->PanelSize.VTotal - 6447 cPtr->PanelSize.VRetraceStart - tmp - 1) - 6448 ChipsNew->XR[0x2C])) 6449 ChipsNew->XR[0x2F] |= 0x80; /* turn FLM delay off */ 6450 ChipsNew->XR[0x2C] = lcdVTotal - lcdVRetraceStart - tmp; 6451 /*ChipsNew->XR[0x2D] = (HSyncStart >> (3 - tmp)) & 0xFF;*/ 6452 ChipsNew->XR[0x2D] = (HDisplay >> (3 - tmp)) & 0xFF; 6453 ChipsNew->XR[0x2F] = (ChipsNew->XR[0x2F] & 0xDF) 6454 | (((HSyncStart >> (3 - tmp)) & 0x100) >> 3); 6455 } 6456 6457 /* set stretching/centering */ 6458 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_SUSPEND_HACK, FALSE)) { 6459 ChipsNew->XR[0x51] |= 0x40; /* enable FP compensation */ 6460 ChipsNew->XR[0x55] |= 0x01; /* enable horiz. compensation */ 6461 ChipsNew->XR[0x57] |= 0x01; /* enable horiz. compensation */ 6462 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, 6463 FALSE)) { 6464 if (mode->CrtcHDisplay < 1489) /* HWBug */ 6465 ChipsNew->XR[0x55] |= 0x02; /* enable auto h-centering */ 6466 else { 6467 ChipsNew->XR[0x55] &= 0xFD; /* disable auto h-centering */ 6468 if (pScrn->bitsPerPixel == 24) /* ? */ 6469 ChipsNew->XR[0x56] = (lcdHDisplay - CrtcHDisplay) >> 1; 6470 } 6471 } else { 6472 ChipsNew->XR[0x55] &= 0xFD; /* disable h-centering */ 6473 ChipsNew->XR[0x56] = 0; 6474 } 6475 ChipsNew->XR[0x57] = 0x03; /* enable v-comp disable v-stretch */ 6476 if (!xf86ReturnOptValBool(cPtr->Options, OPTION_LCD_STRETCH, 6477 FALSE)) { 6478 ChipsNew->XR[0x55] |= 0x20; /* enable h-comp disable h-double*/ 6479 ChipsNew->XR[0x57] |= 0x60; /* Enable vertical stretching */ 6480 tmp = (mode->CrtcVDisplay / (cPtr->PanelSize.VDisplay - 6481 mode->CrtcVDisplay + 1)); 6482 if (tmp) { 6483 if (cPtr->PanelSize.HDisplay 6484 && cPtr->PanelSize.VDisplay 6485 && (cPtr->PanelSize.HDisplay != mode->CrtcHDisplay) 6486 && (cPtr->PanelSize.VDisplay != mode->CrtcVDisplay)) { 6487 /* Possible H/W bug? */ 6488 if(cPtr->Accel.UseHWCursor) 6489 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 6490 "Disabling HW Cursor on stretched LCD\n"); 6491 cPtr->Flags &= ~ChipsHWCursor; 6492 } 6493 } 6494 if (cPtr->Flags & ChipsHWCursor) 6495 tmp = (tmp == 0 ? 1 : tmp); /* Bug when doubling */ 6496 ChipsNew->XR[0x5A] = tmp > 0x0F ? 0 : (unsigned char)tmp; 6497 } else { 6498 ChipsNew->XR[0x55] &= 0xDF; /* disable h-comp, h-double */ 6499 ChipsNew->XR[0x57] &= 0x9F; /* disable vertical stretching */ 6500 } 6501 } 6502 } 6503 6504 /* set video mode */ 6505 ChipsNew->XR[0x2B] = chipsVideoMode(pScrn->depth, (cPtr->PanelType & ChipsLCD) ? 6506 min(HDisplay, cPtr->PanelSize.HDisplay) : HDisplay,cPtr->PanelSize.VDisplay); 6507#ifdef DEBUG 6508 ErrorF("VESA Mode: %Xh\n", ChipsNew->XR[0x2B]); 6509#endif 6510 6511 /* set some linear specific registers */ 6512 if (cPtr->Flags & ChipsLinearSupport) { 6513 /* enable linear addressing */ 6514 ChipsNew->XR[0x0B] &= 0xFD; /* dual page clear */ 6515 ChipsNew->XR[0x0B] |= 0x10; /* linear mode on */ 6516 if (cPtr->Chipset == CHIPS_CT65535) 6517 ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 17); 6518 else if (cPtr->Chipset > CHIPS_CT65535) 6519 ChipsNew->XR[0x08] = (unsigned char)(cPtr->FbAddress >> 20); 6520 else { 6521 /* Its probably set correctly by BIOS anyway. Leave it alone */ 6522 /* 65525 - 65530 require XR04[6] set for greater than 512k of */ 6523 /* ram. We only correct obvious bugs; VL probably uses MEMR/MEMW*/ 6524 if (cPtr->Bus == ChipsISA) 6525 ChipsNew->XR[0x04] &= ~0x40; /* A19 sceme */ 6526 if (pScrn->videoRam > 512) 6527 ChipsNew->XR[0x04] |= 0x40; /* MEMR/MEMW sceme */ 6528 } 6529 6530 /* general setup */ 6531 ChipsNew->XR[0x03] |= 0x08; /* High bandwidth on 65548 */ 6532 ChipsNew->XR[0x40] = 0x01; /*BitBLT Draw Mode for 8 and 24 bpp */ 6533 } 6534 6535 /* common general setup */ 6536 ChipsNew->XR[0x52] |= 0x01; /* Refresh count */ 6537 ChipsNew->XR[0x0F] &= 0xEF; /* not Hi-/True-Colour */ 6538 ChipsNew->XR[0x02] |= 0x01; /* 16bit CPU Memory Access */ 6539 ChipsNew->XR[0x02] &= 0xE3; /* Attr. Cont. default access */ 6540 /* use ext. regs. for hor. in dual */ 6541 ChipsNew->XR[0x06] &= 0xF3; /* bpp clear */ 6542 6543 /* PCI */ 6544 if (cPtr->Bus == ChipsPCI) 6545 ChipsNew->XR[0x03] |= 0x40; /*PCI burst */ 6546 6547 /* sync. polarities */ 6548 if ((mode->Flags & (V_PHSYNC | V_NHSYNC)) 6549 && (mode->Flags & (V_PVSYNC | V_NVSYNC))) { 6550 if (mode->Flags & (V_PHSYNC | V_NHSYNC)) { 6551 if (mode->Flags & V_PHSYNC) { 6552 ChipsNew->XR[0x55] &= 0xBF; /* CRT Hsync positive */ 6553 } else { 6554 ChipsNew->XR[0x55] |= 0x40; /* CRT Hsync negative */ 6555 } 6556 } 6557 if (mode->Flags & (V_PVSYNC | V_NVSYNC)) { 6558 if (mode->Flags & V_PVSYNC) { 6559 ChipsNew->XR[0x55] &= 0x7F; /* CRT Vsync positive */ 6560 } else { 6561 ChipsNew->XR[0x55] |= 0x80; /* CRT Vsync negative */ 6562 } 6563 } 6564 } 6565 6566 /* bpp depend */ 6567 /*XR06: Palette control */ 6568 /* bit 0: Pixel Data Pin Diag, 0 for flat panel pix. data (def) */ 6569 /* bit 1: Internal DAC disable */ 6570 /* bit 3-2: Colour depth, 0 for 4 or 8 bpp, 1 for 16(5-5-5) bpp, */ 6571 /* 2 for 24 bpp, 3 for 16(5-6-5)bpp */ 6572 /* bit 4: Enable PC Video Overlay on colour key */ 6573 /* bit 5: Bypass Internal VGA palette */ 6574 /* bit 7-6: Colour reduction select, 0 for NTSC (default), */ 6575 /* 1 for Equivalent weighting, 2 for green only, */ 6576 /* 3 for Colour w/o reduction */ 6577 /* XR50 Panel Format Register 1 */ 6578 /* bit 1-0: Frame Rate Control; 00, No FRC; */ 6579 /* 01, 16-frame FRC for colour STN and monochrome */ 6580 /* 10, 2-frame FRC for colour TFT or monochrome; */ 6581 /* 11, reserved */ 6582 /* bit 3-2: Dither Enable */ 6583 /* 00, disable dithering; 01, enable dithering */ 6584 /* for 256 mode */ 6585 /* 10, enable dithering for all modes; 11, reserved */ 6586 /* bit6-4: Clock Divide (CD) */ 6587 /* 000, Shift Clock Freq = Dot Clock Freq; */ 6588 /* 001, SClk = DClk/2; 010 SClk = DClk/4; */ 6589 /* 011, SClk = DClk/8; 100 SClk = DClk/16; */ 6590 /* bit 7: TFT data width */ 6591 /* 0, 16 bit(565RGB); 1, 24bit (888RGB) */ 6592 if (pScrn->bitsPerPixel == 16) { 6593 ChipsNew->XR[0x06] |= 0xC4; /*15 or 16 bpp colour */ 6594 ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ 6595 ChipsNew->XR[0x40] = 0x02; /*BitBLT Draw Mode for 16 bpp */ 6596 if (pScrn->weight.green != 5) 6597 ChipsNew->XR[0x06] |= 0x08; /*16bpp */ 6598 } else if (pScrn->bitsPerPixel == 24) { 6599 ChipsNew->XR[0x06] |= 0xC8; /*24 bpp colour */ 6600 ChipsNew->XR[0x0F] |= 0x10; /*Hi-/True-Colour */ 6601 if (xf86ReturnOptValBool(cPtr->Options, OPTION_18_BIT_BUS, FALSE)) { 6602 ChipsNew->XR[0x50] &= 0x7F; /*18 bit TFT data width */ 6603 } else { 6604 ChipsNew->XR[0x50] |= 0x80; /*24 bit TFT data width */ 6605 } 6606 } 6607 6608 /*CRT only: interlaced mode */ 6609 if (!(cPtr->PanelType & ChipsLCD)) { 6610 if (mode->Flags & V_INTERLACE){ 6611 ChipsNew->XR[0x28] |= 0x20; /* set interlace */ 6612 /* empirical value */ 6613 tmp = ((((mode->CrtcHDisplay >> 3) - 1) >> 1) 6614 - 6 * (pScrn->bitsPerPixel >= 8 ? bytesPerPixel : 1 )); 6615 if(cPtr->Chipset < CHIPS_CT65535) 6616 ChipsNew->XR[0x19] = tmp & 0xFF; 6617 else 6618 ChipsNew->XR[0x29] = tmp & 0xFF; 6619 ChipsNew->XR[0x0F] &= ~0x40; /* set SW-Flag */ 6620 } else { 6621 ChipsNew->XR[0x28] &= ~0x20; /* unset interlace */ 6622 ChipsNew->XR[0x0F] |= 0x40; /* set SW-Flag */ 6623 } 6624 } 6625 6626 /* STN specific */ 6627 if (IS_STN(cPtr->PanelType)) { 6628 ChipsNew->XR[0x50] &= ~0x03; /* FRC clear */ 6629 ChipsNew->XR[0x50] |= 0x01; /* 16 frame FRC */ 6630 ChipsNew->XR[0x50] &= ~0x0C; /* Dither clear */ 6631 ChipsNew->XR[0x50] |= 0x08; /* Dither all modes */ 6632 if (cPtr->Chipset == CHIPS_CT65548) { 6633 ChipsNew->XR[0x03] |= 0x20; /* CRT I/F priority */ 6634 ChipsNew->XR[0x04] |= 0x10; /* RAS precharge 65548 */ 6635 } 6636 } 6637 6638 /* This stuff was emprically derived several years ago. Not sure its 6639 * still needed, and I'd love to get rid of it as its ugly 6640 */ 6641 switch (cPtr->Chipset) { 6642 case CHIPS_CT65545: /*jet mini *//*DEC HighNote Ultra DSTN */ 6643 ChipsNew->XR[0x03] |= 0x10; /* do not hold off CPU for palette acc*/ 6644 break; 6645 case CHIPS_CT65546: /*CT 65546, only for Toshiba */ 6646 ChipsNew->XR[0x05] |= 0x80; /* EDO RAM enable */ 6647 break; 6648 } 6649 6650 if (cPtr->PanelType & ChipsLCD) 6651 ChipsNew->XR[0x51] |= 0x04; 6652 else 6653 ChipsNew->XR[0x51] &= ~0x04; 6654 6655 /* Program the registers */ 6656 /*vgaHWProtect(pScrn, TRUE);*/ 6657 chipsRestore(pScrn, ChipsStd, ChipsNew, FALSE); 6658 /*vgaHWProtect(pScrn, FALSE);*/ 6659 6660 return (TRUE); 6661} 6662 6663static void 6664chipsRestore(ScrnInfoPtr pScrn, vgaRegPtr VgaReg, CHIPSRegPtr ChipsReg, 6665 Bool restoreFonts) 6666{ 6667 vgaHWPtr hwp = VGAHWPTR(pScrn); 6668 CHIPSPtr cPtr = CHIPSPTR(pScrn); 6669 unsigned char tmp = 0; 6670 6671 /*vgaHWProtect(pScrn, TRUE);*/ 6672 6673 /* set registers so that we can program the controller */ 6674 if (IS_HiQV(cPtr)) { 6675 cPtr->writeXR(cPtr, 0x0E, 0x00); 6676 if (cPtr->Flags & ChipsDualChannelSupport) { 6677 tmp = cPtr->readFR(cPtr, 0x01); /* Disable pipeline */ 6678 cPtr->writeFR(cPtr, 0x01, (tmp & 0xFC)); 6679 cPtr->writeFR(cPtr, 0x02, 0x00); /* CRT/FP off */ 6680 } 6681 } else { 6682 cPtr->writeXR(cPtr, 0x10, 0x00); 6683 cPtr->writeXR(cPtr, 0x11, 0x00); 6684 tmp = cPtr->readXR(cPtr, 0x0C) & ~0x50; /* WINgine stores MSB here */ 6685 cPtr->writeXR(cPtr, 0x0C, tmp); 6686 cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect all registers */ 6687 tmp = cPtr->readXR(cPtr, 0x14); 6688 cPtr->writeXR(cPtr, 0x14, tmp & ~0x20); /* enable vsync on ST01 */ 6689 } 6690 6691 chipsFixResume(pScrn); 6692 6693 /* 6694 * Wait for vsync if sequencer is running - stop sequencer. 6695 * Only do if sync reset is ignored. Dual pipeline capable 6696 * chips have pipeline forced off here, so we don't care. 6697 */ 6698 if ((cPtr->SyncResetIgn) && (!(cPtr->Flags & ChipsDualChannelSupport))) { 6699 while (((hwp->readST01(hwp)) & 0x08) == 0x08); /* VSync off */ 6700 while (((hwp->readST01(hwp)) & 0x08) == 0x00); /* VSync on */ 6701 hwp->writeSeq(hwp, 0x07, 0x00); /* reset hsync - just in case... */ 6702 } 6703 6704 /* set the clock */ 6705 chipsClockLoad(pScrn, &ChipsReg->Clock); 6706 /* chipsClockLoad() sets this so we don't want vgaHWRestore() change it */ 6707 VgaReg->MiscOutReg = inb(cPtr->PIOBase + 0x3CC); 6708 6709 /* set extended regs */ 6710 chipsRestoreExtendedRegs(pScrn, ChipsReg); 6711#if 0 6712 /* if people complain about lock ups or blank screens -- reenable */ 6713 /* set CRTC registers - do it before sequencer restarts */ 6714 for (i=0; i<25; i++) 6715 hwp->writeCrtc(hwp, i, VgaReg->CRTC[i]); 6716#endif 6717 /* set generic registers */ 6718 /* 6719 * Enabling writing to the colourmap causes 69030's to lock. 6720 * Anyone care to explain to me why ???? 6721 */ 6722 if (cPtr->Flags & ChipsDualChannelSupport) { 6723 /* Enable pipeline if needed */ 6724 cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); 6725 cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); 6726 vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | 6727 (restoreFonts ? VGA_SR_FONTS : 0)); 6728 } else { 6729 vgaHWRestore(pScrn, VgaReg, VGA_SR_MODE | VGA_SR_CMAP | 6730 (restoreFonts ? VGA_SR_FONTS : 0)); 6731 } 6732 6733 /* set stretching registers */ 6734 if (IS_HiQV(cPtr)) { 6735 chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], 6736 (unsigned char)ChipsReg->FR[0x48]); 6737#if 0 6738 /* if people report about stretching not working -- reenable */ 6739 /* why twice ? : 6740 * sometimes the console is not well restored even if these registers 6741 * are good, re-write the registers works around it 6742 */ 6743 chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->FR[0x40], 6744 (unsigned char)ChipsReg->FR[0x48]); 6745#endif 6746 } else if (!IS_Wingine(cPtr)) 6747 chipsRestoreStretching(pScrn, (unsigned char)ChipsReg->XR[0x55], 6748 (unsigned char)ChipsReg->XR[0x57]); 6749 6750 /* perform a synchronous reset */ 6751 if (!cPtr->SyncResetIgn) { 6752 if (!IS_HiQV(cPtr)) { 6753 /* enable syncronous reset on 655xx */ 6754 tmp = cPtr->readXR(cPtr, 0x0E); 6755 cPtr->writeXR(cPtr, 0x0E, tmp & 0x7F); 6756 } 6757 hwp->writeSeq(hwp, 0x00, 0x01); 6758 usleep(10000); 6759 hwp->writeSeq(hwp, 0x00, 0x03); 6760 if (!IS_HiQV(cPtr)) 6761 cPtr->writeXR(cPtr, 0x0E, tmp); 6762 } 6763 /* Flag valid start address, if using CRT extensions */ 6764 if (IS_HiQV(cPtr) && (ChipsReg->XR[0x09] & 0x1) == 0x1) { 6765 tmp = hwp->readCrtc(hwp, 0x40); 6766 hwp->writeCrtc(hwp, 0x40, tmp | 0x80); 6767 } 6768 6769 /* Fix resume again here, as Nozomi seems to need it */ 6770 chipsFixResume(pScrn); 6771 /*vgaHWProtect(pScrn, FALSE);*/ 6772 6773#if 0 6774 /* Enable pipeline if needed */ 6775 if (cPtr->Flags & ChipsDualChannelSupport) { 6776 cPtr->writeFR(cPtr, 0x01, ChipsReg->FR[0x01]); 6777 cPtr->writeFR(cPtr, 0x02, ChipsReg->FR[0x02]); 6778 } 6779#endif 6780} 6781 6782static void 6783chipsRestoreExtendedRegs(ScrnInfoPtr pScrn, CHIPSRegPtr Regs) 6784{ 6785 vgaHWPtr hwp = VGAHWPTR(pScrn); 6786 CHIPSPtr cPtr = CHIPSPTR(pScrn); 6787 int i; 6788 unsigned char tmp; 6789 6790 if (IS_HiQV(cPtr)) { 6791 /* set extended regs */ 6792 for (i = 0; i < 0x43; i++) { 6793 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6794 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6795 } 6796 6797 /* Set SAR04 multimedia register correctly */ 6798 if ((cPtr->Flags & ChipsOverlay8plus16) 6799 || (cPtr->Flags & ChipsVideoSupport)) { 6800#ifdef SAR04 6801 cPtr->writeXR(cPtr, 0x4E, 0x04); 6802 if (cPtr->readXR(cPtr, 0x4F) != Regs->XR[0x4F]) 6803 cPtr->writeXR(cPtr, 0x4F, Regs->XR[0x4F]); 6804#endif 6805 } 6806 6807 /* Don't touch reserved memory control registers */ 6808 for (i = 0x50; i < 0xBF; i++) { 6809 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6810 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6811 } 6812 /* Don't touch VCLK regs, but fix up MClk */ 6813 6814 /* set mem clock */ 6815 tmp = cPtr->readXR(cPtr, 0xCE); /* Select Fixed MClk before */ 6816 cPtr->writeXR(cPtr, 0xCE, tmp & 0x7F); 6817 if ((cPtr->readXR(cPtr, 0xCC)) != Regs->XR[0xCC]) 6818 cPtr->writeXR(cPtr, 0xCC, Regs->XR[0xCC]); 6819 if ((cPtr->readXR(cPtr, 0xCD)) != Regs->XR[0xCD]) 6820 cPtr->writeXR(cPtr, 0xCD, Regs->XR[0xCD]); 6821 if ((cPtr->readXR(cPtr, 0xCE)) != Regs->XR[0xCE]) 6822 cPtr->writeXR(cPtr, 0xCE, Regs->XR[0xCE]); 6823 6824 /* set flat panel regs. */ 6825 for (i = 0xD0; i < 0xFF; i++) { 6826 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6827 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6828 } 6829 6830 for (i = 0; i < 0x80; i++) { 6831 /* Don't touch alternate clock select reg. */ 6832 if ((i == 0x01) && (cPtr->Chipset == CHIPS_CT69030)) { 6833 /* restore the non clock bits */ 6834 tmp = cPtr->readFR(cPtr, 0x01); 6835 cPtr->writeFR(cPtr, 0x01, ((Regs->FR[0x01] & 0xF0) | 6836 (tmp & ~0xF0))); 6837 continue; 6838 } 6839 6840 if ((i == 0x02) && (cPtr->Chipset == CHIPS_CT69030)) 6841 /* keep pipeline disabled till we are ready */ 6842 continue; 6843 6844 if ((i == 0x03) && (cPtr->Chipset != CHIPS_CT69030)) { 6845 /* restore the non clock bits */ 6846 tmp = cPtr->readFR(cPtr, 0x03); 6847 cPtr->writeFR(cPtr, 0x03, ((Regs->FR[0x03] & 0xC3) | 6848 (tmp & ~0xC3))); 6849 continue; 6850 } 6851 6852 if ((i > 0x03) && (cPtr->Chipset != CHIPS_CT69030) && 6853 (cPtr->SecondCrtc == TRUE)) 6854 continue; 6855 6856 if ( (i == 0x40) || (i==0x48)) { 6857 /* !! set stretching but disable compensation */ 6858 cPtr->writeFR(cPtr, i, Regs->FR[i] & 0xFE); 6859 continue ; /* some registers must be set before FR40/FR48 */ 6860 } 6861 if ((cPtr->readFR(cPtr, i)) != Regs->FR[i]) { 6862 cPtr->writeFR(cPtr, i, Regs->FR[i]); 6863 } 6864 } 6865 6866 /* set the multimedia regs */ 6867 for (i = 0x02; i < 0x80; i++) { 6868 if ( (i == 0x43) || (i == 0x44)) 6869 continue; 6870 if ((cPtr->readMR(cPtr, i)) != Regs->MR[i]) 6871 cPtr->writeMR(cPtr, i, Regs->MR[i]); 6872 } 6873 6874 /* set extended crtc regs. */ 6875 for (i = 0x30; i < 0x80; i++) { 6876 if ((hwp->readCrtc(hwp, i)) != Regs->CR[i]) 6877 hwp->writeCrtc(hwp, i, Regs->CR[i]); 6878 } 6879 } else { 6880 /* set extended regs. */ 6881 for (i = 0; i < 0x30; i++) { 6882 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6883 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6884 } 6885 cPtr->writeXR(cPtr, 0x15, 0x00); /* unprotect just in case ... */ 6886 /* Don't touch MCLK/VCLK regs. */ 6887 for (i = 0x34; i < 0x54; i++) { 6888 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6889 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6890 } 6891 tmp = cPtr->readXR(cPtr, 0x54); /* restore the non clock bits */ 6892 cPtr->writeXR(cPtr, 0x54, ((Regs->XR[0x54] & 0xF3) | (tmp & ~0xF3))); 6893 cPtr->writeXR(cPtr, 0x55, Regs->XR[0x55] & 0xFE); /* h-comp off */ 6894 cPtr->writeXR(cPtr, 0x56, Regs->XR[0x56]); 6895 cPtr->writeXR(cPtr, 0x57, Regs->XR[0x57] & 0xFE); /* v-comp off */ 6896 for (i=0x58; i < 0x7D; i++) {/* don't touch XR7D and XR7F on WINGINE */ 6897 if ((cPtr->readXR(cPtr, i)) != Regs->XR[i]) 6898 cPtr->writeXR(cPtr, i, Regs->XR[i]); 6899 } 6900 } 6901#ifdef DEBUG 6902 /* debug - dump out all the extended registers... */ 6903 if (IS_HiQV(cPtr)) { 6904 for (i = 0; i < 0xFF; i++) { 6905 ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], 6906 cPtr->readXR(cPtr, i)); 6907 } 6908 for (i = 0; i < 0x80; i++) { 6909 ErrorF("FR%X - %X : %X\n", i, Regs->FR[i], 6910 cPtr->readFR(cPtr, i)); 6911 } 6912 } else { 6913 for (i = 0; i < 0x80; i++) { 6914 ErrorF("XR%X - %X : %X\n", i, Regs->XR[i], 6915 cPtr->readXR(cPtr, i)); 6916 } 6917 } 6918#endif 6919} 6920 6921static void 6922chipsRestoreStretching(ScrnInfoPtr pScrn, unsigned char ctHorizontalStretch, 6923 unsigned char ctVerticalStretch) 6924{ 6925 unsigned char tmp; 6926 CHIPSPtr cPtr = CHIPSPTR(pScrn); 6927 6928 /* write to regs. */ 6929 if (IS_HiQV(cPtr)) { 6930 tmp = cPtr->readFR(cPtr, 0x48); 6931 cPtr->writeFR(cPtr, 0x48, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); 6932 tmp = cPtr->readFR(cPtr, 0x40); 6933 cPtr->writeFR(cPtr, 0x40, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); 6934 } else { 6935 tmp = cPtr->readXR(cPtr, 0x55); 6936 cPtr->writeXR(cPtr, 0x55, (tmp & 0xFE) | (ctHorizontalStretch & 0x01)); 6937 tmp = cPtr->readXR(cPtr, 0x57); 6938 cPtr->writeXR(cPtr, 0x57, (tmp & 0xFE) | (ctVerticalStretch & 0x01)); 6939 } 6940 6941 usleep(20000); /* to be active */ 6942} 6943 6944static int 6945chipsVideoMode(int depth, int displayHSize, 6946 int displayVSize) 6947{ 6948 /* 4 bpp 8 bpp 16 bpp 18 bpp 24 bpp 32 bpp */ 6949 /* 640 0x20 0x30 0x40 - 0x50 - */ 6950 /* 800 0x22 0x32 0x42 - 0x52 - */ 6951 /*1024 0x24 0x34 0x44 - 0x54 - for 1024x768 */ 6952 /*1024 - 0x36 0x47 - 0x56 - for 1024x600 */ 6953 /*1152 0x27 0x37 0x47 - 0x57 - */ 6954 /*1280 0x28 0x38 0x49 - - - */ 6955 /*1600 0x2C 0x3C 0x4C 0x5D - - */ 6956 /*This value is only for BIOS.... */ 6957 6958 int videoMode = 0; 6959 6960 switch (depth) { 6961 case 1: 6962 case 4: 6963 videoMode = 0x20; 6964 break; 6965 case 8: 6966 videoMode = 0x30; 6967 break; 6968 case 15: 6969 videoMode = 0x40; 6970 break; 6971 case 16: 6972 videoMode = 0x41; 6973 break; 6974 default: 6975 videoMode = 0x50; 6976 break; 6977 } 6978 6979 switch (displayHSize) { 6980 case 800: 6981 videoMode |= 0x02; 6982 break; 6983 case 1024: 6984 videoMode |= 0x04; 6985 if(displayVSize < 768) 6986 videoMode |= 0x02; 6987 break; 6988 case 1152: 6989 videoMode |= 0x07; 6990 break; 6991 case 1280: 6992 videoMode |= 0x08; 6993 break; 6994 case 1600: 6995 videoMode |= 0x0C; /*0x0A??*/ 6996 break; 6997 } 6998 6999 return videoMode; 7000} 7001 7002 7003/* 7004 * Map the framebuffer and MMIO memory. 7005 */ 7006 7007static Bool 7008chipsMapMem(ScrnInfoPtr pScrn) 7009{ 7010 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7011 vgaHWPtr hwp = VGAHWPTR(pScrn); 7012 CHIPSEntPtr cPtrEnt; 7013 7014 if (cPtr->Flags & ChipsLinearSupport) { 7015 if (cPtr->UseMMIO) { 7016 if (IS_HiQV(cPtr)) { 7017#ifndef XSERVER_LIBPCIACCESS 7018 if (cPtr->pEnt->location.type == BUS_PCI) 7019 cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, 7020 VIDMEM_MMIO_32BIT,cPtr->PciTag, cPtr->IOAddress, 7021 0x20000L); 7022 else 7023 cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, 7024 VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L); 7025#else 7026 { 7027 if (cPtr->pEnt->location.type == BUS_PCI) { 7028 void** result = (void**)&cPtr->MMIOBase; 7029 int err = pci_device_map_range(cPtr->PciInfo, 7030 cPtr->IOAddress, 7031 0x20000L, 7032 PCI_DEV_MAP_FLAG_WRITABLE, 7033 result); 7034 if (err) { 7035 xf86Msg(X_ERROR, "PCI mmap failed\n"); 7036 return FALSE; 7037 } 7038 } else 7039 cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, 7040 VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x20000L); 7041 7042 } 7043#endif 7044 } else { 7045#ifndef XSERVER_LIBPCIACCESS 7046 if (cPtr->pEnt->location.type == BUS_PCI) 7047 cPtr->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, 7048 VIDMEM_MMIO_32BIT, cPtr->PciTag, cPtr->IOAddress, 7049 0x10000L); 7050 else 7051 cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, 7052 VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L); 7053#else 7054 { 7055 if (cPtr->pEnt->location.type == BUS_PCI) { 7056 void** result = (void**)&cPtr->MMIOBase; 7057 int err = pci_device_map_range(cPtr->PciInfo, 7058 cPtr->IOAddress, 7059 0x10000L, 7060 PCI_DEV_MAP_FLAG_WRITABLE, 7061 result); 7062 if (err) { 7063 xf86Msg(X_ERROR, "PCI mmap failed\n"); 7064 return FALSE; 7065 } 7066 } else 7067 cPtr->MMIOBase = xf86MapVidMem(pScrn->scrnIndex, 7068 VIDMEM_MMIO_32BIT, cPtr->IOAddress, 0x10000L); 7069 } 7070#endif 7071 } 7072 7073 if (cPtr->MMIOBase == NULL) 7074 return FALSE; 7075 } 7076 if (cPtr->FbMapSize) { 7077 unsigned long Addr = (unsigned long)cPtr->FbAddress; 7078 unsigned int Map = cPtr->FbMapSize; 7079 7080 if ((cPtr->Flags & ChipsDualChannelSupport) && 7081 (xf86IsEntityShared(pScrn->entityList[0]))) { 7082 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 7083 CHIPSEntityIndex)->ptr; 7084 if(cPtr->SecondCrtc == FALSE) { 7085 Addr = cPtrEnt->masterFbAddress; 7086 Map = cPtrEnt->masterFbMapSize; 7087 } else { 7088 Addr = cPtrEnt->slaveFbAddress; 7089 Map = cPtrEnt->slaveFbMapSize; 7090 } 7091 } 7092 7093#ifndef XSERVER_LIBPCIACCESS 7094 if (cPtr->pEnt->location.type == BUS_PCI) 7095 cPtr->FbBase = xf86MapPciMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, 7096 cPtr->PciTag, Addr, Map); 7097 7098 else 7099 cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, 7100 Addr, Map); 7101#else 7102 if (cPtr->pEnt->location.type == BUS_PCI) { 7103 void** result = (void**)&cPtr->FbBase; 7104 int err = pci_device_map_range(cPtr->PciInfo, 7105 Addr, 7106 Map, 7107 PCI_DEV_MAP_FLAG_WRITABLE | 7108 PCI_DEV_MAP_FLAG_WRITE_COMBINE, 7109 result); 7110 if (err) { 7111 xf86Msg(X_ERROR, "PCI mmap fb failed\n"); 7112 return FALSE; 7113 } 7114 } else 7115 cPtr->FbBase = xf86MapVidMem(pScrn->scrnIndex,VIDMEM_FRAMEBUFFER, 7116 Addr, Map); 7117 7118#endif 7119 7120 if (cPtr->FbBase == NULL) 7121 return FALSE; 7122 } 7123 if (cPtr->Flags & ChipsFullMMIOSupport) { 7124#ifndef XSERVER_LIBPCIACCESS 7125 cPtr->MMIOBaseVGA = xf86MapPciMem(pScrn->scrnIndex, 7126 VIDMEM_MMIO,cPtr->PciTag, 7127 cPtr->IOAddress, 0x2000L); 7128#else 7129 cPtr->MMIOBaseVGA = cPtr->MMIOBase; 7130#endif 7131 /* 69030 MMIO Fix. 7132 * 7133 * The hardware lets us map the PipeB data registers 7134 * into the MMIO address space normally occupied by PipeA, 7135 * but it doesn't allow remapping of the index registers. 7136 * So we're forced to map a separate MMIO space for each 7137 * pipe and to toggle between them as necessary. -GHB 7138 */ 7139 if (cPtr->Flags & ChipsDualChannelSupport) 7140#ifndef XSERVER_LIBPCIACCESS 7141 cPtr->MMIOBasePipeB = xf86MapPciMem(pScrn->scrnIndex, 7142 VIDMEM_MMIO,cPtr->PciTag, 7143 cPtr->IOAddress + 0x800000, 0x2000L); 7144#else 7145 { 7146 void** result = (void**)&cPtr->MMIOBasePipeB; 7147 int err = pci_device_map_range(cPtr->PciInfo, 7148 cPtr->IOAddress + 0x800000, 7149 0x2000L, 7150 PCI_DEV_MAP_FLAG_WRITABLE, 7151 result); 7152 if (err) 7153 return FALSE; 7154 } 7155#endif 7156 7157 cPtr->MMIOBasePipeA = cPtr->MMIOBaseVGA; 7158 } 7159 } else { 7160 /* In paged mode Base is the VGA window at 0xA0000 */ 7161 cPtr->FbBase = hwp->Base; 7162 } 7163 7164 return TRUE; 7165} 7166 7167 7168/* 7169 * Unmap the framebuffer and MMIO memory. 7170 */ 7171 7172static Bool 7173chipsUnmapMem(ScrnInfoPtr pScrn) 7174{ 7175 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7176 7177 if (cPtr->Flags & ChipsLinearSupport) { 7178 if (IS_HiQV(cPtr)) { 7179#ifndef XSERVER_LIBPCIACCESS 7180 if (cPtr->MMIOBase) 7181 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, 7182 0x20000); 7183 if (cPtr->MMIOBasePipeB) 7184 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBasePipeB, 7185 0x20000); 7186#else 7187 if (cPtr->MMIOBase) 7188 pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x20000); 7189 7190 if (cPtr->MMIOBasePipeB) 7191 pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBasePipeB, 0x2000); 7192 7193#endif 7194 cPtr->MMIOBasePipeB = NULL; 7195 } else { 7196#ifndef XSERVER_LIBPCIACCESS 7197 if (cPtr->MMIOBase) 7198 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->MMIOBase, 7199 0x10000); 7200#else 7201 if (cPtr->MMIOBase) 7202 pci_device_unmap_range(cPtr->PciInfo, cPtr->MMIOBase, 0x10000); 7203#endif 7204 } 7205 cPtr->MMIOBase = NULL; 7206#ifndef XSERVER_LIBPCIACCESS 7207 xf86UnMapVidMem(pScrn->scrnIndex, (pointer)cPtr->FbBase, 7208 cPtr->FbMapSize); 7209#else 7210 pci_device_unmap_range(cPtr->PciInfo, cPtr->FbBase, cPtr->FbMapSize); 7211#endif 7212 } 7213 cPtr->FbBase = NULL; 7214 7215 return TRUE; 7216} 7217 7218static void 7219chipsProtect(ScrnInfoPtr pScrn, Bool on) 7220{ 7221 vgaHWProtect(pScrn, on); 7222} 7223 7224static void 7225chipsBlankScreen(ScrnInfoPtr pScrn, Bool unblank) 7226{ 7227 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7228 vgaHWPtr hwp = VGAHWPTR(pScrn); 7229 unsigned char scrn; 7230 CHIPSEntPtr cPtrEnt; 7231 7232 if (cPtr->UseDualChannel) { 7233 cPtrEnt = xf86GetEntityPrivate(pScrn->entityList[0], 7234 CHIPSEntityIndex)->ptr; 7235 DUALREOPEN; 7236 } 7237 7238 /* fix things that could be messed up by suspend/resume */ 7239 if (!IS_HiQV(cPtr)) 7240 cPtr->writeXR(cPtr, 0x15, 0x00); 7241 7242 scrn = hwp->readSeq(hwp, 0x01); 7243 7244 if (unblank) { 7245 scrn &= 0xDF; /* enable screen */ 7246 } else { 7247 scrn |= 0x20; /* blank screen */ 7248 } 7249 7250 /* synchronous reset - stop counters */ 7251 if (!cPtr->SyncResetIgn) { 7252 hwp->writeSeq(hwp, 0x00, 0x01); 7253 } 7254 7255 hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ 7256 7257 /* end reset - start counters */ 7258 if (!cPtr->SyncResetIgn) { 7259 hwp->writeSeq(hwp, 0x00, 0x03); 7260 } 7261 7262 if ((cPtr->UseDualChannel) && 7263 (! xf86IsEntityShared(pScrn->entityList[0]))) { 7264 unsigned int IOSS, MSS; 7265 IOSS = cPtr->readIOSS(cPtr); 7266 MSS = cPtr->readMSS(cPtr); 7267 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 7268 IOSS_PIPE_B)); 7269 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | MSS_PIPE_B)); 7270 7271 /* fix things that could be messed up by suspend/resume */ 7272 if (!IS_HiQV(cPtr)) 7273 cPtr->writeXR(cPtr, 0x15, 0x00); 7274 7275 scrn = hwp->readSeq(hwp, 0x01); 7276 7277 if (unblank) { 7278 scrn &= 0xDF; /* enable screen */ 7279 } else { 7280 scrn |= 0x20; /* blank screen */ 7281 } 7282 7283 /* synchronous reset - stop counters */ 7284 if (!cPtr->SyncResetIgn) { 7285 hwp->writeSeq(hwp, 0x00, 0x01); 7286 } 7287 7288 hwp->writeSeq(hwp, 0x01, scrn); /* change mode */ 7289 7290 /* end reset - start counters */ 7291 if (!cPtr->SyncResetIgn) { 7292 hwp->writeSeq(hwp, 0x00, 0x03); 7293 } 7294 7295 cPtr->writeIOSS(cPtr, IOSS); 7296 cPtr->writeMSS(cPtr, hwp, MSS); 7297 } 7298 7299} 7300 7301static void 7302chipsLock(ScrnInfoPtr pScrn) 7303{ 7304 vgaHWPtr hwp = VGAHWPTR(pScrn); 7305 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7306 unsigned char tmp; 7307 7308 vgaHWLock(hwp); 7309 7310 if (!IS_HiQV(cPtr)) { 7311 /* group protection attribute controller access */ 7312 cPtr->writeXR(cPtr, 0x15, cPtr->SuspendHack.xr15); 7313 tmp = cPtr->readXR(cPtr, 0x02); 7314 cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18) | cPtr->SuspendHack.xr02); 7315 tmp = cPtr->readXR(cPtr, 0x14); 7316 cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20) | cPtr->SuspendHack.xr14); 7317 7318 /* reset 32 bit register access */ 7319 if (cPtr->Chipset > CHIPS_CT65540) { 7320 tmp = cPtr->readXR(cPtr, 0x03); 7321 cPtr->writeXR(cPtr, 0x03, (tmp & ~0x0A) | cPtr->SuspendHack.xr03); 7322 } 7323 } 7324} 7325 7326static void 7327chipsUnlock(ScrnInfoPtr pScrn) 7328{ 7329 vgaHWPtr hwp = VGAHWPTR(pScrn); 7330 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7331 unsigned char tmp; 7332 7333 if (!IS_HiQV(cPtr)) { 7334 /* group protection attribute controller access */ 7335 cPtr->writeXR(cPtr, 0x15, 0x00); 7336 tmp = cPtr->readXR(cPtr, 0x02); 7337 cPtr->writeXR(cPtr, 0x02, (tmp & ~0x18)); 7338 tmp = cPtr->readXR(cPtr, 0x14); 7339 cPtr->writeXR(cPtr, 0x14, (tmp & ~0x20)); 7340 /* enable 32 bit register access */ 7341 if (cPtr->Chipset > CHIPS_CT65540) { 7342 cPtr->writeXR(cPtr, 0x03, cPtr->SuspendHack.xr03 | 0x0A); 7343 } 7344 } 7345 vgaHWUnlock(hwp); 7346} 7347 7348static void 7349chipsHWCursorOn(CHIPSPtr cPtr, ScrnInfoPtr pScrn) 7350{ 7351 /* enable HW cursor */ 7352 if (cPtr->HWCursorShown) { 7353 if (IS_HiQV(cPtr)) { 7354 cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); 7355 if (cPtr->UseDualChannel && 7356 (! xf86IsEntityShared(pScrn->entityList[0]))) { 7357 unsigned int IOSS, MSS; 7358 IOSS = cPtr->readIOSS(cPtr); 7359 MSS = cPtr->readMSS(cPtr); 7360 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 7361 IOSS_PIPE_B)); 7362 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & 7363 MSS_MASK) | MSS_PIPE_B)); 7364 cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xFF); 7365 cPtr->writeIOSS(cPtr, IOSS); 7366 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); 7367 } 7368 } else { 7369 HW_DEBUG(0x8); 7370 if (cPtr->UseMMIO) { 7371 MMIOmeml(DR(0x8)) = cPtr->HWCursorContents; 7372 } else { 7373 outl(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents); 7374 } 7375 } 7376 } 7377} 7378 7379static void 7380chipsHWCursorOff(CHIPSPtr cPtr, ScrnInfoPtr pScrn) 7381{ 7382 /* disable HW cursor */ 7383 if (cPtr->HWCursorShown) { 7384 if (IS_HiQV(cPtr)) { 7385 cPtr->HWCursorContents = cPtr->readXR(cPtr, 0xA0); 7386 cPtr->writeXR(cPtr, 0xA0, cPtr->HWCursorContents & 0xF8); 7387 } else { 7388 HW_DEBUG(0x8); 7389 if (cPtr->UseMMIO) { 7390 cPtr->HWCursorContents = MMIOmeml(DR(0x8)); 7391 /* Below used to be MMIOmemw() change back if problem!!! */ 7392 /* Also see ct_cursor.c */ 7393 MMIOmeml(DR(0x8)) = cPtr->HWCursorContents & 0xFFFE; 7394 } else { 7395 cPtr->HWCursorContents = inl(cPtr->PIOBase + DR(0x8)); 7396 outw(cPtr->PIOBase + DR(0x8), cPtr->HWCursorContents & 0xFFFE); 7397 } 7398 } 7399 } 7400} 7401 7402void 7403chipsFixResume(ScrnInfoPtr pScrn) 7404{ 7405 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7406 vgaHWPtr hwp = VGAHWPTR(pScrn); 7407 unsigned char tmp; 7408 7409 /* fix things that could be messed up by suspend/resume */ 7410 if (!IS_HiQV(cPtr)) 7411 cPtr->writeXR(cPtr, 0x15, 0x00); 7412 tmp = hwp->readMiscOut(hwp); 7413 hwp->writeMiscOut(hwp, (tmp & 0xFE) | cPtr->SuspendHack.vgaIOBaseFlag); 7414 tmp = hwp->readCrtc(hwp, 0x11); 7415 hwp->writeCrtc(hwp, 0x11, (tmp & 0x7F)); 7416} 7417 7418static char 7419chipsTestDACComp(ScrnInfoPtr pScrn, unsigned char a, unsigned char b, 7420 unsigned char c) 7421{ 7422 vgaHWPtr hwp = VGAHWPTR(pScrn); 7423 unsigned char type; 7424 7425 hwp->writeDacWriteAddr(hwp, 0x00); 7426 while ((hwp->readST01(hwp)) & 0x08){}; /* wait for vsync to end */ 7427 while (!(hwp->readST01(hwp)) & 0x08){}; /* wait for new vsync */ 7428 hwp->writeDacData(hwp, a); /* set pattern */ 7429 hwp->writeDacData(hwp, b); 7430 hwp->writeDacData(hwp, c); 7431 while (!(hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ 7432 while ((hwp->readST01(hwp)) & 0x01){}; /* wait for hsync to end */ 7433 type = hwp->readST00(hwp); /* read comparator */ 7434 return (type & 0x10); 7435} 7436 7437static int 7438chipsProbeMonitor(ScrnInfoPtr pScrn) 7439{ 7440 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7441 vgaHWPtr hwp = VGAHWPTR(pScrn); 7442 unsigned char dacmask; 7443 unsigned char dacdata[3]; 7444 unsigned char xr1, xr2; 7445 int type = 2; /* no monitor */ 7446 unsigned char IOSS=0, MSS=0, tmpfr02=0, tmpfr01a=0, tmpfr01b=0; 7447 7448 /* Dual channel display, enable both pipelines */ 7449 if (cPtr->Flags & ChipsDualChannelSupport) { 7450 IOSS = cPtr->readIOSS(cPtr); 7451 MSS = cPtr->readMSS(cPtr); 7452 tmpfr02 = cPtr->readFR(cPtr,0x02); 7453 cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF)); /* CRT/FP off */ 7454 usleep(1000); 7455 cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); 7456 cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); 7457 tmpfr01a = cPtr->readFR(cPtr,0x01); 7458 if ((tmpfr01a & 0x3) != 0x01) 7459 cPtr->writeFR(cPtr, 0x01, ((tmpfr01a & 0xFC) | 0x1)); 7460 cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); 7461 cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); 7462 tmpfr01b = cPtr->readFR(cPtr,0x01); 7463 if ((tmpfr01b & 0x3) != 0x01) 7464 cPtr->writeFR(cPtr, 0x01, ((tmpfr01b & 0xFC) | 0x1)); 7465 cPtr->writeIOSS(cPtr, IOSS); 7466 cPtr->writeMSS(cPtr, hwp, MSS); 7467 cPtr->writeFR(cPtr, 0x02, (tmpfr02 & 0xCF) | 0x10); /* CRT on/FP off*/ 7468 } 7469 7470 dacmask = hwp->readDacMask(hwp); /* save registers */ 7471 hwp->writeDacMask(hwp, 0x00); 7472 hwp->writeDacReadAddr(hwp, 0x00); 7473 7474 dacdata[0]=hwp->readDacData(hwp); 7475 dacdata[1]=hwp->readDacData(hwp); 7476 dacdata[2]=hwp->readDacData(hwp); 7477 7478 if (!IS_HiQV(cPtr)) { 7479 xr1 = cPtr->readXR(cPtr, 0x06); 7480 xr2 = cPtr->readXR(cPtr, 0x1F); 7481 cPtr->writeXR(cPtr, 0x06, xr1 & 0xF1); /* turn on dac */ 7482 cPtr->writeXR(cPtr, 0x1F, xr2 & 0x7F); /* enable comp */ 7483 } else { 7484 xr1 = cPtr->readXR(cPtr, 0x81); 7485 xr2 = cPtr->readXR(cPtr, 0xD0); 7486 cPtr->writeXR(cPtr, 0x81,(xr1 & 0xF0)); 7487 cPtr->writeXR(cPtr, 0xD0,(xr2 | 0x03)); 7488 } 7489 if (chipsTestDACComp(pScrn, 0x12,0x12,0x12)) { /* test patterns */ 7490 if (chipsTestDACComp(pScrn,0x14,0x14,0x14)) /* taken from */ 7491 if (!chipsTestDACComp(pScrn,0x2D,0x14,0x14)) /* BIOS */ 7492 if (!chipsTestDACComp(pScrn,0x14,0x2D,0x14)) 7493 if (!chipsTestDACComp(pScrn,0x14,0x14,0x2D)) 7494 if (!chipsTestDACComp(pScrn,0x2D,0x2D,0x2D)) 7495 type = 0; /* color monitor */ 7496 } else { 7497 if (chipsTestDACComp(pScrn,0x04,0x12,0x04)) 7498 if (!chipsTestDACComp(pScrn,0x1E,0x12,0x04)) 7499 if (!chipsTestDACComp(pScrn,0x04,0x2D,0x04)) 7500 if (!chipsTestDACComp(pScrn,0x1E,0x16,0x15)) 7501 if (chipsTestDACComp(pScrn,0x00,0x00,0x00)) 7502 type = 1; /* monochrome */ 7503 } 7504 7505 hwp->writeDacWriteAddr(hwp, 0x00); /* restore registers */ 7506 hwp->writeDacData(hwp, dacdata[0]); 7507 hwp->writeDacData(hwp, dacdata[1]); 7508 hwp->writeDacData(hwp, dacdata[2]); 7509 hwp->writeDacMask(hwp, dacmask); 7510 if (!IS_HiQV(cPtr)) { 7511 cPtr->writeXR(cPtr,0x06,xr1); 7512 cPtr->writeXR(cPtr,0x1F,xr2); 7513 } else { 7514 cPtr->writeXR(cPtr,0x81,xr1); 7515 cPtr->writeXR(cPtr,0xD0,xr2); 7516 } 7517 7518 if (cPtr->Flags & ChipsDualChannelSupport) { 7519 cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_A)); 7520 cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_A)); 7521 cPtr->writeFR(cPtr, 0x01, tmpfr01a); 7522 cPtr->writeIOSS(cPtr, ((IOSS & IOSS_MASK) | IOSS_PIPE_B)); 7523 cPtr->writeMSS(cPtr, hwp, ((MSS & MSS_MASK) | MSS_PIPE_B)); 7524 cPtr->writeFR(cPtr, 0x01, tmpfr01b); 7525 usleep(1000); 7526 cPtr->writeIOSS(cPtr, IOSS); 7527 cPtr->writeMSS(cPtr, hwp, MSS); 7528 cPtr->writeFR(cPtr, 0x02, tmpfr02); 7529 } 7530 7531 return type; 7532} 7533 7534static int 7535chipsSetMonitor(ScrnInfoPtr pScrn) 7536{ 7537 int tmp= chipsProbeMonitor(pScrn); 7538 7539 switch (tmp) { 7540 case 0: 7541 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Color monitor detected\n"); 7542 break; 7543 case 1: 7544 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Monochrome monitor detected\n"); 7545 break; 7546 default: 7547 xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No monitor detected\n"); 7548 } 7549 return (tmp); 7550} 7551 7552static void 7553chipsSetPanelType(CHIPSPtr cPtr) 7554{ 7555 CARD8 tmp; 7556 7557 if (IS_HiQV(cPtr)) { 7558 if (cPtr->Chipset == CHIPS_CT69030) { 7559 tmp = cPtr->readFR(cPtr, 0x00); 7560 if (tmp & 0x20) { 7561 /* FR02: DISPLAY TYPE REGISTER */ 7562 /* FR02[4] = CRT, FR02[5] = FlatPanel */ 7563 tmp = cPtr->readFR(cPtr, 0x02); 7564 if (tmp & 0x10) 7565 cPtr->PanelType |= ChipsCRT; 7566 if (tmp & 0x20) 7567 cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; 7568 } else { 7569 cPtr->PanelType |= ChipsCRT; 7570 } 7571 } else { 7572 /* test LCD */ 7573 /* FR01: DISPLAY TYPE REGISTER */ 7574 /* FR01[1:0]: Display Type, 01 = CRT, 10 = FlatPanel */ 7575 /* LCD */ 7576 tmp = cPtr->readFR(cPtr, 0x01); 7577 if ((tmp & 0x03) == 0x02) { 7578 cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; 7579 } 7580 tmp = cPtr->readXR(cPtr,0xD0); 7581 if (tmp & 0x01) { 7582 cPtr->PanelType |= ChipsCRT; 7583 } 7584 } 7585 } else { 7586 tmp = cPtr->readXR(cPtr, 0x51); 7587 /* test LCD */ 7588 /* XR51: DISPLAY TYPE REGISTER */ 7589 /* XR51[2]: Display Type, 0 = CRT, 1 = FlatPanel */ 7590 if (tmp & 0x04) { 7591 cPtr->PanelType |= ChipsLCD | ChipsLCDProbed; 7592 } 7593 if ((cPtr->readXR(cPtr, 0x06)) & 0x02) { 7594 cPtr->PanelType |= ChipsCRT; 7595 } 7596 } 7597} 7598 7599static void 7600chipsBlockHandler ( 7601 int i, 7602 pointer blockData, 7603 pointer pTimeout, 7604 pointer pReadmask 7605){ 7606 ScreenPtr pScreen = screenInfo.screens[i]; 7607 ScrnInfoPtr pScrn = xf86Screens[i]; 7608 CHIPSPtr cPtr = CHIPSPTR(pScrn); 7609 7610 pScreen->BlockHandler = cPtr->BlockHandler; 7611 (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); 7612 pScreen->BlockHandler = chipsBlockHandler; 7613 7614 if(cPtr->VideoTimerCallback) { 7615 UpdateCurrentTime(); 7616 (*cPtr->VideoTimerCallback)(pScrn, currentTime.milliseconds); 7617 } 7618} 7619