Author: dumbbell
Date: Sat Nov 22 17:37:51 2014
New Revision: 274865
URL: https://svnweb.freebsd.org/changeset/base/274865

Log:
  drm: Take vt(4) default mode from loader tunables
  
  By default, vt(4) gets the "preferred mode" from DRM, when using a DRM
  video driver as its backend. The preferred mode is usually the native
  screen resolution.
  
  Now, if this mode isn't appropriate, a user can use loader tunables to
  select a mode. The tunables are read in the following order:
      1. kern.vt.fb.modes.$connector_name
      2. kern.vt.fb.default_mode
  
  For example, to set a 1024x768 mode, no matter the connector:
      kern.vt.fb.default_mode="1024x768"
  
  To set a 800x600 mode only on the laptop builtin screen:
      kern.vt.fb.modes.LVDS-1="800x600"
  
  Beside r274031, this MFC includes:
  
  r274049:
    drm: When reading connector mode tunables, list connectors
  
    ... and their associated tunables. This gives a way to know the list of
    available connectors, no matter the driver.
  
    The problem is that xrandr(1) can list connectors but it uses a
    different naming.
  
  r274050:
    vt(4): Document kern.vt.fb.default_mode and kern.vt.fb.modes.*
  
    Those tunables are used to set a specific mode in vt(4) instead of using
    the default mode.
  
    Differential Revision:      https://reviews.freebsd.org/D1098
    Reviewed by:        ak@, emaste@, kwm@
  
  r274051:
    vt(4): Improve the description of kern.vt.fb.modes.$connector
  
    Differential Revision:      https://reviews.freebsd.org/D1098
    Submitted by:       emaste@
  
  r274053:
    vt(4): Start new sentences on their own lines
  
    Submitted by:       brueffer@
  
  MFC of:               r274031, r274049, r274050, r274051, r274053

Modified:
  stable/10/share/man/man4/vt.4
  stable/10/sys/dev/drm2/drm_fb_helper.c
  stable/10/sys/dev/drm2/drm_fb_helper.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man4/vt.4
==============================================================================
--- stable/10/share/man/man4/vt.4       Sat Nov 22 17:30:37 2014        
(r274864)
+++ stable/10/share/man/man4/vt.4       Sat Nov 22 17:37:51 2014        
(r274865)
@@ -45,6 +45,8 @@ In
 .Xr loader.conf 5 :
 .Cd hw.vga.textmode=1
 .Cd kern.vty=vt
+.Cd kern.vt.fb.default_mode="<X>x<Y>"
+.Cd kern.vt.fb.modes.<connector>="<X>x<Y>"
 .Pp
 In
 .Xr loader.conf 5 or
@@ -176,7 +178,7 @@ Otherwise,
 switches to 640x480x16 VGA mode using
 .Cm vt_vga .
 If a KMS
-.Pq Kernel Mode Switching
+.Pq Kernel Mode Setting
 video driver is available, the display is switched to high resolution
 and the KMS driver takes over.
 When a KMS driver is not available,
@@ -203,6 +205,30 @@ By default,
 is used on computers that boot from BIOS, and
 .Nm
 is used on computers that boot from UEFI.
+.It Va kern.vt.fb.default_mode
+Set this value to a graphic mode to override the default mode picked by the
+.Nm
+backend.
+The mode is applied to all output connectors.
+This is currently only supported by the
+.Cm vt_fb
+backend when it's paired with a KMS video driver.
+.It Va kern.vt.fb.modes. Ns Pa connector_name
+Set this value to a graphic mode to override the default mode picked by the
+.Nm
+backend.
+This mode is applied to the output connector
+.Pa connector_name
+only. It has precedence over
+.Va kern.vt.fb.default_mode .
+The names of available connector names can be found in
+.Xr dmesg 8
+after loading the KMS driver.
+It will contain a list of connectors and their associated tunables.
+This is currently only supported by the
+.Cm vt_fb
+backend when it's paired with a KMS video driver.
+.El
 .Sh KEYBOARD SYSCTL TUNABLES
 These settings control whether certain special key combinations are enabled or
 ignored.
@@ -255,6 +281,22 @@ This line changes the default color of k
 on a black background, or black on a bright red background when reversed.
 .Pp
 .Dl "options TERMINAL_KERN_ATTR=(FG_LIGHTRED|BG_BLACK)"
+.Pp
+To set a 1024x768 mode on all output connectors, put the following line in
+.Pa /boot/loader.conf :
+.Pp
+.Dl kern.vt.fb.default_mode="1024x768"
+.Pp
+To set a 800x600 only on a laptop builtin screen, use the following line 
instead:
+.Pp
+.Dl kern.vt.fb.modes.LVDS-1="800x600"
+.Pp
+The connector name was found in
+.Xr dmesg 8 :
+.Pp
+.Dl info: [drm] Connector LVDS-1: get mode from tunables:
+.Dl info: [drm]   - kern.vt.fb.modes.LVDS-1
+.Dl info: [drm]   - kern.vt.fb.default_mode
 .Sh SEE ALSO
 .Xr kbdcontrol 1 ,
 .Xr login 1 ,

Modified: stable/10/sys/dev/drm2/drm_fb_helper.c
==============================================================================
--- stable/10/sys/dev/drm2/drm_fb_helper.c      Sat Nov 22 17:30:37 2014        
(r274864)
+++ stable/10/sys/dev/drm2/drm_fb_helper.c      Sat Nov 22 17:37:51 2014        
(r274865)
@@ -38,6 +38,8 @@ __FBSDID("$FreeBSD$");
 
 
 #include <sys/kdb.h>
+#include <sys/param.h>
+#include <sys/systm.h>
 
 struct vt_kms_softc {
        struct drm_fb_helper *fb_helper;
@@ -97,170 +99,34 @@ int drm_fb_helper_single_add_all_connect
        return 0;
 }
 
-const char *fb_mode_option;
-
-/**
- * drm_fb_helper_connector_parse_command_line - parse command line for 
connector
- * @connector - connector to parse line for
- * @mode_option - per connector mode option
- *
- * This parses the connector specific then generic command lines for
- * modes and options to configure the connector.
- *
- * This uses the same parameters as the fb modedb.c, except for extra
- *     <xres>x<yres>[M][R][-<bpp>][@<refresh>][i][m][eDd]
- *
- * enable/enable Digital/disable bit at the end
- */
-static bool drm_fb_helper_connector_parse_command_line(struct 
drm_fb_helper_connector *fb_helper_conn,
-                                                      const char *mode_option)
-{
-       const char *name;
-       unsigned int namelen;
-       int res_specified = 0, bpp_specified = 0, refresh_specified = 0;
-       unsigned int xres = 0, yres = 0, bpp = 32, refresh = 0;
-       int yres_specified = 0, cvt = 0, rb = 0, interlace = 0, margins = 0;
-       int i;
-       enum drm_connector_force force = DRM_FORCE_UNSPECIFIED;
-       struct drm_fb_helper_cmdline_mode *cmdline_mode;
-       struct drm_connector *connector;
-
-       if (!fb_helper_conn)
-               return false;
-       connector = fb_helper_conn->connector;
-
-       cmdline_mode = &fb_helper_conn->cmdline_mode;
-       if (!mode_option)
-               mode_option = fb_mode_option;
-
-       if (!mode_option) {
-               cmdline_mode->specified = false;
-               return false;
-       }
-
-       name = mode_option;
-       namelen = strlen(name);
-       for (i = namelen-1; i >= 0; i--) {
-               switch (name[i]) {
-               case '@':
-                       namelen = i;
-                       if (!refresh_specified && !bpp_specified &&
-                           !yres_specified) {
-                               refresh = strtol(&name[i+1], NULL, 10);
-                               refresh_specified = 1;
-                               if (cvt || rb)
-                                       cvt = 0;
-                       } else
-                               goto done;
-                       break;
-               case '-':
-                       namelen = i;
-                       if (!bpp_specified && !yres_specified) {
-                               bpp = strtol(&name[i+1], NULL, 10);
-                               bpp_specified = 1;
-                               if (cvt || rb)
-                                       cvt = 0;
-                       } else
-                               goto done;
-                       break;
-               case 'x':
-                       if (!yres_specified) {
-                               yres = strtol(&name[i+1], NULL, 10);
-                               yres_specified = 1;
-                       } else
-                               goto done;
-               case '0' ... '9':
-                       break;
-               case 'M':
-                       if (!yres_specified)
-                               cvt = 1;
-                       break;
-               case 'R':
-                       if (cvt)
-                               rb = 1;
-                       break;
-               case 'm':
-                       if (!cvt)
-                               margins = 1;
-                       break;
-               case 'i':
-                       if (!cvt)
-                               interlace = 1;
-                       break;
-               case 'e':
-                       force = DRM_FORCE_ON;
-                       break;
-               case 'D':
-                       if ((connector->connector_type != 
DRM_MODE_CONNECTOR_DVII) &&
-                           (connector->connector_type != 
DRM_MODE_CONNECTOR_HDMIB))
-                               force = DRM_FORCE_ON;
-                       else
-                               force = DRM_FORCE_ON_DIGITAL;
-                       break;
-               case 'd':
-                       force = DRM_FORCE_OFF;
-                       break;
-               default:
-                       goto done;
-               }
-       }
-       if (i < 0 && yres_specified) {
-               xres = strtol(name, NULL, 10);
-               res_specified = 1;
-       }
-done:
-
-       DRM_DEBUG_KMS("cmdline mode for connector %s %dx%d@%dHz%s%s%s\n",
-               drm_get_connector_name(connector), xres, yres,
-               (refresh) ? refresh : 60, (rb) ? " reduced blanking" :
-               "", (margins) ? " with margins" : "", (interlace) ?
-               " interlaced" : "");
-
-       if (force) {
-               const char *s;
-               switch (force) {
-               case DRM_FORCE_OFF: s = "OFF"; break;
-               case DRM_FORCE_ON_DIGITAL: s = "ON - dig"; break;
-               default:
-               case DRM_FORCE_ON: s = "ON"; break;
-               }
-
-               DRM_INFO("forcing %s connector %s\n",
-                        drm_get_connector_name(connector), s);
-               connector->force = force;
-       }
-
-       if (res_specified) {
-               cmdline_mode->specified = true;
-               cmdline_mode->xres = xres;
-               cmdline_mode->yres = yres;
-       }
-
-       if (refresh_specified) {
-               cmdline_mode->refresh_specified = true;
-               cmdline_mode->refresh = refresh;
-       }
-
-       if (bpp_specified) {
-               cmdline_mode->bpp_specified = true;
-               cmdline_mode->bpp = bpp;
-       }
-       cmdline_mode->rb = rb ? true : false;
-       cmdline_mode->cvt = cvt  ? true : false;
-       cmdline_mode->interlace = interlace ? true : false;
-
-       return true;
-}
-
 static int
 fb_get_options(const char *connector_name, char **option)
 {
+       char tunable[64];
 
        /*
-        * TODO: store mode options pointer in ${option} for connector with
-        * name ${connector_name}
+        * A user may use loader tunables to set a specific mode for the
+        * console. Tunables are read in the following order:
+        *     1. kern.vt.fb.modes.$connector_name
+        *     2. kern.vt.fb.default_mode
+        *
+        * Example of a mode specific to the LVDS connector:
+        *     kern.vt.fb.modes.LVDS="1024x768"
+        *
+        * Example of a mode applied to all connectors not having a
+        * connector-specific mode:
+        *     kern.vt.fb.default_mode="640x480"
         */
-       return (1);
+       snprintf(tunable, sizeof(tunable), "kern.vt.fb.modes.%s",
+           connector_name);
+       DRM_INFO("Connector %s: get mode from tunables:\n", connector_name);
+       DRM_INFO("  - %s\n", tunable);
+       DRM_INFO("  - kern.vt.fb.default_mode\n");
+       *option = getenv(tunable);
+       if (*option == NULL)
+               *option = getenv("kern.vt.fb.default_mode");
+
+       return (*option != NULL ? 0 : 1);
 }
 
 static int drm_fb_helper_parse_command_line(struct drm_fb_helper *fb_helper)
@@ -269,15 +135,52 @@ static int drm_fb_helper_parse_command_l
        int i;
 
        for (i = 0; i < fb_helper->connector_count; i++) {
+               struct drm_cmdline_mode *mode;
+               struct drm_connector *connector;
                char *option = NULL;
 
                fb_helper_conn = fb_helper->connector_info[i];
+               connector = fb_helper_conn->connector;
+               mode = &fb_helper_conn->cmdline_mode;
 
                /* do something on return - turn off connector maybe */
-               if 
(fb_get_options(drm_get_connector_name(fb_helper_conn->connector), &option))
+               if (fb_get_options(drm_get_connector_name(connector), &option))
                        continue;
 
-               drm_fb_helper_connector_parse_command_line(fb_helper_conn, 
option);
+               if (drm_mode_parse_command_line_for_connector(option,
+                                                             connector,
+                                                             mode)) {
+                       if (mode->force) {
+                               const char *s;
+                               switch (mode->force) {
+                               case DRM_FORCE_OFF:
+                                       s = "OFF";
+                                       break;
+                               case DRM_FORCE_ON_DIGITAL:
+                                       s = "ON - dig";
+                                       break;
+                               default:
+                               case DRM_FORCE_ON:
+                                       s = "ON";
+                                       break;
+                               }
+
+                               DRM_INFO("forcing %s connector %s\n",
+                                        drm_get_connector_name(connector), s);
+                               connector->force = mode->force;
+                       }
+
+                       DRM_INFO("cmdline mode for connector %s 
%dx%d@%dHz%s%s%s\n",
+                                     drm_get_connector_name(connector),
+                                     mode->xres, mode->yres,
+                                     mode->refresh_specified ? mode->refresh : 
60,
+                                     mode->rb ? " reduced blanking" : "",
+                                     mode->margins ? " with margins" : "",
+                                     mode->interlace ?  " interlaced" : "");
+               }
+
+               freeenv(option);
+
        }
        return 0;
 }
@@ -956,7 +859,7 @@ int drm_fb_helper_single_fb_probe(struct
        /* first up get a count of crtcs now in use and new min/maxes 
width/heights */
        for (i = 0; i < fb_helper->connector_count; i++) {
                struct drm_fb_helper_connector *fb_helper_conn = 
fb_helper->connector_info[i];
-               struct drm_fb_helper_cmdline_mode *cmdline_mode;
+               struct drm_cmdline_mode *cmdline_mode;
 
                cmdline_mode = &fb_helper_conn->cmdline_mode;
 
@@ -1181,7 +1084,7 @@ static struct drm_display_mode *drm_has_
 
 static bool drm_has_cmdline_mode(struct drm_fb_helper_connector *fb_connector)
 {
-       struct drm_fb_helper_cmdline_mode *cmdline_mode;
+       struct drm_cmdline_mode *cmdline_mode;
        cmdline_mode = &fb_connector->cmdline_mode;
        return cmdline_mode->specified;
 }
@@ -1192,10 +1095,8 @@ static struct drm_display_mode *drm_pick
        struct drm_cmdline_mode *cmdline_mode;
        struct drm_display_mode *mode = NULL;
 
-       cmdline_mode = &fb_helper_conn->cmdline_mode1;
-       if (cmdline_mode->specified == false &&
-           !drm_fetch_cmdline_mode_from_kenv(fb_helper_conn->connector,
-           cmdline_mode))
+       cmdline_mode = &fb_helper_conn->cmdline_mode;
+       if (cmdline_mode->specified == false)
                        return (NULL);
 
        /* attempt to find a matching mode in the list of modes

Modified: stable/10/sys/dev/drm2/drm_fb_helper.h
==============================================================================
--- stable/10/sys/dev/drm2/drm_fb_helper.h      Sat Nov 22 17:30:37 2014        
(r274864)
+++ stable/10/sys/dev/drm2/drm_fb_helper.h      Sat Nov 22 17:37:51 2014        
(r274865)
@@ -40,20 +40,6 @@ struct drm_fb_helper_crtc {
        struct drm_display_mode *desired_mode;
 };
 
-/* mode specified on the command line */
-struct drm_fb_helper_cmdline_mode {
-       bool specified;
-       bool refresh_specified;
-       bool bpp_specified;
-       int xres, yres;
-       int bpp;
-       int refresh;
-       bool rb;
-       bool interlace;
-       bool cvt;
-       bool margins;
-};
-
 struct drm_fb_helper_surface_size {
        u32 fb_width;
        u32 fb_height;
@@ -74,9 +60,8 @@ struct drm_fb_helper_funcs {
 };
 
 struct drm_fb_helper_connector {
-       struct drm_fb_helper_cmdline_mode cmdline_mode;
-       struct drm_cmdline_mode cmdline_mode1;
        struct drm_connector *connector;
+       struct drm_cmdline_mode cmdline_mode;
 };
 
 struct drm_fb_helper {
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to