aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc_helper.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2009-09-23 00:44:08 -0400
committerDave Airlie <airlied@linux.ie>2009-09-24 23:08:20 -0400
commitd50ba256b5f1478e15accfcfda9b72fd7a661364 (patch)
tree7148b1294057a734ecdbc62b7df7ed0397adfeb4 /drivers/gpu/drm/drm_crtc_helper.c
parentf80330357284c908e1f67cc8b4d8e56a3e2f6fc6 (diff)
drm/kms: start adding command line interface using fb.
[note this requires an fb patch posted to linux-fbdev-devel already] This uses the normal video= command line option to control the kms output setup at boot time. It is used to override the autodetection done by kms. video= normally takes a framebuffer as the first parameter, in kms it will take a connector name, DVI-I-1, or LVDS-1 etc. If no output connector is specified the mode string will apply to all connectors. The mode specification used will match down the probed modes, and if no mode is found it will add a CVT mode that matches. video=1024x768 - all connectors match a 1024x768 mode or add a CVT on video=VGA-1:1024x768, VGA-1 connector gets mode only. The same strings as used in current fb modedb.c are used, except I've added three more letters, e, D, d, e = enable, D = enable Digital, d = disable, which allow a connector to be forced into a certain state. Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c79
1 files changed, 74 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index fe8697447f32..82fd6e82450f 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -32,6 +32,7 @@
32#include "drmP.h" 32#include "drmP.h"
33#include "drm_crtc.h" 33#include "drm_crtc.h"
34#include "drm_crtc_helper.h" 34#include "drm_crtc_helper.h"
35#include "drm_fb_helper.h"
35 36
36static void drm_mode_validate_flag(struct drm_connector *connector, 37static void drm_mode_validate_flag(struct drm_connector *connector,
37 int flags) 38 int flags)
@@ -90,7 +91,15 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
90 list_for_each_entry_safe(mode, t, &connector->modes, head) 91 list_for_each_entry_safe(mode, t, &connector->modes, head)
91 mode->status = MODE_UNVERIFIED; 92 mode->status = MODE_UNVERIFIED;
92 93
93 connector->status = connector->funcs->detect(connector); 94 if (connector->force) {
95 if (connector->force == DRM_FORCE_ON)
96 connector->status = connector_status_connected;
97 else
98 connector->status = connector_status_disconnected;
99 if (connector->funcs->force)
100 connector->funcs->force(connector);
101 } else
102 connector->status = connector->funcs->detect(connector);
94 103
95 if (connector->status == connector_status_disconnected) { 104 if (connector->status == connector_status_disconnected) {
96 DRM_DEBUG_KMS("%s is disconnected\n", 105 DRM_DEBUG_KMS("%s is disconnected\n",
@@ -267,6 +276,56 @@ static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *con
267 return NULL; 276 return NULL;
268} 277}
269 278
279static bool drm_has_cmdline_mode(struct drm_connector *connector)
280{
281 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
282 struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode;
283 return cmdline_mode->specified;
284}
285
286static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height)
287{
288 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
289 struct drm_fb_helper_cmdline_mode *cmdline_mode = &fb_help_conn->cmdline_mode;
290 struct drm_display_mode *mode = NULL;
291
292 if (cmdline_mode->specified == false)
293 return mode;
294
295 /* attempt to find a matching mode in the list of modes
296 * we have gotten so far, if not add a CVT mode that conforms
297 */
298 if (cmdline_mode->rb || cmdline_mode->margins)
299 goto create_mode;
300
301 list_for_each_entry(mode, &connector->modes, head) {
302 /* check width/height */
303 if (mode->hdisplay != cmdline_mode->xres ||
304 mode->vdisplay != cmdline_mode->yres)
305 continue;
306
307 if (cmdline_mode->refresh_specified) {
308 if (mode->vrefresh != cmdline_mode->refresh)
309 continue;
310 }
311
312 if (cmdline_mode->interlace) {
313 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
314 continue;
315 }
316 return mode;
317 }
318
319create_mode:
320 mode = drm_cvt_mode(connector->dev, cmdline_mode->xres,
321 cmdline_mode->yres,
322 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
323 cmdline_mode->rb, cmdline_mode->interlace,
324 cmdline_mode->margins);
325 list_add(&mode->head, &connector->modes);
326 return mode;
327}
328
270static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 329static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
271{ 330{
272 bool enable; 331 bool enable;
@@ -317,10 +376,16 @@ static bool drm_target_preferred(struct drm_device *dev,
317 continue; 376 continue;
318 } 377 }
319 378
320 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", 379 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
321 connector->base.id); 380 connector->base.id);
322 381
323 modes[i] = drm_has_preferred_mode(connector, width, height); 382 /* got for command line mode first */
383 modes[i] = drm_pick_cmdline_mode(connector, width, height);
384 if (!modes[i]) {
385 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
386 connector->base.id);
387 modes[i] = drm_has_preferred_mode(connector, width, height);
388 }
324 /* No preferred modes, pick one off the list */ 389 /* No preferred modes, pick one off the list */
325 if (!modes[i] && !list_empty(&connector->modes)) { 390 if (!modes[i] && !list_empty(&connector->modes)) {
326 list_for_each_entry(modes[i], &connector->modes, head) 391 list_for_each_entry(modes[i], &connector->modes, head)
@@ -369,6 +434,8 @@ static int drm_pick_crtcs(struct drm_device *dev,
369 my_score = 1; 434 my_score = 1;
370 if (connector->status == connector_status_connected) 435 if (connector->status == connector_status_connected)
371 my_score++; 436 my_score++;
437 if (drm_has_cmdline_mode(connector))
438 my_score++;
372 if (drm_has_preferred_mode(connector, width, height)) 439 if (drm_has_preferred_mode(connector, width, height))
373 my_score++; 440 my_score++;
374 441
@@ -943,6 +1010,8 @@ bool drm_helper_initial_config(struct drm_device *dev)
943{ 1010{
944 int count = 0; 1011 int count = 0;
945 1012
1013 drm_fb_helper_parse_command_line(dev);
1014
946 count = drm_helper_probe_connector_modes(dev, 1015 count = drm_helper_probe_connector_modes(dev,
947 dev->mode_config.max_width, 1016 dev->mode_config.max_width,
948 dev->mode_config.max_height); 1017 dev->mode_config.max_height);
@@ -950,7 +1019,7 @@ bool drm_helper_initial_config(struct drm_device *dev)
950 /* 1019 /*
951 * we shouldn't end up with no modes here. 1020 * we shouldn't end up with no modes here.
952 */ 1021 */
953 WARN(!count, "Connected connector with 0 modes\n"); 1022 WARN(!count, "No connectors reported connected with modes\n");
954 1023
955 drm_setup_crtcs(dev); 1024 drm_setup_crtcs(dev);
956 1025