Back to index

xserver-xorg-video-modesetting  0.3.0
drmmode_display.c
Go to the documentation of this file.
00001 /*
00002  * Copyright © 2007 Red Hat, Inc.
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a
00005  * copy of this software and associated documentation files (the "Software"),
00006  * to deal in the Software without restriction, including without limitation
00007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008  * and/or sell copies of the Software, and to permit persons to whom the
00009  * Software is furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice (including the next
00012  * paragraph) shall be included in all copies or substantial portions of the
00013  * Software.
00014  *
00015  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00018  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00019  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00020  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00021  * SOFTWARE.
00022  *
00023  * Authors:
00024  *    Dave Airlie <airlied@redhat.com>
00025  *
00026  */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #include "config.h"
00030 #endif
00031 
00032 #include <errno.h>
00033 #include <sys/ioctl.h>
00034 #include <sys/mman.h>
00035 #include "xf86str.h"
00036 #include "X11/Xatom.h"
00037 #include "micmap.h"
00038 #include "xf86cmap.h"
00039 #include "xf86DDC.h"
00040 
00041 #include <xf86drm.h>
00042 #include "xf86Crtc.h"
00043 #include "drmmode_display.h"
00044 
00045 /* DPMS */
00046 #ifdef HAVE_XEXTPROTO_71
00047 #include <X11/extensions/dpmsconst.h>
00048 #else
00049 #define DPMS_SERVER
00050 #include <X11/extensions/dpms.h>
00051 #endif
00052 
00053 static struct dumb_bo *dumb_bo_create(int fd,
00054                        const unsigned width, const unsigned height,
00055                        const unsigned bpp)
00056 {
00057        struct drm_mode_create_dumb arg;
00058        struct dumb_bo *bo;
00059        int ret;
00060 
00061        bo = calloc(1, sizeof(*bo));
00062        if (!bo)
00063               return NULL;
00064 
00065        memset(&arg, 0, sizeof(arg));
00066        arg.width = width;
00067        arg.height = height;
00068        arg.bpp = bpp;
00069        
00070        ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &arg);
00071        if (ret)
00072               goto err_free;
00073 
00074        bo->handle = arg.handle;
00075        bo->size = arg.size;
00076        bo->pitch = arg.pitch;
00077 
00078        return bo;
00079  err_free:
00080        free(bo);
00081        return NULL;
00082 }
00083 
00084 static int dumb_bo_map(int fd, struct dumb_bo *bo)
00085 {
00086        struct drm_mode_map_dumb arg;
00087        int ret;
00088        void *map;
00089 
00090        if (bo->ptr) {
00091               bo->map_count++;
00092               return 0;
00093        }
00094 
00095        memset(&arg, 0, sizeof(arg));
00096        arg.handle = bo->handle;
00097 
00098        ret = drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &arg);
00099        if (ret)
00100               return ret;
00101 
00102        map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
00103                  fd, arg.offset);
00104        if (map == MAP_FAILED)
00105               return -errno;
00106 
00107        bo->ptr = map;
00108        return 0;
00109 }
00110 
00111 #if 0
00112 static int dumb_bo_unmap(int fd, struct dumb_bo *bo)
00113 {
00114        bo->map_count--;
00115        return 0;
00116 }
00117 #endif
00118 
00119 static int dumb_bo_destroy(int fd, struct dumb_bo *bo)
00120 {
00121        struct drm_mode_destroy_dumb arg;
00122        int ret;
00123        
00124        if (bo->ptr) {
00125               munmap(bo->ptr, bo->size);
00126               bo->ptr = NULL;
00127        }
00128 
00129        memset(&arg, 0, sizeof(arg));
00130        arg.handle = bo->handle;
00131        ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &arg);
00132        if (ret)
00133               return -errno;
00134 
00135        free(bo);
00136        return 0;
00137 }
00138 
00139 static void
00140 drmmode_ConvertFromKMode(ScrnInfoPtr      scrn,
00141                    drmModeModeInfo *kmode,
00142                    DisplayModePtr  mode)
00143 {
00144        memset(mode, 0, sizeof(DisplayModeRec));
00145        mode->status = MODE_OK;
00146 
00147        mode->Clock = kmode->clock;
00148 
00149        mode->HDisplay = kmode->hdisplay;
00150        mode->HSyncStart = kmode->hsync_start;
00151        mode->HSyncEnd = kmode->hsync_end;
00152        mode->HTotal = kmode->htotal;
00153        mode->HSkew = kmode->hskew;
00154 
00155        mode->VDisplay = kmode->vdisplay;
00156        mode->VSyncStart = kmode->vsync_start;
00157        mode->VSyncEnd = kmode->vsync_end;
00158        mode->VTotal = kmode->vtotal;
00159        mode->VScan = kmode->vscan;
00160 
00161        mode->Flags = kmode->flags; //& FLAG_BITS;
00162        mode->name = strdup(kmode->name);
00163 
00164        if (kmode->type & DRM_MODE_TYPE_DRIVER)
00165               mode->type = M_T_DRIVER;
00166        if (kmode->type & DRM_MODE_TYPE_PREFERRED)
00167               mode->type |= M_T_PREFERRED;
00168        xf86SetModeCrtc (mode, scrn->adjustFlags);
00169 }
00170 
00171 static void
00172 drmmode_ConvertToKMode(ScrnInfoPtr scrn,
00173                    drmModeModeInfo *kmode,
00174                    DisplayModePtr  mode)
00175 {
00176        memset(kmode, 0, sizeof(*kmode));
00177 
00178        kmode->clock = mode->Clock;
00179        kmode->hdisplay = mode->HDisplay;
00180        kmode->hsync_start = mode->HSyncStart;
00181        kmode->hsync_end = mode->HSyncEnd;
00182        kmode->htotal = mode->HTotal;
00183        kmode->hskew = mode->HSkew;
00184 
00185        kmode->vdisplay = mode->VDisplay;
00186        kmode->vsync_start = mode->VSyncStart;
00187        kmode->vsync_end = mode->VSyncEnd;
00188        kmode->vtotal = mode->VTotal;
00189        kmode->vscan = mode->VScan;
00190 
00191        kmode->flags = mode->Flags; //& FLAG_BITS;
00192        if (mode->name)
00193               strncpy(kmode->name, mode->name, DRM_DISPLAY_MODE_LEN);
00194        kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
00195 
00196 }
00197 
00198 static void
00199 drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
00200 {
00201 #if 0
00202        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
00203 //     drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00204 //     drmmode_ptr drmmode = drmmode_crtc->drmmode;
00205 
00206        /* bonghits in the randr 1.2 - uses dpms to disable crtc - bad buzz */
00207        if (mode == DPMSModeOff) {
00208 //            drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
00209 //                          0, 0, 0, NULL, 0, NULL);
00210        }
00211 #endif
00212 }
00213 
00214 #if 0
00215 static PixmapPtr
00216 create_pixmap_for_fbcon(drmmode_ptr drmmode,
00217                      ScrnInfoPtr pScrn, int crtc_id)
00218 {
00219        xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
00220        drmmode_crtc_private_ptr drmmode_crtc;
00221        ScreenPtr pScreen = pScrn->pScreen;
00222        PixmapPtr pixmap;
00223        struct radeon_bo *bo;
00224        drmModeFBPtr fbcon;
00225        struct drm_gem_flink flink;
00226 
00227        drmmode_crtc = xf86_config->crtc[crtc_id]->driver_private;
00228 
00229        fbcon = drmModeGetFB(drmmode->fd, drmmode_crtc->mode_crtc->buffer_id);
00230        if (fbcon == NULL)
00231               return NULL;
00232 
00233        flink.handle = fbcon->handle;
00234        if (ioctl(drmmode->fd, DRM_IOCTL_GEM_FLINK, &flink) < 0) {
00235               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
00236                         "Couldn't flink fbcon handle\n");
00237               return NULL;
00238        }
00239 
00240        bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0);
00241        if (bo == NULL) {
00242               xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
00243                         "Couldn't allocate bo for fbcon handle\n");
00244               return NULL;
00245        }
00246 
00247        pixmap = drmmode_create_bo_pixmap(pScreen, fbcon->width, fbcon->height,
00248                                      fbcon->depth, fbcon->bpp,
00249                                      fbcon->pitch, bo);
00250        if (!pixmap) 
00251               return NULL;
00252 
00253        radeon_bo_unref(bo);
00254        drmModeFreeFB(fbcon);
00255        return pixmap;
00256 }
00257 
00258 #endif
00259 
00260 static Bool
00261 drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
00262                    Rotation rotation, int x, int y)
00263 {
00264        ScrnInfoPtr pScrn = crtc->scrn;
00265        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
00266        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00267        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00268        int saved_x, saved_y;
00269        Rotation saved_rotation;
00270        DisplayModeRec saved_mode;
00271        uint32_t *output_ids;
00272        int output_count = 0;
00273        Bool ret = TRUE;
00274        int i;
00275        int fb_id;
00276        drmModeModeInfo kmode;
00277        int height;
00278 
00279        height = pScrn->virtualY;
00280 
00281        if (drmmode->fb_id == 0) {
00282               ret = drmModeAddFB(drmmode->fd,
00283                                pScrn->virtualX, height,
00284                                    pScrn->depth, pScrn->bitsPerPixel,
00285                                drmmode->front_bo->pitch,
00286                                drmmode->front_bo->handle,
00287                                    &drmmode->fb_id);
00288                 if (ret < 0) {
00289                         ErrorF("failed to add fb %d\n", ret);
00290                         return FALSE;
00291                 }
00292         }
00293 
00294        saved_mode = crtc->mode;
00295        saved_x = crtc->x;
00296        saved_y = crtc->y;
00297        saved_rotation = crtc->rotation;
00298 
00299        if (mode) {
00300               crtc->mode = *mode;
00301               crtc->x = x;
00302               crtc->y = y;
00303               crtc->rotation = rotation;
00304 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,5,99,0,0)
00305               crtc->transformPresent = FALSE;
00306 #endif
00307        }
00308 
00309        output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
00310        if (!output_ids) {
00311               ret = FALSE;
00312               goto done;
00313        }
00314 
00315        if (mode) {
00316               for (i = 0; i < xf86_config->num_output; i++) {
00317                      xf86OutputPtr output = xf86_config->output[i];
00318                      drmmode_output_private_ptr drmmode_output;
00319 
00320                      if (output->crtc != crtc)
00321                             continue;
00322 
00323                      drmmode_output = output->driver_private;
00324                      output_ids[output_count] = drmmode_output->mode_output->connector_id;
00325                      output_count++;
00326               }
00327 
00328               if (!xf86CrtcRotate(crtc)) {
00329                      goto done;
00330               }
00331 #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,7,0,0,0)
00332               crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
00333                                    crtc->gamma_blue, crtc->gamma_size);
00334 #endif
00335               
00336               drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
00337 
00338               fb_id = drmmode->fb_id;
00339               if (drmmode_crtc->rotate_fb_id) {
00340                      fb_id = drmmode_crtc->rotate_fb_id;
00341                      x = y = 0;
00342               }
00343               ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
00344                                  fb_id, x, y, output_ids, output_count, &kmode);
00345               if (ret)
00346                      xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
00347                                "failed to set mode: %s", strerror(-ret));
00348               else
00349                      ret = TRUE;
00350 
00351               if (crtc->scrn->pScreen)
00352                      xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
00353               /* go through all the outputs and force DPMS them back on? */
00354               for (i = 0; i < xf86_config->num_output; i++) {
00355                      xf86OutputPtr output = xf86_config->output[i];
00356 
00357                      if (output->crtc != crtc)
00358                             continue;
00359 
00360                      output->funcs->dpms(output, DPMSModeOn);
00361               }
00362        }
00363 
00364 #if 0
00365        if (pScrn->pScreen &&
00366               !xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE))
00367               xf86_reload_cursors(pScrn->pScreen);
00368 #endif
00369 done:
00370        if (!ret) {
00371               crtc->x = saved_x;
00372               crtc->y = saved_y;
00373               crtc->rotation = saved_rotation;
00374               crtc->mode = saved_mode;
00375        }
00376 #if defined(XF86_CRTC_VERSION) && XF86_CRTC_VERSION >= 3
00377        else
00378               crtc->active = TRUE;
00379 #endif
00380 
00381        return ret;
00382 }
00383 
00384 static void
00385 drmmode_set_cursor_colors (xf86CrtcPtr crtc, int bg, int fg)
00386 {
00387 
00388 }
00389 
00390 static void
00391 drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
00392 {
00393        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00394        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00395 
00396        drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y);
00397 }
00398 
00399 static void
00400 drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image)
00401 {
00402        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00403        int i;
00404        uint32_t *ptr;
00405        uint32_t handle = drmmode_crtc->cursor_bo->handle;
00406        int ret;
00407        /* cursor should be mapped already */
00408        ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
00409 
00410        for (i = 0; i < 64 * 64; i++)
00411               ptr[i] = image[i];// cpu_to_le32(image[i]);
00412 
00413        ret = drmModeSetCursor(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
00414        if (ret) {
00415               xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
00416               xf86CursorInfoPtr    cursor_info = xf86_config->cursor_info;
00417               
00418               cursor_info->MaxWidth = cursor_info->MaxHeight = 0;
00419               drmmode_crtc->drmmode->sw_cursor = TRUE;
00420               /* fallback to swcursor */
00421        }
00422 }
00423 
00424 
00425 static void
00426 drmmode_hide_cursor (xf86CrtcPtr crtc)
00427 {
00428        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00429        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00430 
00431        drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64);
00432 
00433 }
00434 
00435 static void
00436 drmmode_show_cursor (xf86CrtcPtr crtc)
00437 {
00438        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00439        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00440        uint32_t handle = drmmode_crtc->cursor_bo->handle;
00441 
00442        drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64);
00443 }
00444 
00445 static void
00446 drmmode_crtc_gamma_set(xf86CrtcPtr crtc, uint16_t *red, uint16_t *green,
00447                       uint16_t *blue, int size)
00448 {
00449        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
00450        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00451 
00452        drmModeCrtcSetGamma(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
00453                          size, red, green, blue);
00454 }
00455 
00456 static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
00457     .dpms = drmmode_crtc_dpms,
00458     .set_mode_major = drmmode_set_mode_major,
00459     .set_cursor_colors = drmmode_set_cursor_colors,
00460     .set_cursor_position = drmmode_set_cursor_position,
00461     .show_cursor = drmmode_show_cursor,
00462     .hide_cursor = drmmode_hide_cursor,
00463     .load_cursor_argb = drmmode_load_cursor_argb,
00464 
00465     .gamma_set = drmmode_crtc_gamma_set,
00466     .destroy = NULL, /* XXX */
00467 };
00468 
00469 static void
00470 drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
00471 {
00472        xf86CrtcPtr crtc;
00473        drmmode_crtc_private_ptr drmmode_crtc;
00474 
00475        crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
00476        if (crtc == NULL)
00477               return;
00478 
00479        drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
00480        drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
00481        drmmode_crtc->drmmode = drmmode;
00482        crtc->driver_private = drmmode_crtc;
00483 }
00484 
00485 static xf86OutputStatus
00486 drmmode_output_detect(xf86OutputPtr output)
00487 {
00488        /* go to the hw and retrieve a new output struct */
00489        drmmode_output_private_ptr drmmode_output = output->driver_private;
00490        drmmode_ptr drmmode = drmmode_output->drmmode;
00491        xf86OutputStatus status;
00492        drmModeFreeConnector(drmmode_output->mode_output);
00493 
00494        drmmode_output->mode_output = drmModeGetConnector(drmmode->fd, drmmode_output->output_id);
00495 
00496        switch (drmmode_output->mode_output->connection) {
00497        case DRM_MODE_CONNECTED:
00498               status = XF86OutputStatusConnected;
00499               break;
00500        case DRM_MODE_DISCONNECTED:
00501               status = XF86OutputStatusDisconnected;
00502               break;
00503        default:
00504        case DRM_MODE_UNKNOWNCONNECTION:
00505               status = XF86OutputStatusUnknown;
00506               break;
00507        }
00508        return status;
00509 }
00510 
00511 static Bool
00512 drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes)
00513 {
00514        return MODE_OK;
00515 }
00516 
00517 static DisplayModePtr
00518 drmmode_output_get_modes(xf86OutputPtr output)
00519 {
00520        drmmode_output_private_ptr drmmode_output = output->driver_private;
00521        drmModeConnectorPtr koutput = drmmode_output->mode_output;
00522        drmmode_ptr drmmode = drmmode_output->drmmode;
00523        int i;
00524        DisplayModePtr Modes = NULL, Mode;
00525        drmModePropertyPtr props;
00526        xf86MonPtr mon = NULL;
00527 
00528        /* look for an EDID property */
00529        for (i = 0; i < koutput->count_props; i++) {
00530               props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
00531               if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
00532                      if (!strcmp(props->name, "EDID")) {
00533                             if (drmmode_output->edid_blob)
00534                                    drmModeFreePropertyBlob(drmmode_output->edid_blob);
00535                             drmmode_output->edid_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
00536                      }
00537                      drmModeFreeProperty(props);
00538               }
00539        }
00540 
00541        if (drmmode_output->edid_blob) {
00542               mon = xf86InterpretEDID(output->scrn->scrnIndex,
00543                                    drmmode_output->edid_blob->data);
00544               if (mon && drmmode_output->edid_blob->length > 128)
00545                      mon->flags |= MONITOR_EDID_COMPLETE_RAWDATA;
00546        }
00547        xf86OutputSetEDID(output, mon);
00548 
00549        /* modes should already be available */
00550        for (i = 0; i < koutput->count_modes; i++) {
00551               Mode = xnfalloc(sizeof(DisplayModeRec));
00552 
00553               drmmode_ConvertFromKMode(output->scrn, &koutput->modes[i], Mode);
00554               Modes = xf86ModesAdd(Modes, Mode);
00555 
00556        }
00557        return Modes;
00558 }
00559 
00560 static void
00561 drmmode_output_destroy(xf86OutputPtr output)
00562 {
00563        drmmode_output_private_ptr drmmode_output = output->driver_private;
00564        int i;
00565 
00566        if (drmmode_output->edid_blob)
00567               drmModeFreePropertyBlob(drmmode_output->edid_blob);
00568        for (i = 0; i < drmmode_output->num_props; i++) {
00569               drmModeFreeProperty(drmmode_output->props[i].mode_prop);
00570               free(drmmode_output->props[i].atoms);
00571        }
00572        for (i = 0; i < drmmode_output->mode_output->count_encoders; i++) {
00573               drmModeFreeEncoder(drmmode_output->mode_encoders[i]);
00574               free(drmmode_output->mode_encoders);
00575        }
00576        free(drmmode_output->props);
00577        drmModeFreeConnector(drmmode_output->mode_output);
00578        free(drmmode_output);
00579        output->driver_private = NULL;
00580 }
00581 
00582 static void
00583 drmmode_output_dpms(xf86OutputPtr output, int mode)
00584 {
00585        drmmode_output_private_ptr drmmode_output = output->driver_private;
00586        drmModeConnectorPtr koutput = drmmode_output->mode_output;
00587        drmmode_ptr drmmode = drmmode_output->drmmode;
00588 
00589        drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
00590                                 drmmode_output->dpms_enum_id, mode);
00591        return;
00592 }
00593 
00594 
00595 static Bool
00596 drmmode_property_ignore(drmModePropertyPtr prop)
00597 {
00598     if (!prop)
00599        return TRUE;
00600     /* ignore blob prop */
00601     if (prop->flags & DRM_MODE_PROP_BLOB)
00602        return TRUE;
00603     /* ignore standard property */
00604     if (!strcmp(prop->name, "EDID") ||
00605            !strcmp(prop->name, "DPMS"))
00606        return TRUE;
00607 
00608     return FALSE;
00609 }
00610 
00611 static void
00612 drmmode_output_create_resources(xf86OutputPtr output)
00613 {
00614     drmmode_output_private_ptr drmmode_output = output->driver_private;
00615     drmModeConnectorPtr mode_output = drmmode_output->mode_output;
00616     drmmode_ptr drmmode = drmmode_output->drmmode;
00617     drmModePropertyPtr drmmode_prop;
00618     int i, j, err;
00619 
00620     drmmode_output->props = calloc(mode_output->count_props, sizeof(drmmode_prop_rec));
00621     if (!drmmode_output->props)
00622        return;
00623     
00624     drmmode_output->num_props = 0;
00625     for (i = 0, j = 0; i < mode_output->count_props; i++) {
00626        drmmode_prop = drmModeGetProperty(drmmode->fd, mode_output->props[i]);
00627        if (drmmode_property_ignore(drmmode_prop)) {
00628            drmModeFreeProperty(drmmode_prop);
00629            continue;
00630        }
00631        drmmode_output->props[j].mode_prop = drmmode_prop;
00632        drmmode_output->props[j].value = mode_output->prop_values[i];
00633        drmmode_output->num_props++;
00634        j++;
00635     }
00636 
00637     for (i = 0; i < drmmode_output->num_props; i++) {
00638        drmmode_prop_ptr p = &drmmode_output->props[i];
00639        drmmode_prop = p->mode_prop;
00640 
00641        if (drmmode_prop->flags & DRM_MODE_PROP_RANGE) {
00642            INT32 range[2];
00643            INT32 value = p->value;
00644 
00645            p->num_atoms = 1;
00646            p->atoms = calloc(p->num_atoms, sizeof(Atom));
00647            if (!p->atoms)
00648               continue;
00649            p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
00650            range[0] = drmmode_prop->values[0];
00651            range[1] = drmmode_prop->values[1];
00652            err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
00653                   FALSE, TRUE,
00654                   drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
00655                   2, range);
00656            if (err != 0) {
00657               xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
00658                      "RRConfigureOutputProperty error, %d\n", err);
00659            }
00660            err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
00661                   XA_INTEGER, 32, PropModeReplace, 1, &value, FALSE, TRUE);
00662            if (err != 0) {
00663               xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
00664                      "RRChangeOutputProperty error, %d\n", err);
00665            }
00666        } else if (drmmode_prop->flags & DRM_MODE_PROP_ENUM) {
00667            p->num_atoms = drmmode_prop->count_enums + 1;
00668            p->atoms = calloc(p->num_atoms, sizeof(Atom));
00669            if (!p->atoms)
00670               continue;
00671            p->atoms[0] = MakeAtom(drmmode_prop->name, strlen(drmmode_prop->name), TRUE);
00672            for (j = 1; j <= drmmode_prop->count_enums; j++) {
00673               struct drm_mode_property_enum *e = &drmmode_prop->enums[j-1];
00674               p->atoms[j] = MakeAtom(e->name, strlen(e->name), TRUE);
00675            }
00676            err = RRConfigureOutputProperty(output->randr_output, p->atoms[0],
00677                   FALSE, FALSE,
00678                   drmmode_prop->flags & DRM_MODE_PROP_IMMUTABLE ? TRUE : FALSE,
00679                   p->num_atoms - 1, (INT32 *)&p->atoms[1]);
00680            if (err != 0) {
00681               xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
00682                      "RRConfigureOutputProperty error, %d\n", err);
00683            }
00684            for (j = 0; j < drmmode_prop->count_enums; j++)
00685               if (drmmode_prop->enums[j].value == p->value)
00686                   break;
00687            /* there's always a matching value */
00688            err = RRChangeOutputProperty(output->randr_output, p->atoms[0],
00689                   XA_ATOM, 32, PropModeReplace, 1, &p->atoms[j+1], FALSE, TRUE);
00690            if (err != 0) {
00691               xf86DrvMsg(output->scrn->scrnIndex, X_ERROR,
00692                      "RRChangeOutputProperty error, %d\n", err);
00693            }
00694        }
00695     }
00696 }
00697 
00698 static Bool
00699 drmmode_output_set_property(xf86OutputPtr output, Atom property,
00700               RRPropertyValuePtr value)
00701 {
00702     drmmode_output_private_ptr drmmode_output = output->driver_private;
00703     drmmode_ptr drmmode = drmmode_output->drmmode;
00704     int i;
00705 
00706     for (i = 0; i < drmmode_output->num_props; i++) {
00707        drmmode_prop_ptr p = &drmmode_output->props[i];
00708 
00709        if (p->atoms[0] != property)
00710            continue;
00711 
00712        if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) {
00713            uint32_t val;
00714 
00715            if (value->type != XA_INTEGER || value->format != 32 ||
00716                   value->size != 1)
00717               return FALSE;
00718            val = *(uint32_t *)value->data;
00719 
00720            drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
00721                   p->mode_prop->prop_id, (uint64_t)val);
00722            return TRUE;
00723        } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) {
00724            Atom      atom;
00725            const char       *name;
00726            int              j;
00727 
00728            if (value->type != XA_ATOM || value->format != 32 || value->size != 1)
00729               return FALSE;
00730            memcpy(&atom, value->data, 4);
00731            name = NameForAtom(atom);
00732 
00733            /* search for matching name string, then set its value down */
00734            for (j = 0; j < p->mode_prop->count_enums; j++) {
00735               if (!strcmp(p->mode_prop->enums[j].name, name)) {
00736                   drmModeConnectorSetProperty(drmmode->fd, drmmode_output->output_id,
00737                          p->mode_prop->prop_id, p->mode_prop->enums[j].value);
00738                   return TRUE;
00739               }
00740            }
00741        }
00742     }
00743 
00744     return TRUE;
00745 }
00746 
00747 static Bool
00748 drmmode_output_get_property(xf86OutputPtr output, Atom property)
00749 {
00750     return TRUE;
00751 }
00752 
00753 static const xf86OutputFuncsRec drmmode_output_funcs = {
00754     .dpms = drmmode_output_dpms,
00755     .create_resources = drmmode_output_create_resources,
00756 #ifdef RANDR_12_INTERFACE
00757     .set_property = drmmode_output_set_property,
00758     .get_property = drmmode_output_get_property,
00759 #endif
00760     .detect = drmmode_output_detect,
00761     .mode_valid = drmmode_output_mode_valid,
00762 
00763     .get_modes = drmmode_output_get_modes,
00764     .destroy = drmmode_output_destroy
00765 };
00766 
00767 static int subpixel_conv_table[7] = { 0, SubPixelUnknown,
00768                                   SubPixelHorizontalRGB,
00769                                   SubPixelHorizontalBGR,
00770                                   SubPixelVerticalRGB,
00771                                   SubPixelVerticalBGR,
00772                                   SubPixelNone };
00773 
00774 const char *output_names[] = { "None",
00775                             "VGA",
00776                             "DVI",
00777                             "DVI",
00778                             "DVI",
00779                             "Composite",
00780                             "S-video",
00781                             "LVDS",
00782                             "CTV",
00783                             "DIN",
00784                             "DisplayPort",
00785                             "HDMI",
00786                             "HDMI",
00787                             "TV",
00788                             "eDP"
00789 };
00790 
00791 static void
00792 drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
00793 {
00794        xf86OutputPtr output;
00795        drmModeConnectorPtr koutput;
00796        drmModeEncoderPtr *kencoders = NULL;
00797        drmmode_output_private_ptr drmmode_output;
00798        drmModePropertyPtr props;
00799        char name[32];
00800        int i;
00801 
00802        koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
00803        if (!koutput)
00804               return;
00805 
00806        kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
00807        if (!kencoders) {
00808               goto out_free_encoders;
00809        }
00810 
00811        for (i = 0; i < koutput->count_encoders; i++) {
00812               kencoders[i] = drmModeGetEncoder(drmmode->fd, koutput->encoders[i]);
00813               if (!kencoders[i]) {
00814                      goto out_free_encoders;
00815               }
00816        }
00817 
00818        /* need to do smart conversion here for compat with non-kms ATI driver */
00819        snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], koutput->connector_type_id - 1);
00820 
00821        output = xf86OutputCreate (pScrn, &drmmode_output_funcs, name);
00822        if (!output) {
00823               goto out_free_encoders;
00824        }
00825 
00826        drmmode_output = calloc(sizeof(drmmode_output_private_rec), 1);
00827        if (!drmmode_output) {
00828               xf86OutputDestroy(output);
00829               goto out_free_encoders;
00830        }
00831 
00832        drmmode_output->output_id = drmmode->mode_res->connectors[num];
00833        drmmode_output->mode_output = koutput;
00834        drmmode_output->mode_encoders = kencoders;
00835        drmmode_output->drmmode = drmmode;
00836        output->mm_width = koutput->mmWidth;
00837        output->mm_height = koutput->mmHeight;
00838 
00839        output->subpixel_order = subpixel_conv_table[koutput->subpixel];
00840        output->interlaceAllowed = TRUE;
00841        output->doubleScanAllowed = TRUE;
00842        output->driver_private = drmmode_output;
00843        
00844        output->possible_crtcs = 0x7f;
00845        for (i = 0; i < koutput->count_encoders; i++) {
00846               output->possible_crtcs &= kencoders[i]->possible_crtcs;
00847        }
00848        /* work out the possible clones later */
00849        output->possible_clones = 0;
00850 
00851        for (i = 0; i < koutput->count_props; i++) {
00852               props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
00853               if (props && (props->flags & DRM_MODE_PROP_ENUM)) {
00854                      if (!strcmp(props->name, "DPMS")) {
00855                             drmmode_output->dpms_enum_id = koutput->props[i];
00856                             drmModeFreeProperty(props);
00857                             break;
00858                      }
00859                      drmModeFreeProperty(props);
00860               }
00861        }
00862 
00863        return;
00864 out_free_encoders:
00865        if (kencoders){
00866               for (i = 0; i < koutput->count_encoders; i++)
00867                      drmModeFreeEncoder(kencoders[i]);
00868               free(kencoders);
00869        }
00870        drmModeFreeConnector(koutput);
00871        
00872 }
00873 
00874 static uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
00875 {
00876        drmmode_output_private_ptr drmmode_output = output->driver_private, clone_drmout;
00877        int i;
00878        xf86OutputPtr clone_output;
00879        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
00880        int index_mask = 0;
00881 
00882        if (drmmode_output->enc_clone_mask == 0)
00883               return index_mask;
00884 
00885        for (i = 0; i < xf86_config->num_output; i++) {
00886               clone_output = xf86_config->output[i];
00887               clone_drmout = clone_output->driver_private;
00888               if (output == clone_output)
00889                      continue;
00890               
00891               if (clone_drmout->enc_mask == 0)
00892                      continue;
00893               if (drmmode_output->enc_clone_mask == clone_drmout->enc_mask)
00894                      index_mask |= (1 << i);
00895        }
00896        return index_mask;
00897 }
00898 
00899 
00900 static void
00901 drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
00902 {
00903        int i, j;
00904        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
00905 
00906        for (i = 0; i < xf86_config->num_output; i++) {
00907               xf86OutputPtr output = xf86_config->output[i];
00908               drmmode_output_private_ptr drmmode_output;
00909 
00910               drmmode_output = output->driver_private;
00911               drmmode_output->enc_clone_mask = 0xff;
00912               /* and all the possible encoder clones for this output together */
00913               for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
00914               {
00915                      int k;
00916                      for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
00917                             if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
00918                                    drmmode_output->enc_mask |= (1 << k);
00919                      }
00920 
00921                      drmmode_output->enc_clone_mask &= drmmode_output->mode_encoders[j]->possible_clones;
00922               }
00923        }
00924 
00925        for (i = 0; i < xf86_config->num_output; i++) {
00926               xf86OutputPtr output = xf86_config->output[i];
00927               output->possible_clones = find_clones(scrn, output);
00928        }
00929 }
00930 
00931 static Bool
00932 drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
00933 {
00934        xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
00935        drmmode_crtc_private_ptr
00936                   drmmode_crtc = xf86_config->crtc[0]->driver_private;
00937        drmmode_ptr drmmode = drmmode_crtc->drmmode;
00938        struct dumb_bo *old_front = NULL;
00939        Bool       ret;
00940        ScreenPtr   screen = screenInfo.screens[scrn->scrnIndex];
00941        uint32_t    old_fb_id;
00942        int        i, pitch, old_width, old_height, old_pitch;
00943        int cpp = (scrn->bitsPerPixel + 7) / 8;
00944        PixmapPtr ppix = screen->GetScreenPixmap(screen);
00945        void *new_pixels;
00946 
00947        if (scrn->virtualX == width && scrn->virtualY == height)
00948               return TRUE;
00949 
00950        xf86DrvMsg(scrn->scrnIndex, X_INFO,
00951                  "Allocate new frame buffer %dx%d stride\n",
00952                  width, height);
00953 
00954        old_width = scrn->virtualX;
00955        old_height = scrn->virtualY;
00956        old_pitch = drmmode->front_bo->pitch;
00957        old_fb_id = drmmode->fb_id;
00958        old_front = drmmode->front_bo;
00959 
00960        drmmode->front_bo = dumb_bo_create(drmmode->fd, width, height, scrn->bitsPerPixel);
00961        if (!drmmode->front_bo)
00962               goto fail;
00963 
00964        pitch = drmmode->front_bo->pitch;
00965 
00966        scrn->virtualX = width;
00967        scrn->virtualY = height;
00968        scrn->displayWidth = pitch / cpp;
00969 
00970        ret = drmModeAddFB(drmmode->fd, width, height, scrn->depth,
00971                         scrn->bitsPerPixel, pitch,
00972                         drmmode->front_bo->handle,
00973                         &drmmode->fb_id);
00974        if (ret)
00975               goto fail;
00976        
00977        new_pixels  = drmmode_map_front_bo(drmmode);
00978        if (!new_pixels)
00979               goto fail;
00980 
00981        if (!drmmode->shadow_enable)
00982               screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
00983                                       pitch, new_pixels);
00984        else {
00985               void *new_shadow;
00986               uint32_t size = scrn->displayWidth * scrn->virtualY *
00987                      ((scrn->bitsPerPixel + 7) >> 3);
00988               new_shadow = calloc(1, size);
00989               if (new_shadow == NULL)
00990                      goto fail;
00991               free(drmmode->shadow_fb);
00992               drmmode->shadow_fb = new_shadow;
00993               screen->ModifyPixmapHeader(ppix, width, height, -1, -1,
00994                                       pitch, drmmode->shadow_fb);
00995        }
00996 
00997 #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,9,99,1,0)
00998        scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
00999 #endif
01000 
01001        for (i = 0; i < xf86_config->num_crtc; i++) {
01002               xf86CrtcPtr crtc = xf86_config->crtc[i];
01003 
01004               if (!crtc->enabled)
01005                      continue;
01006 
01007               drmmode_set_mode_major(crtc, &crtc->mode,
01008                                    crtc->rotation, crtc->x, crtc->y);
01009        }
01010 
01011        if (old_fb_id) {
01012               drmModeRmFB(drmmode->fd, old_fb_id);
01013               dumb_bo_destroy(drmmode->fd, old_front);
01014        }
01015 
01016        return TRUE;
01017 
01018  fail:
01019        if (drmmode->front_bo)
01020               dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
01021        drmmode->front_bo = old_front;
01022        scrn->virtualX = old_width;
01023        scrn->virtualY = old_height;
01024        scrn->displayWidth = old_pitch / cpp;
01025        drmmode->fb_id = old_fb_id;
01026 
01027        return FALSE;
01028 }
01029 
01030 static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
01031        drmmode_xf86crtc_resize
01032 };
01033 
01034 Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
01035 {
01036        int i, num_dvi = 0, num_hdmi = 0;
01037        int ret;
01038        uint64_t value = 0;
01039 
01040        /* check for dumb capability */
01041        ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_BUFFER, &value);
01042        if (ret > 0 || value != 1) {
01043               xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "KMS doesn't support dumb interface\n");
01044               return FALSE;
01045        }
01046 
01047        xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
01048 
01049        drmmode->scrn = pScrn;
01050        drmmode->cpp = cpp;
01051        drmmode->mode_res = drmModeGetResources(drmmode->fd);
01052        if (!drmmode->mode_res)
01053               return FALSE;
01054 
01055        xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
01056        for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
01057               if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
01058                      drmmode_crtc_init(pScrn, drmmode, i);
01059 
01060        for (i = 0; i < drmmode->mode_res->count_connectors; i++)
01061               drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
01062 
01063        /* workout clones */
01064        drmmode_clones_init(pScrn, drmmode);
01065 
01066        xf86InitialConfiguration(pScrn, TRUE);
01067 
01068        return TRUE;
01069 }
01070 
01071 void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y, int flags)
01072 {
01073        xf86CrtcConfigPtr    config = XF86_CRTC_CONFIG_PTR(pScrn);
01074        xf86OutputPtr  output = config->output[config->compat_output];
01075        xf86CrtcPtr   crtc = output->crtc;
01076 
01077        if (crtc && crtc->enabled) {
01078               drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation,
01079                                    x, y);
01080        }
01081 }
01082 
01083 Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
01084 {
01085        xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
01086        int c;
01087 
01088        for (c = 0; c < config->num_crtc; c++) {
01089               xf86CrtcPtr   crtc = config->crtc[c];
01090               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
01091               xf86OutputPtr output = NULL;
01092               int           o;
01093 
01094               /* Skip disabled CRTCs */
01095               if (!crtc->enabled) {
01096                      drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
01097                                    0, 0, 0, NULL, 0, NULL);
01098                      continue;
01099               }
01100 
01101               if (config->output[config->compat_output]->crtc == crtc)
01102                      output = config->output[config->compat_output];
01103               else
01104               {
01105                      for (o = 0; o < config->num_output; o++)
01106                             if (config->output[o]->crtc == crtc)
01107                             {
01108                                    output = config->output[o];
01109                                    break;
01110                             }
01111               }
01112               /* paranoia */
01113               if (!output)
01114                      continue;
01115 
01116               /* Mark that we'll need to re-set the mode for sure */
01117               memset(&crtc->mode, 0, sizeof(crtc->mode));
01118               if (!crtc->desiredMode.CrtcHDisplay)
01119               {
01120                      DisplayModePtr  mode = xf86OutputFindClosestMode (output, pScrn->currentMode);
01121 
01122                      if (!mode)
01123                             return FALSE;
01124                      crtc->desiredMode = *mode;
01125                      crtc->desiredRotation = RR_Rotate_0;
01126                      crtc->desiredX = 0;
01127                      crtc->desiredY = 0;
01128               }
01129 
01130               if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
01131                                            crtc->desiredX, crtc->desiredY))
01132                      return FALSE;
01133        }
01134        return TRUE;
01135 }
01136 
01137 static void drmmode_load_palette(ScrnInfoPtr pScrn, int numColors,
01138                                  int *indices, LOCO *colors, VisualPtr pVisual)
01139 {
01140     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
01141     uint16_t       lut_r[256], lut_g[256], lut_b[256];
01142     int index, j, i;
01143     int c;
01144 
01145     for (c = 0; c < xf86_config->num_crtc; c++) {
01146         xf86CrtcPtr crtc = xf86_config->crtc[c];
01147        drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
01148 
01149         for (i = 0 ; i < 256; i++) {
01150             lut_r[i] = drmmode_crtc->lut_r[i] << 6;
01151             lut_g[i] = drmmode_crtc->lut_g[i] << 6;
01152             lut_b[i] = drmmode_crtc->lut_b[i] << 6;
01153         }
01154 
01155         switch(pScrn->depth) {
01156         case 15:
01157             for (i = 0; i < numColors; i++) {
01158                 index = indices[i];
01159                 for (j = 0; j < 8; j++) {
01160                     lut_r[index * 8 + j] = colors[index].red << 6;
01161                     lut_g[index * 8 + j] = colors[index].green << 6;
01162                     lut_b[index * 8 + j] = colors[index].blue << 6;
01163                 }
01164             }
01165          break;
01166          case 16:
01167              for (i = 0; i < numColors; i++) {
01168                  index = indices[i];
01169 
01170                   if (i <= 31) {
01171                       for (j = 0; j < 8; j++) {
01172                           lut_r[index * 8 + j] = colors[index].red << 6;
01173                           lut_b[index * 8 + j] = colors[index].blue << 6;
01174                       }
01175                   }
01176 
01177                   for (j = 0; j < 4; j++) {
01178                       lut_g[index * 4 + j] = colors[index].green << 6;
01179                   }
01180               }
01181          break;
01182           default:
01183               for (i = 0; i < numColors; i++) {
01184                   index = indices[i];
01185                   lut_r[index] = colors[index].red << 6;
01186                   lut_g[index] = colors[index].green << 6;
01187                   lut_b[index] = colors[index].blue << 6;
01188               }
01189               break;
01190           }
01191 
01192     /* Make the change through RandR */
01193 #ifdef RANDR_12_INTERFACE
01194         if (crtc->randr_crtc)
01195             RRCrtcGammaSet(crtc->randr_crtc, lut_r, lut_g, lut_b);
01196         else
01197 #endif
01198             crtc->funcs->gamma_set(crtc, lut_r, lut_g, lut_b, 256);
01199      }
01200 }
01201 
01202 Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
01203 {
01204     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, 0,
01205                   "Initializing kms color map\n");
01206     if (!miCreateDefColormap(pScreen))
01207         return FALSE;
01208     /* all radeons support 10 bit CLUTs */
01209     if (!xf86HandleColormaps(pScreen, 256, 10,
01210                              drmmode_load_palette, NULL,
01211                              CMAP_PALETTED_TRUECOLOR
01212 #if 0 /* This option messes up text mode! (eich@suse.de) */
01213                              | CMAP_LOAD_EVEN_IF_OFFSCREEN
01214 #endif
01215                              | CMAP_RELOAD_ON_MODE_SWITCH))
01216          return FALSE;
01217     return TRUE;
01218 }
01219 
01220 #ifdef HAVE_UDEV
01221 static void
01222 drmmode_handle_uevents(int fd, void *closure)
01223 {
01224        drmmode_ptr drmmode = closure;
01225        ScrnInfoPtr scrn = drmmode->scrn;
01226        struct udev_device *dev;
01227        dev = udev_monitor_receive_device(drmmode->uevent_monitor);
01228        if (!dev)
01229               return;
01230 
01231        RRGetInfo(screenInfo.screens[scrn->scrnIndex], TRUE);
01232        udev_device_unref(dev);
01233 }
01234 #endif
01235 
01236 void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
01237 {
01238 #ifdef HAVE_UDEV
01239        struct udev *u;
01240        struct udev_monitor *mon;
01241 
01242        u = udev_new();
01243        if (!u)
01244               return;
01245        mon = udev_monitor_new_from_netlink(u, "udev");
01246        if (!mon) {
01247               udev_unref(u);
01248               return;
01249        }
01250 
01251        if (udev_monitor_filter_add_match_subsystem_devtype(mon,
01252                                                      "drm",
01253                                                      "drm_minor") < 0 ||
01254            udev_monitor_enable_receiving(mon) < 0) {
01255               udev_monitor_unref(mon);
01256               udev_unref(u);
01257               return;
01258        }
01259 
01260        drmmode->uevent_handler =
01261               xf86AddGeneralHandler(udev_monitor_get_fd(mon),
01262                                   drmmode_handle_uevents,
01263                                   drmmode);
01264 
01265        drmmode->uevent_monitor = mon;
01266 #endif
01267 }
01268 
01269 void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
01270 {
01271 #ifdef HAVE_UDEV
01272        if (drmmode->uevent_handler) {
01273               struct udev *u = udev_monitor_get_udev(drmmode->uevent_monitor);
01274               xf86RemoveGeneralHandler(drmmode->uevent_handler);
01275 
01276               udev_monitor_unref(drmmode->uevent_monitor);
01277               udev_unref(u);
01278        }
01279 #endif
01280 }
01281 
01282 /* create front and cursor BOs */
01283 Bool drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
01284 {
01285        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
01286        int width;
01287        int height;
01288        int bpp = pScrn->bitsPerPixel;
01289        int i;
01290        int cpp = (bpp + 7) / 8;
01291 
01292        width = pScrn->virtualX;
01293        height = pScrn->virtualY;
01294 
01295        drmmode->front_bo = dumb_bo_create(drmmode->fd, width, height, bpp);
01296        if (!drmmode->front_bo)
01297               return FALSE;
01298        pScrn->displayWidth = drmmode->front_bo->pitch / cpp;
01299 
01300        width = height = 64;
01301        bpp = 32;
01302        for (i = 0; i < xf86_config->num_crtc; i++) {
01303               xf86CrtcPtr crtc = xf86_config->crtc[i];
01304               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
01305               drmmode_crtc->cursor_bo = dumb_bo_create(drmmode->fd, width, height, bpp);
01306        }
01307        return TRUE;
01308 }
01309 
01310 void *drmmode_map_front_bo(drmmode_ptr drmmode)
01311 {
01312        int ret;
01313 
01314        if (drmmode->front_bo->ptr)
01315               return drmmode->front_bo->ptr;
01316 
01317        ret = dumb_bo_map(drmmode->fd, drmmode->front_bo);
01318        if (ret)
01319               return NULL;
01320 
01321        return drmmode->front_bo->ptr;
01322        
01323 }
01324 
01325 Bool drmmode_map_cursor_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
01326 {
01327        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
01328        int i, ret;
01329        for (i = 0; i < xf86_config->num_crtc; i++) {
01330               xf86CrtcPtr crtc = xf86_config->crtc[i];
01331               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
01332               ret = dumb_bo_map(drmmode->fd, drmmode_crtc->cursor_bo);
01333               if (ret)
01334                      return FALSE;
01335        }
01336        return TRUE;
01337 }
01338 
01339 void drmmode_free_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
01340 {
01341        xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
01342        int i;
01343 
01344        if (drmmode->fb_id) {
01345               drmModeRmFB(drmmode->fd, drmmode->fb_id);
01346               drmmode->fb_id = 0;
01347        }
01348 
01349        dumb_bo_destroy(drmmode->fd, drmmode->front_bo);
01350        drmmode->front_bo = NULL;
01351 
01352        for (i = 0; i < xf86_config->num_crtc; i++) {
01353               xf86CrtcPtr crtc = xf86_config->crtc[i];
01354               drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
01355               dumb_bo_destroy(drmmode->fd, drmmode_crtc->cursor_bo);
01356        }
01357 }
01358 
01359 /* ugly workaround to see if we can create 32bpp */
01360 void drmmode_get_default_bpp(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int *depth, int *bpp)
01361 {
01362        drmModeResPtr mode_res;
01363        uint64_t value;
01364        struct dumb_bo *bo;
01365        uint32_t fb_id;
01366        int ret;
01367 
01368        /* 16 is fine */
01369        ret = drmGetCap(drmmode->fd, DRM_CAP_DUMB_PREFERRED_DEPTH, &value);
01370        if (!ret && (value == 16 || value == 8)) {
01371               *depth = value;
01372               *bpp = value;
01373               return;
01374        }
01375 
01376        *depth = 24;
01377        mode_res = drmModeGetResources(drmmode->fd);
01378        if (!mode_res)
01379               return;
01380 
01381        /*create a bo */
01382        bo = dumb_bo_create(drmmode->fd, mode_res->min_width, mode_res->min_height, 32);
01383        if (!bo) {
01384               *bpp = 24;
01385               goto out;
01386        }
01387 
01388        ret = drmModeAddFB(drmmode->fd, mode_res->min_width, mode_res->min_height,
01389                          24, 32, bo->pitch, bo->handle, &fb_id);
01390 
01391        if (ret) {
01392               *bpp = 24;
01393               dumb_bo_destroy(drmmode->fd, bo);
01394               goto out;
01395        }
01396 
01397        drmModeRmFB(drmmode->fd, fb_id);
01398        *bpp = 32;
01399 
01400        dumb_bo_destroy(drmmode->fd, bo);
01401 out:   
01402        drmModeFreeResources(mode_res);
01403        return;
01404 }