summaryrefslogtreecommitdiffstats
path: root/drivers/staging/vboxvideo/vbox_mode.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/vboxvideo/vbox_mode.c')
-rw-r--r--drivers/staging/vboxvideo/vbox_mode.c121
1 files changed, 62 insertions, 59 deletions
diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c
index 79836c8fb909..47de1364ec4d 100644
--- a/drivers/staging/vboxvideo/vbox_mode.c
+++ b/drivers/staging/vboxvideo/vbox_mode.c
@@ -221,53 +221,68 @@ static bool vbox_set_up_input_mapping(struct vbox_private *vbox)
return old_single_framebuffer != vbox->single_framebuffer;
}
-static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
- struct drm_framebuffer *old_fb,
- struct drm_framebuffer *new_fb,
- int x, int y)
+static int vbox_fb_pin(struct drm_framebuffer *fb, u64 *addr)
+{
+ struct vbox_bo *bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj);
+ int ret;
+
+ ret = vbox_bo_reserve(bo, false);
+ if (ret)
+ return ret;
+
+ ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, addr);
+ vbox_bo_unreserve(bo);
+ return ret;
+}
+
+static void vbox_fb_unpin(struct drm_framebuffer *fb)
{
- struct vbox_private *vbox = crtc->dev->dev_private;
- struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
- struct drm_gem_object *obj;
- struct vbox_framebuffer *vbox_fb;
struct vbox_bo *bo;
int ret;
- u64 gpu_addr;
- /* Unpin the previous fb. */
- if (old_fb) {
- vbox_fb = to_vbox_framebuffer(old_fb);
- obj = vbox_fb->obj;
- bo = gem_to_vbox_bo(obj);
- ret = vbox_bo_reserve(bo, false);
- if (ret)
- return ret;
+ if (!fb)
+ return;
- vbox_bo_unpin(bo);
- vbox_bo_unreserve(bo);
+ bo = gem_to_vbox_bo(to_vbox_framebuffer(fb)->obj);
+
+ ret = vbox_bo_reserve(bo, false);
+ if (ret) {
+ DRM_ERROR("Error %d reserving fb bo, leaving it pinned\n", ret);
+ return;
}
- vbox_fb = to_vbox_framebuffer(new_fb);
- obj = vbox_fb->obj;
- bo = gem_to_vbox_bo(obj);
+ vbox_bo_unpin(bo);
+ vbox_bo_unreserve(bo);
+}
- ret = vbox_bo_reserve(bo, false);
- if (ret)
- return ret;
+static int vbox_crtc_set_base_and_mode(struct drm_crtc *crtc,
+ struct drm_framebuffer *old_fb,
+ struct drm_framebuffer *new_fb,
+ struct drm_display_mode *mode,
+ int x, int y)
+{
+ struct vbox_private *vbox = crtc->dev->dev_private;
+ struct vbox_crtc *vbox_crtc = to_vbox_crtc(crtc);
+ u64 gpu_addr;
+ int ret;
- ret = vbox_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
+ /* Prepare: pin the new framebuffer bo */
+ ret = vbox_fb_pin(new_fb, &gpu_addr);
if (ret) {
- vbox_bo_unreserve(bo);
+ DRM_WARN("Error %d pinning new fb, out of video mem?\n", ret);
return ret;
}
- if (&vbox->fbdev->afb == vbox_fb)
+ /* Commit: Update hardware to use the new fb */
+ mutex_lock(&vbox->hw_mutex);
+
+ if (&vbox->fbdev->afb == to_vbox_framebuffer(new_fb))
vbox_fbdev_set_base(vbox, gpu_addr);
- vbox_bo_unreserve(bo);
- /* vbox_set_start_address_crt1(crtc, (u32)gpu_addr); */
vbox_crtc->fb_offset = gpu_addr;
- if (vbox_set_up_input_mapping(vbox)) {
+
+ /* vbox_do_modeset() checks vbox->single_framebuffer so update it now */
+ if (mode && vbox_set_up_input_mapping(vbox)) {
struct drm_crtc *crtci;
list_for_each_entry(crtci, &vbox->dev->mode_config.crtc_list,
@@ -277,13 +292,20 @@ static int vbox_crtc_do_set_base(struct drm_crtc *crtc,
}
}
- return 0;
-}
+ vbox_set_view(crtc);
+ vbox_do_modeset(crtc, mode ? mode : &crtc->mode);
-static int vbox_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
- struct drm_framebuffer *old_fb)
-{
- return vbox_crtc_do_set_base(crtc, old_fb, CRTC_FB(crtc), x, y);
+ if (mode)
+ hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
+ vbox->input_mapping_width,
+ vbox->input_mapping_height);
+
+ mutex_unlock(&vbox->hw_mutex);
+
+ /* Cleanup: unpin the old fb */
+ vbox_fb_unpin(old_fb);
+
+ return 0;
}
static int vbox_crtc_mode_set(struct drm_crtc *crtc,
@@ -291,21 +313,8 @@ static int vbox_crtc_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *adjusted_mode,
int x, int y, struct drm_framebuffer *old_fb)
{
- struct vbox_private *vbox = crtc->dev->dev_private;
- int ret;
-
- vbox_crtc_mode_set_base(crtc, x, y, old_fb);
-
- mutex_lock(&vbox->hw_mutex);
- ret = vbox_set_view(crtc);
- if (!ret)
- vbox_do_modeset(crtc, mode);
- hgsmi_update_input_mapping(vbox->guest_pool, 0, 0,
- vbox->input_mapping_width,
- vbox->input_mapping_height);
- mutex_unlock(&vbox->hw_mutex);
-
- return ret;
+ return vbox_crtc_set_base_and_mode(crtc, old_fb, CRTC_FB(crtc),
+ mode, x, y);
}
static int vbox_crtc_page_flip(struct drm_crtc *crtc,
@@ -319,15 +328,10 @@ static int vbox_crtc_page_flip(struct drm_crtc *crtc,
unsigned long flags;
int rc;
- rc = vbox_crtc_do_set_base(crtc, CRTC_FB(crtc), fb, 0, 0);
+ rc = vbox_crtc_set_base_and_mode(crtc, CRTC_FB(crtc), fb, NULL, 0, 0);
if (rc)
return rc;
- mutex_lock(&vbox->hw_mutex);
- vbox_set_view(crtc);
- vbox_do_modeset(crtc, &crtc->mode);
- mutex_unlock(&vbox->hw_mutex);
-
spin_lock_irqsave(&drm->event_lock, flags);
if (event)
@@ -354,7 +358,6 @@ static const struct drm_crtc_helper_funcs vbox_crtc_helper_funcs = {
.dpms = vbox_crtc_dpms,
.mode_fixup = vbox_crtc_mode_fixup,
.mode_set = vbox_crtc_mode_set,
- /* .mode_set_base = vbox_crtc_mode_set_base, */
.disable = vbox_crtc_disable,
.prepare = vbox_crtc_prepare,
.commit = vbox_crtc_commit,