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