mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 18:13:41 +02:00
drm/msm/dpu: Reserve resources for CWB
Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes For concurrent writeback, even-indexed CWB muxes must be assigned to even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same even/odd rule applies for dedicated CWB PINGPONGs. Track the CWB muxes in the global state and add a CWB-specific helper to reserve the correct CWB muxes and dedicated PINGPONGs following the even/odd rule. Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> Patchwork: https://patchwork.freedesktop.org/patch/637495/ Link: https://lore.kernel.org/r/20250214-concurrent-wb-v6-7-a44c293cf422@quicinc.com Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
This commit is contained in:
parent
f1f0379e9d
commit
5008375443
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
* Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*
|
||||
* Author: Rob Clark <robdclark@gmail.com>
|
||||
*/
|
||||
|
|
@ -28,6 +28,7 @@
|
|||
#include "dpu_hw_dsc.h"
|
||||
#include "dpu_hw_merge3d.h"
|
||||
#include "dpu_hw_cdm.h"
|
||||
#include "dpu_hw_cwb.h"
|
||||
#include "dpu_formats.h"
|
||||
#include "dpu_encoder_phys.h"
|
||||
#include "dpu_crtc.h"
|
||||
|
|
@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
|
|||
* @cur_slave: As above but for the slave encoder.
|
||||
* @hw_pp: Handle to the pingpong blocks used for the display. No.
|
||||
* pingpong blocks can be different than num_phys_encs.
|
||||
* @hw_cwb: Handle to the CWB muxes used for concurrent writeback
|
||||
* display. Number of CWB muxes can be different than
|
||||
* num_phys_encs.
|
||||
* @hw_dsc: Handle to the DSC blocks used for the display.
|
||||
* @dsc_mask: Bitmask of used DSC blocks.
|
||||
* @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
|
||||
|
|
@ -177,6 +181,7 @@ struct dpu_encoder_virt {
|
|||
struct dpu_encoder_phys *cur_master;
|
||||
struct dpu_encoder_phys *cur_slave;
|
||||
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
|
||||
|
||||
unsigned int dsc_mask;
|
||||
|
|
@ -1149,7 +1154,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
|||
struct dpu_hw_blk *hw_pp[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
|
||||
int num_ctl, num_pp, num_dsc;
|
||||
int num_cwb = 0;
|
||||
bool is_cwb_encoder;
|
||||
unsigned int dsc_mask = 0;
|
||||
int i;
|
||||
|
||||
|
|
@ -1163,6 +1171,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
|||
|
||||
priv = drm_enc->dev->dev_private;
|
||||
dpu_kms = to_dpu_kms(priv->kms);
|
||||
is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
|
||||
dpu_enc->disp_info.intf_type == INTF_WB;
|
||||
|
||||
global_state = dpu_kms_get_existing_global_state(dpu_kms);
|
||||
if (IS_ERR_OR_NULL(global_state)) {
|
||||
|
|
@ -1173,9 +1183,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
|||
trace_dpu_enc_mode_set(DRMID(drm_enc));
|
||||
|
||||
/* Query resource that have been reserved in atomic check step. */
|
||||
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
|
||||
ARRAY_SIZE(hw_pp));
|
||||
if (is_cwb_encoder) {
|
||||
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->crtc,
|
||||
DPU_HW_BLK_DCWB_PINGPONG,
|
||||
hw_pp, ARRAY_SIZE(hw_pp));
|
||||
num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->crtc,
|
||||
DPU_HW_BLK_CWB,
|
||||
hw_cwb, ARRAY_SIZE(hw_cwb));
|
||||
} else {
|
||||
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->crtc,
|
||||
DPU_HW_BLK_PINGPONG, hw_pp,
|
||||
ARRAY_SIZE(hw_pp));
|
||||
}
|
||||
|
||||
for (i = 0; i < num_cwb; i++)
|
||||
dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
|
||||
|
||||
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
|
||||
|
||||
|
|
|
|||
|
|
@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
|
|||
DPU_HW_BLK_LM,
|
||||
DPU_HW_BLK_CTL,
|
||||
DPU_HW_BLK_PINGPONG,
|
||||
DPU_HW_BLK_DCWB_PINGPONG,
|
||||
DPU_HW_BLK_INTF,
|
||||
DPU_HW_BLK_WB,
|
||||
DPU_HW_BLK_DSPP,
|
||||
DPU_HW_BLK_MERGE_3D,
|
||||
DPU_HW_BLK_DSC,
|
||||
DPU_HW_BLK_CDM,
|
||||
DPU_HW_BLK_CWB,
|
||||
DPU_HW_BLK_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -132,6 +132,7 @@ struct dpu_global_state {
|
|||
uint32_t cdm_to_crtc_id;
|
||||
|
||||
uint32_t sspp_to_crtc_id[SSPP_MAX - SSPP_NONE];
|
||||
uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
|
||||
};
|
||||
|
||||
struct dpu_global_state
|
||||
|
|
|
|||
|
|
@ -233,6 +233,59 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
|
||||
struct dpu_global_state *global_state,
|
||||
uint32_t crtc_id,
|
||||
struct msm_display_topology *topology)
|
||||
{
|
||||
int num_cwb_mux = topology->num_lm, cwb_mux_count = 0;
|
||||
int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
|
||||
int cwb_pp_idx[MAX_BLOCKS];
|
||||
int cwb_mux_idx[MAX_BLOCKS];
|
||||
|
||||
/*
|
||||
* Reserve additional dedicated CWB PINGPONG blocks and muxes for each
|
||||
* mixer
|
||||
*
|
||||
* TODO: add support reserving resources for platforms with no
|
||||
* PINGPONG_CWB
|
||||
*/
|
||||
for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
|
||||
cwb_mux_count < num_cwb_mux; i++) {
|
||||
for (int j = 0; j < ARRAY_SIZE(rm->cwb_blks); j++) {
|
||||
/*
|
||||
* Odd LMs must be assigned to odd CWB muxes and even
|
||||
* LMs with even CWB muxes.
|
||||
*
|
||||
* Since the RM HW block array index is based on the HW
|
||||
* block ids, we can also use the array index to enforce
|
||||
* the odd/even rule. See dpu_rm_init() for more
|
||||
* information
|
||||
*/
|
||||
if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) ||
|
||||
i % 2 != j % 2)
|
||||
continue;
|
||||
|
||||
cwb_mux_idx[cwb_mux_count] = j;
|
||||
cwb_pp_idx[cwb_mux_count] = j + cwb_pp_start_idx;
|
||||
cwb_mux_count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cwb_mux_count != num_cwb_mux) {
|
||||
DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
|
||||
return -ENAVAIL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cwb_mux_count; i++) {
|
||||
global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
|
||||
global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
|
||||
* proposed use case requirements, incl. hardwired dependent blocks like
|
||||
|
|
@ -623,6 +676,12 @@ static int _dpu_rm_make_reservation(
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (topology->cwb_enabled) {
|
||||
ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
|
||||
crtc_id, topology);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
|
||||
topology);
|
||||
|
|
@ -680,6 +739,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
|
|||
_dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
|
||||
ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
|
||||
_dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
|
||||
_dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
|
||||
ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -824,6 +885,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
|
|||
|
||||
switch (type) {
|
||||
case DPU_HW_BLK_PINGPONG:
|
||||
case DPU_HW_BLK_DCWB_PINGPONG:
|
||||
hw_blks = rm->pingpong_blks;
|
||||
hw_to_crtc_id = global_state->pingpong_to_crtc_id;
|
||||
max_blks = ARRAY_SIZE(rm->pingpong_blks);
|
||||
|
|
@ -853,6 +915,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
|
|||
hw_to_crtc_id = &global_state->cdm_to_crtc_id;
|
||||
max_blks = 1;
|
||||
break;
|
||||
case DPU_HW_BLK_CWB:
|
||||
hw_blks = rm->cwb_blks;
|
||||
hw_to_crtc_id = global_state->cwb_to_crtc_id;
|
||||
max_blks = ARRAY_SIZE(rm->cwb_blks);
|
||||
break;
|
||||
default:
|
||||
DPU_ERROR("blk type %d not managed by rm\n", type);
|
||||
return 0;
|
||||
|
|
@ -863,6 +930,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
|
|||
if (hw_to_crtc_id[i] != crtc_id)
|
||||
continue;
|
||||
|
||||
if (type == DPU_HW_BLK_PINGPONG) {
|
||||
struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
|
||||
|
||||
if (pp->idx >= PINGPONG_CWB_0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (type == DPU_HW_BLK_DCWB_PINGPONG) {
|
||||
struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
|
||||
|
||||
if (pp->idx < PINGPONG_CWB_0)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (num_blks == blks_size) {
|
||||
DPU_ERROR("More than %d resources assigned to crtc %d\n",
|
||||
blks_size, crtc_id);
|
||||
|
|
@ -945,4 +1026,10 @@ void dpu_rm_print_state(struct drm_printer *p,
|
|||
dpu_rm_print_state_helper(p, rm->hw_sspp[i] ? &rm->hw_sspp[i]->base : NULL,
|
||||
global_state->sspp_to_crtc_id[i]);
|
||||
drm_puts(p, "\n");
|
||||
|
||||
drm_puts(p, "\tcwb=");
|
||||
for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
|
||||
dpu_rm_print_state_helper(p, rm->cwb_blks[i],
|
||||
global_state->cwb_to_crtc_id[i]);
|
||||
drm_puts(p, "\n");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user