From patchwork Mon Feb 17 14:16:03 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jun Nie X-Patchwork-Id: 13977980 Received: from mail-pl1-f175.google.com (mail-pl1-f175.google.com [209.85.214.175]) (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 D4592225404 for ; Mon, 17 Feb 2025 14:18:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739801901; cv=none; b=CGM35b7RZ6EwgOUO4Bti+Hhm/WoL5IpvQgeNdaX7U//WjBJavL5SMYaPYmdg2jEJgUGvx2lK26WIp9SdhlswY2PWiWnZMKxfECh8fcA+LF8acE+qRGTSQjHKYujviOlh/GD3SLmfra1rXnK3bzGyCFALoRfd3LFnT0dW99Gwr5Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739801901; c=relaxed/simple; bh=KCxHPSrq+0wZsSrJjnPZ9OEDEC8A7tuq2rtnWGAQTg0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=hH/0EZLgqPKI3eua3biyhKhXDN4mIUJB2xcZl3xbEvWo/wo5SoM99C3lCxALyRcmxe9Ezq++g8au8Fo3IoG+XkesIgk4md96QZ+L1l38FbvUMu1zgjl2GVV4gwTEMkUQEt2dz5gcQCpfpAWAO6fJOG9vQ0/WguqLLN9fyBuHkcw= 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=lmNkU3+P; arc=none smtp.client-ip=209.85.214.175 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="lmNkU3+P" Received: by mail-pl1-f175.google.com with SMTP id d9443c01a7336-220f4dd756eso50462355ad.3 for ; Mon, 17 Feb 2025 06:18:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1739801899; x=1740406699; 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=Tx6GkoUIFUyuUtNb8RLWVuurpj5FdZ6/dmO+pJenrKM=; b=lmNkU3+PQlQJ1VDkXoNd6M/UimZfQwiADB7OTWJUSPOSjz6h/o3qn6Gm43Xa+sSPGT XiRapnJNYa3/gqC3SHyeKoAmn8ogLGfiWlofwrtAUksS46GsgCLX07h1Ssplj1LlMSHz 2BXx1tFqJSVWCppJbilSFBSHxz7RXZQrECtsJT0AAWJ2EQYcsqe+/h4lMivpeqtzeZf3 SVTYFHkVC1V3BCkvQ6FsKBqMSTZX6kApDC/eYOnq+jzcWFIOAie4vzO+DzGIaNwmmPu/ EKs2gwj8hq7J3uDQg38Vrw+DSbCRW66c7fkSG9kQm+rgdg1Cale2KL+7qYDHoKIWiLlO /nWw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739801899; x=1740406699; 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=Tx6GkoUIFUyuUtNb8RLWVuurpj5FdZ6/dmO+pJenrKM=; b=CjvGMfI95VUip7BFMjcYq6DFssoI7EsIbGobDkUi8VcLAOmTdx8Bc0K//VNLtLku0Q 3pmuao8QhcgRhEY2lClXwm3awQJOPBi7tH+wTmXgG9sfmuZe3EGUTNYGtac7D30ZlsFG uPqV6fVsrGmECRIHLrbuecUI+vFicA2Lm8kWiCbL6cONv0qWEGo0bo0Fwq1T+FtoC6+X f+pH1Sj4MUKc821UjSup8wsI4HLh1/vSw7Ry/Iy0mzauNT38Xo0I+mfDLUvzHwJKuALa 3lxNKnnM2q9jhOVyWOTdyWwbx99vCkGi+aJZPjGAq+xxnQm8GI9myMbwrQQM8Nqgvzha IIAA== X-Gm-Message-State: AOJu0YzHCgY7C9/WuOioiZI4/KLGPz4I3t9au+ocqeToEKEPvN3lNIhO 4F7Wudbgk3NonvxxJkQTixyFBgmKmhHtvTUE1GqNEhOCTmAiOf/g9GAj6mEtZo4= X-Gm-Gg: ASbGncuQqGqHUGSc9vsRNh4IOWLJkSJueOyKs81w5wdEUq8Lap4S5+6eTR6TFWZ15ec zsQC6CEvXnmhSZa5QXTPWwsIOVDHoT3h8hfc6owDkaXoKMS0vlUd0AYV9hgvMEciw7ILIsC8EDL QGkrFizJxtaTWlx842QMvGv4P2xEVUcvG4Zs/2vch0thT8tdvoCrHqCsXzoYOAvYkGDUlA+Z1s5 0BEtpNGo6qTiZLMygo/TNS9+t0O46HPYImDtf1K3YC4fmI0qEq12sGaqQosGEFGxt+0EKqVBoCY apxrwZ3l775N X-Google-Smtp-Source: AGHT+IE/qvCwgaFOQFmjqsTB7+FRF0KmycMJ4EIsWisNbN+EGXcaa/79l70KQ27RjIZIw+iVI8GNpA== X-Received: by 2002:a17:902:ce82:b0:220:e1e6:4457 with SMTP id d9443c01a7336-22104043055mr135578055ad.26.1739801899059; Mon, 17 Feb 2025 06:18:19 -0800 (PST) Received: from [127.0.1.1] ([112.65.12.217]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-220d5366984sm71900845ad.60.2025.02.17.06.18.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Feb 2025 06:18:18 -0800 (PST) From: Jun Nie Date: Mon, 17 Feb 2025 22:16:03 +0800 Subject: [PATCH v6 14/15] drm/msm/dpu: support plane splitting in quad-pipe case Precedence: bulk X-Mailing-List: linux-arm-msm@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20250217-sm8650-v6-14-hmd-deckard-mdss-quad-upstream-oldbootwrapper-36-prep-v6-14-c11402574367@linaro.org> References: <20250217-sm8650-v6-14-hmd-deckard-mdss-quad-upstream-oldbootwrapper-36-prep-v6-0-c11402574367@linaro.org> In-Reply-To: <20250217-sm8650-v6-14-hmd-deckard-mdss-quad-upstream-oldbootwrapper-36-prep-v6-0-c11402574367@linaro.org> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , 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 X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1739801787; l=9503; i=jun.nie@linaro.org; s=20240403; h=from:subject:message-id; bh=KCxHPSrq+0wZsSrJjnPZ9OEDEC8A7tuq2rtnWGAQTg0=; b=SBj1OBYzoS68UHhjatnJwlxOpQxaUwd58sm6MPzB+/Fshxfv2j2YqbLXbNyZZxhHkBZDE+iim CI8d9tu8n7EAHWT/W95lz4OAqJsVT2kAIcRtAnEFKW9Kv+lvERBB0al 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 --- 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 | 134 +++++++++++++++++++++--------- 3 files changed, 107 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 50acaf25a3ffcc94354faaa816fe74566784844c..852c2ea632f1bb52b3d83ccd45c8afd2e5f8e988 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c @@ -1366,6 +1366,17 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en) return 0; } +/** + * 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 = 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 0b148f3ce0d7af80ec4ffcd31d8632a5815b16f1..b14bab2754635953da402d09e11a43b9b4cf4153 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h @@ -264,4 +264,6 @@ static inline enum dpu_crtc_client_type dpu_crtc_get_client_type( void dpu_crtc_frame_event_cb(struct drm_crtc *crtc, u32 event); +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/msm/disp/dpu1/dpu_plane.c index b87da2bd20861370e7b3b1fa60a689a145c2fab7..4d22c9029b8c4af0c7da86af20bd34c3b5d63e11 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -831,8 +831,12 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, struct dpu_plane_state *pstate = 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 = { 0 }; + const struct drm_display_mode *mode = &crtc_state->adjusted_mode; uint32_t max_linewidth; + u32 num_lm; + int stage_id, num_stages; min_scale = FRAC_16_16(1, MAX_UPSCALE_RATIO); max_scale = MAX_DOWNSCALE_RATIO << 16; @@ -855,13 +859,10 @@ 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); + num_lm = dpu_crtc_get_num_lm(crtc_state); - pipe_cfg->dst_rect = 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); fb_rect.x2 = new_plane_state->fb->width; fb_rect.y2 = new_plane_state->fb->height; @@ -886,35 +887,91 @@ static int dpu_plane_atomic_check_nosspp(struct drm_plane *plane, max_linewidth = pdpu->catalog->caps->max_linewidth; - 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); - 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 = (num_lm + 1) / 2; + /* iterate mixer configs for this plane, to separate left/right with the id */ + for (stage_id = 0; stage_id < num_stages; stage_id++) { + struct drm_rect mixer_rect = {stage_id * mode->hdisplay / num_stages, 0, + (stage_id + 1) * mode->hdisplay / num_stages, + mode->vdisplay}; + int cfg_idx = stage_id * PIPES_PER_STAGE; + + pipe_cfg = &pstate->pipe_cfg[cfg_idx]; + r_pipe_cfg = &pstate->pipe_cfg[cfg_idx + 1]; + + drm_rect_fp_to_int(&pipe_cfg->src_rect, &new_plane_state->src); + pipe_cfg->dst_rect = 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; } - *r_pipe_cfg = *pipe_cfg; - pipe_cfg->src_rect.x2 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1; - pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1; - r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2; - r_pipe_cfg->dst_rect.x1 = pipe_cfg->dst_rect.x2; - } else { - memset(r_pipe_cfg, 0, sizeof(*r_pipe_cfg)); - } + pipe_cfg->dst_rect.x1 -= mixer_rect.x1; + pipe_cfg->dst_rect.x2 -= 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)); - 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) != 0) - drm_rect_rotate_inv(&r_pipe_cfg->src_rect, - new_plane_state->fb->width, new_plane_state->fb->height, + /* 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 = (pipe_cfg->src_rect.x1 + pipe_cfg->src_rect.x2) >> 1; + pipe_cfg->dst_rect.x2 = (pipe_cfg->dst_rect.x1 + pipe_cfg->dst_rect.x2) >> 1; + r_pipe_cfg->src_rect.x1 = pipe_cfg->src_rect.x2; + r_pipe_cfg->dst_rect.x1 = 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)); + } + + 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) != 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 = drm_atomic_crtc_needs_modeset(crtc_state); return 0; @@ -954,20 +1011,17 @@ 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[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, - &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 = 0, i; - if (drm_rect_width(&r_pipe_cfg->src_rect) != 0) { - ret = dpu_plane_atomic_check_pipe(pdpu, r_pipe, r_pipe_cfg, + for (i = 0; i < PIPES_PER_PLANE; i++) { + pipe = &pstate->pipe[i]; + pipe_cfg = &pstate->pipe_cfg[i]; + if (!pipe->sspp) + continue; + DPU_DEBUG_PLANE(pdpu, "pipe %d is in use, validate it\n", i); + ret = dpu_plane_atomic_check_pipe(pdpu, pipe, pipe_cfg, &crtc_state->adjusted_mode, new_plane_state); if (ret)