From nobody Mon Feb 9 07:23:13 2026 Received: from mail-pl1-f180.google.com (mail-pl1-f180.google.com [209.85.214.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 024762E62B4 for ; Wed, 21 Jan 2026 08:02:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768982542; cv=none; b=GjZ45YNmnpH6djMxNJzR/ObI2JOLw3QXUmV1x3KJOy+CTikDfOR3b/dB/UOioBajQHtHue7o8gpLw24up1JMYy0SDhdbiR4F/YfEkMGuimW96eR0g2HDhhLYxIc92c0e7XNowSX8OVr0WVO2sPdQmGV9gJj7JpEkRpPPqIlzFU8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768982542; c=relaxed/simple; bh=S1T74Y6D2F9qA1dfaYrbbsQtI+apSIgdZMEVXSOwbbM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ar7XEbQsy3WBjZB1/9Clhlh1qb27MDo8Lf3Qm0nXkqYbt9hc7352HjEdcAKbIa7WxOY6kR0wAuhZ9oKNKYN23YOB+YhLnOBqQqjEQTmWbiKQoPylNJi02bHQshZbQtIwZjC5ogkF/zrYyLH4oScWAv5KEhayxLHGLdVjrXmnCrc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=YI7ZqVSV; arc=none smtp.client-ip=209.85.214.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="YI7ZqVSV" Received: by mail-pl1-f180.google.com with SMTP id d9443c01a7336-2a78e381fc1so4431975ad.3 for ; Wed, 21 Jan 2026 00:02:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1768982539; x=1769587339; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=FBDteOxdBzOojlPhsjzryNojfnZi+drcSiJZtd7Uqqo=; b=YI7ZqVSV3om+R/kUjNgIgIktg4fyZ8editOIXDmhtalOlUbGYX0sus0yJBzr2JPsdr QtiDYPP5bIf9AT2aNdCwVEhQzV+oXIIFhEUjudr3ZZaAXs33IANlVdvPbp+qw6fmxycG f28Xq0qv/qZlh+VhAwlnCjwnMMQGzm4/8/8MevRA5rflzSF6CKbYqNEZbx83RJHAA2LG TaFqFaSa9yWateK1/5tdkmBeuN6UgfJdFwV/DcB0OWBfled8rzIXPbEBjUyRO5uRWzqq If0G5Ct3gB6HrXZAGJ5F1uMQ9SRyDXHk6J1ImB7CR2ojW3W/bGZ4VuvSF+zhhndNqWzq LymA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768982539; x=1769587339; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-gg:x-gm-message-state:from:to :cc:subject:date:message-id:reply-to; bh=FBDteOxdBzOojlPhsjzryNojfnZi+drcSiJZtd7Uqqo=; b=KhsEamnT1wU38/aB2tWbmwuSoQhMSPcsfzgALc2Q9PmSPBgUPe3rz9azke+04Ocl3f MfYmCudAMD+sV3GAa9XOPo7gFazjSq5CZydByrxZzJpiKdAp9BYYxGKOhkLrSRky3sAp bHyRM7SThiMViBU9Lix2xCQPjGVwSx7XP7MCrwwAZGVxFmTZ8ZKTQ5s2qMNM3zRTrqU6 rgYtdsS/rbzkMB2x6DPPR3ECKbxXcia0RaS5/+N2fjDwUrQus0H+vsiRVw81bY4RE0IE k5ypnQuHdBOtxy3aOCaNBjZYP75hwYnmsfG97WfNIpnpgE5gF3VP63oKIVEN+w0IY4nq /GXA== X-Forwarded-Encrypted: i=1; AJvYcCVTV2mngRQRz2IPbRm6MlyrXLxD2uOL0YaKm8nLagRQEtBoQ2FWZYJmLpE4emT6e7hTTDzsOhTzA4mmwR0=@vger.kernel.org X-Gm-Message-State: AOJu0Yw1b38lVLSAw1/wW9wTJB8pKcv994QNugo8nxO1pbS25jzRRcni YzKSc/lKRqiAIgcpOkJ1LVA9hyfKoCkJ5shIfhDVI5+WMYV2hip6LzbF9O/b5CcA9/rSG3WqqX9 Rp1lU4RcMNLAR X-Gm-Gg: AZuq6aJkrkaGU6YUBNQqeistO4S/kIXUvdDGgUylX/ykRsXOWozvJB8Lpm4f1O1cMuV JSgezfBK27i17ixvuBhRpqQJyVxGnepPBiUwppSxdH+Jg8e1bw8JV+b6A6Of5En43zEeJvASCxn oLrBh2QiVBE5ABphsD++7l3nPSstzHHd8OefhIBFhx1W7k6GVwdFWEzZFjSg02N+vq1vrfgbA6i iVHiHvAt6FwlBG/vhVwiTtLOYtXAOeod+7qoe2O+BU6mCa1rgjT+7Cbom5fZ9waI77NMQxX6f0T qKbEtGpslWR0s/KtYR7pn7t33PcNi3wpypR9k+MNlyJqVcutV6O+5iFNdTsY0+f92NZP+iSVD7x Il6wbQWRmr7JFu0tu0/MLOdF3CnpTCmn4VukbLbyvosVnmLfJUN4q72CDacv6 X-Received: by 2002:a17:902:fc4d:b0:2a2:dc1f:78d8 with SMTP id d9443c01a7336-2a7176cc6dfmr164302875ad.42.1768982538308; Wed, 21 Jan 2026 00:02:18 -0800 (PST) Received: from [127.0.1.1] ([2a12:a305:4::4039]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2a7190d14cfsm146851545ad.38.2026.01.21.00.02.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 21 Jan 2026 00:02:17 -0800 (PST) From: Jun Nie Date: Wed, 21 Jan 2026 16:01:52 +0800 Subject: [PATCH v17 3/4] drm/msm/dpu: support plane splitting in quad-pipe case Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260121-msm-next-quad-pipe-split-v17-3-6eb6d8675ca2@linaro.org> References: <20260121-msm-next-quad-pipe-split-v17-0-6eb6d8675ca2@linaro.org> In-Reply-To: <20260121-msm-next-quad-pipe-split-v17-0-6eb6d8675ca2@linaro.org> To: Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Rob Clark , Neil Armstrong Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, Jun Nie , Dmitry Baryshkov X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1768982516; l=9242; i=jun.nie@linaro.org; s=20240403; h=from:subject:message-id; bh=S1T74Y6D2F9qA1dfaYrbbsQtI+apSIgdZMEVXSOwbbM=; b=fIAULDF7cS2VXPNYOVzkpJvCZ62aZuyDv4TDf2ZEV/exFmMAMp5rvC8XEvzTix4AuY2hj5usz vgmIAa0BTaGBA9fRJtDDFwa+ugQ9eUaV1BYAYQA8flXfAN3X/7zHk31 X-Developer-Key: i=jun.nie@linaro.org; a=ed25519; pk=MNiBt/faLPvo+iJoP1hodyY2x6ozVXL8QMptmsKg3cc= The content of every half of screen is sent out via one interface in dual-DSI case. The content for every interface is blended by a LM pair in quad-pipe case, thus a LM pair should not blend any content that cross the half of screen in this case. Clip plane into pipes per left and right half screen ROI if topology is quad pipe case. The clipped rectangle on every half of screen is futher handled by two pipes if its width exceeds a limit for a single pipe. Signed-off-by: Jun Nie Reviewed-by: Dmitry Baryshkov Reviewed-by: Jessica Zhang Patchwork: https://patchwork.freedesktop.org/patch/675416/ Link: https://lore.kernel.org/r/20250918-v6-16-rc2-quad-pipe-upstream-4-v16= -9-ff6232e3472f@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 +++ drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 + drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 139 +++++++++++++++++++++-----= ---- 3 files changed, 110 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm= /disp/dpu1/dpu_crtc.c index debdbbe6160dd..87a934e3801f3 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1606,6 +1606,17 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en) return 0; } =20 +/** + * dpu_crtc_get_num_lm - Get mixer number in this CRTC pipeline + * @state: Pointer to drm crtc state object + */ +unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state) +{ + struct dpu_crtc_state *cstate =3D to_dpu_crtc_state(state); + + return cstate->num_mixers; +} + #ifdef CONFIG_DEBUG_FS static int _dpu_debugfs_status_show(struct seq_file *s, void *data) { diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h b/drivers/gpu/drm/msm= /disp/dpu1/dpu_crtc.h index 94392b9b92454..6eaba5696e8e6 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -267,4 +267,6 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_cl= ient_type( =20 void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event); =20 +unsigned int dpu_crtc_get_num_lm(const struct drm_crtc_state *state); + #endif /* _DPU_CRTC_H_ */ diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/ms= m/disp/dpu1/dpu_plane.c index 3c629f4df461d..2637abefe2602 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -881,50 +881,107 @@ static int dpu_plane_split(struct drm_plane *plane, struct dpu_plane_state *pstate =3D to_dpu_plane_state(new_plane_state); struct dpu_sw_pipe_cfg *pipe_cfg; struct dpu_sw_pipe_cfg *r_pipe_cfg; + const struct drm_display_mode *mode =3D &crtc_state->adjusted_mode; uint32_t max_linewidth; + u32 num_lm; + int stage_id, num_stages; =20 if (!new_plane_state->visible) return 0; =20 - /* move the assignment here, to ease handling to another pairs later */ - pipe_cfg =3D &pstate->pipe_cfg[0]; - r_pipe_cfg =3D &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); - - pipe_cfg->dst_rect =3D new_plane_state->dst; + num_lm =3D dpu_crtc_get_num_lm(crtc_state); =20 max_linewidth =3D pdpu->catalog->caps->max_linewidth; =20 - drm_rect_rotate(&pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, - new_plane_state->rotation); + /* + * We have 1 mixer pair cfg for 1:1:1 and 2:2:1 topology, 2 mixer pair + * configs for left and right half screen in case of 4:4:2 topology. + * But we may have 2 rect to split wide plane that exceeds limit with 1 + * config for 2:2:1. So need to handle both wide plane splitting, and + * two halves of screen splitting for quad-pipe case. Check dest + * rectangle left/right clipping first, then check wide rectangle + * splitting in every half next. + */ + num_stages =3D (num_lm + 1) / 2; + /* iterate mixer configs for this plane, to separate left/right with the = id */ + for (stage_id =3D 0; stage_id < num_stages; stage_id++) { + struct drm_rect mixer_rect =3D { + .x1 =3D stage_id * mode->hdisplay / num_stages, + .y1 =3D 0, + .x2 =3D (stage_id + 1) * mode->hdisplay / num_stages, + .y2 =3D mode->vdisplay + }; + int cfg_idx =3D stage_id * PIPES_PER_STAGE; + + pipe_cfg =3D &pstate->pipe_cfg[cfg_idx]; + r_pipe_cfg =3D &pstate->pipe_cfg[cfg_idx + 1]; + + drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src); + + drm_rect_rotate(&pipe_cfg->src_rect, + new_plane_state->fb->width, new_plane_state->fb->height, + new_plane_state->rotation); + + pipe_cfg->dst_rect =3D new_plane_state->dst; + + DPU_DEBUG_PLANE(pdpu, "checking src " DRM_RECT_FMT + " vs clip window " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), + DRM_RECT_ARG(&mixer_rect)); + + /* + * If this plane does not fall into mixer rect, check next + * mixer rect. + */ + if (!drm_rect_clip_scaled(&pipe_cfg->src_rect, + &pipe_cfg->dst_rect, + &mixer_rect)) { + memset(pipe_cfg, 0, 2 * sizeof(struct dpu_sw_pipe_cfg)); =20 - if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) || - _dpu_plane_calc_clk(&crtc_state->adjusted_mode, pipe_cfg) > max_mdp_= clk_rate) { - if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) { - DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", - DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); - return -E2BIG; + continue; } =20 - *r_pipe_cfg =3D *pipe_cfg; - pipe_cfg->src_rect.x2 =3D (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2= ) >> 1; - pipe_cfg->dst_rect.x2 =3D (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2= ) >> 1; - r_pipe_cfg->src_rect.x1 =3D pipe_cfg->src_rect.x2; - r_pipe_cfg->dst_rect.x1 =3D pipe_cfg->dst_rect.x2; - } else { - memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg)); - } + pipe_cfg->dst_rect.x1 -=3D mixer_rect.x1; + pipe_cfg->dst_rect.x2 -=3D mixer_rect.x1; + + DPU_DEBUG_PLANE(pdpu, "Got clip src:" DRM_RECT_FMT " dst: " DRM_RECT_FMT= "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), DRM_RECT_ARG(&pipe_cfg->dst_rect)); + + /* Split wide rect into 2 rect */ + if ((drm_rect_width(&pipe_cfg->src_rect) > max_linewidth) || + _dpu_plane_calc_clk(mode, pipe_cfg) > max_mdp_clk_rate) { + + if (drm_rect_width(&pipe_cfg->src_rect) > 2 * max_linewidth) { + DPU_DEBUG_PLANE(pdpu, "invalid src " DRM_RECT_FMT " line:%u\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), max_linewidth); + return -E2BIG; + } + + memcpy(r_pipe_cfg, pipe_cfg, sizeof(struct dpu_sw_pipe_cfg)); + pipe_cfg->src_rect.x2 =3D (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x= 2) >> 1; + pipe_cfg->dst_rect.x2 =3D (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x= 2) >> 1; + r_pipe_cfg->src_rect.x1 =3D pipe_cfg->src_rect.x2; + r_pipe_cfg->dst_rect.x1 =3D pipe_cfg->dst_rect.x2; + DPU_DEBUG_PLANE(pdpu, "Split wide plane into:" + DRM_RECT_FMT " and " DRM_RECT_FMT "\n", + DRM_RECT_ARG(&pipe_cfg->src_rect), + DRM_RECT_ARG(&r_pipe_cfg->src_rect)); + } else { + memset(r_pipe_cfg, 0, sizeof(struct dpu_sw_pipe_cfg)); + } =20 - drm_rect_rotate_inv(&pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, - new_plane_state->rotation); - if (drm_rect_width(&r_pipe_cfg->src_rect) !=3D 0) - drm_rect_rotate_inv(&r_pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, + drm_rect_rotate_inv(&pipe_cfg->src_rect, + new_plane_state->fb->width, + new_plane_state->fb->height, new_plane_state->rotation); =20 + if (drm_rect_width(&r_pipe_cfg->src_rect) !=3D 0) + drm_rect_rotate_inv(&r_pipe_cfg->src_rect, + new_plane_state->fb->width, + new_plane_state->fb->height, + new_plane_state->rotation); + } + return 0; } =20 @@ -998,20 +1055,18 @@ static int dpu_plane_atomic_check_sspp(struct drm_pl= ane *plane, drm_atomic_get_new_plane_state(state, plane); struct dpu_plane *pdpu =3D to_dpu_plane(plane); struct dpu_plane_state *pstate =3D to_dpu_plane_state(new_plane_state); - struct dpu_sw_pipe *pipe =3D &pstate->pipe[0]; - struct dpu_sw_pipe *r_pipe =3D &pstate->pipe[1]; - struct dpu_sw_pipe_cfg *pipe_cfg =3D &pstate->pipe_cfg[0]; - struct dpu_sw_pipe_cfg *r_pipe_cfg =3D &pstate->pipe_cfg[1]; - int ret =3D 0; =20 - ret =3D dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, - &crtc_state->adjusted_mode, - new_plane_state); - if (ret) - return ret; + struct dpu_sw_pipe *pipe; + struct dpu_sw_pipe_cfg *pipe_cfg; + int ret =3D 0, i; =20 - if (drm_rect_width(&r_pipe_cfg->src_rect) !=3D 0) { - ret =3D dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, + for (i =3D 0; i < PIPES_PER_PLANE; i++) { + pipe =3D &pstate->pipe[i]; + pipe_cfg =3D &pstate->pipe_cfg[i]; + if (!drm_rect_width(&pipe_cfg->src_rect)) + continue; + DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i); + ret =3D dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, &crtc_state->adjusted_mode, new_plane_state); if (ret) --=20 2.43.0