Commit fb4c972b authored by Jun Nie's avatar Jun Nie Committed by Dmitry Baryshkov
Browse files

drm/msm/dpu: handle pipes as array



There are 2 pipes in a drm plane at most currently, while 4 pipes are
required for quad-pipe case. Generalize the handling to pipe pair and
ease handling to another pipe pair later. Store pipes in array with
removing dedicated r_pipe.

Signed-off-by: default avatarJun Nie <jun.nie@linaro.org>
Reviewed-by: default avatarDmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: default avatarJessica Zhang <quic_jesszhan@quicinc.com>
Patchwork: https://patchwork.freedesktop.org/patch/675406/
Link: https://lore.kernel.org/r/20250918-v6-16-rc2-quad-pipe-upstream-4-v16-4-ff6232e3472f@linaro.org


Signed-off-by: default avatarDmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
parent 2c94547e
Loading
Loading
Loading
Loading
+17 −22
Original line number Diff line number Diff line
@@ -449,7 +449,7 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
	struct dpu_plane_state *pstate = NULL;
	const struct msm_format *format;
	struct dpu_hw_ctl *ctl = mixer->lm_ctl;
	u32 lm_idx;
	u32 lm_idx, i;
	bool bg_alpha_enable = false;
	DECLARE_BITMAP(active_fetch, SSPP_MAX);
	DECLARE_BITMAP(active_pipes, SSPP_MAX);
@@ -472,22 +472,17 @@ static void _dpu_crtc_blend_setup_mixer(struct drm_crtc *crtc,
		if (pstate->stage == DPU_STAGE_BASE && format->alpha_enable)
			bg_alpha_enable = true;

		set_bit(pstate->pipe.sspp->idx, active_fetch);
		set_bit(pstate->pipe.sspp->idx, active_pipes);
		_dpu_crtc_blend_setup_pipe(crtc, plane,
					   mixer, cstate->num_mixers,
					   pstate->stage,
					   format, fb ? fb->modifier : 0,
					   &pstate->pipe, 0, stage_cfg);

		if (pstate->r_pipe.sspp) {
			set_bit(pstate->r_pipe.sspp->idx, active_fetch);
			set_bit(pstate->r_pipe.sspp->idx, active_pipes);
		for (i = 0; i < PIPES_PER_STAGE; i++) {
			if (!pstate->pipe[i].sspp)
				continue;
			set_bit(pstate->pipe[i].sspp->idx, active_fetch);
			set_bit(pstate->pipe[i].sspp->idx, active_pipes);
			_dpu_crtc_blend_setup_pipe(crtc, plane,
						   mixer, cstate->num_mixers,
						   pstate->stage,
						   format, fb ? fb->modifier : 0,
						   &pstate->r_pipe, 1, stage_cfg);
						   &pstate->pipe[i], i, stage_cfg);
		}

		/* blend config update */
@@ -1682,15 +1677,15 @@ static int _dpu_debugfs_status_show(struct seq_file *s, void *data)
		seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
			state->crtc_x, state->crtc_y, state->crtc_w,
			state->crtc_h);
		seq_printf(s, "\tsspp[0]:%s\n",
			   pstate->pipe.sspp->cap->name);
		seq_printf(s, "\tmultirect[0]: mode: %d index: %d\n",
			pstate->pipe.multirect_mode, pstate->pipe.multirect_index);
		if (pstate->r_pipe.sspp) {
			seq_printf(s, "\tsspp[1]:%s\n",
				   pstate->r_pipe.sspp->cap->name);
			seq_printf(s, "\tmultirect[1]: mode: %d index: %d\n",
				   pstate->r_pipe.multirect_mode, pstate->r_pipe.multirect_index);

		for (i = 0; i < PIPES_PER_STAGE; i++) {
			if (!pstate->pipe[i].sspp)
				continue;
			seq_printf(s, "\tsspp[%d]:%s\n",
				   i, pstate->pipe[i].sspp->cap->name);
			seq_printf(s, "\tmultirect[%d]: mode: %d index: %d\n",
				   i, pstate->pipe[i].multirect_mode,
				   pstate->pipe[i].multirect_index);
		}

		seq_puts(s, "\n");
+97 −81
Original line number Diff line number Diff line
@@ -622,6 +622,7 @@ static void _dpu_plane_color_fill(struct dpu_plane *pdpu,
	struct msm_drm_private *priv = plane->dev->dev_private;
	struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
	u32 fill_color = (color & 0xFFFFFF) | ((alpha & 0xFF) << 24);
	int i;

	DPU_DEBUG_PLANE(pdpu, "\n");

@@ -635,13 +636,14 @@ static void _dpu_plane_color_fill(struct dpu_plane *pdpu,
		return;

	/* update sspp */
	_dpu_plane_color_fill_pipe(pstate, &pstate->pipe, &pstate->pipe_cfg.dst_rect,
				   fill_color, fmt);

	if (pstate->r_pipe.sspp)
		_dpu_plane_color_fill_pipe(pstate, &pstate->r_pipe, &pstate->r_pipe_cfg.dst_rect,
	for (i = 0; i < PIPES_PER_STAGE; i++) {
		if (!pstate->pipe[i].sspp)
			continue;
		_dpu_plane_color_fill_pipe(pstate, &pstate->pipe[i],
					   &pstate->pipe_cfg[i].dst_rect,
					   fill_color, fmt);
	}
}

static int dpu_plane_prepare_fb(struct drm_plane *plane,
		struct drm_plane_state *new_state)
@@ -822,8 +824,8 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
	struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base);
	u64 max_mdp_clk_rate = kms->perf.max_core_clk_rate;
	struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
	struct dpu_sw_pipe_cfg *pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg;
	struct drm_rect fb_rect = { 0 };
	uint32_t max_linewidth;

@@ -848,6 +850,9 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane,
		return -EINVAL;
	}

	/* move the assignment here, to ease handling to another pairs later */
	pipe_cfg = &pstate->pipe_cfg[0];
	r_pipe_cfg = &pstate->pipe_cfg[1];
	/* state->src is 16.16, src_rect is not */
	drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src);

@@ -963,10 +968,10 @@ static int dpu_plane_atomic_check_sspp(struct drm_plane *plane,
		drm_atomic_get_new_plane_state(state, plane);
	struct dpu_plane *pdpu = to_dpu_plane(plane);
	struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
	struct dpu_sw_pipe *pipe = &pstate->pipe;
	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
	struct dpu_sw_pipe *pipe = &pstate->pipe[0];
	struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
	int ret = 0;

	ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg,
@@ -1021,15 +1026,15 @@ static int dpu_plane_try_multirect_shared(struct dpu_plane_state *pstate,
					  const struct msm_format *fmt,
					  uint32_t max_linewidth)
{
	struct dpu_sw_pipe *pipe = &pstate->pipe;
	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	struct dpu_sw_pipe *prev_pipe = &prev_adjacent_pstate->pipe;
	struct dpu_sw_pipe_cfg *prev_pipe_cfg = &prev_adjacent_pstate->pipe_cfg;
	struct dpu_sw_pipe *pipe = &pstate->pipe[0];
	struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
	struct dpu_sw_pipe *prev_pipe = &prev_adjacent_pstate->pipe[0];
	struct dpu_sw_pipe_cfg *prev_pipe_cfg = &prev_adjacent_pstate->pipe_cfg[0];
	const struct msm_format *prev_fmt = msm_framebuffer_format(prev_adjacent_pstate->base.fb);
	u16 max_tile_height = 1;

	if (prev_adjacent_pstate->r_pipe.sspp != NULL ||
	if (prev_adjacent_pstate->pipe[1].sspp != NULL ||
	    prev_pipe->multirect_mode != DPU_SSPP_MULTIRECT_NONE)
		return false;

@@ -1089,10 +1094,10 @@ static int dpu_plane_atomic_check(struct drm_plane *plane,
	struct dpu_plane *pdpu = to_dpu_plane(plane);
	struct dpu_plane_state *pstate = to_dpu_plane_state(new_plane_state);
	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
	struct dpu_sw_pipe *pipe = &pstate->pipe;
	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
	struct dpu_sw_pipe *pipe = &pstate->pipe[0];
	struct dpu_sw_pipe *r_pipe = &pstate->pipe[1];
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg[0];
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->pipe_cfg[1];
	const struct drm_crtc_state *crtc_state = NULL;
	uint32_t max_linewidth = dpu_kms->catalog->caps->max_linewidth;

@@ -1136,7 +1141,7 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
		drm_atomic_get_old_plane_state(state, plane);
	struct dpu_plane_state *pstate = to_dpu_plane_state(plane_state);
	struct drm_crtc_state *crtc_state = NULL;
	int ret;
	int ret, i;

	if (IS_ERR(plane_state))
		return PTR_ERR(plane_state);
@@ -1154,8 +1159,8 @@ static int dpu_plane_virtual_atomic_check(struct drm_plane *plane,
		 * resources are freed by dpu_crtc_assign_plane_resources(),
		 * but clean them here.
		 */
		pstate->pipe.sspp = NULL;
		pstate->r_pipe.sspp = NULL;
		for (i = 0; i < PIPES_PER_STAGE; i++)
			pstate->pipe[i].sspp = NULL;

		return 0;
	}
@@ -1193,6 +1198,7 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
	struct dpu_sw_pipe_cfg *pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg;
	const struct msm_format *fmt;
	int i;

	if (plane_state->crtc)
		crtc_state = drm_atomic_get_new_crtc_state(state,
@@ -1201,13 +1207,14 @@ static int dpu_plane_virtual_assign_resources(struct drm_crtc *crtc,
	pstate = to_dpu_plane_state(plane_state);
	prev_adjacent_pstate = prev_adjacent_plane_state ?
		to_dpu_plane_state(prev_adjacent_plane_state) : NULL;
	pipe = &pstate->pipe;
	r_pipe = &pstate->r_pipe;
	pipe_cfg = &pstate->pipe_cfg;
	r_pipe_cfg = &pstate->r_pipe_cfg;

	pipe->sspp = NULL;
	r_pipe->sspp = NULL;
	pipe = &pstate->pipe[0];
	r_pipe = &pstate->pipe[1];
	pipe_cfg = &pstate->pipe_cfg[0];
	r_pipe_cfg = &pstate->pipe_cfg[1];

	for (i = 0; i < PIPES_PER_STAGE; i++)
		pstate->pipe[i].sspp = NULL;

	if (!plane_state->fb)
		return -EINVAL;
@@ -1318,6 +1325,7 @@ void dpu_plane_flush(struct drm_plane *plane)
{
	struct dpu_plane *pdpu;
	struct dpu_plane_state *pstate;
	int i;

	if (!plane || !plane->state) {
		DPU_ERROR("invalid plane\n");
@@ -1338,8 +1346,8 @@ void dpu_plane_flush(struct drm_plane *plane)
		/* force 100% alpha */
		_dpu_plane_color_fill(pdpu, pdpu->color_fill, 0xFF);
	else {
		dpu_plane_flush_csc(pdpu, &pstate->pipe);
		dpu_plane_flush_csc(pdpu, &pstate->r_pipe);
		for (i = 0; i < PIPES_PER_STAGE; i++)
			dpu_plane_flush_csc(pdpu, &pstate->pipe[i]);
	}

	/* flag h/w flush complete */
@@ -1440,15 +1448,12 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane,
	struct dpu_plane *pdpu = to_dpu_plane(plane);
	struct drm_plane_state *state = plane->state;
	struct dpu_plane_state *pstate = to_dpu_plane_state(state);
	struct dpu_sw_pipe *pipe = &pstate->pipe;
	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	struct drm_crtc *crtc = state->crtc;
	struct drm_framebuffer *fb = state->fb;
	bool is_rt_pipe;
	const struct msm_format *fmt =
		msm_framebuffer_format(fb);
	struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
	int i;

	pstate->pending = true;

@@ -1463,12 +1468,12 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane,
			crtc->base.id, DRM_RECT_ARG(&state->dst),
			&fmt->pixel_format, MSM_FORMAT_IS_UBWC(fmt));

	dpu_plane_sspp_update_pipe(plane, pipe, pipe_cfg, fmt,
				   drm_mode_vrefresh(&crtc->mode),
				   &pstate->layout);

	if (r_pipe->sspp) {
		dpu_plane_sspp_update_pipe(plane, r_pipe, r_pipe_cfg, fmt,
	/* move the assignment here, to ease handling to another pairs later */
	for (i = 0; i < PIPES_PER_STAGE; i++) {
		if (!drm_rect_width(&pstate->pipe_cfg[i].src_rect))
			continue;
		dpu_plane_sspp_update_pipe(plane, &pstate->pipe[i],
					   &pstate->pipe_cfg[i], fmt,
					   drm_mode_vrefresh(&crtc->mode),
					   &pstate->layout);
	}
@@ -1476,15 +1481,17 @@ static void dpu_plane_sspp_atomic_update(struct drm_plane *plane,
	if (pstate->needs_qos_remap)
		pstate->needs_qos_remap = false;

	pstate->plane_fetch_bw = _dpu_plane_calc_bw(pdpu->catalog, fmt,
						    &crtc->mode, pipe_cfg);

	pstate->plane_clk = _dpu_plane_calc_clk(&crtc->mode, pipe_cfg);

	if (r_pipe->sspp) {
		pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt, &crtc->mode, r_pipe_cfg);
	pstate->plane_fetch_bw = 0;
	pstate->plane_clk = 0;
	for (i = 0; i < PIPES_PER_STAGE; i++) {
		if (!drm_rect_width(&pstate->pipe_cfg[i].src_rect))
			continue;
		pstate->plane_fetch_bw += _dpu_plane_calc_bw(pdpu->catalog, fmt,
							     &crtc->mode, &pstate->pipe_cfg[i]);

		pstate->plane_clk = max(pstate->plane_clk, _dpu_plane_calc_clk(&crtc->mode, r_pipe_cfg));
		pstate->plane_clk = max(pstate->plane_clk,
					_dpu_plane_calc_clk(&crtc->mode,
							    &pstate->pipe_cfg[i]));
	}
}

@@ -1492,17 +1499,28 @@ static void _dpu_plane_atomic_disable(struct drm_plane *plane)
{
	struct drm_plane_state *state = plane->state;
	struct dpu_plane_state *pstate = to_dpu_plane_state(state);
	struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	struct dpu_sw_pipe *pipe;
	int i;

	for (i = 0; i < PIPES_PER_STAGE; i += 1) {
		pipe = &pstate->pipe[i];
		if (!pipe->sspp)
			continue;

		trace_dpu_plane_disable(DRMID(plane), false,
				pstate->pipe.multirect_mode);
					pstate->pipe[i].multirect_mode);

	if (r_pipe->sspp) {
		r_pipe->multirect_index = DPU_SSPP_RECT_SOLO;
		r_pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
		if (i % PIPES_PER_STAGE == 0)
			continue;

		if (r_pipe->sspp->ops.setup_multirect)
			r_pipe->sspp->ops.setup_multirect(r_pipe);
		/*
		 * clear multirect for the right pipe so that the SSPP
		 * can be further reused in the solo mode
		 */
		pipe->multirect_index = DPU_SSPP_RECT_SOLO;
		pipe->multirect_mode = DPU_SSPP_MULTIRECT_NONE;
		if (pipe->sspp->ops.setup_multirect)
			pipe->sspp->ops.setup_multirect(pipe);
	}

	pstate->pending = true;
@@ -1597,31 +1615,26 @@ static void dpu_plane_atomic_print_state(struct drm_printer *p,
		const struct drm_plane_state *state)
{
	const struct dpu_plane_state *pstate = to_dpu_plane_state(state);
	const struct dpu_sw_pipe *pipe = &pstate->pipe;
	const struct dpu_sw_pipe_cfg *pipe_cfg = &pstate->pipe_cfg;
	const struct dpu_sw_pipe *r_pipe = &pstate->r_pipe;
	const struct dpu_sw_pipe_cfg *r_pipe_cfg = &pstate->r_pipe_cfg;
	const struct dpu_sw_pipe *pipe;
	const struct dpu_sw_pipe_cfg *pipe_cfg;
	int i;

	drm_printf(p, "\tstage=%d\n", pstate->stage);

	if (pipe->sspp) {
		drm_printf(p, "\tsspp[0]=%s\n", pipe->sspp->cap->name);
		drm_printf(p, "\tmultirect_mode[0]=%s\n",
	for (i = 0; i < PIPES_PER_STAGE; i++) {
		pipe = &pstate->pipe[i];
		if (!pipe->sspp)
			continue;
		pipe_cfg = &pstate->pipe_cfg[i];
		drm_printf(p, "\tsspp[%d]=%s\n", i, pipe->sspp->cap->name);
		drm_printf(p, "\tmultirect_mode[%d]=%s\n", i,
			   dpu_get_multirect_mode(pipe->multirect_mode));
		drm_printf(p, "\tmultirect_index[0]=%s\n",
		drm_printf(p, "\tmultirect_index[%d]=%s\n", i,
			   dpu_get_multirect_index(pipe->multirect_index));
		drm_printf(p, "\tsrc[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->src_rect));
		drm_printf(p, "\tdst[0]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&pipe_cfg->dst_rect));
	}

	if (r_pipe->sspp) {
		drm_printf(p, "\tsspp[1]=%s\n", r_pipe->sspp->cap->name);
		drm_printf(p, "\tmultirect_mode[1]=%s\n",
			   dpu_get_multirect_mode(r_pipe->multirect_mode));
		drm_printf(p, "\tmultirect_index[1]=%s\n",
			   dpu_get_multirect_index(r_pipe->multirect_index));
		drm_printf(p, "\tsrc[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->src_rect));
		drm_printf(p, "\tdst[1]=" DRM_RECT_FMT "\n", DRM_RECT_ARG(&r_pipe_cfg->dst_rect));
		drm_printf(p, "\tsrc[%d]=" DRM_RECT_FMT "\n", i,
			   DRM_RECT_ARG(&pipe_cfg->src_rect));
		drm_printf(p, "\tdst[%d]=" DRM_RECT_FMT "\n", i,
			   DRM_RECT_ARG(&pipe_cfg->dst_rect));
	}
}

@@ -1659,14 +1672,17 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
	struct dpu_plane *pdpu = to_dpu_plane(plane);
	struct dpu_plane_state *pstate = to_dpu_plane_state(plane->state);
	struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
	int i;

	if (!pdpu->is_rt_pipe)
		return;

	pm_runtime_get_sync(&dpu_kms->pdev->dev);
	_dpu_plane_set_qos_ctrl(plane, &pstate->pipe, enable);
	if (pstate->r_pipe.sspp)
		_dpu_plane_set_qos_ctrl(plane, &pstate->r_pipe, enable);
	for (i = 0; i < PIPES_PER_STAGE; i++) {
		if (!pstate->pipe[i].sspp)
			continue;
		_dpu_plane_set_qos_ctrl(plane, &pstate->pipe[i], enable);
	}
	pm_runtime_put_sync(&dpu_kms->pdev->dev);
}
#endif
+4 −8
Original line number Diff line number Diff line
@@ -17,10 +17,8 @@
/**
 * struct dpu_plane_state: Define dpu extension of drm plane state object
 * @base:	base drm plane state object
 * @pipe:	software pipe description
 * @r_pipe:	software pipe description of the second pipe
 * @pipe_cfg:	software pipe configuration
 * @r_pipe_cfg:	software pipe configuration for the second pipe
 * @pipe:	software pipe description array
 * @pipe_cfg:	software pipe configuration array
 * @stage:	assigned by crtc blender
 * @needs_qos_remap: qos remap settings need to be updated
 * @multirect_index: index of the rectangle of SSPP
@@ -33,10 +31,8 @@
 */
struct dpu_plane_state {
	struct drm_plane_state base;
	struct dpu_sw_pipe pipe;
	struct dpu_sw_pipe r_pipe;
	struct dpu_sw_pipe_cfg pipe_cfg;
	struct dpu_sw_pipe_cfg r_pipe_cfg;
	struct dpu_sw_pipe pipe[PIPES_PER_STAGE];
	struct dpu_sw_pipe_cfg pipe_cfg[PIPES_PER_STAGE];
	enum dpu_stage stage;
	bool needs_qos_remap;
	bool pending;