15a112b11Smrg/* all drivers need this */ 205b261ecSmrg#ifdef HAVE_XORG_CONFIG_H 305b261ecSmrg#include <xorg-config.h> 405b261ecSmrg#endif 505b261ecSmrg 605b261ecSmrg#include <string.h> 705b261ecSmrg 805b261ecSmrg#include "xf86.h" 9188eae84Sprlw#include "xf86Modes.h" 1005b261ecSmrg#include "xf86_OSproc.h" 1105b261ecSmrg 1205b261ecSmrg/* pci stuff */ 1305b261ecSmrg#include "xf86Pci.h" 1405b261ecSmrg 1505b261ecSmrg#include "xf86cmap.h" 1605b261ecSmrg 1705b261ecSmrg#include "fbdevhw.h" 1805b261ecSmrg#include "fbpriv.h" 1905b261ecSmrg#include "globals.h" 206747b715Smrg#include <X11/extensions/dpmsconst.h> 2105b261ecSmrg 2205b261ecSmrg#define PAGE_MASK (~(getpagesize() - 1)) 2305b261ecSmrg 24f7df2e56Smrgstatic XF86ModuleVersionInfo fbdevHWVersRec = { 25f7df2e56Smrg "fbdevhw", 26f7df2e56Smrg MODULEVENDORSTRING, 27f7df2e56Smrg MODINFOSTRING1, 28f7df2e56Smrg MODINFOSTRING2, 29f7df2e56Smrg XORG_VERSION_CURRENT, 30f7df2e56Smrg 0, 0, 2, 31f7df2e56Smrg ABI_CLASS_VIDEODRV, 32f7df2e56Smrg ABI_VIDEODRV_VERSION, 33f7df2e56Smrg MOD_CLASS_NONE, 34f7df2e56Smrg {0, 0, 0, 0} 3505b261ecSmrg}; 3605b261ecSmrg 3705b261ecSmrg_X_EXPORT XF86ModuleData fbdevhwModuleData = { 3805b261ecSmrg &fbdevHWVersRec, 399ace9065Smrg NULL, 4005b261ecSmrg NULL 4105b261ecSmrg}; 4205b261ecSmrg 4305b261ecSmrg#include <fcntl.h> 4405b261ecSmrg#include <errno.h> 4505b261ecSmrg#include <sys/mman.h> 4605b261ecSmrg#include <sys/ioctl.h> 4705b261ecSmrg#include <stdio.h> 4805b261ecSmrg#include <stdlib.h> 4905b261ecSmrg#include <unistd.h> 5005b261ecSmrg 5105b261ecSmrg/* -------------------------------------------------------------------- */ 5205b261ecSmrg/* our private data, and two functions to allocate/free this */ 5305b261ecSmrg 5405b261ecSmrg#define FBDEVHWPTRLVAL(p) (p)->privates[fbdevHWPrivateIndex].ptr 5505b261ecSmrg#define FBDEVHWPTR(p) ((fbdevHWPtr)(FBDEVHWPTRLVAL(p))) 5605b261ecSmrg 5705b261ecSmrgstatic int fbdevHWPrivateIndex = -1; 5805b261ecSmrg 5905b261ecSmrgtypedef struct { 60f7df2e56Smrg /* framebuffer device: filename (/dev/fb*), handle, more */ 61f7df2e56Smrg char *device; 62f7df2e56Smrg int fd; 63f7df2e56Smrg void *fbmem; 64f7df2e56Smrg unsigned int fbmem_len; 65f7df2e56Smrg unsigned int fboff; 66f7df2e56Smrg char *mmio; 67f7df2e56Smrg unsigned int mmio_len; 68f7df2e56Smrg 69f7df2e56Smrg /* current hardware state */ 70f7df2e56Smrg struct fb_fix_screeninfo fix; 71f7df2e56Smrg struct fb_var_screeninfo var; 72f7df2e56Smrg 73f7df2e56Smrg /* saved video mode */ 74f7df2e56Smrg struct fb_var_screeninfo saved_var; 75f7df2e56Smrg 76f7df2e56Smrg /* buildin video mode */ 77f7df2e56Smrg DisplayModeRec buildin; 78f7df2e56Smrg 79f7df2e56Smrg /* disable non-fatal unsupported ioctls */ 80f7df2e56Smrg CARD32 unsupported_ioctls; 8105b261ecSmrg} fbdevHWRec, *fbdevHWPtr; 8205b261ecSmrg 83f7df2e56Smrgenum { 84f7df2e56Smrg FBIOBLANK_UNSUPPORTED = 0, 85f7df2e56Smrg}; 86f7df2e56Smrg 8705b261ecSmrgBool 8805b261ecSmrgfbdevHWGetRec(ScrnInfoPtr pScrn) 8905b261ecSmrg{ 90f7df2e56Smrg if (fbdevHWPrivateIndex < 0) 91f7df2e56Smrg fbdevHWPrivateIndex = xf86AllocateScrnInfoPrivateIndex(); 9205b261ecSmrg 93f7df2e56Smrg if (FBDEVHWPTR(pScrn) != NULL) 94f7df2e56Smrg return TRUE; 95f7df2e56Smrg 96f7df2e56Smrg FBDEVHWPTRLVAL(pScrn) = xnfcalloc(sizeof(fbdevHWRec), 1); 97f7df2e56Smrg return TRUE; 9805b261ecSmrg} 9905b261ecSmrg 10005b261ecSmrgvoid 10105b261ecSmrgfbdevHWFreeRec(ScrnInfoPtr pScrn) 10205b261ecSmrg{ 103f7df2e56Smrg if (fbdevHWPrivateIndex < 0) 104f7df2e56Smrg return; 105f7df2e56Smrg free(FBDEVHWPTR(pScrn)); 106f7df2e56Smrg FBDEVHWPTRLVAL(pScrn) = NULL; 10705b261ecSmrg} 10805b261ecSmrg 1096747b715Smrgint 1106747b715SmrgfbdevHWGetFD(ScrnInfoPtr pScrn) 1116747b715Smrg{ 1126747b715Smrg fbdevHWPtr fPtr; 1136747b715Smrg 1146747b715Smrg fbdevHWGetRec(pScrn); 1156747b715Smrg fPtr = FBDEVHWPTR(pScrn); 1166747b715Smrg 1176747b715Smrg return fPtr->fd; 1186747b715Smrg} 1196747b715Smrg 12005b261ecSmrg/* -------------------------------------------------------------------- */ 1215a112b11Smrg/* some helpers for printing debug information */ 12205b261ecSmrg 1237e31ba66Smrg#ifdef DEBUG 12405b261ecSmrgstatic void 125f7df2e56Smrgprint_fbdev_mode(const char *txt, struct fb_var_screeninfo *var) 12605b261ecSmrg{ 127f7df2e56Smrg ErrorF("fbdev %s mode:\t%d %d %d %d %d %d %d %d %d %d %d:%d:%d\n", 128f7df2e56Smrg txt, var->pixclock, 129f7df2e56Smrg var->xres, var->right_margin, var->hsync_len, var->left_margin, 130f7df2e56Smrg var->yres, var->lower_margin, var->vsync_len, var->upper_margin, 131f7df2e56Smrg var->bits_per_pixel, 132f7df2e56Smrg var->red.length, var->green.length, var->blue.length); 13305b261ecSmrg} 13405b261ecSmrg 13505b261ecSmrgstatic void 136f7df2e56Smrgprint_xfree_mode(const char *txt, DisplayModePtr mode) 13705b261ecSmrg{ 138f7df2e56Smrg ErrorF("xfree %s mode:\t%d %d %d %d %d %d %d %d %d\n", 139f7df2e56Smrg txt, mode->Clock, 140f7df2e56Smrg mode->HDisplay, mode->HSyncStart, mode->HSyncEnd, mode->HTotal, 141f7df2e56Smrg mode->VDisplay, mode->VSyncStart, mode->VSyncEnd, mode->VTotal); 14205b261ecSmrg} 14305b261ecSmrg#endif 14405b261ecSmrg 14505b261ecSmrg/* -------------------------------------------------------------------- */ 14605b261ecSmrg/* Convert timings between the XFree and the Frame Buffer Device */ 14705b261ecSmrg 14805b261ecSmrgstatic void 14905b261ecSmrgxfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var) 15005b261ecSmrg{ 151f7df2e56Smrg var->xres_virtual = pScrn->displayWidth ? pScrn->displayWidth : 152f7df2e56Smrg pScrn->virtualX; 153f7df2e56Smrg var->yres_virtual = pScrn->virtualY; 154f7df2e56Smrg var->bits_per_pixel = pScrn->bitsPerPixel; 155f7df2e56Smrg if (pScrn->defaultVisual == TrueColor || 156f7df2e56Smrg pScrn->defaultVisual == DirectColor) { 157f7df2e56Smrg var->red.length = pScrn->weight.red; 158f7df2e56Smrg var->green.length = pScrn->weight.green; 159f7df2e56Smrg var->blue.length = pScrn->weight.blue; 160f7df2e56Smrg } 161f7df2e56Smrg else { 162f7df2e56Smrg var->red.length = 8; 163f7df2e56Smrg var->green.length = 8; 164f7df2e56Smrg var->blue.length = 8; 165f7df2e56Smrg } 16605b261ecSmrg} 16705b261ecSmrg 16805b261ecSmrgstatic void 16905b261ecSmrgxfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var) 17005b261ecSmrg{ 171f7df2e56Smrg var->xres = mode->HDisplay; 172f7df2e56Smrg var->yres = mode->VDisplay; 173f7df2e56Smrg if (var->xres_virtual < var->xres) 174f7df2e56Smrg var->xres_virtual = var->xres; 175f7df2e56Smrg if (var->yres_virtual < var->yres) 176f7df2e56Smrg var->yres_virtual = var->yres; 177f7df2e56Smrg var->xoffset = var->yoffset = 0; 178f7df2e56Smrg var->pixclock = mode->Clock ? 1000000000 / mode->Clock : 0; 179f7df2e56Smrg var->right_margin = mode->HSyncStart - mode->HDisplay; 180f7df2e56Smrg var->hsync_len = mode->HSyncEnd - mode->HSyncStart; 181f7df2e56Smrg var->left_margin = mode->HTotal - mode->HSyncEnd; 182f7df2e56Smrg var->lower_margin = mode->VSyncStart - mode->VDisplay; 183f7df2e56Smrg var->vsync_len = mode->VSyncEnd - mode->VSyncStart; 184f7df2e56Smrg var->upper_margin = mode->VTotal - mode->VSyncEnd; 185f7df2e56Smrg var->sync = 0; 186f7df2e56Smrg if (mode->Flags & V_PHSYNC) 187f7df2e56Smrg var->sync |= FB_SYNC_HOR_HIGH_ACT; 188f7df2e56Smrg if (mode->Flags & V_PVSYNC) 189f7df2e56Smrg var->sync |= FB_SYNC_VERT_HIGH_ACT; 190f7df2e56Smrg if (mode->Flags & V_PCSYNC) 191f7df2e56Smrg var->sync |= FB_SYNC_COMP_HIGH_ACT; 192f7df2e56Smrg if (mode->Flags & V_BCAST) 193f7df2e56Smrg var->sync |= FB_SYNC_BROADCAST; 194f7df2e56Smrg if (mode->Flags & V_INTERLACE) 195f7df2e56Smrg var->vmode = FB_VMODE_INTERLACED; 196f7df2e56Smrg else if (mode->Flags & V_DBLSCAN) 197f7df2e56Smrg var->vmode = FB_VMODE_DOUBLE; 198f7df2e56Smrg else 199f7df2e56Smrg var->vmode = FB_VMODE_NONINTERLACED; 20005b261ecSmrg} 20105b261ecSmrg 20205b261ecSmrgstatic Bool 20305b261ecSmrgfbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req) 20405b261ecSmrg{ 205f7df2e56Smrg return (set->xres_virtual >= req->xres_virtual && 206f7df2e56Smrg set->yres_virtual >= req->yres_virtual && 207f7df2e56Smrg set->bits_per_pixel == req->bits_per_pixel && 208f7df2e56Smrg set->red.length == req->red.length && 209f7df2e56Smrg set->green.length == req->green.length && 210f7df2e56Smrg set->blue.length == req->blue.length && 211f7df2e56Smrg set->xres == req->xres && set->yres == req->yres && 212f7df2e56Smrg set->right_margin == req->right_margin && 213f7df2e56Smrg set->hsync_len == req->hsync_len && 214f7df2e56Smrg set->left_margin == req->left_margin && 215f7df2e56Smrg set->lower_margin == req->lower_margin && 216f7df2e56Smrg set->vsync_len == req->vsync_len && 217f7df2e56Smrg set->upper_margin == req->upper_margin && 218f7df2e56Smrg set->sync == req->sync && set->vmode == req->vmode); 21905b261ecSmrg} 22005b261ecSmrg 22105b261ecSmrgstatic void 22205b261ecSmrgfbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode) 22305b261ecSmrg{ 224f7df2e56Smrg mode->Clock = var->pixclock ? 1000000000 / var->pixclock : 0; 225f7df2e56Smrg mode->HDisplay = var->xres; 226f7df2e56Smrg mode->HSyncStart = mode->HDisplay + var->right_margin; 227f7df2e56Smrg mode->HSyncEnd = mode->HSyncStart + var->hsync_len; 228f7df2e56Smrg mode->HTotal = mode->HSyncEnd + var->left_margin; 229f7df2e56Smrg mode->VDisplay = var->yres; 230f7df2e56Smrg mode->VSyncStart = mode->VDisplay + var->lower_margin; 231f7df2e56Smrg mode->VSyncEnd = mode->VSyncStart + var->vsync_len; 232f7df2e56Smrg mode->VTotal = mode->VSyncEnd + var->upper_margin; 233f7df2e56Smrg mode->Flags = 0; 234f7df2e56Smrg mode->Flags |= var->sync & FB_SYNC_HOR_HIGH_ACT ? V_PHSYNC : V_NHSYNC; 235f7df2e56Smrg mode->Flags |= var->sync & FB_SYNC_VERT_HIGH_ACT ? V_PVSYNC : V_NVSYNC; 236f7df2e56Smrg mode->Flags |= var->sync & FB_SYNC_COMP_HIGH_ACT ? V_PCSYNC : V_NCSYNC; 237f7df2e56Smrg if (var->sync & FB_SYNC_BROADCAST) 238f7df2e56Smrg mode->Flags |= V_BCAST; 239f7df2e56Smrg if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_INTERLACED) 240f7df2e56Smrg mode->Flags |= V_INTERLACE; 241f7df2e56Smrg else if ((var->vmode & FB_VMODE_MASK) == FB_VMODE_DOUBLE) 242f7df2e56Smrg mode->Flags |= V_DBLSCAN; 243f7df2e56Smrg mode->SynthClock = mode->Clock; 244f7df2e56Smrg mode->CrtcHDisplay = mode->HDisplay; 245f7df2e56Smrg mode->CrtcHSyncStart = mode->HSyncStart; 246f7df2e56Smrg mode->CrtcHSyncEnd = mode->HSyncEnd; 247f7df2e56Smrg mode->CrtcHTotal = mode->HTotal; 248f7df2e56Smrg mode->CrtcVDisplay = mode->VDisplay; 249f7df2e56Smrg mode->CrtcVSyncStart = mode->VSyncStart; 250f7df2e56Smrg mode->CrtcVSyncEnd = mode->VSyncEnd; 251f7df2e56Smrg mode->CrtcVTotal = mode->VTotal; 252f7df2e56Smrg mode->CrtcHAdjusted = FALSE; 253f7df2e56Smrg mode->CrtcVAdjusted = FALSE; 25405b261ecSmrg} 25505b261ecSmrg 25605b261ecSmrg/* -------------------------------------------------------------------- */ 25705b261ecSmrg/* open correct framebuffer device */ 25805b261ecSmrg 2594642e01fSmrg/** 260f7df2e56Smrg * Try to find the framebuffer device for a given PCI device 2614642e01fSmrg */ 26205b261ecSmrgstatic int 263f7df2e56Smrgfbdev_open_pci(struct pci_device *pPci, char **namep) 26405b261ecSmrg{ 265f7df2e56Smrg struct fb_fix_screeninfo fix; 266f7df2e56Smrg char filename[256]; 267f7df2e56Smrg int fd, i; 2684642e01fSmrg 2694642e01fSmrg for (i = 0; i < 8; i++) { 270f7df2e56Smrg snprintf(filename, sizeof(filename), 271f7df2e56Smrg "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics/fb%d", 272f7df2e56Smrg pPci->domain, pPci->bus, pPci->dev, pPci->func, i); 2734642e01fSmrg 274f7df2e56Smrg fd = open(filename, O_RDONLY, 0); 275b1d344b3Smrg if (fd < 0) { 276f7df2e56Smrg snprintf(filename, sizeof(filename), 277f7df2e56Smrg "/sys/bus/pci/devices/%04x:%02x:%02x.%d/graphics:fb%d", 278f7df2e56Smrg pPci->domain, pPci->bus, pPci->dev, pPci->func, i); 279b1d344b3Smrg fd = open(filename, O_RDONLY, 0); 280b1d344b3Smrg } 281f7df2e56Smrg if (fd >= 0) { 282f7df2e56Smrg close(fd); 283f7df2e56Smrg snprintf(filename, sizeof(filename), "/dev/fb%d", i); 284f7df2e56Smrg 285f7df2e56Smrg fd = open(filename, O_RDWR, 0); 286f7df2e56Smrg if (fd != -1) { 287f7df2e56Smrg if (ioctl(fd, FBIOGET_FSCREENINFO, (void *) &fix) != -1) { 288f7df2e56Smrg if (namep) { 289f7df2e56Smrg *namep = xnfalloc(16); 290f7df2e56Smrg strncpy(*namep, fix.id, 16); 291f7df2e56Smrg } 292f7df2e56Smrg 293f7df2e56Smrg return fd; 294f7df2e56Smrg } 295f7df2e56Smrg close(fd); 296f7df2e56Smrg } 297f7df2e56Smrg } 2984642e01fSmrg } 2994642e01fSmrg 3004642e01fSmrg if (namep) 301f7df2e56Smrg *namep = NULL; 3024642e01fSmrg 3039ace9065Smrg xf86DrvMsg(-1, X_ERROR, "Unable to find a valid framebuffer device\n"); 3044642e01fSmrg return -1; 30505b261ecSmrg} 30605b261ecSmrg 30705b261ecSmrgstatic int 308f7df2e56Smrgfbdev_open(int scrnIndex, const char *dev, char **namep) 309f7df2e56Smrg{ 310f7df2e56Smrg struct fb_fix_screeninfo fix; 311f7df2e56Smrg int fd; 312f7df2e56Smrg 313f7df2e56Smrg /* try argument (from XF86Config) first */ 314f7df2e56Smrg if (dev) { 315f7df2e56Smrg fd = open(dev, O_RDWR, 0); 316f7df2e56Smrg } 317f7df2e56Smrg else { 318f7df2e56Smrg /* second: environment variable */ 319f7df2e56Smrg dev = getenv("FRAMEBUFFER"); 320f7df2e56Smrg if ((NULL == dev) || ((fd = open(dev, O_RDWR, 0)) == -1)) { 321f7df2e56Smrg /* last try: default device */ 322f7df2e56Smrg dev = "/dev/fb0"; 323f7df2e56Smrg fd = open(dev, O_RDWR, 0); 324f7df2e56Smrg } 325f7df2e56Smrg } 326f7df2e56Smrg 327f7df2e56Smrg if (fd == -1) { 328f7df2e56Smrg xf86DrvMsg(scrnIndex, X_ERROR, "open %s: %s\n", dev, strerror(errno)); 329f7df2e56Smrg return -1; 330f7df2e56Smrg } 331f7df2e56Smrg 3327e31ba66Smrg /* only touch non-PCI devices on this path */ 3337e31ba66Smrg { 3345a112b11Smrg char buf[PATH_MAX] = {0}; 3357e31ba66Smrg char *sysfs_path = NULL; 3367e31ba66Smrg char *node = strrchr(dev, '/') + 1; 3377e31ba66Smrg 338d566a54bSmrg if (asprintf(&sysfs_path, "/sys/class/graphics/%s/device/subsystem", node) < 0 || 3395a112b11Smrg readlink(sysfs_path, buf, sizeof(buf) - 1) < 0 || 340d566a54bSmrg strstr(buf, "bus/pci")) { 3417e31ba66Smrg free(sysfs_path); 3427e31ba66Smrg close(fd); 3437e31ba66Smrg return -1; 3447e31ba66Smrg } 3457e31ba66Smrg free(sysfs_path); 3467e31ba66Smrg } 3477e31ba66Smrg 348f7df2e56Smrg if (namep) { 349f7df2e56Smrg if (-1 == ioctl(fd, FBIOGET_FSCREENINFO, (void *) (&fix))) { 350f7df2e56Smrg *namep = NULL; 351f7df2e56Smrg xf86DrvMsg(scrnIndex, X_ERROR, 352f7df2e56Smrg "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); 353f7df2e56Smrg return -1; 354f7df2e56Smrg } 355f7df2e56Smrg else { 356f7df2e56Smrg *namep = xnfalloc(16); 357f7df2e56Smrg strncpy(*namep, fix.id, 16); 358f7df2e56Smrg } 359f7df2e56Smrg } 360f7df2e56Smrg return fd; 36105b261ecSmrg} 36205b261ecSmrg 36305b261ecSmrg/* -------------------------------------------------------------------- */ 36405b261ecSmrg 36505b261ecSmrgBool 366f7df2e56SmrgfbdevHWProbe(struct pci_device *pPci, char *device, char **namep) 36705b261ecSmrg{ 368f7df2e56Smrg int fd; 36905b261ecSmrg 370f7df2e56Smrg if (pPci) 371f7df2e56Smrg fd = fbdev_open_pci(pPci, namep); 372f7df2e56Smrg else 373f7df2e56Smrg fd = fbdev_open(-1, device, namep); 37405b261ecSmrg 375f7df2e56Smrg if (-1 == fd) 376f7df2e56Smrg return FALSE; 377f7df2e56Smrg close(fd); 378f7df2e56Smrg return TRUE; 37905b261ecSmrg} 38005b261ecSmrg 38105b261ecSmrgBool 382f7df2e56SmrgfbdevHWInit(ScrnInfoPtr pScrn, struct pci_device *pPci, char *device) 383f7df2e56Smrg{ 384f7df2e56Smrg fbdevHWPtr fPtr; 385f7df2e56Smrg 386f7df2e56Smrg fbdevHWGetRec(pScrn); 387f7df2e56Smrg fPtr = FBDEVHWPTR(pScrn); 388f7df2e56Smrg 389f7df2e56Smrg /* open device */ 390f7df2e56Smrg if (pPci) 391f7df2e56Smrg fPtr->fd = fbdev_open_pci(pPci, NULL); 392f7df2e56Smrg else 393f7df2e56Smrg fPtr->fd = fbdev_open(pScrn->scrnIndex, device, NULL); 394f7df2e56Smrg if (-1 == fPtr->fd) { 395f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 396f7df2e56Smrg "Failed to open framebuffer device, consult warnings" 397f7df2e56Smrg " and/or errors above for possible reasons\n" 398f7df2e56Smrg "\t(you may have to look at the server log to see" 399f7df2e56Smrg " warnings)\n"); 400f7df2e56Smrg return FALSE; 401f7df2e56Smrg } 402f7df2e56Smrg 403f7df2e56Smrg /* get current fb device settings */ 404f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOGET_FSCREENINFO, (void *) (&fPtr->fix))) { 405f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 406f7df2e56Smrg "ioctl FBIOGET_FSCREENINFO: %s\n", strerror(errno)); 407f7df2e56Smrg return FALSE; 408f7df2e56Smrg } 409f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *) (&fPtr->var))) { 410f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 411f7df2e56Smrg "ioctl FBIOGET_VSCREENINFO: %s\n", strerror(errno)); 412f7df2e56Smrg return FALSE; 413f7df2e56Smrg } 414f7df2e56Smrg 415f7df2e56Smrg /* we can use the current settings as "buildin mode" */ 416f7df2e56Smrg fbdev2xfree_timing(&fPtr->var, &fPtr->buildin); 417f7df2e56Smrg fPtr->buildin.name = "current"; 418f7df2e56Smrg fPtr->buildin.next = &fPtr->buildin; 419f7df2e56Smrg fPtr->buildin.prev = &fPtr->buildin; 420f7df2e56Smrg fPtr->buildin.type |= M_T_BUILTIN; 421f7df2e56Smrg 422f7df2e56Smrg return TRUE; 423f7df2e56Smrg} 424f7df2e56Smrg 425f7df2e56Smrgchar * 42605b261ecSmrgfbdevHWGetName(ScrnInfoPtr pScrn) 42705b261ecSmrg{ 428f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 429f7df2e56Smrg 430f7df2e56Smrg return fPtr->fix.id; 43105b261ecSmrg} 43205b261ecSmrg 43305b261ecSmrgint 43405b261ecSmrgfbdevHWGetDepth(ScrnInfoPtr pScrn, int *fbbpp) 43505b261ecSmrg{ 436f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 43705b261ecSmrg 438f7df2e56Smrg if (fbbpp) 439f7df2e56Smrg *fbbpp = fPtr->var.bits_per_pixel; 44005b261ecSmrg 441f7df2e56Smrg if (fPtr->fix.visual == FB_VISUAL_TRUECOLOR || 442f7df2e56Smrg fPtr->fix.visual == FB_VISUAL_DIRECTCOLOR) 443f7df2e56Smrg return fPtr->var.red.length + fPtr->var.green.length + 444f7df2e56Smrg fPtr->var.blue.length; 445f7df2e56Smrg else 446f7df2e56Smrg return fPtr->var.bits_per_pixel; 44705b261ecSmrg} 44805b261ecSmrg 44905b261ecSmrgint 45005b261ecSmrgfbdevHWGetLineLength(ScrnInfoPtr pScrn) 45105b261ecSmrg{ 452f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 45305b261ecSmrg 454f7df2e56Smrg if (fPtr->fix.line_length) 455f7df2e56Smrg return fPtr->fix.line_length; 456f7df2e56Smrg else 457f7df2e56Smrg return fPtr->var.xres_virtual * fPtr->var.bits_per_pixel / 8; 45805b261ecSmrg} 45905b261ecSmrg 46005b261ecSmrgint 46105b261ecSmrgfbdevHWGetType(ScrnInfoPtr pScrn) 46205b261ecSmrg{ 463f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 464f7df2e56Smrg 465f7df2e56Smrg return fPtr->fix.type; 46605b261ecSmrg} 46705b261ecSmrg 46805b261ecSmrgint 46905b261ecSmrgfbdevHWGetVidmem(ScrnInfoPtr pScrn) 47005b261ecSmrg{ 471f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 472f7df2e56Smrg 473f7df2e56Smrg return fPtr->fix.smem_len; 47405b261ecSmrg} 47505b261ecSmrg 47605b261ecSmrgstatic Bool 47705b261ecSmrgfbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check) 47805b261ecSmrg{ 479f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 480f7df2e56Smrg struct fb_var_screeninfo req_var = fPtr->var, set_var; 48105b261ecSmrg 482f7df2e56Smrg xfree2fbdev_fblayout(pScrn, &req_var); 483f7df2e56Smrg xfree2fbdev_timing(mode, &req_var); 48405b261ecSmrg 4857e31ba66Smrg#ifdef DEBUG 486f7df2e56Smrg print_xfree_mode("init", mode); 487f7df2e56Smrg print_fbdev_mode("init", &req_var); 48805b261ecSmrg#endif 48905b261ecSmrg 490f7df2e56Smrg set_var = req_var; 49105b261ecSmrg 492f7df2e56Smrg if (check) 493f7df2e56Smrg set_var.activate = FB_ACTIVATE_TEST; 49405b261ecSmrg 495f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *) (&set_var))) { 496f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 497f7df2e56Smrg "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); 498f7df2e56Smrg return FALSE; 499f7df2e56Smrg } 50005b261ecSmrg 501f7df2e56Smrg if (!fbdev_modes_equal(&set_var, &req_var)) { 502f7df2e56Smrg if (!check) 503f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 504f7df2e56Smrg "FBIOPUT_VSCREENINFO succeeded but modified " "mode\n"); 5057e31ba66Smrg#ifdef DEBUG 506f7df2e56Smrg print_fbdev_mode("returned", &set_var); 50705b261ecSmrg#endif 508f7df2e56Smrg return FALSE; 509f7df2e56Smrg } 51005b261ecSmrg 511f7df2e56Smrg if (!check) 512f7df2e56Smrg fPtr->var = set_var; 51305b261ecSmrg 514f7df2e56Smrg return TRUE; 51505b261ecSmrg} 51605b261ecSmrg 51705b261ecSmrgvoid 51805b261ecSmrgfbdevHWSetVideoModes(ScrnInfoPtr pScrn) 51905b261ecSmrg{ 520f7df2e56Smrg const char **modename; 521f7df2e56Smrg DisplayModePtr mode, this, last = pScrn->modes; 522f7df2e56Smrg 523f7df2e56Smrg if (NULL == pScrn->display->modes) 524f7df2e56Smrg return; 525f7df2e56Smrg 526f7df2e56Smrg pScrn->virtualX = pScrn->display->virtualX; 527f7df2e56Smrg pScrn->virtualY = pScrn->display->virtualY; 528f7df2e56Smrg 529f7df2e56Smrg for (modename = pScrn->display->modes; *modename != NULL; modename++) { 530f7df2e56Smrg for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next) { 531f7df2e56Smrg if (0 == strcmp(mode->name, *modename)) { 532f7df2e56Smrg if (fbdevHWSetMode(pScrn, mode, TRUE)) 533f7df2e56Smrg break; 534f7df2e56Smrg 535f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 536f7df2e56Smrg "\tmode \"%s\" test failed\n", *modename); 537f7df2e56Smrg } 538f7df2e56Smrg } 539f7df2e56Smrg 540f7df2e56Smrg if (NULL == mode) { 541f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 542f7df2e56Smrg "\tmode \"%s\" not found\n", *modename); 543f7df2e56Smrg continue; 544f7df2e56Smrg } 545f7df2e56Smrg 546f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, "\tmode \"%s\" ok\n", *modename); 547f7df2e56Smrg 548f7df2e56Smrg if (pScrn->virtualX < mode->HDisplay) 549f7df2e56Smrg pScrn->virtualX = mode->HDisplay; 550f7df2e56Smrg if (pScrn->virtualY < mode->VDisplay) 551f7df2e56Smrg pScrn->virtualY = mode->VDisplay; 552f7df2e56Smrg 553f7df2e56Smrg if (NULL == pScrn->modes) { 554f7df2e56Smrg this = pScrn->modes = xf86DuplicateMode(mode); 555f7df2e56Smrg this->next = this; 556f7df2e56Smrg this->prev = this; 557f7df2e56Smrg } 558f7df2e56Smrg else { 559f7df2e56Smrg this = xf86DuplicateMode(mode); 560f7df2e56Smrg this->next = pScrn->modes; 561f7df2e56Smrg this->prev = last; 562f7df2e56Smrg last->next = this; 563f7df2e56Smrg pScrn->modes->prev = this; 564f7df2e56Smrg } 565f7df2e56Smrg last = this; 566f7df2e56Smrg } 56705b261ecSmrg} 56805b261ecSmrg 56905b261ecSmrgDisplayModePtr 57005b261ecSmrgfbdevHWGetBuildinMode(ScrnInfoPtr pScrn) 57105b261ecSmrg{ 572f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 573f7df2e56Smrg 574f7df2e56Smrg return &fPtr->buildin; 57505b261ecSmrg} 57605b261ecSmrg 57705b261ecSmrgvoid 57805b261ecSmrgfbdevHWUseBuildinMode(ScrnInfoPtr pScrn) 57905b261ecSmrg{ 580f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 58105b261ecSmrg 582f7df2e56Smrg pScrn->modes = &fPtr->buildin; 583f7df2e56Smrg pScrn->virtualX = pScrn->display->virtualX; 584f7df2e56Smrg pScrn->virtualY = pScrn->display->virtualY; 585f7df2e56Smrg if (pScrn->virtualX < fPtr->buildin.HDisplay) 586f7df2e56Smrg pScrn->virtualX = fPtr->buildin.HDisplay; 587f7df2e56Smrg if (pScrn->virtualY < fPtr->buildin.VDisplay) 588f7df2e56Smrg pScrn->virtualY = fPtr->buildin.VDisplay; 58905b261ecSmrg} 59005b261ecSmrg 59105b261ecSmrg/* -------------------------------------------------------------------- */ 59205b261ecSmrg 59305b261ecSmrgstatic void 59405b261ecSmrgcalculateFbmem_len(fbdevHWPtr fPtr) 59505b261ecSmrg{ 596f7df2e56Smrg fPtr->fboff = (unsigned long) fPtr->fix.smem_start & ~PAGE_MASK; 597f7df2e56Smrg fPtr->fbmem_len = (fPtr->fboff + fPtr->fix.smem_len + ~PAGE_MASK) & 598f7df2e56Smrg PAGE_MASK; 59905b261ecSmrg} 60005b261ecSmrg 601f7df2e56Smrgvoid * 60205b261ecSmrgfbdevHWMapVidmem(ScrnInfoPtr pScrn) 60305b261ecSmrg{ 604f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 605f7df2e56Smrg 606f7df2e56Smrg if (NULL == fPtr->fbmem) { 607f7df2e56Smrg calculateFbmem_len(fPtr); 608f7df2e56Smrg fPtr->fbmem = mmap(NULL, fPtr->fbmem_len, PROT_READ | PROT_WRITE, 609f7df2e56Smrg MAP_SHARED, fPtr->fd, 0); 610f7df2e56Smrg if (-1 == (long) fPtr->fbmem) { 611f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 612f7df2e56Smrg "mmap fbmem: %s\n", strerror(errno)); 613f7df2e56Smrg fPtr->fbmem = NULL; 614f7df2e56Smrg } 615f7df2e56Smrg else { 616f7df2e56Smrg /* Perhaps we'd better add fboff to fbmem and return 0 in 617f7df2e56Smrg fbdevHWLinearOffset()? Of course we then need to mask 618f7df2e56Smrg fPtr->fbmem with PAGE_MASK in fbdevHWUnmapVidmem() as 619f7df2e56Smrg well. [geert] */ 620f7df2e56Smrg } 621f7df2e56Smrg } 622f7df2e56Smrg pScrn->memPhysBase = 623f7df2e56Smrg (unsigned long) fPtr->fix.smem_start & (unsigned long) (PAGE_MASK); 624f7df2e56Smrg pScrn->fbOffset = 625f7df2e56Smrg (unsigned long) fPtr->fix.smem_start & (unsigned long) (~PAGE_MASK); 626f7df2e56Smrg return fPtr->fbmem; 62705b261ecSmrg} 62805b261ecSmrg 62905b261ecSmrgint 63005b261ecSmrgfbdevHWLinearOffset(ScrnInfoPtr pScrn) 63105b261ecSmrg{ 632f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 63305b261ecSmrg 634f7df2e56Smrg return fPtr->fboff; 63505b261ecSmrg} 63605b261ecSmrg 63705b261ecSmrgBool 63805b261ecSmrgfbdevHWUnmapVidmem(ScrnInfoPtr pScrn) 63905b261ecSmrg{ 640f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 64105b261ecSmrg 642f7df2e56Smrg if (NULL != fPtr->fbmem) { 643f7df2e56Smrg if (-1 == munmap(fPtr->fbmem, fPtr->fbmem_len)) 644f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 645f7df2e56Smrg "munmap fbmem: %s\n", strerror(errno)); 646f7df2e56Smrg fPtr->fbmem = NULL; 647f7df2e56Smrg } 648f7df2e56Smrg return TRUE; 64905b261ecSmrg} 65005b261ecSmrg 651f7df2e56Smrgvoid * 65205b261ecSmrgfbdevHWMapMMIO(ScrnInfoPtr pScrn) 65305b261ecSmrg{ 654f7df2e56Smrg unsigned int mmio_off; 655f7df2e56Smrg 656f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 657f7df2e56Smrg 658f7df2e56Smrg if (NULL == fPtr->mmio) { 659f7df2e56Smrg /* tell the kernel not to use accels to speed up console scrolling */ 660f7df2e56Smrg fPtr->var.accel_flags = 0; 661f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *) (&fPtr->var))) { 662f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 663f7df2e56Smrg "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); 664f7df2e56Smrg return FALSE; 665f7df2e56Smrg } 666f7df2e56Smrg mmio_off = (unsigned long) fPtr->fix.mmio_start & ~PAGE_MASK; 667f7df2e56Smrg fPtr->mmio_len = (mmio_off + fPtr->fix.mmio_len + ~PAGE_MASK) & 668f7df2e56Smrg PAGE_MASK; 669f7df2e56Smrg if (NULL == fPtr->fbmem) 670f7df2e56Smrg calculateFbmem_len(fPtr); 671f7df2e56Smrg fPtr->mmio = mmap(NULL, fPtr->mmio_len, PROT_READ | PROT_WRITE, 672f7df2e56Smrg MAP_SHARED, fPtr->fd, fPtr->fbmem_len); 673f7df2e56Smrg if (-1 == (long) fPtr->mmio) { 674f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 675f7df2e56Smrg "mmap mmio: %s\n", strerror(errno)); 676f7df2e56Smrg fPtr->mmio = NULL; 677f7df2e56Smrg } 678f7df2e56Smrg else 679f7df2e56Smrg fPtr->mmio += mmio_off; 680f7df2e56Smrg } 681f7df2e56Smrg return fPtr->mmio; 68205b261ecSmrg} 68305b261ecSmrg 68405b261ecSmrgBool 68505b261ecSmrgfbdevHWUnmapMMIO(ScrnInfoPtr pScrn) 68605b261ecSmrg{ 687f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 68805b261ecSmrg 689f7df2e56Smrg if (NULL != fPtr->mmio) { 690f7df2e56Smrg if (-1 == 691f7df2e56Smrg munmap((void *) ((unsigned long) fPtr->mmio & PAGE_MASK), 692f7df2e56Smrg fPtr->mmio_len)) 693f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "munmap mmio: %s\n", 694f7df2e56Smrg strerror(errno)); 695f7df2e56Smrg fPtr->mmio = NULL; 696f7df2e56Smrg /* FIXME: restore var.accel_flags [geert] */ 697f7df2e56Smrg } 698f7df2e56Smrg return TRUE; 69905b261ecSmrg} 70005b261ecSmrg 70105b261ecSmrg/* -------------------------------------------------------------------- */ 70205b261ecSmrg 70305b261ecSmrgBool 70405b261ecSmrgfbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode) 705f7df2e56Smrg{ 706f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 707f7df2e56Smrg 708f7df2e56Smrg pScrn->vtSema = TRUE; 709f7df2e56Smrg 710f7df2e56Smrg /* set */ 711f7df2e56Smrg if (!fbdevHWSetMode(pScrn, mode, FALSE)) 712f7df2e56Smrg return FALSE; 713f7df2e56Smrg 714f7df2e56Smrg /* read back */ 715f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOGET_FSCREENINFO, (void *) (&fPtr->fix))) { 716f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 717f7df2e56Smrg "FBIOGET_FSCREENINFO: %s\n", strerror(errno)); 718f7df2e56Smrg return FALSE; 719f7df2e56Smrg } 720f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *) (&fPtr->var))) { 721f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 722f7df2e56Smrg "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); 723f7df2e56Smrg return FALSE; 724f7df2e56Smrg } 725f7df2e56Smrg 726f7df2e56Smrg if (pScrn->defaultVisual == TrueColor || 727f7df2e56Smrg pScrn->defaultVisual == DirectColor) { 728f7df2e56Smrg /* XXX: This is a hack, but it should be a NOP for all the setups that 729f7df2e56Smrg * worked before and actually seems to fix some others... 730f7df2e56Smrg */ 731f7df2e56Smrg pScrn->offset.red = fPtr->var.red.offset; 732f7df2e56Smrg pScrn->offset.green = fPtr->var.green.offset; 733f7df2e56Smrg pScrn->offset.blue = fPtr->var.blue.offset; 734f7df2e56Smrg pScrn->mask.red = 735f7df2e56Smrg ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset; 736f7df2e56Smrg pScrn->mask.green = 737f7df2e56Smrg ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset; 738f7df2e56Smrg pScrn->mask.blue = 739f7df2e56Smrg ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset; 740f7df2e56Smrg } 741f7df2e56Smrg 742f7df2e56Smrg return TRUE; 74305b261ecSmrg} 74405b261ecSmrg 74505b261ecSmrg/* -------------------------------------------------------------------- */ 74605b261ecSmrg/* video mode save/restore */ 74705b261ecSmrgvoid 74805b261ecSmrgfbdevHWSave(ScrnInfoPtr pScrn) 74905b261ecSmrg{ 750f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 75105b261ecSmrg 752f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOGET_VSCREENINFO, (void *) (&fPtr->saved_var))) 753f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 754f7df2e56Smrg "FBIOGET_VSCREENINFO: %s\n", strerror(errno)); 75505b261ecSmrg} 75605b261ecSmrg 75705b261ecSmrgvoid 75805b261ecSmrgfbdevHWRestore(ScrnInfoPtr pScrn) 75905b261ecSmrg{ 760f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 76105b261ecSmrg 762f7df2e56Smrg if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void *) (&fPtr->saved_var))) 763f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 764f7df2e56Smrg "FBIOPUT_VSCREENINFO: %s\n", strerror(errno)); 76505b261ecSmrg} 76605b261ecSmrg 76705b261ecSmrg/* -------------------------------------------------------------------- */ 76805b261ecSmrg/* callback for xf86HandleColormaps */ 76905b261ecSmrg 77005b261ecSmrgvoid 77105b261ecSmrgfbdevHWLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indices, 772f7df2e56Smrg LOCO * colors, VisualPtr pVisual) 773f7df2e56Smrg{ 774f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 775f7df2e56Smrg struct fb_cmap cmap; 776f7df2e56Smrg unsigned short red, green, blue; 777f7df2e56Smrg int i; 778f7df2e56Smrg 779f7df2e56Smrg cmap.len = 1; 780f7df2e56Smrg cmap.red = &red; 781f7df2e56Smrg cmap.green = &green; 782f7df2e56Smrg cmap.blue = &blue; 783f7df2e56Smrg cmap.transp = NULL; 784f7df2e56Smrg for (i = 0; i < numColors; i++) { 785f7df2e56Smrg cmap.start = indices[i]; 786f7df2e56Smrg red = (colors[indices[i]].red << 8) | colors[indices[i]].red; 787f7df2e56Smrg green = (colors[indices[i]].green << 8) | colors[indices[i]].green; 788f7df2e56Smrg blue = (colors[indices[i]].blue << 8) | colors[indices[i]].blue; 789f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOPUTCMAP, (void *) &cmap)) 790f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_ERROR, 791f7df2e56Smrg "FBIOPUTCMAP: %s\n", strerror(errno)); 792f7df2e56Smrg } 79305b261ecSmrg} 79405b261ecSmrg 79505b261ecSmrg/* -------------------------------------------------------------------- */ 79605b261ecSmrg/* these can be hooked directly into ScrnInfoRec */ 79705b261ecSmrg 79805b261ecSmrgModeStatus 799f7df2e56SmrgfbdevHWValidMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool verbose, int flags) 80005b261ecSmrg{ 801f7df2e56Smrg if (!fbdevHWSetMode(pScrn, mode, TRUE)) 802f7df2e56Smrg return MODE_BAD; 80305b261ecSmrg 804f7df2e56Smrg return MODE_OK; 80505b261ecSmrg} 80605b261ecSmrg 80705b261ecSmrgBool 808f7df2e56SmrgfbdevHWSwitchMode(ScrnInfoPtr pScrn, DisplayModePtr mode) 80905b261ecSmrg{ 810f7df2e56Smrg if (!fbdevHWSetMode(pScrn, mode, FALSE)) 811f7df2e56Smrg return FALSE; 81205b261ecSmrg 813f7df2e56Smrg return TRUE; 81405b261ecSmrg} 81505b261ecSmrg 81605b261ecSmrgvoid 817f7df2e56SmrgfbdevHWAdjustFrame(ScrnInfoPtr pScrn, int x, int y) 81805b261ecSmrg{ 819f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 82005b261ecSmrg 821f7df2e56Smrg if (x < 0 || x + fPtr->var.xres > fPtr->var.xres_virtual || 822f7df2e56Smrg y < 0 || y + fPtr->var.yres > fPtr->var.yres_virtual) 823f7df2e56Smrg return; 82405b261ecSmrg 825f7df2e56Smrg fPtr->var.xoffset = x; 826f7df2e56Smrg fPtr->var.yoffset = y; 827f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOPAN_DISPLAY, (void *) &fPtr->var)) 828f7df2e56Smrg xf86DrvMsgVerb(pScrn->scrnIndex, X_WARNING, 5, 829f7df2e56Smrg "FBIOPAN_DISPLAY: %s\n", strerror(errno)); 83005b261ecSmrg} 83105b261ecSmrg 83205b261ecSmrgBool 833f7df2e56SmrgfbdevHWEnterVT(ScrnInfoPtr pScrn) 83405b261ecSmrg{ 835f7df2e56Smrg if (!fbdevHWModeInit(pScrn, pScrn->currentMode)) 836f7df2e56Smrg return FALSE; 837f7df2e56Smrg fbdevHWAdjustFrame(pScrn, pScrn->frameX0, pScrn->frameY0); 838f7df2e56Smrg return TRUE; 83905b261ecSmrg} 84005b261ecSmrg 84105b261ecSmrgvoid 842f7df2e56SmrgfbdevHWLeaveVT(ScrnInfoPtr pScrn) 84305b261ecSmrg{ 844f7df2e56Smrg fbdevHWRestore(pScrn); 84505b261ecSmrg} 84605b261ecSmrg 84705b261ecSmrgvoid 84805b261ecSmrgfbdevHWDPMSSet(ScrnInfoPtr pScrn, int mode, int flags) 84905b261ecSmrg{ 850f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 851f7df2e56Smrg unsigned long fbmode; 852f7df2e56Smrg 853f7df2e56Smrg if (!pScrn->vtSema) 854f7df2e56Smrg return; 855f7df2e56Smrg 856f7df2e56Smrg if (fPtr->unsupported_ioctls & (1 << FBIOBLANK_UNSUPPORTED)) 857f7df2e56Smrg return; 858f7df2e56Smrg 859f7df2e56Smrg switch (mode) { 860f7df2e56Smrg case DPMSModeOn: 861f7df2e56Smrg fbmode = 0; 862f7df2e56Smrg break; 863f7df2e56Smrg case DPMSModeStandby: 864f7df2e56Smrg fbmode = 2; 865f7df2e56Smrg break; 866f7df2e56Smrg case DPMSModeSuspend: 867f7df2e56Smrg fbmode = 3; 868f7df2e56Smrg break; 869f7df2e56Smrg case DPMSModeOff: 870f7df2e56Smrg fbmode = 4; 871f7df2e56Smrg break; 872f7df2e56Smrg default: 873f7df2e56Smrg return; 874f7df2e56Smrg } 875f7df2e56Smrg 876f7df2e56SmrgRETRY: 877f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *) fbmode)) { 878f7df2e56Smrg switch (errno) { 879f7df2e56Smrg case EAGAIN: 880f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 881f7df2e56Smrg "FBIOBLANK: %s\n", strerror(errno)); 882f7df2e56Smrg break; 883f7df2e56Smrg case EINTR: 884f7df2e56Smrg case ERESTART: 885f7df2e56Smrg goto RETRY; 886f7df2e56Smrg default: 887f7df2e56Smrg fPtr->unsupported_ioctls |= (1 << FBIOBLANK_UNSUPPORTED); 888f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 889f7df2e56Smrg "FBIOBLANK: %s (Screen blanking not supported " 890f7df2e56Smrg "by kernel - disabling)\n", strerror(errno)); 891f7df2e56Smrg } 892f7df2e56Smrg } 89305b261ecSmrg} 89405b261ecSmrg 89505b261ecSmrgBool 89605b261ecSmrgfbdevHWSaveScreen(ScreenPtr pScreen, int mode) 89705b261ecSmrg{ 898f7df2e56Smrg ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); 899f7df2e56Smrg fbdevHWPtr fPtr = FBDEVHWPTR(pScrn); 900f7df2e56Smrg unsigned long unblank; 901f7df2e56Smrg 902f7df2e56Smrg if (!pScrn->vtSema) 903f7df2e56Smrg return TRUE; 904f7df2e56Smrg 905f7df2e56Smrg if (fPtr->unsupported_ioctls & (1 << FBIOBLANK_UNSUPPORTED)) 906f7df2e56Smrg return FALSE; 907f7df2e56Smrg 908f7df2e56Smrg unblank = xf86IsUnblank(mode); 909f7df2e56Smrg 910f7df2e56SmrgRETRY: 911f7df2e56Smrg if (-1 == ioctl(fPtr->fd, FBIOBLANK, (void *) (1 - unblank))) { 912f7df2e56Smrg switch (errno) { 913f7df2e56Smrg case EAGAIN: 914f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 915f7df2e56Smrg "FBIOBLANK: %s\n", strerror(errno)); 916f7df2e56Smrg break; 917f7df2e56Smrg case EINTR: 918f7df2e56Smrg case ERESTART: 919f7df2e56Smrg goto RETRY; 920f7df2e56Smrg default: 921f7df2e56Smrg fPtr->unsupported_ioctls |= (1 << FBIOBLANK_UNSUPPORTED); 922f7df2e56Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 923f7df2e56Smrg "FBIOBLANK: %s (Screen blanking not supported " 924f7df2e56Smrg "by kernel - disabling)\n", strerror(errno)); 925f7df2e56Smrg } 926f7df2e56Smrg return FALSE; 927f7df2e56Smrg } 92805b261ecSmrg 929f7df2e56Smrg return TRUE; 93005b261ecSmrg} 93105b261ecSmrg 93205b261ecSmrgxf86SwitchModeProc * 933f7df2e56SmrgfbdevHWSwitchModeWeak(void) 934f7df2e56Smrg{ 935f7df2e56Smrg return fbdevHWSwitchMode; 936f7df2e56Smrg} 93705b261ecSmrg 93805b261ecSmrgxf86AdjustFrameProc * 939f7df2e56SmrgfbdevHWAdjustFrameWeak(void) 940f7df2e56Smrg{ 941f7df2e56Smrg return fbdevHWAdjustFrame; 942f7df2e56Smrg} 94305b261ecSmrg 94405b261ecSmrgxf86EnterVTProc * 945f7df2e56SmrgfbdevHWEnterVTWeak(void) 946f7df2e56Smrg{ 947f7df2e56Smrg return fbdevHWEnterVT; 948f7df2e56Smrg} 94905b261ecSmrg 95005b261ecSmrgxf86LeaveVTProc * 951f7df2e56SmrgfbdevHWLeaveVTWeak(void) 952f7df2e56Smrg{ 953f7df2e56Smrg return fbdevHWLeaveVT; 954f7df2e56Smrg} 95505b261ecSmrg 95605b261ecSmrgxf86ValidModeProc * 957f7df2e56SmrgfbdevHWValidModeWeak(void) 958f7df2e56Smrg{ 959f7df2e56Smrg return fbdevHWValidMode; 960f7df2e56Smrg} 96105b261ecSmrg 96205b261ecSmrgxf86DPMSSetProc * 963f7df2e56SmrgfbdevHWDPMSSetWeak(void) 964f7df2e56Smrg{ 965f7df2e56Smrg return fbdevHWDPMSSet; 966f7df2e56Smrg} 96705b261ecSmrg 96805b261ecSmrgxf86LoadPaletteProc * 969f7df2e56SmrgfbdevHWLoadPaletteWeak(void) 970f7df2e56Smrg{ 971f7df2e56Smrg return fbdevHWLoadPalette; 972f7df2e56Smrg} 97305b261ecSmrg 97405b261ecSmrgSaveScreenProcPtr 975f7df2e56SmrgfbdevHWSaveScreenWeak(void) 976f7df2e56Smrg{ 977f7df2e56Smrg return fbdevHWSaveScreen; 978f7df2e56Smrg} 979