1706f2543Smrg/* 2706f2543Smrg * Copyright � 1999 Keith Packard 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that 7706f2543Smrg * copyright notice and this permission notice appear in supporting 8706f2543Smrg * documentation, and that the name of Keith Packard not be used in 9706f2543Smrg * advertising or publicity pertaining to distribution of the software without 10706f2543Smrg * specific, written prior permission. Keith Packard makes no 11706f2543Smrg * representations about the suitability of this software for any purpose. It 12706f2543Smrg * is provided "as is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_CONFIG_H 24706f2543Smrg#include <kdrive-config.h> 25706f2543Smrg#endif 26706f2543Smrg#include "fbdev.h" 27706f2543Smrg#include <sys/ioctl.h> 28706f2543Smrg 29706f2543Smrg#include <errno.h> 30706f2543Smrg 31706f2543Smrgextern int KdTsPhyScreen; 32706f2543Smrg 33706f2543Smrgchar *fbdevDevicePath = NULL; 34706f2543Smrg 35706f2543Smrgstatic Bool 36706f2543SmrgfbdevInitialize (KdCardInfo *card, FbdevPriv *priv) 37706f2543Smrg{ 38706f2543Smrg unsigned long off; 39706f2543Smrg 40706f2543Smrg if (fbdevDevicePath == NULL) 41706f2543Smrg fbdevDevicePath = "/dev/fb0"; 42706f2543Smrg 43706f2543Smrg if ((priv->fd = open(fbdevDevicePath, O_RDWR)) < 0) 44706f2543Smrg { 45706f2543Smrg ErrorF("Error opening framebuffer %s: %s\n", 46706f2543Smrg fbdevDevicePath, strerror(errno)); 47706f2543Smrg return FALSE; 48706f2543Smrg } 49706f2543Smrg 50706f2543Smrg /* quiet valgrind */ 51706f2543Smrg memset (&priv->fix, '\0', sizeof (priv->fix)); 52706f2543Smrg if (ioctl(priv->fd, FBIOGET_FSCREENINFO, &priv->fix) < 0) { 53706f2543Smrg perror("Error with /dev/fb ioctl FIOGET_FSCREENINFO"); 54706f2543Smrg close (priv->fd); 55706f2543Smrg return FALSE; 56706f2543Smrg } 57706f2543Smrg /* quiet valgrind */ 58706f2543Smrg memset (&priv->var, '\0', sizeof (priv->var)); 59706f2543Smrg if (ioctl(priv->fd, FBIOGET_VSCREENINFO, &priv->var) < 0) { 60706f2543Smrg perror("Error with /dev/fb ioctl FIOGET_VSCREENINFO"); 61706f2543Smrg close (priv->fd); 62706f2543Smrg return FALSE; 63706f2543Smrg } 64706f2543Smrg 65706f2543Smrg priv->fb_base = (char *) mmap ((caddr_t) NULL, 66706f2543Smrg priv->fix.smem_len, 67706f2543Smrg PROT_READ|PROT_WRITE, 68706f2543Smrg MAP_SHARED, 69706f2543Smrg priv->fd, 0); 70706f2543Smrg 71706f2543Smrg if (priv->fb_base == (char *)-1) 72706f2543Smrg { 73706f2543Smrg perror("ERROR: mmap framebuffer fails!"); 74706f2543Smrg close (priv->fd); 75706f2543Smrg return FALSE; 76706f2543Smrg } 77706f2543Smrg off = (unsigned long) priv->fix.smem_start % (unsigned long) getpagesize(); 78706f2543Smrg priv->fb = priv->fb_base + off; 79706f2543Smrg return TRUE; 80706f2543Smrg} 81706f2543Smrg 82706f2543SmrgBool 83706f2543SmrgfbdevCardInit (KdCardInfo *card) 84706f2543Smrg{ 85706f2543Smrg FbdevPriv *priv; 86706f2543Smrg 87706f2543Smrg priv = (FbdevPriv *) malloc(sizeof (FbdevPriv)); 88706f2543Smrg if (!priv) 89706f2543Smrg return FALSE; 90706f2543Smrg 91706f2543Smrg if (!fbdevInitialize (card, priv)) 92706f2543Smrg { 93706f2543Smrg free(priv); 94706f2543Smrg return FALSE; 95706f2543Smrg } 96706f2543Smrg card->driver = priv; 97706f2543Smrg 98706f2543Smrg return TRUE; 99706f2543Smrg} 100706f2543Smrg 101706f2543Smrgstatic Pixel 102706f2543SmrgfbdevMakeContig (Pixel orig, Pixel others) 103706f2543Smrg{ 104706f2543Smrg Pixel low; 105706f2543Smrg 106706f2543Smrg low = lowbit (orig) >> 1; 107706f2543Smrg while (low && (others & low) == 0) 108706f2543Smrg { 109706f2543Smrg orig |= low; 110706f2543Smrg low >>= 1; 111706f2543Smrg } 112706f2543Smrg return orig; 113706f2543Smrg} 114706f2543Smrg 115706f2543Smrgstatic Bool 116706f2543SmrgfbdevModeSupported (KdScreenInfo *screen, 117706f2543Smrg const KdMonitorTiming *t) 118706f2543Smrg{ 119706f2543Smrg return TRUE; 120706f2543Smrg} 121706f2543Smrg 122706f2543Smrgstatic void 123706f2543SmrgfbdevConvertMonitorTiming (const KdMonitorTiming *t, struct fb_var_screeninfo *var) 124706f2543Smrg{ 125706f2543Smrg memset (var, 0, sizeof (struct fb_var_screeninfo)); 126706f2543Smrg 127706f2543Smrg var->xres = t->horizontal; 128706f2543Smrg var->yres = t->vertical; 129706f2543Smrg var->xres_virtual = t->horizontal; 130706f2543Smrg var->yres_virtual = t->vertical; 131706f2543Smrg var->xoffset = 0; 132706f2543Smrg var->yoffset = 0; 133706f2543Smrg var->pixclock = t->clock ? 1000000000 / t->clock : 0; 134706f2543Smrg var->left_margin = t->hbp; 135706f2543Smrg var->right_margin = t->hfp; 136706f2543Smrg var->upper_margin = t->vbp; 137706f2543Smrg var->lower_margin = t->vfp; 138706f2543Smrg var->hsync_len = t->hblank - t->hfp - t->hbp; 139706f2543Smrg var->vsync_len = t->vblank - t->vfp - t->vbp; 140706f2543Smrg 141706f2543Smrg var->sync = 0; 142706f2543Smrg var->vmode = 0; 143706f2543Smrg 144706f2543Smrg if (t->hpol == KdSyncPositive) 145706f2543Smrg var->sync |= FB_SYNC_HOR_HIGH_ACT; 146706f2543Smrg if (t->vpol == KdSyncPositive) 147706f2543Smrg var->sync |= FB_SYNC_VERT_HIGH_ACT; 148706f2543Smrg} 149706f2543Smrg 150706f2543Smrgstatic Bool 151706f2543SmrgfbdevScreenInitialize (KdScreenInfo *screen, FbdevScrPriv *scrpriv) 152706f2543Smrg{ 153706f2543Smrg FbdevPriv *priv = screen->card->driver; 154706f2543Smrg Pixel allbits; 155706f2543Smrg int depth; 156706f2543Smrg Bool gray; 157706f2543Smrg struct fb_var_screeninfo var; 158706f2543Smrg const KdMonitorTiming *t; 159706f2543Smrg int k; 160706f2543Smrg 161706f2543Smrg k = ioctl (priv->fd, FBIOGET_VSCREENINFO, &var); 162706f2543Smrg 163706f2543Smrg if (!screen->width || !screen->height) 164706f2543Smrg { 165706f2543Smrg if (k >= 0) 166706f2543Smrg { 167706f2543Smrg screen->width = var.xres; 168706f2543Smrg screen->height = var.yres; 169706f2543Smrg } 170706f2543Smrg else 171706f2543Smrg { 172706f2543Smrg screen->width = 1024; 173706f2543Smrg screen->height = 768; 174706f2543Smrg } 175706f2543Smrg screen->rate = 103; /* FIXME: should get proper value from fb driver */ 176706f2543Smrg } 177706f2543Smrg if (!screen->fb.depth) 178706f2543Smrg { 179706f2543Smrg if (k >= 0) 180706f2543Smrg screen->fb.depth = var.bits_per_pixel; 181706f2543Smrg else 182706f2543Smrg screen->fb.depth = 16; 183706f2543Smrg } 184706f2543Smrg 185706f2543Smrg if ((screen->width != var.xres) || (screen->height != var.yres)) 186706f2543Smrg { 187706f2543Smrg t = KdFindMode (screen, fbdevModeSupported); 188706f2543Smrg screen->rate = t->rate; 189706f2543Smrg screen->width = t->horizontal; 190706f2543Smrg screen->height = t->vertical; 191706f2543Smrg 192706f2543Smrg /* Now try setting the mode */ 193706f2543Smrg if (k < 0 || (t->horizontal != var.xres || t->vertical != var.yres)) 194706f2543Smrg fbdevConvertMonitorTiming (t, &var); 195706f2543Smrg } 196706f2543Smrg 197706f2543Smrg var.activate = FB_ACTIVATE_NOW; 198706f2543Smrg var.bits_per_pixel = screen->fb.depth; 199706f2543Smrg var.nonstd = 0; 200706f2543Smrg var.grayscale = 0; 201706f2543Smrg 202706f2543Smrg k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &var); 203706f2543Smrg 204706f2543Smrg if (k < 0) 205706f2543Smrg { 206706f2543Smrg fprintf (stderr, "error: %s\n", strerror (errno)); 207706f2543Smrg return FALSE; 208706f2543Smrg } 209706f2543Smrg 210706f2543Smrg /* Re-get the "fixed" parameters since they might have changed */ 211706f2543Smrg k = ioctl (priv->fd, FBIOGET_FSCREENINFO, &priv->fix); 212706f2543Smrg if (k < 0) 213706f2543Smrg perror ("FBIOGET_FSCREENINFO"); 214706f2543Smrg 215706f2543Smrg /* Now get the new screeninfo */ 216706f2543Smrg ioctl (priv->fd, FBIOGET_VSCREENINFO, &priv->var); 217706f2543Smrg depth = priv->var.bits_per_pixel; 218706f2543Smrg gray = priv->var.grayscale; 219706f2543Smrg 220706f2543Smrg switch (priv->fix.visual) { 221706f2543Smrg case FB_VISUAL_PSEUDOCOLOR: 222706f2543Smrg if (gray) 223706f2543Smrg { 224706f2543Smrg screen->fb.visuals = (1 << StaticGray); 225706f2543Smrg /* could also support GrayScale, but what's the point? */ 226706f2543Smrg } 227706f2543Smrg else 228706f2543Smrg { 229706f2543Smrg screen->fb.visuals = ((1 << StaticGray) | 230706f2543Smrg (1 << GrayScale) | 231706f2543Smrg (1 << StaticColor) | 232706f2543Smrg (1 << PseudoColor) | 233706f2543Smrg (1 << TrueColor) | 234706f2543Smrg (1 << DirectColor)); 235706f2543Smrg } 236706f2543Smrg screen->fb.blueMask = 0x00; 237706f2543Smrg screen->fb.greenMask = 0x00; 238706f2543Smrg screen->fb.redMask = 0x00; 239706f2543Smrg break; 240706f2543Smrg case FB_VISUAL_STATIC_PSEUDOCOLOR: 241706f2543Smrg if (gray) 242706f2543Smrg { 243706f2543Smrg screen->fb.visuals = (1 << StaticGray); 244706f2543Smrg } 245706f2543Smrg else 246706f2543Smrg { 247706f2543Smrg screen->fb.visuals = (1 << StaticColor); 248706f2543Smrg } 249706f2543Smrg screen->fb.blueMask = 0x00; 250706f2543Smrg screen->fb.greenMask = 0x00; 251706f2543Smrg screen->fb.redMask = 0x00; 252706f2543Smrg break; 253706f2543Smrg case FB_VISUAL_TRUECOLOR: 254706f2543Smrg case FB_VISUAL_DIRECTCOLOR: 255706f2543Smrg screen->fb.visuals = (1 << TrueColor); 256706f2543Smrg#define Mask(o,l) (((1 << l) - 1) << o) 257706f2543Smrg screen->fb.redMask = Mask (priv->var.red.offset, priv->var.red.length); 258706f2543Smrg screen->fb.greenMask = Mask (priv->var.green.offset, priv->var.green.length); 259706f2543Smrg screen->fb.blueMask = Mask (priv->var.blue.offset, priv->var.blue.length); 260706f2543Smrg 261706f2543Smrg /* 262706f2543Smrg * This is a kludge so that Render will work -- fill in the gaps 263706f2543Smrg * in the pixel 264706f2543Smrg */ 265706f2543Smrg screen->fb.redMask = fbdevMakeContig (screen->fb.redMask, 266706f2543Smrg screen->fb.greenMask| 267706f2543Smrg screen->fb.blueMask); 268706f2543Smrg 269706f2543Smrg screen->fb.greenMask = fbdevMakeContig (screen->fb.greenMask, 270706f2543Smrg screen->fb.redMask| 271706f2543Smrg screen->fb.blueMask); 272706f2543Smrg 273706f2543Smrg screen->fb.blueMask = fbdevMakeContig (screen->fb.blueMask, 274706f2543Smrg screen->fb.redMask| 275706f2543Smrg screen->fb.greenMask); 276706f2543Smrg 277706f2543Smrg allbits = screen->fb.redMask | screen->fb.greenMask | screen->fb.blueMask; 278706f2543Smrg depth = 32; 279706f2543Smrg while (depth && !(allbits & (1 << (depth - 1)))) 280706f2543Smrg depth--; 281706f2543Smrg break; 282706f2543Smrg default: 283706f2543Smrg return FALSE; 284706f2543Smrg break; 285706f2543Smrg } 286706f2543Smrg screen->fb.depth = depth; 287706f2543Smrg screen->fb.bitsPerPixel = priv->var.bits_per_pixel; 288706f2543Smrg 289706f2543Smrg scrpriv->randr = screen->randr; 290706f2543Smrg 291706f2543Smrg return fbdevMapFramebuffer (screen); 292706f2543Smrg} 293706f2543Smrg 294706f2543SmrgBool 295706f2543SmrgfbdevScreenInit (KdScreenInfo *screen) 296706f2543Smrg{ 297706f2543Smrg FbdevScrPriv *scrpriv; 298706f2543Smrg 299706f2543Smrg scrpriv = calloc(1, sizeof (FbdevScrPriv)); 300706f2543Smrg if (!scrpriv) 301706f2543Smrg return FALSE; 302706f2543Smrg screen->driver = scrpriv; 303706f2543Smrg if (!fbdevScreenInitialize (screen, scrpriv)) 304706f2543Smrg { 305706f2543Smrg screen->driver = 0; 306706f2543Smrg free(scrpriv); 307706f2543Smrg return FALSE; 308706f2543Smrg } 309706f2543Smrg return TRUE; 310706f2543Smrg} 311706f2543Smrg 312706f2543Smrgstatic void * 313706f2543SmrgfbdevWindowLinear (ScreenPtr pScreen, 314706f2543Smrg CARD32 row, 315706f2543Smrg CARD32 offset, 316706f2543Smrg int mode, 317706f2543Smrg CARD32 *size, 318706f2543Smrg void *closure) 319706f2543Smrg{ 320706f2543Smrg KdScreenPriv(pScreen); 321706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 322706f2543Smrg 323706f2543Smrg if (!pScreenPriv->enabled) 324706f2543Smrg return 0; 325706f2543Smrg *size = priv->fix.line_length; 326706f2543Smrg return (CARD8 *) priv->fb + row * priv->fix.line_length + offset; 327706f2543Smrg} 328706f2543Smrg 329706f2543SmrgBool 330706f2543SmrgfbdevMapFramebuffer (KdScreenInfo *screen) 331706f2543Smrg{ 332706f2543Smrg FbdevScrPriv *scrpriv = screen->driver; 333706f2543Smrg KdPointerMatrix m; 334706f2543Smrg FbdevPriv *priv = screen->card->driver; 335706f2543Smrg 336706f2543Smrg if (scrpriv->randr != RR_Rotate_0) 337706f2543Smrg scrpriv->shadow = TRUE; 338706f2543Smrg else 339706f2543Smrg scrpriv->shadow = FALSE; 340706f2543Smrg 341706f2543Smrg KdComputePointerMatrix (&m, scrpriv->randr, screen->width, screen->height); 342706f2543Smrg 343706f2543Smrg KdSetPointerMatrix (&m); 344706f2543Smrg 345706f2543Smrg screen->width = priv->var.xres; 346706f2543Smrg screen->height = priv->var.yres; 347706f2543Smrg 348706f2543Smrg if (scrpriv->shadow) 349706f2543Smrg { 350706f2543Smrg if (!KdShadowFbAlloc (screen, 351706f2543Smrg scrpriv->randr & (RR_Rotate_90|RR_Rotate_270))) 352706f2543Smrg return FALSE; 353706f2543Smrg } 354706f2543Smrg else 355706f2543Smrg { 356706f2543Smrg screen->fb.byteStride = priv->fix.line_length; 357706f2543Smrg screen->fb.pixelStride = (priv->fix.line_length * 8 / 358706f2543Smrg priv->var.bits_per_pixel); 359706f2543Smrg screen->fb.frameBuffer = (CARD8 *) (priv->fb); 360706f2543Smrg } 361706f2543Smrg 362706f2543Smrg return TRUE; 363706f2543Smrg} 364706f2543Smrg 365706f2543Smrgstatic void 366706f2543SmrgfbdevSetScreenSizes (ScreenPtr pScreen) 367706f2543Smrg{ 368706f2543Smrg KdScreenPriv(pScreen); 369706f2543Smrg KdScreenInfo *screen = pScreenPriv->screen; 370706f2543Smrg FbdevScrPriv *scrpriv = screen->driver; 371706f2543Smrg FbdevPriv *priv = screen->card->driver; 372706f2543Smrg 373706f2543Smrg if (scrpriv->randr & (RR_Rotate_0|RR_Rotate_180)) 374706f2543Smrg { 375706f2543Smrg pScreen->width = priv->var.xres; 376706f2543Smrg pScreen->height = priv->var.yres; 377706f2543Smrg pScreen->mmWidth = screen->width_mm; 378706f2543Smrg pScreen->mmHeight = screen->height_mm; 379706f2543Smrg } 380706f2543Smrg else 381706f2543Smrg { 382706f2543Smrg pScreen->width = priv->var.yres; 383706f2543Smrg pScreen->height = priv->var.xres; 384706f2543Smrg pScreen->mmWidth = screen->height_mm; 385706f2543Smrg pScreen->mmHeight = screen->width_mm; 386706f2543Smrg } 387706f2543Smrg} 388706f2543Smrg 389706f2543Smrgstatic Bool 390706f2543SmrgfbdevUnmapFramebuffer (KdScreenInfo *screen) 391706f2543Smrg{ 392706f2543Smrg KdShadowFbFree (screen); 393706f2543Smrg return TRUE; 394706f2543Smrg} 395706f2543Smrg 396706f2543Smrgstatic Bool 397706f2543SmrgfbdevSetShadow (ScreenPtr pScreen) 398706f2543Smrg{ 399706f2543Smrg KdScreenPriv(pScreen); 400706f2543Smrg KdScreenInfo *screen = pScreenPriv->screen; 401706f2543Smrg FbdevScrPriv *scrpriv = screen->driver; 402706f2543Smrg FbdevPriv *priv = screen->card->driver; 403706f2543Smrg ShadowUpdateProc update; 404706f2543Smrg ShadowWindowProc window; 405706f2543Smrg int useYX = 0; 406706f2543Smrg 407706f2543Smrg#ifdef __arm__ 408706f2543Smrg /* Use variant copy routines that always read left to right in the 409706f2543Smrg shadow framebuffer. Reading vertical strips is exceptionally 410706f2543Smrg slow on XScale due to cache effects. */ 411706f2543Smrg useYX = 1; 412706f2543Smrg#endif 413706f2543Smrg 414706f2543Smrg window = fbdevWindowLinear; 415706f2543Smrg update = 0; 416706f2543Smrg if (scrpriv->randr) 417706f2543Smrg if (priv->var.bits_per_pixel == 16) { 418706f2543Smrg switch (scrpriv->randr) { 419706f2543Smrg case RR_Rotate_90: 420706f2543Smrg if (useYX) 421706f2543Smrg update = shadowUpdateRotate16_90YX; 422706f2543Smrg else 423706f2543Smrg update = shadowUpdateRotate16_90; 424706f2543Smrg break; 425706f2543Smrg case RR_Rotate_180: 426706f2543Smrg update = shadowUpdateRotate16_180; 427706f2543Smrg break; 428706f2543Smrg case RR_Rotate_270: 429706f2543Smrg if (useYX) 430706f2543Smrg update = shadowUpdateRotate16_270YX; 431706f2543Smrg else 432706f2543Smrg update = shadowUpdateRotate16_270; 433706f2543Smrg break; 434706f2543Smrg default: 435706f2543Smrg update = shadowUpdateRotate16; 436706f2543Smrg break; 437706f2543Smrg } 438706f2543Smrg } else 439706f2543Smrg update = shadowUpdateRotatePacked; 440706f2543Smrg else 441706f2543Smrg update = shadowUpdatePacked; 442706f2543Smrg return KdShadowSet (pScreen, scrpriv->randr, update, window); 443706f2543Smrg} 444706f2543Smrg 445706f2543Smrg 446706f2543Smrg#ifdef RANDR 447706f2543Smrgstatic Bool 448706f2543SmrgfbdevRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) 449706f2543Smrg{ 450706f2543Smrg KdScreenPriv(pScreen); 451706f2543Smrg KdScreenInfo *screen = pScreenPriv->screen; 452706f2543Smrg FbdevScrPriv *scrpriv = screen->driver; 453706f2543Smrg RRScreenSizePtr pSize; 454706f2543Smrg Rotation randr; 455706f2543Smrg int n; 456706f2543Smrg 457706f2543Smrg *rotations = RR_Rotate_All|RR_Reflect_All; 458706f2543Smrg 459706f2543Smrg for (n = 0; n < pScreen->numDepths; n++) 460706f2543Smrg if (pScreen->allowedDepths[n].numVids) 461706f2543Smrg break; 462706f2543Smrg if (n == pScreen->numDepths) 463706f2543Smrg return FALSE; 464706f2543Smrg 465706f2543Smrg pSize = RRRegisterSize (pScreen, 466706f2543Smrg screen->width, 467706f2543Smrg screen->height, 468706f2543Smrg screen->width_mm, 469706f2543Smrg screen->height_mm); 470706f2543Smrg 471706f2543Smrg randr = KdSubRotation (scrpriv->randr, screen->randr); 472706f2543Smrg 473706f2543Smrg RRSetCurrentConfig (pScreen, randr, 0, pSize); 474706f2543Smrg 475706f2543Smrg return TRUE; 476706f2543Smrg} 477706f2543Smrg 478706f2543Smrgstatic Bool 479706f2543SmrgfbdevRandRSetConfig (ScreenPtr pScreen, 480706f2543Smrg Rotation randr, 481706f2543Smrg int rate, 482706f2543Smrg RRScreenSizePtr pSize) 483706f2543Smrg{ 484706f2543Smrg KdScreenPriv(pScreen); 485706f2543Smrg KdScreenInfo *screen = pScreenPriv->screen; 486706f2543Smrg FbdevScrPriv *scrpriv = screen->driver; 487706f2543Smrg Bool wasEnabled = pScreenPriv->enabled; 488706f2543Smrg FbdevScrPriv oldscr; 489706f2543Smrg int oldwidth; 490706f2543Smrg int oldheight; 491706f2543Smrg int oldmmwidth; 492706f2543Smrg int oldmmheight; 493706f2543Smrg int newwidth, newheight; 494706f2543Smrg 495706f2543Smrg if (screen->randr & (RR_Rotate_0|RR_Rotate_180)) 496706f2543Smrg { 497706f2543Smrg newwidth = pSize->width; 498706f2543Smrg newheight = pSize->height; 499706f2543Smrg } 500706f2543Smrg else 501706f2543Smrg { 502706f2543Smrg newwidth = pSize->height; 503706f2543Smrg newheight = pSize->width; 504706f2543Smrg } 505706f2543Smrg 506706f2543Smrg if (wasEnabled) 507706f2543Smrg KdDisableScreen (pScreen); 508706f2543Smrg 509706f2543Smrg oldscr = *scrpriv; 510706f2543Smrg 511706f2543Smrg oldwidth = screen->width; 512706f2543Smrg oldheight = screen->height; 513706f2543Smrg oldmmwidth = pScreen->mmWidth; 514706f2543Smrg oldmmheight = pScreen->mmHeight; 515706f2543Smrg 516706f2543Smrg /* 517706f2543Smrg * Set new configuration 518706f2543Smrg */ 519706f2543Smrg 520706f2543Smrg scrpriv->randr = KdAddRotation (screen->randr, randr); 521706f2543Smrg 522706f2543Smrg fbdevUnmapFramebuffer (screen); 523706f2543Smrg 524706f2543Smrg if (!fbdevMapFramebuffer (screen)) 525706f2543Smrg goto bail4; 526706f2543Smrg 527706f2543Smrg KdShadowUnset (screen->pScreen); 528706f2543Smrg 529706f2543Smrg if (!fbdevSetShadow (screen->pScreen)) 530706f2543Smrg goto bail4; 531706f2543Smrg 532706f2543Smrg fbdevSetScreenSizes (screen->pScreen); 533706f2543Smrg 534706f2543Smrg /* 535706f2543Smrg * Set frame buffer mapping 536706f2543Smrg */ 537706f2543Smrg (*pScreen->ModifyPixmapHeader) (fbGetScreenPixmap (pScreen), 538706f2543Smrg pScreen->width, 539706f2543Smrg pScreen->height, 540706f2543Smrg screen->fb.depth, 541706f2543Smrg screen->fb.bitsPerPixel, 542706f2543Smrg screen->fb.byteStride, 543706f2543Smrg screen->fb.frameBuffer); 544706f2543Smrg 545706f2543Smrg /* set the subpixel order */ 546706f2543Smrg 547706f2543Smrg KdSetSubpixelOrder (pScreen, scrpriv->randr); 548706f2543Smrg if (wasEnabled) 549706f2543Smrg KdEnableScreen (pScreen); 550706f2543Smrg 551706f2543Smrg return TRUE; 552706f2543Smrg 553706f2543Smrgbail4: 554706f2543Smrg fbdevUnmapFramebuffer (screen); 555706f2543Smrg *scrpriv = oldscr; 556706f2543Smrg (void) fbdevMapFramebuffer (screen); 557706f2543Smrg pScreen->width = oldwidth; 558706f2543Smrg pScreen->height = oldheight; 559706f2543Smrg pScreen->mmWidth = oldmmwidth; 560706f2543Smrg pScreen->mmHeight = oldmmheight; 561706f2543Smrg 562706f2543Smrg if (wasEnabled) 563706f2543Smrg KdEnableScreen (pScreen); 564706f2543Smrg return FALSE; 565706f2543Smrg} 566706f2543Smrg 567706f2543Smrgstatic Bool 568706f2543SmrgfbdevRandRInit (ScreenPtr pScreen) 569706f2543Smrg{ 570706f2543Smrg rrScrPrivPtr pScrPriv; 571706f2543Smrg 572706f2543Smrg if (!RRScreenInit (pScreen)) 573706f2543Smrg return FALSE; 574706f2543Smrg 575706f2543Smrg pScrPriv = rrGetScrPriv(pScreen); 576706f2543Smrg pScrPriv->rrGetInfo = fbdevRandRGetInfo; 577706f2543Smrg pScrPriv->rrSetConfig = fbdevRandRSetConfig; 578706f2543Smrg return TRUE; 579706f2543Smrg} 580706f2543Smrg#endif 581706f2543Smrg 582706f2543Smrgstatic Bool 583706f2543SmrgfbdevCreateColormap (ColormapPtr pmap) 584706f2543Smrg{ 585706f2543Smrg ScreenPtr pScreen = pmap->pScreen; 586706f2543Smrg KdScreenPriv(pScreen); 587706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 588706f2543Smrg VisualPtr pVisual; 589706f2543Smrg int i; 590706f2543Smrg int nent; 591706f2543Smrg xColorItem *pdefs; 592706f2543Smrg 593706f2543Smrg switch (priv->fix.visual) { 594706f2543Smrg case FB_VISUAL_STATIC_PSEUDOCOLOR: 595706f2543Smrg pVisual = pmap->pVisual; 596706f2543Smrg nent = pVisual->ColormapEntries; 597706f2543Smrg pdefs = malloc(nent * sizeof (xColorItem)); 598706f2543Smrg if (!pdefs) 599706f2543Smrg return FALSE; 600706f2543Smrg for (i = 0; i < nent; i++) 601706f2543Smrg pdefs[i].pixel = i; 602706f2543Smrg fbdevGetColors (pScreen, nent, pdefs); 603706f2543Smrg for (i = 0; i < nent; i++) 604706f2543Smrg { 605706f2543Smrg pmap->red[i].co.local.red = pdefs[i].red; 606706f2543Smrg pmap->red[i].co.local.green = pdefs[i].green; 607706f2543Smrg pmap->red[i].co.local.blue = pdefs[i].blue; 608706f2543Smrg } 609706f2543Smrg free(pdefs); 610706f2543Smrg return TRUE; 611706f2543Smrg default: 612706f2543Smrg return fbInitializeColormap (pmap); 613706f2543Smrg } 614706f2543Smrg} 615706f2543Smrg 616706f2543SmrgBool 617706f2543SmrgfbdevInitScreen (ScreenPtr pScreen) 618706f2543Smrg{ 619706f2543Smrg#ifdef TOUCHSCREEN 620706f2543Smrg KdTsPhyScreen = pScreen->myNum; 621706f2543Smrg#endif 622706f2543Smrg 623706f2543Smrg pScreen->CreateColormap = fbdevCreateColormap; 624706f2543Smrg return TRUE; 625706f2543Smrg} 626706f2543Smrg 627706f2543SmrgBool 628706f2543SmrgfbdevFinishInitScreen (ScreenPtr pScreen) 629706f2543Smrg{ 630706f2543Smrg if (!shadowSetup (pScreen)) 631706f2543Smrg return FALSE; 632706f2543Smrg 633706f2543Smrg#ifdef RANDR 634706f2543Smrg if (!fbdevRandRInit (pScreen)) 635706f2543Smrg return FALSE; 636706f2543Smrg#endif 637706f2543Smrg 638706f2543Smrg return TRUE; 639706f2543Smrg} 640706f2543Smrg 641706f2543Smrg 642706f2543SmrgBool 643706f2543SmrgfbdevCreateResources (ScreenPtr pScreen) 644706f2543Smrg{ 645706f2543Smrg return fbdevSetShadow (pScreen); 646706f2543Smrg} 647706f2543Smrg 648706f2543Smrgvoid 649706f2543SmrgfbdevPreserve (KdCardInfo *card) 650706f2543Smrg{ 651706f2543Smrg} 652706f2543Smrg 653706f2543Smrgstatic int 654706f2543SmrgfbdevUpdateFbColormap(FbdevPriv *priv, int minidx, int maxidx) 655706f2543Smrg{ 656706f2543Smrg struct fb_cmap cmap; 657706f2543Smrg 658706f2543Smrg cmap.start = minidx; 659706f2543Smrg cmap.len = maxidx - minidx + 1; 660706f2543Smrg cmap.red = &priv->red[minidx]; 661706f2543Smrg cmap.green = &priv->green[minidx]; 662706f2543Smrg cmap.blue = &priv->blue[minidx]; 663706f2543Smrg cmap.transp = 0; 664706f2543Smrg 665706f2543Smrg return ioctl(priv->fd, FBIOPUTCMAP, &cmap); 666706f2543Smrg} 667706f2543Smrg 668706f2543SmrgBool 669706f2543SmrgfbdevEnable (ScreenPtr pScreen) 670706f2543Smrg{ 671706f2543Smrg KdScreenPriv(pScreen); 672706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 673706f2543Smrg int k; 674706f2543Smrg 675706f2543Smrg priv->var.activate = FB_ACTIVATE_NOW|FB_CHANGE_CMAP_VBL; 676706f2543Smrg 677706f2543Smrg /* display it on the LCD */ 678706f2543Smrg k = ioctl (priv->fd, FBIOPUT_VSCREENINFO, &priv->var); 679706f2543Smrg if (k < 0) 680706f2543Smrg { 681706f2543Smrg perror ("FBIOPUT_VSCREENINFO"); 682706f2543Smrg return FALSE; 683706f2543Smrg } 684706f2543Smrg 685706f2543Smrg if (priv->fix.visual == FB_VISUAL_DIRECTCOLOR) 686706f2543Smrg { 687706f2543Smrg int i; 688706f2543Smrg 689706f2543Smrg for (i = 0; 690706f2543Smrg i < (1 << priv->var.red.length) || 691706f2543Smrg i < (1 << priv->var.green.length) || 692706f2543Smrg i < (1 << priv->var.blue.length); i++) 693706f2543Smrg { 694706f2543Smrg priv->red[i] = i * 65535 / ((1 << priv->var.red.length) - 1); 695706f2543Smrg priv->green[i] = i * 65535 / ((1 << priv->var.green.length) - 1); 696706f2543Smrg priv->blue[i] = i * 65535 / ((1 << priv->var.blue.length) - 1); 697706f2543Smrg } 698706f2543Smrg 699706f2543Smrg fbdevUpdateFbColormap(priv, 0, i); 700706f2543Smrg } 701706f2543Smrg return TRUE; 702706f2543Smrg} 703706f2543Smrg 704706f2543SmrgBool 705706f2543SmrgfbdevDPMS (ScreenPtr pScreen, int mode) 706706f2543Smrg{ 707706f2543Smrg KdScreenPriv(pScreen); 708706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 709706f2543Smrg static int oldmode = -1; 710706f2543Smrg 711706f2543Smrg if (mode == oldmode) 712706f2543Smrg return TRUE; 713706f2543Smrg#ifdef FBIOPUT_POWERMODE 714706f2543Smrg if (ioctl (priv->fd, FBIOPUT_POWERMODE, &mode) >= 0) 715706f2543Smrg { 716706f2543Smrg oldmode = mode; 717706f2543Smrg return TRUE; 718706f2543Smrg } 719706f2543Smrg#endif 720706f2543Smrg#ifdef FBIOBLANK 721706f2543Smrg if (ioctl (priv->fd, FBIOBLANK, mode ? mode + 1 : 0) >= 0) 722706f2543Smrg { 723706f2543Smrg oldmode = mode; 724706f2543Smrg return TRUE; 725706f2543Smrg } 726706f2543Smrg#endif 727706f2543Smrg return FALSE; 728706f2543Smrg} 729706f2543Smrg 730706f2543Smrgvoid 731706f2543SmrgfbdevDisable (ScreenPtr pScreen) 732706f2543Smrg{ 733706f2543Smrg} 734706f2543Smrg 735706f2543Smrgvoid 736706f2543SmrgfbdevRestore (KdCardInfo *card) 737706f2543Smrg{ 738706f2543Smrg} 739706f2543Smrg 740706f2543Smrgvoid 741706f2543SmrgfbdevScreenFini (KdScreenInfo *screen) 742706f2543Smrg{ 743706f2543Smrg} 744706f2543Smrg 745706f2543Smrgvoid 746706f2543SmrgfbdevCardFini (KdCardInfo *card) 747706f2543Smrg{ 748706f2543Smrg FbdevPriv *priv = card->driver; 749706f2543Smrg 750706f2543Smrg munmap (priv->fb_base, priv->fix.smem_len); 751706f2543Smrg close (priv->fd); 752706f2543Smrg free(priv); 753706f2543Smrg} 754706f2543Smrg 755706f2543Smrg/* 756706f2543Smrg * Retrieve actual colormap and return selected n entries in pdefs. 757706f2543Smrg */ 758706f2543Smrgvoid 759706f2543SmrgfbdevGetColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 760706f2543Smrg{ 761706f2543Smrg KdScreenPriv(pScreen); 762706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 763706f2543Smrg struct fb_cmap cmap; 764706f2543Smrg int p; 765706f2543Smrg int k; 766706f2543Smrg int min, max; 767706f2543Smrg 768706f2543Smrg min = 256; 769706f2543Smrg max = 0; 770706f2543Smrg for (k = 0; k < n; k++) 771706f2543Smrg { 772706f2543Smrg if (pdefs[k].pixel < min) 773706f2543Smrg min = pdefs[k].pixel; 774706f2543Smrg if (pdefs[k].pixel > max) 775706f2543Smrg max = pdefs[k].pixel; 776706f2543Smrg } 777706f2543Smrg cmap.start = min; 778706f2543Smrg cmap.len = max - min + 1; 779706f2543Smrg cmap.red = &priv->red[min]; 780706f2543Smrg cmap.green = &priv->green[min]; 781706f2543Smrg cmap.blue = &priv->blue[min]; 782706f2543Smrg cmap.transp = 0; 783706f2543Smrg k = ioctl (priv->fd, FBIOGETCMAP, &cmap); 784706f2543Smrg if (k < 0) 785706f2543Smrg { 786706f2543Smrg perror ("can't get colormap"); 787706f2543Smrg return; 788706f2543Smrg } 789706f2543Smrg while (n--) 790706f2543Smrg { 791706f2543Smrg p = pdefs->pixel; 792706f2543Smrg pdefs->red = priv->red[p]; 793706f2543Smrg pdefs->green = priv->green[p]; 794706f2543Smrg pdefs->blue = priv->blue[p]; 795706f2543Smrg pdefs++; 796706f2543Smrg } 797706f2543Smrg} 798706f2543Smrg 799706f2543Smrg/* 800706f2543Smrg * Change colormap by updating n entries described in pdefs. 801706f2543Smrg */ 802706f2543Smrgvoid 803706f2543SmrgfbdevPutColors (ScreenPtr pScreen, int n, xColorItem *pdefs) 804706f2543Smrg{ 805706f2543Smrg KdScreenPriv(pScreen); 806706f2543Smrg FbdevPriv *priv = pScreenPriv->card->driver; 807706f2543Smrg int p; 808706f2543Smrg int min, max; 809706f2543Smrg 810706f2543Smrg min = 256; 811706f2543Smrg max = 0; 812706f2543Smrg while (n--) 813706f2543Smrg { 814706f2543Smrg p = pdefs->pixel; 815706f2543Smrg priv->red[p] = pdefs->red; 816706f2543Smrg priv->green[p] = pdefs->green; 817706f2543Smrg priv->blue[p] = pdefs->blue; 818706f2543Smrg if (p < min) 819706f2543Smrg min = p; 820706f2543Smrg if (p > max) 821706f2543Smrg max = p; 822706f2543Smrg pdefs++; 823706f2543Smrg } 824706f2543Smrg 825706f2543Smrg fbdevUpdateFbColormap(priv, min, max); 826706f2543Smrg} 827