aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/radeon_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_fb.c')
-rw-r--r--drivers/gpu/drm/radeon/radeon_fb.c240
1 files changed, 132 insertions, 108 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index a7e4c2a89ee0..705425defba0 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -23,10 +23,6 @@
23 * Authors: 23 * Authors:
24 * David Airlie 24 * David Airlie
25 */ 25 */
26 /*
27 * Modularization
28 */
29
30#include <linux/module.h> 26#include <linux/module.h>
31#include <linux/fb.h> 27#include <linux/fb.h>
32 28
@@ -45,7 +41,7 @@
45 this contains a helper + a radeon fb 41 this contains a helper + a radeon fb
46 the helper contains a pointer to radeon framebuffer baseclass. 42 the helper contains a pointer to radeon framebuffer baseclass.
47*/ 43*/
48struct radeon_kernel_fbdev { 44struct radeon_fbdev {
49 struct drm_fb_helper helper; 45 struct drm_fb_helper helper;
50 struct radeon_framebuffer rfb; 46 struct radeon_framebuffer rfb;
51 struct list_head fbdev_list; 47 struct list_head fbdev_list;
@@ -95,49 +91,44 @@ static struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
95 .gamma_get = radeon_crtc_fb_gamma_get, 91 .gamma_get = radeon_crtc_fb_gamma_get,
96}; 92};
97 93
98static int radeonfb_create(struct drm_device *dev, 94static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
99 struct drm_fb_helper_surface_size *sizes,
100 struct radeon_kernel_fbdev **rfbdev_p)
101{ 95{
102 struct radeon_device *rdev = dev->dev_private; 96 struct radeon_bo *rbo = gobj->driver_private;
103 struct fb_info *info; 97 int ret;
104 struct radeon_kernel_fbdev *rfbdev; 98
105 struct drm_framebuffer *fb = NULL; 99 ret = radeon_bo_reserve(rbo, false);
106 struct drm_mode_fb_cmd mode_cmd; 100 if (likely(ret == 0)) {
101 radeon_bo_kunmap(rbo);
102 radeon_bo_unreserve(rbo);
103 }
104 drm_gem_object_unreference_unlocked(gobj);
105}
106
107static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
108 struct drm_mode_fb_cmd *mode_cmd,
109 struct drm_gem_object **gobj_p)
110{
111 struct radeon_device *rdev = rfbdev->rdev;
107 struct drm_gem_object *gobj = NULL; 112 struct drm_gem_object *gobj = NULL;
108 struct radeon_bo *rbo = NULL; 113 struct radeon_bo *rbo = NULL;
109 struct device *device = &rdev->pdev->dev;
110 int size, aligned_size, ret;
111 u64 fb_gpuaddr;
112 void *fbptr = NULL;
113 unsigned long tmp;
114 bool fb_tiled = false; /* useful for testing */ 114 bool fb_tiled = false; /* useful for testing */
115 u32 tiling_flags = 0; 115 u32 tiling_flags = 0;
116 int ret;
117 int aligned_size, size;
116 118
117 mode_cmd.width = sizes->surface_width;
118 mode_cmd.height = sizes->surface_height;
119
120 /* avivo can't scanout real 24bpp */
121 if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
122 sizes->surface_bpp = 32;
123
124 mode_cmd.bpp = sizes->surface_bpp;
125 /* need to align pitch with crtc limits */ 119 /* need to align pitch with crtc limits */
126 mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8); 120 mode_cmd->pitch = radeon_align_pitch(rdev, mode_cmd->width, mode_cmd->bpp, fb_tiled) * ((mode_cmd->bpp + 1) / 8);
127 mode_cmd.depth = sizes->surface_depth;
128 121
129 size = mode_cmd.pitch * mode_cmd.height; 122 size = mode_cmd->pitch * mode_cmd->height;
130 aligned_size = ALIGN(size, PAGE_SIZE); 123 aligned_size = ALIGN(size, PAGE_SIZE);
131
132 ret = radeon_gem_object_create(rdev, aligned_size, 0, 124 ret = radeon_gem_object_create(rdev, aligned_size, 0,
133 RADEON_GEM_DOMAIN_VRAM, 125 RADEON_GEM_DOMAIN_VRAM,
134 false, ttm_bo_type_kernel, 126 false, ttm_bo_type_kernel,
135 &gobj); 127 &gobj);
136 if (ret) { 128 if (ret) {
137 printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", 129 printk(KERN_ERR "failed to allocate framebuffer (%d)\n",
138 sizes->surface_width, sizes->surface_height); 130 aligned_size);
139 ret = -ENOMEM; 131 return -ENOMEM;
140 goto out;
141 } 132 }
142 rbo = gobj->driver_private; 133 rbo = gobj->driver_private;
143 134
@@ -145,7 +136,7 @@ static int radeonfb_create(struct drm_device *dev,
145 tiling_flags = RADEON_TILING_MACRO; 136 tiling_flags = RADEON_TILING_MACRO;
146 137
147#ifdef __BIG_ENDIAN 138#ifdef __BIG_ENDIAN
148 switch (mode_cmd.bpp) { 139 switch (mode_cmd->bpp) {
149 case 32: 140 case 32:
150 tiling_flags |= RADEON_TILING_SWAP_32BIT; 141 tiling_flags |= RADEON_TILING_SWAP_32BIT;
151 break; 142 break;
@@ -158,54 +149,82 @@ static int radeonfb_create(struct drm_device *dev,
158 149
159 if (tiling_flags) { 150 if (tiling_flags) {
160 ret = radeon_bo_set_tiling_flags(rbo, 151 ret = radeon_bo_set_tiling_flags(rbo,
161 tiling_flags | RADEON_TILING_SURFACE, 152 tiling_flags | RADEON_TILING_SURFACE,
162 mode_cmd.pitch); 153 mode_cmd->pitch);
163 if (ret) 154 if (ret)
164 dev_err(rdev->dev, "FB failed to set tiling flags\n"); 155 dev_err(rdev->dev, "FB failed to set tiling flags\n");
165 } 156 }
166 mutex_lock(&rdev->ddev->struct_mutex); 157
167 158
168 ret = radeon_bo_reserve(rbo, false); 159 ret = radeon_bo_reserve(rbo, false);
169 if (unlikely(ret != 0)) 160 if (unlikely(ret != 0))
170 goto out_unref; 161 goto out_unref;
171 ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); 162 ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, NULL);
172 if (ret) { 163 if (ret) {
173 radeon_bo_unreserve(rbo); 164 radeon_bo_unreserve(rbo);
174 goto out_unref; 165 goto out_unref;
175 } 166 }
176 if (fb_tiled) 167 if (fb_tiled)
177 radeon_bo_check_tiling(rbo, 0, 0); 168 radeon_bo_check_tiling(rbo, 0, 0);
178 ret = radeon_bo_kmap(rbo, &fbptr); 169 ret = radeon_bo_kmap(rbo, NULL);
179 radeon_bo_unreserve(rbo); 170 radeon_bo_unreserve(rbo);
180 if (ret) { 171 if (ret) {
181 goto out_unref; 172 goto out_unref;
182 } 173 }
183 174
184 info = framebuffer_alloc(sizeof(struct radeon_kernel_fbdev), device); 175 *gobj_p = gobj;
176 return 0;
177out_unref:
178 radeonfb_destroy_pinned_object(gobj);
179 *gobj_p = NULL;
180 return ret;
181}
182
183static int radeonfb_create(struct radeon_fbdev *rfbdev,
184 struct drm_fb_helper_surface_size *sizes)
185{
186 struct radeon_device *rdev = rfbdev->rdev;
187 struct fb_info *info;
188 struct drm_framebuffer *fb = NULL;
189 struct drm_mode_fb_cmd mode_cmd;
190 struct drm_gem_object *gobj = NULL;
191 struct radeon_bo *rbo = NULL;
192 struct device *device = &rdev->pdev->dev;
193 int ret;
194 unsigned long tmp;
195
196 mode_cmd.width = sizes->surface_width;
197 mode_cmd.height = sizes->surface_height;
198
199 /* avivo can't scanout real 24bpp */
200 if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev))
201 sizes->surface_bpp = 32;
202
203 mode_cmd.bpp = sizes->surface_bpp;
204 mode_cmd.depth = sizes->surface_depth;
205
206 ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
207 rbo = gobj->driver_private;
208
209 /* okay we have an object now allocate the framebuffer */
210 info = framebuffer_alloc(0, device);
185 if (info == NULL) { 211 if (info == NULL) {
186 ret = -ENOMEM; 212 ret = -ENOMEM;
187 goto out_unref; 213 goto out_unref;
188 } 214 }
189 215
190 rfbdev = info->par; 216 info->par = rfbdev;
191 rfbdev->rdev = rdev; 217
192 radeon_framebuffer_init(dev, &rfbdev->rfb, &mode_cmd, gobj); 218 radeon_framebuffer_init(rdev->ddev, &rfbdev->rfb, &mode_cmd, gobj);
219
193 fb = &rfbdev->rfb.base; 220 fb = &rfbdev->rfb.base;
194 221
195 /* setup helper */ 222 /* setup helper */
196 rfbdev->helper.fb = fb; 223 rfbdev->helper.fb = fb;
197 rfbdev->helper.fbdev = info; 224 rfbdev->helper.fbdev = info;
198 rfbdev->helper.funcs = &radeon_fb_helper_funcs; 225 rfbdev->helper.funcs = &radeon_fb_helper_funcs;
199 rfbdev->helper.dev = dev;
200
201 *rfbdev_p = rfbdev;
202 226
203 ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, rdev->num_crtc, 227 memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo));
204 RADEONFB_CONN_LIMIT);
205 if (ret)
206 goto out_unref;
207
208 memset_io(fbptr, 0x0, aligned_size);
209 228
210 strcpy(info->fix.id, "radeondrmfb"); 229 strcpy(info->fix.id, "radeondrmfb");
211 230
@@ -214,11 +233,11 @@ static int radeonfb_create(struct drm_device *dev,
214 info->flags = FBINFO_DEFAULT; 233 info->flags = FBINFO_DEFAULT;
215 info->fbops = &radeonfb_ops; 234 info->fbops = &radeonfb_ops;
216 235
217 tmp = fb_gpuaddr - rdev->mc.vram_start; 236 tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
218 info->fix.smem_start = rdev->mc.aper_base + tmp; 237 info->fix.smem_start = rdev->mc.aper_base + tmp;
219 info->fix.smem_len = size; 238 info->fix.smem_len = radeon_bo_size(rbo);
220 info->screen_base = fbptr; 239 info->screen_base = rbo->kptr;
221 info->screen_size = size; 240 info->screen_size = radeon_bo_size(rbo);
222 241
223 drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height); 242 drm_fb_helper_fill_var(info, &rfbdev->helper, sizes->fb_width, sizes->fb_height);
224 243
@@ -239,60 +258,40 @@ static int radeonfb_create(struct drm_device *dev,
239 } 258 }
240 DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); 259 DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
241 DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); 260 DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base);
242 DRM_INFO("size %lu\n", (unsigned long)size); 261 DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo));
243 DRM_INFO("fb depth is %d\n", fb->depth); 262 DRM_INFO("fb depth is %d\n", fb->depth);
244 DRM_INFO(" pitch is %d\n", fb->pitch); 263 DRM_INFO(" pitch is %d\n", fb->pitch);
245 264
246
247 mutex_unlock(&rdev->ddev->struct_mutex);
248 vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); 265 vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
249 return 0; 266 return 0;
250 267
251out_unref: 268out_unref:
252 if (rbo) { 269 if (rbo) {
253 ret = radeon_bo_reserve(rbo, false); 270
254 if (likely(ret == 0)) {
255 radeon_bo_kunmap(rbo);
256 radeon_bo_unreserve(rbo);
257 }
258 } 271 }
259 if (fb && ret) { 272 if (fb && ret) {
260 drm_gem_object_unreference(gobj); 273 drm_gem_object_unreference(gobj);
261 drm_framebuffer_cleanup(fb); 274 drm_framebuffer_cleanup(fb);
262 kfree(fb); 275 kfree(fb);
263 } 276 }
264 drm_gem_object_unreference(gobj); 277
265 mutex_unlock(&rdev->ddev->struct_mutex);
266out: 278out:
267 return ret; 279 return ret;
268} 280}
269 281
270static int radeon_fb_find_or_create_single(struct drm_device *dev, 282static int radeon_fb_find_or_create_single(struct drm_fb_helper *helper,
271 struct drm_fb_helper_surface_size *sizes, 283 struct drm_fb_helper_surface_size *sizes)
272 struct drm_fb_helper **fb_ptr)
273{ 284{
274 struct radeon_device *rdev = dev->dev_private; 285 struct radeon_fbdev *rfbdev = (struct radeon_fbdev *)helper;
275 struct radeon_kernel_fbdev *rfbdev = NULL;
276 int new_fb = 0; 286 int new_fb = 0;
277 int ret; 287 int ret;
278 288
279 if (!rdev->mode_info.rfbdev) { 289 if (!helper->fb) {
280 ret = radeonfb_create(dev, sizes, 290 ret = radeonfb_create(rfbdev, sizes);
281 &rfbdev);
282 if (ret) 291 if (ret)
283 return ret; 292 return ret;
284 rdev->mode_info.rfbdev = rfbdev;
285 new_fb = 1; 293 new_fb = 1;
286 } else {
287 rfbdev = rdev->mode_info.rfbdev;
288 if (rfbdev->rfb.base.width < sizes->surface_width ||
289 rfbdev->rfb.base.height < sizes->surface_height) {
290 DRM_ERROR("Framebuffer not large enough to scale console onto.\n");
291 return -EINVAL;
292 }
293 } 294 }
294
295 *fb_ptr = &rfbdev->helper;
296 return new_fb; 295 return new_fb;
297} 296}
298 297
@@ -312,48 +311,55 @@ int radeon_parse_options(char *options)
312 return 0; 311 return 0;
313} 312}
314 313
315static int radeonfb_probe(struct drm_device *dev) 314static int radeonfb_probe(struct radeon_fbdev *rfbdev)
316{ 315{
317 struct radeon_device *rdev = dev->dev_private; 316 struct radeon_device *rdev = rfbdev->rdev;
318 int bpp_sel = 32; 317 int bpp_sel = 32;
319 318
320 /* select 8 bpp console on RN50 or 16MB cards */ 319 /* select 8 bpp console on RN50 or 16MB cards */
321 if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024)) 320 if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
322 bpp_sel = 8; 321 bpp_sel = 8;
323 322
324 return drm_fb_helper_single_fb_probe(dev, bpp_sel, &radeon_fb_find_or_create_single); 323 return drm_fb_helper_single_fb_probe(&rfbdev->helper, bpp_sel);
325} 324}
326 325
327void radeonfb_hotplug(struct drm_device *dev) 326void radeonfb_hotplug(struct drm_device *dev)
328{ 327{
329 drm_helper_fb_hotplug_event(dev); 328 struct radeon_device *rdev = dev->dev_private;
329 int max_width, max_height;
330
331 max_width = rdev->mode_info.rfbdev->rfb.base.width;
332 max_height = rdev->mode_info.rfbdev->rfb.base.height;
333 drm_helper_fb_hotplug_event(&rdev->mode_info.rfbdev->helper, max_width, max_height);
330 334
331 radeonfb_probe(dev); 335 radeonfb_probe(rdev->mode_info.rfbdev);
332} 336}
333 337
334static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_kernel_fbdev *rfbdev) 338static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
335{ 339{
336 struct fb_info *info; 340 struct fb_info *info;
337 struct radeon_framebuffer *rfb = &rfbdev->rfb; 341 struct radeon_framebuffer *rfb = &rfbdev->rfb;
338 struct radeon_bo *rbo; 342 struct radeon_bo *rbo;
339 int r; 343 int r;
340 344
341 rbo = rfb->obj->driver_private; 345 if (rfbdev->helper.fbdev) {
342 info = rfbdev->helper.fbdev; 346 info = rfbdev->helper.fbdev;
343 unregister_framebuffer(info); 347 unregister_framebuffer(info);
344 r = radeon_bo_reserve(rbo, false); 348 framebuffer_release(info);
345 if (likely(r == 0)) {
346 radeon_bo_kunmap(rbo);
347 radeon_bo_unpin(rbo);
348 radeon_bo_unreserve(rbo);
349 } 349 }
350 350
351 if (rfb->obj) {
352 rbo = rfb->obj->driver_private;
353 r = radeon_bo_reserve(rbo, false);
354 if (likely(r == 0)) {
355 radeon_bo_kunmap(rbo);
356 radeon_bo_unpin(rbo);
357 radeon_bo_unreserve(rbo);
358 }
359 drm_gem_object_unreference_unlocked(rfb->obj);
360 }
351 drm_fb_helper_free(&rfbdev->helper); 361 drm_fb_helper_free(&rfbdev->helper);
352 drm_framebuffer_cleanup(&rfb->base); 362 drm_framebuffer_cleanup(&rfb->base);
353 if (rfb->obj)
354 drm_gem_object_unreference_unlocked(rfb->obj);
355
356 framebuffer_release(info);
357 363
358 return 0; 364 return 0;
359} 365}
@@ -361,14 +367,32 @@ MODULE_LICENSE("GPL");
361 367
362int radeon_fbdev_init(struct radeon_device *rdev) 368int radeon_fbdev_init(struct radeon_device *rdev)
363{ 369{
364 drm_helper_initial_config(rdev->ddev); 370 struct radeon_fbdev *rfbdev;
365 radeonfb_probe(rdev->ddev); 371
372 rfbdev = kzalloc(sizeof(struct radeon_fbdev), GFP_KERNEL);
373 if (!rfbdev)
374 return -ENOMEM;
375
376 rfbdev->rdev = rdev;
377 rdev->mode_info.rfbdev = rfbdev;
378
379 drm_fb_helper_init_crtc_count(rdev->ddev, &rfbdev->helper,
380 rdev->num_crtc,
381 RADEONFB_CONN_LIMIT);
382 rfbdev->helper.fb_probe = radeon_fb_find_or_create_single;
383 drm_fb_helper_initial_config(&rfbdev->helper);
384 radeonfb_probe(rfbdev);
366 return 0; 385 return 0;
386
367} 387}
368 388
369void radeon_fbdev_fini(struct radeon_device *rdev) 389void radeon_fbdev_fini(struct radeon_device *rdev)
370{ 390{
391 if (!rdev->mode_info.rfbdev)
392 return;
393
371 radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev); 394 radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev);
395 kfree(rdev->mode_info.rfbdev);
372 rdev->mode_info.rfbdev = NULL; 396 rdev->mode_info.rfbdev = NULL;
373} 397}
374 398