aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2014-03-07 11:57:55 -0500
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-03-08 05:31:58 -0500
commit484b41dd70a9fbea894632d8926bbb93f05021c7 (patch)
tree3ea2683f50180ebe0bca779fda0d60d19d846aa9
parentd978ef14456a38034f6c0e94a794129501f89200 (diff)
drm/i915: remove early fb allocation dependency on CONFIG_FB v2
By stuffing the fb allocation into the crtc, we get mode set lifetime refcounting for free, but have to handle the initial pin & fence slightly differently. It also means we can move the shared fb handling into the core rather than leaving it out in the fbdev code. v2: null out crtc->fb on error (Daniel) take fbdev fb ref and remove unused error path (Daniel) Requested-by: Daniel Vetter <daniel@ffwll.ch> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r--drivers/gpu/drm/i915/intel_display.c145
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_fbdev.c38
3 files changed, 105 insertions, 79 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index d3c29116711f..8710496bab4c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2068,7 +2068,7 @@ int intel_format_to_fourcc(int format)
2068 } 2068 }
2069} 2069}
2070 2070
2071static void intel_alloc_plane_obj(struct intel_crtc *crtc, 2071static bool intel_alloc_plane_obj(struct intel_crtc *crtc,
2072 struct intel_plane_config *plane_config) 2072 struct intel_plane_config *plane_config)
2073{ 2073{
2074 struct drm_device *dev = crtc->base.dev; 2074 struct drm_device *dev = crtc->base.dev;
@@ -2076,38 +2076,76 @@ static void intel_alloc_plane_obj(struct intel_crtc *crtc,
2076 struct drm_mode_fb_cmd2 mode_cmd = { 0 }; 2076 struct drm_mode_fb_cmd2 mode_cmd = { 0 };
2077 u32 base = plane_config->base; 2077 u32 base = plane_config->base;
2078 2078
2079 if (!plane_config->fb)
2080 return;
2081
2082 obj = i915_gem_object_create_stolen_for_preallocated(dev, base, base, 2079 obj = i915_gem_object_create_stolen_for_preallocated(dev, base, base,
2083 plane_config->size); 2080 plane_config->size);
2084 if (!obj) 2081 if (!obj)
2085 return; 2082 return false;
2086 2083
2087 if (plane_config->tiled) { 2084 if (plane_config->tiled) {
2088 obj->tiling_mode = I915_TILING_X; 2085 obj->tiling_mode = I915_TILING_X;
2089 obj->stride = plane_config->fb->base.pitches[0]; 2086 obj->stride = crtc->base.fb->pitches[0];
2090 } 2087 }
2091 2088
2092 mode_cmd.pixel_format = plane_config->fb->base.pixel_format; 2089 mode_cmd.pixel_format = crtc->base.fb->pixel_format;
2093 mode_cmd.width = plane_config->fb->base.width; 2090 mode_cmd.width = crtc->base.fb->width;
2094 mode_cmd.height = plane_config->fb->base.height; 2091 mode_cmd.height = crtc->base.fb->height;
2095 mode_cmd.pitches[0] = plane_config->fb->base.pitches[0]; 2092 mode_cmd.pitches[0] = crtc->base.fb->pitches[0];
2096 2093
2097 mutex_lock(&dev->struct_mutex); 2094 mutex_lock(&dev->struct_mutex);
2098 2095
2099 if (intel_framebuffer_init(dev, plane_config->fb, &mode_cmd, obj)) { 2096 if (intel_framebuffer_init(dev, to_intel_framebuffer(crtc->base.fb),
2097 &mode_cmd, obj)) {
2100 DRM_DEBUG_KMS("intel fb init failed\n"); 2098 DRM_DEBUG_KMS("intel fb init failed\n");
2101 goto out_unref_obj; 2099 goto out_unref_obj;
2102 } 2100 }
2103 2101
2104 mutex_unlock(&dev->struct_mutex); 2102 mutex_unlock(&dev->struct_mutex);
2105 DRM_DEBUG_KMS("plane fb obj %p\n", plane_config->fb->obj); 2103
2106 return; 2104 DRM_DEBUG_KMS("plane fb obj %p\n", obj);
2105 return true;
2107 2106
2108out_unref_obj: 2107out_unref_obj:
2109 drm_gem_object_unreference(&obj->base); 2108 drm_gem_object_unreference(&obj->base);
2110 mutex_unlock(&dev->struct_mutex); 2109 mutex_unlock(&dev->struct_mutex);
2110 return false;
2111}
2112
2113static void intel_find_plane_obj(struct intel_crtc *intel_crtc,
2114 struct intel_plane_config *plane_config)
2115{
2116 struct drm_device *dev = intel_crtc->base.dev;
2117 struct drm_crtc *c;
2118 struct intel_crtc *i;
2119 struct intel_framebuffer *fb;
2120
2121 if (!intel_crtc->base.fb)
2122 return;
2123
2124 if (intel_alloc_plane_obj(intel_crtc, plane_config))
2125 return;
2126
2127 kfree(intel_crtc->base.fb);
2128
2129 /*
2130 * Failed to alloc the obj, check to see if we should share
2131 * an fb with another CRTC instead
2132 */
2133 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
2134 i = to_intel_crtc(c);
2135
2136 if (c == &intel_crtc->base)
2137 continue;
2138
2139 if (!i->active || !c->fb)
2140 continue;
2141
2142 fb = to_intel_framebuffer(c->fb);
2143 if (i915_gem_obj_ggtt_offset(fb->obj) == plane_config->base) {
2144 drm_framebuffer_reference(c->fb);
2145 intel_crtc->base.fb = c->fb;
2146 break;
2147 }
2148 }
2111} 2149}
2112 2150
2113static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, 2151static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb,
@@ -5678,8 +5716,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5678 int fourcc, pixel_format; 5716 int fourcc, pixel_format;
5679 int aligned_height; 5717 int aligned_height;
5680 5718
5681 plane_config->fb = kzalloc(sizeof(*plane_config->fb), GFP_KERNEL); 5719 crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
5682 if (!plane_config->fb) { 5720 if (!crtc->base.fb) {
5683 DRM_DEBUG_KMS("failed to alloc fb\n"); 5721 DRM_DEBUG_KMS("failed to alloc fb\n");
5684 return; 5722 return;
5685 } 5723 }
@@ -5692,8 +5730,8 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5692 5730
5693 pixel_format = val & DISPPLANE_PIXFORMAT_MASK; 5731 pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
5694 fourcc = intel_format_to_fourcc(pixel_format); 5732 fourcc = intel_format_to_fourcc(pixel_format);
5695 plane_config->fb->base.pixel_format = fourcc; 5733 crtc->base.fb->pixel_format = fourcc;
5696 plane_config->fb->base.bits_per_pixel = 5734 crtc->base.fb->bits_per_pixel =
5697 drm_format_plane_cpp(fourcc, 0) * 8; 5735 drm_format_plane_cpp(fourcc, 0) * 8;
5698 5736
5699 if (INTEL_INFO(dev)->gen >= 4) { 5737 if (INTEL_INFO(dev)->gen >= 4) {
@@ -5708,23 +5746,23 @@ static void i9xx_get_plane_config(struct intel_crtc *crtc,
5708 plane_config->base = base; 5746 plane_config->base = base;
5709 5747
5710 val = I915_READ(PIPESRC(pipe)); 5748 val = I915_READ(PIPESRC(pipe));
5711 plane_config->fb->base.width = ((val >> 16) & 0xfff) + 1; 5749 crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
5712 plane_config->fb->base.height = ((val >> 0) & 0xfff) + 1; 5750 crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
5713 5751
5714 val = I915_READ(DSPSTRIDE(pipe)); 5752 val = I915_READ(DSPSTRIDE(pipe));
5715 plane_config->fb->base.pitches[0] = val & 0xffffff80; 5753 crtc->base.fb->pitches[0] = val & 0xffffff80;
5716 5754
5717 aligned_height = intel_align_height(dev, plane_config->fb->base.height, 5755 aligned_height = intel_align_height(dev, crtc->base.fb->height,
5718 plane_config->tiled); 5756 plane_config->tiled);
5719 5757
5720 plane_config->size = ALIGN(plane_config->fb->base.pitches[0] * 5758 plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
5721 aligned_height, PAGE_SIZE); 5759 aligned_height, PAGE_SIZE);
5722 5760
5723 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 5761 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
5724 pipe, plane, plane_config->fb->base.width, 5762 pipe, plane, crtc->base.fb->width,
5725 plane_config->fb->base.height, 5763 crtc->base.fb->height,
5726 plane_config->fb->base.bits_per_pixel, base, 5764 crtc->base.fb->bits_per_pixel, base,
5727 plane_config->fb->base.pitches[0], 5765 crtc->base.fb->pitches[0],
5728 plane_config->size); 5766 plane_config->size);
5729 5767
5730} 5768}
@@ -6686,8 +6724,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6686 int fourcc, pixel_format; 6724 int fourcc, pixel_format;
6687 int aligned_height; 6725 int aligned_height;
6688 6726
6689 plane_config->fb = kzalloc(sizeof(*plane_config->fb), GFP_KERNEL); 6727 crtc->base.fb = kzalloc(sizeof(struct intel_framebuffer), GFP_KERNEL);
6690 if (!plane_config->fb) { 6728 if (!crtc->base.fb) {
6691 DRM_DEBUG_KMS("failed to alloc fb\n"); 6729 DRM_DEBUG_KMS("failed to alloc fb\n");
6692 return; 6730 return;
6693 } 6731 }
@@ -6700,8 +6738,8 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6700 6738
6701 pixel_format = val & DISPPLANE_PIXFORMAT_MASK; 6739 pixel_format = val & DISPPLANE_PIXFORMAT_MASK;
6702 fourcc = intel_format_to_fourcc(pixel_format); 6740 fourcc = intel_format_to_fourcc(pixel_format);
6703 plane_config->fb->base.pixel_format = fourcc; 6741 crtc->base.fb->pixel_format = fourcc;
6704 plane_config->fb->base.bits_per_pixel = 6742 crtc->base.fb->bits_per_pixel =
6705 drm_format_plane_cpp(fourcc, 0) * 8; 6743 drm_format_plane_cpp(fourcc, 0) * 8;
6706 6744
6707 base = I915_READ(DSPSURF(plane)) & 0xfffff000; 6745 base = I915_READ(DSPSURF(plane)) & 0xfffff000;
@@ -6716,23 +6754,23 @@ static void ironlake_get_plane_config(struct intel_crtc *crtc,
6716 plane_config->base = base; 6754 plane_config->base = base;
6717 6755
6718 val = I915_READ(PIPESRC(pipe)); 6756 val = I915_READ(PIPESRC(pipe));
6719 plane_config->fb->base.width = ((val >> 16) & 0xfff) + 1; 6757 crtc->base.fb->width = ((val >> 16) & 0xfff) + 1;
6720 plane_config->fb->base.height = ((val >> 0) & 0xfff) + 1; 6758 crtc->base.fb->height = ((val >> 0) & 0xfff) + 1;
6721 6759
6722 val = I915_READ(DSPSTRIDE(pipe)); 6760 val = I915_READ(DSPSTRIDE(pipe));
6723 plane_config->fb->base.pitches[0] = val & 0xffffff80; 6761 crtc->base.fb->pitches[0] = val & 0xffffff80;
6724 6762
6725 aligned_height = intel_align_height(dev, plane_config->fb->base.height, 6763 aligned_height = intel_align_height(dev, crtc->base.fb->height,
6726 plane_config->tiled); 6764 plane_config->tiled);
6727 6765
6728 plane_config->size = ALIGN(plane_config->fb->base.pitches[0] * 6766 plane_config->size = ALIGN(crtc->base.fb->pitches[0] *
6729 aligned_height, PAGE_SIZE); 6767 aligned_height, PAGE_SIZE);
6730 6768
6731 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n", 6769 DRM_DEBUG_KMS("pipe/plane %d/%d with fb: size=%dx%d@%d, offset=%x, pitch %d, size 0x%x\n",
6732 pipe, plane, plane_config->fb->base.width, 6770 pipe, plane, crtc->base.fb->width,
6733 plane_config->fb->base.height, 6771 crtc->base.fb->height,
6734 plane_config->fb->base.bits_per_pixel, base, 6772 crtc->base.fb->bits_per_pixel, base,
6735 plane_config->fb->base.pitches[0], 6773 crtc->base.fb->pitches[0],
6736 plane_config->size); 6774 plane_config->size);
6737} 6775}
6738 6776
@@ -11290,10 +11328,7 @@ void intel_modeset_init(struct drm_device *dev)
11290 if (!crtc->active) 11328 if (!crtc->active)
11291 continue; 11329 continue;
11292 11330
11293#if IS_ENABLED(CONFIG_FB)
11294 /* 11331 /*
11295 * We don't have a good way of freeing the buffer w/o the FB
11296 * layer owning it...
11297 * Note that reserving the BIOS fb up front prevents us 11332 * Note that reserving the BIOS fb up front prevents us
11298 * from stuffing other stolen allocations like the ring 11333 * from stuffing other stolen allocations like the ring
11299 * on top. This prevents some ugliness at boot time, and 11334 * on top. This prevents some ugliness at boot time, and
@@ -11307,9 +11342,8 @@ void intel_modeset_init(struct drm_device *dev)
11307 * If the fb is shared between multiple heads, we'll 11342 * If the fb is shared between multiple heads, we'll
11308 * just get the first one. 11343 * just get the first one.
11309 */ 11344 */
11310 intel_alloc_plane_obj(crtc, &crtc->plane_config); 11345 intel_find_plane_obj(crtc, &crtc->plane_config);
11311 } 11346 }
11312#endif
11313 } 11347 }
11314} 11348}
11315 11349
@@ -11680,9 +11714,32 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
11680 11714
11681void intel_modeset_gem_init(struct drm_device *dev) 11715void intel_modeset_gem_init(struct drm_device *dev)
11682{ 11716{
11717 struct drm_crtc *c;
11718 struct intel_framebuffer *fb;
11719
11683 intel_modeset_init_hw(dev); 11720 intel_modeset_init_hw(dev);
11684 11721
11685 intel_setup_overlay(dev); 11722 intel_setup_overlay(dev);
11723
11724 /*
11725 * Make sure any fbs we allocated at startup are properly
11726 * pinned & fenced. When we do the allocation it's too early
11727 * for this.
11728 */
11729 mutex_lock(&dev->struct_mutex);
11730 list_for_each_entry(c, &dev->mode_config.crtc_list, head) {
11731 if (!c->fb)
11732 continue;
11733
11734 fb = to_intel_framebuffer(c->fb);
11735 if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL)) {
11736 DRM_ERROR("failed to pin boot fb on pipe %d\n",
11737 to_intel_crtc(c)->pipe);
11738 drm_framebuffer_unreference(c->fb);
11739 c->fb = NULL;
11740 }
11741 }
11742 mutex_unlock(&dev->struct_mutex);
11686} 11743}
11687 11744
11688void intel_connector_unregister(struct intel_connector *intel_connector) 11745void intel_connector_unregister(struct intel_connector *intel_connector)
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 75baa64a357d..5360d1628263 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -220,7 +220,6 @@ typedef struct dpll {
220} intel_clock_t; 220} intel_clock_t;
221 221
222struct intel_plane_config { 222struct intel_plane_config {
223 struct intel_framebuffer *fb; /* ends up managed by intel_fbdev.c */
224 bool tiled; 223 bool tiled;
225 int size; 224 int size;
226 u32 base; 225 u32 base;
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index 32a05edc517c..d6d78c86c232 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -481,7 +481,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 481 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
482 intel_crtc = to_intel_crtc(crtc); 482 intel_crtc = to_intel_crtc(crtc);
483 483
484 if (!intel_crtc->active || !intel_crtc->plane_config.fb) { 484 if (!intel_crtc->active || !crtc->fb) {
485 DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n", 485 DRM_DEBUG_KMS("pipe %c not active or no fb, skipping\n",
486 pipe_name(intel_crtc->pipe)); 486 pipe_name(intel_crtc->pipe));
487 continue; 487 continue;
@@ -491,7 +491,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
491 DRM_DEBUG_KMS("found possible fb from plane %c\n", 491 DRM_DEBUG_KMS("found possible fb from plane %c\n",
492 pipe_name(intel_crtc->pipe)); 492 pipe_name(intel_crtc->pipe));
493 plane_config = &intel_crtc->plane_config; 493 plane_config = &intel_crtc->plane_config;
494 fb = plane_config->fb; 494 fb = to_intel_framebuffer(crtc->fb);
495 max_size = plane_config->size; 495 max_size = plane_config->size;
496 } 496 }
497 } 497 }
@@ -543,43 +543,15 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
543 max_size, cur_size); 543 max_size, cur_size);
544 } 544 }
545 545
546 /* Free unused fbs */
547 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
548 struct intel_framebuffer *cur_fb;
549
550 intel_crtc = to_intel_crtc(crtc);
551 cur_fb = intel_crtc->plane_config.fb;
552
553 if (cur_fb && cur_fb != fb)
554 drm_framebuffer_unreference(&cur_fb->base);
555 }
556
557 if (!fb) { 546 if (!fb) {
558 DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n"); 547 DRM_DEBUG_KMS("BIOS fb not suitable for all pipes, not using\n");
559 goto out; 548 goto out;
560 } 549 }
561 550
562 ifbdev->preferred_bpp = plane_config->fb->base.bits_per_pixel; 551 ifbdev->preferred_bpp = fb->base.bits_per_pixel;
563 ifbdev->fb = fb; 552 ifbdev->fb = fb;
564 553
565 /* Assuming a single fb across all pipes here */ 554 drm_framebuffer_reference(&ifbdev->fb->base);
566 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
567 intel_crtc = to_intel_crtc(crtc);
568
569 if (!intel_crtc->active)
570 continue;
571
572 /*
573 * This should only fail on the first one so we don't need
574 * to cleanup any secondary crtc->fbs
575 */
576 if (intel_pin_and_fence_fb_obj(dev, fb->obj, NULL))
577 goto out_unref_obj;
578
579 crtc->fb = &fb->base;
580 drm_gem_object_reference(&fb->obj->base);
581 drm_framebuffer_reference(&fb->base);
582 }
583 555
584 /* Final pass to check if any active pipes don't have fbs */ 556 /* Final pass to check if any active pipes don't have fbs */
585 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 557 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -597,8 +569,6 @@ static bool intel_fbdev_init_bios(struct drm_device *dev,
597 DRM_DEBUG_KMS("using BIOS fb for initial console\n"); 569 DRM_DEBUG_KMS("using BIOS fb for initial console\n");
598 return true; 570 return true;
599 571
600out_unref_obj:
601 drm_framebuffer_unreference(&fb->base);
602out: 572out:
603 573
604 return false; 574 return false;