儲存庫 vbox 的更動 67397
- 時間撮記:
- 2017-6-14 下午12:56:01 (7 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Additions/linux/drm/vbox_fb.c
r66544 r67397 47 47 #include <linux/init.h> 48 48 49 50 49 #include <drm/drmP.h> 51 50 #include <drm/drm_crtc.h> … … 59 58 */ 60 59 static void vbox_dirty_update(struct vbox_fbdev *fbdev, 61 int x, int y, int width, int height) 62 { 63 struct drm_gem_object *obj; 64 struct vbox_bo *bo; 65 int ret = -EBUSY; 66 bool store_for_later = false; 67 int x2, y2; 68 unsigned long flags; 69 struct drm_clip_rect rect; 70 71 obj = fbdev->afb.obj; 72 bo = gem_to_vbox_bo(obj); 73 74 /* 75 * try and reserve the BO, if we fail with busy 76 * then the BO is being moved and we should 77 * store up the damage until later. 78 */ 79 if (drm_can_sleep()) 80 ret = vbox_bo_reserve(bo, true); 81 if (ret) { 82 if (ret != -EBUSY) 83 return; 84 85 store_for_later = true; 86 } 87 88 x2 = x + width - 1; 89 y2 = y + height - 1; 90 spin_lock_irqsave(&fbdev->dirty_lock, flags); 91 92 if (fbdev->y1 < y) 93 y = fbdev->y1; 94 if (fbdev->y2 > y2) 95 y2 = fbdev->y2; 96 if (fbdev->x1 < x) 97 x = fbdev->x1; 98 if (fbdev->x2 > x2) 99 x2 = fbdev->x2; 100 101 if (store_for_later) { 102 fbdev->x1 = x; 103 fbdev->x2 = x2; 104 fbdev->y1 = y; 105 fbdev->y2 = y2; 106 spin_unlock_irqrestore(&fbdev->dirty_lock, flags); 107 return; 108 } 109 110 fbdev->x1 = fbdev->y1 = INT_MAX; 111 fbdev->x2 = fbdev->y2 = 0; 112 spin_unlock_irqrestore(&fbdev->dirty_lock, flags); 113 114 /* Not sure why the original code subtracted 1 here, but I will keep it that 115 * way to avoid unnecessary differences. */ 116 rect.x1 = x; 117 rect.x2 = x2 + 1; 118 rect.y1 = y; 119 rect.y2 = y2 + 1; 120 vbox_framebuffer_dirty_rectangles(&fbdev->afb.base, &rect, 1); 121 122 vbox_bo_unreserve(bo); 60 int x, int y, int width, int height) 61 { 62 struct drm_gem_object *obj; 63 struct vbox_bo *bo; 64 int ret = -EBUSY; 65 bool store_for_later = false; 66 int x2, y2; 67 unsigned long flags; 68 struct drm_clip_rect rect; 69 70 obj = fbdev->afb.obj; 71 bo = gem_to_vbox_bo(obj); 72 73 /* 74 * try and reserve the BO, if we fail with busy 75 * then the BO is being moved and we should 76 * store up the damage until later. 77 */ 78 if (drm_can_sleep()) 79 ret = vbox_bo_reserve(bo, true); 80 if (ret) { 81 if (ret != -EBUSY) 82 return; 83 84 store_for_later = true; 85 } 86 87 x2 = x + width - 1; 88 y2 = y + height - 1; 89 spin_lock_irqsave(&fbdev->dirty_lock, flags); 90 91 if (fbdev->y1 < y) 92 y = fbdev->y1; 93 if (fbdev->y2 > y2) 94 y2 = fbdev->y2; 95 if (fbdev->x1 < x) 96 x = fbdev->x1; 97 if (fbdev->x2 > x2) 98 x2 = fbdev->x2; 99 100 if (store_for_later) { 101 fbdev->x1 = x; 102 fbdev->x2 = x2; 103 fbdev->y1 = y; 104 fbdev->y2 = y2; 105 spin_unlock_irqrestore(&fbdev->dirty_lock, flags); 106 return; 107 } 108 109 fbdev->x1 = INT_MAX; 110 fbdev->y1 = INT_MAX; 111 fbdev->x2 = 0; 112 fbdev->y2 = 0; 113 114 spin_unlock_irqrestore(&fbdev->dirty_lock, flags); 115 116 /* 117 * Not sure why the original code subtracted 1 here, but I will keep 118 * it that way to avoid unnecessary differences. 119 */ 120 rect.x1 = x; 121 rect.x2 = x2 + 1; 122 rect.y1 = y; 123 rect.y2 = y2 + 1; 124 vbox_framebuffer_dirty_rectangles(&fbdev->afb.base, &rect, 1); 125 126 vbox_bo_unreserve(bo); 123 127 } 124 128 125 129 #ifdef CONFIG_FB_DEFERRED_IO 126 static void vbox_deferred_io(struct fb_info *info, 127 struct list_head *pagelist) 128 { 129 struct vbox_fbdev *fbdev = info->par; 130 unsigned long start, end, min, max; 131 struct page *page; 132 int y1, y2; 133 134 min = ULONG_MAX; 135 max = 0; 136 list_for_each_entry(page, pagelist, lru) { 137 start = page->index << PAGE_SHIFT; 138 end = start + PAGE_SIZE - 1; 139 min = min(min, start); 140 max = max(max, end); 141 } 142 143 if (min < max) { 144 y1 = min / info->fix.line_length; 145 y2 = (max / info->fix.line_length) + 1; 146 printk(KERN_INFO "%s: Calling dirty update: 0, %d, %d, %d\n", 147 __func__, y1, info->var.xres, y2 - y1 - 1); 148 vbox_dirty_update(fbdev, 0, y1, info->var.xres, y2 - y1 - 1); 149 } 150 } 151 152 static struct fb_deferred_io vbox_defio = 153 { 154 .delay = VBOX_DIRTY_DELAY, 155 .deferred_io = vbox_deferred_io, 130 static void vbox_deferred_io(struct fb_info *info, struct list_head *pagelist) 131 { 132 struct vbox_fbdev *fbdev = info->par; 133 unsigned long start, end, min, max; 134 struct page *page; 135 int y1, y2; 136 137 min = ULONG_MAX; 138 max = 0; 139 list_for_each_entry(page, pagelist, lru) { 140 start = page->index << PAGE_SHIFT; 141 end = start + PAGE_SIZE - 1; 142 min = min(min, start); 143 max = max(max, end); 144 } 145 146 if (min < max) { 147 y1 = min / info->fix.line_length; 148 y2 = (max / info->fix.line_length) + 1; 149 DRM_INFO("%s: Calling dirty update: 0, %d, %d, %d\n", 150 __func__, y1, info->var.xres, y2 - y1 - 1); 151 vbox_dirty_update(fbdev, 0, y1, info->var.xres, y2 - y1 - 1); 152 } 153 } 154 155 static struct fb_deferred_io vbox_defio = { 156 .delay = VBOX_DIRTY_DELAY, 157 .deferred_io = vbox_deferred_io, 156 158 }; 157 159 #endif 158 160 159 static void vbox_fillrect(struct fb_info *info, 160 const struct fb_fillrect *rect) 161 { 162 struct vbox_fbdev *fbdev = info->par; 163 sys_fillrect(info, rect); 164 vbox_dirty_update(fbdev, rect->dx, rect->dy, rect->width, 165 rect->height); 166 } 167 168 static void vbox_copyarea(struct fb_info *info, 169 const struct fb_copyarea *area) 170 { 171 struct vbox_fbdev *fbdev = info->par; 172 sys_copyarea(info, area); 173 vbox_dirty_update(fbdev, area->dx, area->dy, area->width, 174 area->height); 175 } 176 177 static void vbox_imageblit(struct fb_info *info, 178 const struct fb_image *image) 179 { 180 struct vbox_fbdev *fbdev = info->par; 181 sys_imageblit(info, image); 182 vbox_dirty_update(fbdev, image->dx, image->dy, image->width, 183 image->height); 161 static void vbox_fillrect(struct fb_info *info, const struct fb_fillrect *rect) 162 { 163 struct vbox_fbdev *fbdev = info->par; 164 165 sys_fillrect(info, rect); 166 vbox_dirty_update(fbdev, rect->dx, rect->dy, rect->width, rect->height); 167 } 168 169 static void vbox_copyarea(struct fb_info *info, const struct fb_copyarea *area) 170 { 171 struct vbox_fbdev *fbdev = info->par; 172 173 sys_copyarea(info, area); 174 vbox_dirty_update(fbdev, area->dx, area->dy, area->width, area->height); 175 } 176 177 static void vbox_imageblit(struct fb_info *info, const struct fb_image *image) 178 { 179 struct vbox_fbdev *fbdev = info->par; 180 181 sys_imageblit(info, image); 182 vbox_dirty_update(fbdev, image->dx, image->dy, image->width, 183 image->height); 184 184 } 185 185 186 186 static struct fb_ops vboxfb_ops = { 187 188 189 190 191 192 193 194 195 196 197 187 .owner = THIS_MODULE, 188 .fb_check_var = drm_fb_helper_check_var, 189 .fb_set_par = drm_fb_helper_set_par, 190 .fb_fillrect = vbox_fillrect, 191 .fb_copyarea = vbox_copyarea, 192 .fb_imageblit = vbox_imageblit, 193 .fb_pan_display = drm_fb_helper_pan_display, 194 .fb_blank = drm_fb_helper_blank, 195 .fb_setcmap = drm_fb_helper_setcmap, 196 .fb_debug_enter = drm_fb_helper_debug_enter, 197 .fb_debug_leave = drm_fb_helper_debug_leave, 198 198 }; 199 199 200 200 static int vboxfb_create_object(struct vbox_fbdev *fbdev, 201 202 203 { 204 205 206 201 struct DRM_MODE_FB_CMD *mode_cmd, 202 struct drm_gem_object **gobj_p) 203 { 204 struct drm_device *dev = fbdev->helper.dev; 205 u32 size; 206 struct drm_gem_object *gobj; 207 207 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 208 __u32 pitch = mode_cmd->pitch;208 u32 pitch = mode_cmd->pitch; 209 209 #else 210 __u32 pitch = mode_cmd->pitches[0];211 #endif 212 213 214 215 216 217 218 219 220 221 210 u32 pitch = mode_cmd->pitches[0]; 211 #endif 212 213 int ret = 0; 214 215 size = pitch * mode_cmd->height; 216 ret = vbox_gem_create(dev, size, true, &gobj); 217 if (ret) 218 return ret; 219 220 *gobj_p = gobj; 221 return ret; 222 222 } 223 223 224 224 static int vboxfb_create(struct drm_fb_helper *helper, 225 struct drm_fb_helper_surface_size *sizes) 226 { 227 struct vbox_fbdev *fbdev = 228 container_of(helper, struct vbox_fbdev, helper); 229 struct drm_device *dev = fbdev->helper.dev; 230 struct DRM_MODE_FB_CMD mode_cmd; 231 struct drm_framebuffer *fb; 232 struct fb_info *info; 233 __u32 pitch; 234 int size, ret; 235 struct device *device = &dev->pdev->dev; 236 struct drm_gem_object *gobj = NULL; 237 struct vbox_bo *bo = NULL; 238 mode_cmd.width = sizes->surface_width; 239 mode_cmd.height = sizes->surface_height; 240 pitch = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); 225 struct drm_fb_helper_surface_size *sizes) 226 { 227 struct vbox_fbdev *fbdev = 228 container_of(helper, struct vbox_fbdev, helper); 229 struct drm_device *dev = fbdev->helper.dev; 230 struct DRM_MODE_FB_CMD mode_cmd; 231 struct drm_framebuffer *fb; 232 struct fb_info *info; 233 struct device *device = &dev->pdev->dev; 234 struct drm_gem_object *gobj = NULL; 235 struct vbox_bo *bo = NULL; 236 int size, ret; 237 u32 pitch; 238 239 mode_cmd.width = sizes->surface_width; 240 mode_cmd.height = sizes->surface_height; 241 pitch = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); 241 242 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 3, 0) 242 243 244 243 mode_cmd.bpp = sizes->surface_bpp; 244 mode_cmd.depth = sizes->surface_depth; 245 mode_cmd.pitch = pitch; 245 246 #else 246 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 247 sizes->surface_depth); 248 mode_cmd.pitches[0] = pitch; 249 #endif 250 251 size = pitch * mode_cmd.height; 252 253 ret = vboxfb_create_object(fbdev, &mode_cmd, &gobj); 254 if (ret) { 255 DRM_ERROR("failed to create fbcon backing object %d\n", ret); 256 return ret; 257 } 258 259 ret = vbox_framebuffer_init(dev, &fbdev->afb, &mode_cmd, gobj); 260 if (ret) 261 return ret; 262 263 bo = gem_to_vbox_bo(gobj); 264 265 ret = vbox_bo_reserve(bo, false); 266 if (ret) 267 return ret; 268 269 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); 270 if (ret) { 271 vbox_bo_unreserve(bo); 272 return ret; 273 } 274 275 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); 276 vbox_bo_unreserve(bo); 277 if (ret) { 278 DRM_ERROR("failed to kmap fbcon\n"); 279 return ret; 280 } 281 282 info = framebuffer_alloc(0, device); 283 if (!info) 284 return -ENOMEM; 285 info->par = fbdev; 286 287 fbdev->size = size; 288 289 fb = &fbdev->afb.base; 290 fbdev->helper.fb = fb; 291 fbdev->helper.fbdev = info; 292 293 strcpy(info->fix.id, "vboxdrmfb"); 294 295 /* The last flag forces a mode set on VT switches even if the kernel does 296 * not think it is needed. */ 297 info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT 298 | FBINFO_MISC_ALWAYS_SETPAR; 299 info->fbops = &vboxfb_ops; 300 301 ret = fb_alloc_cmap(&info->cmap, 256, 0); 302 if (ret) 303 return -ENOMEM; 304 305 /* This seems to be done for safety checking that the framebuffer is not 306 * registered twice by different drivers. */ 307 info->apertures = alloc_apertures(1); 308 if (!info->apertures) 309 return -ENOMEM; 310 info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0); 311 info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); 247 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 248 sizes->surface_depth); 249 mode_cmd.pitches[0] = pitch; 250 #endif 251 252 size = pitch * mode_cmd.height; 253 254 ret = vboxfb_create_object(fbdev, &mode_cmd, &gobj); 255 if (ret) { 256 DRM_ERROR("failed to create fbcon backing object %d\n", ret); 257 return ret; 258 } 259 260 ret = vbox_framebuffer_init(dev, &fbdev->afb, &mode_cmd, gobj); 261 if (ret) 262 return ret; 263 264 bo = gem_to_vbox_bo(gobj); 265 266 ret = vbox_bo_reserve(bo, false); 267 if (ret) 268 return ret; 269 270 ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL); 271 if (ret) { 272 vbox_bo_unreserve(bo); 273 return ret; 274 } 275 276 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap); 277 vbox_bo_unreserve(bo); 278 if (ret) { 279 DRM_ERROR("failed to kmap fbcon\n"); 280 return ret; 281 } 282 283 info = framebuffer_alloc(0, device); 284 if (!info) 285 return -ENOMEM; 286 info->par = fbdev; 287 288 fbdev->size = size; 289 290 fb = &fbdev->afb.base; 291 fbdev->helper.fb = fb; 292 fbdev->helper.fbdev = info; 293 294 strcpy(info->fix.id, "vboxdrmfb"); 295 296 /* 297 * The last flag forces a mode set on VT switches even if the kernel 298 * does not think it is needed. 299 */ 300 info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT | 301 FBINFO_MISC_ALWAYS_SETPAR; 302 info->fbops = &vboxfb_ops; 303 304 ret = fb_alloc_cmap(&info->cmap, 256, 0); 305 if (ret) 306 return -ENOMEM; 307 308 /* 309 * This seems to be done for safety checking that the framebuffer 310 * is not registered twice by different drivers. 311 */ 312 info->apertures = alloc_apertures(1); 313 if (!info->apertures) 314 return -ENOMEM; 315 info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0); 316 info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); 312 317 313 318 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 314 319 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); 315 320 #else 316 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); 317 #endif 318 drm_fb_helper_fill_var(info, &fbdev->helper, sizes->fb_width, sizes->fb_height); 319 320 info->screen_base = bo->kmap.virtual; 321 info->screen_size = size; 321 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); 322 #endif 323 drm_fb_helper_fill_var(info, &fbdev->helper, sizes->fb_width, 324 sizes->fb_height); 325 326 info->screen_base = bo->kmap.virtual; 327 info->screen_size = size; 322 328 323 329 #ifdef CONFIG_FB_DEFERRED_IO 324 info->fbdefio = &vbox_defio; 325 fb_deferred_io_init(info); 326 #endif 327 328 info->pixmap.flags = FB_PIXMAP_SYSTEM; 329 330 DRM_DEBUG_KMS("allocated %dx%d\n", 331 fb->width, fb->height); 332 333 return 0; 330 info->fbdefio = &vbox_defio; 331 fb_deferred_io_init(info); 332 #endif 333 334 info->pixmap.flags = FB_PIXMAP_SYSTEM; 335 336 DRM_DEBUG_KMS("allocated %dx%d\n", fb->width, fb->height); 337 338 return 0; 334 339 } 335 340 336 341 static void vbox_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, 337 u16 blue, int regno) 338 { 339 342 u16 blue, int regno) 343 { 340 344 } 341 345 342 346 static void vbox_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, 343 344 { 345 346 347 347 u16 *blue, int regno) 348 { 349 *red = regno; 350 *green = regno; 351 *blue = regno; 348 352 } 349 353 350 354 static struct drm_fb_helper_funcs vbox_fb_helper_funcs = { 351 352 353 355 .gamma_set = vbox_fb_gamma_set, 356 .gamma_get = vbox_fb_gamma_get, 357 .fb_probe = vboxfb_create, 354 358 }; 355 359 356 static void vbox_fbdev_destroy(struct drm_device *dev, 357 struct vbox_fbdev *fbdev) 358 { 359 struct fb_info *info; 360 struct vbox_framebuffer *afb = &fbdev->afb; 361 if (fbdev->helper.fbdev) { 362 info = fbdev->helper.fbdev; 363 unregister_framebuffer(info); 364 if (info->cmap.len) 365 fb_dealloc_cmap(&info->cmap); 366 framebuffer_release(info); 367 } 368 369 if (afb->obj) { 370 struct vbox_bo *bo = gem_to_vbox_bo(afb->obj); 371 if (!vbox_bo_reserve(bo, false)) { 372 if (bo->kmap.virtual) 373 ttm_bo_kunmap(&bo->kmap); 374 /* QXL does this, but is it really needed before freeing? */ 375 if (bo->pin_count) 376 vbox_bo_unpin(bo); 377 vbox_bo_unreserve(bo); 378 } 379 drm_gem_object_unreference_unlocked(afb->obj); 380 afb->obj = NULL; 381 } 382 drm_fb_helper_fini(&fbdev->helper); 360 static void vbox_fbdev_destroy(struct drm_device *dev, struct vbox_fbdev *fbdev) 361 { 362 struct fb_info *info; 363 struct vbox_framebuffer *afb = &fbdev->afb; 364 365 if (fbdev->helper.fbdev) { 366 info = fbdev->helper.fbdev; 367 unregister_framebuffer(info); 368 if (info->cmap.len) 369 fb_dealloc_cmap(&info->cmap); 370 framebuffer_release(info); 371 } 372 373 if (afb->obj) { 374 struct vbox_bo *bo = gem_to_vbox_bo(afb->obj); 375 376 if (!vbox_bo_reserve(bo, false)) { 377 if (bo->kmap.virtual) 378 ttm_bo_kunmap(&bo->kmap); 379 /* 380 * QXL does this, but is it really needed before 381 * freeing? 382 */ 383 if (bo->pin_count) 384 vbox_bo_unpin(bo); 385 vbox_bo_unreserve(bo); 386 } 387 drm_gem_object_unreference_unlocked(afb->obj); 388 afb->obj = NULL; 389 } 390 drm_fb_helper_fini(&fbdev->helper); 383 391 384 392 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) 385 386 #endif 387 393 drm_framebuffer_unregister_private(&afb->base); 394 #endif 395 drm_framebuffer_cleanup(&afb->base); 388 396 } 389 397 390 398 int vbox_fbdev_init(struct drm_device *dev) 391 399 { 392 393 394 395 396 fbdev = kzalloc(sizeof(struct vbox_fbdev), GFP_KERNEL);397 398 399 400 401 400 struct vbox_private *vbox = dev->dev_private; 401 struct vbox_fbdev *fbdev; 402 int ret; 403 404 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); 405 if (!fbdev) 406 return -ENOMEM; 407 408 vbox->fbdev = fbdev; 409 spin_lock_init(&fbdev->dirty_lock); 402 410 403 411 #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 17, 0) 404 412 fbdev->helper.funcs = &vbox_fb_helper_funcs; 405 413 #else 406 414 drm_fb_helper_prepare(dev, &fbdev->helper, &vbox_fb_helper_funcs); 407 415 #endif 408 416 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) 409 417 ret = drm_fb_helper_init(dev, &fbdev->helper, vbox->num_crtcs); 410 418 #else 411 ret = drm_fb_helper_init(dev, &fbdev->helper, vbox->num_crtcs, vbox->num_crtcs); 412 #endif 413 if (ret) 414 goto free; 415 416 ret = drm_fb_helper_single_add_all_connectors(&fbdev->helper); 417 if (ret) 418 goto fini; 419 420 /* disable all the possible outputs/crtcs before entering KMS mode */ 421 drm_helper_disable_unused_functions(dev); 422 423 ret = drm_fb_helper_initial_config(&fbdev->helper, 32); 424 if (ret) 425 goto fini; 426 427 return 0; 419 ret = 420 drm_fb_helper_init(dev, &fbdev->helper, vbox->num_crtcs, 421 vbox->num_crtcs); 422 #endif 423 if (ret) 424 goto free; 425 426 ret = drm_fb_helper_single_add_all_connectors(&fbdev->helper); 427 if (ret) 428 goto fini; 429 430 /* disable all the possible outputs/crtcs before entering KMS mode */ 431 drm_helper_disable_unused_functions(dev); 432 433 ret = drm_fb_helper_initial_config(&fbdev->helper, 32); 434 if (ret) 435 goto fini; 436 437 return 0; 438 428 439 fini: 429 440 drm_fb_helper_fini(&fbdev->helper); 430 441 free: 431 kfree(fbdev); 432 vbox->fbdev = NULL; 433 return ret; 442 kfree(fbdev); 443 vbox->fbdev = NULL; 444 445 return ret; 434 446 } 435 447 436 448 void vbox_fbdev_fini(struct drm_device *dev) 437 449 { 438 439 440 441 442 443 444 445 450 struct vbox_private *vbox = dev->dev_private; 451 452 if (!vbox->fbdev) 453 return; 454 455 vbox_fbdev_destroy(dev, vbox->fbdev); 456 kfree(vbox->fbdev); 457 vbox->fbdev = NULL; 446 458 } 447 459 448 460 void vbox_fbdev_set_suspend(struct drm_device *dev, int state) 449 461 { 450 451 452 453 454 455 462 struct vbox_private *vbox = dev->dev_private; 463 464 if (!vbox->fbdev) 465 return; 466 467 fb_set_suspend(vbox->fbdev->helper.fbdev, state); 456 468 } 457 469 458 470 void vbox_fbdev_set_base(struct vbox_private *vbox, unsigned long gpu_addr) 459 471 { 460 461 vbox->fbdev->helper.fbdev->apertures->ranges[0].base + 462 gpu_addr; 463 vbox->fbdev->helper.fbdev->fix.smem_len =vbox->available_vram_size - gpu_addr;464 } 472 vbox->fbdev->helper.fbdev->fix.smem_start = 473 vbox->fbdev->helper.fbdev->apertures->ranges[0].base + gpu_addr; 474 vbox->fbdev->helper.fbdev->fix.smem_len = 475 vbox->available_vram_size - gpu_addr; 476 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器