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"