From b0119cb9229d0db0d8c3ec8b302d549775e03a0c Mon Sep 17 00:00:00 2001 From: Sinclair Yeh Date: Thu, 23 Mar 2017 14:38:18 -0700 Subject: [PATCH] drm/vmwgfx: Switch over to internal atomic API for SOU and LDU Switch over to internal atomic API. This completes the atomic internal atomic switch for all the Display Units. Signed-off-by: Sinclair Yeh Signed-off-by: Thomas Hellstrom Reviewed-by: Thomas Hellstrom --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 103 ++--------------- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 217 +++-------------------------------- 2 files changed, 25 insertions(+), 295 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 1b9e083..5e2f639 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -95,7 +95,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) if (crtc == NULL) return 0; - fb = entry->base.crtc.primary->fb; + fb = entry->base.crtc.primary->state->fb; return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], fb->format->cpp[0] * 8, @@ -104,7 +104,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) if (!list_empty(&lds->active)) { entry = list_entry(lds->active.next, typeof(*entry), active); - fb = entry->base.crtc.primary->fb; + fb = entry->base.crtc.primary->state->fb; vmw_kms_write_svga(dev_priv, fb->width, fb->height, fb->pitches[0], fb->format->cpp[0] * 8, fb->format->depth); @@ -255,102 +255,13 @@ static void vmw_ldu_crtc_helper_disable(struct drm_crtc *crtc) { } -static int vmw_ldu_crtc_set_config(struct drm_mode_set *set) -{ - struct vmw_private *dev_priv; - struct vmw_legacy_display_unit *ldu; - struct drm_connector *connector; - struct drm_display_mode *mode; - struct drm_encoder *encoder; - struct vmw_framebuffer *vfb; - struct drm_framebuffer *fb; - struct drm_crtc *crtc; - - if (!set) - return -EINVAL; - - if (!set->crtc) - return -EINVAL; - - /* get the ldu */ - crtc = set->crtc; - ldu = vmw_crtc_to_ldu(crtc); - vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; - dev_priv = vmw_priv(crtc->dev); - - if (set->num_connectors > 1) { - DRM_ERROR("to many connectors\n"); - return -EINVAL; - } - - if (set->num_connectors == 1 && - set->connectors[0] != &ldu->base.connector) { - DRM_ERROR("connector doesn't match %p %p\n", - set->connectors[0], &ldu->base.connector); - return -EINVAL; - } - - /* ldu only supports one fb active at the time */ - if (dev_priv->ldu_priv->fb && vfb && - !(dev_priv->ldu_priv->num_active == 1 && - !list_empty(&ldu->active)) && - dev_priv->ldu_priv->fb != vfb) { - DRM_ERROR("Multiple framebuffers not supported\n"); - return -EINVAL; - } - - /* since they always map one to one these are safe */ - connector = &ldu->base.connector; - encoder = &ldu->base.encoder; - - /* should we turn the crtc off? */ - if (set->num_connectors == 0 || !set->mode || !set->fb) { - - connector->encoder = NULL; - encoder->crtc = NULL; - crtc->primary->fb = NULL; - crtc->enabled = false; - - vmw_ldu_del_active(dev_priv, ldu); - - return vmw_ldu_commit_list(dev_priv); - } - - - /* we now know we want to set a mode */ - mode = set->mode; - fb = set->fb; - - if (set->x + mode->hdisplay > fb->width || - set->y + mode->vdisplay > fb->height) { - DRM_ERROR("set outside of framebuffer\n"); - return -EINVAL; - } - - vmw_svga_enable(dev_priv); - - crtc->primary->fb = fb; - encoder->crtc = crtc; - connector->encoder = encoder; - crtc->x = set->x; - crtc->y = set->y; - crtc->mode = *mode; - crtc->enabled = true; - ldu->base.set_gui_x = set->x; - ldu->base.set_gui_y = set->y; - - vmw_ldu_add_active(dev_priv, ldu, vfb); - - return vmw_ldu_commit_list(dev_priv); -} - static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, .reset = vmw_du_crtc_reset, .atomic_duplicate_state = vmw_du_crtc_duplicate_state, .atomic_destroy_state = vmw_du_crtc_destroy_state, - .set_config = vmw_ldu_crtc_set_config, + .set_config = vmw_kms_set_config, }; @@ -439,8 +350,8 @@ vmw_ldu_primary_plane_atomic_update(struct drm_plane *plane, static const struct drm_plane_funcs vmw_ldu_plane_funcs = { - .update_plane = drm_primary_helper_update, - .disable_plane = drm_primary_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = vmw_du_primary_plane_destroy, .reset = vmw_du_plane_reset, .atomic_duplicate_state = vmw_du_plane_duplicate_state, @@ -448,8 +359,8 @@ static const struct drm_plane_funcs vmw_ldu_plane_funcs = { }; static const struct drm_plane_funcs vmw_ldu_cursor_funcs = { - .update_plane = vmw_du_cursor_plane_update, - .disable_plane = vmw_du_cursor_plane_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = vmw_du_cursor_plane_destroy, .reset = vmw_du_plane_reset, .atomic_duplicate_state = vmw_du_plane_duplicate_state, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 536f4b5..106a943 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -205,52 +205,6 @@ static int vmw_sou_fifo_destroy(struct vmw_private *dev_priv, } /** - * Free the backing store. - */ -static void vmw_sou_backing_free(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou) -{ - vmw_dmabuf_unreference(&sou->buffer); - sou->buffer_size = 0; -} - -/** - * Allocate the backing store for the buffer. - */ -static int vmw_sou_backing_alloc(struct vmw_private *dev_priv, - struct vmw_screen_object_unit *sou, - unsigned long size) -{ - int ret; - - if (sou->buffer_size == size) - return 0; - - if (sou->buffer) - vmw_sou_backing_free(dev_priv, sou); - - sou->buffer = kzalloc(sizeof(*sou->buffer), GFP_KERNEL); - if (unlikely(sou->buffer == NULL)) - return -ENOMEM; - - /* After we have alloced the backing store might not be able to - * resume the overlays, this is preferred to failing to alloc. - */ - vmw_overlay_pause_all(dev_priv); - ret = vmw_dmabuf_init(dev_priv, sou->buffer, size, - &vmw_vram_ne_placement, - false, &vmw_dmabuf_bo_free); - vmw_overlay_resume_all(dev_priv); - - if (unlikely(ret != 0)) - sou->buffer = NULL; /* vmw_dmabuf_init frees on error */ - else - sou->buffer_size = size; - - return ret; -} - -/** * vmw_sou_crtc_mode_set_nofb - Create new screen * * @crtc: CRTC associated with the new screen @@ -353,158 +307,14 @@ static void vmw_sou_crtc_helper_disable(struct drm_crtc *crtc) } } -static int vmw_sou_crtc_set_config(struct drm_mode_set *set) -{ - struct vmw_private *dev_priv; - struct vmw_screen_object_unit *sou; - struct drm_connector *connector; - struct drm_display_mode *mode; - struct drm_encoder *encoder; - struct vmw_framebuffer *vfb; - struct drm_framebuffer *fb; - struct drm_crtc *crtc; - int ret = 0; - - if (!set) - return -EINVAL; - - if (!set->crtc) - return -EINVAL; - - /* get the sou */ - crtc = set->crtc; - sou = vmw_crtc_to_sou(crtc); - vfb = set->fb ? vmw_framebuffer_to_vfb(set->fb) : NULL; - dev_priv = vmw_priv(crtc->dev); - - if (set->num_connectors > 1) { - DRM_ERROR("Too many connectors\n"); - return -EINVAL; - } - - if (set->num_connectors == 1 && - set->connectors[0] != &sou->base.connector) { - DRM_ERROR("Connector doesn't match %p %p\n", - set->connectors[0], &sou->base.connector); - return -EINVAL; - } - - /* Only one active implicit frame-buffer at a time. */ - mutex_lock(&dev_priv->global_kms_state_mutex); - if (sou->base.is_implicit && - dev_priv->implicit_fb && vfb && - !(dev_priv->num_implicit == 1 && - sou->base.active_implicit) && - dev_priv->implicit_fb != vfb) { - mutex_unlock(&dev_priv->global_kms_state_mutex); - DRM_ERROR("Multiple implicit framebuffers not supported.\n"); - return -EINVAL; - } - mutex_unlock(&dev_priv->global_kms_state_mutex); - - /* since they always map one to one these are safe */ - connector = &sou->base.connector; - encoder = &sou->base.encoder; - - /* should we turn the crtc off */ - if (set->num_connectors == 0 || !set->mode || !set->fb) { - ret = vmw_sou_fifo_destroy(dev_priv, sou); - /* the hardware has hung don't do anything more */ - if (unlikely(ret != 0)) - return ret; - - connector->encoder = NULL; - encoder->crtc = NULL; - crtc->primary->fb = NULL; - crtc->x = 0; - crtc->y = 0; - crtc->enabled = false; - - vmw_kms_del_active(dev_priv, &sou->base); - - vmw_sou_backing_free(dev_priv, sou); - - return 0; - } - - - /* we now know we want to set a mode */ - mode = set->mode; - fb = set->fb; - - if (set->x + mode->hdisplay > fb->width || - set->y + mode->vdisplay > fb->height) { - DRM_ERROR("set outside of framebuffer\n"); - return -EINVAL; - } - - vmw_svga_enable(dev_priv); - - if (mode->hdisplay != crtc->mode.hdisplay || - mode->vdisplay != crtc->mode.vdisplay) { - /* no need to check if depth is different, because backing - * store depth is forced to 4 by the device. - */ - - ret = vmw_sou_fifo_destroy(dev_priv, sou); - /* the hardware has hung don't do anything more */ - if (unlikely(ret != 0)) - return ret; - - vmw_sou_backing_free(dev_priv, sou); - } - - if (!sou->buffer) { - /* forced to depth 4 by the device */ - size_t size = mode->hdisplay * mode->vdisplay * 4; - ret = vmw_sou_backing_alloc(dev_priv, sou, size); - if (unlikely(ret != 0)) - return ret; - } - - ret = vmw_sou_fifo_create(dev_priv, sou, set->x, set->y, mode); - if (unlikely(ret != 0)) { - /* - * We are in a bit of a situation here, the hardware has - * hung and we may or may not have a buffer hanging of - * the screen object, best thing to do is not do anything - * if we where defined, if not just turn the crtc of. - * Not what userspace wants but it needs to htfu. - */ - if (sou->defined) - return ret; - - connector->encoder = NULL; - encoder->crtc = NULL; - crtc->primary->fb = NULL; - crtc->x = 0; - crtc->y = 0; - crtc->enabled = false; - - return ret; - } - - vmw_kms_add_active(dev_priv, &sou->base, vfb); - - connector->encoder = encoder; - encoder->crtc = crtc; - crtc->mode = *mode; - crtc->primary->fb = fb; - crtc->x = set->x; - crtc->y = set->y; - crtc->enabled = true; - - return 0; -} - static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, - struct drm_framebuffer *fb, + struct drm_framebuffer *new_fb, struct drm_pending_vblank_event *event, uint32_t flags) { struct vmw_private *dev_priv = vmw_priv(crtc->dev); struct drm_framebuffer *old_fb = crtc->primary->fb; - struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(fb); + struct vmw_framebuffer *vfb = vmw_framebuffer_to_vfb(new_fb); struct vmw_fence_obj *fence = NULL; struct drm_vmw_rect vclips; int ret; @@ -512,7 +322,12 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, if (!vmw_kms_crtc_flippable(dev_priv, crtc)) return -EINVAL; - crtc->primary->fb = fb; + flags &= ~DRM_MODE_PAGE_FLIP_ASYNC; + ret = drm_atomic_helper_page_flip(crtc, new_fb, NULL, flags); + if (ret) { + DRM_ERROR("Page flip error %d.\n", ret); + return ret; + } /* do a full screen dirty update */ vclips.x = crtc->x; @@ -559,7 +374,7 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, return ret; out_no_fence: - crtc->primary->fb = old_fb; + drm_atomic_set_fb_for_plane(crtc->primary->state, old_fb); return ret; } @@ -569,7 +384,7 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .reset = vmw_du_crtc_reset, .atomic_duplicate_state = vmw_du_crtc_duplicate_state, .atomic_destroy_state = vmw_du_crtc_destroy_state, - .set_config = vmw_sou_crtc_set_config, + .set_config = vmw_kms_set_config, .page_flip = vmw_sou_crtc_page_flip, }; @@ -711,12 +526,16 @@ static void vmw_sou_primary_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct drm_crtc *crtc = plane->state->crtc; + + if (crtc) + crtc->primary->fb = plane->state->fb; } static const struct drm_plane_funcs vmw_sou_plane_funcs = { - .update_plane = drm_primary_helper_update, - .disable_plane = drm_primary_helper_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = vmw_du_primary_plane_destroy, .reset = vmw_du_plane_reset, .atomic_duplicate_state = vmw_du_plane_duplicate_state, @@ -724,8 +543,8 @@ static const struct drm_plane_funcs vmw_sou_plane_funcs = { }; static const struct drm_plane_funcs vmw_sou_cursor_funcs = { - .update_plane = vmw_du_cursor_plane_update, - .disable_plane = vmw_du_cursor_plane_disable, + .update_plane = drm_atomic_helper_update_plane, + .disable_plane = drm_atomic_helper_disable_plane, .destroy = vmw_du_cursor_plane_destroy, .reset = vmw_du_plane_reset, .atomic_duplicate_state = vmw_du_plane_duplicate_state, -- 2.7.4