Hi,

I have a system using Xorg along with the xf86-video-fbdev display driver.
I'm using a xenfb fbdev driver in the kernel. I need to be able to
dynamically add new video modes to the driver at run-time and switch to it.

I believe this is only possible if the driver implements the RandR 1.2+
extension.
I wrote a little patch to implement the necessary interface to be able to
dynamically add video modes.

I am now able to add custom video modes and switch to it using the randr
tool. Unfortunately, for some reason, when I try to switch to a custom
video mode using libXRandR in a handmade C program, It fails with the
following error message: 

Changing Xorg resolution: X Error of failed request:  BadValue (integer 
parameter out of range for operation)
  Major opcode of failed request:  146 (RANDR)
  Minor opcode of failed request:  21 (RRSetCrtcConfig)
  Value in failed request:  0x0
  Serial number of failed request:  15
  Current serial number in output stream:  15

I haven't figured out why yet (maybe it has nothing to do with the
modifications I made to the driver).

Please tell me if there's something I'm doing wrong and if there's something
I can do to improve that stuff.

Thanks.

diff -ru xf86-video-fbdev-0.4.1-orig//src/fbdev.c 
xf86-video-fbdev-0.4.1//src/fbdev.c
--- xf86-video-fbdev-0.4.1-orig//src/fbdev.c    2010-09-10 18:05:46.000000000 
+0000
+++ xf86-video-fbdev-0.4.1//src/fbdev.c 2010-09-10 18:06:07.000000000 +0000
@@ -40,6 +40,9 @@
 #include <pciaccess.h>
 #endif
 
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+
 static Bool debug = 0;
 
 #define TRACE_ENTER(str) \
@@ -282,6 +285,13 @@
 }
 #endif
 
+static Bool
+FBDevSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
+{
+       ScrnInfoPtr scrn = xf86Screens[scrnIndex];
+
+       return xf86SetSingleMode(scrn, mode, RR_Rotate_0);
+}
 
 static Bool
 FBDevProbe(DriverPtr drv, int flags)
@@ -376,7 +386,7 @@
                    pScrn->Probe         = FBDevProbe;
                    pScrn->PreInit       = FBDevPreInit;
                    pScrn->ScreenInit    = FBDevScreenInit;
-                   pScrn->SwitchMode    = fbdevHWSwitchModeWeak();
+                   pScrn->SwitchMode    = FBDevSwitchMode;
                    pScrn->AdjustFrame   = fbdevHWAdjustFrameWeak();
                    pScrn->EnterVT       = fbdevHWEnterVTWeak();
                    pScrn->LeaveVT       = fbdevHWLeaveVTWeak();
@@ -393,12 +403,272 @@
 }
 
 static Bool
+FBDevCrtcResize(ScrnInfoPtr scrn, int width, int height)
+{
+        int bpp = scrn->bitsPerPixel;
+        ScreenPtr pScreen = scrn->pScreen;
+        PixmapPtr pPixmap = NULL;
+        Bool rc = TRUE;
+
+        if (width * height * bpp / 8 >= scrn->videoRam * 1024)
+        {
+                xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                           "Unable to set up a virtual screen size of %dx%d "
+                           "with %d Kb of video memory.\n",
+                           width, height, scrn->videoRam);
+                rc = FALSE;
+        }
+        if (rc) {
+                pPixmap = pScreen->GetScreenPixmap(pScreen);
+                if (NULL == pPixmap) {
+                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                                   "Failed to get the screen pixmap.\n");
+                        rc = FALSE;
+                }
+        }
+        if (rc) {
+                if (!pScreen->ModifyPixmapHeader(pPixmap, width, height,
+                                                 scrn->depth, bpp, width * bpp 
/ 8,
+                                                 NULL)) {
+                        xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                                            "Failed to set up the screen 
pixmap.\n");
+                        rc = FALSE;
+                }
+        }
+        if (rc) {
+                scrn->virtualX = width;
+                scrn->virtualY = height;
+                scrn->displayWidth = width;
+                /* Write the new values to the hardware */
+                rc = xf86SetDesiredModes(scrn);
+        }
+
+        return rc;
+}
+
+
+static const xf86CrtcConfigFuncsRec FBDevCrtcConfigFuncs = {
+        FBDevCrtcResize
+};
+
+static void
+FBDevCrtcDpms(xf86CrtcPtr crtc, int mode)
+{
+        (void) crtc;
+        (void) mode;
+}
+
+static Bool
+FBDevCrtcLock(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+
+        return FALSE;
+}
+
+static Bool
+FBDevCrtcModeFixup(xf86CrtcPtr crtc, DisplayModePtr mode,
+                   DisplayModePtr adjusted_mode)
+{
+        (void) mode;
+
+        return TRUE;
+}
+
+static void
+FBDevCrtcPrepare(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static void
+FBDevCrtcModeSet(xf86CrtcPtr crtc, DisplayModePtr mode,
+                 DisplayModePtr adjusted_mode, int x, int y)
+{
+        ScrnInfoPtr pScrn = crtc->scrn;
+
+        (void) mode;
+
+        fbdevHWSwitchMode(pScrn->scrnIndex, adjusted_mode, 0);
+        pScrn->AdjustFrame(crtc->scrn->scrnIndex, x, y, 0);
+}
+
+static void
+FBDevCrtcCommit(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static void
+FBDevCrtcGammaSet(xf86CrtcPtr crtc, CARD16 *red,
+                  CARD16 *green, CARD16 *blue, int size)
+{
+        (void) crtc;
+        (void) red;
+        (void) green;
+        (void) blue;
+        (void) size;
+}
+
+static void *
+FBDevCrtcShadowAllocate(xf86CrtcPtr crtc, int width, int height)
+{
+        (void) crtc;
+        (void) width;
+        (void) height;
+
+        return NULL;
+}
+
+static void
+FBDevCrtcDestroy(xf86CrtcPtr crtc)
+{
+        (void) crtc;
+}
+
+static const xf86CrtcFuncsRec FBDevCrtcFuncs = {
+        .dpms = FBDevCrtcDpms,
+        .save = NULL,
+        .restore = NULL,
+        .lock = FBDevCrtcLock,
+        .unlock = NULL,
+        .mode_fixup = FBDevCrtcModeFixup,
+        .prepare = FBDevCrtcPrepare,
+        .mode_set = FBDevCrtcModeSet,
+        .commit = FBDevCrtcCommit,
+        .gamma_set = FBDevCrtcGammaSet,
+        .shadow_allocate = FBDevCrtcShadowAllocate,
+        .shadow_create = NULL,
+        .shadow_destroy = NULL,
+        .set_cursor_colors = NULL,
+        .set_cursor_position = NULL,
+        .show_cursor = NULL,
+        .hide_cursor = NULL,
+        .load_cursor_argb = NULL,
+        .destroy = FBDevCrtcDestroy
+};
+
+static void
+FBDevOutputCreateResources(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputDpms(xf86OutputPtr output, int mode)
+{
+        (void) output;
+        (void) mode;
+}
+
+static int
+FBDevOutputModeValid(xf86OutputPtr output, DisplayModePtr mode)
+{
+        ScrnInfoPtr pScrn = output->scrn;
+        int rc = MODE_OK;
+
+        return rc;
+}
+
+static Bool
+FBDevOutputModeFixup(xf86OutputPtr output, DisplayModePtr mode,
+                     DisplayModePtr adjusted_mode)
+{
+        (void) output;
+        (void) mode;
+        (void) adjusted_mode;
+
+        return TRUE;
+}
+
+static void
+FBDevOutputPrepare(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputCommit(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+static void
+FBDevOutputModeSet(xf86OutputPtr output, DisplayModePtr mode,
+                   DisplayModePtr adjusted_mode)
+{
+        (void) output;
+        (void) mode;
+        (void) adjusted_mode;
+}
+
+static xf86OutputStatus
+FBDevOutputDetect(xf86OutputPtr output)
+{
+        (void) output;
+
+        return XF86OutputStatusConnected;
+}
+
+static DisplayModePtr
+FBDevOutputGetModes (xf86OutputPtr output)
+{
+        unsigned int i;
+        ScrnInfoPtr pScrn = output->scrn;
+        DisplayModePtr pModes = NULL;
+
+        return pModes;
+}
+
+static void
+FBDevOutputDestroy(xf86OutputPtr output)
+{
+        (void) output;
+}
+
+#ifdef RANDR_12_INTERFACE
+static Bool
+FBDevOutputSetProperty(xf86OutputPtr output, Atom property,
+                       RRPropertyValuePtr value)
+{
+        (void) output;
+        (void) property;
+        (void) value;
+
+        return FALSE;
+}
+#endif
+
+
+static const xf86OutputFuncsRec FBDevOutputFuncs = {
+        .create_resources = FBDevOutputCreateResources,
+        .dpms = FBDevOutputDpms,
+        .save = NULL,
+        .restore = NULL,
+        .mode_valid = FBDevOutputModeValid,
+        .mode_fixup = FBDevOutputModeFixup,
+        .prepare = FBDevOutputPrepare,
+        .commit = FBDevOutputCommit,
+        .mode_set = FBDevOutputModeSet,
+        .detect = FBDevOutputDetect,
+        .get_modes = FBDevOutputGetModes,
+#ifdef RANDR_12_INTERFACE
+        .set_property = FBDevOutputSetProperty,
+#endif
+        .destroy = FBDevOutputDestroy
+};
+
+static Bool
 FBDevPreInit(ScrnInfoPtr pScrn, int flags)
 {
        FBDevPtr fPtr;
        int default_depth, fbbpp;
        const char *mod = NULL, *s;
        int type;
+        int i;
+        ClockRangePtr clockRanges;
+        xf86OutputPtr output;
+        xf86CrtcPtr crtc;
 
        if (flags & PROBE_DETECT) return FALSE;
 
@@ -451,6 +721,19 @@
        if (!xf86SetDefaultVisual(pScrn, -1))
                return FALSE;
 
+        xf86CrtcConfigInit(pScrn, &FBDevCrtcConfigFuncs);
+        xf86CrtcSetSizeRange(pScrn, 64, 64, 32000, 32000);
+        crtc = xf86CrtcCreate(pScrn, &FBDevCrtcFuncs);
+        output = xf86OutputCreate(pScrn, &FBDevOutputFuncs, "FBDev");
+        xf86OutputUseScreenMonitor(output, FALSE);
+        output->possible_crtcs = 1;
+        output->possible_clones = 0;
+
+        if (!xf86InitialConfiguration(pScrn, TRUE)) {
+                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Initial CRTC 
configuration failed!\n");
+                return (FALSE);
+        }
+
        /* We don't currently support DirectColor at > 8bpp */
        if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "requested default visual"
@@ -470,10 +753,10 @@
        pScrn->progClock = TRUE;
        pScrn->rgbBits   = 8;
        pScrn->chipset   = "fbdev";
-       pScrn->videoRam  = fbdevHWGetVidmem(pScrn);
+       pScrn->videoRam  = fbdevHWGetVidmem(pScrn) / 1024;
 
        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "hardware: %s (video memory:"
-                  " %dkB)\n", fbdevHWGetName(pScrn), pScrn->videoRam/1024);
+                  " %dkB)\n", fbdevHWGetName(pScrn), pScrn->videoRam);
 
        /* handle options */
        xf86CollectOptions(pScrn, NULL);
@@ -521,26 +804,12 @@
          }
        }
 
-       /* select video modes */
-
-       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against 
framebuffer device...\n");
-       fbdevHWSetVideoModes(pScrn);
-
-       xf86DrvMsg(pScrn->scrnIndex, X_INFO, "checking modes against 
monitor...\n");
-       {
-               DisplayModePtr mode, first = mode = pScrn->modes;
-               
-               if (mode != NULL) do {
-                       mode->status = xf86CheckModeForMonitor(mode, 
pScrn->monitor);
-                       mode = mode->next;
-               } while (mode != NULL && mode != first);
-
-               xf86PruneDriverModes(pScrn);
+        if (pScrn->modes == NULL) {
+               xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n");
+               return FALSE;
        }
-
-       if (NULL == pScrn->modes)
-               fbdevHWUseBuildinMode(pScrn);
        pScrn->currentMode = pScrn->modes;
+        xf86CrtcSetMode(crtc, pScrn->currentMode, RR_Rotate_0, 0, 0);
 
        /* First approximation, may be refined in ScreenInit */
        pScrn->displayWidth = pScrn->virtualX;
@@ -930,6 +1199,8 @@
 
        xf86DPMSInit(pScreen, fbdevHWDPMSSetWeak(), 0);
 
+       xf86CrtcScreenInit(pScreen);
+
        pScreen->SaveScreen = fbdevHWSaveScreenWeak();
 
        /* Wrap the current CloseScreen function */




_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to