Author: dumbbell Date: Mon Nov 3 10:42:27 2014 New Revision: 274031 URL: https://svnweb.freebsd.org/changeset/base/274031
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" MFC after: 1 week Modified: head/sys/dev/drm2/drm_fb_helper.c head/sys/dev/drm2/drm_fb_helper.h Modified: head/sys/dev/drm2/drm_fb_helper.c ============================================================================== --- head/sys/dev/drm2/drm_fb_helper.c Mon Nov 3 10:38:22 2014 (r274030) +++ head/sys/dev/drm2/drm_fb_helper.c Mon Nov 3 10:42:27 2014 (r274031) @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <dev/drm2/drm_crtc_helper.h> #include <sys/kdb.h> +#include <sys/param.h> +#include <sys/systm.h> struct vt_kms_softc { struct drm_fb_helper *fb_helper; @@ -96,170 +98,31 @@ 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); + *option = kern_getenv(tunable); + if (*option == NULL) + *option = kern_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) @@ -268,15 +131,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; } @@ -955,7 +855,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; @@ -1180,7 +1080,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; } @@ -1191,10 +1091,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: head/sys/dev/drm2/drm_fb_helper.h ============================================================================== --- head/sys/dev/drm2/drm_fb_helper.h Mon Nov 3 10:38:22 2014 (r274030) +++ head/sys/dev/drm2/drm_fb_helper.h Mon Nov 3 10:42:27 2014 (r274031) @@ -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"