From nobody Thu Oct 2 10:53:50 2025 Received: from mail-pj1-f44.google.com (mail-pj1-f44.google.com [209.85.216.44]) (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 A8E6630DD2E for ; Thu, 18 Sep 2025 13:30:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758202209; cv=none; b=kjfr/kpsjyX0bA72WOWUD5n3Ah2bRE9tnM+xGABxDEWWgSJsZnyokp8IIAzsDn5XgLqqqlgQgJFSo8AP7Czk11sU5+WdiwFgmiXcM8D2ODTUDQPzjP8BXOgC99LNvTERyIauzsIjig7zG8B+ZNPVwtj2446NWcuDJqqv2zgkg1Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1758202209; c=relaxed/simple; bh=u4VBOLy/mL0r8aYeNuhgkBJoVhD1c9UPZQ+/07d212E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=rlouquAqODOJUe1Ewy/ZAVlbBdhzHpptCfP9ltZbUVcnNvuplhF9A10eqeDoMuW7HbrSbYWVVYoLBfhZ5NBolRAgphBgx2KkvGztCSDWI89lZbXSeo2ZPpz9/aQEV/TKqoFiGlwsuXUuhU3cSH14zibSV7Dg4hNvlAMBAqgj3k4= 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=wWAb1VBn; arc=none smtp.client-ip=209.85.216.44 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="wWAb1VBn" Received: by mail-pj1-f44.google.com with SMTP id 98e67ed59e1d1-3306d3ab2e4so598931a91.3 for ; Thu, 18 Sep 2025 06:30:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1758202207; x=1758807007; 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=W50eS6OJphepB698zgCldQ57w3gQ9vi5VJ8RV7KP1W4=; b=wWAb1VBnJIYQ8IVl9vk240V4fKsZg6cHpeKGnpShDTKIcTWfhaDP61YYyLj3MAtYBo 27j2qYriNn4qD7PjJJhifcOKUfCH7JK+S8TDfP0GiY9s7xn3yaJ4JKV5umsTx6Nfq4Kt GvJwNfZJOS65vB1RdjbLWwYfFPYVR8RabzskO5y5ba8CF4ebxDHy31UWzGwqBAhBHZmL Ny6X7Ilf2RjGqd7xRPgbHGQs9daZFArHyuLMDtheXxdLbN+enZL9EOPszHLvMBGI/c5z 8wtwCtT0AMGNOn9WpzDsPAE5LfkSzpnGdGswafj51OcBlqoQ6su/5IOnSmoO3P0DQH26 cucA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1758202207; x=1758807007; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=W50eS6OJphepB698zgCldQ57w3gQ9vi5VJ8RV7KP1W4=; b=sCJWR9ujdg0Fr/SHBPAGEg206e4fb+ighZnj8JJ47/4INOhsuuHwTxjiMc1qvVhc/3 nHc00bQJcK/HBVoR9VNzq4XpCQD9v9uZDYNy37otDqHPDu651HhQpR9mbLb/uZ8wf8ig DaDkY7FoEfDthWt3xYcF6HQ9PTKsk2ZxlnrWdQbvNNMmcotAXLaidi0pN77I3mHt6ZiE mgdRDP0MnWZO9KQIctWxRyNVWq4e+EXOmlGlunJbBmDiKjD5koFIPJLt7wQ8/P8MLaz7 RpbRIoQ3cOsFZJ0nUpXMi4Pmn+NAJWP/vdD3VGVprme+0oYHhyH40Vg53enbIjEjyNED lR/g== X-Forwarded-Encrypted: i=1; AJvYcCU1apEM0u2VNScV1qUWjXAP7t9a1vGufPJTK2dUA8HGMjxvgxfXgIdFcRpwGv6kvnGxXPKfB1GPNgw6rK4=@vger.kernel.org X-Gm-Message-State: AOJu0Yw6o9rF2Z1CaXzkJJMygv+pBHOpiGKkgjNWGrSp7DsFFmBnmYHw Y83U0YDd+/n9fQ7HKcGCPGF/RySNhYZVaefXsWkNqkJvaG8wOLsvV0Lxcfl5n3AUE4SCVrdemzt EeYehOj0= X-Gm-Gg: ASbGncu2zdXHXnzDQtKLNiPTFN1jPRy4gtJdw2b6B1Idd7EpcHtgx54LBDJx4mcJ320 2ZRNqCRTJOPPeOKxO2LXz9HNJ0sPoEETUv68gVxpEuqDSxAlF3QB9LsjMiF+W0wyh0HFhps910O pmlUtzqxmfgcOG2QWmsXAC3JY3j6ThXhinyj82gBKMxlKTo/0nmYFjLBh0ySzX8l5w86AW3JUbE 8QYDt2i+Kpyum6enDIVXASHn4mOEVAZHMqU6kx8ewl7lx2mSZ+nEDWsqyG+WHkEcC74XvnAlXfZ 62mLDeIr7EgnvG31u2w10VXmyudZTP0sHLAXuDgfGO6FFupxoB77VwJ2F+HAfuh7tAO+6wmMLIN zDAJVdvJmqn0ZpIJ80LkhAJPhYxsd5yJS0Vg= X-Google-Smtp-Source: AGHT+IFVDaJVwcecGEi8tbNFdsx5LihkbO7RCyP/tWCzEEGD5cuLKuRvZ9t7q1+zXXiKZysbNgFoDQ== X-Received: by 2002:a17:90b:35cb:b0:330:797a:f4ea with SMTP id 98e67ed59e1d1-330797af6a8mr2226549a91.29.1758202207032; Thu, 18 Sep 2025 06:30:07 -0700 (PDT) Received: from [127.0.1.1] ([112.64.61.5]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-b54ff35cc76sm2331479a12.10.2025.09.18.06.30.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 18 Sep 2025 06:30:06 -0700 (PDT) From: Jun Nie Date: Thu, 18 Sep 2025 21:29:01 +0800 Subject: [PATCH v16 09/10] 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: <20250918-v6-16-rc2-quad-pipe-upstream-4-v16-9-ff6232e3472f@linaro.org> References: <20250918-v6-16-rc2-quad-pipe-upstream-4-v16-0-ff6232e3472f@linaro.org> In-Reply-To: <20250918-v6-16-rc2-quad-pipe-upstream-4-v16-0-ff6232e3472f@linaro.org> To: Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Rob Clark , Jessica Zhang 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.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1758202147; l=9687; i=jun.nie@linaro.org; s=20240403; h=from:subject:message-id; bh=u4VBOLy/mL0r8aYeNuhgkBJoVhD1c9UPZQ+/07d212E=; b=w3ZwRiyuQVAyi3gh+lpkRX2lETZ0PQ5QA29K8nwsnipy72sdFvKf8zT/wEv/I3OXsT9C4APd+ 9g4xPfb/4TLDGIy//e1MyZsF7H+VcCuTPHK08nsq/a1mcb5bYIi3dIW 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 --- 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 | 137 +++++++++++++++++++++-----= ---- 3 files changed, 110 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm= /disp/dpu1/dpu_crtc.c index d825eb8e40ae8bd456ede6269951339e3053d0d3..e925d93b38feac0594d735fdc2c= 5b9fd5ae83e6a 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1604,6 +1604,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 94392b9b924546f96e738ae20920cf9afd568e6b..6eaba5696e8e6bd1246a9895c4c= 8714ca6589b10 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 5ae58352cbee1251a0140879f04fc7c304cae674..89a5feb6308bcac537562c3dc4e= 61c16c92e460c 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -824,8 +824,12 @@ static int dpu_plane_atomic_check_nosspp(struct drm_pl= ane *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; + struct dpu_sw_pipe_cfg init_pipe_cfg; struct drm_rect fb_rect =3D { 0 }; + const struct drm_display_mode *mode =3D &crtc_state->adjusted_mode; uint32_t max_linewidth; + u32 num_lm; + int stage_id, num_stages; =20 min_scale =3D FRAC_16_16(1, MAX_UPSCALE_RATIO); max_scale =3D MAX_DOWNSCALE_RATIO << 16; @@ -848,13 +852,10 @@ static int dpu_plane_atomic_check_nosspp(struct drm_p= lane *plane, return -EINVAL; } =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); + num_lm =3D dpu_crtc_get_num_lm(crtc_state); =20 - pipe_cfg->dst_rect =3D new_plane_state->dst; + /* state->src is 16.16, src_rect is not */ + drm_rect_fp_to_int(&init_pipe_cfg.src_rect, &new_plane_state->src); =20 fb_rect.x2 =3D new_plane_state->fb->width; fb_rect.y2 =3D new_plane_state->fb->height; @@ -879,35 +880,94 @@ static int dpu_plane_atomic_check_nosspp(struct drm_p= lane *plane, =20 max_linewidth =3D pdpu->catalog->caps->max_linewidth; =20 - drm_rect_rotate(&pipe_cfg->src_rect, + drm_rect_rotate(&init_pipe_cfg.src_rect, new_plane_state->fb->width, new_plane_state->fb->height, new_plane_state->rotation); =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; + /* + * 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); + 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)); + + 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); + } + pstate->needs_qos_remap =3D drm_atomic_crtc_needs_modeset(crtc_state); =20 return 0; @@ -983,20 +1043,17 @@ 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; - - 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.34.1