diff options
author | Dave Airlie <airlied@redhat.com> | 2010-03-30 01:34:13 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-06 20:21:03 -0400 |
commit | 386516744ba45d50f42c6999151cc210cb4f96e4 (patch) | |
tree | 88e3b6aeb83040a8bd512eb7aad087e6c0fcd556 /drivers/gpu/drm/i915 | |
parent | 643acacf02679befd0f98ac3c5fecb805f1c9548 (diff) |
drm/fb: fix fbdev object model + cleanup properly.
The fbdev layer in the kms code should act like a consumer of the kms services and avoid having relying on information being store in the kms core structures in order for it to work.
This patch
a) removes the info pointer/psuedo palette from the core drm_framebuffer structure and moves it to the fbdev helper layer, it also removes the core drm keeping a list of kernel kms fbdevs.
b) migrated all the fb helper functions out of the crtc helper file into the fb helper file.
c) pushed the fb probing/hotplug control into the driver
d) makes the surface sizes into a structure for ease of passing
This changes the intel/radeon/nouveau drivers to use the new helper.
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 37 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 175 |
5 files changed, 110 insertions, 121 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 8bfc0bbf13e6..7c7d229ddde0 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1491,7 +1491,7 @@ static int i915_load_modeset_init(struct drm_device *dev, | |||
1491 | 1491 | ||
1492 | I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); | 1492 | I915_WRITE(INSTPM, (1 << 5) | (1 << 21)); |
1493 | 1493 | ||
1494 | drm_helper_initial_config(dev); | 1494 | intel_fbdev_init(dev); |
1495 | 1495 | ||
1496 | return 0; | 1496 | return 0; |
1497 | 1497 | ||
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 979439cfb827..601f354e467e 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -220,6 +220,8 @@ enum no_fbc_reason { | |||
220 | FBC_NOT_TILED, /* buffer not tiled */ | 220 | FBC_NOT_TILED, /* buffer not tiled */ |
221 | }; | 221 | }; |
222 | 222 | ||
223 | struct intel_kernel_fbdev; | ||
224 | |||
223 | typedef struct drm_i915_private { | 225 | typedef struct drm_i915_private { |
224 | struct drm_device *dev; | 226 | struct drm_device *dev; |
225 | 227 | ||
@@ -627,6 +629,8 @@ typedef struct drm_i915_private { | |||
627 | u8 max_delay; | 629 | u8 max_delay; |
628 | 630 | ||
629 | enum no_fbc_reason no_fbc_reason; | 631 | enum no_fbc_reason no_fbc_reason; |
632 | |||
633 | struct intel_kernel_fbdev *fbdev; | ||
630 | } drm_i915_private_t; | 634 | } drm_i915_private_t; |
631 | 635 | ||
632 | /** driver private structure attached to each drm_gem_object */ | 636 | /** driver private structure attached to each drm_gem_object */ |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9cd6de5f9906..80577b8a368b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4506,10 +4506,6 @@ static void intel_setup_outputs(struct drm_device *dev) | |||
4506 | static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) | 4506 | static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) |
4507 | { | 4507 | { |
4508 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); | 4508 | struct intel_framebuffer *intel_fb = to_intel_framebuffer(fb); |
4509 | struct drm_device *dev = fb->dev; | ||
4510 | |||
4511 | if (fb->fbdev) | ||
4512 | intelfb_remove(dev, fb); | ||
4513 | 4509 | ||
4514 | drm_framebuffer_cleanup(fb); | 4510 | drm_framebuffer_cleanup(fb); |
4515 | drm_gem_object_unreference_unlocked(intel_fb->obj); | 4511 | drm_gem_object_unreference_unlocked(intel_fb->obj); |
@@ -4532,18 +4528,13 @@ static const struct drm_framebuffer_funcs intel_fb_funcs = { | |||
4532 | .create_handle = intel_user_framebuffer_create_handle, | 4528 | .create_handle = intel_user_framebuffer_create_handle, |
4533 | }; | 4529 | }; |
4534 | 4530 | ||
4535 | int intel_framebuffer_create(struct drm_device *dev, | 4531 | int intel_framebuffer_init(struct drm_device *dev, |
4536 | struct drm_mode_fb_cmd *mode_cmd, | 4532 | struct intel_framebuffer *intel_fb, |
4537 | struct drm_framebuffer **fb, | 4533 | struct drm_mode_fb_cmd *mode_cmd, |
4538 | struct drm_gem_object *obj) | 4534 | struct drm_gem_object *obj) |
4539 | { | 4535 | { |
4540 | struct intel_framebuffer *intel_fb; | ||
4541 | int ret; | 4536 | int ret; |
4542 | 4537 | ||
4543 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); | ||
4544 | if (!intel_fb) | ||
4545 | return -ENOMEM; | ||
4546 | |||
4547 | ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); | 4538 | ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); |
4548 | if (ret) { | 4539 | if (ret) { |
4549 | DRM_ERROR("framebuffer init failed %d\n", ret); | 4540 | DRM_ERROR("framebuffer init failed %d\n", ret); |
@@ -4551,40 +4542,40 @@ int intel_framebuffer_create(struct drm_device *dev, | |||
4551 | } | 4542 | } |
4552 | 4543 | ||
4553 | drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); | 4544 | drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); |
4554 | |||
4555 | intel_fb->obj = obj; | 4545 | intel_fb->obj = obj; |
4556 | |||
4557 | *fb = &intel_fb->base; | ||
4558 | |||
4559 | return 0; | 4546 | return 0; |
4560 | } | 4547 | } |
4561 | 4548 | ||
4562 | |||
4563 | static struct drm_framebuffer * | 4549 | static struct drm_framebuffer * |
4564 | intel_user_framebuffer_create(struct drm_device *dev, | 4550 | intel_user_framebuffer_create(struct drm_device *dev, |
4565 | struct drm_file *filp, | 4551 | struct drm_file *filp, |
4566 | struct drm_mode_fb_cmd *mode_cmd) | 4552 | struct drm_mode_fb_cmd *mode_cmd) |
4567 | { | 4553 | { |
4568 | struct drm_gem_object *obj; | 4554 | struct drm_gem_object *obj; |
4569 | struct drm_framebuffer *fb; | 4555 | struct intel_framebuffer *intel_fb; |
4570 | int ret; | 4556 | int ret; |
4571 | 4557 | ||
4572 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); | 4558 | obj = drm_gem_object_lookup(dev, filp, mode_cmd->handle); |
4573 | if (!obj) | 4559 | if (!obj) |
4574 | return NULL; | 4560 | return NULL; |
4575 | 4561 | ||
4576 | ret = intel_framebuffer_create(dev, mode_cmd, &fb, obj); | 4562 | intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL); |
4563 | if (!intel_fb) | ||
4564 | return NULL; | ||
4565 | |||
4566 | ret = intel_framebuffer_init(dev, intel_fb, | ||
4567 | mode_cmd, obj); | ||
4577 | if (ret) { | 4568 | if (ret) { |
4578 | drm_gem_object_unreference_unlocked(obj); | 4569 | drm_gem_object_unreference_unlocked(obj); |
4570 | kfree(intel_fb); | ||
4579 | return NULL; | 4571 | return NULL; |
4580 | } | 4572 | } |
4581 | 4573 | ||
4582 | return fb; | 4574 | return &intel_fb->base; |
4583 | } | 4575 | } |
4584 | 4576 | ||
4585 | static const struct drm_mode_config_funcs intel_mode_funcs = { | 4577 | static const struct drm_mode_config_funcs intel_mode_funcs = { |
4586 | .fb_create = intel_user_framebuffer_create, | 4578 | .fb_create = intel_user_framebuffer_create, |
4587 | .fb_changed = intelfb_probe, | ||
4588 | }; | 4579 | }; |
4589 | 4580 | ||
4590 | static struct drm_gem_object * | 4581 | static struct drm_gem_object * |
@@ -4924,6 +4915,8 @@ void intel_modeset_cleanup(struct drm_device *dev) | |||
4924 | 4915 | ||
4925 | mutex_lock(&dev->struct_mutex); | 4916 | mutex_lock(&dev->struct_mutex); |
4926 | 4917 | ||
4918 | intel_fbdev_fini(dev); | ||
4919 | |||
4927 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 4920 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
4928 | /* Skip inactive CRTCs */ | 4921 | /* Skip inactive CRTCs */ |
4929 | if (!crtc->fb) | 4922 | if (!crtc->fb) |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 3a467ca57857..9ffb9f2c9abd 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -200,9 +200,6 @@ extern void intel_release_load_detect_pipe(struct intel_output *intel_output, | |||
200 | extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); | 200 | extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); |
201 | extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); | 201 | extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); |
202 | extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); | 202 | extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); |
203 | extern int intelfb_probe(struct drm_device *dev); | ||
204 | extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb); | ||
205 | extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc); | ||
206 | extern void intelfb_restore(void); | 203 | extern void intelfb_restore(void); |
207 | extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | 204 | extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, |
208 | u16 blue, int regno); | 205 | u16 blue, int regno); |
@@ -212,10 +209,12 @@ extern void intel_init_clock_gating(struct drm_device *dev); | |||
212 | extern void ironlake_enable_drps(struct drm_device *dev); | 209 | extern void ironlake_enable_drps(struct drm_device *dev); |
213 | extern void ironlake_disable_drps(struct drm_device *dev); | 210 | extern void ironlake_disable_drps(struct drm_device *dev); |
214 | 211 | ||
215 | extern int intel_framebuffer_create(struct drm_device *dev, | 212 | extern int intel_framebuffer_init(struct drm_device *dev, |
216 | struct drm_mode_fb_cmd *mode_cmd, | 213 | struct intel_framebuffer *ifb, |
217 | struct drm_framebuffer **fb, | 214 | struct drm_mode_fb_cmd *mode_cmd, |
218 | struct drm_gem_object *obj); | 215 | struct drm_gem_object *obj); |
216 | extern int intel_fbdev_init(struct drm_device *dev); | ||
217 | extern void intel_fbdev_fini(struct drm_device *dev); | ||
219 | 218 | ||
220 | extern void intel_prepare_page_flip(struct drm_device *dev, int plane); | 219 | extern void intel_prepare_page_flip(struct drm_device *dev, int plane); |
221 | extern void intel_finish_page_flip(struct drm_device *dev, int pipe); | 220 | extern void intel_finish_page_flip(struct drm_device *dev, int pipe); |
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 8cd791dc5b29..b0de9bbde34a 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -45,9 +45,10 @@ | |||
45 | #include "i915_drm.h" | 45 | #include "i915_drm.h" |
46 | #include "i915_drv.h" | 46 | #include "i915_drv.h" |
47 | 47 | ||
48 | struct intelfb_par { | 48 | struct intel_kernel_fbdev { |
49 | struct drm_fb_helper helper; | 49 | struct drm_fb_helper helper; |
50 | struct intel_framebuffer *intel_fb; | 50 | struct intel_framebuffer ifb; |
51 | struct list_head fbdev_list; | ||
51 | struct drm_display_mode *our_mode; | 52 | struct drm_display_mode *our_mode; |
52 | }; | 53 | }; |
53 | 54 | ||
@@ -70,54 +71,12 @@ static struct drm_fb_helper_funcs intel_fb_helper_funcs = { | |||
70 | }; | 71 | }; |
71 | 72 | ||
72 | 73 | ||
73 | /** | 74 | static int intelfb_create(struct drm_device *dev, |
74 | * Currently it is assumed that the old framebuffer is reused. | 75 | struct drm_fb_helper_surface_size *sizes, |
75 | * | 76 | struct intel_kernel_fbdev **ifbdev_p) |
76 | * LOCKING | ||
77 | * caller should hold the mode config lock. | ||
78 | * | ||
79 | */ | ||
80 | int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) | ||
81 | { | 77 | { |
82 | struct fb_info *info; | 78 | struct fb_info *info; |
83 | struct drm_framebuffer *fb; | 79 | struct intel_kernel_fbdev *ifbdev; |
84 | struct drm_display_mode *mode = crtc->desired_mode; | ||
85 | |||
86 | fb = crtc->fb; | ||
87 | if (!fb) | ||
88 | return 1; | ||
89 | |||
90 | info = fb->fbdev; | ||
91 | if (!info) | ||
92 | return 1; | ||
93 | |||
94 | if (!mode) | ||
95 | return 1; | ||
96 | |||
97 | info->var.xres = mode->hdisplay; | ||
98 | info->var.right_margin = mode->hsync_start - mode->hdisplay; | ||
99 | info->var.hsync_len = mode->hsync_end - mode->hsync_start; | ||
100 | info->var.left_margin = mode->htotal - mode->hsync_end; | ||
101 | info->var.yres = mode->vdisplay; | ||
102 | info->var.lower_margin = mode->vsync_start - mode->vdisplay; | ||
103 | info->var.vsync_len = mode->vsync_end - mode->vsync_start; | ||
104 | info->var.upper_margin = mode->vtotal - mode->vsync_end; | ||
105 | info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100; | ||
106 | /* avoid overflow */ | ||
107 | info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | EXPORT_SYMBOL(intelfb_resize); | ||
112 | |||
113 | static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | ||
114 | uint32_t fb_height, uint32_t surface_width, | ||
115 | uint32_t surface_height, | ||
116 | uint32_t surface_depth, uint32_t surface_bpp, | ||
117 | struct drm_framebuffer **fb_p) | ||
118 | { | ||
119 | struct fb_info *info; | ||
120 | struct intelfb_par *par; | ||
121 | struct drm_framebuffer *fb; | 80 | struct drm_framebuffer *fb; |
122 | struct intel_framebuffer *intel_fb; | 81 | struct intel_framebuffer *intel_fb; |
123 | struct drm_mode_fb_cmd mode_cmd; | 82 | struct drm_mode_fb_cmd mode_cmd; |
@@ -127,15 +86,15 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
127 | int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 86 | int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; |
128 | 87 | ||
129 | /* we don't do packed 24bpp */ | 88 | /* we don't do packed 24bpp */ |
130 | if (surface_bpp == 24) | 89 | if (sizes->surface_bpp == 24) |
131 | surface_bpp = 32; | 90 | sizes->surface_bpp = 32; |
132 | 91 | ||
133 | mode_cmd.width = surface_width; | 92 | mode_cmd.width = sizes->surface_width; |
134 | mode_cmd.height = surface_height; | 93 | mode_cmd.height = sizes->surface_height; |
135 | 94 | ||
136 | mode_cmd.bpp = surface_bpp; | 95 | mode_cmd.bpp = sizes->surface_bpp; |
137 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); | 96 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); |
138 | mode_cmd.depth = surface_depth; | 97 | mode_cmd.depth = sizes->surface_depth; |
139 | 98 | ||
140 | size = mode_cmd.pitch * mode_cmd.height; | 99 | size = mode_cmd.pitch * mode_cmd.height; |
141 | size = ALIGN(size, PAGE_SIZE); | 100 | size = ALIGN(size, PAGE_SIZE); |
@@ -158,28 +117,25 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
158 | /* Flush everything out, we'll be doing GTT only from now on */ | 117 | /* Flush everything out, we'll be doing GTT only from now on */ |
159 | i915_gem_object_set_to_gtt_domain(fbo, 1); | 118 | i915_gem_object_set_to_gtt_domain(fbo, 1); |
160 | 119 | ||
161 | ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); | 120 | info = framebuffer_alloc(sizeof(struct intel_kernel_fbdev), device); |
162 | if (ret) { | 121 | if (!info) { |
163 | DRM_ERROR("failed to allocate fb.\n"); | 122 | ret = -ENOMEM; |
164 | goto out_unpin; | 123 | goto out_unpin; |
165 | } | 124 | } |
166 | 125 | ||
167 | list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); | 126 | ifbdev = info->par; |
127 | intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); | ||
168 | 128 | ||
169 | intel_fb = to_intel_framebuffer(fb); | 129 | fb = &ifbdev->ifb.base; |
170 | *fb_p = fb; | ||
171 | 130 | ||
172 | info = framebuffer_alloc(sizeof(struct intelfb_par), device); | 131 | ifbdev->helper.fb = fb; |
173 | if (!info) { | 132 | ifbdev->helper.fbdev = info; |
174 | ret = -ENOMEM; | 133 | ifbdev->helper.funcs = &intel_fb_helper_funcs; |
175 | goto out_unpin; | 134 | ifbdev->helper.dev = dev; |
176 | } | ||
177 | 135 | ||
178 | par = info->par; | 136 | *ifbdev_p = ifbdev; |
179 | 137 | ||
180 | par->helper.funcs = &intel_fb_helper_funcs; | 138 | ret = drm_fb_helper_init_crtc_count(&ifbdev->helper, 2, |
181 | par->helper.dev = dev; | ||
182 | ret = drm_fb_helper_init_crtc_count(&par->helper, 2, | ||
183 | INTELFB_CONN_LIMIT); | 139 | INTELFB_CONN_LIMIT); |
184 | if (ret) | 140 | if (ret) |
185 | goto out_unref; | 141 | goto out_unref; |
@@ -214,7 +170,7 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
214 | // memset(info->screen_base, 0, size); | 170 | // memset(info->screen_base, 0, size); |
215 | 171 | ||
216 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); | 172 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); |
217 | drm_fb_helper_fill_var(info, fb, fb_width, fb_height); | 173 | drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); |
218 | 174 | ||
219 | /* FIXME: we really shouldn't expose mmio space at all */ | 175 | /* FIXME: we really shouldn't expose mmio space at all */ |
220 | info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar); | 176 | info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar); |
@@ -226,15 +182,11 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
226 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | 182 | info->pixmap.flags = FB_PIXMAP_SYSTEM; |
227 | info->pixmap.scan_align = 1; | 183 | info->pixmap.scan_align = 1; |
228 | 184 | ||
229 | fb->fbdev = info; | ||
230 | |||
231 | par->intel_fb = intel_fb; | ||
232 | |||
233 | /* To allow resizeing without swapping buffers */ | ||
234 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", | 185 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", |
235 | intel_fb->base.width, intel_fb->base.height, | 186 | intel_fb->base.width, intel_fb->base.height, |
236 | obj_priv->gtt_offset, fbo); | 187 | obj_priv->gtt_offset, fbo); |
237 | 188 | ||
189 | |||
238 | mutex_unlock(&dev->struct_mutex); | 190 | mutex_unlock(&dev->struct_mutex); |
239 | vga_switcheroo_client_fb_set(dev->pdev, info); | 191 | vga_switcheroo_client_fb_set(dev->pdev, info); |
240 | return 0; | 192 | return 0; |
@@ -248,35 +200,76 @@ out: | |||
248 | return ret; | 200 | return ret; |
249 | } | 201 | } |
250 | 202 | ||
251 | int intelfb_probe(struct drm_device *dev) | 203 | static int intel_fb_find_or_create_single(struct drm_device *dev, |
204 | struct drm_fb_helper_surface_size *sizes, | ||
205 | struct drm_fb_helper **fb_ptr) | ||
206 | { | ||
207 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
208 | struct intel_kernel_fbdev *ifbdev = NULL; | ||
209 | int new_fb = 0; | ||
210 | int ret; | ||
211 | |||
212 | if (!dev_priv->fbdev) { | ||
213 | ret = intelfb_create(dev, sizes, | ||
214 | &ifbdev); | ||
215 | if (ret) | ||
216 | return ret; | ||
217 | |||
218 | dev_priv->fbdev = ifbdev; | ||
219 | new_fb = 1; | ||
220 | } else { | ||
221 | ifbdev = dev_priv->fbdev; | ||
222 | if (ifbdev->ifb.base.width < sizes->surface_width || | ||
223 | ifbdev->ifb.base.height < sizes->surface_height) { | ||
224 | DRM_ERROR("Framebuffer not large enough to scale console onto.\n"); | ||
225 | return -EINVAL; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | *fb_ptr = &ifbdev->helper; | ||
230 | return new_fb; | ||
231 | } | ||
232 | |||
233 | static int intelfb_probe(struct drm_device *dev) | ||
252 | { | 234 | { |
253 | int ret; | 235 | int ret; |
254 | 236 | ||
255 | DRM_DEBUG_KMS("\n"); | 237 | DRM_DEBUG_KMS("\n"); |
256 | ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create); | 238 | ret = drm_fb_helper_single_fb_probe(dev, 32, intel_fb_find_or_create_single); |
257 | return ret; | 239 | return ret; |
258 | } | 240 | } |
259 | EXPORT_SYMBOL(intelfb_probe); | ||
260 | 241 | ||
261 | int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | 242 | int intel_fbdev_destroy(struct drm_device *dev, |
243 | struct intel_kernel_fbdev *ifbdev) | ||
262 | { | 244 | { |
263 | struct fb_info *info; | 245 | struct fb_info *info; |
246 | struct intel_framebuffer *ifb = &ifbdev->ifb; | ||
264 | 247 | ||
265 | if (!fb) | 248 | info = ifbdev->helper.fbdev; |
266 | return -EINVAL; | ||
267 | 249 | ||
268 | info = fb->fbdev; | 250 | unregister_framebuffer(info); |
251 | iounmap(info->screen_base); | ||
252 | drm_fb_helper_free(&ifbdev->helper); | ||
269 | 253 | ||
270 | if (info) { | 254 | drm_framebuffer_cleanup(&ifb->base); |
271 | struct intelfb_par *par = info->par; | 255 | drm_gem_object_unreference_unlocked(ifb->obj); |
272 | unregister_framebuffer(info); | 256 | |
273 | iounmap(info->screen_base); | 257 | framebuffer_release(info); |
274 | if (info->par) | ||
275 | drm_fb_helper_free(&par->helper); | ||
276 | framebuffer_release(info); | ||
277 | } | ||
278 | 258 | ||
279 | return 0; | 259 | return 0; |
280 | } | 260 | } |
281 | EXPORT_SYMBOL(intelfb_remove); | 261 | |
262 | int intel_fbdev_init(struct drm_device *dev) | ||
263 | { | ||
264 | drm_helper_initial_config(dev); | ||
265 | intelfb_probe(dev); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | void intel_fbdev_fini(struct drm_device *dev) | ||
270 | { | ||
271 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
272 | intel_fbdev_destroy(dev, dev_priv->fbdev); | ||
273 | dev_priv->fbdev = NULL; | ||
274 | } | ||
282 | MODULE_LICENSE("GPL and additional rights"); | 275 | MODULE_LICENSE("GPL and additional rights"); |