From patchwork Tue Mar 26 20:44:54 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10872171 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 782FB17E6 for ; Tue, 26 Mar 2019 20:45:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D8CC28AD3 for ; Tue, 26 Mar 2019 20:45:17 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4D96528CC0; Tue, 26 Mar 2019 20:45:17 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id D7F0528AD3 for ; Tue, 26 Mar 2019 20:45:15 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 76AE66E057; Tue, 26 Mar 2019 20:45:14 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt1-x841.google.com (mail-qt1-x841.google.com [IPv6:2607:f8b0:4864:20::841]) by gabe.freedesktop.org (Postfix) with ESMTPS id 921486E057 for ; Tue, 26 Mar 2019 20:45:12 +0000 (UTC) Received: by mail-qt1-x841.google.com with SMTP id t28so16338391qte.6 for ; Tue, 26 Mar 2019 13:45:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=IdgQ9UJ5SdSiJGi/xXR+llVk/SrOT4hFP6+sNuUNrXg=; b=exdMHwIyedXOlaQhPcG8opDeDDemqxCEiYm1vOKTdtiPbnlJ+zP/OoItywGxMc+XTg nkUUSxfCKBWeP/DWLnXEYiG39uJijZxcR9SoBzkWdo5eu/FGHn5+CLzMGCcTsHQwdpLQ S05fp64VA/8I2FDz86tsXnKcNcuYMMy/ryjPXw9/IW/d/9XCSV7Z6A4YuxKFd9KiGDgh GdmInuEusNhPT/NN3Bn17WoXjSvw/WGJNshI2LkPgtrWBFjxX1BA/ws1Xr1YfBmBcvmr SMiNcnJy27ib7UMpBuQWNhgap35gPD+fqRMFuRRM+kE8LCN2Ogv2+FJ2cBqjPJU5JHTz tUvw== X-Gm-Message-State: APjAAAW5UGVBoJvQSgHelM8EcT7z6a+7fK4Om0zAzq/FOVelNTCpeoiP gtL9xToxK79vAOB1OY3ep+LJdr0Mv68= X-Google-Smtp-Source: APXvYqyzw6pCzJFqv9AJ5zpiipJ5ZJ9xLnZPGyD0xWHN3Pn48ZGs1+Jhv1Q7rGm2Vnvq6Bp2AU2GKg== X-Received: by 2002:ac8:7647:: with SMTP id i7mr26230389qtr.38.1553633111336; Tue, 26 Mar 2019 13:45:11 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:89c6:2139:5435:371d]) by smtp.gmail.com with ESMTPSA id i11sm9405810qkg.33.2019.03.26.13.45.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2019 13:45:10 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 1/5] drm: Add helpers to kick off self refresh mode in drivers Date: Tue, 26 Mar 2019 16:44:54 -0400 Message-Id: <20190326204509.96515-1-sean@poorly.run> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poorly.run; s=google; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=IdgQ9UJ5SdSiJGi/xXR+llVk/SrOT4hFP6+sNuUNrXg=; b=VsskmdRIc7ZYJV0u5dcaXKCauV7xW3NA2zgkyk9yYKRhTYn9ZU9ILH9dYQFuTVKysu OEoTHPEze4WnzZSkmCYSk9X84Bb2oCe1gVZ7FgWinO/rWTRxszVm63ruNkAdvok1nC+F jO5X036ycRRSub8/pq/PIzFWXNi1cSGPls9oiT5svEhXkM2ZxKkBArNvmThTFWgmebgG th4gxyvnrV7LTyaYt1hyG4ARoE03A6Kly6ArZZxH2Q4N7vOz2caiQ1UgcSpnd/hd+vuP 4l8vQnRSAKTTzAycNBpmGYF6uyYdx6h40s9/04lEPn4Zg9YK/tB+Ph1/2caoIZo2kQYv zU1Q== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zain Wang , David Airlie , Jose Souza , Tomasz Figa , Maxime Ripard , Sean Paul , Sean Paul Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul This patch adds a new drm helper library to help drivers implement self refresh. Drivers choosing to use it will register crtcs and will receive callbacks when it's time to enter or exit self refresh mode. In its current form, it has a timer which will trigger after a driver-specified amount of inactivity. When the timer triggers, the helpers will submit a new atomic commit to shut the refreshing pipe off. On the next atomic commit, the drm core will revert the self refresh state and bring everything back up to be actively driven. From the driver's perspective, this works like a regular disable/enable cycle. The driver need only check the 'self_refresh_active' and/or 'self_refresh_changed' state in crtc_state and connector_state. It should initiate self refresh mode on the panel and enter an off or low-power state. Changes in v2: - s/psr/self_refresh/ (Daniel) - integrated the psr exit into the commit that wakes it up (Jose/Daniel) - made the psr state per-crtc (Jose/Daniel) Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-2-sean@poorly.run Cc: Daniel Vetter Cc: Jose Souza Cc: Zain Wang Cc: Tomasz Figa Signed-off-by: Sean Paul --- Documentation/gpu/drm-kms-helpers.rst | 9 + drivers/gpu/drm/Makefile | 3 +- drivers/gpu/drm/drm_atomic.c | 4 + drivers/gpu/drm/drm_atomic_helper.c | 36 +++- drivers/gpu/drm/drm_atomic_state_helper.c | 8 + drivers/gpu/drm/drm_atomic_uapi.c | 5 +- drivers/gpu/drm/drm_self_refresh_helper.c | 212 ++++++++++++++++++++++ include/drm/drm_atomic.h | 15 ++ include/drm/drm_connector.h | 31 ++++ include/drm/drm_crtc.h | 19 ++ include/drm/drm_self_refresh_helper.h | 23 +++ 11 files changed, 360 insertions(+), 5 deletions(-) create mode 100644 drivers/gpu/drm/drm_self_refresh_helper.c create mode 100644 include/drm/drm_self_refresh_helper.h diff --git a/Documentation/gpu/drm-kms-helpers.rst b/Documentation/gpu/drm-kms-helpers.rst index 58b375e47615..b0b71f73829f 100644 --- a/Documentation/gpu/drm-kms-helpers.rst +++ b/Documentation/gpu/drm-kms-helpers.rst @@ -107,6 +107,15 @@ fbdev Helper Functions Reference .. kernel-doc:: drivers/gpu/drm/drm_fb_helper.c :export: +Panel Self Refresh Helper Reference +=================================== + +.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c + :doc: overview + +.. kernel-doc:: drivers/gpu/drm/drm_self_refresh_helper.c + :export: + Framebuffer CMA Helper Functions Reference ========================================== diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index e630eccb951c..5b3a1e26ec94 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -38,7 +38,8 @@ drm_kms_helper-y := drm_crtc_helper.o drm_dp_helper.o drm_dsc.o drm_probe_helper drm_kms_helper_common.o drm_dp_dual_mode_helper.o \ drm_simple_kms_helper.o drm_modeset_helper.o \ drm_scdc_helper.o drm_gem_framebuffer_helper.o \ - drm_atomic_state_helper.o drm_damage_helper.o + drm_atomic_state_helper.o drm_damage_helper.o \ + drm_self_refresh_helper.o drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 5eb40130fafb..a06fe55b5ebf 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -379,6 +379,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p, drm_printf(p, "crtc[%u]: %s\n", crtc->base.id, crtc->name); drm_printf(p, "\tenable=%d\n", state->enable); drm_printf(p, "\tactive=%d\n", state->active); + drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active); drm_printf(p, "\tplanes_changed=%d\n", state->planes_changed); drm_printf(p, "\tmode_changed=%d\n", state->mode_changed); drm_printf(p, "\tactive_changed=%d\n", state->active_changed); @@ -881,6 +882,9 @@ static void drm_atomic_connector_print_state(struct drm_printer *p, drm_printf(p, "connector[%u]: %s\n", connector->base.id, connector->name); drm_printf(p, "\tcrtc=%s\n", state->crtc ? state->crtc->name : "(null)"); + drm_printf(p, "\tself_refresh_active=%d\n", state->self_refresh_active); + drm_printf(p, "\tself_refresh_aware=%d\n", state->self_refresh_aware); + drm_printf(p, "\tself_refresh_changed=%d\n", state->self_refresh_changed); if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) if (state->writeback_job && state->writeback_job->fb) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 2453678d1186..c659db105133 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -950,10 +951,33 @@ int drm_atomic_helper_check(struct drm_device *dev, if (state->legacy_cursor_update) state->async_update = !drm_atomic_helper_async_check(dev, state); + drm_self_refresh_helper_alter_state(state); + return ret; } EXPORT_SYMBOL(drm_atomic_helper_check); +static bool +crtc_needs_disable(struct drm_crtc_state *old_state, + struct drm_crtc_state *new_state) +{ + /* + * No new_state means the crtc is off, so the only criteria is whether + * it's currently active or in self refresh mode. + */ + if (!new_state) + return drm_atomic_crtc_effectively_active(old_state); + + /* + * We need to run through the crtc_funcs->disable() function if the crtc + * is currently on, if it's transitioning to self refresh mode, or if + * it's in self refresh mode and needs to be fully disabled. + */ + return old_state->active || + (old_state->self_refresh_active && !new_state->enable) || + new_state->self_refresh_active; +} + static void disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) { @@ -974,7 +998,14 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) old_crtc_state = drm_atomic_get_old_crtc_state(old_state, old_conn_state->crtc); - if (!old_crtc_state->active || + if (new_conn_state->crtc) + new_crtc_state = drm_atomic_get_new_crtc_state( + old_state, + new_conn_state->crtc); + else + new_crtc_state = NULL; + + if (!crtc_needs_disable(old_crtc_state, new_crtc_state) || !drm_atomic_crtc_needs_modeset(old_conn_state->crtc->state)) continue; @@ -1018,7 +1049,7 @@ disable_outputs(struct drm_device *dev, struct drm_atomic_state *old_state) if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) continue; - if (!old_crtc_state->active) + if (!crtc_needs_disable(old_crtc_state, new_crtc_state)) continue; funcs = crtc->helper_private; @@ -2948,6 +2979,7 @@ int drm_atomic_helper_set_config(struct drm_mode_set *set, return -ENOMEM; state->acquire_ctx = ctx; + ret = __drm_atomic_helper_set_config(set, state); if (ret != 0) goto fail; diff --git a/drivers/gpu/drm/drm_atomic_state_helper.c b/drivers/gpu/drm/drm_atomic_state_helper.c index 4985384e51f6..ec90c527deed 100644 --- a/drivers/gpu/drm/drm_atomic_state_helper.c +++ b/drivers/gpu/drm/drm_atomic_state_helper.c @@ -105,6 +105,10 @@ void __drm_atomic_helper_crtc_duplicate_state(struct drm_crtc *crtc, state->commit = NULL; state->event = NULL; state->pageflip_flags = 0; + + /* Self refresh should be canceled when a new update is available */ + state->active = drm_atomic_crtc_effectively_active(state); + state->self_refresh_active = false; } EXPORT_SYMBOL(__drm_atomic_helper_crtc_duplicate_state); @@ -370,6 +374,10 @@ __drm_atomic_helper_connector_duplicate_state(struct drm_connector *connector, /* Don't copy over a writeback job, they are used only once */ state->writeback_job = NULL; + + /* Self refresh should be canceled when a new update is available */ + state->self_refresh_changed = state->self_refresh_active; + state->self_refresh_active = false; } EXPORT_SYMBOL(__drm_atomic_helper_connector_duplicate_state); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 4eb81f10bc54..d2085332172b 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -490,7 +490,7 @@ drm_atomic_crtc_get_property(struct drm_crtc *crtc, struct drm_mode_config *config = &dev->mode_config; if (property == config->prop_active) - *val = state->active; + *val = drm_atomic_crtc_effectively_active(state); else if (property == config->prop_mode_id) *val = (state->mode_blob) ? state->mode_blob->base.id : 0; else if (property == config->prop_vrr_enabled) @@ -785,7 +785,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, if (property == config->prop_crtc_id) { *val = (state->crtc) ? state->crtc->base.id : 0; } else if (property == config->dpms_property) { - *val = connector->dpms; + *val = state->self_refresh_active ? DRM_MODE_DPMS_ON : + connector->dpms; } else if (property == config->tv_select_subconnector_property) { *val = state->tv.subconnector; } else if (property == config->tv_left_margin_property) { diff --git a/drivers/gpu/drm/drm_self_refresh_helper.c b/drivers/gpu/drm/drm_self_refresh_helper.c new file mode 100644 index 000000000000..a3afa031480e --- /dev/null +++ b/drivers/gpu/drm/drm_self_refresh_helper.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2019 Google, Inc. + * + * Authors: + * Sean Paul + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * DOC: overview + * + * This helper library provides an easy way for drivers to leverage the atomic + * framework to implement panel self refresh (SR) support. Drivers are + * responsible for registering and unregistering the SR helpers on load/unload. + * + * Once a crtc has enabled SR, the helpers will monitor activity and + * call back into the driver to enable/disable SR as appropriate. The best way + * to think about this is that it's a DPMS on/off request with a flag set in + * state that tells you to disable/enable SR on the panel instead of power- + * cycling it. + * + * Drivers may choose to fully disable their crtc/encoder/bridge hardware, or + * they can use the "self_refresh_active" and "self_refresh_changed" flags in + * object state if they want to enter low power mode without full disable (in + * case full disable/enable is too slow). + * + * SR will be deactivated if there are any atomic updates affecting the + * pipe that is in SR mode. If a crtc is driving multiple connectors, all + * connectors must be SR aware and all will enter SR mode. + */ + +struct drm_self_refresh_state { + struct drm_crtc *crtc; + struct delayed_work entry_work; + struct drm_atomic_state *save_state; + unsigned int entry_delay_ms; +}; + +static void drm_self_refresh_helper_entry_work(struct work_struct *work) +{ + struct drm_self_refresh_state *sr_state = container_of( + to_delayed_work(work), + struct drm_self_refresh_state, entry_work); + struct drm_crtc *crtc = sr_state->crtc; + struct drm_device *dev = crtc->dev; + struct drm_modeset_acquire_ctx ctx; + struct drm_atomic_state *state; + struct drm_connector *conn; + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + int i, ret; + + drm_modeset_acquire_init(&ctx, 0); + + state = drm_atomic_state_alloc(dev); + if (!state) { + ret = -ENOMEM; + goto out; + } + +retry: + state->acquire_ctx = &ctx; + + crtc_state = drm_atomic_get_crtc_state(state, crtc); + if (IS_ERR(crtc_state)) { + ret = PTR_ERR(crtc_state); + goto out; + } + + if (!crtc_state->enable) + goto out; + + ret = drm_atomic_add_affected_connectors(state, crtc); + if (ret) + goto out; + + crtc_state->active = false; + crtc_state->self_refresh_active = true; + + for_each_new_connector_in_state(state, conn, conn_state, i) { + if (!conn_state->self_refresh_aware) + goto out; + + conn_state->self_refresh_changed = true; + conn_state->self_refresh_active = true; + } + + ret = drm_atomic_commit(state); + if (ret) + goto out; + +out: + if (ret == -EDEADLK) { + drm_atomic_state_clear(state); + ret = drm_modeset_backoff(&ctx); + if (!ret) + goto retry; + } + + drm_atomic_state_put(state); + drm_modeset_drop_locks(&ctx); + drm_modeset_acquire_fini(&ctx); +} + +/** + * drm_self_refresh_helper_alter_state - Alters the atomic state for SR exit + * @state: the state currently being checked + * + * Called at the end of atomic check. This function checks the state for flags + * incompatible with self refresh exit and changes them. This is a bit + * disingenuous since userspace is expecting one thing and we're giving it + * another. However in order to keep self refresh entirely hidden from + * userspace, this is required. + * + * At the end, we queue up the self refresh entry work so we can enter PSR after + * the desired delay. + */ +void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state) +{ + struct drm_crtc *crtc; + struct drm_crtc_state *crtc_state; + int i; + + if (state->async_update) { + for_each_old_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->self_refresh_active) { + state->async_update = false; + break; + } + } + } + if (!state->allow_modeset) { + for_each_old_crtc_in_state(state, crtc, crtc_state, i) { + if (crtc_state->self_refresh_active) { + state->allow_modeset = true; + break; + } + } + } + + for_each_new_crtc_in_state(state, crtc, crtc_state, i) { + struct drm_self_refresh_state *sr_state; + + /* Don't trigger the entry timer when we're already in SR */ + if (crtc_state->self_refresh_active) + continue; + + sr_state = crtc->self_refresh_state; + mod_delayed_work(system_wq, &sr_state->entry_work, + msecs_to_jiffies(sr_state->entry_delay_ms)); + } +} +EXPORT_SYMBOL(drm_self_refresh_helper_alter_state); + +/** + * drm_self_refresh_helper_register - Registers self refresh helpers for a crtc + * @crtc: the crtc which supports self refresh supported displays + * @entry_delay_ms: amount of inactivity to wait before entering self refresh + */ +int drm_self_refresh_helper_register(struct drm_crtc *crtc, + unsigned int entry_delay_ms) +{ + struct drm_self_refresh_state *sr_state = crtc->self_refresh_state; + + /* Helper is already registered */ + if (WARN_ON(sr_state)) + return -EINVAL; + + sr_state = kzalloc(sizeof(*sr_state), GFP_KERNEL); + if (!sr_state) + return -ENOMEM; + + INIT_DELAYED_WORK(&sr_state->entry_work, + drm_self_refresh_helper_entry_work); + sr_state->entry_delay_ms = entry_delay_ms; + sr_state->crtc = crtc; + + crtc->self_refresh_state = sr_state; + return 0; +} +EXPORT_SYMBOL(drm_self_refresh_helper_register); + +/** + * drm_self_refresh_helper_unregister - Unregisters self refresh helpers + * @crtc: the crtc to unregister + */ +void drm_self_refresh_helper_unregister(struct drm_crtc *crtc) +{ + struct drm_self_refresh_state *sr_state = crtc->self_refresh_state; + + /* Helper is already unregistered */ + if (sr_state) + return; + + crtc->self_refresh_state = NULL; + + cancel_delayed_work_sync(&sr_state->entry_work); + kfree(sr_state); +} +EXPORT_SYMBOL(drm_self_refresh_helper_unregister); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 824a5ed4e216..1e9cab1da97a 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -944,4 +944,19 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state) state->connectors_changed; } +/** + * drm_atomic_crtc_effectively_active - compute whether crtc is actually active + * @state: &drm_crtc_state for the CRTC + * + * When in self refresh mode, the crtc_state->active value will be false, since + * the crtc is off. However in some cases we're interested in whether the crtc + * is active, or effectively active (ie: it's connected to an active display). + * In these cases, use this function instead of just checking active. + */ +static inline bool +drm_atomic_crtc_effectively_active(const struct drm_crtc_state *state) +{ + return state->active || state->self_refresh_active; +} + #endif /* DRM_ATOMIC_H_ */ diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index c8061992d6cb..0ae7e812ec62 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -501,6 +501,37 @@ struct drm_connector_state { /** @tv: TV connector state */ struct drm_tv_connector_state tv; + /** + * @self_refresh_changed: + * + * Set true when self refresh status has changed. This is useful for + * use in encoder/bridge enable where the old state is unavailable to + * the driver and it needs to know whether the enable transition is a + * full transition, or if it just needs to exit self refresh mode. + */ + bool self_refresh_changed; + + /** + * @self_refresh_active: + * + * Used by the self refresh (SR) helpers to denote when the display + * should be self refreshing. If your connector is SR-capable, check + * this flag in .disable(). If it is true, instead of shutting off the + * panel, put it into self refreshing mode. + */ + bool self_refresh_active; + + /** + * @self_refresh_aware: + * + * This tracks whether a connector is aware of the self refresh state. + * It should be set to true for those connector implementations which + * understand the self refresh state. This is needed since the crtc + * registers the self refresh helpers and it doesn't know if the + * connectors downstream have implemented self refresh entry/exit. + */ + bool self_refresh_aware; + /** * @picture_aspect_ratio: Connector property to control the * HDMI infoframe aspect ratio setting. diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index f7c3022dbdf4..208d68129b4c 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -53,6 +53,7 @@ struct drm_mode_set; struct drm_file; struct drm_clip_rect; struct drm_printer; +struct drm_self_refresh_state; struct device_node; struct dma_fence; struct edid; @@ -299,6 +300,17 @@ struct drm_crtc_state { */ bool vrr_enabled; + /** + * @self_refresh_active: + * + * Used by the self refresh helpers to denote when a self refresh + * transition is occuring. This will be set on enable/disable callbacks + * when self refresh is being enabled or disabled. In some cases, it may + * not be desirable to fully shut off the crtc during self refresh. + * CRTC's can inspect this flag and determine the best course of action. + */ + bool self_refresh_active; + /** * @event: * @@ -1087,6 +1099,13 @@ struct drm_crtc { * The name of the CRTC's fence timeline. */ char timeline_name[32]; + + /** + * @self_refresh_state: Holds the state for the self refresh helpers + * + * Initialized via drm_self_refresh_helper_register(). + */ + struct drm_self_refresh_state *self_refresh_state; }; /** diff --git a/include/drm/drm_self_refresh_helper.h b/include/drm/drm_self_refresh_helper.h new file mode 100644 index 000000000000..015dacb8a807 --- /dev/null +++ b/include/drm/drm_self_refresh_helper.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright (C) 2019 Google, Inc. + * + * Authors: + * Sean Paul + */ +#ifndef DRM_SELF_REFRESH_HELPER_H_ +#define DRM_SELF_REFRESH_HELPER_H_ + +struct drm_atomic_state; +struct drm_connector; +struct drm_device; +struct drm_self_refresh_state; +struct drm_modeset_acquire_ctx; + +void drm_self_refresh_helper_alter_state(struct drm_atomic_state *state); + +int drm_self_refresh_helper_register(struct drm_crtc *crtc, + unsigned int entry_delay_ms); + +void drm_self_refresh_helper_unregister(struct drm_crtc *crtc); +#endif From patchwork Tue Mar 26 20:44:55 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10872173 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 24535922 for ; Tue, 26 Mar 2019 20:45:22 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 111E528AD3 for ; Tue, 26 Mar 2019 20:45:22 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0446828CC0; Tue, 26 Mar 2019 20:45:22 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id B43D228AD3 for ; Tue, 26 Mar 2019 20:45:21 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DE0056E05A; Tue, 26 Mar 2019 20:45:20 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) by gabe.freedesktop.org (Postfix) with ESMTPS id AD5426E05A for ; Tue, 26 Mar 2019 20:45:19 +0000 (UTC) Received: by mail-qt1-x842.google.com with SMTP id x12so16320301qts.7 for ; Tue, 26 Mar 2019 13:45:19 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8nEkpo9lke+47iZRk8sdglEdfvZcvUosBAlXnNDttkg=; b=i7zH0IV+ZWIjM2hqHEEFZiSvTWHoBanS7UUD/V/nt1+TJwpi8PeFHXxkPA5o8QtAa1 KPiWPNrLJ53wbVgyUOyR/ER2ri+GN1ArWqFnPz79N3Nx9Q0MmgpSPTu83KqU+/DkJMaO ycigwJS0+0A/ZWzobQjwKZEW9qGZuNuc51zJsqvwkuzH+y9YTTE4re7XpBZ78eMS67xL NTHSKPzCDB82zGw3EAt81l6PyEUbFjK4MwMPAwh6Z/NgCXZjbZucjuCYwyok4O3WnhSO Mrw5Tl9T66iwZANSdPGcAf8UqYu25WBWDUWP0JHCFzkriFCdjanFvJZx2s7hO53xTvDJ puJQ== X-Gm-Message-State: APjAAAVNsqS2LQsTKW5Bo3/dQEu07jzCyehXgxucDICkW6Kp2rtQi/nq xM/TGOZgQiWbDxrKYBNRwDXwE2YUm48= X-Google-Smtp-Source: APXvYqwg1cgXS1aVDeZ1qD69ZmgJD6nR2iZYKWNzC25Z92qXgic7K2rz2oniffWW6fG619MbJHEmJw== X-Received: by 2002:aed:3aa6:: with SMTP id o35mr12606732qte.162.1553633118759; Tue, 26 Mar 2019 13:45:18 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:89c6:2139:5435:371d]) by smtp.gmail.com with ESMTPSA id i11sm9405810qkg.33.2019.03.26.13.45.17 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2019 13:45:18 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 2/5] drm/rockchip: Check for fast link training before enabling psr Date: Tue, 26 Mar 2019 16:44:55 -0400 Message-Id: <20190326204509.96515-2-sean@poorly.run> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog In-Reply-To: <20190326204509.96515-1-sean@poorly.run> References: <20190326204509.96515-1-sean@poorly.run> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poorly.run; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=8nEkpo9lke+47iZRk8sdglEdfvZcvUosBAlXnNDttkg=; b=Dbqhp1vTzqS/tsQXeOteGsJHxduKSdjoMdOeolTU6IVQYryldJwQfa+6wDPJk5cuy2 yDbOl9e8TlypMU4B1bgenOsSsCZr1rY+wv5kYyO9KhLEi9YYmITJUaghL69a/9PVtJrY NAPCgeIkGXA/+pylyI44CduvqVlR4tN/yGya3+ewzGeIp0Tjk92V0jDK7blWMP9cbxyU zEsy/bMTBNCOH4pZl1DkpQihhj4idTsBzSDOkzJiM3hMIDeQ8lehTv4FZj8DUwCuTPwW Lqy4x6DuPDoBCOZiwMsggDtGJCVUid2xXwL6qp6sa3V71Wu2cCUhCZb0AQmmHCWj45jB AlzA== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zain Wang , David Airlie , Tomasz Figa , Sean Paul , Laurent Pinchart Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul Once we start shutting off the link during PSR, we're going to want fast training to work. If the display doesn't support fast training, don't enable psr. Changes in v2: - None Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-3-sean@poorly.run Cc: Zain Wang Cc: Tomasz Figa Signed-off-by: Sean Paul --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 225f5e5dd69b..af34554a5a02 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1040,16 +1040,17 @@ static int analogix_dp_commit(struct analogix_dp_device *dp) if (ret) return ret; + /* Check whether panel supports fast training */ + ret = analogix_dp_fast_link_train_detection(dp); + if (ret) + dp->psr_enable = false; + if (dp->psr_enable) { ret = analogix_dp_enable_sink_psr(dp); if (ret) return ret; } - /* Check whether panel supports fast training */ - ret = analogix_dp_fast_link_train_detection(dp); - if (ret) - dp->psr_enable = false; return ret; } From patchwork Tue Mar 26 20:44:56 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10872175 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4853617E6 for ; Tue, 26 Mar 2019 20:45:44 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3013828AD3 for ; Tue, 26 Mar 2019 20:45:44 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2457F28D01; Tue, 26 Mar 2019 20:45:44 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 7243228AD3 for ; Tue, 26 Mar 2019 20:45:42 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9606C6E064; Tue, 26 Mar 2019 20:45:41 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) by gabe.freedesktop.org (Postfix) with ESMTPS id BF5216E05F for ; Tue, 26 Mar 2019 20:45:39 +0000 (UTC) Received: by mail-qt1-x842.google.com with SMTP id k2so16371494qtm.1 for ; Tue, 26 Mar 2019 13:45:39 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=DnVb5/6Kd7SQBZC88qZcdlYkYRQ8UcdKA8GuJ2vVW8s=; b=jd305F9s+/g66wb1RGMImRHuRtnkfcoIgf7a/rZOgmteizkzxuqPG6Rh3FUmVlJ+CT d7qF7fUX/8PKt7yc/Nn8GQSY7DgmKxo46xKuZ+Hli59dFCiI+8wXcs21CbsveI8SSxMp y/FsB7dZ9r1y0zQrvZwS99co/cMTHxp7Wd4EwXOOri6sBIZMSUvtSTHmtGgmYQ3ebTSo byXsO79jHgjLf4MFzCX3S1ff1tMuoOvk0y0mrfPeS2GHhvYqRwBcIxukCEdI556ZYjLX OZn+33p7LL+3vcMGtwnh2yBTKSP7uGXCBkYj34H/7IdLOspCrZS+14+TCBgggJ2LMkA9 9cPA== X-Gm-Message-State: APjAAAXBxJzwGtQUlpsy8dn51iHzbGlQuFDQxGflnDB9qvBp/6CPovQz dcrzXwt1Ci+4YCmFM+1xctpyCq+25aI= X-Google-Smtp-Source: APXvYqyvATQ00XvkFUCysdgfx9E/qsejF9RC1RJQEODYJ4Rpjal5BEw/CqbhFUhoQrB8COW+7AZ/eg== X-Received: by 2002:ac8:3662:: with SMTP id n31mr16247971qtb.380.1553633138434; Tue, 26 Mar 2019 13:45:38 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:89c6:2139:5435:371d]) by smtp.gmail.com with ESMTPSA id i11sm9405810qkg.33.2019.03.26.13.45.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2019 13:45:37 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 3/5] drm/rockchip: Use the helpers for PSR Date: Tue, 26 Mar 2019 16:44:56 -0400 Message-Id: <20190326204509.96515-3-sean@poorly.run> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog In-Reply-To: <20190326204509.96515-1-sean@poorly.run> References: <20190326204509.96515-1-sean@poorly.run> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poorly.run; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=DnVb5/6Kd7SQBZC88qZcdlYkYRQ8UcdKA8GuJ2vVW8s=; b=XyxmEGrr779NAVDwxePdiEhnTPuM9jqrBfTteBaxmnjZn4PyL8Y/89jHjYFsj3pPFk O3NTyKSUq0r4cjyOyspWSAw9ZBtbLm6ZmRVcOquY3eMFy5bLCNZPKsWh2/2hh1lOhh6A M9xBoAJusyJhggiZnIwAPU/NfwRzpKgEKCXWHWeJ26zrke/lYbSq2D9Pba7ixTFd0giz 7tc6uWJ2pKo4BSxmND3AxvZ76/+Z8tUx37fWTfHQcG8dnAu1vycMfq00l8ej61A/CCM5 CeXkTjOHMVlBWX3c4ibT5G9rcGB8fgMyWAXcHLO8F5UUBbeFco8RyYMSQyhd4ACZu6BU acXQ== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zain Wang , David Airlie , Tomasz Figa , Sean Paul , Laurent Pinchart Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul Instead of rolling our own implementation for tracking when PSR should be [in]active, use the new self refresh helpers to do the heavy lifting. Changes in v2: - updated to reflect changes made in the helpers Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-4-sean@poorly.run Cc: Zain Wang Cc: Tomasz Figa Signed-off-by: Sean Paul --- .../drm/bridge/analogix/analogix_dp_core.c | 213 ++++++++----- .../drm/bridge/analogix/analogix_dp_core.h | 2 +- drivers/gpu/drm/rockchip/Makefile | 3 +- .../gpu/drm/rockchip/analogix_dp-rockchip.c | 70 ++--- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 16 - drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 290 ------------------ drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 30 -- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 33 +- include/drm/bridge/analogix_dp.h | 4 +- 9 files changed, 185 insertions(+), 476 deletions(-) delete mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.c delete mode 100644 drivers/gpu/drm/rockchip/rockchip_drm_psr.h diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index af34554a5a02..c503fe3bc3b3 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -106,63 +106,13 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_enabled(struct analogix_dp_device *dp) +bool analogix_dp_self_refresh_changed(struct analogix_dp_device *dp) { - - return dp->psr_enable; + return dp->connector.state->self_refresh_changed; } -EXPORT_SYMBOL_GPL(analogix_dp_psr_enabled); +EXPORT_SYMBOL_GPL(analogix_dp_self_refresh_changed); -int analogix_dp_enable_psr(struct analogix_dp_device *dp) -{ - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_enable) - return 0; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - - return analogix_dp_send_psr_spd(dp, &psr_vsc, true); -} -EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); - -int analogix_dp_disable_psr(struct analogix_dp_device *dp) -{ - struct edp_vsc_psr psr_vsc; - int ret; - - if (!dp->psr_enable) - return 0; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = 0; - - ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - if (ret != 1) { - dev_err(dp->dev, "Failed to set DP Power0 %d\n", ret); - return ret; - } - - return analogix_dp_send_psr_spd(dp, &psr_vsc, false); -} -EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); - -static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) { unsigned char psr_version; int ret; @@ -170,14 +120,11 @@ static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_SUPPORT, &psr_version); if (ret != 1) { dev_err(dp->dev, "failed to get PSR version, disable it\n"); - return ret; + return false; } dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version); - - dp->psr_enable = (psr_version & DP_PSR_IS_SUPPORTED) ? true : false; - - return 0; + return psr_version & DP_PSR_IS_SUPPORTED; } static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) @@ -200,7 +147,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) } /* Main-Link transmitter remains active during PSR active states */ - psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_CRC_VERIFICATION; ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en); if (ret != 1) { dev_err(dp->dev, "failed to set panel psr\n"); @@ -208,8 +155,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) } /* Enable psr function */ - psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | - DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en); if (ret != 1) { dev_err(dp->dev, "failed to set panel psr\n"); @@ -218,10 +164,11 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) analogix_dp_enable_psr_crc(dp); + dp->psr_supported = true; + return 0; end: dev_err(dp->dev, "enable psr fail, force to disable psr\n"); - dp->psr_enable = false; return ret; } @@ -1036,25 +983,90 @@ static int analogix_dp_commit(struct analogix_dp_device *dp) } } - ret = analogix_dp_detect_sink_psr(dp); - if (ret) - return ret; - /* Check whether panel supports fast training */ ret = analogix_dp_fast_link_train_detection(dp); if (ret) - dp->psr_enable = false; + return ret; - if (dp->psr_enable) { + if (analogix_dp_detect_sink_psr(dp)) { ret = analogix_dp_enable_sink_psr(dp); if (ret) return ret; } + return ret; +} + +static int analogix_dp_enable_psr(struct analogix_dp_device *dp) +{ + struct edp_vsc_psr psr_vsc; + int ret; + u8 sink; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink); + if (ret != 1) + DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret); + else if (sink == DP_PSR_SINK_ACTIVE_RFB) + return 0; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + psr_vsc.DB0 = 0; + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; + + ret = analogix_dp_send_psr_spd(dp, &psr_vsc, true); + if (!ret) + analogix_dp_set_analog_power_down(dp, POWER_ALL, true); return ret; } +static int analogix_dp_disable_psr(struct analogix_dp_device *dp) +{ + struct edp_vsc_psr psr_vsc; + int ret; + u8 sink; + + analogix_dp_set_analog_power_down(dp, POWER_ALL, false); + + ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + if (ret != 1) { + DRM_DEV_ERROR(dp->dev, "Failed to set DP Power0 %d\n", ret); + return ret; + } + + ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink); + if (ret != 1) { + DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret); + return ret; + } else if (sink == DP_PSR_SINK_INACTIVE) { + DRM_DEV_ERROR(dp->dev, "sink inactive, skip disable psr"); + return 0; + } + + ret = analogix_dp_train_link(dp); + if (ret) { + DRM_DEV_ERROR(dp->dev, "Failed to train the link %d\n", ret); + return ret; + } + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.DB0 = 0; + psr_vsc.DB1 = 0; + + return analogix_dp_send_psr_spd(dp, &psr_vsc, true); +} + /* * This function is a bit of a catch-all for panel preparation, hopefully * simplifying the logic of functions that need to prepare/unprepare the panel @@ -1145,9 +1157,23 @@ analogix_dp_best_encoder(struct drm_connector *connector) return dp->encoder; } + +int analogix_dp_atomic_check(struct drm_connector *connector, + struct drm_connector_state *state) +{ + struct analogix_dp_device *dp = to_dp(connector); + + state->self_refresh_aware = true; + if (state->self_refresh_active && !dp->psr_supported) + return -EINVAL; + + return 0; +} + static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { .get_modes = analogix_dp_get_modes, .best_encoder = analogix_dp_best_encoder, + .atomic_check = analogix_dp_atomic_check, }; static enum drm_connector_status @@ -1244,6 +1270,10 @@ static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge) struct analogix_dp_device *dp = bridge->driver_private; int ret; + /* Don't touch the panel if we're coming back from PSR */ + if (dp->connector.state->self_refresh_changed) + return; + ret = analogix_dp_prepare_panel(dp, true, true); if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); @@ -1309,6 +1339,14 @@ static void analogix_dp_bridge_enable(struct drm_bridge *bridge) struct analogix_dp_device *dp = bridge->driver_private; int timeout_loop = 0; + /* Not a full enable, just disable PSR and continue */ + if (dp->connector.state->self_refresh_changed) { + int ret = analogix_dp_disable_psr(dp); + if (ret) + DRM_ERROR("Failed to disable psr %d\n", ret); + return; + } + if (dp->dpms_mode == DRM_MODE_DPMS_ON) return; @@ -1356,11 +1394,37 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); - dp->psr_enable = false; dp->fast_train_enable = false; + dp->psr_supported = false; dp->dpms_mode = DRM_MODE_DPMS_OFF; } +static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct drm_connector_state *conn_state = dp->connector.state; + + /* Don't do a full disable on PSR transitions */ + if (conn_state->crtc && conn_state->self_refresh_changed) + return; + + analogix_dp_bridge_disable(bridge); +} + +static void analogix_dp_bridge_post_disable(struct drm_bridge *bridge) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct drm_connector_state *conn_state = dp->connector.state; + int ret; + + if (conn_state->self_refresh_active) { + ret = analogix_dp_enable_psr(dp); + if (ret) + DRM_ERROR("Failed to enable psr (%d)\n", ret); + return; + } +} + static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *orig_mode, const struct drm_display_mode *mode) @@ -1440,16 +1504,11 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, video->interlaced = true; } -static void analogix_dp_bridge_nop(struct drm_bridge *bridge) -{ - /* do nothing */ -} - static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { .pre_enable = analogix_dp_bridge_pre_enable, .enable = analogix_dp_bridge_enable, - .disable = analogix_dp_bridge_disable, - .post_disable = analogix_dp_bridge_nop, + .disable = analogix_dp_bridge_atomic_disable, + .post_disable = analogix_dp_bridge_post_disable, .mode_set = analogix_dp_bridge_mode_set, .attach = analogix_dp_bridge_attach, }; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 769255dc6e99..d937fa3d9ee8 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -173,8 +173,8 @@ struct analogix_dp_device { int dpms_mode; int hpd_gpio; bool force_hpd; - bool psr_enable; bool fast_train_enable; + bool psr_supported; struct mutex panel_lock; bool panel_is_modeset; diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index f6fc9d5dd0ad..a777726c23cb 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -4,8 +4,7 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ - rockchip_drm_gem.o rockchip_drm_psr.o \ - rockchip_drm_vop.o rockchip_vop_reg.o + rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index bc4423624209..8f42c38848db 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -32,7 +32,6 @@ #include #include "rockchip_drm_drv.h" -#include "rockchip_drm_psr.h" #include "rockchip_drm_vop.h" #define RK3288_GRF_SOC_CON6 0x25c @@ -77,29 +76,6 @@ struct rockchip_dp_device { struct analogix_dp_plat_data plat_data; }; -static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) -{ - struct rockchip_dp_device *dp = to_dp(encoder); - int ret; - - if (!analogix_dp_psr_enabled(dp->adp)) - return 0; - - DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); - - ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, - PSR_WAIT_LINE_FLAG_TIMEOUT_MS); - if (ret) { - DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n"); - return -ETIMEDOUT; - } - - if (enabled) - return analogix_dp_enable_psr(dp->adp); - else - return analogix_dp_disable_psr(dp->adp); -} - static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) { reset_control_assert(dp->rst); @@ -130,21 +106,9 @@ static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data) return ret; } -static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data) -{ - struct rockchip_dp_device *dp = to_dp(plat_data); - - return rockchip_drm_psr_inhibit_put(&dp->encoder); -} - static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) { struct rockchip_dp_device *dp = to_dp(plat_data); - int ret; - - ret = rockchip_drm_psr_inhibit_get(&dp->encoder); - if (ret != 0) - return ret; clk_disable_unprepare(dp->pclk); @@ -190,6 +154,9 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) int ret; u32 val; + if (analogix_dp_self_refresh_changed(dp->adp)) + return; + ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); if (ret < 0) return; @@ -214,9 +181,24 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) clk_disable_unprepare(dp->grfclk); } -static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) +static void rockchip_dp_drm_encoder_disable(struct drm_encoder *encoder) { - /* do nothing */ + struct rockchip_dp_device *dp = to_dp(encoder); + struct drm_crtc *crtc; + int ret; + + drm_for_each_crtc(crtc, dp->drm_dev) { + if (!(crtc->state->encoder_mask & drm_encoder_mask(encoder))) + continue; + + if (!crtc->state->self_refresh_active) + continue; + + ret = rockchip_drm_wait_vact_end(crtc, + PSR_WAIT_LINE_FLAG_TIMEOUT_MS); + if (ret) + DRM_DEV_ERROR(dp->dev, "line flag irq timed out\n"); + } } static int @@ -246,7 +228,7 @@ static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .mode_fixup = rockchip_dp_drm_encoder_mode_fixup, .mode_set = rockchip_dp_drm_encoder_mode_set, .enable = rockchip_dp_drm_encoder_enable, - .disable = rockchip_dp_drm_encoder_nop, + .disable = rockchip_dp_drm_encoder_disable, .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; @@ -338,23 +320,16 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->plat_data.dev_type = dp->data->chip_type; dp->plat_data.power_on_start = rockchip_dp_poweron_start; - dp->plat_data.power_on_end = rockchip_dp_poweron_end; dp->plat_data.power_off = rockchip_dp_powerdown; dp->plat_data.get_modes = rockchip_dp_get_modes; - ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - if (ret < 0) - goto err_cleanup_encoder; - dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); if (IS_ERR(dp->adp)) { ret = PTR_ERR(dp->adp); - goto err_unreg_psr; + goto err_cleanup_encoder; } return 0; -err_unreg_psr: - rockchip_drm_psr_unregister(&dp->encoder); err_cleanup_encoder: dp->encoder.funcs->destroy(&dp->encoder); return ret; @@ -366,7 +341,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, struct rockchip_dp_device *dp = dev_get_drvdata(dev); analogix_dp_unbind(dp->adp); - rockchip_drm_psr_unregister(&dp->encoder); dp->encoder.funcs->destroy(&dp->encoder); dp->adp = ERR_PTR(-ENODEV); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 97438bbbe389..7e121875e3c9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -23,22 +23,10 @@ #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" #include "rockchip_drm_gem.h" -#include "rockchip_drm_psr.h" - -static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb, - struct drm_file *file, - unsigned int flags, unsigned int color, - struct drm_clip_rect *clips, - unsigned int num_clips) -{ - rockchip_drm_psr_flush_all(fb->dev); - return 0; -} static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { .destroy = drm_gem_fb_destroy, .create_handle = drm_gem_fb_create_handle, - .dirty = rockchip_drm_fb_dirty, }; static struct drm_framebuffer * @@ -132,8 +120,6 @@ rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) { struct drm_device *dev = old_state->dev; - rockchip_drm_psr_inhibit_get_state(old_state); - drm_atomic_helper_commit_modeset_disables(dev, old_state); drm_atomic_helper_commit_modeset_enables(dev, old_state); @@ -141,8 +127,6 @@ rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) drm_atomic_helper_commit_planes(dev, old_state, DRM_PLANE_COMMIT_ACTIVE_ONLY); - rockchip_drm_psr_inhibit_put_state(old_state); - drm_atomic_helper_commit_hw_done(old_state); drm_atomic_helper_wait_for_vblanks(dev, old_state); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c deleted file mode 100644 index a0c8bd235b67..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author: Yakir Yang - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include "rockchip_drm_drv.h" -#include "rockchip_drm_psr.h" - -#define PSR_FLUSH_TIMEOUT_MS 100 - -struct psr_drv { - struct list_head list; - struct drm_encoder *encoder; - - struct mutex lock; - int inhibit_count; - bool enabled; - - struct delayed_work flush_work; - - int (*set)(struct drm_encoder *encoder, bool enable); -}; - -static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder) -{ - struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; - struct psr_drv *psr; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry(psr, &drm_drv->psr_list, list) { - if (psr->encoder == encoder) - goto out; - } - psr = ERR_PTR(-ENODEV); - -out: - mutex_unlock(&drm_drv->psr_list_lock); - return psr; -} - -static int psr_set_state_locked(struct psr_drv *psr, bool enable) -{ - int ret; - - if (psr->inhibit_count > 0) - return -EINVAL; - - if (enable == psr->enabled) - return 0; - - ret = psr->set(psr->encoder, enable); - if (ret) - return ret; - - psr->enabled = enable; - return 0; -} - -static void psr_flush_handler(struct work_struct *work) -{ - struct psr_drv *psr = container_of(to_delayed_work(work), - struct psr_drv, flush_work); - - mutex_lock(&psr->lock); - psr_set_state_locked(psr, true); - mutex_unlock(&psr->lock); -} - -/** - * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder - * @encoder: encoder to obtain the PSR encoder - * - * Decrements PSR inhibit count on given encoder. Should be called only - * for a PSR inhibit count increment done before. If PSR inhibit counter - * reaches zero, PSR flush work is scheduled to make the hardware enter - * PSR mode in PSR_FLUSH_TIMEOUT_MS. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder) -{ - struct psr_drv *psr = find_psr_by_encoder(encoder); - - if (IS_ERR(psr)) - return PTR_ERR(psr); - - mutex_lock(&psr->lock); - --psr->inhibit_count; - WARN_ON(psr->inhibit_count < 0); - if (!psr->inhibit_count) - mod_delayed_work(system_wq, &psr->flush_work, - PSR_FLUSH_TIMEOUT_MS); - mutex_unlock(&psr->lock); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put); - -void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_encoder *encoder; - u32 encoder_mask = 0; - int i; - - for_each_old_crtc_in_state(state, crtc, crtc_state, i) { - encoder_mask |= crtc_state->encoder_mask; - encoder_mask |= crtc->state->encoder_mask; - } - - drm_for_each_encoder_mask(encoder, state->dev, encoder_mask) - rockchip_drm_psr_inhibit_get(encoder); -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state); - -void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_encoder *encoder; - u32 encoder_mask = 0; - int i; - - for_each_old_crtc_in_state(state, crtc, crtc_state, i) { - encoder_mask |= crtc_state->encoder_mask; - encoder_mask |= crtc->state->encoder_mask; - } - - drm_for_each_encoder_mask(encoder, state->dev, encoder_mask) - rockchip_drm_psr_inhibit_put(encoder); -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state); - -/** - * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder - * @encoder: encoder to obtain the PSR encoder - * - * Increments PSR inhibit count on given encoder. This function guarantees - * that after it returns PSR is turned off on given encoder and no PSR-related - * hardware state change occurs at least until a matching call to - * rockchip_drm_psr_inhibit_put() is done. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder) -{ - struct psr_drv *psr = find_psr_by_encoder(encoder); - - if (IS_ERR(psr)) - return PTR_ERR(psr); - - mutex_lock(&psr->lock); - psr_set_state_locked(psr, false); - ++psr->inhibit_count; - mutex_unlock(&psr->lock); - cancel_delayed_work_sync(&psr->flush_work); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get); - -static void rockchip_drm_do_flush(struct psr_drv *psr) -{ - cancel_delayed_work_sync(&psr->flush_work); - - mutex_lock(&psr->lock); - if (!psr_set_state_locked(psr, false)) - mod_delayed_work(system_wq, &psr->flush_work, - PSR_FLUSH_TIMEOUT_MS); - mutex_unlock(&psr->lock); -} - -/** - * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders - * @dev: drm device - * - * Disable the PSR function for all registered encoders, and then enable the - * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been - * changed during flush time, then keep the state no change after flush - * timeout. - * - * Returns: - * Zero on success, negative errno on failure. - */ -void rockchip_drm_psr_flush_all(struct drm_device *dev) -{ - struct rockchip_drm_private *drm_drv = dev->dev_private; - struct psr_drv *psr; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry(psr, &drm_drv->psr_list, list) - rockchip_drm_do_flush(psr); - mutex_unlock(&drm_drv->psr_list_lock); -} -EXPORT_SYMBOL(rockchip_drm_psr_flush_all); - -/** - * rockchip_drm_psr_register - register encoder to psr driver - * @encoder: encoder that obtain the PSR function - * @psr_set: call back to set PSR state - * - * The function returns with PSR inhibit counter initialized with one - * and the caller (typically encoder driver) needs to call - * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR - * enable request. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_register(struct drm_encoder *encoder, - int (*psr_set)(struct drm_encoder *, bool enable)) -{ - struct rockchip_drm_private *drm_drv; - struct psr_drv *psr; - - if (!encoder || !psr_set) - return -EINVAL; - - drm_drv = encoder->dev->dev_private; - - psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL); - if (!psr) - return -ENOMEM; - - INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler); - mutex_init(&psr->lock); - - psr->inhibit_count = 1; - psr->enabled = false; - psr->encoder = encoder; - psr->set = psr_set; - - mutex_lock(&drm_drv->psr_list_lock); - list_add_tail(&psr->list, &drm_drv->psr_list); - mutex_unlock(&drm_drv->psr_list_lock); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_register); - -/** - * rockchip_drm_psr_unregister - unregister encoder to psr driver - * @encoder: encoder that obtain the PSR function - * @psr_set: call back to set PSR state - * - * It is expected that the PSR inhibit counter is 1 when this function is - * called, which corresponds to a state when related encoder has been - * disconnected from any CRTCs and its driver called - * rockchip_drm_psr_inhibit_get() to stop the PSR logic. - * - * Returns: - * Zero on success, negative errno on failure. - */ -void rockchip_drm_psr_unregister(struct drm_encoder *encoder) -{ - struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; - struct psr_drv *psr, *n; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { - if (psr->encoder == encoder) { - /* - * Any other value would mean that the encoder - * is still in use. - */ - WARN_ON(psr->inhibit_count != 1); - - list_del(&psr->list); - kfree(psr); - } - } - mutex_unlock(&drm_drv->psr_list_lock); -} -EXPORT_SYMBOL(rockchip_drm_psr_unregister); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h deleted file mode 100644 index 25350ba3237b..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author: Yakir Yang - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __ROCKCHIP_DRM_PSR___ -#define __ROCKCHIP_DRM_PSR___ - -void rockchip_drm_psr_flush_all(struct drm_device *dev); - -int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder); -int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder); - -void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state); -void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state); - -int rockchip_drm_psr_register(struct drm_encoder *encoder, - int (*psr_set)(struct drm_encoder *, bool enable)); -void rockchip_drm_psr_unregister(struct drm_encoder *encoder); - -#endif /* __ROCKCHIP_DRM_PSR__ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c7d4c6073ea5..21fccda70356 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_DRM_ANALOGIX_DP #include #endif @@ -42,10 +43,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_core_clks_disable(struct vop *vop) clk_disable(vop->hclk); } -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_SET(vop, win, enable, 0); + VOP_WIN_SET(vop, win, enable, 0); + } } spin_unlock(&vop->reg_lock); @@ -937,12 +945,10 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane, } 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); } plane->funcs->atomic_destroy_state(plane, plane_state); @@ -1035,7 +1041,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); @@ -1509,6 +1515,13 @@ static int vop_create_crtc(struct vop *vop) init_completion(&vop->line_flag_completion); crtc->port = port; + ret = drm_self_refresh_helper_register(crtc, + VOP_SELF_REFRESH_ENTRY_DELAY_MS); + if (ret) + DRM_DEV_DEBUG_KMS(vop->dev, + "Failed to register %s with SR helpers %d, ignoring\n", + crtc->name, ret); + return 0; err_cleanup_crtc: @@ -1526,6 +1539,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_unregister(crtc); + of_node_put(crtc->port); /* diff --git a/include/drm/bridge/analogix_dp.h b/include/drm/bridge/analogix_dp.h index 475b706b49de..b6cc654143d7 100644 --- a/include/drm/bridge/analogix_dp.h +++ b/include/drm/bridge/analogix_dp.h @@ -42,9 +42,7 @@ struct analogix_dp_plat_data { struct drm_connector *); }; -int analogix_dp_psr_enabled(struct analogix_dp_device *dp); -int analogix_dp_enable_psr(struct analogix_dp_device *dp); -int analogix_dp_disable_psr(struct analogix_dp_device *dp); +bool analogix_dp_self_refresh_changed(struct analogix_dp_device *dp); int analogix_dp_resume(struct analogix_dp_device *dp); int analogix_dp_suspend(struct analogix_dp_device *dp); From patchwork Tue Mar 26 20:44:57 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10872177 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 59E69922 for ; Tue, 26 Mar 2019 20:45:54 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 455C628AD3 for ; Tue, 26 Mar 2019 20:45:54 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 397D028D01; Tue, 26 Mar 2019 20:45:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id BEFB228AD3 for ; Tue, 26 Mar 2019 20:45:53 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EE3E689FC5; Tue, 26 Mar 2019 20:45:52 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt1-x842.google.com (mail-qt1-x842.google.com [IPv6:2607:f8b0:4864:20::842]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4F6EA89FC5 for ; Tue, 26 Mar 2019 20:45:51 +0000 (UTC) Received: by mail-qt1-x842.google.com with SMTP id z17so16280777qts.13 for ; Tue, 26 Mar 2019 13:45:51 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=r/lMKSRJP0NOgF0XiUAPTHQ2uG7jek10qfd+UW8Bf9M=; b=oHHuBwq5BRrbfVzRq59cKoRTHXytjS8vP/AHWPGwt0whexRkMOeVqrYHICN9XSgInd irx++yWnW+nsLSvI9nSfzpwtv0QnLsTwI7oa8LnBjXU1ykM3Y4aWFQNxbuFXDQ5qwEB6 Sy1oARyQ8gjMmnwlPeVzdVfc3PkWZ3Y6FHQDr1PWLeV0Zu/AshmhJcc2Jqy+eACqGZLZ J43fBaS8w31wB6g6BZX/Z6afsTSNusXbuPhYTuwDgh3SfC6pIMrOlDYir+tQ7lH23WO7 Wd4AhUb2i0S6RpyJncVy4Xh3wfRqf2lhRcYSqBAeGJ1x1YM5JUVkLyla4bju3zayowTi oz6g== X-Gm-Message-State: APjAAAWbM94ZIVS0oMLcQ2I5A5NHxln6igueC88K210utOVMBhJEja7K /EDbDFSVqzMfJt3nnJUX/PXDCpBNO08= X-Google-Smtp-Source: APXvYqxUaq7Hd+jut9nyl+HfwMkJ07zGngA9lVSD3EhN8Jb+1UdQfXjmTyuyCugw65Clo2MPIIYxmg== X-Received: by 2002:ac8:3376:: with SMTP id u51mr12930251qta.317.1553633150394; Tue, 26 Mar 2019 13:45:50 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:89c6:2139:5435:371d]) by smtp.gmail.com with ESMTPSA id i11sm9405810qkg.33.2019.03.26.13.45.49 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2019 13:45:49 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 4/5] drm/rockchip: Don't fully disable vop on self refresh Date: Tue, 26 Mar 2019 16:44:57 -0400 Message-Id: <20190326204509.96515-4-sean@poorly.run> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog In-Reply-To: <20190326204509.96515-1-sean@poorly.run> References: <20190326204509.96515-1-sean@poorly.run> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poorly.run; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=r/lMKSRJP0NOgF0XiUAPTHQ2uG7jek10qfd+UW8Bf9M=; b=OYPGeZ2FytnkZzJu1/yuyvCZoTTE+FZ/czB9MSGb+jOyQQ038Fu0mCefS1O1keKcr9 7lRPB0aAWuqjj7FFEGJGZrhwQIGz/1p/oG+H1ffTbc6z/Y6iAXACF2y+UtfXKCBKDUk5 5CaFnezenwU2ebAgMtBWWrTa2I3q02pntWFhnP9rzgIrjn5ZLkABo3ON7RgyNAJzDDSP DPrzHir9/F1zWYPCi+aWGgNVevHWN+1cD6aY4Il9R/X7hC/74GFR5FRKmY2e2FwyWcRI qp+moEB6Ks2sveZWK/hVAugrAIyOP3CzmdG8ggycnTKbbhGPDT34xHDrMMiRTj/whwLx xb7A== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zain Wang , David Airlie , Tomasz Figa , Sean Paul , "Kristian H . Kristensen" Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul Instead of fully disabling and re-enabling the vop on self refresh transitions, only disable the active windows. This will speed up self refresh exits substantially and is still a power-savings win. This patch integrates portions of Zain's patch from here: https://patchwork.kernel.org/patch/9615063/ Changes in v2: - None Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-5-sean@poorly.run Cc: Zain Wang Cc: Tomasz Figa Cc: Kristian H. Kristensen Signed-off-by: Sean Paul --- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 21fccda70356..a1e8a9a7bdd0 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -134,6 +134,7 @@ struct vop { bool is_enabled; struct completion dsp_hold_completion; + unsigned int win_enabled; /* protected by dev->event_lock */ struct drm_pending_vblank_event *event; @@ -594,6 +595,7 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) const struct vop_win_data *win = vop_win->data; VOP_WIN_SET(vop, win, enable, 0); + vop->win_enabled &= ~BIT(i); } } spin_unlock(&vop->reg_lock); @@ -624,6 +626,25 @@ static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) return ret; } +static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled) +{ + struct vop *vop = to_vop(crtc); + int i; + + spin_lock(&vop->reg_lock); + + 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_SET(vop, win, enable, + enabled && (vop->win_enabled & BIT(i))); + } + vop_cfg_done(vop); + + spin_unlock(&vop->reg_lock); +} + static void vop_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -631,9 +652,15 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, WARN_ON(vop->event); + if (crtc->state->self_refresh_active) + rockchip_drm_set_win_enabled(crtc, false); + mutex_lock(&vop->vop_lock); drm_crtc_vblank_off(crtc); + if (crtc->state->self_refresh_active) + goto out; + /* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete. @@ -664,6 +691,8 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, clk_disable(vop->dclk); vop_core_clks_disable(vop); pm_runtime_put(vop->dev); + +out: mutex_unlock(&vop->vop_lock); if (crtc->state->event && !crtc->state->active) { @@ -744,6 +773,7 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, spin_lock(&vop->reg_lock); VOP_WIN_SET(vop, win, enable, 0); + vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win)); spin_unlock(&vop->reg_lock); } @@ -882,6 +912,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, } VOP_WIN_SET(vop, win, enable, 1); + vop->win_enabled |= BIT(win_index); spin_unlock(&vop->reg_lock); } @@ -1037,6 +1068,12 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, uint32_t pin_pol, val; int ret; + if (old_state && old_state->self_refresh_active) { + drm_crtc_vblank_on(crtc); + rockchip_drm_set_win_enabled(crtc, true); + return; + } + mutex_lock(&vop->vop_lock); WARN_ON(vop->event); @@ -1639,6 +1676,7 @@ static int vop_initial(struct vop *vop) VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel); VOP_WIN_SET(vop, win, enable, 0); VOP_WIN_SET(vop, win, gate, 1); + vop->win_enabled &= ~BIT(i); } vop_cfg_done(vop); From patchwork Tue Mar 26 20:44:58 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Paul X-Patchwork-Id: 10872179 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 604B817E6 for ; Tue, 26 Mar 2019 20:46:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4C70328AD3 for ; Tue, 26 Mar 2019 20:46:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4084728D01; Tue, 26 Mar 2019 20:46:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id EAA5728AD3 for ; Tue, 26 Mar 2019 20:46:01 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 2E7786E051; Tue, 26 Mar 2019 20:46:01 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qt1-x841.google.com (mail-qt1-x841.google.com [IPv6:2607:f8b0:4864:20::841]) by gabe.freedesktop.org (Postfix) with ESMTPS id C17D66E051 for ; Tue, 26 Mar 2019 20:45:59 +0000 (UTC) Received: by mail-qt1-x841.google.com with SMTP id t28so16341091qte.6 for ; Tue, 26 Mar 2019 13:45:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AroNjwSg9NHnOjzwnLrE8Zyy0RaWm1yOpvUkVR0KN5g=; b=gv3qycbeO7ZjTxWphDIhb/ha0XFzMOcc3xgHGVtszHKQwQMJB7aO7KPb1n9OINgTVz Sy3gOdsBXgHnqZJgv0LEhYvY6xMsJA2YUqQHt7dAAqefE2xsjEGXBGeHY150yL7o+8lp gHiuy/NPOzD2M2WkuZTNUfQu9RxWAyLWIG2elG3kJI4uBxOUqXVqMhVH+vmPQN8eD7kL YiGDqQ1kQqS1a5hXLmbt+fiikYSLDUrbq4dQ0aA8eBMV0DrqCjW9m3V2MnW8Aq0wgRFh aoWWQftxChfD4eZwUvPppE9MJfLUMzGAZ98s8p9nNDujNwrkpgvvWHk3b/AOkCx85rLy e4wQ== X-Gm-Message-State: APjAAAXGQsCDM67b+WQngEpKs0bYejmuhj/ZCHq7LlKpYQmEFMcrGdAn kCu6MfYMvMaVTV/SMbgOPGjxuqepwOI= X-Google-Smtp-Source: APXvYqyC/nfua4Tz75p+jza0/5/OO7yDzK7FIqao6ie9EZWHUk5CvViLo0gdWWK2WufdvzVRJcSERA== X-Received: by 2002:a0c:b501:: with SMTP id d1mr28006090qve.115.1553633158884; Tue, 26 Mar 2019 13:45:58 -0700 (PDT) Received: from rosewood.cam.corp.google.com ([2620:0:1013:11:89c6:2139:5435:371d]) by smtp.gmail.com with ESMTPSA id i11sm9405810qkg.33.2019.03.26.13.45.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Mar 2019 13:45:58 -0700 (PDT) From: Sean Paul To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 5/5] drm/rockchip: Use drm_atomic_helper_commit_tail_rpm Date: Tue, 26 Mar 2019 16:44:58 -0400 Message-Id: <20190326204509.96515-5-sean@poorly.run> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog In-Reply-To: <20190326204509.96515-1-sean@poorly.run> References: <20190326204509.96515-1-sean@poorly.run> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poorly.run; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AroNjwSg9NHnOjzwnLrE8Zyy0RaWm1yOpvUkVR0KN5g=; b=a+blo5GutSHGPJDn3PktP+s2mvvwby1vFNS1V/blupQDbxXHQD0ZGEZnQR/t6S1znV Ofsky1PdRlN2CVBSk1Hzg4G592QxkTF+a56sQ7mkSJiIxHaXwVgBOt3SarUZs0XToLz3 CDkacG+I6ydlmyvWyZUE5+xodx3BcGfFQttpfydcxKG20N1hZCLaPwQyt/HTLu0RcEAb F2v6bYhdZq1iewZDovJ2EVbr1K+DVubxyqNaogpgnZ5fsyA7jnfQebRinYFMk6295Ajk /N8k3YlW9g8TsEsGhjyZrlB23j9oWLEIPpF6NxI9ZL9bjcOqhCHv140SQV9M7N31Sh/V WMiw== X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Zain Wang , David Airlie , Tomasz Figa , Sean Paul Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Sean Paul Now that we use the drm psr helpers, we no longer need to hand-roll our atomic_commit_tail implementation. So use the helper Changes in v2: - None Link to v1: https://patchwork.freedesktop.org/patch/msgid/20190228210939.83386-6-sean@poorly.run Cc: Zain Wang Cc: Tomasz Figa Signed-off-by: Sean Paul --- drivers/gpu/drm/rockchip/rockchip_drm_fb.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 7e121875e3c9..75198df2b022 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -115,27 +115,8 @@ rockchip_user_fb_create(struct drm_device *dev, struct drm_file *file_priv, return ERR_PTR(ret); } -static void -rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) -{ - struct drm_device *dev = old_state->dev; - - drm_atomic_helper_commit_modeset_disables(dev, old_state); - - drm_atomic_helper_commit_modeset_enables(dev, old_state); - - drm_atomic_helper_commit_planes(dev, old_state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); - - drm_atomic_helper_commit_hw_done(old_state); - - drm_atomic_helper_wait_for_vblanks(dev, old_state); - - drm_atomic_helper_cleanup_planes(dev, old_state); -} - static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { - .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm, + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, }; static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {