From 5ed4fdfa58f091a65cb533cc6b8f47ade4cc4475 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 5 Dec 2017 15:29:00 +0000 Subject: drm/mali-dp: Align pitch size to be multiple of bus burst read size. Mali DP hardware needs pitch line sizes aligned to the bus burst size for reads, so take that into consideration when allocating dumb buffers. If the layer is rotated then the stride size requirement is even larger for some hardware versions, so allocate for the worst case scenario. Update the ->dumb_create() hook to a driver specific function that sets the correct pitch size. Reported-by: Ayan Halder Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers/gpu/drm/arm/malidp_drv.c') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 3d82712d8002..d88a3b9d59cc 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -312,13 +312,26 @@ static int malidp_irq_init(struct platform_device *pdev) DEFINE_DRM_GEM_CMA_FOPS(fops); +static int malidp_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + struct malidp_drm *malidp = drm->dev_private; + /* allocate for the worst case scenario, i.e. rotated buffers */ + u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 1); + + args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment); + + return drm_gem_cma_dumb_create_internal(file_priv, drm, args); +} + static struct drm_driver malidp_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_PRIME, .lastclose = drm_fb_helper_lastclose, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, - .dumb_create = drm_gem_cma_dumb_create, + .dumb_create = malidp_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, -- cgit v1.2.3 From d862b2d622530d14072f3ae417a0525fb7361410 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Thu, 1 Mar 2018 16:38:02 +0000 Subject: drm/mali-dp: Fix malidp_atomic_commit_hw_done() for event sending. Mali DP hardware has a 'go' bit (config_valid) for making the new scene parameters active at the next page flip. The problem with the current code is that the driver first sets this bit and then proceeds to wait for confirmation from the hardware that the configuration has been updated before arming the vblank event. As config_valid is actually asserted by the hardware after the vblank event, during the prefetch phase, when we get to arming the vblank event we are going to send it at the next vblank, in effect halving the vblank rate from the userspace perspective. Fix it by sending the userspace event from the IRQ handler, when we handle the config_valid interrupt, which syncs with the time when the hardware is active with the new parameters. Reported-by: Alexandru-Cosmin Gheorghe Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 32 +++++++++++++++++--------------- drivers/gpu/drm/arm/malidp_drv.h | 1 + drivers/gpu/drm/arm/malidp_hw.c | 12 +++++++++--- 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'drivers/gpu/drm/arm/malidp_drv.c') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index d88a3b9d59cc..3c628e43bf25 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -185,25 +185,29 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm) static void malidp_atomic_commit_hw_done(struct drm_atomic_state *state) { - struct drm_pending_vblank_event *event; struct drm_device *drm = state->dev; struct malidp_drm *malidp = drm->dev_private; - if (malidp->crtc.enabled) { - /* only set config_valid if the CRTC is enabled */ - if (malidp_set_and_wait_config_valid(drm)) - DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n"); - } + malidp->event = malidp->crtc.state->event; + malidp->crtc.state->event = NULL; - event = malidp->crtc.state->event; - if (event) { - malidp->crtc.state->event = NULL; + if (malidp->crtc.state->active) { + /* + * if we have an event to deliver to userspace, make sure + * the vblank is enabled as we are sending it from the IRQ + * handler. + */ + if (malidp->event) + drm_crtc_vblank_get(&malidp->crtc); + /* only set config_valid if the CRTC is enabled */ + if (malidp_set_and_wait_config_valid(drm) < 0) + DRM_DEBUG_DRIVER("timed out waiting for updated configuration\n"); + } else if (malidp->event) { + /* CRTC inactive means vblank IRQ is disabled, send event directly */ spin_lock_irq(&drm->event_lock); - if (drm_crtc_vblank_get(&malidp->crtc) == 0) - drm_crtc_arm_vblank_event(&malidp->crtc, event); - else - drm_crtc_send_vblank_event(&malidp->crtc, event); + drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); + malidp->event = NULL; spin_unlock_irq(&drm->event_lock); } drm_atomic_helper_commit_hw_done(state); @@ -232,8 +236,6 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) malidp_atomic_commit_hw_done(state); - drm_atomic_helper_wait_for_vblanks(drm, state); - pm_runtime_put(drm->dev); drm_atomic_helper_cleanup_planes(drm, state); diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index e0d12c9fc6b8..c2375bb49619 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -22,6 +22,7 @@ struct malidp_drm { struct malidp_hw_device *dev; struct drm_crtc crtc; wait_queue_head_t wq; + struct drm_pending_vblank_event *event; atomic_t config_valid; u32 core_id; }; diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 2bfb542135ac..8abd335ec313 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -782,9 +782,15 @@ static irqreturn_t malidp_de_irq(int irq, void *arg) /* first handle the config valid IRQ */ dc_status = malidp_hw_read(hwdev, hw->map.dc_base + MALIDP_REG_STATUS); if (dc_status & hw->map.dc_irq_map.vsync_irq) { - /* we have a page flip event */ - atomic_set(&malidp->config_valid, 1); malidp_hw_clear_irq(hwdev, MALIDP_DC_BLOCK, dc_status); + /* do we have a page flip event? */ + if (malidp->event != NULL) { + spin_lock(&drm->event_lock); + drm_crtc_send_vblank_event(&malidp->crtc, malidp->event); + malidp->event = NULL; + spin_unlock(&drm->event_lock); + } + atomic_set(&malidp->config_valid, 1); ret = IRQ_WAKE_THREAD; } @@ -794,7 +800,7 @@ static irqreturn_t malidp_de_irq(int irq, void *arg) mask = malidp_hw_read(hwdev, MALIDP_REG_MASKIRQ); status &= mask; - if (status & de->vsync_irq) + if ((status & de->vsync_irq) && malidp->crtc.enabled) drm_crtc_handle_vblank(&malidp->crtc); malidp_hw_clear_irq(hwdev, MALIDP_DE_BLOCK, status); -- cgit v1.2.3 From 084ffbd7fd147ce6e114d82298c84f143d4fff7f Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 17 Jan 2018 23:55:29 +0200 Subject: drm: arm: malidp: Don't destroy planes manually in error handlers The top-level error handler calls drm_mode_config_cleanup() which will destroy all planes. There's no need to destroy them manually in lower error handlers. As plane cleanup is now handled entirely by drm_mode_config_cleanup(), we must ensure that the plane .destroy() handler frees allocated memory for the plane object that was freed by malidp_de_planes_destroy(). Do so by replacing the call to devm_kfree() in the .destroy() handler by kfree(). devm_kfree() is currently a no-op as the plane memory is allocated with kzalloc(), not devm_kzalloc(). Signed-off-by: Laurent Pinchart Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_crtc.c | 10 ++-------- drivers/gpu/drm/arm/malidp_drv.c | 1 - drivers/gpu/drm/arm/malidp_drv.h | 1 - drivers/gpu/drm/arm/malidp_planes.c | 13 +------------ 4 files changed, 3 insertions(+), 22 deletions(-) (limited to 'drivers/gpu/drm/arm/malidp_drv.c') diff --git a/drivers/gpu/drm/arm/malidp_crtc.c b/drivers/gpu/drm/arm/malidp_crtc.c index 7b952559fc43..fcc62bc60f6a 100644 --- a/drivers/gpu/drm/arm/malidp_crtc.c +++ b/drivers/gpu/drm/arm/malidp_crtc.c @@ -531,14 +531,13 @@ int malidp_crtc_init(struct drm_device *drm) if (!primary) { DRM_ERROR("no primary plane found\n"); - ret = -EINVAL; - goto crtc_cleanup_planes; + return -EINVAL; } ret = drm_crtc_init_with_planes(drm, &malidp->crtc, primary, NULL, &malidp_crtc_funcs, NULL); if (ret) - goto crtc_cleanup_planes; + return ret; drm_crtc_helper_add(&malidp->crtc, &malidp_crtc_helper_funcs); drm_mode_crtc_set_gamma_size(&malidp->crtc, MALIDP_GAMMA_LUT_SIZE); @@ -548,9 +547,4 @@ int malidp_crtc_init(struct drm_device *drm) malidp_se_set_enh_coeffs(malidp->dev); return 0; - -crtc_cleanup_planes: - malidp_de_planes_destroy(drm); - - return ret; } diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 3c628e43bf25..2b26f40a9786 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -278,7 +278,6 @@ static int malidp_init(struct drm_device *drm) static void malidp_fini(struct drm_device *drm) { - malidp_de_planes_destroy(drm); drm_mode_config_cleanup(drm); } diff --git a/drivers/gpu/drm/arm/malidp_drv.h b/drivers/gpu/drm/arm/malidp_drv.h index c2375bb49619..c70989b93387 100644 --- a/drivers/gpu/drm/arm/malidp_drv.h +++ b/drivers/gpu/drm/arm/malidp_drv.h @@ -60,7 +60,6 @@ struct malidp_crtc_state { #define to_malidp_crtc_state(x) container_of(x, struct malidp_crtc_state, base) int malidp_de_planes_init(struct drm_device *drm); -void malidp_de_planes_destroy(struct drm_device *drm); int malidp_crtc_init(struct drm_device *drm); /* often used combination of rotational bits */ diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 1a2992f178e5..648e97693df9 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -64,7 +64,7 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) drm_plane_helper_disable(plane); drm_plane_cleanup(plane); - devm_kfree(plane->dev->dev, mp); + kfree(mp); } /* @@ -449,18 +449,7 @@ int malidp_de_planes_init(struct drm_device *drm) return 0; cleanup: - malidp_de_planes_destroy(drm); kfree(formats); return ret; } - -void malidp_de_planes_destroy(struct drm_device *drm) -{ - struct drm_plane *p, *pt; - - list_for_each_entry_safe(p, pt, &drm->mode_config.plane_list, head) { - drm_plane_cleanup(p); - kfree(p); - } -} -- cgit v1.2.3 From 828f207077c699a8363415efbcb2a6d8a11bb100 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Wed, 17 Jan 2018 23:55:30 +0200 Subject: drm: arm: malidp: Use drm_atomic_helper_shutdown() to disable planes on removal The plane cleanup handler currently calls drm_plane_helper_disable(), which is a legacy helper function. Replace it with a call to drm_atomic_helper_shutdown() at removal time. Signed-off-by: Laurent Pinchart Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 1 + drivers/gpu/drm/arm/malidp_planes.c | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers/gpu/drm/arm/malidp_drv.c') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 2b26f40a9786..274db28c0648 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -278,6 +278,7 @@ static int malidp_init(struct drm_device *drm) static void malidp_fini(struct drm_device *drm) { + drm_atomic_helper_shutdown(drm); drm_mode_config_cleanup(drm); } diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 648e97693df9..5e64060cc8fc 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -59,10 +59,6 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) { struct malidp_plane *mp = to_malidp_plane(plane); - if (mp->base.fb) - drm_framebuffer_put(mp->base.fb); - - drm_plane_helper_disable(plane); drm_plane_cleanup(plane); kfree(mp); } -- cgit v1.2.3 From 57085dca982bd042f64aa23f5e03747595b2c8c0 Mon Sep 17 00:00:00 2001 From: Liviu Dudau Date: Tue, 27 Feb 2018 18:23:06 +0000 Subject: drm: mali-dp: Turn off CRTC vblank when removing module. When unbinding the mali-dp driver the drm_vblank_cleanup() function warns us that the vblanks are still enabled. Fix that by calling drm_crtc_vblank_off() in the malidp_unbind() function. Signed-off-by: Liviu Dudau --- drivers/gpu/drm/arm/malidp_drv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/arm/malidp_drv.c') diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index 274db28c0648..8d20faa198cf 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -677,8 +677,10 @@ static void malidp_unbind(struct device *dev) drm_fb_cma_fbdev_fini(drm); drm_kms_helper_poll_fini(drm); pm_runtime_get_sync(dev); + drm_crtc_vblank_off(&malidp->crtc); malidp_se_irq_fini(drm); malidp_de_irq_fini(drm); + drm->irq_enabled = false; component_unbind_all(dev, drm); of_node_put(malidp->crtc.port); malidp->crtc.port = NULL; -- cgit v1.2.3