1 2/* 3 * Leo (ZX) framebuffer driver. 4 * 5 * Copyright (C) 2000 Jakub Jelinek (jakub@redhat.com) 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * JAKUB JELINEK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include <string.h> 30 31#include "xf86.h" 32#include "xf86_OSproc.h" 33#include "mipointer.h" 34#include "micmap.h" 35 36#include "fb.h" 37#include "xf86cmap.h" 38#include "leo.h" 39 40static const OptionInfoRec * LeoAvailableOptions(int chipid, int busid); 41static void LeoIdentify(int flags); 42static Bool LeoProbe(DriverPtr drv, int flags); 43static Bool LeoPreInit(ScrnInfoPtr pScrn, int flags); 44static Bool LeoScreenInit(SCREEN_INIT_ARGS_DECL); 45static Bool LeoEnterVT(VT_FUNC_ARGS_DECL); 46static void LeoLeaveVT(VT_FUNC_ARGS_DECL); 47static Bool LeoCloseScreen(CLOSE_SCREEN_ARGS_DECL); 48static Bool LeoSaveScreen(ScreenPtr pScreen, int mode); 49 50/* Required if the driver supports mode switching */ 51static Bool LeoSwitchMode(SWITCH_MODE_ARGS_DECL); 52/* Required if the driver supports moving the viewport */ 53static void LeoAdjustFrame(ADJUST_FRAME_ARGS_DECL); 54 55/* Optional functions */ 56static void LeoFreeScreen(FREE_SCREEN_ARGS_DECL); 57static ModeStatus LeoValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, 58 Bool verbose, int flags); 59 60void LeoSync(ScrnInfoPtr pScrn); 61 62#define LEO_VERSION 4000 63#define LEO_NAME "SUNLEO" 64#define LEO_DRIVER_NAME "sunleo" 65#define LEO_MAJOR_VERSION PACKAGE_VERSION_MAJOR 66#define LEO_MINOR_VERSION PACKAGE_VERSION_MINOR 67#define LEO_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL 68 69/* 70 * This contains the functions needed by the server after loading the driver 71 * module. It must be supplied, and gets passed back by the SetupProc 72 * function in the dynamic case. In the static case, a reference to this 73 * is compiled in, and this requires that the name of this DriverRec be 74 * an upper-case version of the driver name. 75 */ 76 77_X_EXPORT DriverRec SUNLEO = { 78 LEO_VERSION, 79 LEO_DRIVER_NAME, 80 LeoIdentify, 81 LeoProbe, 82 LeoAvailableOptions, 83 NULL, 84 0 85}; 86 87typedef enum { 88 OPTION_SW_CURSOR, 89 OPTION_HW_CURSOR, 90 OPTION_NOACCEL 91} LeoOpts; 92 93static const OptionInfoRec LeoOptions[] = { 94 { OPTION_SW_CURSOR, "SWcursor", OPTV_BOOLEAN, {0}, FALSE }, 95 { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, 96 { OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, 97 { -1, NULL, OPTV_NONE, {0}, FALSE } 98}; 99 100#ifdef XFree86LOADER 101 102static MODULESETUPPROTO(leoSetup); 103 104static XF86ModuleVersionInfo sunleoVersRec = 105{ 106 "sunleo", 107 MODULEVENDORSTRING, 108 MODINFOSTRING1, 109 MODINFOSTRING2, 110 XORG_VERSION_CURRENT, 111 LEO_MAJOR_VERSION, LEO_MINOR_VERSION, LEO_PATCHLEVEL, 112 ABI_CLASS_VIDEODRV, 113 ABI_VIDEODRV_VERSION, 114 MOD_CLASS_VIDEODRV, 115 {0,0,0,0} 116}; 117 118_X_EXPORT XF86ModuleData sunleoModuleData = { &sunleoVersRec, leoSetup, NULL }; 119 120pointer 121leoSetup(pointer module, pointer opts, int *errmaj, int *errmin) 122{ 123 static Bool setupDone = FALSE; 124 125 if (!setupDone) { 126 setupDone = TRUE; 127 xf86AddDriver(&SUNLEO, module, 0); 128 129 /* 130 * Modules that this driver always requires can be loaded here 131 * by calling LoadSubModule(). 132 */ 133 134 /* 135 * The return value must be non-NULL on success even though there 136 * is no TearDownProc. 137 */ 138 return (pointer)TRUE; 139 } else { 140 if (errmaj) *errmaj = LDR_ONCEONLY; 141 return NULL; 142 } 143} 144 145#endif /* XFree86LOADER */ 146 147static Bool 148LeoGetRec(ScrnInfoPtr pScrn) 149{ 150 /* 151 * Allocate an LeoRec, and hook it into pScrn->driverPrivate. 152 * pScrn->driverPrivate is initialised to NULL, so we can check if 153 * the allocation has already been done. 154 */ 155 if (pScrn->driverPrivate != NULL) 156 return TRUE; 157 158 pScrn->driverPrivate = xnfcalloc(sizeof(LeoRec), 1); 159 return TRUE; 160} 161 162static void 163LeoFreeRec(ScrnInfoPtr pScrn) 164{ 165 LeoPtr pLeo; 166 167 if (pScrn->driverPrivate == NULL) 168 return; 169 170 pLeo = GET_LEO_FROM_SCRN(pScrn); 171 172 free(pScrn->driverPrivate); 173 pScrn->driverPrivate = NULL; 174 175 return; 176} 177 178static const OptionInfoRec * 179LeoAvailableOptions(int chipid, int busid) 180{ 181 return LeoOptions; 182} 183 184/* Mandatory */ 185static void 186LeoIdentify(int flags) 187{ 188 xf86Msg(X_INFO, "%s: driver for Leo (ZX)\n", LEO_NAME); 189} 190 191 192/* Mandatory */ 193static Bool 194LeoProbe(DriverPtr drv, int flags) 195{ 196 int i; 197 GDevPtr *devSections; 198 int *usedChips; 199 int numDevSections; 200 int numUsed; 201 Bool foundScreen = FALSE; 202 EntityInfoPtr pEnt; 203 204 /* 205 * The aim here is to find all cards that this driver can handle, 206 * and for the ones not already claimed by another driver, claim the 207 * slot, and allocate a ScrnInfoRec. 208 * 209 * This should be a minimal probe, and it should under no circumstances 210 * change the state of the hardware. Because a device is found, don't 211 * assume that it will be used. Don't do any initialisations other than 212 * the required ScrnInfoRec initialisations. Don't allocate any new 213 * data structures. 214 */ 215 216 /* 217 * Next we check, if there has been a chipset override in the config file. 218 * For this we must find out if there is an active device section which 219 * is relevant, i.e., which has no driver specified or has THIS driver 220 * specified. 221 */ 222 223 if ((numDevSections = xf86MatchDevice(LEO_DRIVER_NAME, 224 &devSections)) <= 0) { 225 /* 226 * There's no matching device section in the config file, so quit 227 * now. 228 */ 229 return FALSE; 230 } 231 232 /* 233 * We need to probe the hardware first. We then need to see how this 234 * fits in with what is given in the config file, and allow the config 235 * file info to override any contradictions. 236 */ 237 238 numUsed = xf86MatchSbusInstances(LEO_NAME, SBUS_DEVICE_LEO, 239 devSections, numDevSections, 240 drv, &usedChips); 241 242 free(devSections); 243 if (numUsed <= 0) 244 return FALSE; 245 246 if (flags & PROBE_DETECT) 247 foundScreen = TRUE; 248 else for (i = 0; i < numUsed; i++) { 249 pEnt = xf86GetEntityInfo(usedChips[i]); 250 251 /* 252 * Check that nothing else has claimed the slots. 253 */ 254 if(pEnt->active) { 255 ScrnInfoPtr pScrn; 256 257 /* Allocate a ScrnInfoRec and claim the slot */ 258 pScrn = xf86AllocateScreen(drv, 0); 259 260 /* Fill in what we can of the ScrnInfoRec */ 261 pScrn->driverVersion = LEO_VERSION; 262 pScrn->driverName = LEO_DRIVER_NAME; 263 pScrn->name = LEO_NAME; 264 pScrn->Probe = LeoProbe; 265 pScrn->PreInit = LeoPreInit; 266 pScrn->ScreenInit = LeoScreenInit; 267 pScrn->SwitchMode = LeoSwitchMode; 268 pScrn->AdjustFrame = LeoAdjustFrame; 269 pScrn->EnterVT = LeoEnterVT; 270 pScrn->LeaveVT = LeoLeaveVT; 271 pScrn->FreeScreen = LeoFreeScreen; 272 pScrn->ValidMode = LeoValidMode; 273 xf86AddEntityToScreen(pScrn, pEnt->index); 274 foundScreen = TRUE; 275 } 276 free(pEnt); 277 } 278 free(usedChips); 279 return foundScreen; 280} 281 282/* Mandatory */ 283static Bool 284LeoPreInit(ScrnInfoPtr pScrn, int flags) 285{ 286 LeoPtr pLeo; 287 sbusDevicePtr psdp; 288 MessageType from; 289 int i; 290 291 if (flags & PROBE_DETECT) return FALSE; 292 293 /* 294 * Note: This function is only called once at server startup, and 295 * not at the start of each server generation. This means that 296 * only things that are persistent across server generations can 297 * be initialised here. xf86Screens[] is (pScrn is a pointer to one 298 * of these). Privates allocated using xf86AllocateScrnInfoPrivateIndex() 299 * are too, and should be used for data that must persist across 300 * server generations. 301 * 302 * Per-generation data should be allocated with 303 * AllocateScreenPrivateIndex() from the ScreenInit() function. 304 */ 305 306 /* Allocate the LeoRec driverPrivate */ 307 if (!LeoGetRec(pScrn)) { 308 return FALSE; 309 } 310 pLeo = GET_LEO_FROM_SCRN(pScrn); 311 312 /* Set pScrn->monitor */ 313 pScrn->monitor = pScrn->confScreen->monitor; 314 315 /* This driver doesn't expect more than one entity per screen */ 316 if (pScrn->numEntities > 1) 317 return FALSE; 318 /* This is the general case */ 319 for (i = 0; i < pScrn->numEntities; i++) { 320 EntityInfoPtr pEnt = xf86GetEntityInfo(pScrn->entityList[i]); 321 322 /* LEO is purely SBUS */ 323 if (pEnt->location.type == BUS_SBUS) { 324 psdp = xf86GetSbusInfoForEntity(pEnt->index); 325 pLeo->psdp = psdp; 326 } else 327 return FALSE; 328 } 329 330 /********************* 331 deal with depth 332 *********************/ 333 334 if (!xf86SetDepthBpp(pScrn, 32, 0, 32, Support32bppFb)) { 335 return FALSE; 336 } else { 337 /* Check that the returned depth is one we support */ 338 switch (pScrn->depth) { 339 case 32: 340 case 24: 341 /* OK */ 342 break; 343 default: 344 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 345 "Given depth (%d) is not supported by this driver\n", 346 pScrn->depth); 347 return FALSE; 348 } 349 } 350 351 /* Collect all of the relevant option flags (fill in pScrn->options) */ 352 xf86CollectOptions(pScrn, NULL); 353 /* Process the options */ 354 if (!(pLeo->Options = malloc(sizeof(LeoOptions)))) 355 return FALSE; 356 memcpy(pLeo->Options, LeoOptions, sizeof(LeoOptions)); 357 xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pLeo->Options); 358 359 /* 360 * This must happen after pScrn->display has been set because 361 * xf86SetWeight references it. 362 */ 363 if (pScrn->depth > 8) { 364 rgb weight = {0, 0, 0}; 365 rgb mask = {0xff, 0xff00, 0xff0000}; 366 367 if (!xf86SetWeight(pScrn, weight, mask)) { 368 return FALSE; 369 } 370 } 371 372 if (!xf86SetDefaultVisual(pScrn, -1)) { 373 return FALSE; 374 } else { 375 /* We don't currently support DirectColor */ 376 if (pScrn->defaultVisual != TrueColor) { 377 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual" 378 " (%s) is not supported\n", 379 xf86GetVisualName(pScrn->defaultVisual)); 380 return FALSE; 381 } 382 } 383 384 /* 385 * The new cmap code requires this to be initialised. 386 */ 387 388 { 389 Gamma zeros = {0.0, 0.0, 0.0}; 390 391 if (!xf86SetGamma(pScrn, zeros)) { 392 return FALSE; 393 } 394 } 395 396 /* Set the bits per RGB for 8bpp mode */ 397 from = X_DEFAULT; 398 399 /* determine whether we use hardware or software cursor */ 400 401 pLeo->HWCursor = TRUE; 402 if (xf86GetOptValBool(pLeo->Options, OPTION_HW_CURSOR, &pLeo->HWCursor)) 403 from = X_CONFIG; 404 if (xf86ReturnOptValBool(pLeo->Options, OPTION_SW_CURSOR, FALSE)) { 405 from = X_CONFIG; 406 pLeo->HWCursor = FALSE; 407 } 408 409 xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n", 410 pLeo->HWCursor ? "HW" : "SW"); 411 412 if (xf86ReturnOptValBool(pLeo->Options, OPTION_NOACCEL, FALSE)) { 413 pLeo->NoAccel = TRUE; 414 xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n"); 415 } 416 417 if (xf86LoadSubModule(pScrn, "fb") == NULL) { 418 LeoFreeRec(pScrn); 419 return FALSE; 420 } 421 422 if (pLeo->HWCursor && xf86LoadSubModule(pScrn, "ramdac") == NULL) { 423 LeoFreeRec(pScrn); 424 return FALSE; 425 } 426 427 /********************* 428 set up clock and mode stuff 429 *********************/ 430 431 pScrn->progClock = TRUE; 432 433 if(pScrn->display->virtualX || pScrn->display->virtualY) { 434 xf86DrvMsg(pScrn->scrnIndex, X_WARNING, 435 "Leo does not support a virtual desktop\n"); 436 pScrn->display->virtualX = 0; 437 pScrn->display->virtualY = 0; 438 } 439 440 xf86SbusUseBuiltinMode(pScrn, pLeo->psdp); 441 pScrn->currentMode = pScrn->modes; 442 pScrn->displayWidth = pScrn->virtualX; 443 444 /* Set display resolution */ 445 xf86SetDpi(pScrn, 0, 0); 446 447 return TRUE; 448} 449 450/* Mandatory */ 451 452/* This gets called at the start of each server generation */ 453 454static Bool 455LeoScreenInit(SCREEN_INIT_ARGS_DECL) 456{ 457 ScrnInfoPtr pScrn; 458 LeoPtr pLeo; 459 int ret; 460 VisualPtr visual; 461 extern Bool LeoAccelInit(ScreenPtr pScreen, LeoPtr pLeo); 462 463 /* 464 * First get the ScrnInfoRec 465 */ 466 pScrn = xf86ScreenToScrn(pScreen); 467 468 pLeo = GET_LEO_FROM_SCRN(pScrn); 469 470 /* Map the Leo memory */ 471 pLeo->fb = 472 xf86MapSbusMem (pLeo->psdp, LEO_FB0_VOFF, 0x803000); 473 474 if (! pLeo->fb) 475 return FALSE; 476 477 /* Darken the screen for aesthetic reasons and set the viewport */ 478 LeoSaveScreen(pScreen, SCREEN_SAVER_ON); 479 480 /* 481 * The next step is to setup the screen's visuals, and initialise the 482 * framebuffer code. In cases where the framebuffer's default 483 * choices for things like visual layouts and bits per RGB are OK, 484 * this may be as simple as calling the framebuffer's ScreenInit() 485 * function. If not, the visuals will need to be setup before calling 486 * a fb ScreenInit() function and fixed up after. 487 */ 488 489 /* 490 * Reset visual list. 491 */ 492 miClearVisualTypes(); 493 494 /* Setup the visuals we support. */ 495 496 if (!miSetVisualTypes(pScrn->depth, TrueColorMask, pScrn->rgbBits, 497 pScrn->defaultVisual)) 498 return FALSE; 499 500 /* 501 * Call the framebuffer layer's ScreenInit function, and fill in other 502 * pScreen fields. 503 */ 504 505 ret = fbScreenInit(pScreen, pLeo->fb, pScrn->virtualX, 506 pScrn->virtualY, pScrn->xDpi, pScrn->yDpi, 507 2048, pScrn->bitsPerPixel); 508 if (!ret) 509 return FALSE; 510 511 xf86SetBackingStore(pScreen); 512 xf86SetSilkenMouse(pScreen); 513 514 xf86SetBlackWhitePixels(pScreen); 515 516 if (pScrn->bitsPerPixel > 8) { 517 /* Fixup RGB ordering */ 518 visual = pScreen->visuals + pScreen->numVisuals; 519 while (--visual >= pScreen->visuals) { 520 if ((visual->class | DynamicClass) == DirectColor) { 521 visual->offsetRed = pScrn->offset.red; 522 visual->offsetGreen = pScrn->offset.green; 523 visual->offsetBlue = pScrn->offset.blue; 524 visual->redMask = pScrn->mask.red; 525 visual->greenMask = pScrn->mask.green; 526 visual->blueMask = pScrn->mask.blue; 527 } 528 } 529 } 530 531 if (!LeoAccelInit(pScreen, pLeo)) 532 return FALSE; 533 534 if (!pLeo->NoAccel) 535 xf86Msg(X_INFO, "%s: Using acceleration\n", pLeo->psdp->device); 536 537 /* Initialise cursor functions */ 538 miDCInitialize (pScreen, xf86GetPointerScreenFuncs()); 539 540 /* Initialize HW cursor layer. 541 Must follow software cursor initialization*/ 542 if (pLeo->HWCursor) { 543 extern Bool LeoHWCursorInit(ScreenPtr pScreen); 544 545 if(!LeoHWCursorInit(pScreen)) { 546 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 547 "Hardware cursor initialization failed\n"); 548 return(FALSE); 549 } 550 xf86SbusHideOsHwCursor(pLeo->psdp); 551 } 552 553 /* Initialise default colourmap */ 554 if (!miCreateDefColormap(pScreen)) 555 return FALSE; 556 557 pLeo->CloseScreen = pScreen->CloseScreen; 558 pScreen->CloseScreen = LeoCloseScreen; 559 pScreen->SaveScreen = LeoSaveScreen; 560 561 /* Report any unused options (only for the first generation) */ 562 if (serverGeneration == 1) { 563 xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); 564 } 565 566 /* unblank the screen */ 567 LeoSaveScreen(pScreen, SCREEN_SAVER_OFF); 568 569 /* Done */ 570 return TRUE; 571} 572 573 574/* Usually mandatory */ 575static Bool 576LeoSwitchMode(SWITCH_MODE_ARGS_DECL) 577{ 578 return TRUE; 579} 580 581 582/* 583 * This function is used to initialize the Start Address - the first 584 * displayed location in the video memory. 585 */ 586/* Usually mandatory */ 587static void 588LeoAdjustFrame(ADJUST_FRAME_ARGS_DECL) 589{ 590 /* we don't support virtual desktops */ 591 return; 592} 593 594extern void LeoVtChange (ScreenPtr pScreen, int enter); 595 596/* 597 * This is called when VT switching back to the X server. Its job is 598 * to reinitialise the video mode. 599 */ 600 601/* Mandatory */ 602static Bool 603LeoEnterVT(VT_FUNC_ARGS_DECL) 604{ 605 SCRN_INFO_PTR(arg); 606 LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn); 607 608 pLeo->vtSema = FALSE; 609 LeoVtChange (pScrn->pScreen, TRUE); 610 if (pLeo->HWCursor) 611 xf86SbusHideOsHwCursor (pLeo->psdp); 612 return TRUE; 613} 614 615 616/* 617 * This is called when VT switching away from the X server. 618 */ 619 620/* Mandatory */ 621static void 622LeoLeaveVT(VT_FUNC_ARGS_DECL) 623{ 624 SCRN_INFO_PTR(arg); 625 LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn); 626 627 LeoVtChange (pScrn->pScreen, FALSE); 628 pLeo->vtSema = TRUE; 629} 630 631 632/* 633 * This is called at the end of each server generation. It restores the 634 * original (text) mode. It should really also unmap the video memory too. 635 */ 636 637/* Mandatory */ 638static Bool 639LeoCloseScreen(CLOSE_SCREEN_ARGS_DECL) 640{ 641 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 642 LeoPtr pLeo = GET_LEO_FROM_SCRN(pScrn); 643 644 pScrn->vtSema = FALSE; 645 xf86UnmapSbusMem(pLeo->psdp, pLeo->fb, 0x803000); 646 647 if (pLeo->HWCursor) 648 xf86SbusHideOsHwCursor (pLeo->psdp); 649 650 pScreen->CloseScreen = pLeo->CloseScreen; 651 return (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS); 652 return FALSE; 653} 654 655 656/* Free up any per-generation data structures */ 657 658/* Optional */ 659static void 660LeoFreeScreen(FREE_SCREEN_ARGS_DECL) 661{ 662 SCRN_INFO_PTR(arg); 663 LeoFreeRec(pScrn); 664} 665 666 667/* Checks if a mode is suitable for the selected chipset. */ 668 669/* Optional */ 670static ModeStatus 671LeoValidMode(SCRN_ARG_TYPE arg, DisplayModePtr mode, Bool verbose, int flags) 672{ 673 if (mode->Flags & V_INTERLACE) 674 return(MODE_BAD); 675 676 return(MODE_OK); 677} 678 679/* Do screen blanking */ 680 681/* Mandatory */ 682static Bool 683LeoSaveScreen(ScreenPtr pScreen, int mode) 684 /* this function should blank the screen when unblank is FALSE and 685 unblank it when unblank is TRUE -- it doesn't actually seem to be 686 used for much though */ 687{ 688 return TRUE; 689} 690 691/* 692 * This is the implementation of the Sync() function. 693 */ 694void 695LeoSync(ScrnInfoPtr pScrn) 696{ 697 return; 698} 699