aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_display.c
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 /drivers/gpu/drm/i915/intel_display.c
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>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c145
1 files changed, 101 insertions, 44 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)