diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2014-03-07 11:57:55 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-03-08 05:31:58 -0500 |
commit | 484b41dd70a9fbea894632d8926bbb93f05021c7 (patch) | |
tree | 3ea2683f50180ebe0bca779fda0d60d19d846aa9 /drivers/gpu/drm/i915/intel_display.c | |
parent | d978ef14456a38034f6c0e94a794129501f89200 (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.c | 145 |
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 | ||
2071 | static void intel_alloc_plane_obj(struct intel_crtc *crtc, | 2071 | static 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 | ||
2108 | out_unref_obj: | 2107 | out_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 | |||
2113 | static 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 | ||
2113 | static int i9xx_update_plane(struct drm_crtc *crtc, struct drm_framebuffer *fb, | 2151 | static 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 | ||
11681 | void intel_modeset_gem_init(struct drm_device *dev) | 11715 | void 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 | ||
11688 | void intel_connector_unregister(struct intel_connector *intel_connector) | 11745 | void intel_connector_unregister(struct intel_connector *intel_connector) |