1/* 2 * Copyright � 1999 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that 7 * copyright notice and this permission notice appear in supporting 8 * documentation, and that the name of Keith Packard not be used in 9 * advertising or publicity pertaining to distribution of the software without 10 * specific, written prior permission. Keith Packard makes no 11 * representations about the suitability of this software for any purpose. It 12 * is provided "as is" without express or implied warranty. 13 * 14 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20 * PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23#ifdef HAVE_CONFIG_H 24#include <kdrive-config.h> 25#endif 26#include "fbdev.h" 27#include <sys/ioctl.h> 28 29#include <errno.h> 30 31extern int KdTsPhyScreen; 32 33char *fbdevDevicePath = NULL; 34 35static Bool 36fbdevInitialize (KdCardInfo *card, FbdevPriv *priv) 37{ 38 unsigned long off; 39 40 if (fbdevDevicePath == NULL) 41 fbdevDevicePath = "/dev/fb0"; 42 43 if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) 44 { 45 ErrorF("Error opening framebuffer %s: %s\n", 46 fbdevDevicePath, strerror(errno)); 47 return FALSE; 48 } 49 50 /* quiet valgrind */ 51 memset (&priv->fix, '\0', sizeof (priv->fix)); 52 if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { 53 perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); 54 close (priv->fd); 55 return FALSE; 56 } 57 /* quiet valgrind */ 58 memset (&priv->var, '\0', sizeof (priv->var)); 59 if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { 60 perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); 61 close (priv->fd); 62 return FALSE; 63 } 64 65 priv->fb_base = (char *) mmap ((caddr_t) NULL, 66 priv->fix.smem_len, 67 PROT_READ|PROT_WRITE, 68 MAP_SHARED, 69 priv->fd, 0); 70 71 if (priv->fb_base == (char *)-1) 72 { 73 perror("ERROR: mmap framebuffer fails!"); 74 close (priv->fd); 75 return FALSE; 76 } 77 off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); 78 priv->fb = priv->fb_base + off; 79 return TRUE; 80} 81 82Bool 83fbdevCardInit (KdCardInfo *card) 84{ 85 FbdevPriv *priv; 86 87 priv = (FbdevPriv *) malloc(sizeof (FbdevPriv)); 88 if (!priv) 89 return FALSE; 90 91 if (!fbdevInitialize (card, priv)) 92 { 93 free(priv); 94 return FALSE; 95 } 96 card->driver = priv; 97 98 return TRUE; 99} 100 101static Pixel 102fbdevMakeContig (Pixel orig, Pixel others) 103{ 104 Pixel low; 105 106 low = lowbit (orig) >> 1; 107 while (low && (others & low) == 0) 108 { 109 orig |= low; 110 low >>= 1; 111 } 112 return orig; 113} 114 115static Bool 116fbdevModeSupported (KdScreenInfo *screen, 117 const KdMonitorTiming *t) 118{ 119 return TRUE; 120} 121 122static void 123fbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var) 124{ 125 memset (var, 0, sizeof (struct fb_var_screeninfo)); 126 127 var->xres = t->horizontal; 128 var->yres = t->vertical; 129 var->xres_virtual = t->horizontal; 130 var->yres_virtual = t->vertical; 131 var->xoffset = 0; 132 var->yoffset = 0; 133 var->pixclock = t->clock ? 1000000000 / t->clock : 0; 134 var->left_margin = t->hbp; 135 var->right_margin = t->hfp; 136 var->upper_margin = t->vbp; 137 var->lower_margin = t->vfp; 138 var->hsync_len = t->hblank - t->hfp - t->hbp; 139 var->vsync_len = t->vblank - t->vfp - t->vbp; 140 141 var->sync = 0; 142 var->vmode = 0; 143 144 if (t->hpol == KdSyncPositive) 145 var->sync |= FB_SYNC_HOR_HIGH_ACT; 146 if (t->vpol == KdSyncPositive) 147 var->sync |= FB_SYNC_VERT_HIGH_ACT; 148} 149 150static Bool 151fbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv) 152{ 153 FbdevPriv *priv = screen->card->driver; 154 Pixel allbits; 155 int depth; 156 Bool gray; 157 struct fb_var_screeninfo var; 158 const KdMonitorTiming *t; 159 int k; 160 161 k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var); 162 163 if (!screen->width || !screen->height) 164 { 165 if (k >= 0) 166 { 167 screen->width = var.xres; 168 screen->height = var.yres; 169 } 170 else 171 { 172 screen->width = 1024; 173 screen->height = 768; 174 } 175 screen->rate = 103; /* FIXME: should get proper value from fb driver */ 176 } 177 if (!screen->fb.depth) 178 { 179 if (k >= 0) 180 screen->fb.depth = var.bits_per_pixel; 181 else 182 screen->fb.depth = 16; 183 } 184 185 if ((screen->width != var.xres) || (screen->height != var.yres)) 186 { 187 t = KdFindMode (screen, fbdevModeSupported); 188 screen->rate = t->rate; 189 screen->width = t->horizontal; 190 screen->height = t->vertical; 191 192 /* Now try setting the mode */ 193 if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) 194 fbdevConvertMonitorTiming (t, &var); 195 } 196 197 var.activate = FB_ACTIVATE_NOW; 198 var.bits_per_pixel = screen->fb.depth; 199 var.nonstd = 0; 200 var.grayscale = 0; 201 202 k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var); 203 204 if (k < 0) 205 { 206 fprintf (stderr, "error: %s\n", strerror (errno)); 207 return FALSE; 208 } 209 210 /* Re-get the "fixed" parameters since they might have changed */ 211 k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix); 212 if (k < 0) 213 perror ("FBIOGET_FSCREENINFO"); 214 215 /* Now get the new screeninfo */ 216 ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var); 217 depth = priv->var.bits_per_pixel; 218 gray = priv->var.grayscale; 219 220 switch (priv->fix.visual) { 221 case FB_VISUAL_PSEUDOCOLOR: 222 if (gray) 223 { 224 screen->fb.visuals = (1 << StaticGray); 225 /* could also support GrayScale, but what's the point? */ 226 } 227 else 228 { 229 screen->fb.visuals = ((1 << StaticGray) | 230 (1 << GrayScale) | 231 (1 << StaticColor) | 232 (1 << PseudoColor) | 233 (1 << TrueColor) | 234 (1 << DirectColor)); 235 } 236 screen->fb.blueMask = 0x00; 237 screen->fb.greenMask = 0x00; 238 screen->fb.redMask = 0x00; 239 break; 240 case FB_VISUAL_STATIC_PSEUDOCOLOR: 241 if (gray) 242 { 243 screen->fb.visuals = (1 << StaticGray); 244 } 245 else 246 { 247 screen->fb.visuals = (1 << StaticColor); 248 } 249 screen->fb.blueMask = 0x00; 250 screen->fb.greenMask = 0x00; 251 screen->fb.redMask = 0x00; 252 break; 253 case FB_VISUAL_TRUECOLOR: 254 case FB_VISUAL_DIRECTCOLOR: 255 screen->fb.visuals = (1 << TrueColor); 256#define Mask(o,l) (((1 << l) - 1) << o) 257 screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length); 258 screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length); 259 screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length); 260 261 /* 262 * This is a kludge so that Render will work -- fill in the gaps 263 * in the pixel 264 */ 265 screen->fb.redMask = fbdevMakeContig (screen->fb.redMask, 266 screen->fb.greenMask| 267 screen->fb.blueMask); 268 269 screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask, 270 screen->fb.redMask| 271 screen->fb.blueMask); 272 273 screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask, 274 screen->fb.redMask| 275 screen->fb.greenMask); 276 277 allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask; 278 depth = 32; 279 while (depth && !(allbits & (1 << (depth - 1)))) 280 depth--; 281 break; 282 default: 283 return FALSE; 284 break; 285 } 286 screen->fb.depth = depth; 287 screen->fb.bitsPerPixel = priv->var.bits_per_pixel; 288 289 scrpriv->randr = screen->randr; 290 291 return fbdevMapFramebuffer (screen); 292} 293 294Bool 295fbdevScreenInit (KdScreenInfo *screen) 296{ 297 FbdevScrPriv *scrpriv; 298 299 scrpriv = calloc(1, sizeof (FbdevScrPriv)); 300 if (!scrpriv) 301 return FALSE; 302 screen->driver = scrpriv; 303 if (!fbdevScreenInitialize (screen, scrpriv)) 304 { 305 screen->driver = 0; 306 free(scrpriv); 307 return FALSE; 308 } 309 return TRUE; 310} 311 312static void * 313fbdevWindowLinear (ScreenPtr pScreen, 314 CARD32 row, 315 CARD32 offset, 316 int mode, 317 CARD32 *size, 318 void *closure) 319{ 320 KdScreenPriv(pScreen); 321 FbdevPriv *priv = pScreenPriv->card->driver; 322 323 if (!pScreenPriv->enabled) 324 return 0; 325 *size = priv->fix.line_length; 326 return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; 327} 328 329Bool 330fbdevMapFramebuffer (KdScreenInfo *screen) 331{ 332 FbdevScrPriv *scrpriv = screen->driver; 333 KdPointerMatrix m; 334 FbdevPriv *priv = screen->card->driver; 335 336 if (scrpriv->randr != RR_Rotate_0) 337 scrpriv->shadow = TRUE; 338 else 339 scrpriv->shadow = FALSE; 340 341 KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); 342 343 KdSetPointerMatrix (&m); 344 345 screen->width = priv->var.xres; 346 screen->height = priv->var.yres; 347 348 if (scrpriv->shadow) 349 { 350 if (!KdShadowFbAlloc (screen, 351 scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) 352 return FALSE; 353 } 354 else 355 { 356 screen->fb.byteStride = priv->fix.line_length; 357 screen->fb.pixelStride = (priv->fix.line_length * 8 / 358 priv->var.bits_per_pixel); 359 screen->fb.frameBuffer = (CARD8 *) (priv->fb); 360 } 361 362 return TRUE; 363} 364 365static void 366fbdevSetScreenSizes (ScreenPtr pScreen) 367{ 368 KdScreenPriv(pScreen); 369 KdScreenInfo *screen = pScreenPriv->screen; 370 FbdevScrPriv *scrpriv = screen->driver; 371 FbdevPriv *priv = screen->card->driver; 372 373 if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) 374 { 375 pScreen->width = priv->var.xres; 376 pScreen->height = priv->var.yres; 377 pScreen->mmWidth = screen->width_mm; 378 pScreen->mmHeight = screen->height_mm; 379 } 380 else 381 { 382 pScreen->width = priv->var.yres; 383 pScreen->height = priv->var.xres; 384 pScreen->mmWidth = screen->height_mm; 385 pScreen->mmHeight = screen->width_mm; 386 } 387} 388 389static Bool 390fbdevUnmapFramebuffer (KdScreenInfo *screen) 391{ 392 KdShadowFbFree (screen); 393 return TRUE; 394} 395 396static Bool 397fbdevSetShadow (ScreenPtr pScreen) 398{ 399 KdScreenPriv(pScreen); 400 KdScreenInfo *screen = pScreenPriv->screen; 401 FbdevScrPriv *scrpriv = screen->driver; 402 FbdevPriv *priv = screen->card->driver; 403 ShadowUpdateProc update; 404 ShadowWindowProc window; 405 int useYX = 0; 406 407#ifdef __arm__ 408 /* Use variant copy routines that always read left to right in the 409 shadow framebuffer. Reading vertical strips is exceptionally 410 slow on XScale due to cache effects. */ 411 useYX = 1; 412#endif 413 414 window = fbdevWindowLinear; 415 update = 0; 416 if (scrpriv->randr) 417 if (priv->var.bits_per_pixel == 16) { 418 switch (scrpriv->randr) { 419 case RR_Rotate_90: 420 if (useYX) 421 update = shadowUpdateRotate16_90YX; 422 else 423 update = shadowUpdateRotate16_90; 424 break; 425 case RR_Rotate_180: 426 update = shadowUpdateRotate16_180; 427 break; 428 case RR_Rotate_270: 429 if (useYX) 430 update = shadowUpdateRotate16_270YX; 431 else 432 update = shadowUpdateRotate16_270; 433 break; 434 default: 435 update = shadowUpdateRotate16; 436 break; 437 } 438 } else 439 update = shadowUpdateRotatePacked; 440 else 441 update = shadowUpdatePacked; 442 return KdShadowSet (pScreen, scrpriv->randr, update, window); 443} 444 445 446#ifdef RANDR 447static Bool 448fbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) 449{ 450 KdScreenPriv(pScreen); 451 KdScreenInfo *screen = pScreenPriv->screen; 452 FbdevScrPriv *scrpriv = screen->driver; 453 RRScreenSizePtr pSize; 454 Rotation randr; 455 int n; 456 457 *rotations = RR_Rotate_All|RR_Reflect_All; 458 459 for (n = 0; n < pScreen->numDepths; n++) 460 if (pScreen->allowedDepths[n].numVids) 461 break; 462 if (n == pScreen->numDepths) 463 return FALSE; 464 465 pSize = RRRegisterSize (pScreen, 466 screen->width, 467 screen->height, 468 screen->width_mm, 469 screen->height_mm); 470 471 randr = KdSubRotation (scrpriv->randr, screen->randr); 472 473 RRSetCurrentConfig (pScreen, randr, 0, pSize); 474 475 return TRUE; 476} 477 478static Bool 479fbdevRandRSetConfig (ScreenPtr pScreen, 480 Rotation randr, 481 int rate, 482 RRScreenSizePtr pSize) 483{ 484 KdScreenPriv(pScreen); 485 KdScreenInfo *screen = pScreenPriv->screen; 486 FbdevScrPriv *scrpriv = screen->driver; 487 Bool wasEnabled = pScreenPriv->enabled; 488 FbdevScrPriv oldscr; 489 int oldwidth; 490 int oldheight; 491 int oldmmwidth; 492 int oldmmheight; 493 int newwidth, newheight; 494 495 if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) 496 { 497 newwidth = pSize->width; 498 newheight = pSize->height; 499 } 500 else 501 { 502 newwidth = pSize->height; 503 newheight = pSize->width; 504 } 505 506 if (wasEnabled) 507 KdDisableScreen (pScreen); 508 509 oldscr = *scrpriv; 510 511 oldwidth = screen->width; 512 oldheight = screen->height; 513 oldmmwidth = pScreen->mmWidth; 514 oldmmheight = pScreen->mmHeight; 515 516 /* 517 * Set new configuration 518 */ 519 520 scrpriv->randr = KdAddRotation (screen->randr, randr); 521 522 fbdevUnmapFramebuffer (screen); 523 524 if (!fbdevMapFramebuffer (screen)) 525 goto bail4; 526 527 KdShadowUnset (screen->pScreen); 528 529 if (!fbdevSetShadow (screen->pScreen)) 530 goto bail4; 531 532 fbdevSetScreenSizes (screen->pScreen); 533 534 /* 535 * Set frame buffer mapping 536 */ 537 (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), 538 pScreen->width, 539 pScreen->height, 540 screen->fb.depth, 541 screen->fb.bitsPerPixel, 542 screen->fb.byteStride, 543 screen->fb.frameBuffer); 544 545 /* set the subpixel order */ 546 547 KdSetSubpixelOrder (pScreen, scrpriv->randr); 548 if (wasEnabled) 549 KdEnableScreen (pScreen); 550 551 return TRUE; 552 553bail4: 554 fbdevUnmapFramebuffer (screen); 555 *scrpriv = oldscr; 556 (void) fbdevMapFramebuffer (screen); 557 pScreen->width = oldwidth; 558 pScreen->height = oldheight; 559 pScreen->mmWidth = oldmmwidth; 560 pScreen->mmHeight = oldmmheight; 561 562 if (wasEnabled) 563 KdEnableScreen (pScreen); 564 return FALSE; 565} 566 567static Bool 568fbdevRandRInit (ScreenPtr pScreen) 569{ 570 rrScrPrivPtr pScrPriv; 571 572 if (!RRScreenInit (pScreen)) 573 return FALSE; 574 575 pScrPriv = rrGetScrPriv(pScreen); 576 pScrPriv->rrGetInfo = fbdevRandRGetInfo; 577 pScrPriv->rrSetConfig = fbdevRandRSetConfig; 578 return TRUE; 579} 580#endif 581 582static Bool 583fbdevCreateColormap (ColormapPtr pmap) 584{ 585 ScreenPtr pScreen = pmap->pScreen; 586 KdScreenPriv(pScreen); 587 FbdevPriv *priv = pScreenPriv->card->driver; 588 VisualPtr pVisual; 589 int i; 590 int nent; 591 xColorItem *pdefs; 592 593 switch (priv->fix.visual) { 594 case FB_VISUAL_STATIC_PSEUDOCOLOR: 595 pVisual = pmap->pVisual; 596 nent = pVisual->ColormapEntries; 597 pdefs = malloc(nent * sizeof (xColorItem)); 598 if (!pdefs) 599 return FALSE; 600 for (i = 0; i < nent; i++) 601 pdefs[i].pixel = i; 602 fbdevGetColors (pScreen, nent, pdefs); 603 for (i = 0; i < nent; i++) 604 { 605 pmap->red[i].co.local.red = pdefs[i].red; 606 pmap->red[i].co.local.green = pdefs[i].green; 607 pmap->red[i].co.local.blue = pdefs[i].blue; 608 } 609 free(pdefs); 610 return TRUE; 611 default: 612 return fbInitializeColormap (pmap); 613 } 614} 615 616Bool 617fbdevInitScreen (ScreenPtr pScreen) 618{ 619#ifdef TOUCHSCREEN 620 KdTsPhyScreen = pScreen->myNum; 621#endif 622 623 pScreen->CreateColormap = fbdevCreateColormap; 624 return TRUE; 625} 626 627Bool 628fbdevFinishInitScreen (ScreenPtr pScreen) 629{ 630 if (!shadowSetup (pScreen)) 631 return FALSE; 632 633#ifdef RANDR 634 if (!fbdevRandRInit (pScreen)) 635 return FALSE; 636#endif 637 638 return TRUE; 639} 640 641 642Bool 643fbdevCreateResources (ScreenPtr pScreen) 644{ 645 return fbdevSetShadow (pScreen); 646} 647 648void 649fbdevPreserve (KdCardInfo *card) 650{ 651} 652 653static int 654fbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) 655{ 656 struct fb_cmap cmap; 657 658 cmap.start = minidx; 659 cmap.len = maxidx - minidx + 1; 660 cmap.red = &priv->red[minidx]; 661 cmap.green = &priv->green[minidx]; 662 cmap.blue = &priv->blue[minidx]; 663 cmap.transp = 0; 664 665 return ioctl(priv->fd, FBIOPUTCMAP, &cmap); 666} 667 668Bool 669fbdevEnable (ScreenPtr pScreen) 670{ 671 KdScreenPriv(pScreen); 672 FbdevPriv *priv = pScreenPriv->card->driver; 673 int k; 674 675 priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL; 676 677 /* display it on the LCD */ 678 k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var); 679 if (k < 0) 680 { 681 perror ("FBIOPUT_VSCREENINFO"); 682 return FALSE; 683 } 684 685 if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) 686 { 687 int i; 688 689 for (i = 0; 690 i < (1 << priv->var.red.length) || 691 i < (1 << priv->var.green.length) || 692 i < (1 << priv->var.blue.length); i++) 693 { 694 priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1); 695 priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1); 696 priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1); 697 } 698 699 fbdevUpdateFbColormap(priv, 0, i); 700 } 701 return TRUE; 702} 703 704Bool 705fbdevDPMS (ScreenPtr pScreen, int mode) 706{ 707 KdScreenPriv(pScreen); 708 FbdevPriv *priv = pScreenPriv->card->driver; 709 static int oldmode = -1; 710 711 if (mode == oldmode) 712 return TRUE; 713#ifdef FBIOPUT_POWERMODE 714 if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) 715 { 716 oldmode = mode; 717 return TRUE; 718 } 719#endif 720#ifdef FBIOBLANK 721 if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) 722 { 723 oldmode = mode; 724 return TRUE; 725 } 726#endif 727 return FALSE; 728} 729 730void 731fbdevDisable (ScreenPtr pScreen) 732{ 733} 734 735void 736fbdevRestore (KdCardInfo *card) 737{ 738} 739 740void 741fbdevScreenFini (KdScreenInfo *screen) 742{ 743} 744 745void 746fbdevCardFini (KdCardInfo *card) 747{ 748 FbdevPriv *priv = card->driver; 749 750 munmap (priv->fb_base, priv->fix.smem_len); 751 close (priv->fd); 752 free(priv); 753} 754 755/* 756 * Retrieve actual colormap and return selected n entries in pdefs. 757 */ 758void 759fbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 760{ 761 KdScreenPriv(pScreen); 762 FbdevPriv *priv = pScreenPriv->card->driver; 763 struct fb_cmap cmap; 764 int p; 765 int k; 766 int min, max; 767 768 min = 256; 769 max = 0; 770 for (k = 0; k < n; k++) 771 { 772 if (pdefs[k].pixel < min) 773 min = pdefs[k].pixel; 774 if (pdefs[k].pixel > max) 775 max = pdefs[k].pixel; 776 } 777 cmap.start = min; 778 cmap.len = max - min + 1; 779 cmap.red = &priv->red[min]; 780 cmap.green = &priv->green[min]; 781 cmap.blue = &priv->blue[min]; 782 cmap.transp = 0; 783 k = ioctl (priv->fd, FBIOGETCMAP, &cmap); 784 if (k < 0) 785 { 786 perror ("can't get colormap"); 787 return; 788 } 789 while (n--) 790 { 791 p = pdefs->pixel; 792 pdefs->red = priv->red[p]; 793 pdefs->green = priv->green[p]; 794 pdefs->blue = priv->blue[p]; 795 pdefs++; 796 } 797} 798 799/* 800 * Change colormap by updating n entries described in pdefs. 801 */ 802void 803fbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 804{ 805 KdScreenPriv(pScreen); 806 FbdevPriv *priv = pScreenPriv->card->driver; 807 int p; 808 int min, max; 809 810 min = 256; 811 max = 0; 812 while (n--) 813 { 814 p = pdefs->pixel; 815 priv->red[p] = pdefs->red; 816 priv->green[p] = pdefs->green; 817 priv->blue[p] = pdefs->blue; 818 if (p < min) 819 min = p; 820 if (p > max) 821 max = p; 822 pdefs++; 823 } 824 825 fbdevUpdateFbColormap(priv, min, max); 826} 827