diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 21:44:24 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-05-03 21:44:24 +0300 |
commit | 2f34c1231bfc9f2550f934acb268ac7315fb3837 (patch) | |
tree | ff8114b3b4ec4723a11b041c6b74c389e9f0eeb9 /drivers/gpu/drm/qxl | |
parent | a3719f34fdb664ffcfaec2160ef20fca7becf2ee (diff) | |
parent | 8b03d1ed2c43a2ba5ef3381322ee4515b97381bf (diff) | |
download | linux-2f34c1231bfc9f2550f934acb268ac7315fb3837.tar.xz |
Merge tag 'drm-for-v4.12' of git://people.freedesktop.org/~airlied/linux
Pull drm u pdates from Dave Airlie:
"This is the main drm pull request for v4.12. Apart from two fixes
pulls, everything should have been in drm-next for at least 2 weeks.
The biggest thing in here is AMD released the public headers for their
upcoming VEGA GPUs. These as always are quite a sizeable chunk of
header files. They've also added initial non-display support for those
GPUs, though they aren't available in production yet.
Otherwise it's pretty much normal.
New bridge drivers:
- megachips-stdpxxxx-ge-b850v3-fw LVDS->DP++
- generic LVDS bridge support.
Core:
- Displayport link train failure reporting to userspace
- debugfs interface cleaned up
- subsystem TODO in kerneldoc now
- Extended fbdev support (flipping and vblank wait)
- drm_platform removed
- EDP CRC support in helper
- HF-VSDB SCDC support in EDID parser
- Lots of code cleanups and header extraction
- Thunderbolt external GPU awareness
- Atomic helper improvements
- Documentation improvements
panel:
- Sitronix and Samsung new panel support
amdgpu:
- Preliminary vega10 support
- Multi-level page table support
- GPU sensor support for userspace
- PRT support for sparse buffers
- SR-IOV improvements
- Non-contig VRAM CPU mapping
i915:
- Atomic modesetting enabled by default on Gen5+
- LSPCON improvements
- Atomic state handling for cdclk
- GPU reset improvements
- In-kernel unit tests
- Geminilake improvements and color manager support
- Designware i2c fixes
- vblank evasion improvements
- Hotplug safe connector iterators
- GVT scheduler QoS support
- GVT Kabylake support
nouveau:
- Acceleration support for Pascal (GP10x).
- Rearchitecture of code handling proprietary signed firmware
- Fix GTX 970 with odd MMU configuration
- GP10B support
- GP107 acceleration support
vmwgfx:
- Atomic modesetting support for vmwgfx
omapdrm:
- Support for render nodes
- Refactor omapdss code
- Fix some probe ordering issues
- Fix too dark RGB565 rendering
sunxi:
- prelim rework for multiple pipes.
mali-dp:
- Color management support
- Plane scaling
- Power management improvements
imx-drm:
- Prefetch Resolve Engine/Gasket on i.MX6QP
- Deferred plane disabling
- Separate alpha support
mediatek:
- Mediatek SoC MT2701 support
rcar-du:
- Gen3 HDMI support
msm:
- 4k support for newer chips
- OPP bindings for gpu
- prep work for per-process pagetables
vc4:
- HDMI audio support
- fixes
qxl:
- minor fixes.
dw-hdmi:
- PHY improvements
- CSC fixes
- Amlogic GX SoC support"
* tag 'drm-for-v4.12' of git://people.freedesktop.org/~airlied/linux: (1778 commits)
drm/nouveau/fb/gf100-: Fix 32 bit wraparound in new ram detection
drm/nouveau/secboot/gm20b: fix the error return code in gm20b_secboot_tegra_read_wpr()
drm/nouveau/kms: Increase max retries in scanout position queries.
drm/nouveau/bios/bitP: check that table is long enough for optional pointers
drm/nouveau/fifo/nv40: no ctxsw for pre-nv44 mpeg engine
drm: mali-dp: use div_u64 for expensive 64-bit divisions
drm/i915: Confirm the request is still active before adding it to the await
drm/i915: Avoid busy-spinning on VLV_GLTC_PW_STATUS mmio
drm/i915/selftests: Allocate inode/file dynamically
drm/i915: Fix system hang with EI UP masked on Haswell
drm/i915: checking for NULL instead of IS_ERR() in mock selftests
drm/i915: Perform link quality check unconditionally during long pulse
drm/i915: Fix use after free in lpe_audio_platdev_destroy()
drm/i915: Use the right mapping_gfp_mask for final shmem allocation
drm/i915: Make legacy cursor updates more unsynced
drm/i915: Apply a cond_resched() to the saturated signaler
drm/i915: Park the signaler before sleeping
drm: mali-dp: Check the mclk rate and allow up/down scaling
drm: mali-dp: Enable image enhancement when scaling
drm: mali-dp: Add plane upscaling support
...
Diffstat (limited to 'drivers/gpu/drm/qxl')
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_debugfs.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_display.c | 822 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.c | 32 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_drv.h | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_fb.c | 39 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_kms.c | 28 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_object.c | 41 | ||||
-rw-r--r-- | drivers/gpu/drm/qxl/qxl_ttm.c | 1 |
8 files changed, 475 insertions, 522 deletions
diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index d58751c94618..ffe821b61f7d 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -100,15 +100,6 @@ qxl_debugfs_init(struct drm_minor *minor) return 0; } -void -qxl_debugfs_takedown(struct drm_minor *minor) -{ -#if defined(CONFIG_DEBUG_FS) - drm_debugfs_remove_files(qxl_debugfs_list, QXL_DEBUGFS_ENTRIES, - minor); -#endif -} - int qxl_debugfs_add_files(struct qxl_device *qdev, struct drm_info_list *files, unsigned nfiles) @@ -138,16 +129,3 @@ int qxl_debugfs_add_files(struct qxl_device *qdev, #endif return 0; } - -void qxl_debugfs_remove_files(struct qxl_device *qdev) -{ -#if defined(CONFIG_DEBUG_FS) - unsigned i; - - for (i = 0; i < qdev->debugfs_count; i++) { - drm_debugfs_remove_files(qdev->debugfs[i].files, - qdev->debugfs[i].num_files, - qdev->ddev.primary); - } -#endif -} diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 1094cd33eb06..058340a002c2 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -30,6 +30,8 @@ #include "qxl_object.h" #include "drm_crtc_helper.h" #include <drm/drm_plane_helper.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic.h> static bool qxl_head_enabled(struct qxl_head *head) { @@ -79,6 +81,10 @@ static int qxl_display_copy_rom_client_monitors_config(struct qxl_device *qdev) qdev->rom->client_monitors_config_crc); return MONITORS_CONFIG_BAD_CRC; } + if (!num_monitors) { + DRM_DEBUG_KMS("no client monitors configured\n"); + return status; + } if (num_monitors > qdev->monitors_config->max_allowed) { DRM_DEBUG_KMS("client monitors list will be truncated: %d < %d\n", qdev->monitors_config->max_allowed, num_monitors); @@ -155,19 +161,23 @@ static void qxl_update_offset_props(struct qxl_device *qdev) void qxl_display_read_client_monitors_config(struct qxl_device *qdev) { - struct drm_device *dev = &qdev->ddev; - int status; + int status, retries; - status = qxl_display_copy_rom_client_monitors_config(qdev); - while (status == MONITORS_CONFIG_BAD_CRC) { - qxl_io_log(qdev, "failed crc check for client_monitors_config," - " retrying\n"); + for (retries = 0; retries < 10; retries++) { status = qxl_display_copy_rom_client_monitors_config(qdev); + if (status != MONITORS_CONFIG_BAD_CRC) + break; + udelay(5); + } + if (status == MONITORS_CONFIG_BAD_CRC) { + qxl_io_log(qdev, "config: bad crc\n"); + DRM_DEBUG_KMS("ignoring client monitors config: bad crc"); + return; } if (status == MONITORS_CONFIG_UNCHANGED) { - qxl_io_log(qdev, "config unchanged\n"); - DRM_DEBUG("ignoring unchanged client monitors config"); + qxl_io_log(qdev, "config: unchanged\n"); + DRM_DEBUG_KMS("ignoring client monitors config: unchanged"); return; } @@ -192,9 +202,17 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector, struct drm_display_mode *mode = NULL; struct qxl_head *head; + if (!qdev->monitors_config) + return 0; + if (h >= qdev->monitors_config->max_allowed) + return 0; if (!qdev->client_monitors_config) return 0; + if (h >= qdev->client_monitors_config->count) + return 0; + head = &qdev->client_monitors_config->heads[h]; + DRM_DEBUG_KMS("head %d is %dx%d\n", h, head->width, head->height); mode = drm_cvt_mode(dev, head->width, head->height, 60, false, false, false); @@ -251,310 +269,38 @@ static int qxl_add_common_modes(struct drm_connector *connector, return i - 1; } -static void qxl_crtc_destroy(struct drm_crtc *crtc) -{ - struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc); - - drm_crtc_cleanup(crtc); - qxl_bo_unref(&qxl_crtc->cursor_bo); - kfree(qxl_crtc); -} - -static int qxl_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, - struct drm_pending_vblank_event *event, - uint32_t page_flip_flags) +static void qxl_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_crtc_state *old_crtc_state) { struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - struct qxl_framebuffer *qfb_src = to_qxl_framebuffer(fb); - struct qxl_framebuffer *qfb_old = to_qxl_framebuffer(crtc->primary->fb); - struct qxl_bo *bo_old = gem_to_qxl_bo(qfb_old->obj); - struct qxl_bo *bo = gem_to_qxl_bo(qfb_src->obj); + struct drm_pending_vblank_event *event; unsigned long flags; - struct drm_clip_rect norect = { - .x1 = 0, - .y1 = 0, - .x2 = fb->width, - .y2 = fb->height - }; - int inc = 1; - int one_clip_rect = 1; - int ret = 0; - crtc->primary->fb = fb; - bo_old->is_primary = false; - bo->is_primary = true; + if (crtc->state && crtc->state->event) { + event = crtc->state->event; + crtc->state->event = NULL; - ret = qxl_bo_reserve(bo, false); - if (ret) - return ret; - ret = qxl_bo_pin(bo, bo->type, NULL); - qxl_bo_unreserve(bo); - if (ret) - return ret; - - qxl_draw_dirty_fb(qdev, qfb_src, bo, 0, 0, - &norect, one_clip_rect, inc); - - drm_crtc_vblank_get(crtc); - - if (event) { spin_lock_irqsave(&dev->event_lock, flags); drm_crtc_send_vblank_event(crtc, event); spin_unlock_irqrestore(&dev->event_lock, flags); } - drm_crtc_vblank_put(crtc); - - ret = qxl_bo_reserve(bo, false); - if (!ret) { - qxl_bo_unpin(bo); - qxl_bo_unreserve(bo); - } - - return 0; } -static int -qxl_hide_cursor(struct qxl_device *qdev) -{ - struct qxl_release *release; - struct qxl_cursor_cmd *cmd; - int ret; - - ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD, - &release, NULL); - if (ret) - return ret; - - ret = qxl_release_reserve_list(release, true); - if (ret) { - qxl_release_free(qdev, release); - return ret; - } - - cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); - cmd->type = QXL_CURSOR_HIDE; - qxl_release_unmap(qdev, release, &cmd->release_info); - - qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); - qxl_release_fence_buffer_objects(release); - return 0; -} - -static int qxl_crtc_apply_cursor(struct drm_crtc *crtc) -{ - struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - struct qxl_cursor_cmd *cmd; - struct qxl_release *release; - int ret = 0; - - if (!qcrtc->cursor_bo) - return 0; - - ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), - QXL_RELEASE_CURSOR_CMD, - &release, NULL); - if (ret) - return ret; - - ret = qxl_release_list_add(release, qcrtc->cursor_bo); - if (ret) - goto out_free_release; - - ret = qxl_release_reserve_list(release, false); - if (ret) - goto out_free_release; - - cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); - cmd->type = QXL_CURSOR_SET; - cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x; - cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y; - - cmd->u.set.shape = qxl_bo_physical_address(qdev, qcrtc->cursor_bo, 0); - - cmd->u.set.visible = 1; - qxl_release_unmap(qdev, release, &cmd->release_info); - - qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); - qxl_release_fence_buffer_objects(release); - - return ret; - -out_free_release: - qxl_release_free(qdev, release); - return ret; -} - -static int qxl_crtc_cursor_set2(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, - uint32_t height, int32_t hot_x, int32_t hot_y) -{ - struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); - struct drm_gem_object *obj; - struct qxl_cursor *cursor; - struct qxl_cursor_cmd *cmd; - struct qxl_bo *cursor_bo, *user_bo; - struct qxl_release *release; - void *user_ptr; - - int size = 64*64*4; - int ret = 0; - if (!handle) - return qxl_hide_cursor(qdev); - - obj = drm_gem_object_lookup(file_priv, handle); - if (!obj) { - DRM_ERROR("cannot find cursor object\n"); - return -ENOENT; - } - - user_bo = gem_to_qxl_bo(obj); - - ret = qxl_bo_reserve(user_bo, false); - if (ret) - goto out_unref; - - ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); - qxl_bo_unreserve(user_bo); - if (ret) - goto out_unref; - - ret = qxl_bo_kmap(user_bo, &user_ptr); - if (ret) - goto out_unpin; - - ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), - QXL_RELEASE_CURSOR_CMD, - &release, NULL); - if (ret) - goto out_kunmap; - - ret = qxl_alloc_bo_reserved(qdev, release, sizeof(struct qxl_cursor) + size, - &cursor_bo); - if (ret) - goto out_free_release; - - ret = qxl_release_reserve_list(release, false); - if (ret) - goto out_free_bo; - - ret = qxl_bo_kmap(cursor_bo, (void **)&cursor); - if (ret) - goto out_backoff; - - cursor->header.unique = 0; - cursor->header.type = SPICE_CURSOR_TYPE_ALPHA; - cursor->header.width = 64; - cursor->header.height = 64; - cursor->header.hot_spot_x = hot_x; - cursor->header.hot_spot_y = hot_y; - cursor->data_size = size; - cursor->chunk.next_chunk = 0; - cursor->chunk.prev_chunk = 0; - cursor->chunk.data_size = size; - - memcpy(cursor->chunk.data, user_ptr, size); - - qxl_bo_kunmap(cursor_bo); - - qxl_bo_kunmap(user_bo); - - qcrtc->cur_x += qcrtc->hot_spot_x - hot_x; - qcrtc->cur_y += qcrtc->hot_spot_y - hot_y; - qcrtc->hot_spot_x = hot_x; - qcrtc->hot_spot_y = hot_y; - - cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); - cmd->type = QXL_CURSOR_SET; - cmd->u.set.position.x = qcrtc->cur_x + qcrtc->hot_spot_x; - cmd->u.set.position.y = qcrtc->cur_y + qcrtc->hot_spot_y; - - cmd->u.set.shape = qxl_bo_physical_address(qdev, cursor_bo, 0); - - cmd->u.set.visible = 1; - qxl_release_unmap(qdev, release, &cmd->release_info); - - qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); - qxl_release_fence_buffer_objects(release); - - /* finish with the userspace bo */ - ret = qxl_bo_reserve(user_bo, false); - if (!ret) { - qxl_bo_unpin(user_bo); - qxl_bo_unreserve(user_bo); - } - drm_gem_object_unreference_unlocked(obj); - - qxl_bo_unref (&qcrtc->cursor_bo); - qcrtc->cursor_bo = cursor_bo; - - return ret; - -out_backoff: - qxl_release_backoff_reserve_list(release); -out_free_bo: - qxl_bo_unref(&cursor_bo); -out_free_release: - qxl_release_free(qdev, release); -out_kunmap: - qxl_bo_kunmap(user_bo); -out_unpin: - qxl_bo_unpin(user_bo); -out_unref: - drm_gem_object_unreference_unlocked(obj); - return ret; -} - -static int qxl_crtc_cursor_move(struct drm_crtc *crtc, - int x, int y) +static void qxl_crtc_destroy(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); - struct qxl_release *release; - struct qxl_cursor_cmd *cmd; - int ret; - - ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), QXL_RELEASE_CURSOR_CMD, - &release, NULL); - if (ret) - return ret; - - ret = qxl_release_reserve_list(release, true); - if (ret) { - qxl_release_free(qdev, release); - return ret; - } - - qcrtc->cur_x = x; - qcrtc->cur_y = y; - - cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); - cmd->type = QXL_CURSOR_MOVE; - cmd->u.position.x = qcrtc->cur_x + qcrtc->hot_spot_x; - cmd->u.position.y = qcrtc->cur_y + qcrtc->hot_spot_y; - qxl_release_unmap(qdev, release, &cmd->release_info); - - qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); - qxl_release_fence_buffer_objects(release); + struct qxl_crtc *qxl_crtc = to_qxl_crtc(crtc); - return 0; + drm_crtc_cleanup(crtc); + kfree(qxl_crtc); } - static const struct drm_crtc_funcs qxl_crtc_funcs = { - .cursor_set2 = qxl_crtc_cursor_set2, - .cursor_move = qxl_crtc_cursor_move, - .set_config = drm_crtc_helper_set_config, + .set_config = drm_atomic_helper_set_config, .destroy = qxl_crtc_destroy, - .page_flip = qxl_crtc_page_flip, + .page_flip = drm_atomic_helper_page_flip, + .reset = drm_atomic_helper_crtc_reset, + .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, }; void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) @@ -692,143 +438,410 @@ static void qxl_monitors_config_set(struct qxl_device *qdev, } -static int qxl_crtc_mode_set(struct drm_crtc *crtc, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode, - int x, int y, - struct drm_framebuffer *old_fb) +void qxl_mode_set_nofb(struct drm_crtc *crtc) { - struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - struct qxl_framebuffer *qfb; - struct qxl_bo *bo, *old_bo = NULL; + struct qxl_device *qdev = crtc->dev->dev_private; struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); - bool recreate_primary = false; - int ret; - int surf_id; - if (!crtc->primary->fb) { - DRM_DEBUG_KMS("No FB bound\n"); + struct drm_display_mode *mode = &crtc->mode; + + DRM_DEBUG("Mode set (%d,%d)\n", + mode->hdisplay, mode->vdisplay); + + qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, + mode->hdisplay, mode->vdisplay, 0); + +} + +static void qxl_crtc_commit(struct drm_crtc *crtc) +{ + DRM_DEBUG("\n"); +} + +static void qxl_crtc_disable(struct drm_crtc *crtc) +{ + struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); + struct qxl_device *qdev = crtc->dev->dev_private; + + qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0); + + qxl_send_monitors_config(qdev); +} + +static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { + .dpms = qxl_crtc_dpms, + .disable = qxl_crtc_disable, + .mode_fixup = qxl_crtc_mode_fixup, + .mode_set_nofb = qxl_mode_set_nofb, + .commit = qxl_crtc_commit, + .atomic_flush = qxl_crtc_atomic_flush, +}; + +int qxl_primary_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct qxl_device *qdev = plane->dev->dev_private; + struct qxl_framebuffer *qfb; + struct qxl_bo *bo; + + if (!state->crtc || !state->fb) return 0; - } - if (old_fb) { - qfb = to_qxl_framebuffer(old_fb); - old_bo = gem_to_qxl_bo(qfb->obj); - } - qfb = to_qxl_framebuffer(crtc->primary->fb); + qfb = to_qxl_framebuffer(state->fb); bo = gem_to_qxl_bo(qfb->obj); - DRM_DEBUG("+%d+%d (%d,%d) => (%d,%d)\n", - x, y, - mode->hdisplay, mode->vdisplay, - adjusted_mode->hdisplay, - adjusted_mode->vdisplay); - - if (bo->is_primary == false) - recreate_primary = true; if (bo->surf.stride * bo->surf.height > qdev->vram_size) { DRM_ERROR("Mode doesn't fit in vram size (vgamem)"); return -EINVAL; - } - - ret = qxl_bo_reserve(bo, false); - if (ret != 0) - return ret; - ret = qxl_bo_pin(bo, bo->type, NULL); - if (ret != 0) { - qxl_bo_unreserve(bo); - return -EINVAL; } - qxl_bo_unreserve(bo); - if (recreate_primary) { - qxl_io_destroy_primary(qdev); + + return 0; +} + +static void qxl_primary_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct qxl_device *qdev = plane->dev->dev_private; + struct qxl_framebuffer *qfb = + to_qxl_framebuffer(plane->state->fb); + struct qxl_framebuffer *qfb_old; + struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); + struct qxl_bo *bo_old; + struct drm_clip_rect norect = { + .x1 = 0, + .y1 = 0, + .x2 = qfb->base.width, + .y2 = qfb->base.height + }; + + if (!old_state->fb) { qxl_io_log(qdev, - "recreate primary: %dx%d,%d,%d\n", + "create primary fb: %dx%d,%d,%d\n", bo->surf.width, bo->surf.height, bo->surf.stride, bo->surf.format); + qxl_io_create_primary(qdev, 0, bo); bo->is_primary = true; + return; - ret = qxl_crtc_apply_cursor(crtc); - if (ret) { - DRM_ERROR("could not set cursor after modeset"); - ret = 0; - } - } - - if (bo->is_primary) { - DRM_DEBUG_KMS("setting surface_id to 0 for primary surface %d on crtc %d\n", bo->surface_id, qcrtc->index); - surf_id = 0; } else { - surf_id = bo->surface_id; + qfb_old = to_qxl_framebuffer(old_state->fb); + bo_old = gem_to_qxl_bo(qfb_old->obj); + bo_old->is_primary = false; } - if (old_bo && old_bo != bo) { - old_bo->is_primary = false; - ret = qxl_bo_reserve(old_bo, false); - qxl_bo_unpin(old_bo); - qxl_bo_unreserve(old_bo); + bo->is_primary = true; + qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); +} + +static void qxl_primary_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct qxl_device *qdev = plane->dev->dev_private; + + if (old_state->fb) + { struct qxl_framebuffer *qfb = + to_qxl_framebuffer(old_state->fb); + struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); + + qxl_io_destroy_primary(qdev); + bo->is_primary = false; } +} - qxl_monitors_config_set(qdev, qcrtc->index, x, y, - mode->hdisplay, - mode->vdisplay, surf_id); +int qxl_plane_atomic_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ return 0; } -static void qxl_crtc_prepare(struct drm_crtc *crtc) +static void qxl_cursor_atomic_update(struct drm_plane *plane, + struct drm_plane_state *old_state) { - DRM_DEBUG("current: %dx%d+%d+%d (%d).\n", - crtc->mode.hdisplay, crtc->mode.vdisplay, - crtc->x, crtc->y, crtc->enabled); + struct drm_device *dev = plane->dev; + struct qxl_device *qdev = dev->dev_private; + struct drm_framebuffer *fb = plane->state->fb; + struct qxl_release *release; + struct qxl_cursor_cmd *cmd; + struct qxl_cursor *cursor; + struct drm_gem_object *obj; + struct qxl_bo *cursor_bo, *user_bo = NULL; + int ret; + void *user_ptr; + int size = 64*64*4; + + ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), + QXL_RELEASE_CURSOR_CMD, + &release, NULL); + if (ret) + return; + + cmd = (struct qxl_cursor_cmd *) qxl_release_map(qdev, release); + + if (fb != old_state->fb) { + obj = to_qxl_framebuffer(fb)->obj; + user_bo = gem_to_qxl_bo(obj); + + /* pinning is done in the prepare/cleanup framevbuffer */ + ret = qxl_bo_kmap(user_bo, &user_ptr); + if (ret) + goto out_free_release; + + ret = qxl_alloc_bo_reserved(qdev, release, + sizeof(struct qxl_cursor) + size, + &cursor_bo); + if (ret) + goto out_kunmap; + + ret = qxl_release_reserve_list(release, true); + if (ret) + goto out_free_bo; + + ret = qxl_bo_kmap(cursor_bo, (void **)&cursor); + if (ret) + goto out_backoff; + + cursor->header.unique = 0; + cursor->header.type = SPICE_CURSOR_TYPE_ALPHA; + cursor->header.width = 64; + cursor->header.height = 64; + cursor->header.hot_spot_x = fb->hot_x; + cursor->header.hot_spot_y = fb->hot_y; + cursor->data_size = size; + cursor->chunk.next_chunk = 0; + cursor->chunk.prev_chunk = 0; + cursor->chunk.data_size = size; + memcpy(cursor->chunk.data, user_ptr, size); + qxl_bo_kunmap(cursor_bo); + qxl_bo_kunmap(user_bo); + + cmd->u.set.visible = 1; + cmd->u.set.shape = qxl_bo_physical_address(qdev, + cursor_bo, 0); + cmd->type = QXL_CURSOR_SET; + } else { + + ret = qxl_release_reserve_list(release, true); + if (ret) + goto out_free_release; + + cmd->type = QXL_CURSOR_MOVE; + } + + cmd->u.position.x = plane->state->crtc_x + fb->hot_x; + cmd->u.position.y = plane->state->crtc_y + fb->hot_y; + + qxl_release_unmap(qdev, release, &cmd->release_info); + qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); + qxl_release_fence_buffer_objects(release); + + return; + +out_backoff: + qxl_release_backoff_reserve_list(release); +out_free_bo: + qxl_bo_unref(&cursor_bo); +out_kunmap: + qxl_bo_kunmap(user_bo); +out_free_release: + qxl_release_free(qdev, release); + return; + } -static void qxl_crtc_commit(struct drm_crtc *crtc) +void qxl_cursor_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) { - DRM_DEBUG("\n"); + struct qxl_device *qdev = plane->dev->dev_private; + struct qxl_release *release; + struct qxl_cursor_cmd *cmd; + int ret; + + ret = qxl_alloc_release_reserved(qdev, sizeof(*cmd), + QXL_RELEASE_CURSOR_CMD, + &release, NULL); + if (ret) + return; + + ret = qxl_release_reserve_list(release, true); + if (ret) { + qxl_release_free(qdev, release); + return; + } + + cmd = (struct qxl_cursor_cmd *)qxl_release_map(qdev, release); + cmd->type = QXL_CURSOR_HIDE; + qxl_release_unmap(qdev, release, &cmd->release_info); + + qxl_push_cursor_ring_release(qdev, release, QXL_CMD_CURSOR, false); + qxl_release_fence_buffer_objects(release); } -static void qxl_crtc_disable(struct drm_crtc *crtc) +int qxl_plane_prepare_fb(struct drm_plane *plane, + struct drm_plane_state *new_state) { - struct qxl_crtc *qcrtc = to_qxl_crtc(crtc); - struct drm_device *dev = crtc->dev; - struct qxl_device *qdev = dev->dev_private; - if (crtc->primary->fb) { - struct qxl_framebuffer *qfb = to_qxl_framebuffer(crtc->primary->fb); - struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj); - int ret; - ret = qxl_bo_reserve(bo, false); - qxl_bo_unpin(bo); - qxl_bo_unreserve(bo); - crtc->primary->fb = NULL; - } + struct drm_gem_object *obj; + struct qxl_bo *user_bo; + int ret; - qxl_monitors_config_set(qdev, qcrtc->index, 0, 0, 0, 0, 0); + if (!new_state->fb) + return 0; - qxl_send_monitors_config(qdev); + obj = to_qxl_framebuffer(new_state->fb)->obj; + user_bo = gem_to_qxl_bo(obj); + + ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); + if (ret) + return ret; + + return 0; } -static const struct drm_crtc_helper_funcs qxl_crtc_helper_funcs = { - .dpms = qxl_crtc_dpms, - .disable = qxl_crtc_disable, - .mode_fixup = qxl_crtc_mode_fixup, - .mode_set = qxl_crtc_mode_set, - .prepare = qxl_crtc_prepare, - .commit = qxl_crtc_commit, +static void qxl_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct drm_gem_object *obj; + struct qxl_bo *user_bo; + + if (!plane->state->fb) { + /* we never executed prepare_fb, so there's nothing to + * unpin. + */ + return; + } + + obj = to_qxl_framebuffer(plane->state->fb)->obj; + user_bo = gem_to_qxl_bo(obj); + qxl_bo_unpin(user_bo); +} + +static const uint32_t qxl_cursor_plane_formats[] = { + DRM_FORMAT_ARGB8888, +}; + +static const struct drm_plane_helper_funcs qxl_cursor_helper_funcs = { + .atomic_check = qxl_plane_atomic_check, + .atomic_update = qxl_cursor_atomic_update, + .atomic_disable = qxl_cursor_atomic_disable, + .prepare_fb = qxl_plane_prepare_fb, + .cleanup_fb = qxl_plane_cleanup_fb, +}; + +static const struct drm_plane_funcs qxl_cursor_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_primary_helper_destroy, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static const uint32_t qxl_primary_plane_formats[] = { + DRM_FORMAT_XRGB8888, + DRM_FORMAT_ARGB8888, +}; + +static const struct drm_plane_helper_funcs primary_helper_funcs = { + .atomic_check = qxl_primary_atomic_check, + .atomic_update = qxl_primary_atomic_update, + .atomic_disable = qxl_primary_atomic_disable, + .prepare_fb = qxl_plane_prepare_fb, + .cleanup_fb = qxl_plane_cleanup_fb, }; +static const struct drm_plane_funcs qxl_primary_plane_funcs = { + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, + .destroy = drm_primary_helper_destroy, + .reset = drm_atomic_helper_plane_reset, + .atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_plane_destroy_state, +}; + +static struct drm_plane *qxl_create_plane(struct qxl_device *qdev, + unsigned int possible_crtcs, + enum drm_plane_type type) +{ + const struct drm_plane_helper_funcs *helper_funcs = NULL; + struct drm_plane *plane; + const struct drm_plane_funcs *funcs; + const uint32_t *formats; + int num_formats; + int err; + + if (type == DRM_PLANE_TYPE_PRIMARY) { + funcs = &qxl_primary_plane_funcs; + formats = qxl_primary_plane_formats; + num_formats = ARRAY_SIZE(qxl_primary_plane_formats); + helper_funcs = &primary_helper_funcs; + } else if (type == DRM_PLANE_TYPE_CURSOR) { + funcs = &qxl_cursor_plane_funcs; + formats = qxl_cursor_plane_formats; + helper_funcs = &qxl_cursor_helper_funcs; + num_formats = ARRAY_SIZE(qxl_cursor_plane_formats); + } else { + return ERR_PTR(-EINVAL); + } + + plane = kzalloc(sizeof(*plane), GFP_KERNEL); + if (!plane) + return ERR_PTR(-ENOMEM); + + err = drm_universal_plane_init(&qdev->ddev, plane, possible_crtcs, + funcs, formats, num_formats, + type, NULL); + if (err) + goto free_plane; + + drm_plane_helper_add(plane, helper_funcs); + + return plane; + +free_plane: + kfree(plane); + return ERR_PTR(-EINVAL); +} + static int qdev_crtc_init(struct drm_device *dev, int crtc_id) { struct qxl_crtc *qxl_crtc; + struct drm_plane *primary, *cursor; + struct qxl_device *qdev = dev->dev_private; + int r; qxl_crtc = kzalloc(sizeof(struct qxl_crtc), GFP_KERNEL); if (!qxl_crtc) return -ENOMEM; - drm_crtc_init(dev, &qxl_crtc->base, &qxl_crtc_funcs); + primary = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_PRIMARY); + if (IS_ERR(primary)) { + r = -ENOMEM; + goto free_mem; + } + + cursor = qxl_create_plane(qdev, 1 << crtc_id, DRM_PLANE_TYPE_CURSOR); + if (IS_ERR(cursor)) { + r = -ENOMEM; + goto clean_primary; + } + + r = drm_crtc_init_with_planes(dev, &qxl_crtc->base, primary, cursor, + &qxl_crtc_funcs, NULL); + if (r) + goto clean_cursor; + qxl_crtc->index = crtc_id; drm_crtc_helper_add(&qxl_crtc->base, &qxl_crtc_helper_funcs); return 0; + +clean_cursor: + drm_plane_cleanup(cursor); + kfree(cursor); +clean_primary: + drm_plane_cleanup(primary); + kfree(primary); +free_mem: + kfree(qxl_crtc); + return r; } static void qxl_enc_dpms(struct drm_encoder *encoder, int mode) @@ -908,19 +921,13 @@ static void qxl_enc_mode_set(struct drm_encoder *encoder, static int qxl_conn_get_modes(struct drm_connector *connector) { - int ret = 0; - struct qxl_device *qdev = connector->dev->dev_private; unsigned pwidth = 1024; unsigned pheight = 768; + int ret = 0; - DRM_DEBUG_KMS("monitors_config=%p\n", qdev->monitors_config); - /* TODO: what should we do here? only show the configured modes for the - * device, or allow the full list, or both? */ - if (qdev->monitors_config && qdev->monitors_config->count) { - ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight); - if (ret < 0) - return ret; - } + ret = qxl_add_monitors_config_modes(connector, &pwidth, &pheight); + if (ret < 0) + return ret; ret += qxl_add_common_modes(connector, pwidth, pheight); return ret; } @@ -1019,6 +1026,9 @@ static const struct drm_connector_funcs qxl_connector_funcs = { .fill_modes = drm_helper_probe_single_connector_modes, .set_property = qxl_conn_set_property, .destroy = qxl_conn_destroy, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; static void qxl_enc_destroy(struct drm_encoder *encoder) @@ -1109,6 +1119,8 @@ qxl_user_framebuffer_create(struct drm_device *dev, static const struct drm_mode_config_funcs qxl_mode_funcs = { .fb_create = qxl_user_framebuffer_create, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, }; int qxl_create_monitors_object(struct qxl_device *qdev) @@ -1128,17 +1140,9 @@ int qxl_create_monitors_object(struct qxl_device *qdev) } qdev->monitors_config_bo = gem_to_qxl_bo(gobj); - ret = qxl_bo_reserve(qdev->monitors_config_bo, false); - if (ret) - return ret; - ret = qxl_bo_pin(qdev->monitors_config_bo, QXL_GEM_DOMAIN_VRAM, NULL); - if (ret) { - qxl_bo_unreserve(qdev->monitors_config_bo); + if (ret) return ret; - } - - qxl_bo_unreserve(qdev->monitors_config_bo); qxl_bo_kmap(qdev->monitors_config_bo, NULL); @@ -1159,13 +1163,10 @@ int qxl_destroy_monitors_object(struct qxl_device *qdev) qdev->ram_header->monitors_config = 0; qxl_bo_kunmap(qdev->monitors_config_bo); - ret = qxl_bo_reserve(qdev->monitors_config_bo, false); + ret = qxl_bo_unpin(qdev->monitors_config_bo); if (ret) return ret; - qxl_bo_unpin(qdev->monitors_config_bo); - qxl_bo_unreserve(qdev->monitors_config_bo); - qxl_bo_unref(&qdev->monitors_config_bo); return 0; } @@ -1184,8 +1185,8 @@ int qxl_modeset_init(struct qxl_device *qdev) qdev->ddev.mode_config.funcs = (void *)&qxl_mode_funcs; /* modes will be validated against the framebuffer size */ - qdev->ddev.mode_config.min_width = 320; - qdev->ddev.mode_config.min_height = 200; + qdev->ddev.mode_config.min_width = 0; + qdev->ddev.mode_config.min_height = 0; qdev->ddev.mode_config.max_width = 8192; qdev->ddev.mode_config.max_height = 8192; @@ -1199,8 +1200,11 @@ int qxl_modeset_init(struct qxl_device *qdev) qdev_output_init(&qdev->ddev, i); } + qxl_display_read_client_monitors_config(qdev); qdev->mode_info.mode_config_initialized = true; + drm_mode_config_reset(&qdev->ddev); + /* primary surface must be created by this point, to allow * issuing command queue commands and having them read by * spice server. */ diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index 8e17c241e63c..abf7b8360361 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -79,17 +79,13 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (ret) goto free_dev; - ret = qxl_device_init(qdev, &qxl_driver, pdev, ent->driver_data); + ret = qxl_device_init(qdev, &qxl_driver, pdev); if (ret) goto disable_pci; - ret = drm_vblank_init(&qdev->ddev, 1); - if (ret) - goto unload; - ret = qxl_modeset_init(qdev); if (ret) - goto vblank_cleanup; + goto unload; drm_kms_helper_poll_init(&qdev->ddev); @@ -102,8 +98,6 @@ qxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) modeset_cleanup: qxl_modeset_fini(qdev); -vblank_cleanup: - drm_vblank_cleanup(&qdev->ddev); unload: qxl_device_fini(qdev); disable_pci: @@ -247,21 +241,6 @@ static int qxl_pm_restore(struct device *dev) return qxl_drm_resume(drm_dev, false); } -static u32 qxl_noop_get_vblank_counter(struct drm_device *dev, - unsigned int pipe) -{ - return 0; -} - -static int qxl_noop_enable_vblank(struct drm_device *dev, unsigned int pipe) -{ - return 0; -} - -static void qxl_noop_disable_vblank(struct drm_device *dev, unsigned int pipe) -{ -} - static const struct dev_pm_ops qxl_pm_ops = { .suspend = qxl_pm_suspend, .resume = qxl_pm_resume, @@ -280,10 +259,8 @@ static struct pci_driver qxl_pci_driver = { static struct drm_driver qxl_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED, - .get_vblank_counter = qxl_noop_get_vblank_counter, - .enable_vblank = qxl_noop_enable_vblank, - .disable_vblank = qxl_noop_disable_vblank, + DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | + DRIVER_ATOMIC, .set_busid = drm_pci_set_busid, @@ -292,7 +269,6 @@ static struct drm_driver qxl_driver = { .dumb_destroy = drm_gem_dumb_destroy, #if defined(CONFIG_DEBUG_FS) .debugfs_init = qxl_debugfs_init, - .debugfs_cleanup = qxl_debugfs_takedown, #endif .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 785c17b56f73..5ea290a33a68 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -134,11 +134,6 @@ struct qxl_bo_list { struct qxl_crtc { struct drm_crtc base; int index; - int cur_x; - int cur_y; - int hot_spot_x; - int hot_spot_y; - struct qxl_bo *cursor_bo; }; struct qxl_output { @@ -165,8 +160,6 @@ struct qxl_mman { }; struct qxl_mode_info { - int num_modes; - struct qxl_mode *modes; bool mode_config_initialized; /* pointer to fbdev info structure */ @@ -237,13 +230,11 @@ int qxl_debugfs_add_files(struct qxl_device *rdev, struct drm_info_list *files, unsigned nfiles); int qxl_debugfs_fence_init(struct qxl_device *rdev); -void qxl_debugfs_remove_files(struct qxl_device *qdev); struct qxl_device; struct qxl_device { struct drm_device ddev; - unsigned long flags; resource_size_t vram_base, vram_size; resource_size_t surfaceram_base, surfaceram_size; @@ -335,7 +326,7 @@ extern const struct drm_ioctl_desc qxl_ioctls[]; extern int qxl_max_ioctl; int qxl_device_init(struct qxl_device *qdev, struct drm_driver *drv, - struct pci_dev *pdev, unsigned long flags); + struct pci_dev *pdev); void qxl_device_fini(struct qxl_device *qdev); int qxl_modeset_init(struct qxl_device *qdev); @@ -529,7 +520,6 @@ int qxl_garbage_collect(struct qxl_device *qdev); /* debugfs */ int qxl_debugfs_init(struct drm_minor *minor); -void qxl_debugfs_takedown(struct drm_minor *minor); int qxl_ttm_debugfs_init(struct qxl_device *qdev); /* qxl_prime.c */ diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index d479b7a7abe4..14e2a49a4dcf 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -90,14 +90,10 @@ static struct fb_ops qxlfb_ops = { static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj) { struct qxl_bo *qbo = gem_to_qxl_bo(gobj); - int ret; - ret = qxl_bo_reserve(qbo, false); - if (likely(ret == 0)) { - qxl_bo_kunmap(qbo); - qxl_bo_unpin(qbo); - qxl_bo_unreserve(qbo); - } + qxl_bo_kunmap(qbo); + qxl_bo_unpin(qbo); + drm_gem_object_unreference_unlocked(gobj); } @@ -148,16 +144,13 @@ static int qxlfb_create_pinned_object(struct qxl_fbdev *qfbdev, qbo->surf.height = mode_cmd->height; qbo->surf.stride = mode_cmd->pitches[0]; qbo->surf.format = SPICE_SURFACE_FMT_32_xRGB; - ret = qxl_bo_reserve(qbo, false); - if (unlikely(ret != 0)) - goto out_unref; + ret = qxl_bo_pin(qbo, QXL_GEM_DOMAIN_SURFACE, NULL); if (ret) { - qxl_bo_unreserve(qbo); goto out_unref; } ret = qxl_bo_kmap(qbo, NULL); - qxl_bo_unreserve(qbo); /* unreserve, will be mmaped */ + if (ret) goto out_unref; @@ -305,7 +298,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, if (info->screen_base == NULL) { ret = -ENOSPC; - goto out_destroy_fbi; + goto out_unref; } #ifdef CONFIG_DRM_FBDEV_EMULATION @@ -320,16 +313,10 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, fb->format->depth, fb->pitches[0], fb->width, fb->height); return 0; -out_destroy_fbi: - drm_fb_helper_release_fbi(&qfbdev->helper); out_unref: if (qbo) { - ret = qxl_bo_reserve(qbo, false); - if (likely(ret == 0)) { - qxl_bo_kunmap(qbo); - qxl_bo_unpin(qbo); - qxl_bo_unreserve(qbo); - } + qxl_bo_kunmap(qbo); + qxl_bo_unpin(qbo); } if (fb && ret) { drm_gem_object_unreference_unlocked(gobj); @@ -363,7 +350,6 @@ static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev) struct qxl_framebuffer *qfb = &qfbdev->qfb; drm_fb_helper_unregister_fbi(&qfbdev->helper); - drm_fb_helper_release_fbi(&qfbdev->helper); if (qfb->obj) { qxlfb_destroy_pinned_object(qfb->obj); @@ -382,9 +368,11 @@ static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = { int qxl_fbdev_init(struct qxl_device *qdev) { + int ret = 0; + +#ifdef CONFIG_DRM_FBDEV_EMULATION struct qxl_fbdev *qfbdev; int bpp_sel = 32; /* TODO: parameter from somewhere? */ - int ret; qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL); if (!qfbdev) @@ -417,6 +405,8 @@ fini: drm_fb_helper_fini(&qfbdev->helper); free: kfree(qfbdev); +#endif + return ret; } @@ -432,6 +422,9 @@ void qxl_fbdev_fini(struct qxl_device *qdev) void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state) { + if (!qdev->mode_info.qfbdev) + return; + drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state); } diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 2dcd5c14cb56..c5716a0ca3b8 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -31,19 +31,9 @@ int qxl_log_level; -static void qxl_dump_mode(struct qxl_device *qdev, void *p) -{ - struct qxl_mode *m = p; - DRM_DEBUG_KMS("%d: %dx%d %d bits, stride %d, %dmm x %dmm, orientation %d\n", - m->id, m->x_res, m->y_res, m->bits, m->stride, m->x_mili, - m->y_mili, m->orientation); -} - static bool qxl_check_device(struct qxl_device *qdev) { struct qxl_rom *rom = qdev->rom; - int mode_offset; - int i; if (rom->magic != 0x4f525851) { DRM_ERROR("bad rom signature %x\n", rom->magic); @@ -53,8 +43,6 @@ static bool qxl_check_device(struct qxl_device *qdev) DRM_INFO("Device Version %d.%d\n", rom->id, rom->update_id); DRM_INFO("Compression level %d log level %d\n", rom->compression_level, rom->log_level); - DRM_INFO("Currently using mode #%d, list at 0x%x\n", - rom->mode, rom->modes_offset); DRM_INFO("%d io pages at offset 0x%x\n", rom->num_io_pages, rom->pages_offset); DRM_INFO("%d byte draw area at offset 0x%x\n", @@ -62,14 +50,6 @@ static bool qxl_check_device(struct qxl_device *qdev) qdev->vram_size = rom->surface0_area_size; DRM_INFO("RAM header offset: 0x%x\n", rom->ram_header_offset); - - mode_offset = rom->modes_offset / 4; - qdev->mode_info.num_modes = ((u32 *)rom)[mode_offset]; - DRM_INFO("rom modes offset 0x%x for %d modes\n", rom->modes_offset, - qdev->mode_info.num_modes); - qdev->mode_info.modes = (void *)((uint32_t *)rom + mode_offset + 1); - for (i = 0; i < qdev->mode_info.num_modes; i++) - qxl_dump_mode(qdev, qdev->mode_info.modes + i); return true; } @@ -117,8 +97,7 @@ static void qxl_gc_work(struct work_struct *work) int qxl_device_init(struct qxl_device *qdev, struct drm_driver *drv, - struct pci_dev *pdev, - unsigned long flags) + struct pci_dev *pdev) { int r, sb; @@ -130,8 +109,6 @@ int qxl_device_init(struct qxl_device *qdev, pci_set_drvdata(pdev, &qdev->ddev); qdev->ddev.dev_private = qdev; - qdev->flags = flags; - mutex_init(&qdev->gem.mutex); mutex_init(&qdev->update_area_mutex); mutex_init(&qdev->release_mutex); @@ -285,7 +262,4 @@ void qxl_device_fini(struct qxl_device *qdev) iounmap(qdev->ram_header); iounmap(qdev->rom); qdev->rom = NULL; - qdev->mode_info.modes = NULL; - qdev->mode_info.num_modes = 0; - qxl_debugfs_remove_files(qdev); } diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index dbc13510a1f8..9a7eef7dd604 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -221,7 +221,7 @@ struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) return bo; } -int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +int __qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) { struct drm_device *ddev = bo->gem_base.dev; int r; @@ -244,7 +244,7 @@ int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) return r; } -int qxl_bo_unpin(struct qxl_bo *bo) +int __qxl_bo_unpin(struct qxl_bo *bo) { struct drm_device *ddev = bo->gem_base.dev; int r, i; @@ -264,6 +264,43 @@ int qxl_bo_unpin(struct qxl_bo *bo) return r; } + +/* + * Reserve the BO before pinning the object. If the BO was reserved + * beforehand, use the internal version directly __qxl_bo_pin. + * + */ +int qxl_bo_pin(struct qxl_bo *bo, u32 domain, u64 *gpu_addr) +{ + int r; + + r = qxl_bo_reserve(bo, false); + if (r) + return r; + + r = __qxl_bo_pin(bo, bo->type, NULL); + qxl_bo_unreserve(bo); + return r; +} + +/* + * Reserve the BO before pinning the object. If the BO was reserved + * beforehand, use the internal version directly __qxl_bo_unpin. + * + */ +int qxl_bo_unpin(struct qxl_bo *bo) +{ + int r; + + r = qxl_bo_reserve(bo, false); + if (r) + return r; + + r = __qxl_bo_unpin(bo); + qxl_bo_unreserve(bo); + return r; +} + void qxl_bo_force_delete(struct qxl_device *qdev) { struct qxl_bo *bo, *n; diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 7d1cab57c89e..0fdedee4509d 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -393,6 +393,7 @@ static struct ttm_bo_driver qxl_bo_driver = { .verify_access = &qxl_verify_access, .io_mem_reserve = &qxl_ttm_io_mem_reserve, .io_mem_free = &qxl_ttm_io_mem_free, + .io_mem_pfn = ttm_bo_default_io_mem_pfn, .move_notify = &qxl_bo_move_notify, }; |