summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/rockchip/rockchip_drm_vop.c')
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_vop.c39
1 files changed, 30 insertions, 9 deletions
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index b0179849de96..90eb9a3bcf03 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -26,6 +26,7 @@
#include <drm/drm_gem_framebuffer_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_probe_helper.h>
+#include <drm/drm_self_refresh_helper.h>
#include <drm/drm_vblank.h>
#ifdef CONFIG_DRM_ANALOGIX_DP
@@ -35,10 +36,11 @@
#include "rockchip_drm_drv.h"
#include "rockchip_drm_gem.h"
#include "rockchip_drm_fb.h"
-#include "rockchip_drm_psr.h"
#include "rockchip_drm_vop.h"
#include "rockchip_rgb.h"
+#define VOP_SELF_REFRESH_ENTRY_DELAY_MS 100
+
#define VOP_WIN_SET(vop, win, name, v) \
vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name)
#define VOP_SCL_SET(vop, win, name, v) \
@@ -541,7 +543,7 @@ static void vop_win_disable(struct vop *vop, const struct vop_win_data *win)
VOP_WIN_SET(vop, win, enable, 0);
}
-static int vop_enable(struct drm_crtc *crtc)
+static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state)
{
struct vop *vop = to_vop(crtc);
int ret, i;
@@ -581,12 +583,18 @@ static int vop_enable(struct drm_crtc *crtc)
* We need to make sure that all windows are disabled before we
* enable the crtc. Otherwise we might try to scan from a destroyed
* buffer later.
+ *
+ * In the case of enable-after-PSR, we don't need to worry about this
+ * case since the buffer is guaranteed to be valid and disabling the
+ * window will result in screen glitches on PSR exit.
*/
- for (i = 0; i < vop->data->win_size; i++) {
- struct vop_win *vop_win = &vop->win[i];
- const struct vop_win_data *win = vop_win->data;
+ if (!old_state || !old_state->self_refresh_active) {
+ for (i = 0; i < vop->data->win_size; i++) {
+ struct vop_win *vop_win = &vop->win[i];
+ const struct vop_win_data *win = vop_win->data;
- vop_win_disable(vop, win);
+ vop_win_disable(vop, win);
+ }
}
spin_unlock(&vop->reg_lock);
@@ -624,6 +632,12 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc,
WARN_ON(vop->event);
mutex_lock(&vop->vop_lock);
+
+ if (!vop->is_enabled) {
+ mutex_unlock(&vop->vop_lock);
+ return;
+ }
+
drm_crtc_vblank_off(crtc);
/*
@@ -925,12 +939,10 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane,
swap(plane->state->fb, new_state->fb);
if (vop->is_enabled) {
- rockchip_drm_psr_inhibit_get_state(new_state->state);
vop_plane_atomic_update(plane, plane->state);
spin_lock(&vop->reg_lock);
vop_cfg_done(vop);
spin_unlock(&vop->reg_lock);
- rockchip_drm_psr_inhibit_put_state(new_state->state);
/*
* A scanout can still be occurring, so we can't drop the
@@ -1038,7 +1050,7 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc,
WARN_ON(vop->event);
- ret = vop_enable(crtc);
+ ret = vop_enable(crtc, old_state);
if (ret) {
mutex_unlock(&vop->vop_lock);
DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret);
@@ -1520,6 +1532,13 @@ static int vop_create_crtc(struct vop *vop)
init_completion(&vop->line_flag_completion);
crtc->port = port;
+ ret = drm_self_refresh_helper_init(crtc,
+ VOP_SELF_REFRESH_ENTRY_DELAY_MS);
+ if (ret)
+ DRM_DEV_DEBUG_KMS(vop->dev,
+ "Failed to init %s with SR helpers %d, ignoring\n",
+ crtc->name, ret);
+
return 0;
err_cleanup_crtc:
@@ -1537,6 +1556,8 @@ static void vop_destroy_crtc(struct vop *vop)
struct drm_device *drm_dev = vop->drm_dev;
struct drm_plane *plane, *tmp;
+ drm_self_refresh_helper_cleanup(crtc);
+
of_node_put(crtc->port);
/*