Rev 5367 | Rev 6088 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5367 | Rev 6084 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | #include |
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
30 | #include |
30 | #include |
31 | #include |
31 | #include |
32 | //#include |
32 | #include |
33 | //#include |
33 | //#include |
34 | #include |
34 | #include |
35 | #include |
35 | #include |
36 | #include |
36 | #include |
37 | //#include |
37 | //#include |
Line 42... | Line 42... | ||
42 | #include |
42 | #include |
43 | #include "intel_drv.h" |
43 | #include "intel_drv.h" |
44 | #include |
44 | #include |
45 | #include "i915_drv.h" |
45 | #include "i915_drv.h" |
Line 46... | Line -... | ||
46 | - | ||
47 | 46 | ||
48 | struct fb_info *framebuffer_alloc(size_t size, struct device *dev) |
47 | struct fb_info *framebuffer_alloc(size_t size, struct device *dev) |
49 | { |
48 | { |
50 | #define BYTES_PER_LONG (BITS_PER_LONG/8) |
49 | #define BYTES_PER_LONG (BITS_PER_LONG/8) |
51 | #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) |
50 | #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) |
Line 79... | Line 78... | ||
79 | int ret; |
78 | int ret; |
Line 80... | Line 79... | ||
80 | 79 | ||
Line 81... | Line 80... | ||
81 | ret = drm_fb_helper_set_par(info); |
80 | ret = drm_fb_helper_set_par(info); |
82 | - | ||
83 | if (ret == 0) { |
- | |
84 | /* |
- | |
85 | * FIXME: fbdev presumes that all callbacks also work from |
- | |
86 | * atomic contexts and relies on that for emergency oops |
- | |
87 | * printing. KMS totally doesn't do that and the locking here is |
- | |
88 | * by far not the only place this goes wrong. Ignore this for |
- | |
89 | * now until we solve this for real. |
81 | |
90 | */ |
82 | if (ret == 0) { |
- | 83 | mutex_lock(&fb_helper->dev->struct_mutex); |
|
- | 84 | intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT); |
|
- | 85 | mutex_unlock(&fb_helper->dev->struct_mutex); |
|
- | 86 | } |
|
- | 87 | ||
- | 88 | return ret; |
|
- | 89 | } |
|
- | 90 | ||
- | 91 | static int intel_fbdev_blank(int blank, struct fb_info *info) |
|
- | 92 | { |
|
- | 93 | struct drm_fb_helper *fb_helper = info->par; |
|
- | 94 | struct intel_fbdev *ifbdev = |
|
- | 95 | container_of(fb_helper, struct intel_fbdev, helper); |
|
- | 96 | int ret; |
|
- | 97 | ||
- | 98 | ret = drm_fb_helper_blank(blank, info); |
|
- | 99 | ||
- | 100 | if (ret == 0) { |
|
- | 101 | mutex_lock(&fb_helper->dev->struct_mutex); |
|
- | 102 | intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT); |
|
- | 103 | mutex_unlock(&fb_helper->dev->struct_mutex); |
|
91 | mutex_lock(&fb_helper->dev->struct_mutex); |
104 | } |
- | 105 | ||
- | 106 | return ret; |
|
- | 107 | } |
|
- | 108 | ||
- | 109 | static int intel_fbdev_pan_display(struct fb_var_screeninfo *var, |
|
- | 110 | struct fb_info *info) |
|
- | 111 | { |
|
- | 112 | struct drm_fb_helper *fb_helper = info->par; |
|
- | 113 | struct intel_fbdev *ifbdev = |
|
- | 114 | container_of(fb_helper, struct intel_fbdev, helper); |
|
- | 115 | ||
- | 116 | int ret; |
|
- | 117 | ret = drm_fb_helper_pan_display(var, info); |
|
- | 118 | ||
- | 119 | if (ret == 0) { |
|
92 | ret = i915_gem_object_set_to_gtt_domain(ifbdev->fb->obj, |
120 | mutex_lock(&fb_helper->dev->struct_mutex); |
93 | true); |
121 | intel_fb_obj_invalidate(ifbdev->fb->obj, ORIGIN_GTT); |
Line 94... | Line 122... | ||
94 | mutex_unlock(&fb_helper->dev->struct_mutex); |
122 | mutex_unlock(&fb_helper->dev->struct_mutex); |
95 | } |
123 | } |
Line 102... | Line 130... | ||
102 | .fb_check_var = drm_fb_helper_check_var, |
130 | .fb_check_var = drm_fb_helper_check_var, |
103 | .fb_set_par = intel_fbdev_set_par, |
131 | .fb_set_par = intel_fbdev_set_par, |
104 | // .fb_fillrect = cfb_fillrect, |
132 | // .fb_fillrect = cfb_fillrect, |
105 | // .fb_copyarea = cfb_copyarea, |
133 | // .fb_copyarea = cfb_copyarea, |
106 | // .fb_imageblit = cfb_imageblit, |
134 | // .fb_imageblit = cfb_imageblit, |
107 | // .fb_pan_display = drm_fb_helper_pan_display, |
135 | .fb_pan_display = intel_fbdev_pan_display, |
108 | .fb_blank = drm_fb_helper_blank, |
136 | .fb_blank = intel_fbdev_blank, |
109 | // .fb_setcmap = drm_fb_helper_setcmap, |
137 | // .fb_setcmap = drm_fb_helper_setcmap, |
110 | // .fb_debug_enter = drm_fb_helper_debug_enter, |
138 | // .fb_debug_enter = drm_fb_helper_debug_enter, |
111 | // .fb_debug_leave = drm_fb_helper_debug_leave, |
139 | // .fb_debug_leave = drm_fb_helper_debug_leave, |
112 | }; |
140 | }; |
Line 116... | Line 144... | ||
116 | { |
144 | { |
117 | struct intel_fbdev *ifbdev = |
145 | struct intel_fbdev *ifbdev = |
118 | container_of(helper, struct intel_fbdev, helper); |
146 | container_of(helper, struct intel_fbdev, helper); |
119 | struct drm_framebuffer *fb; |
147 | struct drm_framebuffer *fb; |
120 | struct drm_device *dev = helper->dev; |
148 | struct drm_device *dev = helper->dev; |
- | 149 | struct drm_i915_private *dev_priv = to_i915(dev); |
|
121 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
150 | struct drm_mode_fb_cmd2 mode_cmd = {}; |
122 | struct drm_i915_gem_object *obj; |
151 | struct drm_i915_gem_object *obj = NULL; |
123 | int size, ret; |
152 | int size, ret; |
Line 124... | Line 153... | ||
124 | 153 | ||
125 | /* we don't do packed 24bpp */ |
154 | /* we don't do packed 24bpp */ |
126 | if (sizes->surface_bpp == 24) |
155 | if (sizes->surface_bpp == 24) |
Line 133... | Line 162... | ||
133 | DIV_ROUND_UP(sizes->surface_bpp, 8), 64); |
162 | DIV_ROUND_UP(sizes->surface_bpp, 8), 64); |
134 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
163 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
135 | sizes->surface_depth); |
164 | sizes->surface_depth); |
Line 136... | Line 165... | ||
136 | 165 | ||
137 | size = mode_cmd.pitches[0] * mode_cmd.height; |
166 | size = mode_cmd.pitches[0] * mode_cmd.height; |
138 | size = ALIGN(size, PAGE_SIZE); |
167 | size = PAGE_ALIGN(size); |
139 | obj = main_fb_obj; |
168 | obj = main_fb_obj; |
140 | obj->stride = mode_cmd.pitches[0]; |
169 | obj->map_and_fenceable=true; |
141 | if (!obj) { |
170 | if (!obj) { |
142 | DRM_ERROR("failed to allocate framebuffer\n"); |
171 | DRM_ERROR("failed to allocate framebuffer\n"); |
143 | ret = -ENOMEM; |
172 | ret = -ENOMEM; |
144 | goto out; |
173 | goto out; |
Line 149... | Line 178... | ||
149 | ret = PTR_ERR(fb); |
178 | ret = PTR_ERR(fb); |
150 | goto out_unref; |
179 | goto out_unref; |
151 | } |
180 | } |
Line 152... | Line 181... | ||
152 | 181 | ||
153 | /* Flush everything out, we'll be doing GTT only from now on */ |
182 | /* Flush everything out, we'll be doing GTT only from now on */ |
154 | ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL); |
183 | ret = intel_pin_and_fence_fb_obj(NULL, fb, NULL, NULL, NULL); |
155 | if (ret) { |
184 | if (ret) { |
156 | DRM_ERROR("failed to pin obj: %d\n", ret); |
185 | DRM_ERROR("failed to pin obj: %d\n", ret); |
157 | goto out_fb; |
186 | goto out_fb; |
Line 212... | Line 241... | ||
212 | } |
241 | } |
Line 213... | Line 242... | ||
213 | 242 | ||
214 | obj = intel_fb->obj; |
243 | obj = intel_fb->obj; |
Line 215... | Line 244... | ||
215 | size = obj->base.size; |
244 | size = obj->base.size; |
216 | 245 | ||
217 | info = framebuffer_alloc(0, &dev->pdev->dev); |
246 | info = drm_fb_helper_alloc_fbi(helper); |
218 | if (!info) { |
247 | if (IS_ERR(info)) { |
219 | ret = -ENOMEM; |
248 | ret = PTR_ERR(info); |
Line 220... | Line 249... | ||
220 | goto out_unpin; |
249 | goto out_unpin; |
Line 221... | Line 250... | ||
221 | } |
250 | } |
Line -... | Line 251... | ||
- | 251 | ||
- | 252 | info->par = helper; |
|
- | 253 | ||
222 | 254 | fb = &ifbdev->fb->base; |
|
223 | info->par = helper; |
- | |
Line 224... | Line 255... | ||
224 | 255 | ||
Line 225... | Line 256... | ||
225 | fb = &ifbdev->fb->base; |
256 | if(main_framebuffer == NULL) |
226 | 257 | main_framebuffer = fb; |
|
Line 227... | Line 258... | ||
227 | ifbdev->helper.fb = fb; |
258 | |
228 | ifbdev->helper.fbdev = info; |
- | |
229 | - | ||
230 | strcpy(info->fix.id, "inteldrmfb"); |
- | |
231 | - | ||
232 | info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT; |
- | |
233 | info->fbops = &intelfb_ops; |
259 | ifbdev->helper.fb = fb; |
234 | 260 | ||
Line 235... | Line 261... | ||
235 | /* setup aperture base/size for vesafb takeover */ |
261 | strcpy(info->fix.id, "inteldrmfb"); |
Line 251... | Line 277... | ||
251 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); |
277 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); |
252 | drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); |
278 | drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); |
Line 253... | Line 279... | ||
253 | 279 | ||
Line 254... | Line 280... | ||
254 | /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ |
280 | /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ |
255 | 281 | ||
256 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08lx, bo %p\n", |
282 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08llx, bo %p\n", |
Line 257... | Line 283... | ||
257 | fb->width, fb->height, |
283 | fb->width, fb->height, |
258 | i915_gem_obj_ggtt_offset(obj), obj); |
284 | i915_gem_obj_ggtt_offset(obj), obj); |
Line -... | Line 285... | ||
- | 285 | ||
- | 286 | mutex_unlock(&dev->struct_mutex); |
|
259 | 287 | return 0; |
|
260 | mutex_unlock(&dev->struct_mutex); |
288 | |
261 | return 0; |
289 | out_destroy_fbi: |
262 | 290 | drm_fb_helper_release_fbi(helper); |
|
263 | out_unpin: |
291 | out_unpin: |
Line 438... | Line 466... | ||
438 | if (!modes[i]) { |
466 | if (!modes[i]) { |
439 | /* |
467 | /* |
440 | * IMPORTANT: We want to use the adjusted mode (i.e. |
468 | * IMPORTANT: We want to use the adjusted mode (i.e. |
441 | * after the panel fitter upscaling) as the initial |
469 | * after the panel fitter upscaling) as the initial |
442 | * config, not the input mode, which is what crtc->mode |
470 | * config, not the input mode, which is what crtc->mode |
443 | * usually contains. But since our current fastboot |
471 | * usually contains. But since our current |
444 | * code puts a mode derived from the post-pfit timings |
472 | * code puts a mode derived from the post-pfit timings |
445 | * into crtc->mode this works out correctly. We don't |
473 | * into crtc->mode this works out correctly. |
446 | * use hwmode anywhere right now, so use it for this |
- | |
447 | * since the fb helper layer wants a pointer to |
- | |
448 | * something we own. |
- | |
449 | */ |
474 | */ |
450 | DRM_DEBUG_KMS("looking for current mode on connector %s\n", |
475 | DRM_DEBUG_KMS("looking for current mode on connector %s\n", |
451 | connector->name); |
476 | connector->name); |
452 | intel_mode_from_pipe_config(&encoder->crtc->hwmode, |
- | |
453 | &to_intel_crtc(encoder->crtc)->config); |
- | |
454 | modes[i] = &encoder->crtc->hwmode; |
477 | modes[i] = &encoder->crtc->mode; |
455 | } |
478 | } |
456 | crtcs[i] = new_crtc; |
479 | crtcs[i] = new_crtc; |
Line 457... | Line 480... | ||
457 | 480 | ||
458 | DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n", |
481 | DRM_DEBUG_KMS("connector %s on pipe %c [CRTC:%d]: %dx%d%s\n", |
Line 516... | Line 539... | ||
516 | struct intel_fbdev *ifbdev) |
539 | struct intel_fbdev *ifbdev) |
517 | { |
540 | { |
518 | struct intel_framebuffer *fb = NULL; |
541 | struct intel_framebuffer *fb = NULL; |
519 | struct drm_crtc *crtc; |
542 | struct drm_crtc *crtc; |
520 | struct intel_crtc *intel_crtc; |
543 | struct intel_crtc *intel_crtc; |
521 | struct intel_plane_config *plane_config = NULL; |
- | |
522 | unsigned int max_size = 0; |
544 | unsigned int max_size = 0; |
Line 523... | Line -... | ||
523 | - | ||
524 | if (!i915.fastboot) |
- | |
525 | return false; |
- | |
526 | 545 | ||
527 | /* Find the largest fb */ |
546 | /* Find the largest fb */ |
- | 547 | for_each_crtc(dev, crtc) { |
|
- | 548 | struct drm_i915_gem_object *obj = |
|
528 | for_each_crtc(dev, crtc) { |
549 | intel_fb_obj(crtc->primary->state->fb); |
Line 529... | Line 550... | ||
529 | intel_crtc = to_intel_crtc(crtc); |
550 | intel_crtc = to_intel_crtc(crtc); |
530 | 551 | ||
531 | if (!intel_crtc->active || !crtc->primary->fb) { |
552 | if (!crtc->state->active || !obj) { |
532 | DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", |
553 | DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", |
533 | pipe_name(intel_crtc->pipe)); |
554 | pipe_name(intel_crtc->pipe)); |
Line 534... | Line 555... | ||
534 | continue; |
555 | continue; |
535 | } |
556 | } |
536 | 557 | ||
537 | if (intel_crtc->plane_config.size > max_size) { |
- | |
538 | DRM_DEBUG_KMS("found possible fb from plane %c\n", |
558 | if (obj->base.size > max_size) { |
539 | pipe_name(intel_crtc->pipe)); |
559 | DRM_DEBUG_KMS("found possible fb from plane %c\n", |
540 | plane_config = &intel_crtc->plane_config; |
560 | pipe_name(intel_crtc->pipe)); |
541 | fb = to_intel_framebuffer(crtc->primary->fb); |
561 | fb = to_intel_framebuffer(crtc->primary->state->fb); |
Line 542... | Line 562... | ||
542 | max_size = plane_config->size; |
562 | max_size = obj->base.size; |
543 | } |
563 | } |
Line 552... | Line 572... | ||
552 | for_each_crtc(dev, crtc) { |
572 | for_each_crtc(dev, crtc) { |
553 | unsigned int cur_size; |
573 | unsigned int cur_size; |
Line 554... | Line 574... | ||
554 | 574 | ||
Line 555... | Line 575... | ||
555 | intel_crtc = to_intel_crtc(crtc); |
575 | intel_crtc = to_intel_crtc(crtc); |
556 | 576 | ||
557 | if (!intel_crtc->active) { |
577 | if (!crtc->state->active) { |
558 | DRM_DEBUG_KMS("pipe %c not active, skipping\n", |
578 | DRM_DEBUG_KMS("pipe %c not active, skipping\n", |
559 | pipe_name(intel_crtc->pipe)); |
579 | pipe_name(intel_crtc->pipe)); |
Line 566... | Line 586... | ||
566 | /* |
586 | /* |
567 | * See if the plane fb we found above will fit on this |
587 | * See if the plane fb we found above will fit on this |
568 | * pipe. Note we need to use the selected fb's pitch and bpp |
588 | * pipe. Note we need to use the selected fb's pitch and bpp |
569 | * rather than the current pipe's, since they differ. |
589 | * rather than the current pipe's, since they differ. |
570 | */ |
590 | */ |
571 | cur_size = intel_crtc->config.adjusted_mode.crtc_hdisplay; |
591 | cur_size = intel_crtc->config->base.adjusted_mode.crtc_hdisplay; |
572 | cur_size = cur_size * fb->base.bits_per_pixel / 8; |
592 | cur_size = cur_size * fb->base.bits_per_pixel / 8; |
573 | if (fb->base.pitches[0] < cur_size) { |
593 | if (fb->base.pitches[0] < cur_size) { |
574 | DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n", |
594 | DRM_DEBUG_KMS("fb not wide enough for plane %c (%d vs %d)\n", |
575 | pipe_name(intel_crtc->pipe), |
595 | pipe_name(intel_crtc->pipe), |
576 | cur_size, fb->base.pitches[0]); |
596 | cur_size, fb->base.pitches[0]); |
577 | plane_config = NULL; |
- | |
578 | fb = NULL; |
597 | fb = NULL; |
579 | break; |
598 | break; |
580 | } |
599 | } |
Line 581... | Line 600... | ||
581 | 600 | ||
582 | cur_size = intel_crtc->config.adjusted_mode.crtc_vdisplay; |
601 | cur_size = intel_crtc->config->base.adjusted_mode.crtc_vdisplay; |
- | 602 | cur_size = intel_fb_align_height(dev, cur_size, |
|
- | 603 | fb->base.pixel_format, |
|
583 | cur_size = ALIGN(cur_size, plane_config->tiled ? (IS_GEN2(dev) ? 16 : 8) : 1); |
604 | fb->base.modifier[0]); |
584 | cur_size *= fb->base.pitches[0]; |
605 | cur_size *= fb->base.pitches[0]; |
585 | DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n", |
606 | DRM_DEBUG_KMS("pipe %c area: %dx%d, bpp: %d, size: %d\n", |
586 | pipe_name(intel_crtc->pipe), |
607 | pipe_name(intel_crtc->pipe), |
587 | intel_crtc->config.adjusted_mode.crtc_hdisplay, |
608 | intel_crtc->config->base.adjusted_mode.crtc_hdisplay, |
588 | intel_crtc->config.adjusted_mode.crtc_vdisplay, |
609 | intel_crtc->config->base.adjusted_mode.crtc_vdisplay, |
589 | fb->base.bits_per_pixel, |
610 | fb->base.bits_per_pixel, |
Line 590... | Line 611... | ||
590 | cur_size); |
611 | cur_size); |
591 | 612 | ||
592 | if (cur_size > max_size) { |
613 | if (cur_size > max_size) { |
593 | DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n", |
614 | DRM_DEBUG_KMS("fb not big enough for plane %c (%d vs %d)\n", |
594 | pipe_name(intel_crtc->pipe), |
- | |
595 | cur_size, max_size); |
615 | pipe_name(intel_crtc->pipe), |
596 | plane_config = NULL; |
616 | cur_size, max_size); |
597 | fb = NULL; |
617 | fb = NULL; |
Line 598... | Line 618... | ||
598 | break; |
618 | break; |
Line 615... | Line 635... | ||
615 | 635 | ||
616 | /* Final pass to check if any active pipes don't have fbs */ |
636 | /* Final pass to check if any active pipes don't have fbs */ |
617 | for_each_crtc(dev, crtc) { |
637 | for_each_crtc(dev, crtc) { |
Line 618... | Line 638... | ||
618 | intel_crtc = to_intel_crtc(crtc); |
638 | intel_crtc = to_intel_crtc(crtc); |
619 | 639 | ||
Line 620... | Line 640... | ||
620 | if (!intel_crtc->active) |
640 | if (!crtc->state->active) |
621 | continue; |
641 | continue; |
622 | 642 | ||
Line 657... | Line 677... | ||
657 | if (ret) { |
677 | if (ret) { |
658 | kfree(ifbdev); |
678 | kfree(ifbdev); |
659 | return ret; |
679 | return ret; |
660 | } |
680 | } |
Line -... | Line 681... | ||
- | 681 | ||
- | 682 | ifbdev->helper.atomic = true; |
|
661 | 683 | ||
662 | dev_priv->fbdev = ifbdev; |
684 | dev_priv->fbdev = ifbdev; |
Line 663... | Line 685... | ||
663 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
685 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); |
664 | 686 |