mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-01-10 02:16:50 -05:00
Merge tag 'drm-msm-fixes-2024-10-16' of https://gitlab.freedesktop.org/drm/msm into drm-fixes
Fixes for v6.12 Display: - move CRTC resource assignment to atomic_check otherwise to make consecutive calls to atomic_check() consistent - fix rounding / sign-extension issues with pclk calculation in case of DSC - cleanups to drop incorrect null checks in dpu snapshots - fix to use kvzalloc in dpu snapshot to avoid allocation issues in heavily loaded system cases - Fix to not program merge_3d block if dual LM is not being used - Fix to not flush merge_3d block if its not enabled otherwise this leads to false timeouts GPU: - a7xx: add a fence wait before SMMU table update Signed-off-by: Dave Airlie <airlied@redhat.com> From: Rob Clark <robdclark@gmail.com> Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGsp3Zbd_H3FhHdRz9yCYA4wxX4SenpYRSk=Mx2d8GMSuQ@mail.gmail.com
This commit is contained in:
@@ -101,9 +101,10 @@ static void get_stats_counter(struct msm_ringbuffer *ring, u32 counter,
|
||||
}
|
||||
|
||||
static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
struct msm_ringbuffer *ring, struct msm_file_private *ctx)
|
||||
struct msm_ringbuffer *ring, struct msm_gem_submit *submit)
|
||||
{
|
||||
bool sysprof = refcount_read(&a6xx_gpu->base.base.sysprof_active) > 1;
|
||||
struct msm_file_private *ctx = submit->queue->ctx;
|
||||
struct adreno_gpu *adreno_gpu = &a6xx_gpu->base;
|
||||
phys_addr_t ttbr;
|
||||
u32 asid;
|
||||
@@ -115,6 +116,15 @@ static void a6xx_set_pagetable(struct a6xx_gpu *a6xx_gpu,
|
||||
if (msm_iommu_pagetable_params(ctx->aspace->mmu, &ttbr, &asid))
|
||||
return;
|
||||
|
||||
if (adreno_gpu->info->family >= ADRENO_7XX_GEN1) {
|
||||
/* Wait for previous submit to complete before continuing: */
|
||||
OUT_PKT7(ring, CP_WAIT_TIMESTAMP, 4);
|
||||
OUT_RING(ring, 0);
|
||||
OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence)));
|
||||
OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence)));
|
||||
OUT_RING(ring, submit->seqno - 1);
|
||||
}
|
||||
|
||||
if (!sysprof) {
|
||||
if (!adreno_is_a7xx(adreno_gpu)) {
|
||||
/* Turn off protected mode to write to special registers */
|
||||
@@ -193,7 +203,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
struct msm_ringbuffer *ring = submit->ring;
|
||||
unsigned int i, ibs = 0;
|
||||
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx);
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit);
|
||||
|
||||
get_stats_counter(ring, REG_A6XX_RBBM_PERFCTR_CP(0),
|
||||
rbmemptr_stats(ring, index, cpcycles_start));
|
||||
@@ -283,7 +293,7 @@ static void a7xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
|
||||
OUT_PKT7(ring, CP_THREAD_CONTROL, 1);
|
||||
OUT_RING(ring, CP_THREAD_CONTROL_0_SYNC_THREADS | CP_SET_THREAD_BR);
|
||||
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit->queue->ctx);
|
||||
a6xx_set_pagetable(a6xx_gpu, ring, submit);
|
||||
|
||||
get_stats_counter(ring, REG_A7XX_RBBM_PERFCTR_CP(0),
|
||||
rbmemptr_stats(ring, index, cpcycles_start));
|
||||
|
||||
@@ -711,12 +711,13 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc)
|
||||
_dpu_crtc_complete_flip(crtc);
|
||||
}
|
||||
|
||||
static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
|
||||
static int _dpu_crtc_check_and_setup_lm_bounds(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state)
|
||||
{
|
||||
struct dpu_crtc_state *cstate = to_dpu_crtc_state(state);
|
||||
struct drm_display_mode *adj_mode = &state->adjusted_mode;
|
||||
u32 crtc_split_width = adj_mode->hdisplay / cstate->num_mixers;
|
||||
struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cstate->num_mixers; i++) {
|
||||
@@ -727,7 +728,12 @@ static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
|
||||
r->y2 = adj_mode->vdisplay;
|
||||
|
||||
trace_dpu_crtc_setup_lm_bounds(DRMID(crtc), i, r);
|
||||
|
||||
if (drm_rect_width(r) > dpu_kms->catalog->caps->max_mixer_width)
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _dpu_crtc_get_pcc_coeff(struct drm_crtc_state *state,
|
||||
@@ -803,7 +809,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
|
||||
|
||||
DRM_DEBUG_ATOMIC("crtc%d\n", crtc->base.id);
|
||||
|
||||
_dpu_crtc_setup_lm_bounds(crtc, crtc->state);
|
||||
_dpu_crtc_check_and_setup_lm_bounds(crtc, crtc->state);
|
||||
|
||||
/* encoder will trigger pending mask now */
|
||||
drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
|
||||
@@ -1091,9 +1097,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
|
||||
|
||||
dpu_core_perf_crtc_update(crtc, 0);
|
||||
|
||||
memset(cstate->mixers, 0, sizeof(cstate->mixers));
|
||||
cstate->num_mixers = 0;
|
||||
|
||||
/* disable clk & bw control until clk & bw properties are set */
|
||||
cstate->bw_control = false;
|
||||
cstate->bw_split_vote = false;
|
||||
@@ -1192,8 +1195,11 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
|
||||
if (crtc_state->active_changed)
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
if (cstate->num_mixers)
|
||||
_dpu_crtc_setup_lm_bounds(crtc, crtc_state);
|
||||
if (cstate->num_mixers) {
|
||||
rc = _dpu_crtc_check_and_setup_lm_bounds(crtc, crtc_state);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* FIXME: move this to dpu_plane_atomic_check? */
|
||||
drm_atomic_crtc_state_for_each_plane_state(plane, pstate, crtc_state) {
|
||||
|
||||
@@ -624,6 +624,40 @@ static struct msm_display_topology dpu_encoder_get_topology(
|
||||
return topology;
|
||||
}
|
||||
|
||||
static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
|
||||
struct drm_encoder *drm_enc,
|
||||
struct dpu_global_state *global_state,
|
||||
struct drm_crtc_state *crtc_state)
|
||||
{
|
||||
struct dpu_crtc_state *cstate;
|
||||
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC];
|
||||
int num_lm, num_ctl, num_dspp, i;
|
||||
|
||||
cstate = to_dpu_crtc_state(crtc_state);
|
||||
|
||||
memset(cstate->mixers, 0, sizeof(cstate->mixers));
|
||||
|
||||
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
|
||||
num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
|
||||
num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
|
||||
ARRAY_SIZE(hw_dspp));
|
||||
|
||||
for (i = 0; i < num_lm; i++) {
|
||||
int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
|
||||
|
||||
cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
|
||||
cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
|
||||
cstate->mixers[i].hw_dspp = i < num_dspp ? to_dpu_hw_dspp(hw_dspp[i]) : NULL;
|
||||
}
|
||||
|
||||
cstate->num_mixers = num_lm;
|
||||
}
|
||||
|
||||
static int dpu_encoder_virt_atomic_check(
|
||||
struct drm_encoder *drm_enc,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
@@ -692,6 +726,9 @@ static int dpu_encoder_virt_atomic_check(
|
||||
if (!crtc_state->active_changed || crtc_state->enable)
|
||||
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
|
||||
drm_enc, crtc_state, topology);
|
||||
if (!ret)
|
||||
dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
|
||||
global_state, crtc_state);
|
||||
}
|
||||
|
||||
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
|
||||
@@ -1093,14 +1130,11 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
||||
struct dpu_encoder_virt *dpu_enc;
|
||||
struct msm_drm_private *priv;
|
||||
struct dpu_kms *dpu_kms;
|
||||
struct dpu_crtc_state *cstate;
|
||||
struct dpu_global_state *global_state;
|
||||
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_lm[MAX_CHANNELS_PER_ENC];
|
||||
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
|
||||
struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
|
||||
int num_lm, num_ctl, num_pp, num_dsc;
|
||||
int num_ctl, num_pp, num_dsc;
|
||||
unsigned int dsc_mask = 0;
|
||||
int i;
|
||||
|
||||
@@ -1129,11 +1163,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
||||
ARRAY_SIZE(hw_pp));
|
||||
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
|
||||
num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
|
||||
dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
|
||||
drm_enc->base.id, DPU_HW_BLK_DSPP, hw_dspp,
|
||||
ARRAY_SIZE(hw_dspp));
|
||||
|
||||
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
|
||||
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
|
||||
@@ -1159,36 +1188,23 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
|
||||
dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
|
||||
}
|
||||
|
||||
cstate = to_dpu_crtc_state(crtc_state);
|
||||
|
||||
for (i = 0; i < num_lm; i++) {
|
||||
int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
|
||||
|
||||
cstate->mixers[i].hw_lm = to_dpu_hw_mixer(hw_lm[i]);
|
||||
cstate->mixers[i].lm_ctl = to_dpu_hw_ctl(hw_ctl[ctl_idx]);
|
||||
cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
|
||||
}
|
||||
|
||||
cstate->num_mixers = num_lm;
|
||||
|
||||
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
|
||||
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
|
||||
|
||||
if (!dpu_enc->hw_pp[i]) {
|
||||
phys->hw_pp = dpu_enc->hw_pp[i];
|
||||
if (!phys->hw_pp) {
|
||||
DPU_ERROR_ENC(dpu_enc,
|
||||
"no pp block assigned at idx: %d\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hw_ctl[i]) {
|
||||
phys->hw_ctl = i < num_ctl ? to_dpu_hw_ctl(hw_ctl[i]) : NULL;
|
||||
if (!phys->hw_ctl) {
|
||||
DPU_ERROR_ENC(dpu_enc,
|
||||
"no ctl block assigned at idx: %d\n", i);
|
||||
return;
|
||||
}
|
||||
|
||||
phys->hw_pp = dpu_enc->hw_pp[i];
|
||||
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
|
||||
|
||||
phys->cached_mode = crtc_state->adjusted_mode;
|
||||
if (phys->ops.atomic_mode_set)
|
||||
phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
|
||||
|
||||
@@ -302,7 +302,7 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
|
||||
intf_cfg.stream_sel = 0; /* Don't care value for video mode */
|
||||
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
|
||||
intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
|
||||
if (phys_enc->hw_pp->merge_3d)
|
||||
if (intf_cfg.mode_3d && phys_enc->hw_pp->merge_3d)
|
||||
intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->idx;
|
||||
|
||||
spin_lock_irqsave(phys_enc->enc_spinlock, lock_flags);
|
||||
@@ -440,10 +440,12 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
|
||||
struct dpu_hw_ctl *ctl;
|
||||
const struct msm_format *fmt;
|
||||
u32 fmt_fourcc;
|
||||
u32 mode_3d;
|
||||
|
||||
ctl = phys_enc->hw_ctl;
|
||||
fmt_fourcc = dpu_encoder_get_drm_fmt(phys_enc);
|
||||
fmt = mdp_get_format(&phys_enc->dpu_kms->base, fmt_fourcc, 0);
|
||||
mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
|
||||
|
||||
DPU_DEBUG_VIDENC(phys_enc, "\n");
|
||||
|
||||
@@ -466,7 +468,8 @@ static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
|
||||
goto skip_flush;
|
||||
|
||||
ctl->ops.update_pending_flush_intf(ctl, phys_enc->hw_intf->idx);
|
||||
if (ctl->ops.update_pending_flush_merge_3d && phys_enc->hw_pp->merge_3d)
|
||||
if (mode_3d && ctl->ops.update_pending_flush_merge_3d &&
|
||||
phys_enc->hw_pp->merge_3d)
|
||||
ctl->ops.update_pending_flush_merge_3d(ctl, phys_enc->hw_pp->merge_3d->idx);
|
||||
|
||||
if (ctl->ops.update_pending_flush_cdm && phys_enc->hw_cdm)
|
||||
|
||||
@@ -275,6 +275,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
|
||||
struct dpu_hw_pingpong *hw_pp;
|
||||
struct dpu_hw_cdm *hw_cdm;
|
||||
u32 pending_flush = 0;
|
||||
u32 mode_3d;
|
||||
|
||||
if (!phys_enc)
|
||||
return;
|
||||
@@ -283,6 +284,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
|
||||
hw_pp = phys_enc->hw_pp;
|
||||
hw_ctl = phys_enc->hw_ctl;
|
||||
hw_cdm = phys_enc->hw_cdm;
|
||||
mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
|
||||
|
||||
DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);
|
||||
|
||||
@@ -294,7 +296,8 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
|
||||
if (hw_ctl->ops.update_pending_flush_wb)
|
||||
hw_ctl->ops.update_pending_flush_wb(hw_ctl, hw_wb->idx);
|
||||
|
||||
if (hw_ctl->ops.update_pending_flush_merge_3d && hw_pp && hw_pp->merge_3d)
|
||||
if (mode_3d && hw_ctl->ops.update_pending_flush_merge_3d &&
|
||||
hw_pp && hw_pp->merge_3d)
|
||||
hw_ctl->ops.update_pending_flush_merge_3d(hw_ctl,
|
||||
hw_pp->merge_3d->idx);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
|
||||
end_addr = base_addr + aligned_len;
|
||||
|
||||
if (!(*reg))
|
||||
*reg = kzalloc(len_padded, GFP_KERNEL);
|
||||
*reg = kvzalloc(len_padded, GFP_KERNEL);
|
||||
|
||||
if (*reg)
|
||||
dump_addr = *reg;
|
||||
@@ -48,20 +48,21 @@ static void msm_disp_state_dump_regs(u32 **reg, u32 aligned_len, void __iomem *b
|
||||
}
|
||||
}
|
||||
|
||||
static void msm_disp_state_print_regs(u32 **reg, u32 len, void __iomem *base_addr,
|
||||
struct drm_printer *p)
|
||||
static void msm_disp_state_print_regs(const u32 *dump_addr, u32 len,
|
||||
void __iomem *base_addr, struct drm_printer *p)
|
||||
{
|
||||
int i;
|
||||
u32 *dump_addr = NULL;
|
||||
void __iomem *addr;
|
||||
u32 num_rows;
|
||||
|
||||
if (!dump_addr) {
|
||||
drm_printf(p, "Registers not stored\n");
|
||||
return;
|
||||
}
|
||||
|
||||
addr = base_addr;
|
||||
num_rows = len / REG_DUMP_ALIGN;
|
||||
|
||||
if (*reg)
|
||||
dump_addr = *reg;
|
||||
|
||||
for (i = 0; i < num_rows; i++) {
|
||||
drm_printf(p, "0x%lx : %08x %08x %08x %08x\n",
|
||||
(unsigned long)(addr - base_addr),
|
||||
@@ -89,7 +90,7 @@ void msm_disp_state_print(struct msm_disp_state *state, struct drm_printer *p)
|
||||
|
||||
list_for_each_entry_safe(block, tmp, &state->blocks, node) {
|
||||
drm_printf(p, "====================%s================\n", block->name);
|
||||
msm_disp_state_print_regs(&block->state, block->size, block->base_addr, p);
|
||||
msm_disp_state_print_regs(block->state, block->size, block->base_addr, p);
|
||||
}
|
||||
|
||||
drm_printf(p, "===================dpu drm state================\n");
|
||||
@@ -161,7 +162,7 @@ void msm_disp_state_free(void *data)
|
||||
|
||||
list_for_each_entry_safe(block, tmp, &disp_state->blocks, node) {
|
||||
list_del(&block->node);
|
||||
kfree(block->state);
|
||||
kvfree(block->state);
|
||||
kfree(block);
|
||||
}
|
||||
|
||||
|
||||
@@ -542,7 +542,7 @@ static unsigned long dsi_adjust_pclk_for_compression(const struct drm_display_mo
|
||||
|
||||
int new_htotal = mode->htotal - mode->hdisplay + new_hdisplay;
|
||||
|
||||
return new_htotal * mode->vtotal * drm_mode_vrefresh(mode);
|
||||
return mult_frac(mode->clock * 1000u, new_htotal, mode->htotal);
|
||||
}
|
||||
|
||||
static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode,
|
||||
@@ -550,7 +550,7 @@ static unsigned long dsi_get_pclk_rate(const struct drm_display_mode *mode,
|
||||
{
|
||||
unsigned long pclk_rate;
|
||||
|
||||
pclk_rate = mode->clock * 1000;
|
||||
pclk_rate = mode->clock * 1000u;
|
||||
|
||||
if (dsc)
|
||||
pclk_rate = dsi_adjust_pclk_for_compression(mode, dsc);
|
||||
|
||||
@@ -153,15 +153,6 @@ static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk)
|
||||
return dividend - 1;
|
||||
}
|
||||
|
||||
static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk)
|
||||
{
|
||||
u64 fdata = ((u64)pll_cmp) * ref_clk * 10;
|
||||
|
||||
do_div(fdata, HDMI_PLL_CMP_CNT);
|
||||
|
||||
return fdata;
|
||||
}
|
||||
|
||||
#define HDMI_REF_CLOCK_HZ ((u64)19200000)
|
||||
#define HDMI_MHZ_TO_HZ ((u64)1000000)
|
||||
static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk)
|
||||
|
||||
Reference in New Issue
Block a user