tcx_driver.c revision 6adb3ac0
1/* 2 * TCX framebuffer driver. 3 * 4 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24#ifdef HAVE_CONFIG_H 25#include "config.h" 26#endif 27 28#include <fcntl.h> 29#include <sys/types.h> 30#include <sys/time.h> 31#include <string.h> 32#include <sys/ioctl.h> 33#include <dev/sun/fbio.h> 34#include <dev/wscons/wsconsio.h> 35 36#include "xf86.h" 37#include "xf86_OSproc.h" 38#include "mipointer.h" 39#include "micmap.h" 40 41#include "fb.h" 42#include "xf86cmap.h" 43#include "tcx.h" 44 45static const OptionInfoRec * TCXAvailableOptions(int chipid, int busid); 46static void TCXIdentify(int flags); 47static Bool TCXProbe(DriverPtr drv, int flags); 48static Bool TCXPreInit(ScrnInfoPtr pScrn, int flags); 49static Bool TCXScreenInit(SCREEN_INIT_ARGS_DECL); 50static Bool TCXEnterVT(VT_FUNC_ARGS_DECL); 51static void TCXLeaveVT(VT_FUNC_ARGS_DECL); 52static Bool TCXCloseScreen(CLOSE_SCREEN_ARGS_DECL); 53static Bool TCXSaveScreen(ScreenPtr pScreen, int mode); 54static void TCXInitCplane24(ScrnInfoPtr pScrn); 55 56/* Required if the driver supports mode switching */ 57static Bool TCXSwitchMode(SWITCH_MODE_ARGS_DECL); 58/* Required if the driver supports moving the viewport */ 59static void TCXAdjustFrame(ADJUST_FRAME_ARGS_DECL); 60 61/* Optional functions */ 62static void TCXFreeScreen(FREE_SCREEN_ARGS_DECL); 63static ModeStatus TCXValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 64 Bool verbose, int flags); 65 66void TCXSync(ScrnInfoPtr pScrn); 67 68#define TCX_VERSION 4000 69#define TCX_NAME "SUNTCX" 70#define TCX_DRIVER_NAME "suntcx" 71#define TCX_MAJOR_VERSION PACKAGE_VERSION_MAJOR 72#define TCX_MINOR_VERSION PACKAGE_VERSION_MINOR 73#define TCX_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 74 75/* 76 * This contains the functions needed by the server after loading the driver 77 * module. It must be supplied, and gets passed back by the SetupProc 78 * function in the dynamic case. In the static case, a reference to this 79 * is compiled in, and this requires that the name of this DriverRec be 80 * an upper-case version of the driver name. 81 */ 82 83_X_EXPORT DriverRec SUNTCX = { 84 TCX_VERSION, 85 TCX_DRIVER_NAME, 86 TCXIdentify, 87 TCXProbe, 88 TCXAvailableOptions, 89 NULL, 90 0 91}; 92 93typedef enum { 94 OPTION_SW_CURSOR, 95 OPTION_HW_CURSOR, 96 OPTION_NOACCEL 97} TCXOpts; 98 99static const OptionInfoRec TCXOptions[] = { 100 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 101 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, TRUE }, 102 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 103 { -1, NULL, OPTV_NONE, {0}, FALSE } 104}; 105 106static MODULESETUPPROTO(tcxSetup); 107 108static XF86ModuleVersionInfo suntcxVersRec = 109{ 110 "suntcx", 111 MODULEVENDORSTRING, 112 MODINFOSTRING1, 113 MODINFOSTRING2, 114 XORG_VERSION_CURRENT, 115 TCX_MAJOR_VERSION, TCX_MINOR_VERSION, TCX_PATCHLEVEL, 116 ABI_CLASS_VIDEODRV, 117 ABI_VIDEODRV_VERSION, 118 MOD_CLASS_VIDEODRV, 119 {0,0,0,0} 120}; 121 122_X_EXPORT XF86ModuleData suntcxModuleData = { &suntcxVersRec, tcxSetup, NULL }; 123 124pointer 125tcxSetup(pointer module, pointer opts, int *errmaj, int *errmin) 126{ 127 static Bool setupDone = FALSE; 128 129 if (!setupDone) { 130 setupDone = TRUE; 131 xf86AddDriver(&SUNTCX, module, 0); 132 133 /* 134 * Modules that this driver always requires can be loaded here 135 * by calling LoadSubModule(). 136 */ 137 138 /* 139 * The return value must be non-NULL on success even though there 140 * is no TearDownProc. 141 */ 142 return (pointer)TRUE; 143 } else { 144 if (errmaj) *errmaj = LDR_ONCEONLY; 145 return NULL; 146 } 147} 148 149static Bool 150TCXGetRec(ScrnInfoPtr pScrn) 151{ 152 /* 153 * Allocate an TcxRec, and hook it into pScrn->driverPrivate. 154 * pScrn->driverPrivate is initialised to NULL, so we can check if 155 * the allocation has already been done. 156 */ 157 if (pScrn->driverPrivate != NULL) 158 return TRUE; 159 160 pScrn->driverPrivate = xnfcalloc(sizeof(TcxRec), 1); 161 return TRUE; 162} 163 164static void 165TCXFreeRec(ScrnInfoPtr pScrn) 166{ 167 TcxPtr pTcx; 168 169 if (pScrn->driverPrivate == NULL) 170 return; 171 172 pTcx = GET_TCX_FROM_SCRN(pScrn); 173 174 free(pScrn->driverPrivate); 175 pScrn->driverPrivate = NULL; 176 177 return; 178} 179 180static const OptionInfoRec * 181TCXAvailableOptions(int chipid, int busid) 182{ 183 return TCXOptions; 184} 185 186/* Mandatory */ 187static void 188TCXIdentify(int flags) 189{ 190 xf86Msg(X_INFO, "%s: driver for TCX\n", TCX_NAME); 191} 192 193 194/* Mandatory */ 195static Bool 196TCXProbe(DriverPtr drv, int flags) 197{ 198 int i; 199 GDevPtr *devSections; 200 int *usedChips; 201 int numDevSections; 202 int numUsed; 203 Bool foundScreen = FALSE; 204 EntityInfoPtr pEnt; 205 206 /* 207 * The aim here is to find all cards that this driver can handle, 208 * and for the ones not already claimed by another driver, claim the 209 * slot, and allocate a ScrnInfoRec. 210 * 211 * This should be a minimal probe, and it should under no circumstances 212 * change the state of the hardware. Because a device is found, don't 213 * assume that it will be used. Don't do any initialisations other than 214 * the required ScrnInfoRec initialisations. Don't allocate any new 215 * data structures. 216 */ 217 218 /* 219 * Next we check, if there has been a chipset override in the config file. 220 * For this we must find out if there is an active device section which 221 * is relevant, i.e., which has no driver specified or has THIS driver 222 * specified. 223 */ 224 225 if ((numDevSections = xf86MatchDevice(TCX_DRIVER_NAME, 226 &devSections)) <= 0) { 227 /* 228 * There's no matching device section in the config file, so quit 229 * now. 230 */ 231 return FALSE; 232 } 233 234 /* 235 * We need to probe the hardware first. We then need to see how this 236 * fits in with what is given in the config file, and allow the config 237 * file info to override any contradictions. 238 */ 239 240 numUsed = xf86MatchSbusInstances(TCX_NAME, SBUS_DEVICE_TCX, 241 devSections, numDevSections, 242 drv, &usedChips); 243 244 free(devSections); 245 if (numUsed <= 0) 246 return FALSE; 247 248 if (flags & PROBE_DETECT) 249 foundScreen = TRUE; 250 else for (i = 0; i < numUsed; i++) { 251 pEnt = xf86GetEntityInfo(usedChips[i]); 252 253 /* 254 * Check that nothing else has claimed the slots. 255 */ 256 if(pEnt->active) { 257 ScrnInfoPtr pScrn; 258 259 /* Allocate a ScrnInfoRec and claim the slot */ 260 pScrn = xf86AllocateScreen(drv, 0); 261 262 /* Fill in what we can of the ScrnInfoRec */ 263 pScrn->driverVersion = TCX_VERSION; 264 pScrn->driverName = TCX_DRIVER_NAME; 265 pScrn->name = TCX_NAME; 266 pScrn->Probe = TCXProbe; 267 pScrn->PreInit = TCXPreInit; 268 pScrn->ScreenInit = TCXScreenInit; 269 pScrn->SwitchMode = TCXSwitchMode; 270 pScrn->AdjustFrame = TCXAdjustFrame; 271 pScrn->EnterVT = TCXEnterVT; 272 pScrn->LeaveVT = TCXLeaveVT; 273 pScrn->FreeScreen = TCXFreeScreen; 274 pScrn->ValidMode = TCXValidMode; 275 xf86AddEntityToScreen(pScrn, pEnt->index); 276 foundScreen = TRUE; 277 } 278 free(pEnt); 279 } 280 free(usedChips); 281 return foundScreen; 282} 283 284/* Mandatory */ 285static Bool 286TCXPreInit(ScrnInfoPtr pScrn, int flags) 287{ 288 TcxPtr pTcx; 289 sbusDevicePtr psdp = NULL; 290 MessageType from; 291 int i, prom; 292 int hwCursor, lowDepth; 293 294 if (flags & PROBE_DETECT) return FALSE; 295 296 /* 297 * Note: This function is only called once at server startup, and 298 * not at the start of each server generation. This means that 299 * only things that are persistent across server generations can 300 * be initialised here. xf86Screens[] is (pScrn is a pointer to one 301 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 302 * are too, and should be used for data that must persist across 303 * server generations. 304 * 305 * Per-generation data should be allocated with 306 * AllocateScreenPrivateIndex() from the ScreenInit() function. 307 */ 308 309 /* Allocate the TcxRec driverPrivate */ 310 if (!TCXGetRec(pScrn)) { 311 return FALSE; 312 } 313 pTcx = GET_TCX_FROM_SCRN(pScrn); 314 315 /* Set pScrn->monitor */ 316 pScrn->monitor = pScrn->confScreen->monitor; 317 318 /* This driver doesn't expect more than one entity per screen */ 319 if (pScrn->numEntities > 1) 320 return FALSE; 321 /* This is the general case */ 322 for (i = 0; i < pScrn->numEntities; i++) { 323 EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]); 324 325 /* TCX is purely AFX, but we handle it like SBUS */ 326 if (pEnt->location.type == BUS_SBUS) { 327 psdp = xf86GetSbusInfoForEntity(pEnt->index); 328 pTcx->psdp = psdp; 329 } else 330 return FALSE; 331 } 332 if (psdp == NULL) 333 return FALSE; 334 335 /********************** 336 check card capabilities 337 **********************/ 338 hwCursor = 0; 339 lowDepth = 1; 340 341 prom = sparcPromInit(); 342 hwCursor = sparcPromGetBool(&psdp->node, "hw-cursor"); 343 lowDepth = sparcPromGetBool(&psdp->node, "tcx-8-bit"); 344 if (pTcx->HasStipROP = sparcPromGetBool(&psdp->node, "stip-rop")) { 345 xf86Msg(X_PROBED, "stipple space supports ROPs\n"); 346 } 347 pTcx->Is8bit = (lowDepth != 0); 348 /* all S24 support a hardware cursor */ 349 if (!lowDepth) { 350 hwCursor = 1; 351 pTcx->vramsize = 0x100000; /* size of the 8bit fb */ 352 } else { 353 char *b; 354 int len = 4, v = 0; 355 356 /* see if we have more than 1MB vram */ 357 pTcx->vramsize = 0x100000; 358 if ((b = sparcPromGetProperty(&psdp->node, "vram", &len)) != NULL) { 359 memcpy(&v, b, 4); 360 if ((v > 0) && (v < 3)) 361 pTcx->vramsize = 0x100000 * v; 362 } 363 xf86Msg(X_PROBED, "found %d MB video memory\n", v); 364 365 } 366 if (prom) 367 sparcPromClose(); 368 369 xf86Msg(X_PROBED, "hardware cursor support %s\n", 370 hwCursor ? "found" : "not found"); 371 372 /********************* 373 deal with depth 374 *********************/ 375 376 if (!xf86SetDepthBpp(pScrn, lowDepth ? 8 : 0, 0, 0, 377 lowDepth ? NoDepth24Support : Support32bppFb)) { 378 return FALSE; 379 } else { 380 /* Check that the returned depth is one we support */ 381 switch (pScrn->depth) { 382 case 8: 383 /* OK */ 384 break; 385 case 32: 386 case 24: 387 /* unless lowDepth OK */ 388 if (lowDepth) { 389 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 390 "Given depth (32) not supported by hardware\n"); 391 return FALSE; 392 } 393 break; 394 default: 395 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 396 "Given depth (%d) is not supported by this driver\n", 397 pScrn->depth); 398 return FALSE; 399 } 400 } 401 402 /* Collect all of the relevant option flags (fill in pScrn->options) */ 403 xf86CollectOptions(pScrn, NULL); 404 /* Process the options */ 405 if (!(pTcx->Options = malloc(sizeof(TCXOptions)))) 406 return FALSE; 407 memcpy(pTcx->Options, TCXOptions, sizeof(TCXOptions)); 408 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTcx->Options); 409 410 /* 411 * This must happen after pScrn->display has been set because 412 * xf86SetWeight references it. 413 */ 414 if (pScrn->depth > 8) { 415 rgb weight = {0, 0, 0}; 416 rgb mask = {0xff, 0xff00, 0xff0000}; 417 418 if (!xf86SetWeight(pScrn, weight, mask)) { 419 return FALSE; 420 } 421 } 422 423 if (!xf86SetDefaultVisual(pScrn, -1)) 424 return FALSE; 425 else if (pScrn->depth > 8) { 426 /* We don't currently support DirectColor */ 427 if (pScrn->defaultVisual != TrueColor) { 428 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 429 " (%s) is not supported\n", 430 xf86GetVisualName(pScrn->defaultVisual)); 431 return FALSE; 432 } 433 } 434 435 /* 436 * The new cmap code requires this to be initialised. 437 */ 438 439 { 440 Gamma zeros = {0.0, 0.0, 0.0}; 441 442 if (!xf86SetGamma(pScrn, zeros)) { 443 return FALSE; 444 } 445 } 446 447 /* determine whether we use hardware or software cursor */ 448 449 from = X_PROBED; 450 pTcx->HWCursor = FALSE; 451 if (hwCursor) { 452 from = X_DEFAULT; 453 pTcx->HWCursor = TRUE; 454 if (xf86GetOptValBool(pTcx->Options, OPTION_HW_CURSOR, &pTcx->HWCursor)) 455 from = X_CONFIG; 456 if (xf86ReturnOptValBool(pTcx->Options, OPTION_SW_CURSOR, FALSE)) { 457 from = X_CONFIG; 458 pTcx->HWCursor = FALSE; 459 } 460 } 461 462 pTcx->NoAccel = FALSE; 463 if (xf86ReturnOptValBool(pTcx->Options, OPTION_NOACCEL, FALSE)) { 464 pTcx->NoAccel = TRUE; 465 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 466 } 467 468 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 469 pTcx->HWCursor ? "HW" : "SW"); 470 471 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 472 TCXFreeRec(pScrn); 473 return FALSE; 474 } 475 476 if (pTcx->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) { 477 TCXFreeRec(pScrn); 478 return FALSE; 479 } 480 481 /********************* 482 set up clock and mode stuff 483 *********************/ 484 485 pScrn->progClock = TRUE; 486 487 if(pScrn->display->virtualX || pScrn->display->virtualY) { 488 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 489 "TCX does not support a virtual desktop\n"); 490 pScrn->display->virtualX = 0; 491 pScrn->display->virtualY = 0; 492 } 493 494 xf86SbusUseBuiltinMode(pScrn, pTcx->psdp); 495 pScrn->currentMode = pScrn->modes; 496 pScrn->displayWidth = pScrn->virtualX; 497 498 /* Set display resolution */ 499 xf86SetDpi(pScrn, 0, 0); 500 501 return TRUE; 502} 503 504/* Mandatory */ 505 506/* This gets called at the start of each server generation */ 507 508static Bool 509TCXScreenInit(SCREEN_INIT_ARGS_DECL) 510{ 511 ScrnInfoPtr pScrn; 512 TcxPtr pTcx; 513 VisualPtr visual; 514 int ret; 515 516 /* 517 * First get the ScrnInfoRec 518 */ 519 pScrn = xf86ScreenToScrn(pScreen); 520 521 pTcx = GET_TCX_FROM_SCRN(pScrn); 522 523 /* Map the TCX memory */ 524 if (pScrn->depth == 8) { 525 pTcx->fb = 526 xf86MapSbusMem (pTcx->psdp, TCX_RAM8_VOFF, pTcx->vramsize); 527 pTcx->pitchshift = 0; 528 } else { 529 pTcx->fb = 530 xf86MapSbusMem (pTcx->psdp, TCX_RAM24_VOFF, 1024 * 1024 * 4); 531 pTcx->cplane = 532 xf86MapSbusMem (pTcx->psdp, TCX_CPLANE_VOFF, 1024 * 1024 * 4); 533 pTcx->pitchshift = 2; 534 if (! pTcx->cplane) 535 return FALSE; 536 } 537 if (pTcx->HWCursor == TRUE) { 538 pTcx->thc = xf86MapSbusMem (pTcx->psdp, TCX_THC_VOFF, 8192); 539 if (! pTcx->thc) 540 return FALSE; 541 } 542 543 if (pTcx->Is8bit) { 544 /* use STIP and BLIT on tcx */ 545 pTcx->rblit = xf86MapSbusMem(pTcx->psdp, TCX_BLIT_VOFF, 8 * pTcx->vramsize); 546 if (pTcx->rblit == NULL) { 547 xf86Msg(X_ERROR, "Couldn't map BLIT space\n"); 548 return FALSE; 549 } 550 pTcx->rstip = xf86MapSbusMem(pTcx->psdp, TCX_STIP_VOFF, 8 * pTcx->vramsize); 551 if (pTcx->rstip == NULL) { 552 xf86Msg(X_ERROR, "Couldn't map STIP space\n"); 553 return FALSE; 554 } 555 } else { 556 /* use RSTIP and RBLIT on S24 */ 557 pTcx->rblit = xf86MapSbusMem(pTcx->psdp, TCX_RBLIT_VOFF, 8 * 1024 * 1024); 558 if (pTcx->rblit == NULL) { 559 xf86Msg(X_ERROR, "Couldn't map RBLIT space\n"); 560 return FALSE; 561 } 562 pTcx->rstip = xf86MapSbusMem(pTcx->psdp, TCX_RSTIP_VOFF, 8 * 1024 * 1024); 563 if (pTcx->rstip == NULL) { 564 xf86Msg(X_ERROR, "Couldn't map RSTIP space\n"); 565 return FALSE; 566 } 567 } 568 569 if (! pTcx->fb) 570 return FALSE; 571 572 /* Darken the screen for aesthetic reasons and set the viewport */ 573 TCXSaveScreen(pScreen, SCREEN_SAVER_ON); 574 575 /* 576 * The next step is to setup the screen's visuals, and initialise the 577 * framebuffer code. In cases where the framebuffer's default 578 * choices for things like visual layouts and bits per RGB are OK, 579 * this may be as simple as calling the framebuffer's ScreenInit() 580 * function. If not, the visuals will need to be setup before calling 581 * a fb ScreenInit() function and fixed up after. 582 */ 583 584 /* 585 * Reset visual list. 586 */ 587 miClearVisualTypes(); 588 589 if (pScrn->depth == 8) 590 /* Set the bits per RGB for 8bpp mode */ 591 pScrn->rgbBits = 8; 592 593 /* Setup the visuals we support. */ 594 595 if (!miSetVisualTypes(pScrn->depth, 596 pScrn->depth != 8 ? TrueColorMask : 597 miGetDefaultVisualMask(pScrn->depth), 598 pScrn->rgbBits, pScrn->defaultVisual)) 599 return FALSE; 600 601 miSetPixmapDepths (); 602 603 /* 604 * Call the framebuffer layer's ScreenInit function, and fill in other 605 * pScreen fields. 606 */ 607 608 if (pScrn->bitsPerPixel != 8) 609 TCXInitCplane24(pScrn); 610 ret = fbScreenInit(pScreen, pTcx->fb, pScrn->virtualX, 611 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 612 pScrn->virtualX, pScrn->bitsPerPixel); 613 614 if (!ret) 615 return FALSE; 616 617 xf86SetBlackWhitePixels(pScreen); 618 619 if (pScrn->bitsPerPixel > 8) { 620 /* Fixup RGB ordering */ 621 visual = pScreen->visuals + pScreen->numVisuals; 622 while (--visual >= pScreen->visuals) { 623 if ((visual->class | DynamicClass) == DirectColor) { 624 visual->offsetRed = pScrn->offset.red; 625 visual->offsetGreen = pScrn->offset.green; 626 visual->offsetBlue = pScrn->offset.blue; 627 visual->redMask = pScrn->mask.red; 628 visual->greenMask = pScrn->mask.green; 629 visual->blueMask = pScrn->mask.blue; 630 } 631 } 632 } 633 634#ifdef RENDER 635 /* must be after RGB ordering fixed */ 636 fbPictureInit (pScreen, 0, 0); 637#endif 638 639 if (!pTcx->NoAccel) { 640 XF86ModReqInfo req; 641 int errmaj, errmin; 642 643 memset(&req, 0, sizeof(XF86ModReqInfo)); 644 req.majorversion = 2; 645 req.minorversion = 0; 646 if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req, 647 &errmaj, &errmin)) 648 { 649 LoaderErrorMsg(NULL, "exa", errmaj, errmin); 650 return FALSE; 651 } 652 if (!TcxInitAccel(pScreen)) 653 return FALSE; 654 } 655 656 xf86SetBackingStore(pScreen); 657 xf86SetSilkenMouse(pScreen); 658 659 /* Initialise cursor functions */ 660 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 661 662 /* Initialize HW cursor layer. 663 Must follow software cursor initialization*/ 664 if (pTcx->HWCursor) { 665 extern Bool TCXHWCursorInit(ScreenPtr pScreen); 666 667 if(!TCXHWCursorInit(pScreen)) { 668 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 669 "Hardware cursor initialization failed\n"); 670 return(FALSE); 671 } 672 xf86SbusHideOsHwCursor(pTcx->psdp); 673 } 674 675 /* Initialise default colourmap */ 676 if (!miCreateDefColormap(pScreen)) 677 return FALSE; 678 679 if(pScrn->depth == 8 && !xf86SbusHandleColormaps(pScreen, pTcx->psdp)) 680 return FALSE; 681 682 pTcx->CloseScreen = pScreen->CloseScreen; 683 pScreen->CloseScreen = TCXCloseScreen; 684 pScreen->SaveScreen = TCXSaveScreen; 685 686 /* Report any unused options (only for the first generation) */ 687 if (serverGeneration == 1) { 688 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 689 } 690 691 /* unblank the screen */ 692 TCXSaveScreen(pScreen, SCREEN_SAVER_OFF); 693 694 /* Done */ 695 return TRUE; 696} 697 698 699/* Usually mandatory */ 700static Bool 701TCXSwitchMode(SWITCH_MODE_ARGS_DECL) 702{ 703 return TRUE; 704} 705 706 707/* 708 * This function is used to initialize the Start Address - the first 709 * displayed location in the video memory. 710 */ 711/* Usually mandatory */ 712static void 713TCXAdjustFrame(ADJUST_FRAME_ARGS_DECL) 714{ 715 /* we don't support virtual desktops */ 716 return; 717} 718 719/* 720 * This is called when VT switching back to the X server. Its job is 721 * to reinitialise the video mode. 722 */ 723 724/* Mandatory */ 725static Bool 726TCXEnterVT(VT_FUNC_ARGS_DECL) 727{ 728 SCRN_INFO_PTR(arg); 729 TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn); 730 731 if (pTcx->HWCursor) { 732 xf86SbusHideOsHwCursor (pTcx->psdp); 733 pTcx->CursorFg = 0; 734 pTcx->CursorBg = 0; 735 } 736 if (pTcx->cplane) { 737 TCXInitCplane24 (pScrn); 738 } 739 return TRUE; 740} 741 742 743/* 744 * This is called when VT switching away from the X server. 745 */ 746 747/* Mandatory */ 748static void 749TCXLeaveVT(VT_FUNC_ARGS_DECL) 750{ 751 return; 752} 753 754 755/* 756 * This is called at the end of each server generation. It restores the 757 * original (text) mode. It should really also unmap the video memory too. 758 */ 759 760/* Mandatory */ 761static Bool 762TCXCloseScreen(CLOSE_SCREEN_ARGS_DECL) 763{ 764 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 765 TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn); 766 767 pScrn->vtSema = FALSE; 768 if (pScrn->depth == 8) 769 xf86UnmapSbusMem(pTcx->psdp, pTcx->fb, 770 (pTcx->psdp->width * pTcx->psdp->height)); 771 else { 772 xf86UnmapSbusMem(pTcx->psdp, pTcx->fb, 773 (pTcx->psdp->width * pTcx->psdp->height * 4)); 774 xf86UnmapSbusMem(pTcx->psdp, pTcx->cplane, 775 (pTcx->psdp->width * pTcx->psdp->height * 4)); 776 } 777 if (pTcx->thc) 778 xf86UnmapSbusMem(pTcx->psdp, pTcx->thc, 8192); 779 780 if (pTcx->HWCursor) 781 xf86SbusHideOsHwCursor (pTcx->psdp); 782 783 pScreen->CloseScreen = pTcx->CloseScreen; 784 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 785} 786 787 788/* Free up any per-generation data structures */ 789 790/* Optional */ 791static void 792TCXFreeScreen(FREE_SCREEN_ARGS_DECL) 793{ 794 SCRN_INFO_PTR(arg); 795 TCXFreeRec(pScrn); 796} 797 798 799/* Checks if a mode is suitable for the selected chipset. */ 800 801/* Optional */ 802static ModeStatus 803TCXValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 804{ 805 if (mode->Flags & V_INTERLACE) 806 return(MODE_BAD); 807 808 return(MODE_OK); 809} 810 811/* Do screen blanking */ 812 813/* Mandatory */ 814static Bool 815TCXSaveScreen(ScreenPtr pScreen, int mode) 816 /* this function should blank the screen when unblank is FALSE and 817 unblank it when unblank is TRUE -- it doesn't actually seem to be 818 used for much though */ 819{ 820 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 821 TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn); 822 int fd = pTcx->psdp->fd, state; 823 824 /* 825 * we're using ioctl() instead of just whacking the DAC because the 826 * underlying driver will also turn off the backlight which we couldn't do 827 * from here without adding lots more hardware dependencies 828 */ 829 switch(mode) 830 { 831 case SCREEN_SAVER_ON: 832 case SCREEN_SAVER_CYCLE: 833 state = 0; 834 if(ioctl(fd, FBIOSVIDEO, &state) == -1) 835 { 836 /* complain */ 837 } 838 break; 839 case SCREEN_SAVER_OFF: 840 case SCREEN_SAVER_FORCER: 841 state = 1; 842 if(ioctl(fd, FBIOSVIDEO, &state) == -1) 843 { 844 /* complain */ 845 } 846 break; 847 default: 848 return FALSE; 849 } 850 851 return TRUE; 852} 853 854/* 855 * This is the implementation of the Sync() function. 856 */ 857void 858TCXSync(ScrnInfoPtr pScrn) 859{ 860 return; 861} 862 863/* 864 * This initializes CPLANE for 24 bit mode. 865 */ 866static void 867TCXInitCplane24(ScrnInfoPtr pScrn) 868{ 869 TcxPtr pTcx = GET_TCX_FROM_SCRN(pScrn); 870 int size; 871 unsigned int *p, *q; 872 873 if (!pTcx->cplane) 874 return; 875 876 size = pScrn->virtualX * pScrn->virtualY; 877 memset (pTcx->fb, 0, size * 4); 878 p = pTcx->cplane; 879 for (q = pTcx->cplane + size; p != q; p++) 880 *p = (*p & 0xffffff) | TCX_CPLANE_MODE; 881} 882