mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 11:11:26 +02:00
drm/msm/dpu: use common helper for WB and SSPP QoS setup
Rework SSPP and WB code to use common helper for programming QoS settings. Reviewed-by: Jeykumar Sankaran <quic_jeykumar@quicinc.com> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Patchwork: https://patchwork.freedesktop.org/patch/537912/ Link: https://lore.kernel.org/r/20230518222238.3815293-10-dmitry.baryshkov@linaro.org Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
This commit is contained in:
parent
a5ebb27bff
commit
5fe0faa624
|
|
@ -102,7 +102,7 @@ static void dpu_encoder_phys_wb_set_qos_remap(
|
|||
static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
|
||||
{
|
||||
struct dpu_hw_wb *hw_wb;
|
||||
struct dpu_hw_wb_qos_cfg qos_cfg;
|
||||
struct dpu_hw_qos_cfg qos_cfg;
|
||||
const struct dpu_mdss_cfg *catalog;
|
||||
const struct dpu_qos_lut_tbl *qos_lut_tb;
|
||||
|
||||
|
|
@ -115,7 +115,7 @@ static void dpu_encoder_phys_wb_set_qos(struct dpu_encoder_phys *phys_enc)
|
|||
|
||||
hw_wb = phys_enc->hw_wb;
|
||||
|
||||
memset(&qos_cfg, 0, sizeof(struct dpu_hw_wb_qos_cfg));
|
||||
memset(&qos_cfg, 0, sizeof(struct dpu_hw_qos_cfg));
|
||||
qos_cfg.danger_safe_en = true;
|
||||
qos_cfg.danger_lut =
|
||||
catalog->perf->danger_lut_tbl[DPU_QOS_LUT_USAGE_NRT];
|
||||
|
|
|
|||
|
|
@ -539,30 +539,15 @@ static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)
|
|||
color);
|
||||
}
|
||||
|
||||
static void dpu_hw_sspp_setup_danger_safe_lut(struct dpu_hw_sspp *ctx,
|
||||
u32 danger_lut,
|
||||
u32 safe_lut)
|
||||
static void dpu_hw_sspp_setup_qos_lut(struct dpu_hw_sspp *ctx,
|
||||
struct dpu_hw_qos_cfg *cfg)
|
||||
{
|
||||
if (!ctx)
|
||||
if (!ctx || !cfg)
|
||||
return;
|
||||
|
||||
DPU_REG_WRITE(&ctx->hw, SSPP_DANGER_LUT, danger_lut);
|
||||
DPU_REG_WRITE(&ctx->hw, SSPP_SAFE_LUT, safe_lut);
|
||||
}
|
||||
|
||||
static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_sspp *ctx,
|
||||
u64 creq_lut)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->cap && test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features)) {
|
||||
DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_0, creq_lut);
|
||||
DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT_1,
|
||||
creq_lut >> 32);
|
||||
} else {
|
||||
DPU_REG_WRITE(&ctx->hw, SSPP_CREQ_LUT, creq_lut);
|
||||
}
|
||||
_dpu_hw_setup_qos_lut(&ctx->hw, SSPP_DANGER_LUT,
|
||||
test_bit(DPU_SSPP_QOS_8LVL, &ctx->cap->features),
|
||||
cfg);
|
||||
}
|
||||
|
||||
static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,
|
||||
|
|
@ -604,9 +589,7 @@ static void _setup_layer_ops(struct dpu_hw_sspp *c,
|
|||
c->ops.setup_pe = dpu_hw_sspp_setup_pe_config;
|
||||
|
||||
if (test_bit(DPU_SSPP_QOS, &features)) {
|
||||
c->ops.setup_danger_safe_lut =
|
||||
dpu_hw_sspp_setup_danger_safe_lut;
|
||||
c->ops.setup_creq_lut = dpu_hw_sspp_setup_creq_lut;
|
||||
c->ops.setup_qos_lut = dpu_hw_sspp_setup_qos_lut;
|
||||
c->ops.setup_qos_ctrl = dpu_hw_sspp_setup_qos_ctrl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,25 +254,14 @@ struct dpu_hw_sspp_ops {
|
|||
void (*setup_sharpening)(struct dpu_hw_sspp *ctx,
|
||||
struct dpu_hw_sharp_cfg *cfg);
|
||||
|
||||
/**
|
||||
* setup_danger_safe_lut - setup danger safe LUTs
|
||||
* @ctx: Pointer to pipe context
|
||||
* @danger_lut: LUT for generate danger level based on fill level
|
||||
* @safe_lut: LUT for generate safe level based on fill level
|
||||
*
|
||||
*/
|
||||
void (*setup_danger_safe_lut)(struct dpu_hw_sspp *ctx,
|
||||
u32 danger_lut,
|
||||
u32 safe_lut);
|
||||
|
||||
/**
|
||||
* setup_creq_lut - setup CREQ LUT
|
||||
* setup_qos_lut - setup QoS LUTs
|
||||
* @ctx: Pointer to pipe context
|
||||
* @creq_lut: LUT for generate creq level based on fill level
|
||||
*
|
||||
* @cfg: LUT configuration
|
||||
*/
|
||||
void (*setup_creq_lut)(struct dpu_hw_sspp *ctx,
|
||||
u64 creq_lut);
|
||||
void (*setup_qos_lut)(struct dpu_hw_sspp *ctx,
|
||||
struct dpu_hw_qos_cfg *cfg);
|
||||
|
||||
/**
|
||||
* setup_qos_ctrl - setup QoS control
|
||||
|
|
|
|||
|
|
@ -73,6 +73,19 @@ static u32 dpu_hw_util_log_mask = DPU_DBG_MASK_NONE;
|
|||
#define QSEED3LITE_SEP_LUT_SIZE \
|
||||
(QSEED3LITE_LUT_SIZE * QSEED3LITE_SEPARABLE_LUTS * sizeof(u32))
|
||||
|
||||
/* QOS_LUT */
|
||||
#define QOS_DANGER_LUT 0x00
|
||||
#define QOS_SAFE_LUT 0x04
|
||||
#define QOS_CREQ_LUT 0x08
|
||||
#define QOS_QOS_CTRL 0x0C
|
||||
#define QOS_CREQ_LUT_0 0x14
|
||||
#define QOS_CREQ_LUT_1 0x18
|
||||
|
||||
/* QOS_QOS_CTRL */
|
||||
#define QOS_QOS_CTRL_DANGER_SAFE_EN BIT(0)
|
||||
#define QOS_QOS_CTRL_DANGER_VBLANK_MASK GENMASK(5, 4)
|
||||
#define QOS_QOS_CTRL_VBLANK_EN BIT(16)
|
||||
#define QOS_QOS_CTRL_CREQ_VBLANK_MASK GENMASK(21, 20)
|
||||
|
||||
void dpu_reg_write(struct dpu_hw_blk_reg_map *c,
|
||||
u32 reg_off,
|
||||
|
|
@ -450,6 +463,24 @@ u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset,
|
||||
bool qos_8lvl,
|
||||
const struct dpu_hw_qos_cfg *cfg)
|
||||
{
|
||||
DPU_REG_WRITE(c, offset + QOS_DANGER_LUT, cfg->danger_lut);
|
||||
DPU_REG_WRITE(c, offset + QOS_SAFE_LUT, cfg->safe_lut);
|
||||
|
||||
if (qos_8lvl) {
|
||||
DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_0, cfg->creq_lut);
|
||||
DPU_REG_WRITE(c, offset + QOS_CREQ_LUT_1, cfg->creq_lut >> 32);
|
||||
} else {
|
||||
DPU_REG_WRITE(c, offset + QOS_CREQ_LUT, cfg->creq_lut);
|
||||
}
|
||||
|
||||
DPU_REG_WRITE(c, offset + QOS_QOS_CTRL,
|
||||
cfg->danger_safe_en ? QOS_QOS_CTRL_DANGER_SAFE_EN : 0);
|
||||
}
|
||||
|
||||
void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
|
||||
u32 misr_ctrl_offset,
|
||||
bool enable, u32 frame_count)
|
||||
|
|
|
|||
|
|
@ -305,6 +305,23 @@ struct dpu_drm_scaler_v2 {
|
|||
struct dpu_drm_de_v1 de;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_hw_qos_cfg: pipe QoS configuration
|
||||
* @danger_lut: LUT for generate danger level based on fill level
|
||||
* @safe_lut: LUT for generate safe level based on fill level
|
||||
* @creq_lut: LUT for generate creq level based on fill level
|
||||
* @creq_vblank: creq value generated to vbif during vertical blanking
|
||||
* @danger_vblank: danger value generated during vertical blanking
|
||||
* @vblank_en: enable creq_vblank and danger_vblank during vblank
|
||||
* @danger_safe_en: enable danger safe generation
|
||||
*/
|
||||
struct dpu_hw_qos_cfg {
|
||||
u32 danger_lut;
|
||||
u32 safe_lut;
|
||||
u64 creq_lut;
|
||||
bool danger_safe_en;
|
||||
};
|
||||
|
||||
u32 *dpu_hw_util_get_log_mask_ptr(void);
|
||||
|
||||
void dpu_reg_write(struct dpu_hw_blk_reg_map *c,
|
||||
|
|
@ -336,6 +353,10 @@ void dpu_setup_cdp(struct dpu_hw_blk_reg_map *c, u32 offset,
|
|||
u64 _dpu_hw_get_qos_lut(const struct dpu_qos_lut_tbl *tbl,
|
||||
u32 total_fl);
|
||||
|
||||
void _dpu_hw_setup_qos_lut(struct dpu_hw_blk_reg_map *c, u32 offset,
|
||||
bool qos_8lvl,
|
||||
const struct dpu_hw_qos_cfg *cfg);
|
||||
|
||||
void dpu_hw_setup_misr(struct dpu_hw_blk_reg_map *c,
|
||||
u32 misr_ctrl_offset,
|
||||
bool enable,
|
||||
|
|
|
|||
|
|
@ -49,9 +49,6 @@
|
|||
#define WB_OUT_IMAGE_SIZE 0x2C0
|
||||
#define WB_OUT_XY 0x2C4
|
||||
|
||||
/* WB_QOS_CTRL */
|
||||
#define WB_QOS_CTRL_DANGER_SAFE_EN BIT(0)
|
||||
|
||||
static void dpu_hw_wb_setup_outaddress(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_cfg *data)
|
||||
{
|
||||
|
|
@ -135,32 +132,14 @@ static void dpu_hw_wb_roi(struct dpu_hw_wb *ctx, struct dpu_hw_wb_cfg *wb)
|
|||
}
|
||||
|
||||
static void dpu_hw_wb_setup_qos_lut(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_qos_cfg *cfg)
|
||||
struct dpu_hw_qos_cfg *cfg)
|
||||
{
|
||||
struct dpu_hw_blk_reg_map *c = &ctx->hw;
|
||||
u32 qos_ctrl = 0;
|
||||
|
||||
if (!ctx || !cfg)
|
||||
return;
|
||||
|
||||
DPU_REG_WRITE(c, WB_DANGER_LUT, cfg->danger_lut);
|
||||
DPU_REG_WRITE(c, WB_SAFE_LUT, cfg->safe_lut);
|
||||
|
||||
/*
|
||||
* for chipsets not using DPU_WB_QOS_8LVL but still using DPU
|
||||
* driver such as msm8998, the reset value of WB_CREQ_LUT is
|
||||
* sufficient for writeback to work. SW doesn't need to explicitly
|
||||
* program a value.
|
||||
*/
|
||||
if (ctx->caps && test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features)) {
|
||||
DPU_REG_WRITE(c, WB_CREQ_LUT_0, cfg->creq_lut);
|
||||
DPU_REG_WRITE(c, WB_CREQ_LUT_1, cfg->creq_lut >> 32);
|
||||
}
|
||||
|
||||
if (cfg->danger_safe_en)
|
||||
qos_ctrl |= WB_QOS_CTRL_DANGER_SAFE_EN;
|
||||
|
||||
DPU_REG_WRITE(c, WB_QOS_CTRL, qos_ctrl);
|
||||
_dpu_hw_setup_qos_lut(&ctx->hw, WB_DANGER_LUT,
|
||||
test_bit(DPU_WB_QOS_8LVL, &ctx->caps->features),
|
||||
cfg);
|
||||
}
|
||||
|
||||
static void dpu_hw_wb_setup_cdp(struct dpu_hw_wb *ctx,
|
||||
|
|
|
|||
|
|
@ -21,20 +21,6 @@ struct dpu_hw_wb_cfg {
|
|||
struct drm_rect crop;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dpu_hw_wb_qos_cfg : Writeback pipe QoS configuration
|
||||
* @danger_lut: LUT for generate danger level based on fill level
|
||||
* @safe_lut: LUT for generate safe level based on fill level
|
||||
* @creq_lut: LUT for generate creq level based on fill level
|
||||
* @danger_safe_en: enable danger safe generation
|
||||
*/
|
||||
struct dpu_hw_wb_qos_cfg {
|
||||
u32 danger_lut;
|
||||
u32 safe_lut;
|
||||
u64 creq_lut;
|
||||
bool danger_safe_en;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
|
||||
|
|
@ -56,7 +42,7 @@ struct dpu_hw_wb_ops {
|
|||
struct dpu_hw_wb_cfg *wb);
|
||||
|
||||
void (*setup_qos_lut)(struct dpu_hw_wb *ctx,
|
||||
struct dpu_hw_wb_qos_cfg *cfg);
|
||||
struct dpu_hw_qos_cfg *cfg);
|
||||
|
||||
void (*setup_cdp)(struct dpu_hw_wb *ctx,
|
||||
const struct dpu_format *fmt,
|
||||
|
|
|
|||
|
|
@ -190,12 +190,14 @@ static u64 _dpu_plane_calc_clk(const struct drm_display_mode *mode,
|
|||
* _dpu_plane_calc_fill_level - calculate fill level of the given source format
|
||||
* @plane: Pointer to drm plane
|
||||
* @pipe: Pointer to software pipe
|
||||
* @lut_usage: LUT usecase
|
||||
* @fmt: Pointer to source buffer format
|
||||
* @src_width: width of source buffer
|
||||
* Return: fill level corresponding to the source buffer/format or 0 if error
|
||||
*/
|
||||
static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
|
||||
struct dpu_sw_pipe *pipe,
|
||||
enum dpu_qos_lut_usage lut_usage,
|
||||
const struct dpu_format *fmt, u32 src_width)
|
||||
{
|
||||
struct dpu_plane *pdpu;
|
||||
|
|
@ -207,6 +209,9 @@ static int _dpu_plane_calc_fill_level(struct drm_plane *plane,
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (lut_usage == DPU_QOS_LUT_USAGE_NRT)
|
||||
return 0;
|
||||
|
||||
pdpu = to_dpu_plane(plane);
|
||||
fixed_buff_size = pdpu->catalog->caps->pixel_ram_size;
|
||||
|
||||
|
|
@ -252,83 +257,58 @@ static void _dpu_plane_set_qos_lut(struct drm_plane *plane,
|
|||
const struct dpu_format *fmt, struct dpu_sw_pipe_cfg *pipe_cfg)
|
||||
{
|
||||
struct dpu_plane *pdpu = to_dpu_plane(plane);
|
||||
u64 qos_lut;
|
||||
u32 total_fl = 0, lut_usage;
|
||||
struct dpu_hw_qos_cfg cfg;
|
||||
u32 total_fl, lut_usage;
|
||||
|
||||
if (!pdpu->is_rt_pipe) {
|
||||
lut_usage = DPU_QOS_LUT_USAGE_NRT;
|
||||
} else {
|
||||
total_fl = _dpu_plane_calc_fill_level(plane, pipe, fmt,
|
||||
drm_rect_width(&pipe_cfg->src_rect));
|
||||
|
||||
if (fmt && DPU_FORMAT_IS_LINEAR(fmt))
|
||||
lut_usage = DPU_QOS_LUT_USAGE_LINEAR;
|
||||
else
|
||||
lut_usage = DPU_QOS_LUT_USAGE_MACROTILE;
|
||||
}
|
||||
|
||||
qos_lut = _dpu_hw_get_qos_lut(
|
||||
&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
|
||||
total_fl = _dpu_plane_calc_fill_level(plane, pipe, lut_usage, fmt,
|
||||
drm_rect_width(&pipe_cfg->src_rect));
|
||||
|
||||
cfg.creq_lut = _dpu_hw_get_qos_lut(&pdpu->catalog->perf->qos_lut_tbl[lut_usage], total_fl);
|
||||
cfg.danger_lut = pdpu->catalog->perf->danger_lut_tbl[lut_usage];
|
||||
cfg.safe_lut = pdpu->catalog->perf->safe_lut_tbl[lut_usage];
|
||||
|
||||
if (pipe->sspp->idx != SSPP_CURSOR0 &&
|
||||
pipe->sspp->idx != SSPP_CURSOR1 &&
|
||||
pdpu->is_rt_pipe)
|
||||
cfg.danger_safe_en = true;
|
||||
|
||||
DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n",
|
||||
pdpu->pipe - SSPP_VIG0,
|
||||
cfg.danger_safe_en,
|
||||
pdpu->is_rt_pipe);
|
||||
|
||||
trace_dpu_perf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0,
|
||||
(fmt) ? fmt->base.pixel_format : 0,
|
||||
pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage);
|
||||
pdpu->is_rt_pipe, total_fl, cfg.creq_lut, lut_usage);
|
||||
|
||||
DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",
|
||||
pdpu->pipe - SSPP_VIG0,
|
||||
fmt ? (char *)&fmt->base.pixel_format : NULL,
|
||||
pdpu->is_rt_pipe, total_fl, qos_lut);
|
||||
|
||||
pipe->sspp->ops.setup_creq_lut(pipe->sspp, qos_lut);
|
||||
}
|
||||
|
||||
/**
|
||||
* _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane
|
||||
* @plane: Pointer to drm plane
|
||||
* @pipe: Pointer to software pipe
|
||||
* @fmt: Pointer to source buffer format
|
||||
*/
|
||||
static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
|
||||
struct dpu_sw_pipe *pipe,
|
||||
const struct dpu_format *fmt)
|
||||
{
|
||||
struct dpu_plane *pdpu = to_dpu_plane(plane);
|
||||
u32 danger_lut, safe_lut;
|
||||
|
||||
if (!pdpu->is_rt_pipe) {
|
||||
danger_lut = pdpu->catalog->perf->danger_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_NRT];
|
||||
safe_lut = pdpu->catalog->perf->safe_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_NRT];
|
||||
} else {
|
||||
if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
|
||||
danger_lut = pdpu->catalog->perf->danger_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_LINEAR];
|
||||
safe_lut = pdpu->catalog->perf->safe_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_LINEAR];
|
||||
} else {
|
||||
danger_lut = pdpu->catalog->perf->danger_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_MACROTILE];
|
||||
safe_lut = pdpu->catalog->perf->safe_lut_tbl
|
||||
[DPU_QOS_LUT_USAGE_MACROTILE];
|
||||
}
|
||||
}
|
||||
pdpu->is_rt_pipe, total_fl, cfg.creq_lut);
|
||||
|
||||
trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0,
|
||||
(fmt) ? fmt->base.pixel_format : 0,
|
||||
(fmt) ? fmt->fetch_mode : 0,
|
||||
danger_lut,
|
||||
safe_lut);
|
||||
cfg.danger_lut,
|
||||
cfg.safe_lut);
|
||||
|
||||
DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",
|
||||
pdpu->pipe - SSPP_VIG0,
|
||||
fmt ? (char *)&fmt->base.pixel_format : NULL,
|
||||
fmt ? fmt->fetch_mode : -1,
|
||||
danger_lut,
|
||||
safe_lut);
|
||||
cfg.danger_lut,
|
||||
cfg.safe_lut);
|
||||
|
||||
pipe->sspp->ops.setup_danger_safe_lut(pipe->sspp,
|
||||
danger_lut, safe_lut);
|
||||
pipe->sspp->ops.setup_qos_lut(pipe->sspp, &cfg);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -336,7 +316,6 @@ static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
|
|||
* @plane: Pointer to drm plane
|
||||
* @pipe: Pointer to software pipe
|
||||
* @enable: true to enable QoS control
|
||||
* @flags: QoS control mode (enum dpu_plane_qos)
|
||||
*/
|
||||
static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
|
||||
struct dpu_sw_pipe *pipe,
|
||||
|
|
@ -1086,10 +1065,6 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);
|
||||
_dpu_plane_set_danger_lut(plane, pipe, fmt);
|
||||
_dpu_plane_set_qos_ctrl(plane, pipe,
|
||||
pipe->sspp->idx != SSPP_CURSOR0 &&
|
||||
pipe->sspp->idx != SSPP_CURSOR1);
|
||||
|
||||
if (pipe->sspp->idx != SSPP_CURSOR0 &&
|
||||
pipe->sspp->idx != SSPP_CURSOR1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user