Rev 4560 | Rev 5271 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4560 | Rev 5060 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | * Eric Anholt |
27 | * Eric Anholt |
28 | * Dave Airlie |
28 | * Dave Airlie |
29 | * Jesse Barnes |
29 | * Jesse Barnes |
30 | */ |
30 | */ |
Line -... | Line 31... | ||
- | 31 | ||
31 | 32 | #include |
|
32 | #include |
33 | #include |
Line 33... | Line 34... | ||
33 | #include |
34 | #include |
34 | 35 | ||
Line 70... | Line 71... | ||
70 | 71 | ||
71 | list_splice(&panel_list, &dev->mode_config.connector_list); |
72 | list_splice(&panel_list, &dev->mode_config.connector_list); |
72 | } |
73 | } |
Line 73... | Line -... | ||
73 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); |
- | |
74 | - | ||
75 | static bool drm_kms_helper_poll = true; |
- | |
76 | module_param_named(poll, drm_kms_helper_poll, bool, 0600); |
- | |
77 | - | ||
78 | static void drm_mode_validate_flag(struct drm_connector *connector, |
- | |
79 | int flags) |
- | |
80 | { |
- | |
81 | struct drm_display_mode *mode; |
- | |
82 | - | ||
83 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE | |
- | |
84 | DRM_MODE_FLAG_3D_MASK)) |
- | |
85 | return; |
- | |
86 | - | ||
87 | list_for_each_entry(mode, &connector->modes, head) { |
- | |
88 | if ((mode->flags & DRM_MODE_FLAG_INTERLACE) && |
- | |
89 | !(flags & DRM_MODE_FLAG_INTERLACE)) |
- | |
90 | mode->status = MODE_NO_INTERLACE; |
- | |
91 | if ((mode->flags & DRM_MODE_FLAG_DBLSCAN) && |
- | |
92 | !(flags & DRM_MODE_FLAG_DBLSCAN)) |
- | |
93 | mode->status = MODE_NO_DBLESCAN; |
- | |
94 | if ((mode->flags & DRM_MODE_FLAG_3D_MASK) && |
- | |
95 | !(flags & DRM_MODE_FLAG_3D_MASK)) |
- | |
96 | mode->status = MODE_NO_STEREO; |
- | |
97 | } |
- | |
98 | - | ||
99 | return; |
- | |
100 | } |
- | |
101 | - | ||
102 | /** |
- | |
103 | * drm_helper_probe_single_connector_modes - get complete set of display modes |
- | |
104 | * @connector: connector to probe |
- | |
105 | * @maxX: max width for modes |
- | |
106 | * @maxY: max height for modes |
- | |
107 | * |
- | |
108 | * LOCKING: |
- | |
109 | * Caller must hold mode config lock. |
- | |
110 | * |
- | |
111 | * Based on the helper callbacks implemented by @connector try to detect all |
- | |
112 | * valid modes. Modes will first be added to the connector's probed_modes list, |
- | |
113 | * then culled (based on validity and the @maxX, @maxY parameters) and put into |
- | |
114 | * the normal modes list. |
- | |
115 | * |
- | |
116 | * Intended to be use as a generic implementation of the ->fill_modes() |
- | |
117 | * @connector vfunc for drivers that use the crtc helpers for output mode |
- | |
118 | * filtering and detection. |
- | |
119 | * |
- | |
120 | * RETURNS: |
- | |
121 | * Number of modes found on @connector. |
- | |
122 | */ |
- | |
123 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
- | |
124 | uint32_t maxX, uint32_t maxY) |
- | |
125 | { |
- | |
126 | struct drm_device *dev = connector->dev; |
- | |
127 | struct drm_display_mode *mode; |
- | |
128 | struct drm_connector_helper_funcs *connector_funcs = |
- | |
129 | connector->helper_private; |
- | |
130 | int count = 0; |
- | |
131 | int mode_flags = 0; |
- | |
132 | bool verbose_prune = true; |
- | |
133 | - | ||
134 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
- | |
135 | drm_get_connector_name(connector)); |
- | |
136 | /* set all modes to the unverified state */ |
- | |
137 | list_for_each_entry(mode, &connector->modes, head) |
- | |
138 | mode->status = MODE_UNVERIFIED; |
- | |
139 | - | ||
140 | if (connector->force) { |
- | |
141 | if (connector->force == DRM_FORCE_ON) |
- | |
142 | connector->status = connector_status_connected; |
- | |
143 | else |
- | |
144 | connector->status = connector_status_disconnected; |
- | |
145 | if (connector->funcs->force) |
- | |
146 | connector->funcs->force(connector); |
- | |
147 | } else { |
- | |
148 | connector->status = connector->funcs->detect(connector, true); |
- | |
149 | } |
- | |
150 | - | ||
151 | /* Re-enable polling in case the global poll config changed. */ |
- | |
152 | if (drm_kms_helper_poll != dev->mode_config.poll_running) |
- | |
153 | drm_kms_helper_poll_enable(dev); |
- | |
154 | - | ||
155 | dev->mode_config.poll_running = drm_kms_helper_poll; |
- | |
156 | - | ||
157 | if (connector->status == connector_status_disconnected) { |
- | |
158 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] disconnected\n", |
- | |
159 | connector->base.id, drm_get_connector_name(connector)); |
- | |
160 | drm_mode_connector_update_edid_property(connector, NULL); |
- | |
161 | verbose_prune = false; |
- | |
162 | goto prune; |
- | |
163 | } |
- | |
164 | - | ||
165 | #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE |
- | |
166 | count = drm_load_edid_firmware(connector); |
- | |
167 | if (count == 0) |
- | |
168 | #endif |
- | |
169 | count = (*connector_funcs->get_modes)(connector); |
- | |
170 | - | ||
171 | if (count == 0 && connector->status == connector_status_connected) |
- | |
172 | count = drm_add_modes_noedid(connector, 1024, 768); |
- | |
173 | if (count == 0) |
- | |
174 | goto prune; |
- | |
175 | - | ||
176 | drm_mode_connector_list_update(connector); |
- | |
177 | - | ||
178 | if (maxX && maxY) |
- | |
179 | drm_mode_validate_size(dev, &connector->modes, maxX, |
- | |
180 | maxY, 0); |
- | |
181 | - | ||
182 | if (connector->interlace_allowed) |
- | |
183 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
- | |
184 | if (connector->doublescan_allowed) |
- | |
185 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
- | |
186 | if (connector->stereo_allowed) |
- | |
187 | mode_flags |= DRM_MODE_FLAG_3D_MASK; |
- | |
188 | drm_mode_validate_flag(connector, mode_flags); |
- | |
189 | - | ||
190 | list_for_each_entry(mode, &connector->modes, head) { |
- | |
191 | if (mode->status == MODE_OK) |
- | |
192 | mode->status = connector_funcs->mode_valid(connector, |
- | |
193 | mode); |
- | |
194 | } |
- | |
195 | - | ||
196 | prune: |
- | |
197 | drm_mode_prune_invalid(dev, &connector->modes, verbose_prune); |
- | |
198 | - | ||
199 | if (list_empty(&connector->modes)) |
- | |
200 | return 0; |
- | |
201 | - | ||
202 | list_for_each_entry(mode, &connector->modes, head) |
- | |
203 | mode->vrefresh = drm_mode_vrefresh(mode); |
- | |
204 | - | ||
205 | drm_mode_sort(&connector->modes); |
- | |
206 | - | ||
207 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, |
- | |
208 | drm_get_connector_name(connector)); |
- | |
209 | list_for_each_entry(mode, &connector->modes, head) { |
- | |
210 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
- | |
211 | drm_mode_debug_printmodeline(mode); |
- | |
212 | } |
- | |
213 | - | ||
214 | return count; |
- | |
215 | } |
- | |
216 | EXPORT_SYMBOL(drm_helper_probe_single_connector_modes); |
74 | EXPORT_SYMBOL(drm_helper_move_panel_connectors_to_head); |
217 | 75 | ||
218 | /** |
76 | /** |
219 | * drm_helper_encoder_in_use - check if a given encoder is in use |
77 | * drm_helper_encoder_in_use - check if a given encoder is in use |
220 | * @encoder: encoder to check |
- | |
- | 78 | * @encoder: encoder to check |
|
- | 79 | * |
|
221 | * |
80 | * Checks whether @encoder is with the current mode setting output configuration |
222 | * LOCKING: |
81 | * in use by any connector. This doesn't mean that it is actually enabled since |
223 | * Caller must hold mode config lock. |
- | |
224 | * |
- | |
225 | * Walk @encoders's DRM device's mode_config and see if it's in use. |
82 | * the DPMS state is tracked separately. |
226 | * |
83 | * |
227 | * RETURNS: |
84 | * Returns: |
228 | * True if @encoder is part of the mode_config, false otherwise. |
85 | * True if @encoder is used, false otherwise. |
229 | */ |
86 | */ |
230 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) |
87 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) |
231 | { |
88 | { |
Line 240... | Line 97... | ||
240 | 97 | ||
241 | /** |
98 | /** |
242 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config |
99 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config |
243 | * @crtc: CRTC to check |
100 | * @crtc: CRTC to check |
244 | * |
- | |
245 | * LOCKING: |
101 | * |
246 | * Caller must hold mode config lock. |
- | |
247 | * |
102 | * Checks whether @crtc is with the current mode setting output configuration |
- | 103 | * in use by any connector. This doesn't mean that it is actually enabled since |
|
248 | * Walk @crtc's DRM device's mode_config and see if it's in use. |
104 | * the DPMS state is tracked separately. |
249 | * |
105 | * |
250 | * RETURNS: |
106 | * Returns: |
251 | * True if @crtc is part of the mode_config, false otherwise. |
107 | * True if @crtc is used, false otherwise. |
252 | */ |
108 | */ |
253 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) |
109 | bool drm_helper_crtc_in_use(struct drm_crtc *crtc) |
254 | { |
110 | { |
255 | struct drm_encoder *encoder; |
111 | struct drm_encoder *encoder; |
Line 277... | Line 133... | ||
277 | 133 | ||
278 | if (encoder->bridge) |
134 | if (encoder->bridge) |
279 | encoder->bridge->funcs->post_disable(encoder->bridge); |
135 | encoder->bridge->funcs->post_disable(encoder->bridge); |
Line 280... | Line -... | ||
280 | } |
- | |
281 | - | ||
282 | /** |
- | |
283 | * drm_helper_disable_unused_functions - disable unused objects |
- | |
284 | * @dev: DRM device |
- | |
285 | * |
- | |
286 | * LOCKING: |
- | |
287 | * Caller must hold mode config lock. |
- | |
288 | * |
- | |
289 | * If an connector or CRTC isn't part of @dev's mode_config, it can be disabled |
- | |
290 | * by calling its dpms function, which should power it off. |
136 | } |
291 | */ |
137 | |
292 | void drm_helper_disable_unused_functions(struct drm_device *dev) |
138 | static void __drm_helper_disable_unused_functions(struct drm_device *dev) |
293 | { |
- | |
294 | struct drm_encoder *encoder; |
139 | { |
Line 295... | Line -... | ||
295 | struct drm_connector *connector; |
- | |
296 | struct drm_crtc *crtc; |
140 | struct drm_encoder *encoder; |
297 | - | ||
298 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
299 | if (!connector->encoder) |
- | |
300 | continue; |
- | |
Line 301... | Line 141... | ||
301 | if (connector->status == connector_status_disconnected) |
141 | struct drm_crtc *crtc; |
302 | connector->encoder = NULL; |
142 | |
303 | } |
143 | drm_warn_on_modeset_not_all_locked(dev); |
304 | 144 | ||
305 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
145 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
306 | if (!drm_helper_encoder_in_use(encoder)) { |
146 | if (!drm_helper_encoder_in_use(encoder)) { |
307 | drm_encoder_disable(encoder); |
147 | drm_encoder_disable(encoder); |
Line 308... | Line 148... | ||
308 | /* disconnector encoder from any connector */ |
148 | /* disconnect encoder from any connector */ |
Line 316... | Line 156... | ||
316 | if (!crtc->enabled) { |
156 | if (!crtc->enabled) { |
317 | if (crtc_funcs->disable) |
157 | if (crtc_funcs->disable) |
318 | (*crtc_funcs->disable)(crtc); |
158 | (*crtc_funcs->disable)(crtc); |
319 | else |
159 | else |
320 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); |
160 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); |
321 | crtc->fb = NULL; |
161 | crtc->primary->fb = NULL; |
- | 162 | } |
|
322 | } |
163 | } |
323 | } |
164 | } |
- | 165 | ||
- | 166 | /** |
|
- | 167 | * drm_helper_disable_unused_functions - disable unused objects |
|
- | 168 | * @dev: DRM device |
|
- | 169 | * |
|
- | 170 | * This function walks through the entire mode setting configuration of @dev. It |
|
- | 171 | * will remove any crtc links of unused encoders and encoder links of |
|
- | 172 | * disconnected connectors. Then it will disable all unused encoders and crtcs |
|
- | 173 | * either by calling their disable callback if available or by calling their |
|
- | 174 | * dpms callback with DRM_MODE_DPMS_OFF. |
|
- | 175 | */ |
|
- | 176 | void drm_helper_disable_unused_functions(struct drm_device *dev) |
|
- | 177 | { |
|
- | 178 | drm_modeset_lock_all(dev); |
|
- | 179 | __drm_helper_disable_unused_functions(dev); |
|
- | 180 | drm_modeset_unlock_all(dev); |
|
324 | } |
181 | } |
325 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
182 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
Line 326... | Line 183... | ||
326 | 183 | ||
327 | /* |
184 | /* |
Line 353... | Line 210... | ||
353 | * @mode: mode to use |
210 | * @mode: mode to use |
354 | * @x: horizontal offset into the surface |
211 | * @x: horizontal offset into the surface |
355 | * @y: vertical offset into the surface |
212 | * @y: vertical offset into the surface |
356 | * @old_fb: old framebuffer, for cleanup |
213 | * @old_fb: old framebuffer, for cleanup |
357 | * |
214 | * |
358 | * LOCKING: |
- | |
359 | * Caller must hold mode config lock. |
- | |
360 | * |
- | |
361 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance |
215 | * Try to set @mode on @crtc. Give @crtc and its associated connectors a chance |
362 | * to fixup or reject the mode prior to trying to set it. This is an internal |
216 | * to fixup or reject the mode prior to trying to set it. This is an internal |
363 | * helper that drivers could e.g. use to update properties that require the |
217 | * helper that drivers could e.g. use to update properties that require the |
364 | * entire output pipe to be disabled and re-enabled in a new configuration. For |
218 | * entire output pipe to be disabled and re-enabled in a new configuration. For |
365 | * example for changing whether audio is enabled on a hdmi link or for changing |
219 | * example for changing whether audio is enabled on a hdmi link or for changing |
366 | * panel fitter or dither attributes. It is also called by the |
220 | * panel fitter or dither attributes. It is also called by the |
367 | * drm_crtc_helper_set_config() helper function to drive the mode setting |
221 | * drm_crtc_helper_set_config() helper function to drive the mode setting |
368 | * sequence. |
222 | * sequence. |
369 | * |
223 | * |
370 | * RETURNS: |
224 | * Returns: |
371 | * True if the mode was set successfully, or false otherwise. |
225 | * True if the mode was set successfully, false otherwise. |
372 | */ |
226 | */ |
373 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, |
227 | bool drm_crtc_helper_set_mode(struct drm_crtc *crtc, |
374 | struct drm_display_mode *mode, |
228 | struct drm_display_mode *mode, |
375 | int x, int y, |
229 | int x, int y, |
376 | struct drm_framebuffer *old_fb) |
230 | struct drm_framebuffer *old_fb) |
Line 382... | Line 236... | ||
382 | int saved_x, saved_y; |
236 | int saved_x, saved_y; |
383 | bool saved_enabled; |
237 | bool saved_enabled; |
384 | struct drm_encoder *encoder; |
238 | struct drm_encoder *encoder; |
385 | bool ret = true; |
239 | bool ret = true; |
Line -... | Line 240... | ||
- | 240 | ||
- | 241 | drm_warn_on_modeset_not_all_locked(dev); |
|
386 | 242 | ||
387 | saved_enabled = crtc->enabled; |
243 | saved_enabled = crtc->enabled; |
388 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
244 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
389 | if (!crtc->enabled) |
245 | if (!crtc->enabled) |
Line 470... | Line 326... | ||
470 | 326 | ||
471 | if (encoder->crtc != crtc) |
327 | if (encoder->crtc != crtc) |
Line 472... | Line 328... | ||
472 | continue; |
328 | continue; |
473 | 329 | ||
474 | DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", |
330 | DRM_DEBUG_KMS("[ENCODER:%d:%s] set [MODE:%d:%s]\n", |
475 | encoder->base.id, drm_get_encoder_name(encoder), |
331 | encoder->base.id, encoder->name, |
476 | mode->base.id, mode->name); |
332 | mode->base.id, mode->name); |
Line 477... | Line 333... | ||
477 | encoder_funcs = encoder->helper_private; |
333 | encoder_funcs = encoder->helper_private; |
Line 521... | Line 377... | ||
521 | 377 | ||
522 | return ret; |
378 | return ret; |
523 | } |
379 | } |
Line 524... | Line -... | ||
524 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
- | |
525 | 380 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
|
526 | 381 | ||
527 | static int |
382 | static void |
528 | drm_crtc_helper_disable(struct drm_crtc *crtc) |
383 | drm_crtc_helper_disable(struct drm_crtc *crtc) |
529 | { |
384 | { |
530 | struct drm_device *dev = crtc->dev; |
385 | struct drm_device *dev = crtc->dev; |
Line 550... | Line 405... | ||
550 | */ |
405 | */ |
551 | connector->dpms = DRM_MODE_DPMS_OFF; |
406 | connector->dpms = DRM_MODE_DPMS_OFF; |
552 | } |
407 | } |
553 | } |
408 | } |
Line 554... | Line 409... | ||
554 | 409 | ||
555 | drm_helper_disable_unused_functions(dev); |
- | |
556 | return 0; |
410 | __drm_helper_disable_unused_functions(dev); |
Line 557... | Line 411... | ||
557 | } |
411 | } |
558 | 412 | ||
559 | /** |
413 | /** |
560 | * drm_crtc_helper_set_config - set a new config from userspace |
414 | * drm_crtc_helper_set_config - set a new config from userspace |
561 | * @set: mode set configuration |
- | |
562 | * |
- | |
563 | * LOCKING: |
- | |
564 | * Caller must hold mode config lock. |
415 | * @set: mode set configuration |
565 | * |
416 | * |
566 | * Setup a new configuration, provided by the upper layers (either an ioctl call |
417 | * Setup a new configuration, provided by the upper layers (either an ioctl call |
567 | * from userspace or internally e.g. from the fbdev suppport code) in @set, and |
418 | * from userspace or internally e.g. from the fbdev support code) in @set, and |
568 | * enable it. This is the main helper functions for drivers that implement |
419 | * enable it. This is the main helper functions for drivers that implement |
569 | * kernel mode setting with the crtc helper functions and the assorted |
420 | * kernel mode setting with the crtc helper functions and the assorted |
570 | * ->prepare(), ->modeset() and ->commit() helper callbacks. |
421 | * ->prepare(), ->modeset() and ->commit() helper callbacks. |
571 | * |
422 | * |
572 | * RETURNS: |
423 | * Returns: |
573 | * Returns 0 on success, -ERRNO on failure. |
424 | * Returns 0 on success, negative errno numbers on failure. |
574 | */ |
425 | */ |
575 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
426 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
576 | { |
427 | { |
Line 605... | Line 456... | ||
605 | DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", |
456 | DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", |
606 | set->crtc->base.id, set->fb->base.id, |
457 | set->crtc->base.id, set->fb->base.id, |
607 | (int)set->num_connectors, set->x, set->y); |
458 | (int)set->num_connectors, set->x, set->y); |
608 | } else { |
459 | } else { |
609 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
460 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
610 | return drm_crtc_helper_disable(set->crtc); |
461 | drm_crtc_helper_disable(set->crtc); |
- | 462 | return 0; |
|
611 | } |
463 | } |
Line 612... | Line 464... | ||
612 | 464 | ||
Line -... | Line 465... | ||
- | 465 | dev = set->crtc->dev; |
|
- | 466 | ||
613 | dev = set->crtc->dev; |
467 | drm_warn_on_modeset_not_all_locked(dev); |
614 | 468 | ||
615 | /* |
469 | /* |
616 | * Allocate space for the backup of all (non-pointer) encoder and |
470 | * Allocate space for the backup of all (non-pointer) encoder and |
617 | * connector data. |
471 | * connector data. |
Line 645... | Line 499... | ||
645 | 499 | ||
646 | save_set.crtc = set->crtc; |
500 | save_set.crtc = set->crtc; |
647 | save_set.mode = &set->crtc->mode; |
501 | save_set.mode = &set->crtc->mode; |
648 | save_set.x = set->crtc->x; |
502 | save_set.x = set->crtc->x; |
649 | save_set.y = set->crtc->y; |
503 | save_set.y = set->crtc->y; |
Line 650... | Line 504... | ||
650 | save_set.fb = set->crtc->fb; |
504 | save_set.fb = set->crtc->primary->fb; |
651 | 505 | ||
652 | /* We should be able to check here if the fb has the same properties |
506 | /* We should be able to check here if the fb has the same properties |
653 | * and then just flip_or_move it */ |
507 | * and then just flip_or_move it */ |
654 | if (set->crtc->fb != set->fb) { |
508 | if (set->crtc->primary->fb != set->fb) { |
655 | /* If we have no fb then treat it as a full mode set */ |
509 | /* If we have no fb then treat it as a full mode set */ |
656 | if (set->crtc->fb == NULL) { |
510 | if (set->crtc->primary->fb == NULL) { |
657 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); |
511 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); |
658 | mode_changed = true; |
512 | mode_changed = true; |
659 | } else if (set->fb == NULL) { |
513 | } else if (set->fb == NULL) { |
660 | mode_changed = true; |
514 | mode_changed = true; |
661 | } else if (set->fb->pixel_format != |
515 | } else if (set->fb->pixel_format != |
662 | set->crtc->fb->pixel_format) { |
516 | set->crtc->primary->fb->pixel_format) { |
663 | mode_changed = true; |
517 | mode_changed = true; |
664 | } else |
518 | } else |
Line 687... | Line 541... | ||
687 | /* if we can't get an encoder for a connector |
541 | /* if we can't get an encoder for a connector |
688 | we are setting now - then fail */ |
542 | we are setting now - then fail */ |
689 | if (new_encoder == NULL) |
543 | if (new_encoder == NULL) |
690 | /* don't break so fail path works correct */ |
544 | /* don't break so fail path works correct */ |
691 | fail = 1; |
545 | fail = 1; |
692 | break; |
- | |
Line 693... | Line 546... | ||
693 | 546 | ||
694 | if (connector->dpms != DRM_MODE_DPMS_ON) { |
547 | if (connector->dpms != DRM_MODE_DPMS_ON) { |
695 | DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); |
548 | DRM_DEBUG_KMS("connector dpms not on, full mode switch\n"); |
696 | mode_changed = true; |
549 | mode_changed = true; |
- | 550 | } |
|
- | 551 | ||
697 | } |
552 | break; |
698 | } |
553 | } |
Line 699... | Line 554... | ||
699 | } |
554 | } |
700 | 555 | ||
Line 741... | Line 596... | ||
741 | mode_changed = true; |
596 | mode_changed = true; |
742 | connector->encoder->crtc = new_crtc; |
597 | connector->encoder->crtc = new_crtc; |
743 | } |
598 | } |
744 | if (new_crtc) { |
599 | if (new_crtc) { |
745 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", |
600 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [CRTC:%d]\n", |
746 | connector->base.id, drm_get_connector_name(connector), |
601 | connector->base.id, connector->name, |
747 | new_crtc->base.id); |
602 | new_crtc->base.id); |
748 | } else { |
603 | } else { |
749 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", |
604 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] to [NOCRTC]\n", |
750 | connector->base.id, drm_get_connector_name(connector)); |
605 | connector->base.id, connector->name); |
751 | } |
606 | } |
752 | } |
607 | } |
Line 753... | Line 608... | ||
753 | 608 | ||
754 | /* mode_set_base is not a required function */ |
609 | /* mode_set_base is not a required function */ |
Line 758... | Line 613... | ||
758 | if (mode_changed) { |
613 | if (mode_changed) { |
759 | if (drm_helper_crtc_in_use(set->crtc)) { |
614 | if (drm_helper_crtc_in_use(set->crtc)) { |
760 | DRM_DEBUG_KMS("attempting to set mode from" |
615 | DRM_DEBUG_KMS("attempting to set mode from" |
761 | " userspace\n"); |
616 | " userspace\n"); |
762 | drm_mode_debug_printmodeline(set->mode); |
617 | drm_mode_debug_printmodeline(set->mode); |
763 | set->crtc->fb = set->fb; |
618 | set->crtc->primary->fb = set->fb; |
764 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
619 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
765 | set->x, set->y, |
620 | set->x, set->y, |
766 | save_set.fb)) { |
621 | save_set.fb)) { |
767 | DRM_ERROR("failed to set mode on [CRTC:%d]\n", |
622 | DRM_ERROR("failed to set mode on [CRTC:%d]\n", |
768 | set->crtc->base.id); |
623 | set->crtc->base.id); |
769 | set->crtc->fb = save_set.fb; |
624 | set->crtc->primary->fb = save_set.fb; |
770 | ret = -EINVAL; |
625 | ret = -EINVAL; |
771 | goto fail; |
626 | goto fail; |
772 | } |
627 | } |
773 | DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); |
628 | DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); |
774 | for (i = 0; i < set->num_connectors; i++) { |
629 | for (i = 0; i < set->num_connectors; i++) { |
775 | DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, |
630 | DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, |
776 | drm_get_connector_name(set->connectors[i])); |
631 | set->connectors[i]->name); |
777 | set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); |
632 | set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); |
778 | } |
633 | } |
779 | } |
634 | } |
780 | drm_helper_disable_unused_functions(dev); |
635 | __drm_helper_disable_unused_functions(dev); |
781 | } else if (fb_changed) { |
636 | } else if (fb_changed) { |
782 | set->crtc->x = set->x; |
637 | set->crtc->x = set->x; |
783 | set->crtc->y = set->y; |
638 | set->crtc->y = set->y; |
784 | set->crtc->fb = set->fb; |
639 | set->crtc->primary->fb = set->fb; |
785 | ret = crtc_funcs->mode_set_base(set->crtc, |
640 | ret = crtc_funcs->mode_set_base(set->crtc, |
786 | set->x, set->y, save_set.fb); |
641 | set->x, set->y, save_set.fb); |
787 | if (ret != 0) { |
642 | if (ret != 0) { |
788 | set->crtc->x = save_set.x; |
643 | set->crtc->x = save_set.x; |
789 | set->crtc->y = save_set.y; |
644 | set->crtc->y = save_set.y; |
790 | set->crtc->fb = save_set.fb; |
645 | set->crtc->primary->fb = save_set.fb; |
791 | goto fail; |
646 | goto fail; |
792 | } |
647 | } |
793 | } |
648 | } |
Line 794... | Line 649... | ||
794 | 649 | ||
Line 922... | Line 777... | ||
922 | 777 | ||
923 | return; |
778 | return; |
924 | } |
779 | } |
Line -... | Line 780... | ||
- | 780 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
|
- | 781 | ||
- | 782 | /** |
|
- | 783 | * drm_helper_mode_fill_fb_struct - fill out framebuffer metadata |
|
- | 784 | * @fb: drm_framebuffer object to fill out |
|
- | 785 | * @mode_cmd: metadata from the userspace fb creation request |
|
- | 786 | * |
|
- | 787 | * This helper can be used in a drivers fb_create callback to pre-fill the fb's |
|
925 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
788 | * metadata fields. |
926 | 789 | */ |
|
927 | int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |
790 | void drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |
928 | struct drm_mode_fb_cmd2 *mode_cmd) |
791 | struct drm_mode_fb_cmd2 *mode_cmd) |
Line 929... | Line 792... | ||
929 | { |
792 | { |
Line 936... | Line 799... | ||
936 | fb->offsets[i] = mode_cmd->offsets[i]; |
799 | fb->offsets[i] = mode_cmd->offsets[i]; |
937 | } |
800 | } |
938 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
801 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
939 | &fb->bits_per_pixel); |
802 | &fb->bits_per_pixel); |
940 | fb->pixel_format = mode_cmd->pixel_format; |
803 | fb->pixel_format = mode_cmd->pixel_format; |
941 | - | ||
942 | return 0; |
804 | fb->flags = mode_cmd->flags; |
943 | } |
805 | } |
944 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); |
806 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); |
Line -... | Line 807... | ||
- | 807 | ||
- | 808 | /** |
|
- | 809 | * drm_helper_resume_force_mode - force-restore mode setting configuration |
|
- | 810 | * @dev: drm_device which should be restored |
|
- | 811 | * |
|
- | 812 | * Drivers which use the mode setting helpers can use this function to |
|
- | 813 | * force-restore the mode setting configuration e.g. on resume or when something |
|
- | 814 | * else might have trampled over the hw state (like some overzealous old BIOSen |
|
- | 815 | * tended to do). |
|
- | 816 | * |
|
- | 817 | * This helper doesn't provide a error return value since restoring the old |
|
- | 818 | * config should never fail due to resource allocation issues since the driver |
|
- | 819 | * has successfully set the restored configuration already. Hence this should |
|
- | 820 | * boil down to the equivalent of a few dpms on calls, which also don't provide |
|
- | 821 | * an error code. |
|
- | 822 | * |
|
- | 823 | * Drivers where simply restoring an old configuration again might fail (e.g. |
|
- | 824 | * due to slight differences in allocating shared resources when the |
|
- | 825 | * configuration is restored in a different order than when userspace set it up) |
|
- | 826 | * need to use their own restore logic. |
|
945 | 827 | */ |
|
946 | int drm_helper_resume_force_mode(struct drm_device *dev) |
828 | void drm_helper_resume_force_mode(struct drm_device *dev) |
947 | { |
829 | { |
948 | struct drm_crtc *crtc; |
830 | struct drm_crtc *crtc; |
949 | struct drm_encoder *encoder; |
831 | struct drm_encoder *encoder; |
950 | struct drm_crtc_helper_funcs *crtc_funcs; |
832 | struct drm_crtc_helper_funcs *crtc_funcs; |
- | 833 | int encoder_dpms; |
|
Line -... | Line 834... | ||
- | 834 | bool ret; |
|
951 | int ret, encoder_dpms; |
835 | |
Line 952... | Line 836... | ||
952 | 836 | drm_modeset_lock_all(dev); |
|
953 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
837 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
Line 954... | Line 838... | ||
954 | 838 | ||
955 | if (!crtc->enabled) |
839 | if (!crtc->enabled) |
Line -... | Line 840... | ||
- | 840 | continue; |
|
956 | continue; |
841 | |
957 | 842 | ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, |
|
Line 958... | Line 843... | ||
958 | ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, |
843 | crtc->x, crtc->y, crtc->primary->fb); |
959 | crtc->x, crtc->y, crtc->fb); |
844 | |
Line 978... | Line 863... | ||
978 | if (crtc_funcs->dpms) |
863 | if (crtc_funcs->dpms) |
979 | (*crtc_funcs->dpms) (crtc, |
864 | (*crtc_funcs->dpms) (crtc, |
980 | drm_helper_choose_crtc_dpms(crtc)); |
865 | drm_helper_choose_crtc_dpms(crtc)); |
981 | } |
866 | } |
982 | } |
867 | } |
- | 868 | ||
983 | /* disable the unused connectors while restoring the modesetting */ |
869 | /* disable the unused connectors while restoring the modesetting */ |
984 | drm_helper_disable_unused_functions(dev); |
870 | __drm_helper_disable_unused_functions(dev); |
985 | return 0; |
871 | drm_modeset_unlock_all(dev); |
986 | } |
872 | } |
987 | EXPORT_SYMBOL(drm_helper_resume_force_mode); |
873 | EXPORT_SYMBOL(drm_helper_resume_force_mode);>>>>>>> |
988 | - | ||
989 | void drm_kms_helper_hotplug_event(struct drm_device *dev) |
- | |
990 | { |
- | |
991 | /* send a uevent + call fbdev */ |
- | |
992 | if (dev->mode_config.funcs->output_poll_changed) |
- | |
993 | dev->mode_config.funcs->output_poll_changed(dev); |
- | |
994 | } |
- | |
995 | EXPORT_SYMBOL(drm_kms_helper_hotplug_event); |
- | |
996 | - | ||
997 | #define DRM_OUTPUT_POLL_PERIOD (10*HZ) |
- | |
998 | static void output_poll_execute(struct work_struct *work) |
- | |
999 | { |
- | |
1000 | struct delayed_work *delayed_work = to_delayed_work(work); |
- | |
1001 | struct drm_device *dev = container_of(delayed_work, struct drm_device, mode_config.output_poll_work); |
- | |
1002 | struct drm_connector *connector; |
- | |
1003 | enum drm_connector_status old_status; |
- | |
1004 | bool repoll = false, changed = false; |
- | |
1005 | - | ||
1006 | if (!drm_kms_helper_poll) |
- | |
1007 | return; |
- | |
1008 | - | ||
1009 | mutex_lock(&dev->mode_config.mutex); |
- | |
1010 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
1011 | - | ||
1012 | /* Ignore forced connectors. */ |
- | |
1013 | if (connector->force) |
- | |
1014 | continue; |
- | |
1015 | - | ||
1016 | /* Ignore HPD capable connectors and connectors where we don't |
- | |
1017 | * want any hotplug detection at all for polling. */ |
- | |
1018 | if (!connector->polled || connector->polled == DRM_CONNECTOR_POLL_HPD) |
- | |
1019 | continue; |
- | |
1020 | - | ||
1021 | repoll = true; |
- | |
1022 | - | ||
1023 | old_status = connector->status; |
- | |
1024 | /* if we are connected and don't want to poll for disconnect |
- | |
1025 | skip it */ |
- | |
1026 | if (old_status == connector_status_connected && |
- | |
1027 | !(connector->polled & DRM_CONNECTOR_POLL_DISCONNECT)) |
- | |
1028 | continue; |
- | |
1029 | - | ||
1030 | connector->status = connector->funcs->detect(connector, false); |
- | |
1031 | if (old_status != connector->status) { |
- | |
1032 | const char *old, *new; |
- | |
1033 | - | ||
1034 | old = drm_get_connector_status_name(old_status); |
- | |
1035 | new = drm_get_connector_status_name(connector->status); |
- | |
1036 | - | ||
1037 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] " |
- | |
1038 | "status updated from %s to %s\n", |
- | |
1039 | connector->base.id, |
- | |
1040 | drm_get_connector_name(connector), |
- | |
1041 | old, new); |
- | |
1042 | - | ||
1043 | changed = true; |
- | |
1044 | } |
- | |
1045 | } |
- | |
1046 | - | ||
1047 | mutex_unlock(&dev->mode_config.mutex); |
- | |
1048 | - | ||
1049 | if (changed) |
- | |
1050 | drm_kms_helper_hotplug_event(dev); |
- | |
1051 | - | ||
1052 | if (repoll) |
- | |
1053 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); |
- | |
1054 | } |
- | |
1055 | - | ||
1056 | void drm_kms_helper_poll_disable(struct drm_device *dev) |
- | |
1057 | { |
- | |
1058 | if (!dev->mode_config.poll_enabled) |
- | |
1059 | return; |
- | |
1060 | // cancel_delayed_work_sync(&dev->mode_config.output_poll_work); |
- | |
1061 | } |
- | |
1062 | EXPORT_SYMBOL(drm_kms_helper_poll_disable); |
- | |
1063 | - | ||
1064 | void drm_kms_helper_poll_enable(struct drm_device *dev) |
- | |
1065 | { |
- | |
1066 | bool poll = false; |
- | |
1067 | struct drm_connector *connector; |
- | |
1068 | - | ||
1069 | if (!dev->mode_config.poll_enabled || !drm_kms_helper_poll) |
- | |
1070 | return; |
- | |
1071 | - | ||
1072 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
1073 | if (connector->polled & (DRM_CONNECTOR_POLL_CONNECT | |
- | |
1074 | DRM_CONNECTOR_POLL_DISCONNECT)) |
- | |
1075 | poll = true; |
- | |
1076 | } |
- | |
1077 | - | ||
1078 | if (poll) |
- | |
1079 | schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); |
- | |
1080 | } |
- | |
1081 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
- | |
1082 | - | ||
1083 | void drm_kms_helper_poll_init(struct drm_device *dev) |
- | |
1084 | { |
- | |
1085 | INIT_DELAYED_WORK(&dev->mode_config.output_poll_work, output_poll_execute); |
- | |
1086 | dev->mode_config.poll_enabled = true; |
- | |
1087 | - | ||
1088 | drm_kms_helper_poll_enable(dev); |
- | |
1089 | } |
- | |
1090 | EXPORT_SYMBOL(drm_kms_helper_poll_init); |
- | |
1091 | - | ||
1092 | void drm_kms_helper_poll_fini(struct drm_device *dev) |
- | |
1093 | { |
- | |
1094 | drm_kms_helper_poll_disable(dev); |
- | |
1095 | } |
- | |
1096 | EXPORT_SYMBOL(drm_kms_helper_poll_fini); |
- | |
1097 | - | ||
1098 | bool drm_helper_hpd_irq_event(struct drm_device *dev) |
- | |
1099 | { |
- | |
1100 | struct drm_connector *connector; |
- | |
1101 | enum drm_connector_status old_status; |
- | |
1102 | bool changed = false; |
- | |
1103 | - | ||
1104 | if (!dev->mode_config.poll_enabled) |
- | |
1105 | return false; |
- | |
1106 | - | ||
1107 | mutex_lock(&dev->mode_config.mutex); |
- | |
1108 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
1109 | - | ||
1110 | /* Only handle HPD capable connectors. */ |
- | |
1111 | if (!(connector->polled & DRM_CONNECTOR_POLL_HPD)) |
- | |
1112 | continue; |
- | |
1113 | - | ||
1114 | old_status = connector->status; |
- | |
1115 | - | ||
1116 | connector->status = connector->funcs->detect(connector, false); |
- | |
1117 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] status updated from %s to %s\n", |
- | |
1118 | connector->base.id, |
- | |
1119 | drm_get_connector_name(connector), |
- | |
1120 | drm_get_connector_status_name(old_status), |
- | |
1121 | drm_get_connector_status_name(connector->status)); |
- | |
1122 | if (old_status != connector->status) |
- | |
1123 | changed = true; |
- | |
1124 | } |
- | |
1125 | - | ||
1126 | mutex_unlock(&dev->mode_config.mutex); |
- | |
1127 | - | ||
1128 | if (changed) |
- | |
1129 | drm_kms_helper_hotplug_event(dev); |
- | |
1130 | - | ||
1131 | return changed; |
- | |
1132 | } |
- | |
1133 | EXPORT_SYMBOL(drm_helper_hpd_irq_event);>>>>>>> |
- |