disp: msm: sde: calculate line_time once during modeset

Calculate line_time once during modeset and allow
each plane to use it instead of calculating for each frame.
It also simplifies the line_time calculation for
command mode display.

Change-Id: I94ce29eec94bfdbee9016fbf93378661ebf79c03
Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
Dhaval Patel
2021-01-26 14:29:47 -08:00
committed by Prabhanjan Kandula
parent 6de4718ee9
commit b5cde14bca
9 changed files with 57 additions and 67 deletions

View File

@@ -5875,6 +5875,33 @@ exit:
return ret; return ret;
} }
static void sde_crtc_update_line_time(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
struct drm_encoder *encoder;
u32 min_transfer_time = 0, updated_fps = 0;
drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) {
if (sde_encoder_check_curr_mode(encoder, MSM_DISPLAY_CMD_MODE))
sde_encoder_get_transfer_time(encoder, &min_transfer_time);
}
if (min_transfer_time) {
/* get fps by doing 1000 ms / transfer_time */
updated_fps = DIV_ROUND_UP(1000000, min_transfer_time);
/* get line time by doing 1000ns / (fps * vactive) */
sde_crtc->line_time_in_ns = DIV_ROUND_UP(1000000000,
updated_fps * crtc->mode.vdisplay);
} else {
/* get line time by doing 1000ns / (fps * vtotal) */
sde_crtc->line_time_in_ns = DIV_ROUND_UP(1000000000,
drm_mode_vrefresh(&crtc->mode) * crtc->mode.vtotal);
}
SDE_EVT32(min_transfer_time, updated_fps, crtc->mode.vdisplay, crtc->mode.vtotal,
drm_mode_vrefresh(&crtc->mode), sde_crtc->line_time_in_ns);
}
void sde_crtc_set_qos_dirty(struct drm_crtc *crtc) void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
{ {
struct drm_plane *plane; struct drm_plane *plane;
@@ -5890,6 +5917,7 @@ void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
pstate->dirty |= SDE_PLANE_DIRTY_QOS; pstate->dirty |= SDE_PLANE_DIRTY_QOS;
} }
sde_crtc_update_line_time(crtc);
} }
/** /**

View File

@@ -300,7 +300,7 @@ struct sde_crtc_misr_info {
* @skip_blend_plane: enabled plane that has skip blending * @skip_blend_plane: enabled plane that has skip blending
* @skip_blend_plane_w: skip blend plane width * @skip_blend_plane_w: skip blend plane width
* @skip_blend_plane_h: skip blend plane height * @skip_blend_plane_h: skip blend plane height
* * @line_time_in_ns : current mode line time in nano sec is needed for QOS update
*/ */
struct sde_crtc { struct sde_crtc {
struct drm_crtc base; struct drm_crtc base;
@@ -397,6 +397,7 @@ struct sde_crtc {
enum sde_sspp skip_blend_plane; enum sde_sspp skip_blend_plane;
u32 skip_blend_plane_w; u32 skip_blend_plane_w;
u32 skip_blend_plane_h; u32 skip_blend_plane_h;
u32 line_time_in_ns;
}; };
enum sde_crtc_dirty_flags { enum sde_crtc_dirty_flags {
@@ -741,6 +742,16 @@ static inline bool sde_crtc_is_enabled(struct drm_crtc *crtc)
return crtc ? crtc->enabled : false; return crtc ? crtc->enabled : false;
} }
static inline u32 sde_crtc_get_line_time(struct drm_crtc *crtc)
{
struct sde_crtc *sde_crtc;
if (!crtc)
return 0;
sde_crtc = to_sde_crtc(crtc);
return sde_crtc->line_time_in_ns;
}
/** /**
* sde_crtc_is_reset_required - validate the reset request based on the * sde_crtc_is_reset_required - validate the reset request based on the
* pm_suspend and crtc's active status. crtc's are left active * pm_suspend and crtc's active status. crtc's are left active

View File

@@ -4336,7 +4336,7 @@ void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
} }
} }
void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc, void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
u32 *transfer_time_us) u32 *transfer_time_us)
{ {
struct sde_encoder_virt *sde_enc; struct sde_encoder_virt *sde_enc;

View File

@@ -581,6 +581,14 @@ void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable);
struct drm_connector *sde_encoder_get_connector(struct drm_device *dev, struct drm_connector *sde_encoder_get_connector(struct drm_device *dev,
struct drm_encoder *drm_enc); struct drm_encoder *drm_enc);
/**
* sde_encoder_get_transfer_time - get the mdp transfer time in usecs
* @drm_enc: Pointer to drm encoder structure
* @transfer_time_us: Pointer to store the output value
*/
void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
u32 *transfer_time_us);
/* /*
* sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of * sde_encoder_get_dfps_maxfps - get dynamic FPS max frame rate of
the given encoder the given encoder

View File

@@ -542,14 +542,6 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc, void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
struct sde_hw_pp_vsync_info *info); struct sde_hw_pp_vsync_info *info);
/**
* sde_encoder_helper_get_transfer_time - get the mdp transfer time in usecs
* @drm_enc: Pointer to drm encoder structure
* @transfer_time_us: Pointer to store the output value
*/
void sde_encoder_helper_get_transfer_time(struct drm_encoder *drm_enc,
u32 *transfer_time_us);
/** /**
* sde_encoder_helper_trigger_flush - control flush helper function * sde_encoder_helper_trigger_flush - control flush helper function
* This helper function may be optionally specified by physical * This helper function may be optionally specified by physical

View File

@@ -975,18 +975,18 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
} }
/* Calculate the number of extra lines*/ /* Calculate the number of extra lines*/
slow_time_ns = (1 * 1000000000) / qsync_min_fps; slow_time_ns = DIV_ROUND_UP(1000000000, qsync_min_fps);
default_time_ns = (1 * 1000000000) / default_fps; default_time_ns = DIV_ROUND_UP(1000000000, default_fps);
sde_encoder_helper_get_transfer_time(phys_enc->parent, sde_encoder_get_transfer_time(phys_enc->parent,
&transfer_time_us); &transfer_time_us);
if (transfer_time_us) if (transfer_time_us)
idle_time_ns = default_time_ns - idle_time_ns = default_time_ns -
(1000 * transfer_time_us); (1000 * transfer_time_us);
extra_time_ns = slow_time_ns - default_time_ns + idle_time_ns; extra_time_ns = slow_time_ns - default_time_ns + idle_time_ns;
default_line_time_ns = (1 * 1000000000) / (default_fps * yres); default_line_time_ns = DIV_ROUND_UP(1000000000, default_fps * yres);
threshold_lines = extra_time_ns / default_line_time_ns; threshold_lines = DIV_ROUND_UP(extra_time_ns, default_line_time_ns);
SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n", SDE_DEBUG_CMDENC(cmd_enc, "slow:%d default:%d extra:%d(ns)\n",
slow_time_ns, default_time_ns, extra_time_ns); slow_time_ns, default_time_ns, extra_time_ns);

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__ #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -540,47 +540,3 @@ uint32_t sde_copy_formats(
return i; return i;
} }
/**
* sde_get_linetime - returns the line time for a given mode
* @mode: pointer to drm mode to calculate the line time
* @src_bpp: source bpp
* @target_bpp: target bpp
* Return: line time of display mode in nS
*/
uint32_t sde_get_linetime(struct drm_display_mode *mode,
int src_bpp, int target_bpp)
{
u64 pclk_rate;
u32 pclk_period;
u32 line_time;
pclk_rate = mode->clock; /* pixel clock in kHz */
if (pclk_rate == 0) {
SDE_ERROR("pclk is 0, cannot calculate line time\n");
return 0;
}
pclk_period = DIV_ROUND_UP_ULL(1000000000ull, pclk_rate);
if (pclk_period == 0) {
SDE_ERROR("pclk period is 0\n");
return 0;
}
/*
* Line time calculation based on Pixel clock, HTOTAL, and comp_ratio.
* Compression ratio found by src_bpp/target_bpp. Final unit is in ns.
*/
line_time = pclk_period * mode->htotal;
line_time = DIV_ROUND_UP(mult_frac(line_time, target_bpp,
src_bpp), 1000);
if (line_time == 0) {
SDE_ERROR("line time calculation is 0\n");
return 0;
}
pr_debug("clk_rate=%lldkHz, clk_period=%d, linetime=%dns, htotal=%d\n",
pclk_rate, pclk_period, line_time, mode->htotal);
return line_time;
}

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
*/ */
#ifndef _SDE_HW_UTIL_H #ifndef _SDE_HW_UTIL_H
@@ -212,9 +212,6 @@ uint32_t sde_copy_formats(
const struct sde_format_extended *src_list, const struct sde_format_extended *src_list,
uint32_t src_list_size); uint32_t src_list_size);
uint32_t sde_get_linetime(struct drm_display_mode *mode,
int src_bpp, int target_bpp);
static inline bool is_qseed3_rev_qseed3lite(struct sde_mdss_cfg *sde_cfg) static inline bool is_qseed3_rev_qseed3lite(struct sde_mdss_cfg *sde_cfg)
{ {
return ((sde_cfg->qseed_sw_lib_rev == SDE_SSPP_SCALER_QSEED3LITE) ? return ((sde_cfg->qseed_sw_lib_rev == SDE_SSPP_SCALER_QSEED3LITE) ?

View File

@@ -2909,11 +2909,9 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc,
struct sde_rect *src, struct sde_rect *dst) struct sde_rect *src, struct sde_rect *dst)
{ {
struct sde_hw_pipe_uidle_cfg cfg; struct sde_hw_pipe_uidle_cfg cfg;
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
u32 fal1_threshold_max = 15; u32 fal1_threshold_max = 15;
u32 line_time = sde_get_linetime(&crtc->mode, u32 line_time = sde_crtc_get_line_time(crtc);
sde_crtc->src_bpp, sde_crtc->target_bpp); /* nS */
u32 fal1_target_idle_time_ns = u32 fal1_target_idle_time_ns =
psde->catalog->uidle_cfg.fal1_target_idle_time * 1000; /* nS */ psde->catalog->uidle_cfg.fal1_target_idle_time * 1000; /* nS */
u32 fal10_target_idle_time_ns = u32 fal10_target_idle_time_ns =