adreno_tz: Fix GPU target frequency calculation for high refresh rates

It seems that the black-box GPU frequency selection algorithm is unaware
of high refresh rates, and assumes a refresh rate of 60 Hz for its
target frequencies. This results in frequencies that are too low being
selected when a higher refresh rate, such as 90 Hz, is used.

To remedy this, multiply the GPU's busy time by a ratio of the current
refresh rate to 60 Hz. This makes msm-adreno-tz select the right
frequencies needed to avoid stuttering.

[ghostrider-reborn]
- Actually make it work with real-time dynamic refresh rate

Change-Id: Idb8e033bbbd1e6e6ebf1a47d4f9bd618df812658
Signed-off-by: Sultan Alsawaf <sultan@kerneltoast.com>
Signed-off-by: Adithya R <gh0strider.2k18.reborn@gmail.com>
Signed-off-by: Richard Raya <rdxzv.dev@gmail.com>
This commit is contained in:
Sultan Alsawaf 2020-12-28 01:53:11 -08:00 committed by Richard Raya
parent 8a4484ea84
commit bd79183928
3 changed files with 23 additions and 1 deletions

View File

@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/msm_adreno_devfreq.h>
#include <asm/cacheflush.h>
#include <drm/drm_refresh_rate.h>
#include <soc/qcom/scm.h>
#include "governor.h"
@ -378,9 +379,13 @@ static int tz_get_target_freq(struct devfreq *devfreq, unsigned long *freq)
priv->bin.busy_time > CEILING) {
val = -1 * level;
} else {
unsigned int refresh_rate = dsi_panel_get_refresh_rate();
scm_data[0] = level;
scm_data[1] = priv->bin.total_time;
if (refresh_rate > 60)
scm_data[2] = priv->bin.busy_time * refresh_rate / 60;
else
scm_data[2] = priv->bin.busy_time;
scm_data[3] = context_count;
__secure_tz_update_entry3(scm_data, sizeof(scm_data),

View File

@ -59,6 +59,8 @@ static const struct of_device_id dsi_display_dt_match[] = {
{}
};
static unsigned int cur_refresh_rate = 60;
static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display,
u32 mask, bool enable)
{
@ -6845,6 +6847,9 @@ int dsi_display_validate_mode_change(struct dsi_display *display,
/* dfps and dynamic clock with const fps use case */
if (dsi_display_mode_switch_dfps(cur_mode, adj_mode)) {
dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
if (cur_mode->timing.refresh_rate != adj_mode->timing.refresh_rate) {
WRITE_ONCE(cur_refresh_rate, adj_mode->timing.refresh_rate);
}
if (dfps_caps.dfps_support ||
dyn_clk_caps->maintain_const_fps) {
pr_debug("mode switch is variable refresh\n");
@ -7769,6 +7774,11 @@ int dsi_display_pre_commit(void *display,
return rc;
}
unsigned int dsi_panel_get_refresh_rate(void)
{
return READ_ONCE(cur_refresh_rate);
}
int dsi_display_enable(struct dsi_display *display)
{
int rc = 0;
@ -7807,6 +7817,7 @@ int dsi_display_enable(struct dsi_display *display)
mutex_lock(&display->display_lock);
mode = display->panel->cur_mode;
WRITE_ONCE(cur_refresh_rate, mode->timing.refresh_rate);
if (mode->dsi_mode_flags & DSI_MODE_FLAG_DMS) {
rc = dsi_panel_switch(display->panel);

View File

@ -0,0 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Sultan Alsawaf <sultan@kerneltoast.com>.
*/
unsigned int dsi_panel_get_refresh_rate(void);