aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c127
-rw-r--r--include/drm/drm_crtc.h2
-rw-r--r--include/drm/drm_crtc_helper.h2
3 files changed, 95 insertions, 36 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index d8a982b71296..e490e69db21e 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -36,7 +36,7 @@
36/* 36/*
37 * Detailed mode info for 800x600@60Hz 37 * Detailed mode info for 800x600@60Hz
38 */ 38 */
39static struct drm_display_mode std_mode[] = { 39static struct drm_display_mode std_modes[] = {
40 { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, 40 { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840,
41 968, 1056, 0, 600, 601, 605, 628, 0, 41 968, 1056, 0, 600, 601, 605, 628, 0,
42 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, 42 DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -60,15 +60,18 @@ static struct drm_display_mode std_mode[] = {
60 * changes have occurred. 60 * changes have occurred.
61 * 61 *
62 * FIXME: take into account monitor limits 62 * FIXME: take into account monitor limits
63 *
64 * RETURNS:
65 * Number of modes found on @connector.
63 */ 66 */
64void drm_helper_probe_single_connector_modes(struct drm_connector *connector, 67int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
65 uint32_t maxX, uint32_t maxY) 68 uint32_t maxX, uint32_t maxY)
66{ 69{
67 struct drm_device *dev = connector->dev; 70 struct drm_device *dev = connector->dev;
68 struct drm_display_mode *mode, *t; 71 struct drm_display_mode *mode, *t;
69 struct drm_connector_helper_funcs *connector_funcs = 72 struct drm_connector_helper_funcs *connector_funcs =
70 connector->helper_private; 73 connector->helper_private;
71 int ret; 74 int count = 0;
72 75
73 DRM_DEBUG("%s\n", drm_get_connector_name(connector)); 76 DRM_DEBUG("%s\n", drm_get_connector_name(connector));
74 /* set all modes to the unverified state */ 77 /* set all modes to the unverified state */
@@ -81,14 +84,14 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
81 DRM_DEBUG("%s is disconnected\n", 84 DRM_DEBUG("%s is disconnected\n",
82 drm_get_connector_name(connector)); 85 drm_get_connector_name(connector));
83 /* TODO set EDID to NULL */ 86 /* TODO set EDID to NULL */
84 return; 87 return 0;
85 } 88 }
86 89
87 ret = (*connector_funcs->get_modes)(connector); 90 count = (*connector_funcs->get_modes)(connector);
91 if (!count)
92 return 0;
88 93
89 if (ret) { 94 drm_mode_connector_list_update(connector);
90 drm_mode_connector_list_update(connector);
91 }
92 95
93 if (maxX && maxY) 96 if (maxX && maxY)
94 drm_mode_validate_size(dev, &connector->modes, maxX, 97 drm_mode_validate_size(dev, &connector->modes, maxX,
@@ -102,25 +105,8 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
102 105
103 drm_mode_prune_invalid(dev, &connector->modes, true); 106 drm_mode_prune_invalid(dev, &connector->modes, true);
104 107
105 if (list_empty(&connector->modes)) { 108 if (list_empty(&connector->modes))
106 struct drm_display_mode *stdmode; 109 return 0;
107
108 DRM_DEBUG("No valid modes on %s\n",
109 drm_get_connector_name(connector));
110
111 /* Should we do this here ???
112 * When no valid EDID modes are available we end up
113 * here and bailed in the past, now we add a standard
114 * 640x480@60Hz mode and carry on.
115 */
116 stdmode = drm_mode_duplicate(dev, &std_mode[0]);
117 drm_mode_probed_add(connector, stdmode);
118 drm_mode_list_concat(&connector->probed_modes,
119 &connector->modes);
120
121 DRM_DEBUG("Adding standard 640x480 @ 60Hz to %s\n",
122 drm_get_connector_name(connector));
123 }
124 110
125 drm_mode_sort(&connector->modes); 111 drm_mode_sort(&connector->modes);
126 112
@@ -131,20 +117,58 @@ void drm_helper_probe_single_connector_modes(struct drm_connector *connector,
131 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); 117 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
132 drm_mode_debug_printmodeline(mode); 118 drm_mode_debug_printmodeline(mode);
133 } 119 }
120
121 return count;
134} 122}
135EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); 123EXPORT_SYMBOL(drm_helper_probe_single_connector_modes);
136 124
137void drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX, 125int drm_helper_probe_connector_modes(struct drm_device *dev, uint32_t maxX,
138 uint32_t maxY) 126 uint32_t maxY)
139{ 127{
140 struct drm_connector *connector; 128 struct drm_connector *connector;
129 int count = 0;
141 130
142 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 131 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
143 drm_helper_probe_single_connector_modes(connector, maxX, maxY); 132 count += drm_helper_probe_single_connector_modes(connector,
133 maxX, maxY);
144 } 134 }
135
136 return count;
145} 137}
146EXPORT_SYMBOL(drm_helper_probe_connector_modes); 138EXPORT_SYMBOL(drm_helper_probe_connector_modes);
147 139
140static void drm_helper_add_std_modes(struct drm_device *dev,
141 struct drm_connector *connector)
142{
143 struct drm_display_mode *mode, *t;
144 int i;
145
146 for (i = 0; i < ARRAY_SIZE(std_modes); i++) {
147 struct drm_display_mode *stdmode;
148
149 /*
150 * When no valid EDID modes are available we end up
151 * here and bailed in the past, now we add some standard
152 * modes and move on.
153 */
154 stdmode = drm_mode_duplicate(dev, &std_modes[i]);
155 drm_mode_probed_add(connector, stdmode);
156 drm_mode_list_concat(&connector->probed_modes,
157 &connector->modes);
158
159 DRM_DEBUG("Adding mode %s to %s\n", stdmode->name,
160 drm_get_connector_name(connector));
161 }
162 drm_mode_sort(&connector->modes);
163
164 DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector));
165 list_for_each_entry_safe(mode, t, &connector->modes, head) {
166 mode->vrefresh = drm_mode_vrefresh(mode);
167
168 drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
169 drm_mode_debug_printmodeline(mode);
170 }
171}
148 172
149/** 173/**
150 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config 174 * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config
@@ -237,6 +261,8 @@ static void drm_enable_connectors(struct drm_device *dev, bool *enabled)
237 261
238 list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 262 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
239 enabled[i] = drm_connector_enabled(connector, true); 263 enabled[i] = drm_connector_enabled(connector, true);
264 DRM_DEBUG("connector %d enabled? %s\n", connector->base.id,
265 enabled[i] ? "yes" : "no");
240 any_enabled |= enabled[i]; 266 any_enabled |= enabled[i];
241 i++; 267 i++;
242 } 268 }
@@ -265,11 +291,17 @@ static bool drm_target_preferred(struct drm_device *dev,
265 continue; 291 continue;
266 } 292 }
267 293
294 DRM_DEBUG("looking for preferred mode on connector %d\n",
295 connector->base.id);
296
268 modes[i] = drm_has_preferred_mode(connector, width, height); 297 modes[i] = drm_has_preferred_mode(connector, width, height);
269 if (!modes[i]) { 298 /* No preferred modes, pick one off the list */
299 if (!modes[i] && !list_empty(&connector->modes)) {
270 list_for_each_entry(modes[i], &connector->modes, head) 300 list_for_each_entry(modes[i], &connector->modes, head)
271 break; 301 break;
272 } 302 }
303 DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name :
304 "none");
273 i++; 305 i++;
274 } 306 }
275 return true; 307 return true;
@@ -369,6 +401,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
369 int width, height; 401 int width, height;
370 int i, ret; 402 int i, ret;
371 403
404 DRM_DEBUG("\n");
405
372 width = dev->mode_config.max_width; 406 width = dev->mode_config.max_width;
373 height = dev->mode_config.max_height; 407 height = dev->mode_config.max_height;
374 408
@@ -390,6 +424,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
390 if (!ret) 424 if (!ret)
391 DRM_ERROR("Unable to find initial modes\n"); 425 DRM_ERROR("Unable to find initial modes\n");
392 426
427 DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height);
428
393 drm_pick_crtcs(dev, crtcs, modes, 0, width, height); 429 drm_pick_crtcs(dev, crtcs, modes, 0, width, height);
394 430
395 i = 0; 431 i = 0;
@@ -403,6 +439,8 @@ static void drm_setup_crtcs(struct drm_device *dev)
403 } 439 }
404 440
405 if (mode && crtc) { 441 if (mode && crtc) {
442 DRM_DEBUG("desired mode %s set on crtc %d\n",
443 mode->name, crtc->base.id);
406 crtc->desired_mode = mode; 444 crtc->desired_mode = mode;
407 connector->encoder->crtc = crtc; 445 connector->encoder->crtc = crtc;
408 } else 446 } else
@@ -764,10 +802,31 @@ bool drm_helper_plugged_event(struct drm_device *dev)
764 */ 802 */
765bool drm_helper_initial_config(struct drm_device *dev, bool can_grow) 803bool drm_helper_initial_config(struct drm_device *dev, bool can_grow)
766{ 804{
767 int ret = false; 805 struct drm_connector *connector;
806 int count = 0;
768 807
769 drm_helper_plugged_event(dev); 808 count = drm_helper_probe_connector_modes(dev,
770 return ret; 809 dev->mode_config.max_width,
810 dev->mode_config.max_height);
811
812 /*
813 * None of the available connectors had any modes, so add some
814 * and try to light them up anyway
815 */
816 if (!count) {
817 DRM_ERROR("connectors have no modes, using standard modes\n");
818 list_for_each_entry(connector,
819 &dev->mode_config.connector_list,
820 head)
821 drm_helper_add_std_modes(dev, connector);
822 }
823
824 drm_setup_crtcs(dev);
825
826 /* alert the driver fb layer */
827 dev->mode_config.funcs->fb_changed(dev);
828
829 return 0;
771} 830}
772EXPORT_SYMBOL(drm_helper_initial_config); 831EXPORT_SYMBOL(drm_helper_initial_config);
773 832
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0acb07f31fa4..47809ac94bc3 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -395,7 +395,7 @@ struct drm_connector_funcs {
395 void (*save)(struct drm_connector *connector); 395 void (*save)(struct drm_connector *connector);
396 void (*restore)(struct drm_connector *connector); 396 void (*restore)(struct drm_connector *connector);
397 enum drm_connector_status (*detect)(struct drm_connector *connector); 397 enum drm_connector_status (*detect)(struct drm_connector *connector);
398 void (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); 398 int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
399 int (*set_property)(struct drm_connector *connector, struct drm_property *property, 399 int (*set_property)(struct drm_connector *connector, struct drm_property *property,
400 uint64_t val); 400 uint64_t val);
401 void (*destroy)(struct drm_connector *connector); 401 void (*destroy)(struct drm_connector *connector);
diff --git a/include/drm/drm_crtc_helper.h b/include/drm/drm_crtc_helper.h
index 4bc04cf460a7..0c6f0e11b41b 100644
--- a/include/drm/drm_crtc_helper.h
+++ b/include/drm/drm_crtc_helper.h
@@ -88,7 +88,7 @@ struct drm_connector_helper_funcs {
88 struct drm_encoder *(*best_encoder)(struct drm_connector *connector); 88 struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
89}; 89};
90 90
91extern void drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY); 91extern int drm_helper_probe_single_connector_modes(struct drm_connector *connector, uint32_t maxX, uint32_t maxY);
92extern void drm_helper_disable_unused_functions(struct drm_device *dev); 92extern void drm_helper_disable_unused_functions(struct drm_device *dev);
93extern int drm_helper_hotplug_stage_two(struct drm_device *dev); 93extern int drm_helper_hotplug_stage_two(struct drm_device *dev);
94extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow); 94extern bool drm_helper_initial_config(struct drm_device *dev, bool can_grow);