summaryrefslogtreecommitdiffstats
path: root/sys/dev/drm2
diff options
context:
space:
mode:
authordumbbell <dumbbell@FreeBSD.org>2014-11-22 17:37:51 +0000
committerdumbbell <dumbbell@FreeBSD.org>2014-11-22 17:37:51 +0000
commit2b470c5d7501426073ca250c41c34319c6ce4871 (patch)
treeef55755e5b4dc8f3c32f73dec74bec1c5944864a /sys/dev/drm2
parent395d6697ce00ffaceefdc18e548271866f962418 (diff)
downloadFreeBSD-src-2b470c5d7501426073ca250c41c34319c6ce4871.zip
FreeBSD-src-2b470c5d7501426073ca250c41c34319c6ce4871.tar.gz
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
Diffstat (limited to 'sys/dev/drm2')
-rw-r--r--sys/dev/drm2/drm_fb_helper.c233
-rw-r--r--sys/dev/drm2/drm_fb_helper.h17
2 files changed, 68 insertions, 182 deletions
diff --git a/sys/dev/drm2/drm_fb_helper.c b/sys/dev/drm2/drm_fb_helper.c
index 05f616e..20ee3fb 100644
--- a/sys/dev/drm2/drm_fb_helper.c
+++ b/sys/dev/drm2/drm_fb_helper.c
@@ -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_connectors(struct drm_fb_helper *fb_helper)
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_line(struct drm_fb_helper *fb_helper)
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 drm_fb_helper *fb_helper,
/* 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_preferred_mode(struct drm_fb_helper_conn
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_cmdline_mode(struct drm_fb_helper_conne
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
diff --git a/sys/dev/drm2/drm_fb_helper.h b/sys/dev/drm2/drm_fb_helper.h
index 4b5ef85..16ef7ee 100644
--- a/sys/dev/drm2/drm_fb_helper.h
+++ b/sys/dev/drm2/drm_fb_helper.h
@@ -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 {
OpenPOWER on IntegriCloud