Add raw modeline support.
authorScott Moreau <oreaus@gmail.com>
Tue, 31 Jul 2012 21:30:41 +0000 (15:30 -0600)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 1 Aug 2012 02:38:21 +0000 (22:38 -0400)
This allows specifying a modeline in the config for the 'mode' key
in the output section, such as one you would get from cvt.

src/compositor-drm.c
weston.ini

index 24e454c..2075a99 100644 (file)
@@ -53,13 +53,15 @@ enum output_config {
        OUTPUT_CONFIG_OFF,
        OUTPUT_CONFIG_PREFERRED,
        OUTPUT_CONFIG_CURRENT,
-       OUTPUT_CONFIG_MODE
+       OUTPUT_CONFIG_MODE,
+       OUTPUT_CONFIG_MODELINE
 };
 
 struct drm_configured_output {
        char *name;
        char *mode;
        int32_t width, height;
+       drmModeModeInfo crtc_mode;
        enum output_config config;
        struct wl_list link;
 };
@@ -1397,7 +1399,8 @@ create_output_for_connector(struct drm_compositor *ec,
 
        wl_list_for_each(drm_mode, &output->base.mode_list, base.link) {
                if (o && o->width == drm_mode->base.width &&
-                       o->height == drm_mode->base.height)
+                       o->height == drm_mode->base.height &&
+                       o->config == OUTPUT_CONFIG_MODE)
                        configured = &drm_mode->base;
                if (!memcmp(&crtc_mode, &drm_mode->mode_info, sizeof crtc_mode))
                        current = &drm_mode->base;
@@ -1405,6 +1408,15 @@ create_output_for_connector(struct drm_compositor *ec,
                        preferred = &drm_mode->base;
        }
 
+       if (o && o->config == OUTPUT_CONFIG_MODELINE) {
+               ret = drm_output_add_mode(output, &o->crtc_mode);
+               if (ret)
+                       goto err_free;
+               configured = container_of(output->base.mode_list.prev,
+                                      struct weston_mode, link);
+               current = configured;
+       }
+
        if (current == NULL && crtc_mode.clock != 0) {
                ret = drm_output_add_mode(output, &crtc_mode);
                if (ret)
@@ -2043,6 +2055,65 @@ err_base:
        return NULL;
 }
 
+static int
+set_sync_flags(drmModeModeInfo *mode, char *hsync, char *vsync)
+{
+       mode->flags = 0;
+
+       if (strcmp(hsync, "+hsync") == 0)
+               mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else if (strcmp(hsync, "-hsync") == 0)
+               mode->flags |= DRM_MODE_FLAG_NHSYNC;
+       else
+               return -1;
+
+       if (strcmp(vsync, "+vsync") == 0)
+               mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else if (strcmp(vsync, "-vsync") == 0)
+               mode->flags |= DRM_MODE_FLAG_NVSYNC;
+       else
+               return -1;
+
+       return 0;
+}
+
+static int
+check_for_modeline(struct drm_configured_output *output)
+{
+       drmModeModeInfo mode;
+       char hsync[16];
+       char vsync[16];
+       char mode_name[16];
+       float fclock;
+
+       mode.type = DRM_MODE_TYPE_USERDEF;
+       mode.hskew = 0;
+       mode.vscan = 0;
+       mode.vrefresh = 0;
+
+       if (sscanf(output_mode, "%f %hd %hd %hd %hd %hd %hd %hd %hd %s %s",
+                                               &fclock, &mode.hdisplay,
+                                               &mode.hsync_start,
+                                               &mode.hsync_end, &mode.htotal,
+                                               &mode.vdisplay,
+                                               &mode.vsync_start,
+                                               &mode.vsync_end, &mode.vtotal,
+                                               hsync, vsync) == 11) {
+               if (set_sync_flags(&mode, hsync, vsync))
+                       return -1;
+
+               sprintf(mode_name, "%dx%d", mode.hdisplay, mode.vdisplay);
+               strcpy(mode.name, mode_name);
+
+               mode.clock = fclock * 1000;
+       } else
+               return -1;
+
+       output->crtc_mode = mode;
+
+       return 0;
+}
+
 static void
 output_section_done(void *data)
 {
@@ -2070,6 +2141,8 @@ output_section_done(void *data)
                output->config = OUTPUT_CONFIG_CURRENT;
        else if (sscanf(output_mode, "%dx%d", &output->width, &output->height) == 2)
                output->config = OUTPUT_CONFIG_MODE;
+       else if (check_for_modeline(output) == 0)
+               output->config = OUTPUT_CONFIG_MODELINE;
 
        if (output->config != OUTPUT_CONFIG_INVALID)
                wl_list_insert(&configured_output_list, &output->link);
index 375f4ee..c2d6369 100644 (file)
@@ -36,8 +36,8 @@ duration=600
 
 #[output]
 #name=LVDS1
-#mode=off
+#mode=1680x1050
 
 #[output]
 #name=VGA1
-#mode=1280x1024
+#mode=173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync