Rev 2160 | Rev 3051 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 2160 | Rev 3031 | ||
---|---|---|---|
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 | ||
- | 32 | #include |
|
- | 33 | #include |
|
31 | 34 | ||
32 | #include "drmP.h" |
35 | #include |
- | 36 | #include |
|
33 | #include "drm_crtc.h" |
37 | #include |
34 | #include "drm_crtc_helper.h" |
38 | #include |
- | 39 | #include |
|
Line 35... | Line 40... | ||
35 | #include "drm_fb_helper.h" |
40 | #include |
Line 36... | Line 41... | ||
36 | 41 | ||
37 | static bool drm_kms_helper_poll = true; |
42 | static bool drm_kms_helper_poll = true; |
38 | 43 | ||
39 | static void drm_mode_validate_flag(struct drm_connector *connector, |
44 | static void drm_mode_validate_flag(struct drm_connector *connector, |
Line 40... | Line 45... | ||
40 | int flags) |
45 | int flags) |
41 | { |
46 | { |
Line 42... | Line 47... | ||
42 | struct drm_display_mode *mode, *t; |
47 | struct drm_display_mode *mode; |
43 | 48 | ||
44 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) |
49 | if (flags == (DRM_MODE_FLAG_DBLSCAN | DRM_MODE_FLAG_INTERLACE)) |
45 | return; |
50 | return; |
46 | 51 | ||
47 | list_for_each_entry_safe(mode, t, &connector->modes, head) { |
52 | list_for_each_entry(mode, &connector->modes, head) { |
Line 80... | Line 85... | ||
80 | */ |
85 | */ |
81 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
86 | int drm_helper_probe_single_connector_modes(struct drm_connector *connector, |
82 | uint32_t maxX, uint32_t maxY) |
87 | uint32_t maxX, uint32_t maxY) |
83 | { |
88 | { |
84 | struct drm_device *dev = connector->dev; |
89 | struct drm_device *dev = connector->dev; |
85 | struct drm_display_mode *mode, *t; |
90 | struct drm_display_mode *mode; |
86 | struct drm_connector_helper_funcs *connector_funcs = |
91 | struct drm_connector_helper_funcs *connector_funcs = |
87 | connector->helper_private; |
92 | connector->helper_private; |
88 | int count = 0; |
93 | int count = 0; |
89 | int mode_flags = 0; |
94 | int mode_flags = 0; |
Line 90... | Line 95... | ||
90 | 95 | ||
91 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
96 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, |
92 | drm_get_connector_name(connector)); |
97 | drm_get_connector_name(connector)); |
93 | /* set all modes to the unverified state */ |
98 | /* set all modes to the unverified state */ |
94 | list_for_each_entry_safe(mode, t, &connector->modes, head) |
99 | list_for_each_entry(mode, &connector->modes, head) |
Line 95... | Line 100... | ||
95 | mode->status = MODE_UNVERIFIED; |
100 | mode->status = MODE_UNVERIFIED; |
96 | 101 | ||
97 | if (connector->force) { |
102 | if (connector->force) { |
Line 111... | Line 116... | ||
111 | connector->base.id, drm_get_connector_name(connector)); |
116 | connector->base.id, drm_get_connector_name(connector)); |
112 | drm_mode_connector_update_edid_property(connector, NULL); |
117 | drm_mode_connector_update_edid_property(connector, NULL); |
113 | goto prune; |
118 | goto prune; |
114 | } |
119 | } |
Line -... | Line 120... | ||
- | 120 | ||
- | 121 | #ifdef CONFIG_DRM_LOAD_EDID_FIRMWARE |
|
- | 122 | count = drm_load_edid_firmware(connector); |
|
- | 123 | if (count == 0) |
|
115 | 124 | #endif |
|
- | 125 | count = (*connector_funcs->get_modes)(connector); |
|
116 | count = (*connector_funcs->get_modes)(connector); |
126 | |
117 | if (count == 0 && connector->status == connector_status_connected) |
127 | if (count == 0 && connector->status == connector_status_connected) |
118 | count = drm_add_modes_noedid(connector, 1024, 768); |
128 | count = drm_add_modes_noedid(connector, 1024, 768); |
119 | if (count == 0) |
129 | if (count == 0) |
Line 129... | Line 139... | ||
129 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
139 | mode_flags |= DRM_MODE_FLAG_INTERLACE; |
130 | if (connector->doublescan_allowed) |
140 | if (connector->doublescan_allowed) |
131 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
141 | mode_flags |= DRM_MODE_FLAG_DBLSCAN; |
132 | drm_mode_validate_flag(connector, mode_flags); |
142 | drm_mode_validate_flag(connector, mode_flags); |
Line 133... | Line 143... | ||
133 | 143 | ||
134 | list_for_each_entry_safe(mode, t, &connector->modes, head) { |
144 | list_for_each_entry(mode, &connector->modes, head) { |
135 | if (mode->status == MODE_OK) |
145 | if (mode->status == MODE_OK) |
136 | mode->status = connector_funcs->mode_valid(connector, |
146 | mode->status = connector_funcs->mode_valid(connector, |
137 | mode); |
147 | mode); |
Line 145... | Line 155... | ||
145 | 155 | ||
Line 146... | Line 156... | ||
146 | drm_mode_sort(&connector->modes); |
156 | drm_mode_sort(&connector->modes); |
147 | 157 | ||
148 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, |
158 | DRM_DEBUG_KMS("[CONNECTOR:%d:%s] probed modes :\n", connector->base.id, |
149 | drm_get_connector_name(connector)); |
159 | drm_get_connector_name(connector)); |
Line 150... | Line 160... | ||
150 | list_for_each_entry_safe(mode, t, &connector->modes, head) { |
160 | list_for_each_entry(mode, &connector->modes, head) { |
151 | mode->vrefresh = drm_mode_vrefresh(mode); |
161 | mode->vrefresh = drm_mode_vrefresh(mode); |
152 | 162 | ||
Line 256... | Line 266... | ||
256 | else |
266 | else |
257 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); |
267 | (*crtc_funcs->dpms)(crtc, DRM_MODE_DPMS_OFF); |
258 | crtc->fb = NULL; |
268 | crtc->fb = NULL; |
259 | } |
269 | } |
260 | } |
270 | } |
- | 271 | ||
261 | } |
272 | } |
262 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
273 | EXPORT_SYMBOL(drm_helper_disable_unused_functions); |
Line 263... | Line 274... | ||
263 | 274 | ||
264 | /** |
275 | /** |
Line 340... | Line 351... | ||
340 | struct drm_encoder_helper_funcs *encoder_funcs; |
351 | struct drm_encoder_helper_funcs *encoder_funcs; |
341 | int saved_x, saved_y; |
352 | int saved_x, saved_y; |
342 | struct drm_encoder *encoder; |
353 | struct drm_encoder *encoder; |
343 | bool ret = true; |
354 | bool ret = true; |
Line -... | Line 355... | ||
- | 355 | ||
- | 356 | ENTER(); |
|
344 | 357 | ||
345 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
358 | crtc->enabled = drm_helper_crtc_in_use(crtc); |
346 | if (!crtc->enabled) |
359 | if (!crtc->enabled) |
Line -... | Line 360... | ||
- | 360 | return true; |
|
- | 361 | ||
347 | return true; |
362 | printf("crtc->enabled\n"); |
- | 363 | ||
- | 364 | adjusted_mode = drm_mode_duplicate(dev, mode); |
|
- | 365 | if (!adjusted_mode) |
|
- | 366 | return false; |
|
Line 348... | Line 367... | ||
348 | 367 | ||
349 | adjusted_mode = drm_mode_duplicate(dev, mode); |
368 | printf("adjusted_mode\n"); |
350 | 369 | ||
351 | saved_hwmode = crtc->hwmode; |
370 | saved_hwmode = crtc->hwmode; |
Line 369... | Line 388... | ||
369 | if (encoder->crtc != crtc) |
388 | if (encoder->crtc != crtc) |
370 | continue; |
389 | continue; |
371 | encoder_funcs = encoder->helper_private; |
390 | encoder_funcs = encoder->helper_private; |
372 | if (!(ret = encoder_funcs->mode_fixup(encoder, mode, |
391 | if (!(ret = encoder_funcs->mode_fixup(encoder, mode, |
373 | adjusted_mode))) { |
392 | adjusted_mode))) { |
- | 393 | DRM_DEBUG_KMS("Encoder fixup failed\n"); |
|
374 | goto done; |
394 | goto done; |
375 | } |
395 | } |
376 | } |
396 | } |
Line -... | Line 397... | ||
- | 397 | ||
- | 398 | printf("list_for_each_entry\n"); |
|
- | 399 | printf("mode_fixup %x\n", crtc_funcs->mode_fixup); |
|
377 | 400 | ||
- | 401 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { |
|
378 | if (!(ret = crtc_funcs->mode_fixup(crtc, mode, adjusted_mode))) { |
402 | DRM_DEBUG_KMS("CRTC fixup failed\n"); |
379 | goto done; |
403 | goto done; |
380 | } |
404 | } |
Line 381... | Line 405... | ||
381 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
405 | DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id); |
Line 443... | Line 467... | ||
443 | crtc->mode = saved_mode; |
467 | crtc->mode = saved_mode; |
444 | crtc->x = saved_x; |
468 | crtc->x = saved_x; |
445 | crtc->y = saved_y; |
469 | crtc->y = saved_y; |
446 | } |
470 | } |
Line -... | Line 471... | ||
- | 471 | ||
- | 472 | LEAVE(); |
|
447 | 473 | ||
448 | return ret; |
474 | return ret; |
449 | } |
475 | } |
Line -... | Line 476... | ||
- | 476 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
|
- | 477 | ||
- | 478 | ||
- | 479 | static int |
|
- | 480 | drm_crtc_helper_disable(struct drm_crtc *crtc) |
|
- | 481 | { |
|
- | 482 | struct drm_device *dev = crtc->dev; |
|
- | 483 | struct drm_connector *connector; |
|
- | 484 | struct drm_encoder *encoder; |
|
- | 485 | ||
- | 486 | /* Decouple all encoders and their attached connectors from this crtc */ |
|
- | 487 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
|
- | 488 | if (encoder->crtc != crtc) |
|
- | 489 | continue; |
|
- | 490 | ||
- | 491 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
|
- | 492 | if (connector->encoder != encoder) |
|
- | 493 | continue; |
|
- | 494 | ||
- | 495 | connector->encoder = NULL; |
|
- | 496 | } |
|
- | 497 | } |
|
- | 498 | ||
- | 499 | drm_helper_disable_unused_functions(dev); |
|
450 | EXPORT_SYMBOL(drm_crtc_helper_set_mode); |
500 | return 0; |
451 | 501 | } |
|
452 | 502 | ||
453 | /** |
503 | /** |
454 | * drm_crtc_helper_set_config - set a new config from userspace |
504 | * drm_crtc_helper_set_config - set a new config from userspace |
Line 476... | Line 526... | ||
476 | bool mode_changed = false; /* if true do a full mode set */ |
526 | bool mode_changed = false; /* if true do a full mode set */ |
477 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
527 | bool fb_changed = false; /* if true and !mode_changed just do a flip */ |
478 | struct drm_connector *save_connectors, *connector; |
528 | struct drm_connector *save_connectors, *connector; |
479 | int count = 0, ro, fail = 0; |
529 | int count = 0, ro, fail = 0; |
480 | struct drm_crtc_helper_funcs *crtc_funcs; |
530 | struct drm_crtc_helper_funcs *crtc_funcs; |
- | 531 | struct drm_mode_set save_set; |
|
481 | int ret = 0; |
532 | int ret; |
482 | int i; |
533 | int i; |
Line 483... | Line 534... | ||
483 | 534 | ||
Line 484... | Line 535... | ||
484 | DRM_DEBUG_KMS("\n"); |
535 | DRM_DEBUG_KMS("\n"); |
Line 501... | Line 552... | ||
501 | DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", |
552 | DRM_DEBUG_KMS("[CRTC:%d] [FB:%d] #connectors=%d (x y) (%i %i)\n", |
502 | set->crtc->base.id, set->fb->base.id, |
553 | set->crtc->base.id, set->fb->base.id, |
503 | (int)set->num_connectors, set->x, set->y); |
554 | (int)set->num_connectors, set->x, set->y); |
504 | } else { |
555 | } else { |
505 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
556 | DRM_DEBUG_KMS("[CRTC:%d] [NOFB]\n", set->crtc->base.id); |
506 | set->mode = NULL; |
- | |
507 | set->num_connectors = 0; |
557 | return drm_crtc_helper_disable(set->crtc); |
508 | } |
558 | } |
Line 509... | Line 559... | ||
509 | 559 | ||
Line 510... | Line 560... | ||
510 | dev = set->crtc->dev; |
560 | dev = set->crtc->dev; |
Line 548... | Line 598... | ||
548 | count = 0; |
598 | count = 0; |
549 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
599 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
550 | save_connectors[count++] = *connector; |
600 | save_connectors[count++] = *connector; |
551 | } |
601 | } |
Line -... | Line 602... | ||
- | 602 | ||
- | 603 | save_set.crtc = set->crtc; |
|
- | 604 | save_set.mode = &set->crtc->mode; |
|
- | 605 | save_set.x = set->crtc->x; |
|
- | 606 | save_set.y = set->crtc->y; |
|
- | 607 | save_set.fb = set->crtc->fb; |
|
552 | 608 | ||
553 | /* We should be able to check here if the fb has the same properties |
609 | /* We should be able to check here if the fb has the same properties |
554 | * and then just flip_or_move it */ |
610 | * and then just flip_or_move it */ |
555 | if (set->crtc->fb != set->fb) { |
611 | if (set->crtc->fb != set->fb) { |
556 | /* If we have no fb then treat it as a full mode set */ |
612 | /* If we have no fb then treat it as a full mode set */ |
Line 672... | Line 728... | ||
672 | } |
728 | } |
673 | DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); |
729 | DRM_DEBUG_KMS("Setting connector DPMS state to on\n"); |
674 | for (i = 0; i < set->num_connectors; i++) { |
730 | for (i = 0; i < set->num_connectors; i++) { |
675 | DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, |
731 | DRM_DEBUG_KMS("\t[CONNECTOR:%d:%s] set DPMS on\n", set->connectors[i]->base.id, |
676 | drm_get_connector_name(set->connectors[i])); |
732 | drm_get_connector_name(set->connectors[i])); |
677 | set->connectors[i]->dpms = DRM_MODE_DPMS_ON; |
733 | set->connectors[i]->funcs->dpms(set->connectors[i], DRM_MODE_DPMS_ON); |
678 | } |
734 | } |
679 | } |
735 | } |
680 | drm_helper_disable_unused_functions(dev); |
736 | drm_helper_disable_unused_functions(dev); |
681 | } else if (fb_changed) { |
737 | } else if (fb_changed) { |
682 | set->crtc->x = set->x; |
738 | set->crtc->x = set->x; |
Line 713... | Line 769... | ||
713 | count = 0; |
769 | count = 0; |
714 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
770 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) { |
715 | *connector = save_connectors[count++]; |
771 | *connector = save_connectors[count++]; |
716 | } |
772 | } |
Line -... | Line 773... | ||
- | 773 | ||
- | 774 | /* Try to restore the config */ |
|
- | 775 | if (mode_changed && |
|
- | 776 | !drm_crtc_helper_set_mode(save_set.crtc, save_set.mode, save_set.x, |
|
- | 777 | save_set.y, save_set.fb)) |
|
- | 778 | DRM_ERROR("failed to restore config after modeset failure\n"); |
|
717 | 779 | ||
718 | kfree(save_connectors); |
780 | kfree(save_connectors); |
719 | kfree(save_encoders); |
781 | kfree(save_encoders); |
720 | kfree(save_crtcs); |
782 | kfree(save_crtcs); |
721 | return ret; |
783 | return ret; |
Line 803... | Line 865... | ||
803 | return; |
865 | return; |
804 | } |
866 | } |
805 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
867 | EXPORT_SYMBOL(drm_helper_connector_dpms); |
Line 806... | Line 868... | ||
806 | 868 | ||
807 | int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |
869 | int drm_helper_mode_fill_fb_struct(struct drm_framebuffer *fb, |
808 | struct drm_mode_fb_cmd *mode_cmd) |
870 | struct drm_mode_fb_cmd2 *mode_cmd) |
- | 871 | { |
|
- | 872 | int i; |
|
809 | { |
873 | |
810 | fb->width = mode_cmd->width; |
874 | fb->width = mode_cmd->width; |
- | 875 | fb->height = mode_cmd->height; |
|
811 | fb->height = mode_cmd->height; |
876 | for (i = 0; i < 4; i++) { |
812 | fb->pitch = mode_cmd->pitch; |
877 | fb->pitches[i] = mode_cmd->pitches[i]; |
- | 878 | fb->offsets[i] = mode_cmd->offsets[i]; |
|
- | 879 | } |
|
- | 880 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &fb->depth, |
|
813 | fb->bits_per_pixel = mode_cmd->bpp; |
881 | &fb->bits_per_pixel); |
Line 814... | Line 882... | ||
814 | fb->depth = mode_cmd->depth; |
882 | fb->pixel_format = mode_cmd->pixel_format; |
815 | 883 | ||
816 | return 0; |
884 | return 0; |
Line 911... | Line 979... | ||
911 | if (dev->mode_config.funcs->output_poll_changed) |
979 | if (dev->mode_config.funcs->output_poll_changed) |
912 | dev->mode_config.funcs->output_poll_changed(dev); |
980 | dev->mode_config.funcs->output_poll_changed(dev); |
913 | } |
981 | } |
Line 914... | Line 982... | ||
914 | 982 | ||
915 | if (repoll) |
983 | if (repoll) |
916 | queue_delayed_work(system_nrt_wq, delayed_work, DRM_OUTPUT_POLL_PERIOD); |
984 | schedule_delayed_work(delayed_work, DRM_OUTPUT_POLL_PERIOD); |
Line 917... | Line 985... | ||
917 | } |
985 | } |
918 | 986 | ||
919 | void drm_kms_helper_poll_disable(struct drm_device *dev) |
987 | void drm_kms_helper_poll_disable(struct drm_device *dev) |
Line 936... | Line 1004... | ||
936 | if (connector->polled) |
1004 | if (connector->polled) |
937 | poll = true; |
1005 | poll = true; |
938 | } |
1006 | } |
Line 939... | Line 1007... | ||
939 | 1007 | ||
940 | if (poll) |
1008 | if (poll) |
941 | queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); |
1009 | schedule_delayed_work(&dev->mode_config.output_poll_work, DRM_OUTPUT_POLL_PERIOD); |
942 | } |
1010 | } |
Line 943... | Line 1011... | ||
943 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
1011 | EXPORT_SYMBOL(drm_kms_helper_poll_enable); |
944 | 1012 | ||
Line 963... | Line 1031... | ||
963 | return; |
1031 | return; |
Line 964... | Line 1032... | ||
964 | 1032 | ||
965 | /* kill timer and schedule immediate execution, this doesn't block */ |
1033 | /* kill timer and schedule immediate execution, this doesn't block */ |
966 | cancel_delayed_work(&dev->mode_config.output_poll_work); |
1034 | cancel_delayed_work(&dev->mode_config.output_poll_work); |
967 | if (drm_kms_helper_poll) |
1035 | if (drm_kms_helper_poll) |
968 | queue_delayed_work(system_nrt_wq, &dev->mode_config.output_poll_work, 0); |
1036 | schedule_delayed_work(&dev->mode_config.output_poll_work, 0); |
969 | } |
1037 | } |
Line 970... | Line -... | ||
970 | EXPORT_SYMBOL(drm_helper_hpd_irq_event); |
- | |
971 | 1038 | EXPORT_SYMBOL(drm_helper_hpd_irq_event); |