Commit 4cd33d97 authored by Dave Airlie's avatar Dave Airlie
Browse files

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: default avatarDave Airlie <airlied@redhat.com>
From: Rob Clark <robdclark@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/CAF6AEGsp3Zbd_H3FhHdRz9yCYA4wxX4SenpYRSk=Mx2d8GMSuQ@mail.gmail.com
parents 8e929cb5 77ad507d
Loading
Loading
Loading
Loading
+13 −3
Original line number Diff line number Diff line
@@ -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));
+13 −7
Original line number Diff line number Diff line
@@ -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) {
+42 −26
Original line number Diff line number Diff line
@@ -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);
+5 −2
Original line number Diff line number Diff line
@@ -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)
+4 −1
Original line number Diff line number Diff line
@@ -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);

Loading