Rev 1126 | Rev 1182 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1126 | Rev 1179 | ||
---|---|---|---|
Line 31... | Line 31... | ||
31 | 31 | ||
32 | #include "drmP.h" |
32 | #include "drmP.h" |
33 | #include "drm_crtc.h" |
33 | #include "drm_crtc.h" |
Line 34... | Line -... | ||
34 | #include "drm_crtc_helper.h" |
- | |
35 | - | ||
36 | /* |
- | |
37 | * Detailed mode info for 800x600@60Hz |
- | |
38 | */ |
- | |
39 | static struct drm_display_mode std_modes[] = { |
- | |
40 | { DRM_MODE("800x600", DRM_MODE_TYPE_DEFAULT, 40000, 800, 840, |
- | |
41 | 968, 1056, 0, 600, 601, 605, 628, 0, |
- | |
42 | DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, |
- | |
43 | }; |
34 | #include "drm_crtc_helper.h" |
44 | 35 | ||
45 | static void drm_mode_validate_flag(struct drm_connector *connector, |
36 | static void drm_mode_validate_flag(struct drm_connector *connector, |
46 | int flags) |
37 | int flags) |
Line 92... | Line 83... | ||
92 | struct drm_connector_helper_funcs *connector_funcs = |
83 | struct drm_connector_helper_funcs *connector_funcs = |
93 | connector->helper_private; |
84 | connector->helper_private; |
94 | int count = 0; |
85 | int count = 0; |
95 | int mode_flags = 0; |
86 | int mode_flags = 0; |
Line 96... | Line 87... | ||
96 | 87 | ||
97 | DRM_DEBUG("%s\n", drm_get_connector_name(connector)); |
88 | DRM_DEBUG_KMS("%s\n", drm_get_connector_name(connector)); |
98 | /* set all modes to the unverified state */ |
89 | /* set all modes to the unverified state */ |
99 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
90 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
Line 100... | Line 91... | ||
100 | mode->status = MODE_UNVERIFIED; |
91 | mode->status = MODE_UNVERIFIED; |
Line 101... | Line 92... | ||
101 | 92 | ||
102 | connector->status = connector->funcs->detect(connector); |
93 | connector->status = connector->funcs->detect(connector); |
103 | 94 | ||
104 | if (connector->status == connector_status_disconnected) { |
- | |
105 | DRM_DEBUG("%s is disconnected\n", |
95 | if (connector->status == connector_status_disconnected) { |
106 | drm_get_connector_name(connector)); |
96 | DRM_DEBUG_KMS("%s is disconnected\n", |
Line 107... | Line 97... | ||
107 | /* TODO set EDID to NULL */ |
97 | drm_get_connector_name(connector)); |
- | 98 | goto prune; |
|
- | 99 | } |
|
108 | return 0; |
100 | |
109 | } |
101 | count = (*connector_funcs->get_modes)(connector); |
- | 102 | if (!count) { |
|
Line 110... | Line 103... | ||
110 | 103 | count = drm_add_modes_noedid(connector, 800, 600); |
|
Line 111... | Line 104... | ||
111 | count = (*connector_funcs->get_modes)(connector); |
104 | if (!count) |
112 | if (!count) |
105 | return 0; |
Line 128... | Line 121... | ||
128 | if (mode->status == MODE_OK) |
121 | if (mode->status == MODE_OK) |
129 | mode->status = connector_funcs->mode_valid(connector, |
122 | mode->status = connector_funcs->mode_valid(connector, |
130 | mode); |
123 | mode); |
131 | } |
124 | } |
Line 132... | Line 125... | ||
132 | 125 | ||
133 | 126 | prune: |
|
Line 134... | Line 127... | ||
134 | drm_mode_prune_invalid(dev, &connector->modes, true); |
127 | drm_mode_prune_invalid(dev, &connector->modes, true); |
135 | 128 | ||
Line 136... | Line 129... | ||
136 | if (list_empty(&connector->modes)) |
129 | if (list_empty(&connector->modes)) |
Line -... | Line 130... | ||
- | 130 | return 0; |
|
137 | return 0; |
131 | |
138 | 132 | drm_mode_sort(&connector->modes); |
|
139 | drm_mode_sort(&connector->modes); |
133 | |
Line 140... | Line 134... | ||
140 | 134 | DRM_DEBUG_KMS("Probed modes for %s\n", |
|
141 | DRM_DEBUG("Probed modes for %s\n", drm_get_connector_name(connector)); |
135 | drm_get_connector_name(connector)); |
Line 163... | Line 157... | ||
163 | 157 | ||
164 | return count; |
158 | return count; |
165 | } |
159 | } |
Line 166... | Line -... | ||
166 | EXPORT_SYMBOL(drm_helper_probe_connector_modes); |
- | |
167 | - | ||
168 | static void drm_helper_add_std_modes(struct drm_device *dev, |
- | |
169 | struct drm_connector *connector) |
- | |
170 | { |
- | |
171 | struct drm_display_mode *mode, *t; |
- | |
172 | int i; |
- | |
173 | - | ||
174 | for (i = 0; i < ARRAY_SIZE(std_modes); i++) { |
- | |
175 | struct drm_display_mode *stdmode; |
- | |
176 | - | ||
177 | /* |
- | |
178 | * When no valid EDID modes are available we end up |
- | |
179 | * here and bailed in the past, now we add some standard |
- | |
180 | * modes and move on. |
- | |
181 | */ |
- | |
182 | stdmode = drm_mode_duplicate(dev, &std_modes[i]); |
- | |
183 | drm_mode_probed_add(connector, stdmode); |
- | |
184 | drm_mode_list_concat(&connector->probed_modes, |
- | |
185 | &connector->modes); |
- | |
186 | - | ||
187 | DRM_DEBUG("Adding mode %s to %s\n", stdmode->name, |
- | |
188 | drm_get_connector_name(connector)); |
- | |
189 | } |
- | |
190 | drm_mode_sort(&connector->modes); |
- | |
191 | - | ||
192 | DRM_DEBUG("Added std modes on %s\n", drm_get_connector_name(connector)); |
- | |
193 | list_for_each_entry_safe(mode, t, &connector->modes, head) { |
- | |
194 | mode->vrefresh = drm_mode_vrefresh(mode); |
- | |
195 | - | ||
196 | drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); |
- | |
197 | drm_mode_debug_printmodeline(mode); |
- | |
198 | } |
- | |
199 | } |
160 | EXPORT_SYMBOL(drm_helper_probe_connector_modes); |
200 | 161 | ||
201 | /** |
162 | /** |
202 | * drm_helper_encoder_in_use - check if a given encoder is in use |
163 | * drm_helper_encoder_in_use - check if a given encoder is in use |
203 | * @encoder: encoder to check |
164 | * @encoder: encoder to check |
Line 256... | Line 217... | ||
256 | * by calling its dpms function, which should power it off. |
217 | * by calling its dpms function, which should power it off. |
257 | */ |
218 | */ |
258 | void drm_helper_disable_unused_functions(struct drm_device *dev) |
219 | void drm_helper_disable_unused_functions(struct drm_device *dev) |
259 | { |
220 | { |
260 | struct drm_encoder *encoder; |
221 | struct drm_encoder *encoder; |
- | 222 | struct drm_connector *connector; |
|
261 | struct drm_encoder_helper_funcs *encoder_funcs; |
223 | struct drm_encoder_helper_funcs *encoder_funcs; |
262 | struct drm_crtc *crtc; |
224 | struct drm_crtc *crtc; |
Line -... | Line 225... | ||
- | 225 | ||
- | 226 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 227 | if (!connector->encoder) |
|
- | 228 | continue; |
|
- | 229 | if (connector->status == connector_status_disconnected) |
|
- | 230 | connector->encoder = NULL; |
|
- | 231 | } |
|
263 | 232 | ||
264 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
233 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
265 | encoder_funcs = encoder->helper_private; |
234 | encoder_funcs = encoder->helper_private; |
- | 235 | if (!drm_helper_encoder_in_use(encoder)) { |
|
- | 236 | if (encoder_funcs->disable) |
|
- | 237 | (*encoder_funcs->disable)(encoder); |
|
266 | if (!drm_helper_encoder_in_use(encoder)) |
238 | else |
- | 239 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
|
- | 240 | /* disconnector encoder from any connector */ |
|
- | 241 | encoder->crtc = NULL; |
|
267 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
242 | } |
Line 268... | Line 243... | ||
268 | } |
243 | } |
269 | 244 | ||
270 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
245 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
Line 280... | Line 255... | ||
280 | 255 | ||
281 | static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) |
256 | static struct drm_display_mode *drm_has_preferred_mode(struct drm_connector *connector, int width, int height) |
282 | { |
257 | { |
Line 283... | Line -... | ||
283 | struct drm_display_mode *mode; |
- | |
284 | - | ||
285 | ENTRY(); |
258 | struct drm_display_mode *mode; |
286 | 259 | ||
287 | list_for_each_entry(mode, &connector->modes, head) { |
260 | list_for_each_entry(mode, &connector->modes, head) { |
288 | if (drm_mode_width(mode) > width || |
261 | if (drm_mode_width(mode) > width || |
289 | drm_mode_height(mode) > height) |
262 | drm_mode_height(mode) > height) |
Line 312... | Line 285... | ||
312 | struct drm_connector *connector; |
285 | struct drm_connector *connector; |
313 | int i = 0; |
286 | int i = 0; |
Line 314... | Line 287... | ||
314 | 287 | ||
315 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
288 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
316 | enabled[i] = drm_connector_enabled(connector, true); |
289 | enabled[i] = drm_connector_enabled(connector, true); |
317 | DRM_DEBUG("connector %d enabled ? %s\n", connector->base.id, |
290 | DRM_DEBUG_KMS("connector %d enabled? %s\n", connector->base.id, |
318 | enabled[i] ? "yes" : "no"); |
291 | enabled[i] ? "yes" : "no"); |
319 | any_enabled |= enabled[i]; |
292 | any_enabled |= enabled[i]; |
320 | i++; |
293 | i++; |
Line 342... | Line 315... | ||
342 | if (enabled[i] == false) { |
315 | if (enabled[i] == false) { |
343 | i++; |
316 | i++; |
344 | continue; |
317 | continue; |
345 | } |
318 | } |
Line 346... | Line 319... | ||
346 | 319 | ||
347 | DRM_DEBUG("looking for preferred mode on connector %d\n", |
320 | DRM_DEBUG_KMS("looking for preferred mode on connector %d\n", |
Line 348... | Line 321... | ||
348 | connector->base.id); |
321 | connector->base.id); |
349 | 322 | ||
350 | modes[i] = drm_has_preferred_mode(connector, width, height); |
323 | modes[i] = drm_has_preferred_mode(connector, width, height); |
351 | /* No preferred modes, pick one off the list */ |
324 | /* No preferred modes, pick one off the list */ |
352 | if (!modes[i] && !list_empty(&connector->modes)) { |
325 | if (!modes[i] && !list_empty(&connector->modes)) { |
353 | list_for_each_entry(modes[i], &connector->modes, head) |
326 | list_for_each_entry(modes[i], &connector->modes, head) |
354 | break; |
327 | break; |
355 | } |
328 | } |
356 | DRM_DEBUG("found mode %s\n", modes[i] ? modes[i]->name : |
329 | DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : |
357 | "none"); |
330 | "none"); |
358 | i++; |
331 | i++; |
359 | } |
332 | } |
Line 380... | Line 353... | ||
380 | if (c == n) |
353 | if (c == n) |
381 | break; |
354 | break; |
382 | c++; |
355 | c++; |
383 | } |
356 | } |
Line 384... | Line -... | ||
384 | - | ||
385 | dbgprintf("n= %d\n", n); |
- | |
386 | 357 | ||
387 | best_crtcs[n] = NULL; |
358 | best_crtcs[n] = NULL; |
388 | best_crtc = NULL; |
359 | best_crtc = NULL; |
389 | best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height); |
360 | best_score = drm_pick_crtcs(dev, best_crtcs, modes, n+1, width, height); |
390 | if (modes[n] == NULL) |
361 | if (modes[n] == NULL) |
Line 393... | Line 364... | ||
393 | crtcs = kmalloc(dev->mode_config.num_connector * |
364 | crtcs = kmalloc(dev->mode_config.num_connector * |
394 | sizeof(struct drm_crtc *), GFP_KERNEL); |
365 | sizeof(struct drm_crtc *), GFP_KERNEL); |
395 | if (!crtcs) |
366 | if (!crtcs) |
396 | return best_score; |
367 | return best_score; |
Line 397... | Line -... | ||
397 | - | ||
398 | dbgprintf("crtcs = %x\n", crtcs); |
- | |
399 | 368 | ||
400 | my_score = 1; |
369 | my_score = 1; |
401 | if (connector->status == connector_status_connected) |
370 | if (connector->status == connector_status_connected) |
402 | my_score++; |
371 | my_score++; |
403 | if (drm_has_preferred_mode(connector, width, height)) |
372 | if (drm_has_preferred_mode(connector, width, height)) |
Line 404... | Line 373... | ||
404 | my_score++; |
373 | my_score++; |
405 | 374 | ||
406 | connector_funcs = connector->helper_private; |
- | |
407 | encoder = connector_funcs->best_encoder(connector); |
- | |
408 | - | ||
409 | dbgprintf("encoder = %x\n", encoder); |
375 | connector_funcs = connector->helper_private; |
410 | 376 | encoder = connector_funcs->best_encoder(connector); |
|
Line 411... | Line 377... | ||
411 | if (!encoder) |
377 | if (!encoder) |
Line 412... | Line 378... | ||
412 | goto out; |
378 | goto out; |
413 | 379 | ||
414 | connector->encoder = encoder; |
380 | connector->encoder = encoder; |
415 | 381 | ||
Line 416... | Line 382... | ||
416 | /* select a crtc for this connector and then attempt to configure |
382 | /* select a crtc for this connector and then attempt to configure |
417 | remaining connectors */ |
383 | remaining connectors */ |
418 | c = 0; |
384 | c = 0; |
419 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
385 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
Line 420... | Line 386... | ||
420 | 386 | ||
Line 446... | Line 412... | ||
446 | } |
412 | } |
447 | c++; |
413 | c++; |
448 | } |
414 | } |
449 | out: |
415 | out: |
450 | kfree(crtcs); |
416 | kfree(crtcs); |
451 | - | ||
452 | dbgprintf("best_score= %x\n", best_score); |
- | |
453 | - | ||
454 | LEAVE(); |
- | |
455 | - | ||
456 | return best_score; |
417 | return best_score; |
457 | } |
418 | } |
Line 458... | Line 419... | ||
458 | 419 | ||
459 | static void drm_setup_crtcs(struct drm_device *dev) |
420 | static void drm_setup_crtcs(struct drm_device *dev) |
Line 464... | Line 425... | ||
464 | struct drm_connector *connector; |
425 | struct drm_connector *connector; |
465 | bool *enabled; |
426 | bool *enabled; |
466 | int width, height; |
427 | int width, height; |
467 | int i, ret; |
428 | int i, ret; |
Line 468... | Line 429... | ||
468 | 429 | ||
Line 469... | Line 430... | ||
469 | DRM_DEBUG("\n"); |
430 | DRM_DEBUG_KMS("\n"); |
470 | 431 | ||
Line 471... | Line 432... | ||
471 | width = 1280; //dev->mode_config.max_width; |
432 | width = 1280; //dev->mode_config.max_width; |
Line 487... | Line 448... | ||
487 | 448 | ||
488 | ret = drm_target_preferred(dev, modes, enabled, width, height); |
449 | ret = drm_target_preferred(dev, modes, enabled, width, height); |
489 | if (!ret) |
450 | if (!ret) |
Line 490... | Line 451... | ||
490 | DRM_ERROR("Unable to find initial modes\n"); |
451 | DRM_ERROR("Unable to find initial modes\n"); |
Line 491... | Line 452... | ||
491 | 452 | ||
Line 492... | Line 453... | ||
492 | DRM_DEBUG("picking CRTCs for %dx%d config\n", width, height); |
453 | DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n", width, height); |
493 | 454 | ||
Line 502... | Line 463... | ||
502 | i++; |
463 | i++; |
503 | continue; |
464 | continue; |
504 | } |
465 | } |
Line 505... | Line 466... | ||
505 | 466 | ||
506 | if (mode && crtc) { |
467 | if (mode && crtc) { |
507 | DRM_DEBUG("desired mode %s set on crtc %d\n", |
468 | DRM_DEBUG_KMS("desired mode %s set on crtc %d\n", |
508 | mode->name, crtc->base.id); |
469 | mode->name, crtc->base.id); |
509 | crtc->desired_mode = mode; |
- | |
510 | // crtc->mode = *mode; |
470 | crtc->desired_mode = mode; |
511 | crtc->enabled = true; |
471 | crtc->enabled = true; |
512 | connector->encoder->crtc = crtc; |
472 | connector->encoder->crtc = crtc; |
513 | } else |
473 | } else { |
- | 474 | connector->encoder->crtc = NULL; |
|
- | 475 | connector->encoder = NULL; |
|
514 | connector->encoder->crtc = NULL; |
476 | } |
515 | i++; |
477 | i++; |
Line 516... | Line 478... | ||
516 | } |
478 | } |
517 | 479 | ||
518 | kfree(crtcs); |
480 | kfree(crtcs); |
519 | kfree(modes); |
- | |
520 | kfree(enabled); |
- | |
521 | 481 | kfree(modes); |
|
Line 522... | Line 482... | ||
522 | LEAVE(); |
482 | kfree(enabled); |
523 | } |
483 | } |
524 | 484 | ||
Line 601... | Line 561... | ||
601 | struct drm_encoder_helper_funcs *encoder_funcs; |
561 | struct drm_encoder_helper_funcs *encoder_funcs; |
602 | int saved_x, saved_y; |
562 | int saved_x, saved_y; |
603 | struct drm_encoder *encoder; |
563 | struct drm_encoder *encoder; |
604 | bool ret = true; |
564 | bool ret = true; |
Line 605... | Line -... | ||
605 | - | ||
606 | ENTRY(); |
- | |
607 | 565 | ||
Line 608... | Line 566... | ||
608 | adjusted_mode = drm_mode_duplicate(dev, mode); |
566 | adjusted_mode = drm_mode_duplicate(dev, mode); |
Line 609... | Line 567... | ||
609 | 567 | ||
Line 694... | Line 652... | ||
694 | if (!ret) { |
652 | if (!ret) { |
695 | crtc->mode = saved_mode; |
653 | crtc->mode = saved_mode; |
696 | crtc->x = saved_x; |
654 | crtc->x = saved_x; |
697 | crtc->y = saved_y; |
655 | crtc->y = saved_y; |
698 | } |
656 | } |
699 | LEAVE(); |
657 | |
700 | return ret; |
658 | return ret; |
701 | } |
659 | } |
702 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
660 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
Line 720... | Line 678... | ||
720 | * Zero. (FIXME) |
678 | * Zero. (FIXME) |
721 | */ |
679 | */ |
722 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
680 | int drm_crtc_helper_set_config(struct drm_mode_set *set) |
723 | { |
681 | { |
724 | struct drm_device *dev; |
682 | struct drm_device *dev; |
725 | struct drm_crtc **save_crtcs, *new_crtc; |
683 | struct drm_crtc *save_crtcs, *new_crtc, *crtc; |
726 | struct drm_encoder **save_encoders, *new_encoder; |
684 | struct drm_encoder *save_encoders, *new_encoder, *encoder; |
727 | struct drm_framebuffer *old_fb = NULL; |
685 | struct drm_framebuffer *old_fb = NULL; |
728 | bool save_enabled; |
- | |
729 | bool mode_changed = false; |
686 | bool mode_changed = false; /* if true do a full mode set */ |
730 | bool fb_changed = false; |
687 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
731 | struct drm_connector *connector; |
688 | struct drm_connector *save_connectors, *connector; |
732 | int count = 0, ro, fail = 0; |
689 | int count = 0, ro, fail = 0; |
733 | struct drm_crtc_helper_funcs *crtc_funcs; |
690 | struct drm_crtc_helper_funcs *crtc_funcs; |
734 | int ret = 0; |
691 | int ret = 0; |
Line 735... | Line 692... | ||
735 | 692 | ||
Line 736... | Line 693... | ||
736 | DRM_DEBUG("\n"); |
693 | DRM_DEBUG_KMS("\n"); |
737 | 694 | ||
Line 738... | Line 695... | ||
738 | if (!set) |
695 | if (!set) |
Line 744... | Line 701... | ||
744 | if (!set->crtc->helper_private) |
701 | if (!set->crtc->helper_private) |
745 | return -EINVAL; |
702 | return -EINVAL; |
Line 746... | Line 703... | ||
746 | 703 | ||
Line 747... | Line 704... | ||
747 | crtc_funcs = set->crtc->helper_private; |
704 | crtc_funcs = set->crtc->helper_private; |
- | 705 | ||
748 | 706 | DRM_DEBUG_KMS("crtc: %p %d fb: %p connectors: %p num_connectors:" |
|
749 | DRM_DEBUG("crtc: %p %d fb: %p connectors: %p num_connectors: %d (x, y) (%i, %i)\n", |
707 | " %d (x, y) (%i, %i)\n", |
Line 750... | Line 708... | ||
750 | set->crtc, set->crtc->base.id, set->fb, set->connectors, |
708 | set->crtc, set->crtc->base.id, set->fb, set->connectors, |
Line 751... | Line -... | ||
751 | (int)set->num_connectors, set->x, set->y); |
- | |
752 | - | ||
753 | dev = set->crtc->dev; |
- | |
754 | - | ||
755 | /* save previous config */ |
709 | (int)set->num_connectors, set->x, set->y); |
756 | save_enabled = set->crtc->enabled; |
710 | |
757 | - | ||
758 | /* |
711 | dev = set->crtc->dev; |
759 | * We do mode_config.num_connectors here since we'll look at the |
712 | |
760 | * CRTC and encoder associated with each connector later. |
713 | /* Allocate space for the backup of all (non-pointer) crtc, encoder and |
761 | */ |
714 | * connector data. */ |
Line 762... | Line 715... | ||
762 | save_crtcs = kzalloc(dev->mode_config.num_connector * |
715 | save_crtcs = kzalloc(dev->mode_config.num_crtc * |
763 | sizeof(struct drm_crtc *), GFP_KERNEL); |
716 | sizeof(struct drm_crtc), GFP_KERNEL); |
764 | if (!save_crtcs) |
717 | if (!save_crtcs) |
765 | return -ENOMEM; |
718 | return -ENOMEM; |
766 | 719 | ||
767 | save_encoders = kzalloc(dev->mode_config.num_connector * |
720 | save_encoders = kzalloc(dev->mode_config.num_encoder * |
Line -... | Line 721... | ||
- | 721 | sizeof(struct drm_encoder), GFP_KERNEL); |
|
- | 722 | if (!save_encoders) { |
|
- | 723 | kfree(save_crtcs); |
|
- | 724 | return -ENOMEM; |
|
- | 725 | } |
|
- | 726 | ||
- | 727 | save_connectors = kzalloc(dev->mode_config.num_connector * |
|
- | 728 | sizeof(struct drm_connector), GFP_KERNEL); |
|
- | 729 | if (!save_connectors) { |
|
- | 730 | kfree(save_crtcs); |
|
- | 731 | kfree(save_encoders); |
|
- | 732 | return -ENOMEM; |
|
- | 733 | } |
|
- | 734 | ||
- | 735 | /* Copy data. Note that driver private data is not affected. |
|
- | 736 | * Should anything bad happen only the expected state is |
|
- | 737 | * restored, not the drivers personal bookkeeping. |
|
- | 738 | */ |
|
- | 739 | count = 0; |
|
- | 740 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
|
- | 741 | save_crtcs[count++] = *crtc; |
|
- | 742 | } |
|
- | 743 | ||
- | 744 | count = 0; |
|
- | 745 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
- | 746 | save_encoders[count++] = *encoder; |
|
- | 747 | } |
|
768 | sizeof(struct drm_encoders *), GFP_KERNEL); |
748 | |
769 | if (!save_encoders) { |
749 | count = 0; |
770 | kfree(save_crtcs); |
750 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
771 | return -ENOMEM; |
751 | save_connectors[count++] = *connector; |
772 | } |
752 | } |
773 | 753 | ||
- | 754 | /* We should be able to check here if the fb has the same properties |
|
- | 755 | * and then just flip_or_move it */ |
|
774 | /* We should be able to check here if the fb has the same properties |
756 | if (set->crtc->fb != set->fb) { |
775 | * and then just flip_or_move it */ |
757 | /* If we have no fb then treat it as a full mode set */ |
776 | if (set->crtc->fb != set->fb) { |
758 | if (set->crtc->fb == NULL) { |
777 | /* If we have no fb then treat it as a full mode set */ |
759 | DRM_DEBUG_KMS("crtc has no fb, full mode set\n"); |
778 | if (set->crtc->fb == NULL) { |
760 | mode_changed = true; |
Line 788... | Line 770... | ||
788 | 770 | ||
789 | if (set->x != set->crtc->x || set->y != set->crtc->y) |
771 | if (set->x != set->crtc->x || set->y != set->crtc->y) |
Line 790... | Line 772... | ||
790 | fb_changed = true; |
772 | fb_changed = true; |
791 | 773 | ||
792 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
774 | if (set->mode && !drm_mode_equal(set->mode, &set->crtc->mode)) { |
793 | DRM_DEBUG("modes are different, full mode set\n"); |
775 | DRM_DEBUG_KMS("modes are different, full mode set\n"); |
794 | drm_mode_debug_printmodeline(&set->crtc->mode); |
776 | drm_mode_debug_printmodeline(&set->crtc->mode); |
795 | drm_mode_debug_printmodeline(set->mode); |
777 | drm_mode_debug_printmodeline(set->mode); |
Line 796... | Line 778... | ||
796 | mode_changed = true; |
778 | mode_changed = true; |
797 | } |
779 | } |
798 | 780 | ||
799 | /* a) traverse passed in connector list and get encoders for them */ |
781 | /* a) traverse passed in connector list and get encoders for them */ |
800 | count = 0; |
782 | count = 0; |
801 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
802 | struct drm_connector_helper_funcs *connector_funcs = |
783 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
803 | connector->helper_private; |
784 | struct drm_connector_helper_funcs *connector_funcs = |
804 | save_encoders[count++] = connector->encoder; |
785 | connector->helper_private; |
805 | new_encoder = connector->encoder; |
786 | new_encoder = connector->encoder; |
806 | for (ro = 0; ro < set->num_connectors; ro++) { |
787 | for (ro = 0; ro < set->num_connectors; ro++) { |
Line 814... | Line 795... | ||
814 | break; |
795 | break; |
815 | } |
796 | } |
816 | } |
797 | } |
Line 817... | Line 798... | ||
817 | 798 | ||
818 | if (new_encoder != connector->encoder) { |
799 | if (new_encoder != connector->encoder) { |
819 | DRM_DEBUG("encoder changed, full mode switch\n"); |
800 | DRM_DEBUG_KMS("encoder changed, full mode switch\n"); |
- | 801 | mode_changed = true; |
|
- | 802 | /* If the encoder is reused for another connector, then |
|
- | 803 | * the appropriate crtc will be set later. |
|
- | 804 | */ |
|
- | 805 | if (connector->encoder) |
|
820 | mode_changed = true; |
806 | connector->encoder->crtc = NULL; |
821 | connector->encoder = new_encoder; |
807 | connector->encoder = new_encoder; |
822 | } |
808 | } |
Line 823... | Line 809... | ||
823 | } |
809 | } |
824 | 810 | ||
825 | if (fail) { |
811 | if (fail) { |
826 | ret = -EINVAL; |
812 | ret = -EINVAL; |
Line 827... | Line 813... | ||
827 | goto fail_no_encoder; |
813 | goto fail; |
828 | } |
814 | } |
829 | 815 | ||
830 | count = 0; |
816 | count = 0; |
Line 831... | Line -... | ||
831 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
- | |
832 | if (!connector->encoder) |
- | |
833 | continue; |
817 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
834 | 818 | if (!connector->encoder) |
|
835 | save_crtcs[count++] = connector->encoder->crtc; |
819 | continue; |
836 | 820 | ||
Line 846... | Line 830... | ||
846 | 830 | ||
847 | /* Make sure the new CRTC will work with the encoder */ |
831 | /* Make sure the new CRTC will work with the encoder */ |
848 | if (new_crtc && |
832 | if (new_crtc && |
849 | !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { |
833 | !drm_encoder_crtc_ok(connector->encoder, new_crtc)) { |
850 | ret = -EINVAL; |
834 | ret = -EINVAL; |
851 | goto fail_set_mode; |
835 | goto fail; |
852 | } |
836 | } |
853 | if (new_crtc != connector->encoder->crtc) { |
837 | if (new_crtc != connector->encoder->crtc) { |
854 | DRM_DEBUG("crtc changed, full mode switch\n"); |
838 | DRM_DEBUG_KMS("crtc changed, full mode switch\n"); |
855 | mode_changed = true; |
839 | mode_changed = true; |
856 | connector->encoder->crtc = new_crtc; |
840 | connector->encoder->crtc = new_crtc; |
857 | } |
841 | } |
858 | DRM_DEBUG("setting connector %d crtc to %p\n", |
842 | DRM_DEBUG_KMS("setting connector %d crtc to %p\n", |
859 | connector->base.id, new_crtc); |
843 | connector->base.id, new_crtc); |
Line 860... | Line 844... | ||
860 | } |
844 | } |
861 | 845 | ||
Line 866... | Line 850... | ||
866 | if (mode_changed) { |
850 | if (mode_changed) { |
867 | old_fb = set->crtc->fb; |
851 | old_fb = set->crtc->fb; |
868 | set->crtc->fb = set->fb; |
852 | set->crtc->fb = set->fb; |
869 | set->crtc->enabled = (set->mode != NULL); |
853 | set->crtc->enabled = (set->mode != NULL); |
870 | if (set->mode != NULL) { |
854 | if (set->mode != NULL) { |
871 | DRM_DEBUG("attempting to set mode from userspace\n"); |
855 | DRM_DEBUG_KMS("attempting to set mode from" |
- | 856 | " userspace\n"); |
|
872 | drm_mode_debug_printmodeline(set->mode); |
857 | drm_mode_debug_printmodeline(set->mode); |
873 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
858 | if (!drm_crtc_helper_set_mode(set->crtc, set->mode, |
874 | set->x, set->y, |
859 | set->x, set->y, |
875 | old_fb)) { |
860 | old_fb)) { |
876 | DRM_ERROR("failed to set mode on crtc %p\n", |
861 | DRM_ERROR("failed to set mode on crtc %p\n", |
877 | set->crtc); |
862 | set->crtc); |
878 | ret = -EINVAL; |
863 | ret = -EINVAL; |
879 | goto fail_set_mode; |
864 | goto fail; |
880 | } |
865 | } |
881 | /* TODO are these needed? */ |
866 | /* TODO are these needed? */ |
882 | set->crtc->desired_x = set->x; |
867 | set->crtc->desired_x = set->x; |
883 | set->crtc->desired_y = set->y; |
868 | set->crtc->desired_y = set->y; |
884 | set->crtc->desired_mode = set->mode; |
869 | set->crtc->desired_mode = set->mode; |
885 | } |
870 | } |
886 | drm_helper_disable_unused_functions(dev); |
871 | drm_helper_disable_unused_functions(dev); |
887 | } else if (fb_changed) { |
872 | } else if (fb_changed) { |
- | 873 | set->crtc->x = set->x; |
|
- | 874 | set->crtc->y = set->y; |
|
- | 875 | ||
888 | old_fb = set->crtc->fb; |
876 | old_fb = set->crtc->fb; |
889 | if (set->crtc->fb != set->fb) |
877 | if (set->crtc->fb != set->fb) |
890 | set->crtc->fb = set->fb; |
878 | set->crtc->fb = set->fb; |
891 | ret = crtc_funcs->mode_set_base(set->crtc, |
879 | ret = crtc_funcs->mode_set_base(set->crtc, |
892 | set->x, set->y, old_fb); |
880 | set->x, set->y, old_fb); |
893 | if (ret != 0) |
881 | if (ret != 0) |
894 | goto fail_set_mode; |
882 | goto fail; |
895 | } |
883 | } |
Line -... | Line 884... | ||
- | 884 | ||
896 | 885 | kfree(save_connectors); |
|
897 | kfree(save_encoders); |
886 | kfree(save_encoders); |
898 | kfree(save_crtcs); |
887 | kfree(save_crtcs); |
Line 899... | Line 888... | ||
899 | return 0; |
888 | return 0; |
900 | 889 | ||
901 | fail_set_mode: |
- | |
902 | set->crtc->enabled = save_enabled; |
890 | fail: |
903 | set->crtc->fb = old_fb; |
891 | /* Restore all previous data. */ |
904 | count = 0; |
892 | count = 0; |
905 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
893 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
Line -... | Line 894... | ||
- | 894 | *crtc = save_crtcs[count++]; |
|
- | 895 | } |
|
906 | if (!connector->encoder) |
896 | |
907 | continue; |
897 | count = 0; |
908 | - | ||
909 | connector->encoder->crtc = save_crtcs[count++]; |
- | |
- | 898 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
910 | } |
899 | *encoder = save_encoders[count++]; |
911 | fail_no_encoder: |
900 | } |
912 | kfree(save_crtcs); |
901 | |
913 | count = 0; |
902 | count = 0; |
- | 903 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 904 | *connector = save_connectors[count++]; |
|
914 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
905 | } |
- | 906 | ||
915 | connector->encoder = save_encoders[count++]; |
907 | kfree(save_connectors); |
916 | } |
908 | kfree(save_encoders); |
917 | kfree(save_encoders); |
909 | kfree(save_crtcs); |
Line 918... | Line 910... | ||
918 | return ret; |
910 | return ret; |
919 | } |
911 | } |
920 | EXPORT_SYMBOL(drm_crtc_helper_set_config); |
912 | EXPORT_SYMBOL(drm_crtc_helper_set_config); |
Line 921... | Line 913... | ||
921 | 913 | ||
922 | bool drm_helper_plugged_event(struct drm_device *dev) |
914 | bool drm_helper_plugged_event(struct drm_device *dev) |
Line 923... | Line 915... | ||
923 | { |
915 | { |
Line 948... | Line 940... | ||
948 | * RETURNS: |
940 | * RETURNS: |
949 | * Zero if everything went ok, nonzero otherwise. |
941 | * Zero if everything went ok, nonzero otherwise. |
950 | */ |
942 | */ |
951 | bool drm_helper_initial_config(struct drm_device *dev) |
943 | bool drm_helper_initial_config(struct drm_device *dev) |
952 | { |
944 | { |
953 | struct drm_connector *connector; |
- | |
954 | int count = 0; |
945 | int count = 0; |
Line 955... | Line -... | ||
955 | - | ||
956 | ENTRY(); |
- | |
957 | 946 | ||
958 | count = drm_helper_probe_connector_modes(dev, |
947 | count = drm_helper_probe_connector_modes(dev, |
959 | dev->mode_config.max_width, |
948 | dev->mode_config.max_width, |
Line 960... | Line 949... | ||
960 | dev->mode_config.max_height); |
949 | dev->mode_config.max_height); |
961 | - | ||
962 | /* |
950 | |
963 | * None of the available connectors had any modes, so add some |
951 | /* |
964 | * and try to light them up anyway |
- | |
965 | */ |
952 | * we shouldn't end up with no modes here. |
966 | if (!count) { |
- | |
967 | DRM_ERROR("connectors have no modes, using standard modes\n"); |
- | |
968 | list_for_each_entry(connector, |
- | |
969 | &dev->mode_config.connector_list, |
- | |
970 | head) |
- | |
Line 971... | Line 953... | ||
971 | drm_helper_add_std_modes(dev, connector); |
953 | */ |
Line 972... | Line -... | ||
972 | } |
- | |
973 | - | ||
974 | drm_setup_crtcs(dev); |
954 | // WARN(!count, "Connected connector with 0 modes\n"); |
975 | 955 | ||
Line 976... | Line -... | ||
976 | radeonfb_create(dev->dev_private, 1280, 1024, 1280, 1024, NULL); |
- | |
977 | - | ||
978 | // /* alert the driver fb layer */ |
956 | drm_setup_crtcs(dev); |
979 | dev->mode_config.funcs->fb_changed(dev); |
957 | |
980 | 958 | /* alert the driver fb layer */ |
|
Line 981... | Line 959... | ||
981 | LEAVE(); |
959 | dev->mode_config.funcs->fb_changed(dev); |
Line 1098... | Line 1076... | ||
1098 | 1076 | ||
1099 | return 0; |
1077 | return 0; |
1100 | } |
1078 | } |
Line 1101... | Line 1079... | ||
1101 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); |
1079 | EXPORT_SYMBOL(drm_helper_mode_fill_fb_struct); |
1102 | 1080 | ||
1103 | void sysSetScreen(int width, int height) |
1081 | void sysSetScreen(int width, int height, int pitch) |
1104 | { |
1082 | { |
1105 | asm __volatile__ |
- | |
1106 | ( |
- | |
1107 | "decl %%eax \n\t" |
1083 | asm __volatile__ |
1108 | "dec %%edx \n\t" |
1084 | ( |
1109 | "call *__imp__SetScreen" |
1085 | "call *__imp__SetScreen" |
1110 | : |
1086 | : |
1111 | :"a" (width),"d"(height) |
1087 | :"a" (width-1),"d"(height-1), "c"(pitch) |
1112 | :"memory","cc" |
1088 | :"memory","cc" |
Line 1113... | Line 1089... | ||
1113 | ); |
1089 | ); |
1114 | } |
1090 | } |
1115 | 1091 | ||
1116 | - | ||
1117 | int drm_helper_resume_force_mode(struct drm_device *dev) |
- | |
1118 | { |
1092 | |
Line 1119... | Line -... | ||
1119 | struct drm_crtc *crtc; |
- | |
1120 | struct drm_framebuffer *fb; |
- | |
1121 | 1093 | int drm_helper_resume_force_mode(struct drm_device *dev) |
|
Line 1122... | Line 1094... | ||
1122 | int ret; |
1094 | { |
1123 | 1095 | struct drm_crtc *crtc; |
|
1124 | ENTRY(); |
- | |
1125 | - | ||
1126 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
- | |
1127 | - | ||
1128 | if (!crtc->enabled) |
- | |
1129 | continue; |
- | |
Line 1130... | Line 1096... | ||
1130 | dbgprintf("mode %x x %x y %x fb %x\n", |
1096 | int ret; |
1131 | crtc->x, crtc->y, crtc->fb, crtc->mode); |
1097 | |
Line 1132... | Line 1098... | ||
1132 | 1098 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
|
1133 | fb = list_first_entry(&dev->mode_config.fb_kernel_list, struct drm_framebuffer, filp_head); |
1099 | |
1134 | - | ||
1135 | crtc->fb = fb; |
- | |
1136 | - | ||
1137 | ret = drm_crtc_helper_set_mode(crtc, crtc->desired_mode, |
1100 | if (!crtc->enabled) |
- | 1101 | continue; |
|
1138 | crtc->x, crtc->y, crtc->fb); |
1102 | |
1139 | 1103 | ret = drm_crtc_helper_set_mode(crtc, &crtc->mode, |
|
1140 | if (ret == false) |
1104 | crtc->x, crtc->y, crtc->fb); |
1141 | DRM_ERROR("failed to set mode on crtc %p\n", crtc); |
1105 |