Rev 5271 | Rev 6088 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 6084 | ||
---|---|---|---|
Line 56... | Line 56... | ||
56 | */ |
56 | */ |
Line 57... | Line 57... | ||
57 | 57 | ||
58 | static bool drm_kms_helper_poll = true; |
58 | static bool drm_kms_helper_poll = true; |
Line -... | Line 59... | ||
- | 59 | module_param_named(poll, drm_kms_helper_poll, bool, 0600); |
|
59 | module_param_named(poll, drm_kms_helper_poll, bool, 0600); |
60 | |
60 | 61 | static enum drm_mode_status |
|
61 | static void drm_mode_validate_flag(struct drm_connector *connector, |
62 | drm_mode_validate_flag(const struct drm_display_mode *mode, |
62 | int flags) |
- | |
63 | { |
- | |
64 | struct drm_display_mode *mode; |
- | |
65 | - | ||
66 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | |
- | |
67 | DRM_MODE_FLAG_3D_MASK)) |
- | |
68 | return; |
- | |
69 | 63 | int flags) |
|
70 | list_for_each_entry(mode, &connector->modes, head) { |
64 | { |
71 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && |
65 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && |
- | 66 | !(flags & DRM_MODE_FLAG_INTERLACE)) |
|
72 | !(flags & DRM_MODE_FLAG_INTERLACE)) |
67 | return MODE_NO_INTERLACE; |
73 | mode->status = MODE_NO_INTERLACE; |
68 | |
74 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && |
69 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && |
- | 70 | !(flags & DRM_MODE_FLAG_DBLSCAN)) |
|
75 | !(flags & DRM_MODE_FLAG_DBLSCAN)) |
71 | return MODE_NO_DBLESCAN; |
76 | mode->status = MODE_NO_DBLESCAN; |
72 | |
77 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && |
73 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && |
- | 74 | !(flags & DRM_MODE_FLAG_3D_MASK)) |
|
- | 75 | return MODE_NO_STEREO; |
|
- | 76 | ||
- | 77 | return MODE_OK; |
|
- | 78 | } |
|
- | 79 | ||
- | 80 | static int drm_helper_probe_add_cmdline_mode(struct drm_connector *connector) |
|
- | 81 | { |
|
- | 82 | struct drm_display_mode *mode; |
|
- | 83 | ||
- | 84 | if (!connector->cmdline_mode.specified) |
|
- | 85 | return 0; |
|
- | 86 | ||
- | 87 | mode = drm_mode_create_from_cmdline_mode(connector->dev, |
|
- | 88 | &connector->cmdline_mode); |
|
- | 89 | if (mode == NULL) |
|
- | 90 | return 0; |
|
- | 91 | ||
78 | !(flags & DRM_MODE_FLAG_3D_MASK)) |
92 | drm_mode_probed_add(connector, mode); |
Line -... | Line 93... | ||
- | 93 | return 1; |
|
- | 94 | } |
|
- | 95 | ||
- | 96 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) |
|
- | 97 | /** |
|
- | 98 | * drm_kms_helper_poll_enable_locked - re-enable output polling. |
|
- | 99 | * @dev: drm_device |
|
- | 100 | * |
|
- | 101 | * This function re-enables the output polling work without |
|
- | 102 | * locking the mode_config mutex. |
|
- | 103 | * |
|
- | 104 | * This is like drm_kms_helper_poll_enable() however it is to be |
|
- | 105 | * called from a context where the mode_config mutex is locked |
|
- | 106 | * already. |
|
- | 107 | */ |
|
- | 108 | void drm_kms_helper_poll_enable_locked(struct drm_device *dev) |
|
- | 109 | { |
|
- | 110 | bool poll = false; |
|
- | 111 | struct drm_connector *connector; |
|
- | 112 | ||
79 | mode->status = MODE_NO_STEREO; |
113 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); |
- | 114 | ||
- | 115 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) |
|
- | 116 | return; |
|
- | 117 | ||
- | 118 | drm_for_each_connector(connector, dev) { |
|
- | 119 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | |
|
- | 120 | DRM_CONNECTOR_POLL_DISCONNECT)) |
|
80 | } |
121 | poll = true; |
- | 122 | } |
|
- | 123 | ||
Line 81... | Line 124... | ||
81 | 124 | } |
|
82 | return; |
125 | EXPORT_SYMBOL(drm_kms_helper_poll_enable_locked); |
83 | } |
126 | |
84 | 127 | ||
85 | static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, |
128 | static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connector *connector, |
86 | uint32_t maxX, uint32_t maxY, bool merge_type_bits) |
129 | uint32_t maxX, uint32_t maxY, bool merge_type_bits) |
87 | { |
130 | { |
88 | struct drm_device *dev = connector->dev; |
131 | struct drm_device *dev = connector->dev; |
89 | struct drm_display_mode *mode; |
132 | struct drm_display_mode *mode; |
90 | struct drm_connector_helper_funcs *connector_funcs = |
133 | const struct drm_connector_helper_funcs *connector_funcs = |
- | 134 | connector->helper_private; |
|
Line 91... | Line 135... | ||
91 | connector->helper_private; |
135 | int count = 0; |
Line 92... | Line 136... | ||
92 | int count = 0; |
136 | int mode_flags = 0; |
93 | int mode_flags = 0; |
137 | bool verbose_prune = true; |
Line 108... | Line 152... | ||
108 | else |
152 | else |
109 | connector->status = connector_status_disconnected; |
153 | connector->status = connector_status_disconnected; |
110 | if (connector->funcs->force) |
154 | if (connector->funcs->force) |
111 | connector->funcs->force(connector); |
155 | connector->funcs->force(connector); |
112 | } else { |
156 | } else { |
- | 157 | old_status = connector->status; |
|
- | 158 | ||
113 | connector->status = connector->funcs->detect(connector, true); |
159 | connector->status = connector->funcs->detect(connector, true); |
114 | } |
160 | } |
Line 115... | Line 161... | ||
115 | 161 | ||
116 | /* Re-enable polling in case the global poll config changed. */ |
162 | /* Re-enable polling in case the global poll config changed. */ |
117 | if (drm_kms_helper_poll != dev->mode_config.poll_running) |
163 | if (drm_kms_helper_poll != dev->mode_config.poll_running) |
Line 118... | Line 164... | ||
118 | drm_kms_helper_poll_enable(dev); |
164 | drm_kms_helper_poll_enable_locked(dev); |
Line 119... | Line 165... | ||
119 | 165 | ||
120 | dev->mode_config.poll_running = drm_kms_helper_poll; |
166 | dev->mode_config.poll_running = drm_kms_helper_poll; |
Line 134... | Line 180... | ||
134 | { |
180 | { |
135 | if (connector->override_edid) { |
181 | if (connector->override_edid) { |
136 | struct edid *edid = (struct edid *) connector->edid_blob_ptr->data; |
182 | struct edid *edid = (struct edid *) connector->edid_blob_ptr->data; |
Line 137... | Line 183... | ||
137 | 183 | ||
- | 184 | count = drm_add_edid_modes(connector, edid); |
|
138 | count = drm_add_edid_modes(connector, edid); |
185 | drm_edid_to_eld(connector, edid); |
139 | } else |
186 | } else |
140 | count = (*connector_funcs->get_modes)(connector); |
187 | count = (*connector_funcs->get_modes)(connector); |
Line 141... | Line 188... | ||
141 | } |
188 | } |
Line 145... | Line 192... | ||
145 | if (count == 0) |
192 | if (count == 0) |
146 | goto prune; |
193 | goto prune; |
Line 147... | Line 194... | ||
147 | 194 | ||
Line 148... | Line -... | ||
148 | drm_mode_connector_list_update(connector, merge_type_bits); |
- | |
149 | - | ||
150 | if (maxX && maxY) |
- | |
151 | drm_mode_validate_size(dev, &connector->modes, maxX, maxY); |
195 | drm_mode_connector_list_update(connector, merge_type_bits); |
152 | 196 | ||
153 | if (connector->interlace_allowed) |
197 | if (connector->interlace_allowed) |
154 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
198 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
155 | if (connector->doublescan_allowed) |
199 | if (connector->doublescan_allowed) |
156 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
200 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
157 | if (connector->stereo_allowed) |
- | |
Line 158... | Line 201... | ||
158 | mode_flags |= DRM_MODE_FLAG_3D_MASK; |
201 | if (connector->stereo_allowed) |
- | 202 | mode_flags |= DRM_MODE_FLAG_3D_MASK; |
|
- | 203 | ||
- | 204 | list_for_each_entry(mode, &connector->modes, head) { |
|
- | 205 | if (mode->status == MODE_OK) |
|
- | 206 | mode->status = drm_mode_validate_basic(mode); |
|
- | 207 | ||
- | 208 | if (mode->status == MODE_OK) |
|
- | 209 | mode->status = drm_mode_validate_size(mode, maxX, maxY); |
|
- | 210 | ||
159 | drm_mode_validate_flag(connector, mode_flags); |
211 | if (mode->status == MODE_OK) |
160 | 212 | mode->status = drm_mode_validate_flag(mode, mode_flags); |
|
161 | list_for_each_entry(mode, &connector->modes, head) { |
213 | |
162 | if (mode->status == MODE_OK && connector_funcs->mode_valid) |
214 | if (mode->status == MODE_OK && connector_funcs->mode_valid) |
Line 249... | Line 301... | ||
249 | // if (dev->mode_config.funcs->output_poll_changed) |
301 | // if (dev->mode_config.funcs->output_poll_changed) |
250 | // dev->mode_config.funcs->output_poll_changed(dev); |
302 | // dev->mode_config.funcs->output_poll_changed(dev); |
251 | } |
303 | } |
252 | EXPORT_SYMBOL(drm_kms_helper_hotplug_event); |
304 | EXPORT_SYMBOL(drm_kms_helper_hotplug_event); |
Line 253... | Line -... | ||
253 | - | ||
254 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) |
305 | |
255 | static void output_poll_execute(struct work_struct *work) |
306 | static void output_poll_execute(struct work_struct *work) |
256 | { |
307 | { |
257 | struct delayed_work *delayed_work = to_delayed_work(work); |
308 | struct delayed_work *delayed_work = to_delayed_work(work); |
258 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); |
309 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); |
259 | struct drm_connector *connector; |
310 | struct drm_connector *connector; |
260 | enum drm_connector_status old_status; |
311 | enum drm_connector_status old_status; |
- | 312 | bool repoll = false, changed; |
|
- | 313 | ||
- | 314 | /* Pick up any changes detected by the probe functions. */ |
|
- | 315 | changed = dev->mode_config.delayed_event; |
|
Line 261... | Line 316... | ||
261 | bool repoll = false, changed = false; |
316 | dev->mode_config.delayed_event = false; |
262 | 317 | ||
Line 263... | Line 318... | ||
263 | if (!drm_kms_helper_poll) |
318 | if (!drm_kms_helper_poll) |
264 | return; |
319 | goto out; |
Line 265... | Line 320... | ||
265 | 320 | ||
266 | mutex_lock(&dev->mode_config.mutex); |
321 | mutex_lock(&dev->mode_config.mutex); |
267 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
322 | drm_for_each_connector(connector, dev) { |
Line 268... | Line 323... | ||
268 | 323 | ||
269 | /* Ignore forced connectors. */ |
324 | /* Ignore forced connectors. */ |
270 | if (connector->force) |
325 | if (connector->force) |
271 | continue; |
326 | continue; |
Line 272... | Line -... | ||
272 | - | ||
273 | /* Ignore HPD capable connectors and connectors where we don't |
- | |
274 | * want any hotplug detection at all for polling. */ |
327 | |
275 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) |
328 | /* Ignore HPD capable connectors and connectors where we don't |
276 | continue; |
329 | * want any hotplug detection at all for polling. */ |
277 | 330 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) |
|
278 | repoll = true; |
331 | continue; |
279 | 332 | ||
Line -... | Line 333... | ||
- | 333 | old_status = connector->status; |
|
- | 334 | /* if we are connected and don't want to poll for disconnect |
|
280 | old_status = connector->status; |
335 | skip it */ |
281 | /* if we are connected and don't want to poll for disconnect |
336 | if (old_status == connector_status_connected && |
282 | skip it */ |
337 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) |
Line -... | Line 338... | ||
- | 338 | continue; |
|
- | 339 | ||
- | 340 | repoll = true; |
|
- | 341 | ||
- | 342 | connector->status = connector->funcs->detect(connector, false); |
|
- | 343 | if (old_status != connector->status) { |
|
- | 344 | const char *old, *new; |
|
- | 345 | ||
- | 346 | /* |
|
- | 347 | * The poll work sets force=false when calling detect so |
|
- | 348 | * that drivers can avoid to do disruptive tests (e.g. |
|
- | 349 | * when load detect cycles could cause flickering on |
|
- | 350 | * other, running displays). This bears the risk that we |
|
- | 351 | * flip-flop between unknown here in the poll work and |
|
- | 352 | * the real state when userspace forces a full detect |
|
- | 353 | * call after receiving a hotplug event due to this |
|
- | 354 | * change. |
|
- | 355 | * |
|
283 | if (old_status == connector_status_connected && |
356 | * Hence clamp an unknown detect status to the old |
284 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) |
357 | * value. |
Line 285... | Line 358... | ||
285 | continue; |
358 | */ |
286 | 359 | if (connector->status == connector_status_unknown) { |
|
Line 301... | Line 374... | ||
301 | } |
374 | } |
302 | } |
375 | } |
Line 303... | Line 376... | ||
303 | 376 | ||
Line -... | Line 377... | ||
- | 377 | mutex_unlock(&dev->mode_config.mutex); |
|
- | 378 | ||
304 | mutex_unlock(&dev->mode_config.mutex); |
379 | out: ; |
305 | 380 | ||
Line 306... | Line 381... | ||
306 | // if (changed) |
381 | // if (changed) |
307 | // drm_kms_helper_hotplug_event(dev); |
382 | // drm_kms_helper_hotplug_event(dev); |
Line 338... | Line 413... | ||
338 | * an error to call this when the output polling support has not yet been set |
413 | * an error to call this when the output polling support has not yet been set |
339 | * up. |
414 | * up. |
340 | */ |
415 | */ |
341 | void drm_kms_helper_poll_enable(struct drm_device *dev) |
416 | void drm_kms_helper_poll_enable(struct drm_device *dev) |
342 | { |
417 | { |
343 | bool poll = false; |
- | |
344 | struct drm_connector *connector; |
418 | mutex_lock(&dev->mode_config.mutex); |
345 | - | ||
346 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) |
419 | drm_kms_helper_poll_enable_locked(dev); |
347 | return; |
- | |
348 | - | ||
349 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
420 | mutex_unlock(&dev->mode_config.mutex); |
350 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | |
- | |
351 | DRM_CONNECTOR_POLL_DISCONNECT)) |
- | |
352 | poll = true; |
- | |
353 | } |
- | |
354 | - | ||
355 | // if (poll) |
- | |
356 | // schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); |
- | |
357 | } |
421 | } |
358 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
422 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
Line 359... | Line 423... | ||
359 | 423 | ||
360 | /** |
424 | /** |
Line 426... | Line 490... | ||
426 | 490 | ||
427 | if (!dev->mode_config.poll_enabled) |
491 | if (!dev->mode_config.poll_enabled) |
Line 428... | Line 492... | ||
428 | return false; |
492 | return false; |
429 | 493 | ||
Line 430... | Line 494... | ||
430 | mutex_lock(&dev->mode_config.mutex); |
494 | mutex_lock(&dev->mode_config.mutex); |
431 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
495 | drm_for_each_connector(connector, dev) { |
432 | 496 |