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