1 1.15 chs /* $NetBSD: radeon_fb.c,v 1.15 2021/12/20 20:34:58 chs Exp $ */ 2 1.6 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * Copyright 2007 David Airlie 5 1.1 riastrad * 6 1.1 riastrad * Permission is hereby granted, free of charge, to any person obtaining a 7 1.1 riastrad * copy of this software and associated documentation files (the "Software"), 8 1.1 riastrad * to deal in the Software without restriction, including without limitation 9 1.1 riastrad * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 1.1 riastrad * and/or sell copies of the Software, and to permit persons to whom the 11 1.1 riastrad * Software is furnished to do so, subject to the following conditions: 12 1.1 riastrad * 13 1.1 riastrad * The above copyright notice and this permission notice (including the next 14 1.1 riastrad * paragraph) shall be included in all copies or substantial portions of the 15 1.1 riastrad * Software. 16 1.1 riastrad * 17 1.1 riastrad * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 1.1 riastrad * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 1.1 riastrad * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 1.1 riastrad * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 1.1 riastrad * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 1.1 riastrad * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 1.1 riastrad * DEALINGS IN THE SOFTWARE. 24 1.1 riastrad * 25 1.1 riastrad * Authors: 26 1.1 riastrad * David Airlie 27 1.1 riastrad */ 28 1.11 riastrad 29 1.6 riastrad #include <sys/cdefs.h> 30 1.15 chs __KERNEL_RCSID(0, "$NetBSD: radeon_fb.c,v 1.15 2021/12/20 20:34:58 chs Exp $"); 31 1.6 riastrad 32 1.1 riastrad #include <linux/module.h> 33 1.11 riastrad #include <linux/pci.h> 34 1.11 riastrad #include <linux/pm_runtime.h> 35 1.1 riastrad #include <linux/slab.h> 36 1.11 riastrad #include <linux/vga_switcheroo.h> 37 1.1 riastrad 38 1.1 riastrad #include <drm/drm_crtc.h> 39 1.1 riastrad #include <drm/drm_crtc_helper.h> 40 1.11 riastrad #include <drm/drm_fb_helper.h> 41 1.11 riastrad #include <drm/drm_fourcc.h> 42 1.1 riastrad #include <drm/radeon_drm.h> 43 1.11 riastrad 44 1.1 riastrad #include "radeon.h" 45 1.1 riastrad 46 1.3 riastrad #ifdef __NetBSD__ 47 1.3 riastrad #include "radeondrmkmsfb.h" 48 1.8 riastrad 49 1.8 riastrad #include <linux/nbsd-namespace.h> 50 1.3 riastrad #endif 51 1.3 riastrad 52 1.1 riastrad /* object hierarchy - 53 1.11 riastrad * this contains a helper + a radeon fb 54 1.11 riastrad * the helper contains a pointer to radeon framebuffer baseclass. 55 1.11 riastrad */ 56 1.1 riastrad struct radeon_fbdev { 57 1.11 riastrad struct drm_fb_helper helper; /* must be first */ 58 1.11 riastrad struct drm_framebuffer fb; 59 1.1 riastrad struct radeon_device *rdev; 60 1.1 riastrad }; 61 1.1 riastrad 62 1.13 riastrad #ifndef __NetBSD__ 63 1.11 riastrad static int 64 1.11 riastrad radeonfb_open(struct fb_info *info, int user) 65 1.11 riastrad { 66 1.11 riastrad struct radeon_fbdev *rfbdev = info->par; 67 1.11 riastrad struct radeon_device *rdev = rfbdev->rdev; 68 1.11 riastrad int ret = pm_runtime_get_sync(rdev->ddev->dev); 69 1.11 riastrad if (ret < 0 && ret != -EACCES) { 70 1.11 riastrad pm_runtime_mark_last_busy(rdev->ddev->dev); 71 1.11 riastrad pm_runtime_put_autosuspend(rdev->ddev->dev); 72 1.11 riastrad return ret; 73 1.11 riastrad } 74 1.11 riastrad return 0; 75 1.11 riastrad } 76 1.11 riastrad 77 1.11 riastrad static int 78 1.11 riastrad radeonfb_release(struct fb_info *info, int user) 79 1.11 riastrad { 80 1.11 riastrad struct radeon_fbdev *rfbdev = info->par; 81 1.11 riastrad struct radeon_device *rdev = rfbdev->rdev; 82 1.11 riastrad 83 1.11 riastrad pm_runtime_mark_last_busy(rdev->ddev->dev); 84 1.11 riastrad pm_runtime_put_autosuspend(rdev->ddev->dev); 85 1.11 riastrad return 0; 86 1.11 riastrad } 87 1.11 riastrad 88 1.11 riastrad static const struct fb_ops radeonfb_ops = { 89 1.1 riastrad .owner = THIS_MODULE, 90 1.11 riastrad DRM_FB_HELPER_DEFAULT_OPS, 91 1.11 riastrad .fb_open = radeonfb_open, 92 1.11 riastrad .fb_release = radeonfb_release, 93 1.6 riastrad .fb_fillrect = drm_fb_helper_cfb_fillrect, 94 1.6 riastrad .fb_copyarea = drm_fb_helper_cfb_copyarea, 95 1.6 riastrad .fb_imageblit = drm_fb_helper_cfb_imageblit, 96 1.1 riastrad }; 97 1.2 riastrad #endif 98 1.1 riastrad 99 1.1 riastrad 100 1.11 riastrad int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool tiled) 101 1.1 riastrad { 102 1.1 riastrad int aligned = width; 103 1.1 riastrad int align_large = (ASIC_IS_AVIVO(rdev)) || tiled; 104 1.1 riastrad int pitch_mask = 0; 105 1.1 riastrad 106 1.11 riastrad switch (cpp) { 107 1.1 riastrad case 1: 108 1.1 riastrad pitch_mask = align_large ? 255 : 127; 109 1.1 riastrad break; 110 1.1 riastrad case 2: 111 1.1 riastrad pitch_mask = align_large ? 127 : 31; 112 1.1 riastrad break; 113 1.1 riastrad case 3: 114 1.1 riastrad case 4: 115 1.1 riastrad pitch_mask = align_large ? 63 : 15; 116 1.1 riastrad break; 117 1.1 riastrad } 118 1.1 riastrad 119 1.1 riastrad aligned += pitch_mask; 120 1.1 riastrad aligned &= ~pitch_mask; 121 1.11 riastrad return aligned * cpp; 122 1.1 riastrad } 123 1.1 riastrad 124 1.1 riastrad static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj) 125 1.1 riastrad { 126 1.1 riastrad struct radeon_bo *rbo = gem_to_radeon_bo(gobj); 127 1.1 riastrad int ret; 128 1.1 riastrad 129 1.1 riastrad ret = radeon_bo_reserve(rbo, false); 130 1.1 riastrad if (likely(ret == 0)) { 131 1.1 riastrad radeon_bo_kunmap(rbo); 132 1.1 riastrad radeon_bo_unpin(rbo); 133 1.1 riastrad radeon_bo_unreserve(rbo); 134 1.1 riastrad } 135 1.11 riastrad drm_gem_object_put_unlocked(gobj); 136 1.1 riastrad } 137 1.1 riastrad 138 1.1 riastrad static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev, 139 1.1 riastrad struct drm_mode_fb_cmd2 *mode_cmd, 140 1.1 riastrad struct drm_gem_object **gobj_p) 141 1.1 riastrad { 142 1.11 riastrad const struct drm_format_info *info; 143 1.1 riastrad struct radeon_device *rdev = rfbdev->rdev; 144 1.1 riastrad struct drm_gem_object *gobj = NULL; 145 1.1 riastrad struct radeon_bo *rbo = NULL; 146 1.1 riastrad bool fb_tiled = false; /* useful for testing */ 147 1.1 riastrad u32 tiling_flags = 0; 148 1.1 riastrad int ret; 149 1.1 riastrad int aligned_size, size; 150 1.1 riastrad int height = mode_cmd->height; 151 1.11 riastrad u32 cpp; 152 1.1 riastrad 153 1.11 riastrad info = drm_get_format_info(rdev->ddev, mode_cmd); 154 1.11 riastrad cpp = info->cpp[0]; 155 1.1 riastrad 156 1.1 riastrad /* need to align pitch with crtc limits */ 157 1.11 riastrad mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp, 158 1.11 riastrad fb_tiled); 159 1.1 riastrad 160 1.1 riastrad if (rdev->family >= CHIP_R600) 161 1.1 riastrad height = ALIGN(mode_cmd->height, 8); 162 1.1 riastrad size = mode_cmd->pitches[0] * height; 163 1.1 riastrad aligned_size = ALIGN(size, PAGE_SIZE); 164 1.1 riastrad ret = radeon_gem_object_create(rdev, aligned_size, 0, 165 1.1 riastrad RADEON_GEM_DOMAIN_VRAM, 166 1.6 riastrad 0, true, &gobj); 167 1.1 riastrad if (ret) { 168 1.11 riastrad pr_err("failed to allocate framebuffer (%d)\n", aligned_size); 169 1.1 riastrad return -ENOMEM; 170 1.1 riastrad } 171 1.1 riastrad rbo = gem_to_radeon_bo(gobj); 172 1.1 riastrad 173 1.1 riastrad if (fb_tiled) 174 1.1 riastrad tiling_flags = RADEON_TILING_MACRO; 175 1.1 riastrad 176 1.1 riastrad #ifdef __BIG_ENDIAN 177 1.11 riastrad switch (cpp) { 178 1.11 riastrad case 4: 179 1.1 riastrad tiling_flags |= RADEON_TILING_SWAP_32BIT; 180 1.1 riastrad break; 181 1.11 riastrad case 2: 182 1.1 riastrad tiling_flags |= RADEON_TILING_SWAP_16BIT; 183 1.1 riastrad default: 184 1.1 riastrad break; 185 1.1 riastrad } 186 1.1 riastrad #endif 187 1.1 riastrad 188 1.1 riastrad if (tiling_flags) { 189 1.1 riastrad ret = radeon_bo_set_tiling_flags(rbo, 190 1.1 riastrad tiling_flags | RADEON_TILING_SURFACE, 191 1.1 riastrad mode_cmd->pitches[0]); 192 1.1 riastrad if (ret) 193 1.1 riastrad dev_err(rdev->dev, "FB failed to set tiling flags\n"); 194 1.1 riastrad } 195 1.1 riastrad 196 1.1 riastrad 197 1.1 riastrad ret = radeon_bo_reserve(rbo, false); 198 1.1 riastrad if (unlikely(ret != 0)) 199 1.1 riastrad goto out_unref; 200 1.1 riastrad /* Only 27 bit offset for legacy CRTC */ 201 1.1 riastrad ret = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM, 202 1.1 riastrad ASIC_IS_AVIVO(rdev) ? 0 : 1 << 27, 203 1.1 riastrad NULL); 204 1.1 riastrad if (ret) { 205 1.1 riastrad radeon_bo_unreserve(rbo); 206 1.1 riastrad goto out_unref; 207 1.1 riastrad } 208 1.1 riastrad if (fb_tiled) 209 1.1 riastrad radeon_bo_check_tiling(rbo, 0, 0); 210 1.1 riastrad ret = radeon_bo_kmap(rbo, NULL); 211 1.1 riastrad radeon_bo_unreserve(rbo); 212 1.1 riastrad if (ret) { 213 1.1 riastrad goto out_unref; 214 1.1 riastrad } 215 1.1 riastrad 216 1.1 riastrad *gobj_p = gobj; 217 1.1 riastrad return 0; 218 1.1 riastrad out_unref: 219 1.1 riastrad radeonfb_destroy_pinned_object(gobj); 220 1.1 riastrad *gobj_p = NULL; 221 1.1 riastrad return ret; 222 1.1 riastrad } 223 1.1 riastrad 224 1.1 riastrad static int radeonfb_create(struct drm_fb_helper *helper, 225 1.1 riastrad struct drm_fb_helper_surface_size *sizes) 226 1.1 riastrad { 227 1.6 riastrad struct radeon_fbdev *rfbdev = 228 1.6 riastrad container_of(helper, struct radeon_fbdev, helper); 229 1.1 riastrad struct radeon_device *rdev = rfbdev->rdev; 230 1.2 riastrad #ifndef __NetBSD__ 231 1.1 riastrad struct fb_info *info; 232 1.2 riastrad #endif 233 1.1 riastrad struct drm_framebuffer *fb = NULL; 234 1.1 riastrad struct drm_mode_fb_cmd2 mode_cmd; 235 1.1 riastrad struct drm_gem_object *gobj = NULL; 236 1.1 riastrad struct radeon_bo *rbo = NULL; 237 1.1 riastrad int ret; 238 1.2 riastrad #ifndef __NetBSD__ 239 1.1 riastrad unsigned long tmp; 240 1.2 riastrad #endif 241 1.1 riastrad 242 1.1 riastrad mode_cmd.width = sizes->surface_width; 243 1.1 riastrad mode_cmd.height = sizes->surface_height; 244 1.1 riastrad 245 1.1 riastrad /* avivo can't scanout real 24bpp */ 246 1.1 riastrad if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)) 247 1.1 riastrad sizes->surface_bpp = 32; 248 1.1 riastrad 249 1.1 riastrad mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 250 1.1 riastrad sizes->surface_depth); 251 1.1 riastrad 252 1.1 riastrad ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj); 253 1.1 riastrad if (ret) { 254 1.1 riastrad DRM_ERROR("failed to create fbcon object %d\n", ret); 255 1.1 riastrad return ret; 256 1.1 riastrad } 257 1.1 riastrad 258 1.1 riastrad rbo = gem_to_radeon_bo(gobj); 259 1.1 riastrad 260 1.2 riastrad #ifdef __NetBSD__ 261 1.12 riastrad ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->fb, &mode_cmd, gobj); 262 1.2 riastrad if (ret) { 263 1.2 riastrad DRM_ERROR("failed to initialize framebuffer %d\n", ret); 264 1.12 riastrad goto out; 265 1.2 riastrad } 266 1.2 riastrad 267 1.2 riastrad (void)memset(rbo->kptr, 0, radeon_bo_size(rbo)); 268 1.3 riastrad 269 1.3 riastrad { 270 1.3 riastrad static const struct radeonfb_attach_args zero_rfa; 271 1.3 riastrad struct radeonfb_attach_args rfa = zero_rfa; 272 1.3 riastrad 273 1.3 riastrad rfa.rfa_fb_helper = helper; 274 1.3 riastrad rfa.rfa_fb_sizes = *sizes; 275 1.3 riastrad rfa.rfa_fb_ptr = rbo->kptr; 276 1.5 nonaka rfa.rfa_fb_linebytes = mode_cmd.pitches[0]; 277 1.3 riastrad 278 1.15 chs KERNEL_LOCK(1, NULL); 279 1.9 thorpej helper->fbdev = config_found(rdev->ddev->dev, &rfa, NULL, 280 1.10 thorpej CFARGS(.iattr = "radeonfbbus")); 281 1.15 chs KERNEL_UNLOCK_ONE(NULL); 282 1.3 riastrad if (helper->fbdev == NULL) { 283 1.3 riastrad DRM_ERROR("failed to attach genfb\n"); 284 1.12 riastrad goto out; 285 1.2 riastrad } 286 1.3 riastrad } 287 1.12 riastrad fb = &rfbdev->fb; 288 1.2 riastrad rfbdev->helper.fb = fb; 289 1.2 riastrad #else 290 1.1 riastrad /* okay we have an object now allocate the framebuffer */ 291 1.6 riastrad info = drm_fb_helper_alloc_fbi(helper); 292 1.6 riastrad if (IS_ERR(info)) { 293 1.6 riastrad ret = PTR_ERR(info); 294 1.11 riastrad goto out; 295 1.1 riastrad } 296 1.1 riastrad 297 1.11 riastrad /* radeon resume is fragile and needs a vt switch to help it along */ 298 1.11 riastrad info->skip_vt_switch = false; 299 1.1 riastrad 300 1.11 riastrad ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->fb, &mode_cmd, gobj); 301 1.1 riastrad if (ret) { 302 1.1 riastrad DRM_ERROR("failed to initialize framebuffer %d\n", ret); 303 1.11 riastrad goto out; 304 1.1 riastrad } 305 1.1 riastrad 306 1.11 riastrad fb = &rfbdev->fb; 307 1.1 riastrad 308 1.1 riastrad /* setup helper */ 309 1.1 riastrad rfbdev->helper.fb = fb; 310 1.1 riastrad 311 1.1 riastrad memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo)); 312 1.1 riastrad 313 1.1 riastrad info->fbops = &radeonfb_ops; 314 1.1 riastrad 315 1.1 riastrad tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start; 316 1.1 riastrad info->fix.smem_start = rdev->mc.aper_base + tmp; 317 1.1 riastrad info->fix.smem_len = radeon_bo_size(rbo); 318 1.1 riastrad info->screen_base = rbo->kptr; 319 1.1 riastrad info->screen_size = radeon_bo_size(rbo); 320 1.1 riastrad 321 1.11 riastrad drm_fb_helper_fill_info(info, &rfbdev->helper, sizes); 322 1.1 riastrad 323 1.1 riastrad /* setup aperture base/size for vesafb takeover */ 324 1.1 riastrad info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base; 325 1.1 riastrad info->apertures->ranges[0].size = rdev->mc.aper_size; 326 1.1 riastrad 327 1.1 riastrad /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */ 328 1.1 riastrad 329 1.1 riastrad if (info->screen_base == NULL) { 330 1.1 riastrad ret = -ENOSPC; 331 1.11 riastrad goto out; 332 1.1 riastrad } 333 1.1 riastrad 334 1.1 riastrad DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start); 335 1.1 riastrad DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base); 336 1.1 riastrad DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo)); 337 1.11 riastrad DRM_INFO("fb depth is %d\n", fb->format->depth); 338 1.1 riastrad DRM_INFO(" pitch is %d\n", fb->pitches[0]); 339 1.1 riastrad 340 1.1 riastrad vga_switcheroo_client_fb_set(rdev->ddev->pdev, info); 341 1.2 riastrad #endif 342 1.1 riastrad return 0; 343 1.1 riastrad 344 1.11 riastrad out: 345 1.1 riastrad if (rbo) { 346 1.1 riastrad 347 1.1 riastrad } 348 1.1 riastrad if (fb && ret) { 349 1.11 riastrad drm_gem_object_put_unlocked(gobj); 350 1.1 riastrad drm_framebuffer_unregister_private(fb); 351 1.1 riastrad drm_framebuffer_cleanup(fb); 352 1.1 riastrad kfree(fb); 353 1.1 riastrad } 354 1.1 riastrad return ret; 355 1.1 riastrad } 356 1.1 riastrad 357 1.1 riastrad static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev) 358 1.1 riastrad { 359 1.13 riastrad struct drm_framebuffer *fb = &rfbdev->fb; 360 1.1 riastrad 361 1.6 riastrad drm_fb_helper_unregister_fbi(&rfbdev->helper); 362 1.1 riastrad 363 1.11 riastrad if (fb->obj[0]) { 364 1.11 riastrad radeonfb_destroy_pinned_object(fb->obj[0]); 365 1.11 riastrad fb->obj[0] = NULL; 366 1.11 riastrad drm_framebuffer_unregister_private(fb); 367 1.11 riastrad drm_framebuffer_cleanup(fb); 368 1.1 riastrad } 369 1.1 riastrad drm_fb_helper_fini(&rfbdev->helper); 370 1.1 riastrad 371 1.1 riastrad return 0; 372 1.1 riastrad } 373 1.1 riastrad 374 1.6 riastrad static const struct drm_fb_helper_funcs radeon_fb_helper_funcs = { 375 1.1 riastrad .fb_probe = radeonfb_create, 376 1.1 riastrad }; 377 1.1 riastrad 378 1.1 riastrad int radeon_fbdev_init(struct radeon_device *rdev) 379 1.1 riastrad { 380 1.1 riastrad struct radeon_fbdev *rfbdev; 381 1.1 riastrad int bpp_sel = 32; 382 1.1 riastrad int ret; 383 1.1 riastrad 384 1.11 riastrad /* don't enable fbdev if no connectors */ 385 1.11 riastrad if (list_empty(&rdev->ddev->mode_config.connector_list)) 386 1.11 riastrad return 0; 387 1.11 riastrad 388 1.11 riastrad /* select 8 bpp console on 8MB cards, or 16 bpp on RN50 or 32MB */ 389 1.11 riastrad if (rdev->mc.real_vram_size <= (8*1024*1024)) 390 1.1 riastrad bpp_sel = 8; 391 1.11 riastrad else if (ASIC_IS_RN50(rdev) || 392 1.11 riastrad rdev->mc.real_vram_size <= (32*1024*1024)) 393 1.11 riastrad bpp_sel = 16; 394 1.1 riastrad 395 1.1 riastrad rfbdev = kzalloc(sizeof(struct radeon_fbdev), GFP_KERNEL); 396 1.1 riastrad if (!rfbdev) 397 1.1 riastrad return -ENOMEM; 398 1.1 riastrad 399 1.1 riastrad rfbdev->rdev = rdev; 400 1.1 riastrad rdev->mode_info.rfbdev = rfbdev; 401 1.6 riastrad 402 1.6 riastrad drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper, 403 1.6 riastrad &radeon_fb_helper_funcs); 404 1.1 riastrad 405 1.1 riastrad ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper, 406 1.1 riastrad RADEONFB_CONN_LIMIT); 407 1.6 riastrad if (ret) 408 1.6 riastrad goto free; 409 1.1 riastrad 410 1.6 riastrad ret = drm_fb_helper_single_add_all_connectors(&rfbdev->helper); 411 1.6 riastrad if (ret) 412 1.6 riastrad goto fini; 413 1.1 riastrad 414 1.1 riastrad /* disable all the possible outputs/crtcs before entering KMS mode */ 415 1.1 riastrad drm_helper_disable_unused_functions(rdev->ddev); 416 1.1 riastrad 417 1.6 riastrad ret = drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel); 418 1.6 riastrad if (ret) 419 1.6 riastrad goto fini; 420 1.6 riastrad 421 1.1 riastrad return 0; 422 1.6 riastrad 423 1.6 riastrad fini: 424 1.6 riastrad drm_fb_helper_fini(&rfbdev->helper); 425 1.6 riastrad free: 426 1.6 riastrad kfree(rfbdev); 427 1.6 riastrad return ret; 428 1.1 riastrad } 429 1.1 riastrad 430 1.1 riastrad void radeon_fbdev_fini(struct radeon_device *rdev) 431 1.1 riastrad { 432 1.1 riastrad if (!rdev->mode_info.rfbdev) 433 1.1 riastrad return; 434 1.1 riastrad 435 1.1 riastrad radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev); 436 1.1 riastrad kfree(rdev->mode_info.rfbdev); 437 1.1 riastrad rdev->mode_info.rfbdev = NULL; 438 1.1 riastrad } 439 1.1 riastrad 440 1.1 riastrad void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state) 441 1.1 riastrad { 442 1.2 riastrad #ifndef __NetBSD__ /* XXX radeon fb suspend */ 443 1.11 riastrad if (rdev->mode_info.rfbdev) 444 1.11 riastrad drm_fb_helper_set_suspend(&rdev->mode_info.rfbdev->helper, state); 445 1.2 riastrad #endif 446 1.1 riastrad } 447 1.1 riastrad 448 1.6 riastrad bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj) 449 1.6 riastrad { 450 1.11 riastrad if (!rdev->mode_info.rfbdev) 451 1.11 riastrad return false; 452 1.11 riastrad 453 1.11 riastrad if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->fb.obj[0])) 454 1.6 riastrad return true; 455 1.6 riastrad return false; 456 1.6 riastrad } 457 1.6 riastrad 458 1.6 riastrad void radeon_fb_add_connector(struct radeon_device *rdev, struct drm_connector *connector) 459 1.1 riastrad { 460 1.11 riastrad if (rdev->mode_info.rfbdev) 461 1.11 riastrad drm_fb_helper_add_one_connector(&rdev->mode_info.rfbdev->helper, connector); 462 1.6 riastrad } 463 1.1 riastrad 464 1.6 riastrad void radeon_fb_remove_connector(struct radeon_device *rdev, struct drm_connector *connector) 465 1.6 riastrad { 466 1.11 riastrad if (rdev->mode_info.rfbdev) 467 1.11 riastrad drm_fb_helper_remove_one_connector(&rdev->mode_info.rfbdev->helper, connector); 468 1.1 riastrad } 469