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.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c
index b38c4c8e2c61..9ac57a09784b 100644
--- a/drivers/gpu/drm/radeon/radeon_fb.c
+++ b/drivers/gpu/drm/radeon/radeon_fb.c
@@ -28,6 +28,7 @@
28 */ 28 */
29 29
30#include <linux/module.h> 30#include <linux/module.h>
31#include <linux/slab.h>
31#include <linux/fb.h> 32#include <linux/fb.h>
32 33
33#include "drmP.h" 34#include "drmP.h"
@@ -39,6 +40,8 @@
39 40
40#include "drm_fb_helper.h" 41#include "drm_fb_helper.h"
41 42
43#include <linux/vga_switcheroo.h>
44
42struct radeon_fb_device { 45struct radeon_fb_device {
43 struct drm_fb_helper helper; 46 struct drm_fb_helper helper;
44 struct radeon_framebuffer *rfb; 47 struct radeon_framebuffer *rfb;
@@ -59,7 +62,7 @@ static struct fb_ops radeonfb_ops = {
59}; 62};
60 63
61/** 64/**
62 * Curretly it is assumed that the old framebuffer is reused. 65 * Currently it is assumed that the old framebuffer is reused.
63 * 66 *
64 * LOCKING 67 * LOCKING
65 * caller should hold the mode config lock. 68 * caller should hold the mode config lock.
@@ -140,7 +143,7 @@ int radeonfb_create(struct drm_device *dev,
140 struct radeon_framebuffer *rfb; 143 struct radeon_framebuffer *rfb;
141 struct drm_mode_fb_cmd mode_cmd; 144 struct drm_mode_fb_cmd mode_cmd;
142 struct drm_gem_object *gobj = NULL; 145 struct drm_gem_object *gobj = NULL;
143 struct radeon_object *robj = NULL; 146 struct radeon_bo *rbo = NULL;
144 struct device *device = &rdev->pdev->dev; 147 struct device *device = &rdev->pdev->dev;
145 int size, aligned_size, ret; 148 int size, aligned_size, ret;
146 u64 fb_gpuaddr; 149 u64 fb_gpuaddr;
@@ -148,7 +151,6 @@ int radeonfb_create(struct drm_device *dev,
148 unsigned long tmp; 151 unsigned long tmp;
149 bool fb_tiled = false; /* useful for testing */ 152 bool fb_tiled = false; /* useful for testing */
150 u32 tiling_flags = 0; 153 u32 tiling_flags = 0;
151 int crtc_count;
152 154
153 mode_cmd.width = surface_width; 155 mode_cmd.width = surface_width;
154 mode_cmd.height = surface_height; 156 mode_cmd.height = surface_height;
@@ -168,14 +170,14 @@ int radeonfb_create(struct drm_device *dev,
168 ret = radeon_gem_object_create(rdev, aligned_size, 0, 170 ret = radeon_gem_object_create(rdev, aligned_size, 0,
169 RADEON_GEM_DOMAIN_VRAM, 171 RADEON_GEM_DOMAIN_VRAM,
170 false, ttm_bo_type_kernel, 172 false, ttm_bo_type_kernel,
171 false, &gobj); 173 &gobj);
172 if (ret) { 174 if (ret) {
173 printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n", 175 printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
174 surface_width, surface_height); 176 surface_width, surface_height);
175 ret = -ENOMEM; 177 ret = -ENOMEM;
176 goto out; 178 goto out;
177 } 179 }
178 robj = gobj->driver_private; 180 rbo = gobj->driver_private;
179 181
180 if (fb_tiled) 182 if (fb_tiled)
181 tiling_flags = RADEON_TILING_MACRO; 183 tiling_flags = RADEON_TILING_MACRO;
@@ -192,8 +194,13 @@ int radeonfb_create(struct drm_device *dev,
192 } 194 }
193#endif 195#endif
194 196
195 if (tiling_flags) 197 if (tiling_flags) {
196 radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch); 198 ret = radeon_bo_set_tiling_flags(rbo,
199 tiling_flags | RADEON_TILING_SURFACE,
200 mode_cmd.pitch);
201 if (ret)
202 dev_err(rdev->dev, "FB failed to set tiling flags\n");
203 }
197 mutex_lock(&rdev->ddev->struct_mutex); 204 mutex_lock(&rdev->ddev->struct_mutex);
198 fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); 205 fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
199 if (fb == NULL) { 206 if (fb == NULL) {
@@ -201,10 +208,19 @@ int radeonfb_create(struct drm_device *dev,
201 ret = -ENOMEM; 208 ret = -ENOMEM;
202 goto out_unref; 209 goto out_unref;
203 } 210 }
204 ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr); 211 ret = radeon_bo_reserve(rbo, false);
212 if (unlikely(ret != 0))
213 goto out_unref;
214 ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
215 if (ret) {
216 radeon_bo_unreserve(rbo);
217 goto out_unref;
218 }
219 if (fb_tiled)
220 radeon_bo_check_tiling(rbo, 0, 0);
221 ret = radeon_bo_kmap(rbo, &fbptr);
222 radeon_bo_unreserve(rbo);
205 if (ret) { 223 if (ret) {
206 printk(KERN_ERR "failed to pin framebuffer\n");
207 ret = -ENOMEM;
208 goto out_unref; 224 goto out_unref;
209 } 225 }
210 226
@@ -213,7 +229,7 @@ int radeonfb_create(struct drm_device *dev,
213 *fb_p = fb; 229 *fb_p = fb;
214 rfb = to_radeon_framebuffer(fb); 230 rfb = to_radeon_framebuffer(fb);
215 rdev->fbdev_rfb = rfb; 231 rdev->fbdev_rfb = rfb;
216 rdev->fbdev_robj = robj; 232 rdev->fbdev_rbo = rbo;
217 233
218 info = framebuffer_alloc(sizeof(struct radeon_fb_device), device); 234 info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
219 if (info == NULL) { 235 if (info == NULL) {
@@ -225,24 +241,12 @@ int radeonfb_create(struct drm_device *dev,
225 rfbdev = info->par; 241 rfbdev = info->par;
226 rfbdev->helper.funcs = &radeon_fb_helper_funcs; 242 rfbdev->helper.funcs = &radeon_fb_helper_funcs;
227 rfbdev->helper.dev = dev; 243 rfbdev->helper.dev = dev;
228 if (rdev->flags & RADEON_SINGLE_CRTC) 244 ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, rdev->num_crtc,
229 crtc_count = 1;
230 else
231 crtc_count = 2;
232 ret = drm_fb_helper_init_crtc_count(&rfbdev->helper, crtc_count,
233 RADEONFB_CONN_LIMIT); 245 RADEONFB_CONN_LIMIT);
234 if (ret) 246 if (ret)
235 goto out_unref; 247 goto out_unref;
236 248
237 if (fb_tiled) 249 memset_io(fbptr, 0x0, aligned_size);
238 radeon_object_check_tiling(robj, 0, 0);
239
240 ret = radeon_object_kmap(robj, &fbptr);
241 if (ret) {
242 goto out_unref;
243 }
244
245 memset_io(fbptr, 0, aligned_size);
246 250
247 strcpy(info->fix.id, "radeondrmfb"); 251 strcpy(info->fix.id, "radeondrmfb");
248 252
@@ -251,7 +255,7 @@ int radeonfb_create(struct drm_device *dev,
251 info->flags = FBINFO_DEFAULT; 255 info->flags = FBINFO_DEFAULT;
252 info->fbops = &radeonfb_ops; 256 info->fbops = &radeonfb_ops;
253 257
254 tmp = fb_gpuaddr - rdev->mc.vram_location; 258 tmp = fb_gpuaddr - rdev->mc.vram_start;
255 info->fix.smem_start = rdev->mc.aper_base + tmp; 259 info->fix.smem_start = rdev->mc.aper_base + tmp;
256 info->fix.smem_len = size; 260 info->fix.smem_len = size;
257 info->screen_base = fbptr; 261 info->screen_base = fbptr;
@@ -285,11 +289,16 @@ int radeonfb_create(struct drm_device *dev,
285 rfbdev->rdev = rdev; 289 rfbdev->rdev = rdev;
286 290
287 mutex_unlock(&rdev->ddev->struct_mutex); 291 mutex_unlock(&rdev->ddev->struct_mutex);
292 vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
288 return 0; 293 return 0;
289 294
290out_unref: 295out_unref:
291 if (robj) { 296 if (rbo) {
292 radeon_object_kunmap(robj); 297 ret = radeon_bo_reserve(rbo, false);
298 if (likely(ret == 0)) {
299 radeon_bo_kunmap(rbo);
300 radeon_bo_unreserve(rbo);
301 }
293 } 302 }
294 if (fb && ret) { 303 if (fb && ret) {
295 list_del(&fb->filp_head); 304 list_del(&fb->filp_head);
@@ -321,14 +330,22 @@ int radeon_parse_options(char *options)
321 330
322int radeonfb_probe(struct drm_device *dev) 331int radeonfb_probe(struct drm_device *dev)
323{ 332{
324 return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create); 333 struct radeon_device *rdev = dev->dev_private;
334 int bpp_sel = 32;
335
336 /* select 8 bpp console on RN50 or 16MB cards */
337 if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
338 bpp_sel = 8;
339
340 return drm_fb_helper_single_fb_probe(dev, bpp_sel, &radeonfb_create);
325} 341}
326 342
327int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) 343int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
328{ 344{
329 struct fb_info *info; 345 struct fb_info *info;
330 struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb); 346 struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
331 struct radeon_object *robj; 347 struct radeon_bo *rbo;
348 int r;
332 349
333 if (!fb) { 350 if (!fb) {
334 return -EINVAL; 351 return -EINVAL;
@@ -336,10 +353,14 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
336 info = fb->fbdev; 353 info = fb->fbdev;
337 if (info) { 354 if (info) {
338 struct radeon_fb_device *rfbdev = info->par; 355 struct radeon_fb_device *rfbdev = info->par;
339 robj = rfb->obj->driver_private; 356 rbo = rfb->obj->driver_private;
340 unregister_framebuffer(info); 357 unregister_framebuffer(info);
341 radeon_object_kunmap(robj); 358 r = radeon_bo_reserve(rbo, false);
342 radeon_object_unpin(robj); 359 if (likely(r == 0)) {
360 radeon_bo_kunmap(rbo);
361 radeon_bo_unpin(rbo);
362 radeon_bo_unreserve(rbo);
363 }
343 drm_fb_helper_free(&rfbdev->helper); 364 drm_fb_helper_free(&rfbdev->helper);
344 framebuffer_release(info); 365 framebuffer_release(info);
345 } 366 }