aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2010-03-30 01:34:13 -0400
committerDave Airlie <airlied@redhat.com>2010-04-06 20:21:03 -0400
commit386516744ba45d50f42c6999151cc210cb4f96e4 (patch)
tree88e3b6aeb83040a8bd512eb7aad087e6c0fcd556 /drivers/gpu/drm/i915
parent643acacf02679befd0f98ac3c5fecb805f1c9548 (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.c2
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c37
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h13
-rw-r--r--drivers/gpu/drm/i915/intel_fb.c175
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
223struct intel_kernel_fbdev;
224
223typedef struct drm_i915_private { 225typedef 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)
4506static void intel_user_framebuffer_destroy(struct drm_framebuffer *fb) 4506static 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
4535int intel_framebuffer_create(struct drm_device *dev, 4531int 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
4563static struct drm_framebuffer * 4549static struct drm_framebuffer *
4564intel_user_framebuffer_create(struct drm_device *dev, 4550intel_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
4585static const struct drm_mode_config_funcs intel_mode_funcs = { 4577static 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
4590static struct drm_gem_object * 4581static 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,
200extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); 200extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB);
201extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); 201extern int intel_sdvo_supports_hotplug(struct drm_connector *connector);
202extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); 202extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable);
203extern int intelfb_probe(struct drm_device *dev);
204extern int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb);
205extern int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc);
206extern void intelfb_restore(void); 203extern void intelfb_restore(void);
207extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 204extern 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);
212extern void ironlake_enable_drps(struct drm_device *dev); 209extern void ironlake_enable_drps(struct drm_device *dev);
213extern void ironlake_disable_drps(struct drm_device *dev); 210extern void ironlake_disable_drps(struct drm_device *dev);
214 211
215extern int intel_framebuffer_create(struct drm_device *dev, 212extern 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);
216extern int intel_fbdev_init(struct drm_device *dev);
217extern void intel_fbdev_fini(struct drm_device *dev);
219 218
220extern void intel_prepare_page_flip(struct drm_device *dev, int plane); 219extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
221extern void intel_finish_page_flip(struct drm_device *dev, int pipe); 220extern 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
48struct intelfb_par { 48struct 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/** 74static 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 */
80int 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}
111EXPORT_SYMBOL(intelfb_resize);
112
113static 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
251int intelfb_probe(struct drm_device *dev) 203static 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
233static 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}
259EXPORT_SYMBOL(intelfb_probe);
260 241
261int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) 242int 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}
281EXPORT_SYMBOL(intelfb_remove); 261
262int intel_fbdev_init(struct drm_device *dev)
263{
264 drm_helper_initial_config(dev);
265 intelfb_probe(dev);
266 return 0;
267}
268
269void 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}
282MODULE_LICENSE("GPL and additional rights"); 275MODULE_LICENSE("GPL and additional rights");