aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_crtc_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_crtc_helper.c')
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c88
1 files changed, 83 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index fe8697447f32..1fe4e1d344fd 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,65 @@ 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;
283
284 if (!fb_help_conn)
285 return false;
286
287 cmdline_mode = &fb_help_conn->cmdline_mode;
288 return cmdline_mode->specified;
289}
290
291static struct drm_display_mode *drm_pick_cmdline_mode(struct drm_connector *connector, int width, int height)
292{
293 struct drm_fb_helper_connector *fb_help_conn = connector->fb_helper_private;
294 struct drm_fb_helper_cmdline_mode *cmdline_mode;
295 struct drm_display_mode *mode = NULL;
296
297 if (!fb_help_conn)
298 return mode;
299
300 cmdline_mode = &fb_help_conn->cmdline_mode;
301 if (cmdline_mode->specified == false)
302 return mode;
303
304 /* attempt to find a matching mode in the list of modes
305 * we have gotten so far, if not add a CVT mode that conforms
306 */
307 if (cmdline_mode->rb || cmdline_mode->margins)
308 goto create_mode;
309
310 list_for_each_entry(mode, &connector->modes, head) {
311 /* check width/height */
312 if (mode->hdisplay != cmdline_mode->xres ||
313 mode->vdisplay != cmdline_mode->yres)
314 continue;
315
316 if (cmdline_mode->refresh_specified) {
317 if (mode->vrefresh != cmdline_mode->refresh)
318 continue;
319 }
320
321 if (cmdline_mode->interlace) {
322 if (!(mode->flags & DRM_MODE_FLAG_INTERLACE))
323 continue;
324 }
325 return mode;
326 }
327
328create_mode:
329 mode = drm_cvt_mode(connector->dev, cmdline_mode->xres,
330 cmdline_mode->yres,
331 cmdline_mode->refresh_specified ? cmdline_mode->refresh : 60,
332 cmdline_mode->rb, cmdline_mode->interlace,
333 cmdline_mode->margins);
334 list_add(&mode->head, &connector->modes);
335 return mode;
336}
337
270static bool drm_connector_enabled(struct drm_connector *connector, bool strict) 338static bool drm_connector_enabled(struct drm_connector *connector, bool strict)
271{ 339{
272 bool enable; 340 bool enable;
@@ -317,10 +385,16 @@ static bool drm_target_preferred(struct drm_device *dev,
317 continue; 385 continue;
318 } 386 }
319 387
320 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", 388 DRM_DEBUG_KMS("looking for cmdline mode on connector %d\n",
321 connector->base.id); 389 connector->base.id);
322 390
323 modes[i] = drm_has_preferred_mode(connector, width, height); 391 /* got for command line mode first */
392 modes[i] = drm_pick_cmdline_mode(connector, width, height);
393 if (!modes[i]) {
394 DRM_DEBUG_KMS("looking for preferred mode on connector %d\n",
395 connector->base.id);
396 modes[i] = drm_has_preferred_mode(connector, width, height);
397 }
324 /* No preferred modes, pick one off the list */ 398 /* No preferred modes, pick one off the list */
325 if (!modes[i] && !list_empty(&connector->modes)) { 399 if (!modes[i] && !list_empty(&connector->modes)) {
326 list_for_each_entry(modes[i], &connector->modes, head) 400 list_for_each_entry(modes[i], &connector->modes, head)
@@ -369,6 +443,8 @@ static int drm_pick_crtcs(struct drm_device *dev,
369 my_score = 1; 443 my_score = 1;
370 if (connector->status == connector_status_connected) 444 if (connector->status == connector_status_connected)
371 my_score++; 445 my_score++;
446 if (drm_has_cmdline_mode(connector))
447 my_score++;
372 if (drm_has_preferred_mode(connector, width, height)) 448 if (drm_has_preferred_mode(connector, width, height))
373 my_score++; 449 my_score++;
374 450
@@ -943,6 +1019,8 @@ bool drm_helper_initial_config(struct drm_device *dev)
943{ 1019{
944 int count = 0; 1020 int count = 0;
945 1021
1022 drm_fb_helper_parse_command_line(dev);
1023
946 count = drm_helper_probe_connector_modes(dev, 1024 count = drm_helper_probe_connector_modes(dev,
947 dev->mode_config.max_width, 1025 dev->mode_config.max_width,
948 dev->mode_config.max_height); 1026 dev->mode_config.max_height);
@@ -950,7 +1028,7 @@ bool drm_helper_initial_config(struct drm_device *dev)
950 /* 1028 /*
951 * we shouldn't end up with no modes here. 1029 * we shouldn't end up with no modes here.
952 */ 1030 */
953 WARN(!count, "Connected connector with 0 modes\n"); 1031 WARN(!count, "No connectors reported connected with modes\n");
954 1032
955 drm_setup_crtcs(dev); 1033 drm_setup_crtcs(dev);
956 1034