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:

committed by
Prabhanjan Kandula

parent
6de4718ee9
commit
b5cde14bca
@@ -5875,6 +5875,33 @@ exit:
|
||||
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)
|
||||
{
|
||||
struct drm_plane *plane;
|
||||
@@ -5890,6 +5917,7 @@ void sde_crtc_set_qos_dirty(struct drm_crtc *crtc)
|
||||
|
||||
pstate->dirty |= SDE_PLANE_DIRTY_QOS;
|
||||
}
|
||||
sde_crtc_update_line_time(crtc);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -300,7 +300,7 @@ struct sde_crtc_misr_info {
|
||||
* @skip_blend_plane: enabled plane that has skip blending
|
||||
* @skip_blend_plane_w: skip blend plane width
|
||||
* @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 drm_crtc base;
|
||||
@@ -397,6 +397,7 @@ struct sde_crtc {
|
||||
enum sde_sspp skip_blend_plane;
|
||||
u32 skip_blend_plane_w;
|
||||
u32 skip_blend_plane_h;
|
||||
u32 line_time_in_ns;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
* pm_suspend and crtc's active status. crtc's are left active
|
||||
|
@@ -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)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
|
@@ -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_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
|
||||
the given encoder
|
||||
|
@@ -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,
|
||||
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
|
||||
* This helper function may be optionally specified by physical
|
||||
|
@@ -975,18 +975,18 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
|
||||
}
|
||||
|
||||
/* Calculate the number of extra lines*/
|
||||
slow_time_ns = (1 * 1000000000) / qsync_min_fps;
|
||||
default_time_ns = (1 * 1000000000) / default_fps;
|
||||
sde_encoder_helper_get_transfer_time(phys_enc->parent,
|
||||
slow_time_ns = DIV_ROUND_UP(1000000000, qsync_min_fps);
|
||||
default_time_ns = DIV_ROUND_UP(1000000000, default_fps);
|
||||
sde_encoder_get_transfer_time(phys_enc->parent,
|
||||
&transfer_time_us);
|
||||
if (transfer_time_us)
|
||||
idle_time_ns = default_time_ns -
|
||||
(1000 * transfer_time_us);
|
||||
|
||||
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",
|
||||
slow_time_ns, default_time_ns, extra_time_ns);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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__
|
||||
|
||||
@@ -540,47 +540,3 @@ uint32_t sde_copy_formats(
|
||||
|
||||
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;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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
|
||||
@@ -212,9 +212,6 @@ uint32_t sde_copy_formats(
|
||||
const struct sde_format_extended *src_list,
|
||||
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)
|
||||
{
|
||||
return ((sde_cfg->qseed_sw_lib_rev == SDE_SSPP_SCALER_QSEED3LITE) ?
|
||||
|
@@ -2909,11 +2909,9 @@ static void _sde_plane_setup_uidle(struct drm_crtc *crtc,
|
||||
struct sde_rect *src, struct sde_rect *dst)
|
||||
{
|
||||
struct sde_hw_pipe_uidle_cfg cfg;
|
||||
struct sde_crtc *sde_crtc = to_sde_crtc(crtc);
|
||||
u32 fal1_threshold_max = 15;
|
||||
|
||||
u32 line_time = sde_get_linetime(&crtc->mode,
|
||||
sde_crtc->src_bpp, sde_crtc->target_bpp); /* nS */
|
||||
u32 line_time = sde_crtc_get_line_time(crtc);
|
||||
u32 fal1_target_idle_time_ns =
|
||||
psde->catalog->uidle_cfg.fal1_target_idle_time * 1000; /* nS */
|
||||
u32 fal10_target_idle_time_ns =
|
||||
|
Reference in New Issue
Block a user