diff options
Diffstat (limited to 'drivers/gpu/drm')
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 101 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_draw.c | 6 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 32 | ||||
| -rw-r--r-- | drivers/gpu/drm/qxl/qxl_fb.c | 197 |
4 files changed, 60 insertions, 276 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 01704a7f07cb..87d16a0ce01e 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <drm/drm_plane_helper.h> | 28 | #include <drm/drm_plane_helper.h> |
| 29 | #include <drm/drm_atomic_helper.h> | 29 | #include <drm/drm_atomic_helper.h> |
| 30 | #include <drm/drm_atomic.h> | 30 | #include <drm/drm_atomic.h> |
| 31 | #include <drm/drm_gem_framebuffer_helper.h> | ||
| 31 | 32 | ||
| 32 | #include "qxl_drv.h" | 33 | #include "qxl_drv.h" |
| 33 | #include "qxl_object.h" | 34 | #include "qxl_object.h" |
| @@ -388,17 +389,6 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { | |||
| 388 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, | 389 | .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, |
| 389 | }; | 390 | }; |
| 390 | 391 | ||
| 391 | void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) | ||
| 392 | { | ||
| 393 | struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); | ||
| 394 | struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj); | ||
| 395 | |||
| 396 | WARN_ON(bo->shadow); | ||
| 397 | drm_gem_object_put_unlocked(qxl_fb->obj); | ||
| 398 | drm_framebuffer_cleanup(fb); | ||
| 399 | kfree(qxl_fb); | ||
| 400 | } | ||
| 401 | |||
| 402 | static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, | 392 | static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, |
| 403 | struct drm_file *file_priv, | 393 | struct drm_file *file_priv, |
| 404 | unsigned flags, unsigned color, | 394 | unsigned flags, unsigned color, |
| @@ -406,15 +396,14 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, | |||
| 406 | unsigned num_clips) | 396 | unsigned num_clips) |
| 407 | { | 397 | { |
| 408 | /* TODO: vmwgfx where this was cribbed from had locking. Why? */ | 398 | /* TODO: vmwgfx where this was cribbed from had locking. Why? */ |
| 409 | struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); | 399 | struct qxl_device *qdev = fb->dev->dev_private; |
| 410 | struct qxl_device *qdev = qxl_fb->base.dev->dev_private; | ||
| 411 | struct drm_clip_rect norect; | 400 | struct drm_clip_rect norect; |
| 412 | struct qxl_bo *qobj; | 401 | struct qxl_bo *qobj; |
| 413 | int inc = 1; | 402 | int inc = 1; |
| 414 | 403 | ||
| 415 | drm_modeset_lock_all(fb->dev); | 404 | drm_modeset_lock_all(fb->dev); |
| 416 | 405 | ||
| 417 | qobj = gem_to_qxl_bo(qxl_fb->obj); | 406 | qobj = gem_to_qxl_bo(fb->obj[0]); |
| 418 | /* if we aren't primary surface ignore this */ | 407 | /* if we aren't primary surface ignore this */ |
| 419 | if (!qobj->is_primary) { | 408 | if (!qobj->is_primary) { |
| 420 | drm_modeset_unlock_all(fb->dev); | 409 | drm_modeset_unlock_all(fb->dev); |
| @@ -432,7 +421,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, | |||
| 432 | inc = 2; /* skip source rects */ | 421 | inc = 2; /* skip source rects */ |
| 433 | } | 422 | } |
| 434 | 423 | ||
| 435 | qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color, | 424 | qxl_draw_dirty_fb(qdev, fb, qobj, flags, color, |
| 436 | clips, num_clips, inc); | 425 | clips, num_clips, inc); |
| 437 | 426 | ||
| 438 | drm_modeset_unlock_all(fb->dev); | 427 | drm_modeset_unlock_all(fb->dev); |
| @@ -441,31 +430,11 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb, | |||
| 441 | } | 430 | } |
| 442 | 431 | ||
| 443 | static const struct drm_framebuffer_funcs qxl_fb_funcs = { | 432 | static const struct drm_framebuffer_funcs qxl_fb_funcs = { |
| 444 | .destroy = qxl_user_framebuffer_destroy, | 433 | .destroy = drm_gem_fb_destroy, |
| 445 | .dirty = qxl_framebuffer_surface_dirty, | 434 | .dirty = qxl_framebuffer_surface_dirty, |
| 446 | /* TODO? | 435 | .create_handle = drm_gem_fb_create_handle, |
| 447 | * .create_handle = qxl_user_framebuffer_create_handle, */ | ||
| 448 | }; | 436 | }; |
| 449 | 437 | ||
| 450 | int | ||
| 451 | qxl_framebuffer_init(struct drm_device *dev, | ||
| 452 | struct qxl_framebuffer *qfb, | ||
| 453 | const struct drm_mode_fb_cmd2 *mode_cmd, | ||
| 454 | struct drm_gem_object *obj, | ||
| 455 | const struct drm_framebuffer_funcs *funcs) | ||
| 456 | { | ||
| 457 | int ret; | ||
| 458 | |||
| 459 | qfb->obj = obj; | ||
| 460 | drm_helper_mode_fill_fb_struct(dev, &qfb->base, mode_cmd); | ||
| 461 | ret = drm_framebuffer_init(dev, &qfb->base, funcs); | ||
| 462 | if (ret) { | ||
| 463 | qfb->obj = NULL; | ||
| 464 | return ret; | ||
| 465 | } | ||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | static void qxl_crtc_atomic_enable(struct drm_crtc *crtc, | 438 | static void qxl_crtc_atomic_enable(struct drm_crtc *crtc, |
| 470 | struct drm_crtc_state *old_state) | 439 | struct drm_crtc_state *old_state) |
| 471 | { | 440 | { |
| @@ -488,14 +457,12 @@ static int qxl_primary_atomic_check(struct drm_plane *plane, | |||
| 488 | struct drm_plane_state *state) | 457 | struct drm_plane_state *state) |
| 489 | { | 458 | { |
| 490 | struct qxl_device *qdev = plane->dev->dev_private; | 459 | struct qxl_device *qdev = plane->dev->dev_private; |
| 491 | struct qxl_framebuffer *qfb; | ||
| 492 | struct qxl_bo *bo; | 460 | struct qxl_bo *bo; |
| 493 | 461 | ||
| 494 | if (!state->crtc || !state->fb) | 462 | if (!state->crtc || !state->fb) |
| 495 | return 0; | 463 | return 0; |
| 496 | 464 | ||
| 497 | qfb = to_qxl_framebuffer(state->fb); | 465 | bo = gem_to_qxl_bo(state->fb->obj[0]); |
| 498 | bo = gem_to_qxl_bo(qfb->obj); | ||
| 499 | 466 | ||
| 500 | if (bo->surf.stride * bo->surf.height > qdev->vram_size) { | 467 | if (bo->surf.stride * bo->surf.height > qdev->vram_size) { |
| 501 | DRM_ERROR("Mode doesn't fit in vram size (vgamem)"); | 468 | DRM_ERROR("Mode doesn't fit in vram size (vgamem)"); |
| @@ -556,23 +523,19 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, | |||
| 556 | struct drm_plane_state *old_state) | 523 | struct drm_plane_state *old_state) |
| 557 | { | 524 | { |
| 558 | struct qxl_device *qdev = plane->dev->dev_private; | 525 | struct qxl_device *qdev = plane->dev->dev_private; |
| 559 | struct qxl_framebuffer *qfb = | 526 | struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]); |
| 560 | to_qxl_framebuffer(plane->state->fb); | ||
| 561 | struct qxl_framebuffer *qfb_old; | ||
| 562 | struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); | ||
| 563 | struct qxl_bo *bo_old; | 527 | struct qxl_bo *bo_old; |
| 564 | struct drm_clip_rect norect = { | 528 | struct drm_clip_rect norect = { |
| 565 | .x1 = 0, | 529 | .x1 = 0, |
| 566 | .y1 = 0, | 530 | .y1 = 0, |
| 567 | .x2 = qfb->base.width, | 531 | .x2 = plane->state->fb->width, |
| 568 | .y2 = qfb->base.height | 532 | .y2 = plane->state->fb->height |
| 569 | }; | 533 | }; |
| 570 | int ret; | 534 | int ret; |
| 571 | bool same_shadow = false; | 535 | bool same_shadow = false; |
| 572 | 536 | ||
| 573 | if (old_state->fb) { | 537 | if (old_state->fb) { |
| 574 | qfb_old = to_qxl_framebuffer(old_state->fb); | 538 | bo_old = gem_to_qxl_bo(old_state->fb->obj[0]); |
| 575 | bo_old = gem_to_qxl_bo(qfb_old->obj); | ||
| 576 | } else { | 539 | } else { |
| 577 | bo_old = NULL; | 540 | bo_old = NULL; |
| 578 | } | 541 | } |
| @@ -602,7 +565,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, | |||
| 602 | bo->is_primary = true; | 565 | bo->is_primary = true; |
| 603 | } | 566 | } |
| 604 | 567 | ||
| 605 | qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); | 568 | qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1); |
| 606 | } | 569 | } |
| 607 | 570 | ||
| 608 | static void qxl_primary_atomic_disable(struct drm_plane *plane, | 571 | static void qxl_primary_atomic_disable(struct drm_plane *plane, |
| @@ -611,9 +574,7 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane, | |||
| 611 | struct qxl_device *qdev = plane->dev->dev_private; | 574 | struct qxl_device *qdev = plane->dev->dev_private; |
| 612 | 575 | ||
| 613 | if (old_state->fb) { | 576 | if (old_state->fb) { |
| 614 | struct qxl_framebuffer *qfb = | 577 | struct qxl_bo *bo = gem_to_qxl_bo(old_state->fb->obj[0]); |
| 615 | to_qxl_framebuffer(old_state->fb); | ||
| 616 | struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); | ||
| 617 | 578 | ||
| 618 | if (bo->is_primary) { | 579 | if (bo->is_primary) { |
| 619 | qxl_io_destroy_primary(qdev); | 580 | qxl_io_destroy_primary(qdev); |
| @@ -645,7 +606,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane, | |||
| 645 | return; | 606 | return; |
| 646 | 607 | ||
| 647 | if (fb != old_state->fb) { | 608 | if (fb != old_state->fb) { |
| 648 | obj = to_qxl_framebuffer(fb)->obj; | 609 | obj = fb->obj[0]; |
| 649 | user_bo = gem_to_qxl_bo(obj); | 610 | user_bo = gem_to_qxl_bo(obj); |
| 650 | 611 | ||
| 651 | /* pinning is done in the prepare/cleanup framevbuffer */ | 612 | /* pinning is done in the prepare/cleanup framevbuffer */ |
| @@ -765,13 +726,13 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, | |||
| 765 | if (!new_state->fb) | 726 | if (!new_state->fb) |
| 766 | return 0; | 727 | return 0; |
| 767 | 728 | ||
| 768 | obj = to_qxl_framebuffer(new_state->fb)->obj; | 729 | obj = new_state->fb->obj[0]; |
| 769 | user_bo = gem_to_qxl_bo(obj); | 730 | user_bo = gem_to_qxl_bo(obj); |
| 770 | 731 | ||
| 771 | if (plane->type == DRM_PLANE_TYPE_PRIMARY && | 732 | if (plane->type == DRM_PLANE_TYPE_PRIMARY && |
| 772 | user_bo->is_dumb && !user_bo->shadow) { | 733 | user_bo->is_dumb && !user_bo->shadow) { |
| 773 | if (plane->state->fb) { | 734 | if (plane->state->fb) { |
| 774 | obj = to_qxl_framebuffer(plane->state->fb)->obj; | 735 | obj = plane->state->fb->obj[0]; |
| 775 | old_bo = gem_to_qxl_bo(obj); | 736 | old_bo = gem_to_qxl_bo(obj); |
| 776 | } | 737 | } |
| 777 | if (old_bo && old_bo->shadow && | 738 | if (old_bo && old_bo->shadow && |
| @@ -815,7 +776,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, | |||
| 815 | return; | 776 | return; |
| 816 | } | 777 | } |
| 817 | 778 | ||
| 818 | obj = to_qxl_framebuffer(old_state->fb)->obj; | 779 | obj = old_state->fb->obj[0]; |
| 819 | user_bo = gem_to_qxl_bo(obj); | 780 | user_bo = gem_to_qxl_bo(obj); |
| 820 | qxl_bo_unpin(user_bo); | 781 | qxl_bo_unpin(user_bo); |
| 821 | 782 | ||
| @@ -1115,26 +1076,8 @@ qxl_user_framebuffer_create(struct drm_device *dev, | |||
| 1115 | struct drm_file *file_priv, | 1076 | struct drm_file *file_priv, |
| 1116 | const struct drm_mode_fb_cmd2 *mode_cmd) | 1077 | const struct drm_mode_fb_cmd2 *mode_cmd) |
| 1117 | { | 1078 | { |
| 1118 | struct drm_gem_object *obj; | 1079 | return drm_gem_fb_create_with_funcs(dev, file_priv, mode_cmd, |
| 1119 | struct qxl_framebuffer *qxl_fb; | 1080 | &qxl_fb_funcs); |
| 1120 | int ret; | ||
| 1121 | |||
| 1122 | obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]); | ||
| 1123 | if (!obj) | ||
| 1124 | return NULL; | ||
| 1125 | |||
| 1126 | qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL); | ||
| 1127 | if (qxl_fb == NULL) | ||
| 1128 | return NULL; | ||
| 1129 | |||
| 1130 | ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs); | ||
| 1131 | if (ret) { | ||
| 1132 | kfree(qxl_fb); | ||
| 1133 | drm_gem_object_put_unlocked(obj); | ||
| 1134 | return NULL; | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | return &qxl_fb->base; | ||
| 1138 | } | 1081 | } |
| 1139 | 1082 | ||
| 1140 | static const struct drm_mode_config_funcs qxl_mode_funcs = { | 1083 | static const struct drm_mode_config_funcs qxl_mode_funcs = { |
| @@ -1221,7 +1164,6 @@ int qxl_modeset_init(struct qxl_device *qdev) | |||
| 1221 | } | 1164 | } |
| 1222 | 1165 | ||
| 1223 | qxl_display_read_client_monitors_config(qdev); | 1166 | qxl_display_read_client_monitors_config(qdev); |
| 1224 | qdev->mode_info.mode_config_initialized = true; | ||
| 1225 | 1167 | ||
| 1226 | drm_mode_config_reset(&qdev->ddev); | 1168 | drm_mode_config_reset(&qdev->ddev); |
| 1227 | 1169 | ||
| @@ -1237,8 +1179,5 @@ void qxl_modeset_fini(struct qxl_device *qdev) | |||
| 1237 | qxl_fbdev_fini(qdev); | 1179 | qxl_fbdev_fini(qdev); |
| 1238 | 1180 | ||
| 1239 | qxl_destroy_monitors_object(qdev); | 1181 | qxl_destroy_monitors_object(qdev); |
| 1240 | if (qdev->mode_info.mode_config_initialized) { | 1182 | drm_mode_config_cleanup(&qdev->ddev); |
| 1241 | drm_mode_config_cleanup(&qdev->ddev); | ||
| 1242 | qdev->mode_info.mode_config_initialized = false; | ||
| 1243 | } | ||
| 1244 | } | 1183 | } |
diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index 4d8681e84e68..cc5b32e749ce 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c | |||
| @@ -262,7 +262,7 @@ out_free_drawable: | |||
| 262 | * by treating them differently in the server. | 262 | * by treating them differently in the server. |
| 263 | */ | 263 | */ |
| 264 | void qxl_draw_dirty_fb(struct qxl_device *qdev, | 264 | void qxl_draw_dirty_fb(struct qxl_device *qdev, |
| 265 | struct qxl_framebuffer *qxl_fb, | 265 | struct drm_framebuffer *fb, |
| 266 | struct qxl_bo *bo, | 266 | struct qxl_bo *bo, |
| 267 | unsigned flags, unsigned color, | 267 | unsigned flags, unsigned color, |
| 268 | struct drm_clip_rect *clips, | 268 | struct drm_clip_rect *clips, |
| @@ -281,9 +281,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, | |||
| 281 | struct qxl_drawable *drawable; | 281 | struct qxl_drawable *drawable; |
| 282 | struct qxl_rect drawable_rect; | 282 | struct qxl_rect drawable_rect; |
| 283 | struct qxl_rect *rects; | 283 | struct qxl_rect *rects; |
| 284 | int stride = qxl_fb->base.pitches[0]; | 284 | int stride = fb->pitches[0]; |
| 285 | /* depth is not actually interesting, we don't mask with it */ | 285 | /* depth is not actually interesting, we don't mask with it */ |
| 286 | int depth = qxl_fb->base.format->cpp[0] * 8; | 286 | int depth = fb->format->cpp[0] * 8; |
| 287 | uint8_t *surface_base; | 287 | uint8_t *surface_base; |
| 288 | struct qxl_release *release; | 288 | struct qxl_release *release; |
| 289 | struct qxl_bo *clips_bo; | 289 | struct qxl_bo *clips_bo; |
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 01220d386b0a..8ff70a7281a7 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #include <drm/drm_crtc.h> | 39 | #include <drm/drm_crtc.h> |
| 40 | #include <drm/drm_encoder.h> | 40 | #include <drm/drm_encoder.h> |
| 41 | #include <drm/drm_fb_helper.h> | ||
| 41 | #include <drm/drm_gem.h> | 42 | #include <drm/drm_gem.h> |
| 42 | #include <drm/drmP.h> | 43 | #include <drm/drmP.h> |
| 43 | #include <drm/ttm/ttm_bo_api.h> | 44 | #include <drm/ttm/ttm_bo_api.h> |
| @@ -121,15 +122,9 @@ struct qxl_output { | |||
| 121 | struct drm_encoder enc; | 122 | struct drm_encoder enc; |
| 122 | }; | 123 | }; |
| 123 | 124 | ||
| 124 | struct qxl_framebuffer { | ||
| 125 | struct drm_framebuffer base; | ||
| 126 | struct drm_gem_object *obj; | ||
| 127 | }; | ||
| 128 | |||
| 129 | #define to_qxl_crtc(x) container_of(x, struct qxl_crtc, base) | 125 | #define to_qxl_crtc(x) container_of(x, struct qxl_crtc, base) |
| 130 | #define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base) | 126 | #define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base) |
| 131 | #define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc) | 127 | #define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc) |
| 132 | #define to_qxl_framebuffer(x) container_of(x, struct qxl_framebuffer, base) | ||
| 133 | 128 | ||
| 134 | struct qxl_mman { | 129 | struct qxl_mman { |
| 135 | struct ttm_bo_global_ref bo_global_ref; | 130 | struct ttm_bo_global_ref bo_global_ref; |
| @@ -138,13 +133,6 @@ struct qxl_mman { | |||
| 138 | struct ttm_bo_device bdev; | 133 | struct ttm_bo_device bdev; |
| 139 | }; | 134 | }; |
| 140 | 135 | ||
| 141 | struct qxl_mode_info { | ||
| 142 | bool mode_config_initialized; | ||
| 143 | |||
| 144 | /* pointer to fbdev info structure */ | ||
| 145 | struct qxl_fbdev *qfbdev; | ||
| 146 | }; | ||
| 147 | |||
| 148 | 136 | ||
| 149 | struct qxl_memslot { | 137 | struct qxl_memslot { |
| 150 | uint8_t generation; | 138 | uint8_t generation; |
| @@ -232,10 +220,9 @@ struct qxl_device { | |||
| 232 | void *ram; | 220 | void *ram; |
| 233 | struct qxl_mman mman; | 221 | struct qxl_mman mman; |
| 234 | struct qxl_gem gem; | 222 | struct qxl_gem gem; |
| 235 | struct qxl_mode_info mode_info; | ||
| 236 | 223 | ||
| 237 | struct fb_info *fbdev_info; | 224 | struct drm_fb_helper fb_helper; |
| 238 | struct qxl_framebuffer *fbdev_qfb; | 225 | |
| 239 | void *ram_physical; | 226 | void *ram_physical; |
| 240 | 227 | ||
| 241 | struct qxl_ring *release_ring; | 228 | struct qxl_ring *release_ring; |
| @@ -349,19 +336,8 @@ qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo, | |||
| 349 | 336 | ||
| 350 | int qxl_fbdev_init(struct qxl_device *qdev); | 337 | int qxl_fbdev_init(struct qxl_device *qdev); |
| 351 | void qxl_fbdev_fini(struct qxl_device *qdev); | 338 | void qxl_fbdev_fini(struct qxl_device *qdev); |
| 352 | int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, | ||
| 353 | struct drm_file *file_priv, | ||
| 354 | uint32_t *handle); | ||
| 355 | void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state); | ||
| 356 | 339 | ||
| 357 | /* qxl_display.c */ | 340 | /* qxl_display.c */ |
| 358 | void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb); | ||
| 359 | int | ||
| 360 | qxl_framebuffer_init(struct drm_device *dev, | ||
| 361 | struct qxl_framebuffer *rfb, | ||
| 362 | const struct drm_mode_fb_cmd2 *mode_cmd, | ||
| 363 | struct drm_gem_object *obj, | ||
| 364 | const struct drm_framebuffer_funcs *funcs); | ||
| 365 | void qxl_display_read_client_monitors_config(struct qxl_device *qdev); | 341 | void qxl_display_read_client_monitors_config(struct qxl_device *qdev); |
| 366 | int qxl_create_monitors_object(struct qxl_device *qdev); | 342 | int qxl_create_monitors_object(struct qxl_device *qdev); |
| 367 | int qxl_destroy_monitors_object(struct qxl_device *qdev); | 343 | int qxl_destroy_monitors_object(struct qxl_device *qdev); |
| @@ -471,7 +447,7 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image, | |||
| 471 | int stride /* filled in if 0 */); | 447 | int stride /* filled in if 0 */); |
| 472 | 448 | ||
| 473 | void qxl_draw_dirty_fb(struct qxl_device *qdev, | 449 | void qxl_draw_dirty_fb(struct qxl_device *qdev, |
| 474 | struct qxl_framebuffer *qxl_fb, | 450 | struct drm_framebuffer *fb, |
| 475 | struct qxl_bo *bo, | 451 | struct qxl_bo *bo, |
| 476 | unsigned flags, unsigned color, | 452 | unsigned flags, unsigned color, |
| 477 | struct drm_clip_rect *clips, | 453 | struct drm_clip_rect *clips, |
diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index ca465c0d49fa..2294b7f14fdf 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c | |||
| @@ -30,24 +30,12 @@ | |||
| 30 | #include <drm/drm_crtc.h> | 30 | #include <drm/drm_crtc.h> |
| 31 | #include <drm/drm_crtc_helper.h> | 31 | #include <drm/drm_crtc_helper.h> |
| 32 | #include <drm/drm_fb_helper.h> | 32 | #include <drm/drm_fb_helper.h> |
| 33 | #include <drm/drm_gem_framebuffer_helper.h> | ||
| 33 | 34 | ||
| 34 | #include "qxl_drv.h" | 35 | #include "qxl_drv.h" |
| 35 | 36 | ||
| 36 | #include "qxl_object.h" | 37 | #include "qxl_object.h" |
| 37 | 38 | ||
| 38 | #define QXL_DIRTY_DELAY (HZ / 30) | ||
| 39 | |||
| 40 | struct qxl_fbdev { | ||
| 41 | struct drm_fb_helper helper; | ||
| 42 | struct qxl_framebuffer qfb; | ||
| 43 | struct qxl_device *qdev; | ||
| 44 | |||
| 45 | spinlock_t delayed_ops_lock; | ||
| 46 | struct list_head delayed_ops; | ||
| 47 | void *shadow; | ||
| 48 | int size; | ||
| 49 | }; | ||
| 50 | |||
| 51 | static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, | 39 | static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, |
| 52 | struct qxl_device *qdev, struct fb_info *info, | 40 | struct qxl_device *qdev, struct fb_info *info, |
| 53 | const struct fb_image *image) | 41 | const struct fb_image *image) |
| @@ -73,13 +61,6 @@ static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image, | |||
| 73 | } | 61 | } |
| 74 | } | 62 | } |
| 75 | 63 | ||
| 76 | #ifdef CONFIG_DRM_FBDEV_EMULATION | ||
| 77 | static struct fb_deferred_io qxl_defio = { | ||
| 78 | .delay = QXL_DIRTY_DELAY, | ||
| 79 | .deferred_io = drm_fb_helper_deferred_io, | ||
| 80 | }; | ||
| 81 | #endif | ||
| 82 | |||
| 83 | static struct fb_ops qxlfb_ops = { | 64 | static struct fb_ops qxlfb_ops = { |
| 84 | .owner = THIS_MODULE, | 65 | .owner = THIS_MODULE, |
| 85 | DRM_FB_HELPER_DEFAULT_OPS, | 66 | DRM_FB_HELPER_DEFAULT_OPS, |
| @@ -98,26 +79,10 @@ static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj) | |||
| 98 | drm_gem_object_put_unlocked(gobj); | 79 | drm_gem_object_put_unlocked(gobj); |
| 99 | } | 80 | } |
| 100 | 81 | ||
| 101 | int qxl_get_handle_for_primary_fb(struct qxl_device *qdev, | 82 | static int qxlfb_create_pinned_object(struct qxl_device *qdev, |
| 102 | struct drm_file *file_priv, | ||
| 103 | uint32_t *handle) | ||
| 104 | { | ||
| 105 | int r; | ||
| 106 | struct drm_gem_object *gobj = qdev->fbdev_qfb->obj; | ||
| 107 | |||
| 108 | BUG_ON(!gobj); | ||
| 109 | /* drm_get_handle_create adds a reference - good */ | ||
| 110 | r = drm_gem_handle_create(file_priv, gobj, handle); | ||
| 111 | if (r) | ||
| 112 | return r; | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int qxlfb_create_pinned_object(struct qxl_fbdev *qfbdev, | ||
| 117 | const struct drm_mode_fb_cmd2 *mode_cmd, | 83 | const struct drm_mode_fb_cmd2 *mode_cmd, |
| 118 | struct drm_gem_object **gobj_p) | 84 | struct drm_gem_object **gobj_p) |
| 119 | { | 85 | { |
| 120 | struct qxl_device *qdev = qfbdev->qdev; | ||
| 121 | struct drm_gem_object *gobj = NULL; | 86 | struct drm_gem_object *gobj = NULL; |
| 122 | struct qxl_bo *qbo = NULL; | 87 | struct qxl_bo *qbo = NULL; |
| 123 | int ret; | 88 | int ret; |
| @@ -174,13 +139,12 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, | |||
| 174 | unsigned num_clips) | 139 | unsigned num_clips) |
| 175 | { | 140 | { |
| 176 | struct qxl_device *qdev = fb->dev->dev_private; | 141 | struct qxl_device *qdev = fb->dev->dev_private; |
| 177 | struct fb_info *info = qdev->fbdev_info; | 142 | struct fb_info *info = qdev->fb_helper.fbdev; |
| 178 | struct qxl_fbdev *qfbdev = info->par; | ||
| 179 | struct qxl_fb_image qxl_fb_image; | 143 | struct qxl_fb_image qxl_fb_image; |
| 180 | struct fb_image *image = &qxl_fb_image.fb_image; | 144 | struct fb_image *image = &qxl_fb_image.fb_image; |
| 181 | 145 | ||
| 182 | /* TODO: hard coding 32 bpp */ | 146 | /* TODO: hard coding 32 bpp */ |
| 183 | int stride = qfbdev->qfb.base.pitches[0]; | 147 | int stride = fb->pitches[0]; |
| 184 | 148 | ||
| 185 | /* | 149 | /* |
| 186 | * we are using a shadow draw buffer, at qdev->surface0_shadow | 150 | * we are using a shadow draw buffer, at qdev->surface0_shadow |
| @@ -199,7 +163,7 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, | |||
| 199 | image->cmap.green = NULL; | 163 | image->cmap.green = NULL; |
| 200 | image->cmap.blue = NULL; | 164 | image->cmap.blue = NULL; |
| 201 | image->cmap.transp = NULL; | 165 | image->cmap.transp = NULL; |
| 202 | image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1); | 166 | image->data = info->screen_base + (clips->x1 * 4) + (stride * clips->y1); |
| 203 | 167 | ||
| 204 | qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); | 168 | qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL); |
| 205 | qxl_draw_opaque_fb(&qxl_fb_image, stride); | 169 | qxl_draw_opaque_fb(&qxl_fb_image, stride); |
| @@ -208,21 +172,22 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb, | |||
| 208 | } | 172 | } |
| 209 | 173 | ||
| 210 | static const struct drm_framebuffer_funcs qxlfb_fb_funcs = { | 174 | static const struct drm_framebuffer_funcs qxlfb_fb_funcs = { |
| 211 | .destroy = qxl_user_framebuffer_destroy, | 175 | .destroy = drm_gem_fb_destroy, |
| 176 | .create_handle = drm_gem_fb_create_handle, | ||
| 212 | .dirty = qxlfb_framebuffer_dirty, | 177 | .dirty = qxlfb_framebuffer_dirty, |
| 213 | }; | 178 | }; |
| 214 | 179 | ||
| 215 | static int qxlfb_create(struct qxl_fbdev *qfbdev, | 180 | static int qxlfb_create(struct drm_fb_helper *helper, |
| 216 | struct drm_fb_helper_surface_size *sizes) | 181 | struct drm_fb_helper_surface_size *sizes) |
| 217 | { | 182 | { |
| 218 | struct qxl_device *qdev = qfbdev->qdev; | 183 | struct qxl_device *qdev = |
| 184 | container_of(helper, struct qxl_device, fb_helper); | ||
| 219 | struct fb_info *info; | 185 | struct fb_info *info; |
| 220 | struct drm_framebuffer *fb = NULL; | 186 | struct drm_framebuffer *fb = NULL; |
| 221 | struct drm_mode_fb_cmd2 mode_cmd; | 187 | struct drm_mode_fb_cmd2 mode_cmd; |
| 222 | struct drm_gem_object *gobj = NULL; | 188 | struct drm_gem_object *gobj = NULL; |
| 223 | struct qxl_bo *qbo = NULL; | 189 | struct qxl_bo *qbo = NULL; |
| 224 | int ret; | 190 | int ret; |
| 225 | int size; | ||
| 226 | int bpp = sizes->surface_bpp; | 191 | int bpp = sizes->surface_bpp; |
| 227 | int depth = sizes->surface_depth; | 192 | int depth = sizes->surface_depth; |
| 228 | void *shadow; | 193 | void *shadow; |
| @@ -233,7 +198,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, | |||
| 233 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 1) / 8), 64); | 198 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 1) / 8), 64); |
| 234 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); | 199 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); |
| 235 | 200 | ||
| 236 | ret = qxlfb_create_pinned_object(qfbdev, &mode_cmd, &gobj); | 201 | ret = qxlfb_create_pinned_object(qdev, &mode_cmd, &gobj); |
| 237 | if (ret < 0) | 202 | if (ret < 0) |
| 238 | return ret; | 203 | return ret; |
| 239 | 204 | ||
| @@ -247,25 +212,26 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, | |||
| 247 | DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", | 212 | DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", |
| 248 | qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo), | 213 | qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo), |
| 249 | qbo->kptr, shadow); | 214 | qbo->kptr, shadow); |
| 250 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
| 251 | 215 | ||
| 252 | info = drm_fb_helper_alloc_fbi(&qfbdev->helper); | 216 | info = drm_fb_helper_alloc_fbi(helper); |
| 253 | if (IS_ERR(info)) { | 217 | if (IS_ERR(info)) { |
| 254 | ret = PTR_ERR(info); | 218 | ret = PTR_ERR(info); |
| 255 | goto out_unref; | 219 | goto out_unref; |
| 256 | } | 220 | } |
| 257 | 221 | ||
| 258 | info->par = qfbdev; | 222 | info->par = helper; |
| 259 | |||
| 260 | qxl_framebuffer_init(&qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj, | ||
| 261 | &qxlfb_fb_funcs); | ||
| 262 | 223 | ||
| 263 | fb = &qfbdev->qfb.base; | 224 | fb = drm_gem_fbdev_fb_create(&qdev->ddev, sizes, 64, gobj, |
| 225 | &qxlfb_fb_funcs); | ||
| 226 | if (IS_ERR(fb)) { | ||
| 227 | DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb)); | ||
| 228 | ret = PTR_ERR(fb); | ||
| 229 | goto out_unref; | ||
| 230 | } | ||
| 264 | 231 | ||
| 265 | /* setup helper with fb data */ | 232 | /* setup helper with fb data */ |
| 266 | qfbdev->helper.fb = fb; | 233 | qdev->fb_helper.fb = fb; |
| 267 | 234 | ||
| 268 | qfbdev->shadow = shadow; | ||
| 269 | strcpy(info->fix.id, "qxldrmfb"); | 235 | strcpy(info->fix.id, "qxldrmfb"); |
| 270 | 236 | ||
| 271 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); | 237 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth); |
| @@ -278,10 +244,10 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, | |||
| 278 | */ | 244 | */ |
| 279 | info->fix.smem_start = qdev->vram_base; /* TODO - correct? */ | 245 | info->fix.smem_start = qdev->vram_base; /* TODO - correct? */ |
| 280 | info->fix.smem_len = gobj->size; | 246 | info->fix.smem_len = gobj->size; |
| 281 | info->screen_base = qfbdev->shadow; | 247 | info->screen_base = shadow; |
| 282 | info->screen_size = gobj->size; | 248 | info->screen_size = gobj->size; |
| 283 | 249 | ||
| 284 | drm_fb_helper_fill_var(info, &qfbdev->helper, sizes->fb_width, | 250 | drm_fb_helper_fill_var(info, &qdev->fb_helper, sizes->fb_width, |
| 285 | sizes->fb_height); | 251 | sizes->fb_height); |
| 286 | 252 | ||
| 287 | /* setup aperture base/size for vesafb takeover */ | 253 | /* setup aperture base/size for vesafb takeover */ |
| @@ -296,13 +262,9 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, | |||
| 296 | goto out_unref; | 262 | goto out_unref; |
| 297 | } | 263 | } |
| 298 | 264 | ||
| 299 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 265 | /* XXX error handling. */ |
| 300 | info->fbdefio = &qxl_defio; | 266 | drm_fb_helper_defio_init(helper); |
| 301 | fb_deferred_io_init(info); | ||
| 302 | #endif | ||
| 303 | 267 | ||
| 304 | qdev->fbdev_info = info; | ||
| 305 | qdev->fbdev_qfb = &qfbdev->qfb; | ||
| 306 | DRM_INFO("fb mappable at 0x%lX, size %lu\n", info->fix.smem_start, (unsigned long)info->screen_size); | 268 | DRM_INFO("fb mappable at 0x%lX, size %lu\n", info->fix.smem_start, (unsigned long)info->screen_size); |
| 307 | DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", | 269 | DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n", |
| 308 | fb->format->depth, fb->pitches[0], fb->width, fb->height); | 270 | fb->format->depth, fb->pitches[0], fb->width, fb->height); |
| @@ -313,119 +275,26 @@ out_unref: | |||
| 313 | qxl_bo_kunmap(qbo); | 275 | qxl_bo_kunmap(qbo); |
| 314 | qxl_bo_unpin(qbo); | 276 | qxl_bo_unpin(qbo); |
| 315 | } | 277 | } |
| 316 | if (fb && ret) { | ||
| 317 | drm_gem_object_put_unlocked(gobj); | ||
| 318 | drm_framebuffer_cleanup(fb); | ||
| 319 | kfree(fb); | ||
| 320 | } | ||
| 321 | drm_gem_object_put_unlocked(gobj); | 278 | drm_gem_object_put_unlocked(gobj); |
| 322 | return ret; | 279 | return ret; |
| 323 | } | 280 | } |
| 324 | 281 | ||
| 325 | static int qxl_fb_find_or_create_single( | ||
| 326 | struct drm_fb_helper *helper, | ||
| 327 | struct drm_fb_helper_surface_size *sizes) | ||
| 328 | { | ||
| 329 | struct qxl_fbdev *qfbdev = | ||
| 330 | container_of(helper, struct qxl_fbdev, helper); | ||
| 331 | int new_fb = 0; | ||
| 332 | int ret; | ||
| 333 | |||
| 334 | if (!helper->fb) { | ||
| 335 | ret = qxlfb_create(qfbdev, sizes); | ||
| 336 | if (ret) | ||
| 337 | return ret; | ||
| 338 | new_fb = 1; | ||
| 339 | } | ||
| 340 | return new_fb; | ||
| 341 | } | ||
| 342 | |||
| 343 | static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev) | ||
| 344 | { | ||
| 345 | struct qxl_framebuffer *qfb = &qfbdev->qfb; | ||
| 346 | |||
| 347 | drm_fb_helper_unregister_fbi(&qfbdev->helper); | ||
| 348 | |||
| 349 | if (qfb->obj) { | ||
| 350 | qxlfb_destroy_pinned_object(qfb->obj); | ||
| 351 | qfb->obj = NULL; | ||
| 352 | } | ||
| 353 | drm_fb_helper_fini(&qfbdev->helper); | ||
| 354 | vfree(qfbdev->shadow); | ||
| 355 | drm_framebuffer_cleanup(&qfb->base); | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = { | 282 | static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = { |
| 361 | .fb_probe = qxl_fb_find_or_create_single, | 283 | .fb_probe = qxlfb_create, |
| 362 | }; | 284 | }; |
| 363 | 285 | ||
| 364 | int qxl_fbdev_init(struct qxl_device *qdev) | 286 | int qxl_fbdev_init(struct qxl_device *qdev) |
| 365 | { | 287 | { |
| 366 | int ret = 0; | 288 | return drm_fb_helper_fbdev_setup(&qdev->ddev, &qdev->fb_helper, |
| 367 | 289 | &qxl_fb_helper_funcs, 32, | |
| 368 | #ifdef CONFIG_DRM_FBDEV_EMULATION | 290 | QXLFB_CONN_LIMIT); |
| 369 | struct qxl_fbdev *qfbdev; | ||
| 370 | int bpp_sel = 32; /* TODO: parameter from somewhere? */ | ||
| 371 | |||
| 372 | qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL); | ||
| 373 | if (!qfbdev) | ||
| 374 | return -ENOMEM; | ||
| 375 | |||
| 376 | qfbdev->qdev = qdev; | ||
| 377 | qdev->mode_info.qfbdev = qfbdev; | ||
| 378 | spin_lock_init(&qfbdev->delayed_ops_lock); | ||
| 379 | INIT_LIST_HEAD(&qfbdev->delayed_ops); | ||
| 380 | |||
| 381 | drm_fb_helper_prepare(&qdev->ddev, &qfbdev->helper, | ||
| 382 | &qxl_fb_helper_funcs); | ||
| 383 | |||
| 384 | ret = drm_fb_helper_init(&qdev->ddev, &qfbdev->helper, | ||
| 385 | QXLFB_CONN_LIMIT); | ||
| 386 | if (ret) | ||
| 387 | goto free; | ||
| 388 | |||
| 389 | ret = drm_fb_helper_single_add_all_connectors(&qfbdev->helper); | ||
| 390 | if (ret) | ||
| 391 | goto fini; | ||
| 392 | |||
| 393 | ret = drm_fb_helper_initial_config(&qfbdev->helper, bpp_sel); | ||
| 394 | if (ret) | ||
| 395 | goto fini; | ||
| 396 | |||
| 397 | return 0; | ||
| 398 | |||
| 399 | fini: | ||
| 400 | drm_fb_helper_fini(&qfbdev->helper); | ||
| 401 | free: | ||
| 402 | kfree(qfbdev); | ||
| 403 | #endif | ||
| 404 | |||
| 405 | return ret; | ||
| 406 | } | 291 | } |
| 407 | 292 | ||
| 408 | void qxl_fbdev_fini(struct qxl_device *qdev) | 293 | void qxl_fbdev_fini(struct qxl_device *qdev) |
| 409 | { | 294 | { |
| 410 | if (!qdev->mode_info.qfbdev) | 295 | struct fb_info *fbi = qdev->fb_helper.fbdev; |
| 411 | return; | 296 | void *shadow = fbi ? fbi->screen_buffer : NULL; |
| 412 | 297 | ||
| 413 | qxl_fbdev_destroy(&qdev->ddev, qdev->mode_info.qfbdev); | 298 | drm_fb_helper_fbdev_teardown(&qdev->ddev); |
| 414 | kfree(qdev->mode_info.qfbdev); | 299 | vfree(shadow); |
| 415 | qdev->mode_info.qfbdev = NULL; | ||
| 416 | } | ||
| 417 | |||
| 418 | void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state) | ||
| 419 | { | ||
| 420 | if (!qdev->mode_info.qfbdev) | ||
| 421 | return; | ||
| 422 | |||
| 423 | drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state); | ||
| 424 | } | ||
| 425 | |||
| 426 | bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj) | ||
| 427 | { | ||
| 428 | if (qobj == gem_to_qxl_bo(qdev->mode_info.qfbdev->qfb.obj)) | ||
| 429 | return true; | ||
| 430 | return false; | ||
| 431 | } | 300 | } |
