Skip to content

Commit

Permalink
Merge tag 'drm-msm-fixes-2024-10-16' of https://gitlab.freedesktop.or…
Browse files Browse the repository at this point in the history
…g/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 <[email protected]>
From: Rob Clark <[email protected]>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGsp3Zbd_H3FhHdRz9yCYA4wxX4SenpYRSk=Mx2d8GMSuQ@mail.gmail.com
  • Loading branch information
airlied committed Oct 17, 2024
2 parents 8e929cb + 77ad507 commit 4cd33d9
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 59 deletions.
16 changes: 13 additions & 3 deletions drivers/gpu/drm/msm/adreno/a6xx_gpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 */
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down
20 changes: 13 additions & 7 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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,
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
68 changes: 42 additions & 26 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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])
Expand All @@ -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);
Expand Down
7 changes: 5 additions & 2 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");

Expand All @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);

Expand All @@ -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);

Expand Down
19 changes: 10 additions & 9 deletions drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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),
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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);
}

Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/msm/dsi/dsi_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -542,15 +542,15 @@ 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,
const struct drm_dsc_config *dsc, bool is_bonded_dsi)
{
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);
Expand Down
9 changes: 0 additions & 9 deletions drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 4cd33d9

Please sign in to comment.