diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/radeon_fb.c')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fb.c | 87 |
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 | |||
42 | struct radeon_fb_device { | 45 | struct 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 | ||
290 | out_unref: | 295 | out_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 | ||
322 | int radeonfb_probe(struct drm_device *dev) | 331 | int 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 | ||
327 | int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb) | 343 | int 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 | } |