diff options
author | Dave Airlie <airlied@redhat.com> | 2010-04-19 23:16:04 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2010-04-19 23:16:04 -0400 |
commit | 7fff400be6fbf64f10abca9939718aaf1d61c255 (patch) | |
tree | 384118628f5c5aa2d74303cddd120de75308beea /drivers/gpu/drm/i915/intel_fb.c | |
parent | 0bcb1d844ac638a4c4280f697d5bfac9791e9a70 (diff) | |
parent | b1f201980eb4a7a59277a13cf18acdbb46167ad5 (diff) |
Merge branch 'drm-fbdev-cleanup' into drm-core-next
* drm-fbdev-cleanup:
drm/fb: remove drm_fb_helper_setcolreg
drm/kms/fb: use slow work mechanism for normal hotplug also.
drm/kms/fb: add polling support for when nothing is connected.
drm/kms/fb: provide a 1024x768 fbcon if no outputs found.
drm/kms/fb: separate fbdev connector list from core drm connectors
drm/kms/fb: move to using fb helper crtc grouping instead of core crtc list
drm/fb: fix fbdev object model + cleanup properly.
Conflicts:
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/nouveau/nouveau_drv.h
Diffstat (limited to 'drivers/gpu/drm/i915/intel_fb.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_fb.c | 202 |
1 files changed, 96 insertions, 106 deletions
diff --git a/drivers/gpu/drm/i915/intel_fb.c b/drivers/gpu/drm/i915/intel_fb.c index 8a0b3bcdc7b..34ad0333eae 100644 --- a/drivers/gpu/drm/i915/intel_fb.c +++ b/drivers/gpu/drm/i915/intel_fb.c | |||
@@ -44,9 +44,10 @@ | |||
44 | #include "i915_drm.h" | 44 | #include "i915_drm.h" |
45 | #include "i915_drv.h" | 45 | #include "i915_drv.h" |
46 | 46 | ||
47 | struct intelfb_par { | 47 | struct intel_fbdev { |
48 | struct drm_fb_helper helper; | 48 | struct drm_fb_helper helper; |
49 | struct intel_framebuffer *intel_fb; | 49 | struct intel_framebuffer ifb; |
50 | struct list_head fbdev_list; | ||
50 | struct drm_display_mode *our_mode; | 51 | struct drm_display_mode *our_mode; |
51 | }; | 52 | }; |
52 | 53 | ||
@@ -54,7 +55,6 @@ static struct fb_ops intelfb_ops = { | |||
54 | .owner = THIS_MODULE, | 55 | .owner = THIS_MODULE, |
55 | .fb_check_var = drm_fb_helper_check_var, | 56 | .fb_check_var = drm_fb_helper_check_var, |
56 | .fb_set_par = drm_fb_helper_set_par, | 57 | .fb_set_par = drm_fb_helper_set_par, |
57 | .fb_setcolreg = drm_fb_helper_setcolreg, | ||
58 | .fb_fillrect = cfb_fillrect, | 58 | .fb_fillrect = cfb_fillrect, |
59 | .fb_copyarea = cfb_copyarea, | 59 | .fb_copyarea = cfb_copyarea, |
60 | .fb_imageblit = cfb_imageblit, | 60 | .fb_imageblit = cfb_imageblit, |
@@ -63,62 +63,12 @@ static struct fb_ops intelfb_ops = { | |||
63 | .fb_setcmap = drm_fb_helper_setcmap, | 63 | .fb_setcmap = drm_fb_helper_setcmap, |
64 | }; | 64 | }; |
65 | 65 | ||
66 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { | 66 | static int intelfb_create(struct intel_fbdev *ifbdev, |
67 | .gamma_set = intel_crtc_fb_gamma_set, | 67 | struct drm_fb_helper_surface_size *sizes) |
68 | .gamma_get = intel_crtc_fb_gamma_get, | ||
69 | }; | ||
70 | |||
71 | |||
72 | /** | ||
73 | * Currently it is assumed that the old framebuffer is reused. | ||
74 | * | ||
75 | * LOCKING | ||
76 | * caller should hold the mode config lock. | ||
77 | * | ||
78 | */ | ||
79 | int intelfb_resize(struct drm_device *dev, struct drm_crtc *crtc) | ||
80 | { | ||
81 | struct fb_info *info; | ||
82 | struct drm_framebuffer *fb; | ||
83 | struct drm_display_mode *mode = crtc->desired_mode; | ||
84 | |||
85 | fb = crtc->fb; | ||
86 | if (!fb) | ||
87 | return 1; | ||
88 | |||
89 | info = fb->fbdev; | ||
90 | if (!info) | ||
91 | return 1; | ||
92 | |||
93 | if (!mode) | ||
94 | return 1; | ||
95 | |||
96 | info->var.xres = mode->hdisplay; | ||
97 | info->var.right_margin = mode->hsync_start - mode->hdisplay; | ||
98 | info->var.hsync_len = mode->hsync_end - mode->hsync_start; | ||
99 | info->var.left_margin = mode->htotal - mode->hsync_end; | ||
100 | info->var.yres = mode->vdisplay; | ||
101 | info->var.lower_margin = mode->vsync_start - mode->vdisplay; | ||
102 | info->var.vsync_len = mode->vsync_end - mode->vsync_start; | ||
103 | info->var.upper_margin = mode->vtotal - mode->vsync_end; | ||
104 | info->var.pixclock = 10000000 / mode->htotal * 1000 / mode->vtotal * 100; | ||
105 | /* avoid overflow */ | ||
106 | info->var.pixclock = info->var.pixclock * 1000 / mode->vrefresh; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | EXPORT_SYMBOL(intelfb_resize); | ||
111 | |||
112 | static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | ||
113 | uint32_t fb_height, uint32_t surface_width, | ||
114 | uint32_t surface_height, | ||
115 | uint32_t surface_depth, uint32_t surface_bpp, | ||
116 | struct drm_framebuffer **fb_p) | ||
117 | { | 68 | { |
69 | struct drm_device *dev = ifbdev->helper.dev; | ||
118 | struct fb_info *info; | 70 | struct fb_info *info; |
119 | struct intelfb_par *par; | ||
120 | struct drm_framebuffer *fb; | 71 | struct drm_framebuffer *fb; |
121 | struct intel_framebuffer *intel_fb; | ||
122 | struct drm_mode_fb_cmd mode_cmd; | 72 | struct drm_mode_fb_cmd mode_cmd; |
123 | struct drm_gem_object *fbo = NULL; | 73 | struct drm_gem_object *fbo = NULL; |
124 | struct drm_i915_gem_object *obj_priv; | 74 | struct drm_i915_gem_object *obj_priv; |
@@ -126,15 +76,15 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
126 | int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; | 76 | int size, ret, mmio_bar = IS_I9XX(dev) ? 0 : 1; |
127 | 77 | ||
128 | /* we don't do packed 24bpp */ | 78 | /* we don't do packed 24bpp */ |
129 | if (surface_bpp == 24) | 79 | if (sizes->surface_bpp == 24) |
130 | surface_bpp = 32; | 80 | sizes->surface_bpp = 32; |
131 | 81 | ||
132 | mode_cmd.width = surface_width; | 82 | mode_cmd.width = sizes->surface_width; |
133 | mode_cmd.height = surface_height; | 83 | mode_cmd.height = sizes->surface_height; |
134 | 84 | ||
135 | mode_cmd.bpp = surface_bpp; | 85 | mode_cmd.bpp = sizes->surface_bpp; |
136 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); | 86 | mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 1) / 8), 64); |
137 | mode_cmd.depth = surface_depth; | 87 | mode_cmd.depth = sizes->surface_depth; |
138 | 88 | ||
139 | size = mode_cmd.pitch * mode_cmd.height; | 89 | size = mode_cmd.pitch * mode_cmd.height; |
140 | size = ALIGN(size, PAGE_SIZE); | 90 | size = ALIGN(size, PAGE_SIZE); |
@@ -157,39 +107,26 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
157 | /* Flush everything out, we'll be doing GTT only from now on */ | 107 | /* Flush everything out, we'll be doing GTT only from now on */ |
158 | i915_gem_object_set_to_gtt_domain(fbo, 1); | 108 | i915_gem_object_set_to_gtt_domain(fbo, 1); |
159 | 109 | ||
160 | ret = intel_framebuffer_create(dev, &mode_cmd, &fb, fbo); | 110 | info = framebuffer_alloc(0, device); |
161 | if (ret) { | ||
162 | DRM_ERROR("failed to allocate fb.\n"); | ||
163 | goto out_unpin; | ||
164 | } | ||
165 | |||
166 | list_add(&fb->filp_head, &dev->mode_config.fb_kernel_list); | ||
167 | |||
168 | intel_fb = to_intel_framebuffer(fb); | ||
169 | *fb_p = fb; | ||
170 | |||
171 | info = framebuffer_alloc(sizeof(struct intelfb_par), device); | ||
172 | if (!info) { | 111 | if (!info) { |
173 | ret = -ENOMEM; | 112 | ret = -ENOMEM; |
174 | goto out_unpin; | 113 | goto out_unpin; |
175 | } | 114 | } |
176 | 115 | ||
177 | par = info->par; | 116 | info->par = ifbdev; |
178 | 117 | ||
179 | par->helper.funcs = &intel_fb_helper_funcs; | 118 | intel_framebuffer_init(dev, &ifbdev->ifb, &mode_cmd, fbo); |
180 | par->helper.dev = dev; | 119 | |
181 | ret = drm_fb_helper_init_crtc_count(&par->helper, 2, | 120 | fb = &ifbdev->ifb.base; |
182 | INTELFB_CONN_LIMIT); | 121 | |
183 | if (ret) | 122 | ifbdev->helper.fb = fb; |
184 | goto out_unref; | 123 | ifbdev->helper.fbdev = info; |
185 | 124 | ||
186 | strcpy(info->fix.id, "inteldrmfb"); | 125 | strcpy(info->fix.id, "inteldrmfb"); |
187 | 126 | ||
188 | info->flags = FBINFO_DEFAULT; | 127 | info->flags = FBINFO_DEFAULT; |
189 | |||
190 | info->fbops = &intelfb_ops; | 128 | info->fbops = &intelfb_ops; |
191 | 129 | ||
192 | |||
193 | /* setup aperture base/size for vesafb takeover */ | 130 | /* setup aperture base/size for vesafb takeover */ |
194 | info->aperture_base = dev->mode_config.fb_base; | 131 | info->aperture_base = dev->mode_config.fb_base; |
195 | if (IS_I9XX(dev)) | 132 | if (IS_I9XX(dev)) |
@@ -208,12 +145,18 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
208 | ret = -ENOSPC; | 145 | ret = -ENOSPC; |
209 | goto out_unpin; | 146 | goto out_unpin; |
210 | } | 147 | } |
148 | |||
149 | ret = fb_alloc_cmap(&info->cmap, 256, 0); | ||
150 | if (ret) { | ||
151 | ret = -ENOMEM; | ||
152 | goto out_unpin; | ||
153 | } | ||
211 | info->screen_size = size; | 154 | info->screen_size = size; |
212 | 155 | ||
213 | // memset(info->screen_base, 0, size); | 156 | // memset(info->screen_base, 0, size); |
214 | 157 | ||
215 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); | 158 | drm_fb_helper_fill_fix(info, fb->pitch, fb->depth); |
216 | drm_fb_helper_fill_var(info, fb, fb_width, fb_height); | 159 | drm_fb_helper_fill_var(info, &ifbdev->helper, sizes->fb_width, sizes->fb_height); |
217 | 160 | ||
218 | /* FIXME: we really shouldn't expose mmio space at all */ | 161 | /* FIXME: we really shouldn't expose mmio space at all */ |
219 | info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar); | 162 | info->fix.mmio_start = pci_resource_start(dev->pdev, mmio_bar); |
@@ -225,14 +168,10 @@ static int intelfb_create(struct drm_device *dev, uint32_t fb_width, | |||
225 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | 168 | info->pixmap.flags = FB_PIXMAP_SYSTEM; |
226 | info->pixmap.scan_align = 1; | 169 | info->pixmap.scan_align = 1; |
227 | 170 | ||
228 | fb->fbdev = info; | ||
229 | |||
230 | par->intel_fb = intel_fb; | ||
231 | |||
232 | /* To allow resizeing without swapping buffers */ | ||
233 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", | 171 | DRM_DEBUG_KMS("allocated %dx%d fb: 0x%08x, bo %p\n", |
234 | intel_fb->base.width, intel_fb->base.height, | 172 | fb->width, fb->height, |
235 | obj_priv->gtt_offset, fbo); | 173 | obj_priv->gtt_offset, fbo); |
174 | |||
236 | 175 | ||
237 | mutex_unlock(&dev->struct_mutex); | 176 | mutex_unlock(&dev->struct_mutex); |
238 | vga_switcheroo_client_fb_set(dev->pdev, info); | 177 | vga_switcheroo_client_fb_set(dev->pdev, info); |
@@ -247,35 +186,86 @@ out: | |||
247 | return ret; | 186 | return ret; |
248 | } | 187 | } |
249 | 188 | ||
250 | int intelfb_probe(struct drm_device *dev) | 189 | static int intel_fb_find_or_create_single(struct drm_fb_helper *helper, |
190 | struct drm_fb_helper_surface_size *sizes) | ||
251 | { | 191 | { |
192 | struct intel_fbdev *ifbdev = (struct intel_fbdev *)helper; | ||
193 | int new_fb = 0; | ||
252 | int ret; | 194 | int ret; |
253 | 195 | ||
254 | DRM_DEBUG_KMS("\n"); | 196 | if (!helper->fb) { |
255 | ret = drm_fb_helper_single_fb_probe(dev, 32, intelfb_create); | 197 | ret = intelfb_create(ifbdev, sizes); |
256 | return ret; | 198 | if (ret) |
199 | return ret; | ||
200 | new_fb = 1; | ||
201 | } | ||
202 | return new_fb; | ||
257 | } | 203 | } |
258 | EXPORT_SYMBOL(intelfb_probe); | ||
259 | 204 | ||
260 | int intelfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | 205 | void intelfb_hotplug(struct drm_device *dev, bool polled) |
261 | { | 206 | { |
262 | struct fb_info *info; | 207 | drm_i915_private_t *dev_priv = dev->dev_private; |
208 | drm_helper_fb_hpd_irq_event(&dev_priv->fbdev->helper); | ||
209 | } | ||
263 | 210 | ||
264 | if (!fb) | 211 | static struct drm_fb_helper_funcs intel_fb_helper_funcs = { |
265 | return -EINVAL; | 212 | .gamma_set = intel_crtc_fb_gamma_set, |
213 | .gamma_get = intel_crtc_fb_gamma_get, | ||
214 | .fb_probe = intel_fb_find_or_create_single, | ||
215 | }; | ||
266 | 216 | ||
267 | info = fb->fbdev; | 217 | int intel_fbdev_destroy(struct drm_device *dev, |
218 | struct intel_fbdev *ifbdev) | ||
219 | { | ||
220 | struct fb_info *info; | ||
221 | struct intel_framebuffer *ifb = &ifbdev->ifb; | ||
268 | 222 | ||
269 | if (info) { | 223 | if (ifbdev->helper.fbdev) { |
270 | struct intelfb_par *par = info->par; | 224 | info = ifbdev->helper.fbdev; |
271 | unregister_framebuffer(info); | 225 | unregister_framebuffer(info); |
272 | iounmap(info->screen_base); | 226 | iounmap(info->screen_base); |
273 | if (info->par) | 227 | if (info->cmap.len) |
274 | drm_fb_helper_free(&par->helper); | 228 | fb_dealloc_cmap(&info->cmap); |
275 | framebuffer_release(info); | 229 | framebuffer_release(info); |
276 | } | 230 | } |
277 | 231 | ||
232 | drm_fb_helper_fini(&ifbdev->helper); | ||
233 | |||
234 | drm_framebuffer_cleanup(&ifb->base); | ||
235 | if (ifb->obj) | ||
236 | drm_gem_object_unreference_unlocked(ifb->obj); | ||
237 | |||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | int intel_fbdev_init(struct drm_device *dev) | ||
242 | { | ||
243 | struct intel_fbdev *ifbdev; | ||
244 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
245 | |||
246 | ifbdev = kzalloc(sizeof(struct intel_fbdev), GFP_KERNEL); | ||
247 | if (!ifbdev) | ||
248 | return -ENOMEM; | ||
249 | |||
250 | dev_priv->fbdev = ifbdev; | ||
251 | ifbdev->helper.funcs = &intel_fb_helper_funcs; | ||
252 | |||
253 | drm_fb_helper_init(dev, &ifbdev->helper, 2, | ||
254 | INTELFB_CONN_LIMIT, false); | ||
255 | |||
256 | drm_fb_helper_single_add_all_connectors(&ifbdev->helper); | ||
257 | drm_fb_helper_initial_config(&ifbdev->helper, 32); | ||
278 | return 0; | 258 | return 0; |
279 | } | 259 | } |
280 | EXPORT_SYMBOL(intelfb_remove); | 260 | |
261 | void intel_fbdev_fini(struct drm_device *dev) | ||
262 | { | ||
263 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
264 | if (!dev_priv->fbdev) | ||
265 | return; | ||
266 | |||
267 | intel_fbdev_destroy(dev, dev_priv->fbdev); | ||
268 | kfree(dev_priv->fbdev); | ||
269 | dev_priv->fbdev = NULL; | ||
270 | } | ||
281 | MODULE_LICENSE("GPL and additional rights"); | 271 | MODULE_LICENSE("GPL and additional rights"); |