* [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+
@ 2024-12-17 0:43 Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
` (27 more replies)
0 siblings, 28 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
DPU supports a single writeback session running concurrently with primary
display when the CWB mux is configured properly. This series enables
clone mode for DPU driver and adds support for programming the CWB mux
in cases where the hardware has dedicated CWB pingpong blocks. Currently,
the CWB hardware blocks have only been added to the SM8650
hardware catalog and only DSI has been exposed as a possible_clone of WB.
This changes are split into two parts:
The first part of the series will pull in Dmitry's patches to refactor
the DPU resource manager to be based off of CRTC instead of encoder.
This includes some changes (noted in the relevant commits) by me and
Abhinav to fix some issues with getting the global state and refactoring
the CDM allocation to work with Dmitry's changes.
The second part of the series will add support for CWB by doing the
following:
1) Add a DRM helper to detect if the current CRTC state is in clone mode
and add an "in_clone_mode" entry to the atomic state print
2) Add the CWB mux to the hardware catalog and clarify the pingpong
block index enum to specifiy which pingpong blocks are dedicated to
CWB only and which ones are general use pingpong blocks
3) Add CWB as part of the devcoredump
4) Add support for configuring the CWB mux via dpu_hw_cwb ops
5) Add pending flush support for CWB
6) Add support for validating clone mode in the DPU CRTC and setting up
CWB within the encoder
7) Adjust the encoder trigger flush, trigger start, and kickoff order to
accomodate clone mode
8) Adjust when the frame done timer is started for clone mode
9) Define the possible clones for DPU encoders so that
The feature was tested on SM8650 using IGT's kms_writeback test with the
following change [1] and dumping the writeback framebuffer when in clone
mode. I haven't gotten the chance to test it on DP yet, but I've
validated both single and dual LM on DSI.
To test CWB with IGT, you'll need to apply this series [1] and this
driver patch [2]. Run the following command to dump the writeback buffer:
IGT_FRAME_DUMP_PATH=<dump path> FRAME_PNG_FILE_NAME=<file name> \
./build/tests/kms_writeback -d [--run-subtest dump-valid-clones] \
You can also do CRC validation by running this command:
./build/tests/kms_writeback [--run-subtest dump-valid-clones]
[1] https://patchwork.freedesktop.org/series/137933/
[2] https://patchwork.freedesktop.org/series/138284/
---
Changes in v4:
- Rebased onto latest msm-next
- Added kunit tests for framework changes
- Skip valid clone check for encoders that don't have any possible clones set
(this is to avoid failing kunit tests, specifically the HDMI state helper tests)
- Link to v3: https://lore.kernel.org/r/20241016-concurrent-wb-v3-0-a33cf9b93835@quicinc.com
Changes in v3:
- Dropped support for CWB on DP connectors for now
- Dropped unnecessary PINGPONG array in *_setup_cwb()
- Add a check to make sure CWB and CDM aren't supported simultaneously
(Dmitry)
- Document cwb_enabled checks in dpu_crtc_get_topology() (Dmitry)
- Moved implementation of drm_crtc_in_clone_mode() to drm_crtc.c (Jani)
- Dropped duplicate error message for reserving CWB resources (Dmitry)
- Added notes in framework changes about posting a separate series to
add proper KUnit tests (Maxime)
- Added commit message note addressing Sima's comment on handling
mode_changed (Dmitry)
- Formatting fixes (Dmitry)
- Added proper kerneldocs (Dmitry)
- Renamed dpu_encoder_helper_get_cwb() -> *_get_cwb_mask() (Dmitry)
- Capitalize all instances of "pingpong" in comments (Dmitry)
- Link to v2: https://lore.kernel.org/r/20240924-concurrent-wb-v2-0-7849f900e863@quicinc.com
Changes in v2:
- Moved CWB hardware programming to its own dpu_hw_cwb abstraction
(Dmitry)
- Reserve and get assigned CWB muxes using RM API and KMS global state
(Dmitry)
- Dropped requirement to have only one CWB session at a time
- Moved valid clone mode check to DRM framework (Dmitry and Ville)
- Switch to default CWB tap point to LM as the DSPP
- Dropped printing clone mode status in atomic state (Dmitry)
- Call dpu_vbif_clear_errors() before dpu_encoder_kickoff() (Dmitry)
- Squashed setup_input_ctrl() and setup_input_mode() into a single
dpu_hw_cwb op (Dmitry)
- Moved function comment docs to correct place and fixed wording of
comments/commit messages (Dmitry)
- Grabbed old CRTC state using proper drm_atomic_state API in
dpu_crtc_atomic_check() (Dmitry)
- Split HW catalog changes of adding the CWB mux block and changing the
dedicated CWB pingpong indices into 2 separate commits (Dmitry)
- Moved clearing the dpu_crtc_state.num_mixers to "drm/msm/dpu: fill
CRTC resources in dpu_crtc.c" (Dmitry)
- Fixed alignment and other formatting issues (Dmitry)
- Link to v1: https://lore.kernel.org/r/20240829-concurrent-wb-v1-0-502b16ae2ebb@quicinc.com
---
Dmitry Baryshkov (4):
drm/msm/dpu: get rid of struct dpu_rm_requirements
drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
drm/msm/dpu: move resource allocation to CRTC
drm/msm/dpu: fill CRTC resources in dpu_crtc.c
Esha Bharadwaj (3):
drm/msm/dpu: Add CWB entry to catalog for SM8650
drm/msm/dpu: add devcoredumps for cwb registers
drm/msm/dpu: add CWB support to dpu_hw_wb
Jessica Zhang (18):
drm: add clone mode check for CRTC
drm/tests: Add test for drm_crtc_in_clone_mode()
drm: Add valid clones check
drm/tests: Add test for drm_atomic_helper_check_modeset()
drm/msm/dpu: Specify dedicated CWB pingpong blocks
drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block
drm/msm/dpu: Add RM support for allocating CWB
drm/msm/dpu: Add CWB to msm_display_topology
drm/msm/dpu: Require modeset if clone mode status changes
drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
drm/msm/dpu: Reserve resources for CWB
drm/msm/dpu: Configure CWB in writeback encoder
drm/msm/dpu: Support CWB in dpu_hw_ctl
drm/msm/dpu: Adjust writeback phys encoder setup for CWB
drm/msm/dpu: Start frame done timer after encoder kickoff
drm/msm/dpu: Skip trigger flush and start for CWB
drm/msm/dpu: Reorder encoder kickoff for CWB
drm/msm/dpu: Set possible clones for all encoders
drivers/gpu/drm/drm_atomic_helper.c | 28 ++
drivers/gpu/drm/drm_crtc.c | 20 +
drivers/gpu/drm/msm/Makefile | 1 +
.../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +-
.../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 4 +-
.../drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 4 +-
.../gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 4 +-
.../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 4 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 208 ++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 463 ++++++++++++---------
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 14 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 7 +-
.../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 16 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 13 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 15 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c | 73 ++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h | 70 ++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 15 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 4 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 13 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 361 +++++++++-------
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 13 +-
drivers/gpu/drm/tests/drm_atomic_state_test.c | 133 +++++-
include/drm/drm_crtc.h | 2 +-
26 files changed, 1172 insertions(+), 384 deletions(-)
---
base-commit: 86313a9cd152330c634b25d826a281c6a002eb77
change-id: 20240618-concurrent-wb-97d62387f952
prerequisite-change-id: 20241209-abhinavk-modeset-fix-74864f1de08d:v3
prerequisite-patch-id: a197a0cd4647cb189ea20a96583ea78d0c98b638
prerequisite-patch-id: 112c8f1795cbed989beb02b72561854c0ccd59dd
Best regards,
--
Jessica Zhang <quic_jesszhan@quicinc.com>
^ permalink raw reply [flat|nested] 77+ messages in thread
* [PATCH v4 01/25] drm: add clone mode check for CRTC
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 1:49 ` Abhinav Kumar
2024-12-17 17:16 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode() Jessica Zhang
` (26 subsequent siblings)
27 siblings, 2 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add a common helper to check if the given CRTC state is in clone mode.
This can be used by drivers to help detect if a CRTC is being shared by
multiple encoders
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/drm_crtc.c | 20 ++++++++++++++++++++
include/drm/drm_crtc.h | 2 +-
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 3488ff067c69bb820b36177c97bc9fe5d5cbfea1..46655339003db2a1b43441434839e26f61d79b4e 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -939,3 +939,23 @@ int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
return 0;
}
EXPORT_SYMBOL(drm_crtc_create_scaling_filter_property);
+
+/**
+ * drm_crtc_in_clone_mode - check if the given CRTC state is in clone mode
+ *
+ * @crtc_state: CRTC state to check
+ *
+ * This function determines if the given CRTC state is being cloned by multiple
+ * encoders.
+ *
+ * RETURNS:
+ * True if the CRTC state is in clone mode. False otherwise
+ */
+bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state)
+{
+ if (!crtc_state)
+ return false;
+
+ return hweight32(crtc_state->encoder_mask) > 1;
+}
+EXPORT_SYMBOL(drm_crtc_in_clone_mode);
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8b48a1974da3143c7de176e6fe3e01da9c8fc9d8..caa56e039da2a748cf40ebf45b37158acda439d9 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1323,5 +1323,5 @@ static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
int drm_crtc_create_scaling_filter_property(struct drm_crtc *crtc,
unsigned int supported_filters);
-
+bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state);
#endif /* __DRM_CRTC_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode()
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 2:06 ` Abhinav Kumar
2024-12-17 17:17 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 03/25] drm: Add valid clones check Jessica Zhang
` (25 subsequent siblings)
27 siblings, 2 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add kunit test to validate drm_crtc_in_clone_mode() helper
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/tests/drm_atomic_state_test.c | 62 ++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c
index be1f780249450ead7fbfd19ea98c96b442a94478..79bc5a9aedbf77aaf4b369a5fe62b6344e6859cf 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c
@@ -17,6 +17,12 @@
#define DRM_TEST_CONN_0 BIT(0)
+struct drm_clone_mode_test {
+ const char *name;
+ u32 encoder_mask;
+ int expected_result;
+};
+
static const struct drm_display_mode drm_atomic_test_mode = {
DRM_MODE("1024x768", 0, 65000, 1024, 1048,
1184, 1344, 0, 768, 771, 777, 806, 0,
@@ -227,17 +233,71 @@ static void drm_test_check_connector_changed_modeset(struct kunit *test)
KUNIT_ASSERT_EQ(test, modeset_counter, initial_modeset_count + 1);
}
+/*
+ * Test that the drm_crtc_in_clone_mode() helper can detect if a given CRTC
+ * state is in clone mode
+ */
+static void drm_test_check_in_clone_mode(struct kunit *test)
+{
+ bool ret;
+ const struct drm_clone_mode_test *param = test->param_value;
+ struct drm_crtc_state *crtc_state;
+
+ crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, crtc_state);
+
+ crtc_state->encoder_mask = param->encoder_mask;
+
+ ret = drm_crtc_in_clone_mode(crtc_state);
+
+ KUNIT_ASSERT_EQ(test, ret, param->expected_result);
+}
+
+static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t,
+ char *desc)
+{
+ sprintf(desc, "%s", t->name);
+}
+
+static const struct drm_clone_mode_test drm_clone_mode_tests[] = {
+ {
+ .name = "in_clone_mode",
+ .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1,
+ .expected_result = true,
+ },
+ {
+ .name = "not_in_clone_mode",
+ .encoder_mask = DRM_TEST_ENC_0,
+ .expected_result = false,
+ },
+};
+
+KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests,
+ drm_check_in_clone_mode_desc);
+
static struct kunit_case drm_test_check_modeset_test[] = {
KUNIT_CASE(drm_test_check_connector_changed_modeset),
{}
};
+static struct kunit_case drm_in_clone_mode_check_test[] = {
+ KUNIT_CASE_PARAM(drm_test_check_in_clone_mode,
+ drm_check_in_clone_mode_gen_params),
+ {}
+};
+
static struct kunit_suite drm_test_check_modeset_test_suite = {
.name = "drm_validate_modeset",
.test_cases = drm_test_check_modeset_test,
};
-kunit_test_suite(drm_test_check_modeset_test_suite);
+static struct kunit_suite drm_in_clone_mode_check_test_suite = {
+ .name = "drm_validate_clone_mode",
+ .test_cases = drm_in_clone_mode_check_test,
+};
+
+kunit_test_suites(&drm_in_clone_mode_check_test_suite,
+ &drm_test_check_modeset_test_suite);
MODULE_AUTHOR("Jessica Zhang <quic_jesszhan@quicinc.com");
MODULE_DESCRIPTION("Test cases for the drm_atomic_helper functions");
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 03/25] drm: Add valid clones check
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode() Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 17:17 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset() Jessica Zhang
` (24 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Check that all encoders attached to a given CRTC are valid
possible_clones of each other.
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/drm_atomic_helper.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c
index 32902f77f00dd8b85f03811e6d6da99b6d538afe..40e4e1b6c9110677c1c4981eeb15dc93966f4cf6 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -574,6 +574,30 @@ mode_valid(struct drm_atomic_state *state)
return 0;
}
+static int drm_atomic_check_valid_clones(struct drm_atomic_state *state,
+ struct drm_crtc *crtc)
+{
+ struct drm_encoder *drm_enc;
+ struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
+ crtc);
+
+ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
+ if (!drm_enc->possible_clones) {
+ DRM_DEBUG("enc%d possible_clones is 0\n", drm_enc->base.id);
+ continue;
+ }
+
+ if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
+ crtc_state->encoder_mask) {
+ DRM_DEBUG("crtc%d failed valid clone check for mask 0x%x\n",
+ crtc->base.id, crtc_state->encoder_mask);
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
/**
* drm_atomic_helper_check_modeset - validate state object for modeset changes
* @dev: DRM device
@@ -745,6 +769,10 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
ret = drm_atomic_add_affected_planes(state, crtc);
if (ret != 0)
return ret;
+
+ ret = drm_atomic_check_valid_clones(state, crtc);
+ if (ret != 0)
+ return ret;
}
/*
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset()
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (2 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 03/25] drm: Add valid clones check Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 12:14 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
` (23 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add a test for drm_atomic_check_modeset() specifically to validate
drm_atomic_check_valid_clones() helper
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/tests/drm_atomic_state_test.c | 71 +++++++++++++++++++++++++++
1 file changed, 71 insertions(+)
diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c
index 79bc5a9aedbf77aaf4b369a5fe62b6344e6859cf..0ab5d9ec4a7503d0a96cd21d40817c35fdbcea24 100644
--- a/drivers/gpu/drm/tests/drm_atomic_state_test.c
+++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c
@@ -253,12 +253,59 @@ static void drm_test_check_in_clone_mode(struct kunit *test)
KUNIT_ASSERT_EQ(test, ret, param->expected_result);
}
+/*
+ * Test that the atomic commit path will succeed for valid clones (or non-cloned
+ * states) and fail for states where the cloned encoders are not possible_clones
+ * of each other.
+ */
+static void drm_test_check_valid_clones(struct kunit *test)
+{
+ int ret;
+ const struct drm_clone_mode_test *param = test->param_value;
+ struct drm_atomic_test_priv *priv;
+ struct drm_modeset_acquire_ctx *ctx;
+ struct drm_device *drm;
+ struct drm_atomic_state *state;
+ struct drm_crtc_state *crtc_state;
+
+ priv = drm_atomic_test_init_drm_components(test, false);
+ KUNIT_ASSERT_NOT_NULL(test, priv);
+
+ drm = &priv->drm;
+
+ ctx = drm_kunit_helper_acquire_ctx_alloc(test);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, ctx);
+
+ ret = set_up_atomic_state(test, priv, NULL, ctx);
+ KUNIT_ASSERT_EQ(test, ret, 0);
+
+ state = drm_kunit_helper_atomic_state_alloc(test, drm, ctx);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, state);
+
+ crtc_state = drm_atomic_get_crtc_state(state, priv->crtc);
+ KUNIT_ASSERT_NOT_NULL(test, crtc_state);
+
+ crtc_state->encoder_mask = param->encoder_mask;
+
+ // force modeset
+ crtc_state->mode_changed = true;
+
+ ret = drm_atomic_helper_check_modeset(drm, state);
+ KUNIT_ASSERT_EQ(test, ret, param->expected_result);
+}
+
static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t,
char *desc)
{
sprintf(desc, "%s", t->name);
}
+static void drm_check_valid_clones_desc(const struct drm_clone_mode_test *t,
+ char *desc)
+{
+ sprintf(desc, "%s", t->name);
+}
+
static const struct drm_clone_mode_test drm_clone_mode_tests[] = {
{
.name = "in_clone_mode",
@@ -272,9 +319,31 @@ static const struct drm_clone_mode_test drm_clone_mode_tests[] = {
},
};
+static const struct drm_clone_mode_test drm_valid_clone_mode_tests[] = {
+ {
+ .name = "not_in_clone_mode",
+ .encoder_mask = DRM_TEST_ENC_0,
+ .expected_result = 0,
+ },
+
+ {
+ .name = "valid_clone",
+ .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1,
+ .expected_result = 0,
+ },
+ {
+ .name = "invalid_clone",
+ .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_2,
+ .expected_result = -EINVAL,
+ },
+};
+
KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests,
drm_check_in_clone_mode_desc);
+KUNIT_ARRAY_PARAM(drm_check_valid_clones, drm_valid_clone_mode_tests,
+ drm_check_valid_clones_desc);
+
static struct kunit_case drm_test_check_modeset_test[] = {
KUNIT_CASE(drm_test_check_connector_changed_modeset),
{}
@@ -283,6 +352,8 @@ static struct kunit_case drm_test_check_modeset_test[] = {
static struct kunit_case drm_in_clone_mode_check_test[] = {
KUNIT_CASE_PARAM(drm_test_check_in_clone_mode,
drm_check_in_clone_mode_gen_params),
+ KUNIT_CASE_PARAM(drm_test_check_valid_clones,
+ drm_check_valid_clones_gen_params),
{}
};
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (3 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset() Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 1:26 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
` (22 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
The struct dpu_rm_requirements was used to wrap display topology and
hw resources, which meant INTF indices. As of commit ef58e0ad3436
("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
resources struct was removed, leaving struct dpu_rm_requirements
containing a single field (topology). Remove the useless wrapper.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 71 ++++++++++-------------------
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 +-
3 files changed, 25 insertions(+), 50 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 83de7564e2c1fe14fcf8c4f82335cafc937e1b99..5172ab4dea995a154cd88d05c3842d7425fc34ce 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -800,7 +800,7 @@ 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);
+ drm_enc, crtc_state, &topology);
if (!ret)
dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
global_state, crtc_state);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index c247af03dc8ef7174eedf3d5cc267d64f17a8656..cd5960af4a151428cc6fb7154c3ffdb65ebcf287 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -5,6 +5,7 @@
*/
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
+#include "msm_drv.h"
#include "dpu_kms.h"
#include "dpu_hw_lm.h"
#include "dpu_hw_ctl.h"
@@ -26,14 +27,6 @@ static inline bool reserved_by_other(uint32_t *res_map, int idx,
return res_map[idx] && res_map[idx] != enc_id;
}
-/**
- * struct dpu_rm_requirements - Reservation requirements parameter bundle
- * @topology: selected topology for the display
- */
-struct dpu_rm_requirements {
- struct msm_display_topology topology;
-};
-
/**
* dpu_rm_init - Read hardware catalog and create reservation tracking objects
* for all HW blocks.
@@ -241,14 +234,13 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
* mixer in rm->pingpong_blks[].
* @dspp_idx: output parameter, index of dspp block attached to the layer
* mixer in rm->dspp_blks[].
- * @reqs: input parameter, rm requirements for HW blocks needed in the
- * datapath.
+ * @topology: selected topology for the display
* Return: true if lm matches all requirements, false otherwise
*/
static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
struct dpu_global_state *global_state,
uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
- struct dpu_rm_requirements *reqs)
+ struct msm_display_topology *topology)
{
const struct dpu_lm_cfg *lm_cfg;
int idx;
@@ -273,7 +265,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
}
*pp_idx = idx;
- if (!reqs->topology.num_dspp)
+ if (!topology->num_dspp)
return true;
idx = lm_cfg->dspp - DSPP_0;
@@ -295,7 +287,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
struct dpu_global_state *global_state,
uint32_t enc_id,
- struct dpu_rm_requirements *reqs)
+ struct msm_display_topology *topology)
{
int lm_idx[MAX_BLOCKS];
@@ -303,14 +295,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
int dspp_idx[MAX_BLOCKS] = {0};
int i, lm_count = 0;
- if (!reqs->topology.num_lm) {
- DPU_ERROR("invalid number of lm: %d\n", reqs->topology.num_lm);
+ if (!topology->num_lm) {
+ DPU_ERROR("invalid number of lm: %d\n", topology->num_lm);
return -EINVAL;
}
/* Find a primary mixer */
for (i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
- lm_count < reqs->topology.num_lm; i++) {
+ lm_count < topology->num_lm; i++) {
if (!rm->mixer_blks[i])
continue;
@@ -319,14 +311,14 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
enc_id, i, &pp_idx[lm_count],
- &dspp_idx[lm_count], reqs)) {
+ &dspp_idx[lm_count], topology)) {
continue;
}
++lm_count;
/* Valid primary mixer found, find matching peers */
- if (lm_count < reqs->topology.num_lm) {
+ if (lm_count < topology->num_lm) {
int j = _dpu_rm_get_lm_peer(rm, i);
/* ignore the peer if there is an error or if the peer was already processed */
@@ -339,7 +331,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
global_state, enc_id, j,
&pp_idx[lm_count], &dspp_idx[lm_count],
- reqs)) {
+ topology)) {
continue;
}
@@ -348,7 +340,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
}
}
- if (lm_count != reqs->topology.num_lm) {
+ if (lm_count != topology->num_lm) {
DPU_DEBUG("unable to find appropriate mixers\n");
return -ENAVAIL;
}
@@ -357,7 +349,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
global_state->dspp_to_enc_id[dspp_idx[i]] =
- reqs->topology.num_dspp ? enc_id : 0;
+ topology->num_dspp ? enc_id : 0;
trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
pp_idx[i] + PINGPONG_0);
@@ -594,28 +586,28 @@ static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
struct drm_encoder *enc,
- struct dpu_rm_requirements *reqs)
+ struct msm_display_topology *topology)
{
int ret;
- ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, reqs);
+ ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
if (ret) {
DPU_ERROR("unable to find appropriate mixers\n");
return ret;
}
ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
- &reqs->topology);
+ topology);
if (ret) {
DPU_ERROR("unable to find appropriate CTL\n");
return ret;
}
- ret = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+ ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
if (ret)
return ret;
- if (reqs->topology.needs_cdm) {
+ if (topology->needs_cdm) {
ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
if (ret) {
DPU_ERROR("unable to find CDM blk\n");
@@ -626,20 +618,6 @@ static int _dpu_rm_make_reservation(
return ret;
}
-static int _dpu_rm_populate_requirements(
- struct drm_encoder *enc,
- struct dpu_rm_requirements *reqs,
- struct msm_display_topology req_topology)
-{
- reqs->topology = req_topology;
-
- DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d cdm: %d\n",
- reqs->topology.num_lm, reqs->topology.num_dsc,
- reqs->topology.num_intf, reqs->topology.needs_cdm);
-
- return 0;
-}
-
static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
uint32_t enc_id)
{
@@ -693,9 +671,8 @@ int dpu_rm_reserve(
struct dpu_global_state *global_state,
struct drm_encoder *enc,
struct drm_crtc_state *crtc_state,
- struct msm_display_topology topology)
+ struct msm_display_topology *topology)
{
- struct dpu_rm_requirements reqs;
int ret;
/* Check if this is just a page-flip */
@@ -710,13 +687,11 @@ int dpu_rm_reserve(
DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
enc->base.id, crtc_state->crtc->base.id);
- ret = _dpu_rm_populate_requirements(enc, &reqs, topology);
- if (ret) {
- DPU_ERROR("failed to populate hw requirements\n");
- return ret;
- }
+ DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
+ topology->num_lm, topology->num_dsc,
+ topology->num_intf);
- ret = _dpu_rm_make_reservation(rm, global_state, enc, &reqs);
+ ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
if (ret)
DPU_ERROR("failed to reserve hw resources: %d\n", ret);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index ea0e49cb7b0d3e05dfa57442784c83acb69c3ada..2240275080c4e97e91f52eae329a3457ec2bc538 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -63,7 +63,7 @@ int dpu_rm_reserve(struct dpu_rm *rm,
struct dpu_global_state *global_state,
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
- struct msm_display_topology topology);
+ struct msm_display_topology *topology);
void dpu_rm_release(struct dpu_global_state *global_state,
struct drm_encoder *enc);
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (4 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-24 4:45 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
` (21 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Up to now the driver has been using encoder to allocate hardware
resources. Switch it to use CRTC id in preparation for the next step.
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
Changes in v4 (due to rebase):
- moved *_get_assigned_resources() changes for DSPP and LM from
encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
4 files changed, 110 insertions(+), 118 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
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));
+ drm_enc->crtc, 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));
+ drm_enc->crtc, 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,
+ drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
ARRAY_SIZE(hw_dspp));
for (i = 0; i < num_lm; i++) {
@@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
* Dont allocate when active is false.
*/
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
- dpu_rm_release(global_state, drm_enc);
+ dpu_rm_release(global_state, crtc_state->crtc);
if (!crtc_state->active_changed || crtc_state->enable)
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
- drm_enc, crtc_state, &topology);
+ crtc_state->crtc, &topology);
if (!ret)
dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
global_state, crtc_state);
@@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
/* Query resource that have been reserved in atomic check step. */
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
+ drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
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));
+ drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->base.id, DPU_HW_BLK_DSC,
+ drm_enc->crtc, DPU_HW_BLK_DSC,
hw_dsc, ARRAY_SIZE(hw_dsc));
for (i = 0; i < num_dsc; i++) {
dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
@@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
struct dpu_hw_blk *hw_cdm = NULL;
dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->base.id, DPU_HW_BLK_CDM,
+ drm_enc->crtc, DPU_HW_BLK_CDM,
&hw_cdm, 1);
dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
}
@@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
- phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
+ phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
for (i = 0; i < num_lm; i++) {
hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -122,12 +122,12 @@ struct dpu_global_state {
struct dpu_rm *rm;
- uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
- uint32_t mixer_to_enc_id[LM_MAX - LM_0];
- uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
- uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
- uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
- uint32_t cdm_to_enc_id;
+ uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
+ uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
+ uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
+ uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
+ uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
+ uint32_t cdm_to_crtc_id;
};
struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -22,9 +22,9 @@
static inline bool reserved_by_other(uint32_t *res_map, int idx,
- uint32_t enc_id)
+ uint32_t crtc_id)
{
- return res_map[idx] && res_map[idx] != enc_id;
+ return res_map[idx] && res_map[idx] != crtc_id;
}
/**
@@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
* pingpong
* @rm: dpu resource manager handle
* @global_state: resources shared across multiple kms objects
- * @enc_id: encoder id requesting for allocation
+ * @crtc_id: crtc id requesting for allocation
* @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
* if lm, and all other hardwired blocks connected to the lm (pp) is
* available and appropriate
@@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
*/
static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
+ uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
struct msm_display_topology *topology)
{
const struct dpu_lm_cfg *lm_cfg;
int idx;
/* Already reserved? */
- if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
+ if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
return false;
}
@@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
return false;
}
- if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
+ if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
lm_cfg->pingpong);
return false;
@@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
return false;
}
- if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
+ if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
lm_cfg->dspp);
return false;
@@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- uint32_t enc_id,
+ uint32_t crtc_id,
struct msm_display_topology *topology)
{
@@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
lm_idx[lm_count] = i;
if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
- enc_id, i, &pp_idx[lm_count],
+ crtc_id, i, &pp_idx[lm_count],
&dspp_idx[lm_count], topology)) {
continue;
}
@@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
continue;
if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
- global_state, enc_id, j,
+ global_state, crtc_id, j,
&pp_idx[lm_count], &dspp_idx[lm_count],
topology)) {
continue;
@@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
}
for (i = 0; i < lm_count; i++) {
- global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
- global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
- global_state->dspp_to_enc_id[dspp_idx[i]] =
- topology->num_dspp ? enc_id : 0;
+ global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
+ global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
+ global_state->dspp_to_crtc_id[dspp_idx[i]] =
+ topology->num_dspp ? crtc_id : 0;
- trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
+ trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
pp_idx[i] + PINGPONG_0);
}
@@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
static int _dpu_rm_reserve_ctls(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
- uint32_t enc_id,
+ uint32_t crtc_id,
const struct msm_display_topology *top)
{
int ctl_idx[MAX_BLOCKS];
@@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
if (!rm->ctl_blks[j])
continue;
- if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
+ if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
continue;
ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
@@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
return -ENAVAIL;
for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
- global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
- trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
+ global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
+ trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
}
return 0;
@@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
int start,
- uint32_t enc_id)
+ uint32_t crtc_id)
{
int i;
for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
- if (global_state->pingpong_to_enc_id[i] == enc_id)
+ if (global_state->pingpong_to_crtc_id[i] == crtc_id)
return i;
}
@@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- uint32_t enc_id,
+ uint32_t crtc_id,
const struct msm_display_topology *top)
{
int num_dsc = 0;
@@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
if (!rm->dsc_blks[dsc_idx])
continue;
- if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
+ if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
continue;
- pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
+ pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
if (pp_idx < 0)
return -ENAVAIL;
@@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
if (ret)
return -ENAVAIL;
- global_state->dsc_to_enc_id[dsc_idx] = enc_id;
+ global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
num_dsc++;
pp_idx++;
}
@@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- uint32_t enc_id,
+ uint32_t crtc_id,
const struct msm_display_topology *top)
{
int num_dsc = 0;
@@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
continue;
/* consective dsc index to be paired */
- if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
- reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
+ if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
+ reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
continue;
- pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
+ pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
if (pp_idx < 0)
return -ENAVAIL;
@@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
continue;
}
- pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
+ pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
if (pp_idx < 0)
return -ENAVAIL;
@@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
continue;
}
- global_state->dsc_to_enc_id[dsc_idx] = enc_id;
- global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
+ global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
+ global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
num_dsc += 2;
pp_idx++; /* start for next pair */
}
@@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- struct drm_encoder *enc,
+ uint32_t crtc_id,
const struct msm_display_topology *top)
{
- uint32_t enc_id = enc->base.id;
-
if (!top->num_dsc || !top->num_intf)
return 0;
@@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
/* num_dsc should be either 1, 2 or 4 */
if (top->num_dsc > top->num_intf) /* merge mode */
- return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
+ return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
else
- return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
+ return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
return 0;
}
static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- struct drm_encoder *enc)
+ uint32_t crtc_id)
{
/* try allocating only one CDM block */
if (!rm->cdm_blk) {
@@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
return -EIO;
}
- if (global_state->cdm_to_enc_id) {
+ if (global_state->cdm_to_crtc_id) {
DPU_ERROR("CDM_0 is already allocated\n");
return -EIO;
}
- global_state->cdm_to_enc_id = enc->base.id;
+ global_state->cdm_to_crtc_id = crtc_id;
return 0;
}
@@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
- struct drm_encoder *enc,
+ uint32_t crtc_id,
struct msm_display_topology *topology)
{
int ret;
- ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
+ ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
if (ret) {
DPU_ERROR("unable to find appropriate mixers\n");
return ret;
}
- ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
+
+ ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
topology);
if (ret) {
DPU_ERROR("unable to find appropriate CTL\n");
return ret;
}
- ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
+ ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
if (ret)
return ret;
if (topology->needs_cdm) {
- ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
+ ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
if (ret) {
DPU_ERROR("unable to find CDM blk\n");
return ret;
@@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
}
static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
- uint32_t enc_id)
+ uint32_t crtc_id)
{
int i;
for (i = 0; i < cnt; i++) {
- if (res_mapping[i] == enc_id)
+ if (res_mapping[i] == crtc_id)
res_mapping[i] = 0;
}
}
@@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
* dpu_rm_release - Given the encoder for the display chain, release any
* HW blocks previously reserved for that use case.
* @global_state: resources shared across multiple kms objects
- * @enc: DRM Encoder handle
+ * @crtc: DRM CRTC handle
* @return: 0 on Success otherwise -ERROR
*/
void dpu_rm_release(struct dpu_global_state *global_state,
- struct drm_encoder *enc)
+ struct drm_crtc *crtc)
{
- _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
- ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
- ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
- ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
- ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
- ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
- _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
+ uint32_t crtc_id = crtc->base.id;
+
+ _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
+ ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
+ _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
+ ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
+ _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
+ ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
+ _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
+ ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
+ _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
+ ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
+ _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
}
/**
@@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
* HW Reservations should be released via dpu_rm_release_hw.
* @rm: DPU Resource Manager handle
* @global_state: resources shared across multiple kms objects
- * @enc: DRM Encoder handle
- * @crtc_state: Proposed Atomic DRM CRTC State handle
+ * @crtc: DRM CRTC handle
* @topology: Pointer to topology info for the display
* @return: 0 on Success otherwise -ERROR
*/
int dpu_rm_reserve(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
- struct drm_encoder *enc,
- struct drm_crtc_state *crtc_state,
+ struct drm_crtc *crtc,
struct msm_display_topology *topology)
{
int ret;
- /* Check if this is just a page-flip */
- if (!drm_atomic_crtc_needs_modeset(crtc_state))
- return 0;
-
if (IS_ERR(global_state)) {
DPU_ERROR("failed to global state\n");
return PTR_ERR(global_state);
}
- DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
- enc->base.id, crtc_state->crtc->base.id);
+ DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
topology->num_lm, topology->num_dsc,
topology->num_intf);
- ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
+ ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
if (ret)
DPU_ERROR("failed to reserve hw resources: %d\n", ret);
-
-
return ret;
}
@@ -705,48 +697,49 @@ int dpu_rm_reserve(
* assigned to this encoder
* @rm: DPU Resource Manager handle
* @global_state: resources shared across multiple kms objects
- * @enc_id: encoder id requesting for allocation
+ * @crtc: DRM CRTC handle
* @type: resource type to return data for
* @blks: pointer to the array to be filled by HW resources
* @blks_size: size of the @blks array
*/
int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
- struct dpu_global_state *global_state, uint32_t enc_id,
+ struct dpu_global_state *global_state, struct drm_crtc *crtc,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
{
+ uint32_t crtc_id = crtc->base.id;
struct dpu_hw_blk **hw_blks;
- uint32_t *hw_to_enc_id;
+ uint32_t *hw_to_crtc_id;
int i, num_blks, max_blks;
switch (type) {
case DPU_HW_BLK_PINGPONG:
hw_blks = rm->pingpong_blks;
- hw_to_enc_id = global_state->pingpong_to_enc_id;
+ hw_to_crtc_id = global_state->pingpong_to_crtc_id;
max_blks = ARRAY_SIZE(rm->pingpong_blks);
break;
case DPU_HW_BLK_LM:
hw_blks = rm->mixer_blks;
- hw_to_enc_id = global_state->mixer_to_enc_id;
+ hw_to_crtc_id = global_state->mixer_to_crtc_id;
max_blks = ARRAY_SIZE(rm->mixer_blks);
break;
case DPU_HW_BLK_CTL:
hw_blks = rm->ctl_blks;
- hw_to_enc_id = global_state->ctl_to_enc_id;
+ hw_to_crtc_id = global_state->ctl_to_crtc_id;
max_blks = ARRAY_SIZE(rm->ctl_blks);
break;
case DPU_HW_BLK_DSPP:
hw_blks = rm->dspp_blks;
- hw_to_enc_id = global_state->dspp_to_enc_id;
+ hw_to_crtc_id = global_state->dspp_to_crtc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks);
break;
case DPU_HW_BLK_DSC:
hw_blks = rm->dsc_blks;
- hw_to_enc_id = global_state->dsc_to_enc_id;
+ hw_to_crtc_id = global_state->dsc_to_crtc_id;
max_blks = ARRAY_SIZE(rm->dsc_blks);
break;
case DPU_HW_BLK_CDM:
hw_blks = &rm->cdm_blk;
- hw_to_enc_id = &global_state->cdm_to_enc_id;
+ hw_to_crtc_id = &global_state->cdm_to_crtc_id;
max_blks = 1;
break;
default:
@@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
num_blks = 0;
for (i = 0; i < max_blks; i++) {
- if (hw_to_enc_id[i] != enc_id)
+ if (hw_to_crtc_id[i] != crtc_id)
continue;
if (num_blks == blks_size) {
- DPU_ERROR("More than %d resources assigned to enc %d\n",
- blks_size, enc_id);
+ DPU_ERROR("More than %d resources assigned to crtc %d\n",
+ blks_size, crtc_id);
break;
}
if (!hw_blks[i]) {
- DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
- type, enc_id);
+ DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
+ type, crtc_id);
break;
}
blks[num_blks++] = hw_blks[i];
@@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
drm_puts(p, "resource mapping:\n");
drm_puts(p, "\tpingpong=");
- for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
+ for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
- global_state->pingpong_to_enc_id[i]);
+ global_state->pingpong_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tmixer=");
- for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
+ for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->mixer_blks[i],
- global_state->mixer_to_enc_id[i]);
+ global_state->mixer_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tctl=");
- for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
+ for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->ctl_blks[i],
- global_state->ctl_to_enc_id[i]);
+ global_state->ctl_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tdspp=");
- for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
+ for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->dspp_blks[i],
- global_state->dspp_to_enc_id[i]);
+ global_state->dspp_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tdsc=");
- for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
+ for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
dpu_rm_print_state_helper(p, rm->dsc_blks[i],
- global_state->dsc_to_enc_id[i]);
+ global_state->dsc_to_crtc_id[i]);
drm_puts(p, "\n");
drm_puts(p, "\tcdm=");
dpu_rm_print_state_helper(p, rm->cdm_blk,
- global_state->cdm_to_enc_id);
+ global_state->cdm_to_crtc_id);
drm_puts(p, "\n");
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
int dpu_rm_reserve(struct dpu_rm *rm,
struct dpu_global_state *global_state,
- struct drm_encoder *drm_enc,
- struct drm_crtc_state *crtc_state,
+ struct drm_crtc *crtc,
struct msm_display_topology *topology);
void dpu_rm_release(struct dpu_global_state *global_state,
- struct drm_encoder *enc);
+ struct drm_crtc *crtc);
int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
- struct dpu_global_state *global_state, uint32_t enc_id,
+ struct dpu_global_state *global_state, struct drm_crtc *crtc,
enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
void dpu_rm_print_state(struct drm_printer *p,
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (5 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 1:47 ` Abhinav Kumar
2024-12-24 5:02 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
` (20 subsequent siblings)
27 siblings, 2 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
All resource allocation is centered around the LMs. Then other blocks
(except DSCs) are allocated basing on the LMs that was selected, and LM
powers up the CRTC rather than the encoder.
Moreover if at some point the driver supports encoder cloning,
allocating resources from the encoder will be incorrect, as all clones
will have different encoder IDs, while LMs are to be shared by these
encoders.
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
[quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
[quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
3 files changed, 181 insertions(+), 169 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
return false;
}
+#define MAX_HDISPLAY_SPLIT 1080
+
+static struct msm_display_topology dpu_crtc_get_topology(
+ struct drm_crtc *crtc,
+ struct dpu_kms *dpu_kms,
+ struct drm_crtc_state *crtc_state)
+{
+ struct drm_display_mode *mode = &crtc_state->adjusted_mode;
+ struct msm_display_topology topology = {0};
+ struct drm_encoder *drm_enc;
+
+ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
+ dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
+ &crtc_state->adjusted_mode);
+
+ /*
+ * Datapath topology selection
+ *
+ * Dual display
+ * 2 LM, 2 INTF ( Split display using 2 interfaces)
+ *
+ * Single display
+ * 1 LM, 1 INTF
+ * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
+ *
+ * Add dspps to the reservation requirements if ctm is requested
+ */
+
+ if (topology.num_intf == 2)
+ topology.num_lm = 2;
+ else if (topology.num_dsc == 2)
+ topology.num_lm = 2;
+ else if (dpu_kms->catalog->caps->has_3d_merge)
+ topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
+ else
+ topology.num_lm = 1;
+
+ if (crtc_state->ctm)
+ topology.num_dspp = topology.num_lm;
+
+ return topology;
+}
+
+static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
+{
+ struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+ struct dpu_global_state *global_state;
+ struct msm_display_topology topology;
+ int ret;
+
+ /*
+ * Release and Allocate resources on every modeset
+ * Dont allocate when enable is false.
+ */
+ global_state = dpu_kms_get_existing_global_state(dpu_kms);
+ if (IS_ERR(global_state))
+ return PTR_ERR(global_state);
+
+ dpu_rm_release(global_state, crtc);
+
+ if (!crtc_state->enable)
+ return 0;
+
+ topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
+ ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
+ crtc, &topology);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_atomic_state *state)
{
@@ -1193,10 +1265,24 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
const struct drm_plane_state *pstate;
struct drm_plane *plane;
+ struct drm_encoder *drm_enc;
+
int rc = 0;
bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
+ /* there might be cases where encoder needs a modeset too */
+ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
+ if (dpu_encoder_needs_modeset(drm_enc, crtc_state->state))
+ crtc_state->mode_changed = true;
+ }
+
+ if (drm_atomic_crtc_needs_modeset(crtc_state)) {
+ rc = dpu_crtc_assign_resources(crtc, crtc_state);
+ if (rc < 0)
+ return rc;
+ }
+
if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
crtc->base.id, crtc_state->enable,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index e6f930dd34566d01223823de82c922668e6be300..2b999a0558b2a016644ed5d25bf54ab45c38d1d9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -58,8 +58,6 @@
#define IDLE_SHORT_TIMEOUT 1
-#define MAX_HDISPLAY_SPLIT 1080
-
/* timeout in frames waiting for frame done */
#define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
@@ -609,206 +607,127 @@ void dpu_encoder_helper_split_config(
}
}
-/**
- * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
- * @drm_enc: Pointer to previously created drm encoder structure
- */
-bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
+ struct msm_display_topology *topology,
+ struct drm_atomic_state *state,
+ const struct drm_display_mode *adj_mode)
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- int i, intf_count = 0, num_dsc = 0;
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
+ struct msm_display_info *disp_info;
+ struct drm_framebuffer *fb;
+ struct msm_drm_private *priv;
+ int i;
for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
if (dpu_enc->phys_encs[i])
- intf_count++;
+ topology->num_intf++;
- /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
+ /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
if (dpu_enc->dsc)
- num_dsc = 2;
-
- return (num_dsc > 0) && (num_dsc > intf_count);
-}
-
-/**
- * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
- * This helper function is used by physical encoder to get DSC config
- * used for this encoder.
- * @drm_enc: Pointer to encoder structure
- */
-struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
-{
- struct msm_drm_private *priv = drm_enc->dev->dev_private;
- struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- int index = dpu_enc->disp_info.h_tile_instance[0];
+ topology->num_dsc += 2;
- if (dpu_enc->disp_info.intf_type == INTF_DSI)
- return msm_dsi_get_dsc_config(priv->dsi[index]);
+ connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
+ if (!connector)
+ return;
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
+ if (!conn_state)
+ return;
- return NULL;
-}
+ disp_info = &dpu_enc->disp_info;
-static struct msm_display_topology dpu_encoder_get_topology(
- struct dpu_encoder_virt *dpu_enc,
- struct dpu_kms *dpu_kms,
- struct drm_display_mode *mode,
- struct drm_crtc_state *crtc_state,
- struct drm_dsc_config *dsc)
-{
- struct msm_display_topology topology = {0};
- int i, intf_count = 0;
+ priv = drm_enc->dev->dev_private;
- for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
- if (dpu_enc->phys_encs[i])
- intf_count++;
-
- /* Datapath topology selection
- *
- * Dual display
- * 2 LM, 2 INTF ( Split display using 2 interfaces)
- *
- * Single display
- * 1 LM, 1 INTF
- * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
- *
- * Add dspps to the reservation requirements if ctm is requested
+ /*
+ * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
+ * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
+ * earlier.
*/
- if (intf_count == 2)
- topology.num_lm = 2;
- else if (!dpu_kms->catalog->caps->has_3d_merge)
- topology.num_lm = 1;
- else
- topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
-
- if (crtc_state->ctm)
- topology.num_dspp = topology.num_lm;
-
- topology.num_intf = intf_count;
+ if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
+ fb = conn_state->writeback_job->fb;
- if (dsc) {
- /*
- * In case of Display Stream Compression (DSC), we would use
- * 2 DSC encoders, 2 layer mixers and 1 interface
- * this is power optimal and can drive up to (including) 4k
- * screens
- */
- topology.num_dsc = 2;
- topology.num_lm = 2;
- topology.num_intf = 1;
+ if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
+ topology->needs_cdm = true;
+ } else if (disp_info->intf_type == INTF_DP) {
+ if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
+ topology->needs_cdm = true;
}
-
- 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)
+static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
{
- 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
- num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
- num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
- ARRAY_SIZE(hw_dspp));
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+ u32 num_intf = 0;
+ u32 num_dsc = 0;
+ int i;
- for (i = 0; i < num_lm; i++) {
- int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
+ for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
+ if (dpu_enc->phys_encs[i])
+ num_intf++;
- 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;
- }
+ /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
+ if (dpu_enc->dsc)
+ num_dsc += 2;
- cstate->num_mixers = num_lm;
+ return (num_dsc > 0) && (num_dsc > num_intf);
}
-static int dpu_encoder_virt_atomic_check(
- struct drm_encoder *drm_enc,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
+bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state)
{
- struct dpu_encoder_virt *dpu_enc;
- struct msm_drm_private *priv;
- struct dpu_kms *dpu_kms;
- struct drm_display_mode *adj_mode;
- struct msm_display_topology topology;
- struct msm_display_info *disp_info;
- struct dpu_global_state *global_state;
+ struct drm_connector *connector;
+ struct drm_connector_state *conn_state;
struct drm_framebuffer *fb;
- struct drm_dsc_config *dsc;
- int ret = 0;
-
- if (!drm_enc || !crtc_state || !conn_state) {
- DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
- drm_enc != NULL, crtc_state != NULL, conn_state != NULL);
- return -EINVAL;
- }
-
- dpu_enc = to_dpu_encoder_virt(drm_enc);
- DPU_DEBUG_ENC(dpu_enc, "\n");
-
- priv = drm_enc->dev->dev_private;
- disp_info = &dpu_enc->disp_info;
- dpu_kms = to_dpu_kms(priv->kms);
- adj_mode = &crtc_state->adjusted_mode;
- global_state = dpu_kms_get_global_state(crtc_state->state);
- if (IS_ERR(global_state))
- return PTR_ERR(global_state);
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
- trace_dpu_enc_atomic_check(DRMID(drm_enc));
+ if (!drm_enc || !state)
+ return false;
- dsc = dpu_encoder_get_dsc_config(drm_enc);
+ connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
+ if (!connector)
+ return false;
- topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc);
+ conn_state = drm_atomic_get_new_connector_state(state, connector);
- /*
- * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
- * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
- * earlier.
- */
- if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
+ if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
fb = conn_state->writeback_job->fb;
-
- if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
- topology.needs_cdm = true;
- } else if (disp_info->intf_type == INTF_DP) {
- if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
- topology.needs_cdm = true;
+ if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) {
+ if (!dpu_enc->cur_master->hw_cdm)
+ return true;
+ } else {
+ if (dpu_enc->cur_master->hw_cdm)
+ return true;
+ }
}
- if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
- crtc_state->mode_changed = true;
- else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
- crtc_state->mode_changed = true;
- /*
- * Release and Allocate resources on every modeset
- * Dont allocate when active is false.
- */
- if (drm_atomic_crtc_needs_modeset(crtc_state)) {
- dpu_rm_release(global_state, crtc_state->crtc);
+ return false;
+}
- if (!crtc_state->active_changed || crtc_state->enable)
- ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
- crtc_state->crtc, &topology);
- if (!ret)
- dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
- global_state, crtc_state);
- }
+/**
+ * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
+ * This helper function is used by physical encoder to get DSC config
+ * used for this encoder.
+ * @drm_enc: Pointer to encoder structure
+ */
+struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
+{
+ struct msm_drm_private *priv = drm_enc->dev->dev_private;
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
+ int index = dpu_enc->disp_info.h_tile_instance[0];
- trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
+ if (dpu_enc->disp_info.intf_type == INTF_DSI)
+ return msm_dsi_get_dsc_config(priv->dsi[index]);
- return ret;
+ return NULL;
+}
+
+/**
+ * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
+ * @drm_enc: Pointer to previously created drm encoder structure
+ */
+bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
+{
+ return dpu_encoder_needs_dsc_merge(drm_enc);
}
static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
@@ -2627,7 +2546,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
.atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
.atomic_disable = dpu_encoder_virt_atomic_disable,
.atomic_enable = dpu_encoder_virt_atomic_enable,
- .atomic_check = dpu_encoder_virt_atomic_check,
};
static const struct drm_encoder_funcs dpu_encoder_funcs = {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 92b5ee390788d16e85e195a664417896a2bf1cae..3db3ea076c377ad5411ec85006bcf4cd9757eb1d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -11,6 +11,7 @@
#include <drm/drm_crtc.h>
#include "dpu_hw_mdss.h"
+#include "dpu_kms.h"
#define DPU_ENCODER_FRAME_EVENT_DONE BIT(0)
#define DPU_ENCODER_FRAME_EVENT_ERROR BIT(1)
@@ -80,6 +81,13 @@ int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
+void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
+ struct msm_display_topology *topology,
+ struct drm_atomic_state *state,
+ const struct drm_display_mode *adj_mode);
+
+bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
+
void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
struct drm_writeback_job *job);
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (6 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 1:39 ` Abhinav Kumar
2024-12-17 0:43 ` [PATCH v4 09/25] drm/msm/dpu: Add CWB entry to catalog for SM8650 Jessica Zhang
` (19 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Stop poking into CRTC state from dpu_encoder.c, fill CRTC HW resources
from dpu_crtc_assign_resources().
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
[quic_abhinavk@quicinc.com: cleaned up formatting]
Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 +++++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++--
2 files changed, 31 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 186ed84f59f16997716fe216e635b8dce07a63a1..b4bfded3d53025853cee112ca598533ece290318 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1183,6 +1183,7 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
}
#define MAX_HDISPLAY_SPLIT 1080
+#define MAX_CHANNELS_PER_CRTC 2
static struct msm_display_topology dpu_crtc_get_topology(
struct drm_crtc *crtc,
@@ -1227,9 +1228,14 @@ static struct msm_display_topology dpu_crtc_get_topology(
static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
{
+ struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_CRTC];
+ struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_CRTC];
+ struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_CRTC];
+ int i, num_lm, num_ctl, num_dspp;
struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
struct dpu_global_state *global_state;
struct msm_display_topology topology;
+ struct dpu_crtc_state *cstate;
int ret;
/*
@@ -1251,6 +1257,29 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
if (ret)
return ret;
+ cstate = to_dpu_crtc_state(crtc_state);
+
+ num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ crtc, DPU_HW_BLK_CTL, hw_ctl,
+ ARRAY_SIZE(hw_ctl));
+ num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ crtc, DPU_HW_BLK_LM, hw_lm,
+ ARRAY_SIZE(hw_lm));
+ num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ crtc, 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]);
+ if (i < num_dspp)
+ cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
+ }
+
+ cstate->num_mixers = num_lm;
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 2b999a0558b2a016644ed5d25bf54ab45c38d1d9..a895d48fe81ccc71d265e089992786e8b6268b1b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1138,7 +1138,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
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_dsc[MAX_CHANNELS_PER_ENC];
- int num_ctl, num_pp, num_dsc;
+ int num_pp, num_dsc, num_ctl;
unsigned int dsc_mask = 0;
int i;
@@ -1166,7 +1166,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
ARRAY_SIZE(hw_pp));
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
+ drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 09/25] drm/msm/dpu: Add CWB entry to catalog for SM8650
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (7 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 10/25] drm/msm/dpu: Specify dedicated CWB pingpong blocks Jessica Zhang
` (18 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Add a new block for concurrent writeback mux to the SM8650 HW catalog
Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
.../gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 21 +++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 13 +++++++++++++
2 files changed, 34 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
index eb5dfff2ec4f48d793f9d83aafed592d0947f04b..33f5faf4833f7534a1403ccec560fffe8ea0bb1f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
@@ -350,6 +350,25 @@ static const struct dpu_wb_cfg sm8650_wb[] = {
},
};
+static const struct dpu_cwb_cfg sm8650_cwb[] = {
+ {
+ .name = "cwb_0", .id = CWB_0,
+ .base = 0x66200, .len = 0x8,
+ },
+ {
+ .name = "cwb_1", .id = CWB_1,
+ .base = 0x66600, .len = 0x8,
+ },
+ {
+ .name = "cwb_2", .id = CWB_2,
+ .base = 0x7E200, .len = 0x8,
+ },
+ {
+ .name = "cwb_3", .id = CWB_3,
+ .base = 0x7E600, .len = 0x8,
+ },
+};
+
static const struct dpu_intf_cfg sm8650_intf[] = {
{
.name = "intf_0", .id = INTF_0,
@@ -447,6 +466,8 @@ const struct dpu_mdss_cfg dpu_sm8650_cfg = {
.merge_3d = sm8650_merge_3d,
.wb_count = ARRAY_SIZE(sm8650_wb),
.wb = sm8650_wb,
+ .cwb_count = ARRAY_SIZE(sm8650_cwb),
+ .cwb = sm8650_cwb,
.intf_count = ARRAY_SIZE(sm8650_intf),
.intf = sm8650_intf,
.vbif_count = ARRAY_SIZE(sm8650_vbif),
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index c701d18c3522393b7d18d085d6554119f27f737b..a407b522282bf07a12cd3af8febff8d91f52b8da 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -613,6 +613,16 @@ struct dpu_wb_cfg {
enum dpu_clk_ctrl_type clk_ctrl;
};
+/*
+ * struct dpu_cwb_cfg : MDP CWB mux instance info
+ * @id: enum identifying this block
+ * @base: register base offset to mdss
+ * @features bit mask identifying sub-blocks/features
+ */
+struct dpu_cwb_cfg {
+ DPU_HW_BLK_INFO;
+};
+
/**
* struct dpu_vbif_dynamic_ot_cfg - dynamic OT setting
* @pps pixel per seconds
@@ -815,6 +825,9 @@ struct dpu_mdss_cfg {
u32 dspp_count;
const struct dpu_dspp_cfg *dspp;
+ u32 cwb_count;
+ const struct dpu_cwb_cfg *cwb;
+
/* Add additional block data structures here */
const struct dpu_perf_cfg *perf;
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 10/25] drm/msm/dpu: Specify dedicated CWB pingpong blocks
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (8 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 09/25] drm/msm/dpu: Add CWB entry to catalog for SM8650 Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 11/25] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
` (17 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Change pingpong index and names to distinguish between general use
pingpong blocks and pingpong blocks dedicated for concurrent writeback
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 8 ++++----
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 4 ++--
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 4 ++--
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 4 ++--
drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 4 ++--
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 8 ++++----
6 files changed, 16 insertions(+), 16 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
index 33f5faf4833f7534a1403ccec560fffe8ea0bb1f..bfb64b7c1a471d0f9b9e69e9a0ed12bfc7f48a85 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h
@@ -252,25 +252,25 @@ static const struct dpu_pingpong_cfg sm8650_pp[] = {
.merge_3d = MERGE_3D_2,
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
}, {
- .name = "pingpong_6", .id = PINGPONG_6,
+ .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
.base = 0x66000, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_7", .id = PINGPONG_7,
+ .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
.base = 0x66400, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_8", .id = PINGPONG_8,
+ .name = "pingpong_cwb_2", .id = PINGPONG_CWB_2,
.base = 0x7e000, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_4,
}, {
- .name = "pingpong_9", .id = PINGPONG_9,
+ .name = "pingpong_cwb_3", .id = PINGPONG_CWB_3,
.base = 0x7e400, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
index a1779c5597ae701496f21d3a8cb513189424a484..08742472f9cc812fbaf8f842ff7bd78f597e2b8d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
@@ -257,13 +257,13 @@ static const struct dpu_pingpong_cfg sm8450_pp[] = {
.merge_3d = MERGE_3D_2,
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
}, {
- .name = "pingpong_6", .id = PINGPONG_6,
+ .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
.base = 0x65800, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_7", .id = PINGPONG_7,
+ .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
.base = 0x65c00, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
index 907b4d7ceb470b0391d2bbbab3ce520efa2b3263..76ec72a323781363d37b62fec752ea1232bbd75b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h
@@ -256,13 +256,13 @@ static const struct dpu_pingpong_cfg sa8775p_pp[] = {
.merge_3d = MERGE_3D_2,
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
}, {
- .name = "pingpong_6", .id = PINGPONG_6,
+ .name = "pingpong_6", .id = PINGPONG_CWB_0,
.base = 0x65800, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_7", .id = PINGPONG_7,
+ .name = "pingpong_7", .id = PINGPONG_CWB_1,
.base = 0x65c00, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
index ad48defa154f7d808c695860fd91e60bbb08f42a..173f6f53a30cad117c0faea14f4cc512988a61f7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
@@ -251,13 +251,13 @@ static const struct dpu_pingpong_cfg sm8550_pp[] = {
.merge_3d = MERGE_3D_2,
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
}, {
- .name = "pingpong_6", .id = PINGPONG_6,
+ .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
.base = 0x66000, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_7", .id = PINGPONG_7,
+ .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
.base = 0x66400, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
index a3e60ac70689e7f8af8813d978626cd7d4c9fb3e..592ba9abd1adce2932d5e891aefa1bbd3867e5ed 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h
@@ -251,13 +251,13 @@ static const struct dpu_pingpong_cfg x1e80100_pp[] = {
.merge_3d = MERGE_3D_2,
.intr_done = DPU_IRQ_IDX(MDP_SSPP_TOP0_INTR2, 31),
}, {
- .name = "pingpong_6", .id = PINGPONG_6,
+ .name = "pingpong_cwb_0", .id = PINGPONG_CWB_0,
.base = 0x66000, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
.merge_3d = MERGE_3D_3,
}, {
- .name = "pingpong_7", .id = PINGPONG_7,
+ .name = "pingpong_cwb_1", .id = PINGPONG_CWB_1,
.base = 0x66400, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index f8806a4d317be0974c6ad5ad9f772c5029c1f8e1..fb3b6db8112f567f23ddab474d777182abb86033 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -181,10 +181,10 @@ enum dpu_pingpong {
PINGPONG_3,
PINGPONG_4,
PINGPONG_5,
- PINGPONG_6,
- PINGPONG_7,
- PINGPONG_8,
- PINGPONG_9,
+ PINGPONG_CWB_0,
+ PINGPONG_CWB_1,
+ PINGPONG_CWB_2,
+ PINGPONG_CWB_3,
PINGPONG_S0,
PINGPONG_MAX
};
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 11/25] drm/msm/dpu: add devcoredumps for cwb registers
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (9 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 10/25] drm/msm/dpu: Specify dedicated CWB pingpong blocks Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 12/25] drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block Jessica Zhang
` (16 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Implement instance of snapshot function to dump new registers used
for cwb
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index ca4847b2b73876c59dedff1e3ec4188ea70860a7..d244bee94162cef97e2ae6f7ff5203640903f41d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1004,6 +1004,11 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k
dpu_kms->mmio + cat->mdp[0].base, "top");
}
+ /* dump CWB sub-blocks HW regs info */
+ for (i = 0; i < cat->cwb_count; i++)
+ msm_disp_snapshot_add_block(disp_state, cat->cwb[i].len,
+ dpu_kms->mmio + cat->cwb[i].base, cat->cwb[i].name);
+
/* dump DSC sub-blocks HW regs info */
for (i = 0; i < cat->dsc_count; i++) {
base = dpu_kms->mmio + cat->dsc[i].base;
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 12/25] drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (10 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 11/25] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 13/25] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
` (15 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
The CWB mux has its own registers and set of operations. Add dpu_hw_cwb
abstraction to allow driver to configure the CWB mux.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/Makefile | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c | 73 +++++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h | 70 +++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 +-
4 files changed, 148 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index f274d9430cc311405f890074c1466ffe2ec45ac9..5df20cbeafb8bf07c825a1fd72719d5a56c38613 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -78,6 +78,7 @@ msm-display-$(CONFIG_DRM_MSM_DPU) += \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_cdm.o \
disp/dpu1/dpu_hw_ctl.o \
+ disp/dpu1/dpu_hw_cwb.o \
disp/dpu1/dpu_hw_dsc.o \
disp/dpu1/dpu_hw_dsc_1_2.o \
disp/dpu1/dpu_hw_interrupts.o \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c
new file mode 100644
index 0000000000000000000000000000000000000000..5fbf52906ea94847a8eb3fcaa372e582dce2357c
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+
+#include <drm/drm_managed.h>
+#include "dpu_hw_cwb.h"
+
+#define CWB_MUX 0x000
+#define CWB_MODE 0x004
+
+/* CWB mux block bit definitions */
+#define CWB_MUX_MASK GENMASK(3, 0)
+#define CWB_MODE_MASK GENMASK(2, 0)
+
+static void dpu_hw_cwb_config(struct dpu_hw_cwb *ctx,
+ struct dpu_hw_cwb_setup_cfg *cwb_cfg)
+{
+ struct dpu_hw_blk_reg_map *c = &ctx->hw;
+ int cwb_mux_cfg = 0xF;
+ enum dpu_pingpong pp;
+ enum cwb_mode_input input;
+
+ if (!cwb_cfg)
+ return;
+
+ input = cwb_cfg->input;
+ pp = cwb_cfg->pp_idx;
+
+ if (input >= INPUT_MODE_MAX)
+ return;
+
+ /*
+ * The CWB_MUX register takes the pingpong index for the real-time
+ * display
+ */
+ if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX))
+ cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_0);
+
+ input = FIELD_PREP(CWB_MODE_MASK, input);
+
+ DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg);
+ DPU_REG_WRITE(c, CWB_MODE, input);
+}
+
+/**
+ * dpu_hw_cwb_init() - Initializes the writeback hw driver object with cwb.
+ * @dev: Corresponding device for devres management
+ * @cfg: wb_path catalog entry for which driver object is required
+ * @addr: mapped register io address of MDP
+ * Return: Error code or allocated dpu_hw_wb context
+ */
+struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev,
+ const struct dpu_cwb_cfg *cfg,
+ void __iomem *addr)
+{
+ struct dpu_hw_cwb *c;
+
+ if (!addr)
+ return ERR_PTR(-EINVAL);
+
+ c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
+ if (!c)
+ return ERR_PTR(-ENOMEM);
+
+ c->hw.blk_addr = addr + cfg->base;
+ c->hw.log_mask = DPU_DBG_MASK_CWB;
+
+ c->idx = cfg->id;
+ c->ops.config_cwb = dpu_hw_cwb_config;
+
+ return c;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
new file mode 100644
index 0000000000000000000000000000000000000000..96b6edf6b2bbf7d270ac08f76af06fcd3c431527
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h
@@ -0,0 +1,70 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved
+ */
+
+#ifndef _DPU_HW_CWB_H
+#define _DPU_HW_CWB_H
+
+#include "dpu_hw_util.h"
+
+struct dpu_hw_cwb;
+
+enum cwb_mode_input {
+ INPUT_MODE_LM_OUT,
+ INPUT_MODE_DSPP_OUT,
+ INPUT_MODE_MAX
+};
+
+/**
+ * struct dpu_hw_cwb_setup_cfg : Describes configuration for CWB mux
+ * @pp_idx: Index of the real-time pinpong that the CWB mux will
+ * feed the CWB mux
+ * @input: Input tap point
+ */
+struct dpu_hw_cwb_setup_cfg {
+ enum dpu_pingpong pp_idx;
+ enum cwb_mode_input input;
+};
+
+/**
+ *
+ * struct dpu_hw_cwb_ops : Interface to the cwb hw driver functions
+ * @config_cwb: configure CWB mux
+ */
+struct dpu_hw_cwb_ops {
+ void (*config_cwb)(struct dpu_hw_cwb *ctx,
+ struct dpu_hw_cwb_setup_cfg *cwb_cfg);
+};
+
+/**
+ * struct dpu_hw_cwb : CWB mux driver object
+ * @base: Hardware block base structure
+ * @hw: Block hardware details
+ * @idx: CWB index
+ * @ops: handle to operations possible for this CWB
+ */
+struct dpu_hw_cwb {
+ struct dpu_hw_blk base;
+ struct dpu_hw_blk_reg_map hw;
+
+ enum dpu_cwb idx;
+
+ struct dpu_hw_cwb_ops ops;
+};
+
+/**
+ * dpu_hw_cwb - convert base object dpu_hw_base to container
+ * @hw: Pointer to base hardware block
+ * return: Pointer to hardware block container
+ */
+static inline struct dpu_hw_cwb *to_dpu_hw_cwb(struct dpu_hw_blk *hw)
+{
+ return container_of(hw, struct dpu_hw_cwb, base);
+}
+
+struct dpu_hw_cwb *dpu_hw_cwb_init(struct drm_device *dev,
+ const struct dpu_cwb_cfg *cfg,
+ void __iomem *addr);
+
+#endif /*_DPU_HW_CWB_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index fb3b6db8112f567f23ddab474d777182abb86033..ba7bb05efe9b8cac01a908e53121117e130f91ec 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -1,5 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
*/
#ifndef _DPU_HW_MDSS_H
@@ -350,6 +352,7 @@ struct dpu_mdss_color {
#define DPU_DBG_MASK_DSPP (1 << 10)
#define DPU_DBG_MASK_DSC (1 << 11)
#define DPU_DBG_MASK_CDM (1 << 12)
+#define DPU_DBG_MASK_CWB (1 << 13)
/**
* struct dpu_hw_tear_check - Struct contains parameters to configure
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 13/25] drm/msm/dpu: add CWB support to dpu_hw_wb
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (11 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 12/25] drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 14/25] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
` (14 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Adjust the WB_MUX configuration to account for using dedicated CWB
pingpong blocks.
Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
index fb9f909577624959560abddbab8d03b0b1ea11a1..4853e516c48733231de240b9c32ad51d4cf18f0d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -173,7 +173,9 @@ static void dpu_hw_wb_bind_pingpong_blk(
mux_cfg = DPU_REG_READ(c, WB_MUX);
mux_cfg &= ~0xf;
- if (pp)
+ if (pp >= PINGPONG_CWB_0)
+ mux_cfg |= (pp < PINGPONG_CWB_2) ? 0xd : 0xb;
+ else if (pp)
mux_cfg |= (pp - PINGPONG_0) & 0x7;
else
mux_cfg |= 0xf;
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 14/25] drm/msm/dpu: Add RM support for allocating CWB
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (12 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 13/25] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
` (13 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add support for allocating the concurrent writeback mux as part of the
WB allocation
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 16 +++++++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 2f227e6826b5f90bdab508bd1e87075d8b4274fd..b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2023-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
@@ -10,6 +10,7 @@
#include "dpu_hw_lm.h"
#include "dpu_hw_ctl.h"
#include "dpu_hw_cdm.h"
+#include "dpu_hw_cwb.h"
#include "dpu_hw_pingpong.h"
#include "dpu_hw_sspp.h"
#include "dpu_hw_intf.h"
@@ -123,6 +124,19 @@ int dpu_rm_init(struct drm_device *dev,
rm->hw_wb[wb->id - WB_0] = hw;
}
+ for (i = 0; i < cat->cwb_count; i++) {
+ struct dpu_hw_cwb *hw;
+ const struct dpu_cwb_cfg *cwb = &cat->cwb[i];
+
+ hw = dpu_hw_cwb_init(dev, cwb, mmio);
+ if (IS_ERR(hw)) {
+ rc = PTR_ERR(hw);
+ DPU_ERROR("failed cwb object creation: err %d\n", rc);
+ goto fail;
+ }
+ rm->cwb_blks[cwb->id - CWB_0] = &hw->base;
+ }
+
for (i = 0; i < cat->ctl_count; i++) {
struct dpu_hw_ctl *hw;
const struct dpu_ctl_cfg *ctl = &cat->ctl[i];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 893344bf1141046a45f32a1834f857a56aa2b9b6..b061dfdab52e04ab7d777e912a30173273cb3db7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -20,6 +20,7 @@ struct dpu_global_state;
* @ctl_blks: array of ctl hardware resources
* @hw_intf: array of intf hardware resources
* @hw_wb: array of wb hardware resources
+ * @hw_cwb: array of cwb hardware resources
* @dspp_blks: array of dspp hardware resources
* @hw_sspp: array of sspp hardware resources
* @cdm_blk: cdm hardware resource
@@ -30,6 +31,7 @@ struct dpu_rm {
struct dpu_hw_blk *ctl_blks[CTL_MAX - CTL_0];
struct dpu_hw_intf *hw_intf[INTF_MAX - INTF_0];
struct dpu_hw_wb *hw_wb[WB_MAX - WB_0];
+ struct dpu_hw_blk *cwb_blks[CWB_MAX - CWB_0];
struct dpu_hw_blk *dspp_blks[DSPP_MAX - DSPP_0];
struct dpu_hw_blk *merge_3d_blks[MERGE_3D_MAX - MERGE_3D_0];
struct dpu_hw_blk *dsc_blks[DSC_MAX - DSC_0];
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (13 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 14/25] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:03 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
` (12 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add the cwb_enabled flag to msm_display topology and adjust the toplogy
to account for concurrent writeback
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
&crtc_state->adjusted_mode);
+ topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
+
/*
* Datapath topology selection
*
@@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
* 2 LM, 1 INTF (stream merge to support high resolution interfaces)
*
* Add dspps to the reservation requirements if ctm is requested
+ *
+ * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
+ * enabled. This is because in cases where CWB is enabled, num_intf will
+ * count both the WB and real-time phys encoders.
+ *
+ * For non-DSC CWB usecases, have the num_lm be decided by the
+ * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
*/
- if (topology.num_intf == 2)
+ if (topology.num_intf == 2 && !topology.cwb_enabled)
topology.num_lm = 2;
else if (topology.num_dsc == 2)
topology.num_lm = 2;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
int i = 0, j, num_ctls;
bool needs_split_display;
- /* each hw_intf needs its own hw_ctrl to program its control path */
- num_ctls = top->num_intf;
+ /*
+ * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
+ * control path. Hardcode num_ctls to 1 if CWB is enabled
+ */
+ if (top->cwb_enabled)
+ num_ctls = 1;
+ else
+ num_ctls = top->num_intf;
needs_split_display = _dpu_rm_needs_split_display(top);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -46,6 +46,7 @@ struct dpu_rm {
* @num_dspp: number of dspp blocks used
* @num_dsc: number of Display Stream Compression (DSC) blocks used
* @needs_cdm: indicates whether cdm block is needed for this display topology
+ * @cwb_enabled: indicates whether CWB is enabled for this display topology
*/
struct msm_display_topology {
u32 num_lm;
@@ -53,6 +54,7 @@ struct msm_display_topology {
u32 num_dspp;
u32 num_dsc;
bool needs_cdm;
+ bool cwb_enabled;
};
int dpu_rm_init(struct drm_device *dev,
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (14 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:41 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled Jessica Zhang
` (11 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
If the clone mode enabled status is changing, a modeset needs to happen
so that the resources can be reassigned
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
NOTE: As noted by Sima in the v1 [1], the DPU driver doesn't handle
crtc_state->mode_changed correctly. However, fixing this is out of the
scope of this series.
We will post a separate series addressing these issues across the driver
[1] https://lore.kernel.org/dri-devel/ZtW_S0j5AEr4g0QW@phenom.ffwll.local/
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index b063c8fe4c0594772d84401fa56c9c21afc0ad18..9bb920d28bae2706b3892c167fe2bec3fd8857f4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1297,6 +1297,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
+ struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
+ crtc);
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
@@ -1308,6 +1310,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
int rc = 0;
bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
+ bool clone_mode_enabled = drm_crtc_in_clone_mode(old_crtc_state);
+ bool clone_mode_requested = drm_crtc_in_clone_mode(crtc_state);
/* there might be cases where encoder needs a modeset too */
drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
@@ -1315,6 +1319,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
crtc_state->mode_changed = true;
}
+ if ((clone_mode_requested && !clone_mode_enabled) ||
+ (!clone_mode_requested && clone_mode_enabled))
+ crtc_state->mode_changed = true;
+
if (drm_atomic_crtc_needs_modeset(crtc_state)) {
rc = dpu_crtc_assign_resources(crtc, crtc_state);
if (rc < 0)
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (15 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:44 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
` (10 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
We cannot support both CWB and CDM simultaneously as this would require
2 CDM blocks and currently our hardware only supports 1 CDM block at
most.
Thus return an error if both CWB and CDM are enabled.
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9bb920d28bae2706b3892c167fe2bec3fd8857f4..a6372eee916e8aba702bbefc3615d8882ddcaad9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1261,6 +1261,10 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
return 0;
topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
+
+ if (topology.cwb_enabled && topology.needs_cdm)
+ return -EINVAL;
+
ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
crtc, &topology);
if (ret)
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (16 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:52 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
` (9 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
For concurrent writeback, even-indexed CWB muxes must be assigned to
even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
even/odd rule applies for dedicated CWB PINGPONGs.
Track the CWB muxes in the global state and add a CWB-specific helper to
reserve the correct CWB muxes and dedicated PINGPONGs following the
even/odd rule.
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
4 files changed, 116 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2013 Red Hat
* Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Author: Rob Clark <robdclark@gmail.com>
*/
@@ -28,6 +28,7 @@
#include "dpu_hw_dsc.h"
#include "dpu_hw_merge3d.h"
#include "dpu_hw_cdm.h"
+#include "dpu_hw_cwb.h"
#include "dpu_formats.h"
#include "dpu_encoder_phys.h"
#include "dpu_crtc.h"
@@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
* @cur_slave: As above but for the slave encoder.
* @hw_pp: Handle to the pingpong blocks used for the display. No.
* pingpong blocks can be different than num_phys_encs.
+ * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
+ * display. Number of CWB muxes can be different than
+ * num_phys_encs.
* @hw_dsc: Handle to the DSC blocks used for the display.
* @dsc_mask: Bitmask of used DSC blocks.
* @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
@@ -177,6 +181,7 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+ struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
unsigned int dsc_mask;
@@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
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_dsc[MAX_CHANNELS_PER_ENC];
+ struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
int num_pp, num_dsc, num_ctl;
+ int num_cwb = 0;
+ bool is_cwb_encoder;
unsigned int dsc_mask = 0;
int i;
@@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
priv = drm_enc->dev->dev_private;
dpu_kms = to_dpu_kms(priv->kms);
+ is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
+ dpu_enc->disp_info.intf_type == INTF_WB;
global_state = dpu_kms_get_existing_global_state(dpu_kms);
if (IS_ERR_OR_NULL(global_state)) {
@@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
trace_dpu_enc_mode_set(DRMID(drm_enc));
/* Query resource that have been reserved in atomic check step. */
- num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
- ARRAY_SIZE(hw_pp));
+ if (is_cwb_encoder) {
+ num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ drm_enc->crtc,
+ DPU_HW_BLK_DCWB_PINGPONG,
+ hw_pp, ARRAY_SIZE(hw_pp));
+ num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ drm_enc->crtc,
+ DPU_HW_BLK_CWB,
+ hw_cwb, ARRAY_SIZE(hw_cwb));
+ } else {
+ num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ drm_enc->crtc,
+ DPU_HW_BLK_PINGPONG, hw_pp,
+ ARRAY_SIZE(hw_pp));
+ }
+
+ for (i = 0; i < num_cwb; i++)
+ dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
+
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
DPU_HW_BLK_LM,
DPU_HW_BLK_CTL,
DPU_HW_BLK_PINGPONG,
+ DPU_HW_BLK_DCWB_PINGPONG,
DPU_HW_BLK_INTF,
DPU_HW_BLK_WB,
DPU_HW_BLK_DSPP,
DPU_HW_BLK_MERGE_3D,
DPU_HW_BLK_DSC,
DPU_HW_BLK_CDM,
+ DPU_HW_BLK_CWB,
DPU_HW_BLK_MAX,
};
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -128,6 +128,7 @@ struct dpu_global_state {
uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
uint32_t cdm_to_crtc_id;
+ uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
};
struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
return -EINVAL;
}
+static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
+ struct dpu_global_state *global_state,
+ uint32_t crtc_id,
+ struct msm_display_topology *topology)
+{
+ int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
+ int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
+ int cwb_pp_idx[MAX_BLOCKS];
+ int cwb_mux_idx[MAX_BLOCKS];
+
+ /*
+ * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
+ * mixer
+ *
+ * TODO: add support reserving resources for platforms with no
+ * PINGPONG_CWB
+ */
+ for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
+ cwb_pp_count < num_cwb_pp; i++) {
+ for (int j = cwb_pp_start_idx;
+ j < ARRAY_SIZE(rm->pingpong_blks); j++) {
+ /*
+ * Odd LMs must be assigned to odd PINGPONGs and even
+ * LMs with even PINGPONGs
+ */
+ if (reserved_by_other(global_state->pingpong_to_crtc_id, j, crtc_id) ||
+ i % 2 != j % 2)
+ continue;
+
+ cwb_pp_idx[cwb_pp_count] = j;
+ cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
+ cwb_pp_count++;
+ break;
+ }
+ }
+
+ if (cwb_pp_count != num_cwb_pp) {
+ DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
+ return -ENAVAIL;
+ }
+
+ for (int i = 0; i < cwb_pp_count; i++) {
+ global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
+ global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
+ }
+
+ return 0;
+}
+
/**
* _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
* proposed use case requirements, incl. hardwired dependent blocks like
@@ -614,6 +663,12 @@ static int _dpu_rm_make_reservation(
return ret;
}
+ if (topology->cwb_enabled) {
+ ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
+ crtc_id, topology);
+ if (ret)
+ return ret;
+ }
ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
topology);
@@ -671,6 +726,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
_dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
_dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
+ _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
+ ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
}
/**
@@ -733,6 +790,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
switch (type) {
case DPU_HW_BLK_PINGPONG:
+ case DPU_HW_BLK_DCWB_PINGPONG:
hw_blks = rm->pingpong_blks;
hw_to_crtc_id = global_state->pingpong_to_crtc_id;
max_blks = ARRAY_SIZE(rm->pingpong_blks);
@@ -762,6 +820,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_crtc_id = &global_state->cdm_to_crtc_id;
max_blks = 1;
break;
+ case DPU_HW_BLK_CWB:
+ hw_blks = rm->cwb_blks;
+ hw_to_crtc_id = global_state->cwb_to_crtc_id;
+ max_blks = ARRAY_SIZE(rm->cwb_blks);
+ break;
default:
DPU_ERROR("blk type %d not managed by rm\n", type);
return 0;
@@ -772,6 +835,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
if (hw_to_crtc_id[i] != crtc_id)
continue;
+ if (type == DPU_HW_BLK_PINGPONG) {
+ struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
+
+ if (pp->idx >= PINGPONG_CWB_0)
+ continue;
+ }
+
+ if (type == DPU_HW_BLK_DCWB_PINGPONG) {
+ struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
+
+ if (pp->idx < PINGPONG_CWB_0)
+ continue;
+ }
+
if (num_blks == blks_size) {
DPU_ERROR("More than %d resources assigned to crtc %d\n",
blks_size, crtc_id);
@@ -847,4 +924,10 @@ void dpu_rm_print_state(struct drm_printer *p,
dpu_rm_print_state_helper(p, rm->cdm_blk,
global_state->cdm_to_crtc_id);
drm_puts(p, "\n");
+
+ drm_puts(p, "\tcwb=");
+ for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
+ dpu_rm_print_state_helper(p, rm->cwb_blks[i],
+ global_state->cwb_to_crtc_id[i]);
+ drm_puts(p, "\n");
}
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (17 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:55 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 20/25] drm/msm/dpu: Support CWB in dpu_hw_ctl Jessica Zhang
` (8 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Cache the CWB block mask in the DPU virtual encoder and configure CWB
according to the CWB block mask within the writeback phys encoder
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 75 +++++++++++++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 7 +-
.../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 +-
3 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index a95dc1f0c6a422485c7ba98743e944e1a4f43539..066b96601a92945defe778ea40eb9d70783a0ae1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -24,6 +24,7 @@
#include "dpu_hw_catalog.h"
#include "dpu_hw_intf.h"
#include "dpu_hw_ctl.h"
+#include "dpu_hw_cwb.h"
#include "dpu_hw_dspp.h"
#include "dpu_hw_dsc.h"
#include "dpu_hw_merge3d.h"
@@ -139,6 +140,7 @@ enum dpu_enc_rc_states {
* num_phys_encs.
* @hw_dsc: Handle to the DSC blocks used for the display.
* @dsc_mask: Bitmask of used DSC blocks.
+ * @cwb_mask Bitmask of used CWB muxes
* @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
* for partial update right-only cases, such as pingpong
* split where virtual pingpong does not generate IRQs
@@ -185,6 +187,7 @@ struct dpu_encoder_virt {
struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
unsigned int dsc_mask;
+ unsigned int cwb_mask;
bool intfs_swapped;
@@ -1148,6 +1151,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
int num_cwb = 0;
bool is_cwb_encoder;
unsigned int dsc_mask = 0;
+ unsigned int cwb_mask = 0;
int i;
if (!drm_enc) {
@@ -1188,8 +1192,12 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
ARRAY_SIZE(hw_pp));
}
- for (i = 0; i < num_cwb; i++)
+ for (i = 0; i < num_cwb; i++) {
dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
+ cwb_mask |= BIT(dpu_enc->hw_cwb[i]->idx - CWB_0);
+ }
+
+ dpu_enc->cwb_mask = cwb_mask;
num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
@@ -2226,6 +2234,9 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
}
}
+ if (dpu_enc->cwb_mask)
+ dpu_encoder_helper_phys_setup_cwb(phys_enc, false);
+
/* reset the merge 3D HW block */
if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d) {
phys_enc->hw_pp->merge_3d->ops.setup_3d_mode(phys_enc->hw_pp->merge_3d,
@@ -2269,6 +2280,56 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
ctl->ops.clear_pending_flush(ctl);
}
+void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc,
+ bool enable)
+{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
+ struct dpu_hw_cwb *hw_cwb;
+ struct dpu_hw_cwb_setup_cfg cwb_cfg;
+
+ struct dpu_kms *dpu_kms;
+ struct dpu_global_state *global_state;
+ struct dpu_hw_blk *rt_pp_list[MAX_CHANNELS_PER_ENC];
+ int num_pp;
+
+ if (!phys_enc->hw_wb)
+ return;
+
+ dpu_kms = phys_enc->dpu_kms;
+ global_state = dpu_kms_get_existing_global_state(dpu_kms);
+ num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
+ phys_enc->parent->crtc,
+ DPU_HW_BLK_PINGPONG, rt_pp_list,
+ ARRAY_SIZE(rt_pp_list));
+
+ if (num_pp == 0 || num_pp > MAX_CHANNELS_PER_ENC) {
+ DPU_DEBUG_ENC(dpu_enc, "invalid num_pp %d\n", num_pp);
+ return;
+ }
+
+ /*
+ * The CWB mux supports using LM or DSPP as tap points. For now,
+ * always use LM tap point
+ */
+ cwb_cfg.input = INPUT_MODE_LM_OUT;
+
+ for (int i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+ hw_cwb = dpu_enc->hw_cwb[i];
+ if (!hw_cwb)
+ continue;
+
+ if (enable) {
+ struct dpu_hw_pingpong *hw_pp =
+ to_dpu_hw_pingpong(rt_pp_list[i]);
+ cwb_cfg.pp_idx = hw_pp->idx;
+ } else {
+ cwb_cfg.pp_idx = PINGPONG_NONE;
+ }
+
+ hw_cwb->ops.config_cwb(hw_cwb, &cwb_cfg);
+ }
+}
+
/**
* dpu_encoder_helper_phys_setup_cdm - setup chroma down sampling block
* @phys_enc: Pointer to physical encoder
@@ -2729,6 +2790,18 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder)
return INTF_MODE_NONE;
}
+/**
+ * dpu_encoder_helper_get_cwb_mask - get CWB blocks mask for the DPU encoder
+ * @phys_enc: Pointer to physical encoder structure
+ */
+unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc)
+{
+ struct drm_encoder *encoder = phys_enc->parent;
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(encoder);
+
+ return dpu_enc->cwb_mask;
+}
+
/**
* dpu_encoder_helper_get_dsc - get DSC blocks mask for the DPU encoder
* This helper function is used by physical encoder to get DSC blocks mask
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
index 63f09857025c2004dcb56bd33e9c51f8e0f80e48..61b22d9494546885db609efa156222792af73d2a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
*/
@@ -309,6 +309,8 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
return BLEND_3D_NONE;
}
+unsigned int dpu_encoder_helper_get_cwb_mask(struct dpu_encoder_phys *phys_enc);
+
unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc);
@@ -331,6 +333,9 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc);
+void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc,
+ bool enable);
+
void dpu_encoder_helper_phys_setup_cdm(struct dpu_encoder_phys *phys_enc,
const struct msm_format *dpu_fmt,
u32 output_type);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 4c006ec74575b2829265f0eae5c462af8d491621..f2cbc9335e54e826c2ebd00b3a809af41eed95a4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
@@ -340,6 +340,8 @@ static void dpu_encoder_phys_wb_setup(
dpu_encoder_helper_phys_setup_cdm(phys_enc, format, CDM_CDWN_OUTPUT_WB);
+ dpu_encoder_helper_phys_setup_cwb(phys_enc, true);
+
dpu_encoder_phys_wb_setup_ctl(phys_enc);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 20/25] drm/msm/dpu: Support CWB in dpu_hw_ctl
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (18 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 21/25] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
` (7 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
The CWB mux has a pending flush bit and *_active register.
Add support for configuring them within the dpu_hw_ctl layer.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 13 ++++++++++
.../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +++++++++++++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 15 ++++++++++-
4 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 066b96601a92945defe778ea40eb9d70783a0ae1..0af813aae626853a7f75f4994999cf1ca137d342 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2263,6 +2263,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
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);
+ intf_cfg.cwb = dpu_enc->cwb_mask;
if (phys_enc->hw_intf)
intf_cfg.intf = phys_enc->hw_intf->idx;
@@ -2285,6 +2286,7 @@ void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc,
{
struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
struct dpu_hw_cwb *hw_cwb;
+ struct dpu_hw_ctl *hw_ctl;
struct dpu_hw_cwb_setup_cfg cwb_cfg;
struct dpu_kms *dpu_kms;
@@ -2295,6 +2297,14 @@ void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc,
if (!phys_enc->hw_wb)
return;
+ hw_ctl = phys_enc->hw_ctl;
+
+ if (!phys_enc->hw_ctl) {
+ DPU_DEBUG("[wb:%d] no ctl assigned\n",
+ phys_enc->hw_wb->idx - WB_0);
+ return;
+ }
+
dpu_kms = phys_enc->dpu_kms;
global_state = dpu_kms_get_existing_global_state(dpu_kms);
num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
@@ -2327,6 +2337,9 @@ void dpu_encoder_helper_phys_setup_cwb(struct dpu_encoder_phys *phys_enc,
}
hw_cwb->ops.config_cwb(hw_cwb, &cwb_cfg);
+
+ if (hw_ctl->ops.update_pending_flush_cwb)
+ hw_ctl->ops.update_pending_flush_cwb(hw_ctl, hw_cwb->idx);
}
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index f2cbc9335e54e826c2ebd00b3a809af41eed95a4..648e6b3aab84957ca0401cbbc25889f0bd64b71a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -236,6 +236,7 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
intf_cfg.intf = DPU_NONE;
intf_cfg.wb = hw_wb->idx;
+ intf_cfg.cwb = dpu_encoder_helper_get_cwb_mask(phys_enc);
if (mode_3d && hw_pp && hw_pp->merge_3d)
intf_cfg.merge_3d = hw_pp->merge_3d->idx;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 4893f10d6a5832521808c0f4d8b231c356dbdc41..411a7cf088eb72f856940c09b0af9e108ccade4b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/delay.h>
@@ -31,12 +31,14 @@
#define CTL_MERGE_3D_ACTIVE 0x0E4
#define CTL_DSC_ACTIVE 0x0E8
#define CTL_WB_ACTIVE 0x0EC
+#define CTL_CWB_ACTIVE 0x0F0
#define CTL_INTF_ACTIVE 0x0F4
#define CTL_CDM_ACTIVE 0x0F8
#define CTL_FETCH_PIPE_ACTIVE 0x0FC
#define CTL_MERGE_3D_FLUSH 0x100
#define CTL_DSC_FLUSH 0x104
#define CTL_WB_FLUSH 0x108
+#define CTL_CWB_FLUSH 0x10C
#define CTL_INTF_FLUSH 0x110
#define CTL_CDM_FLUSH 0x114
#define CTL_PERIPH_FLUSH 0x128
@@ -53,6 +55,7 @@
#define PERIPH_IDX 30
#define INTF_IDX 31
#define WB_IDX 16
+#define CWB_IDX 28
#define DSPP_IDX 29 /* From DPU hw rev 7.x.x */
#define CTL_INVALID_BIT 0xffff
#define CTL_DEFAULT_GROUP_ID 0xf
@@ -110,6 +113,7 @@ static inline void dpu_hw_ctl_clear_pending_flush(struct dpu_hw_ctl *ctx)
ctx->pending_flush_mask = 0x0;
ctx->pending_intf_flush_mask = 0;
ctx->pending_wb_flush_mask = 0;
+ ctx->pending_cwb_flush_mask = 0;
ctx->pending_merge_3d_flush_mask = 0;
ctx->pending_dsc_flush_mask = 0;
ctx->pending_cdm_flush_mask = 0;
@@ -144,6 +148,9 @@ static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
if (ctx->pending_flush_mask & BIT(WB_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_WB_FLUSH,
ctx->pending_wb_flush_mask);
+ if (ctx->pending_flush_mask & BIT(CWB_IDX))
+ DPU_REG_WRITE(&ctx->hw, CTL_CWB_FLUSH,
+ ctx->pending_cwb_flush_mask);
if (ctx->pending_flush_mask & BIT(DSPP_IDX))
for (dspp = DSPP_0; dspp < DSPP_MAX; dspp++) {
@@ -310,6 +317,13 @@ static void dpu_hw_ctl_update_pending_flush_wb_v1(struct dpu_hw_ctl *ctx,
ctx->pending_flush_mask |= BIT(WB_IDX);
}
+static void dpu_hw_ctl_update_pending_flush_cwb_v1(struct dpu_hw_ctl *ctx,
+ enum dpu_cwb cwb)
+{
+ ctx->pending_cwb_flush_mask |= BIT(cwb - CWB_0);
+ ctx->pending_flush_mask |= BIT(CWB_IDX);
+}
+
static void dpu_hw_ctl_update_pending_flush_intf_v1(struct dpu_hw_ctl *ctx,
enum dpu_intf intf)
{
@@ -547,6 +561,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
u32 intf_active = 0;
u32 dsc_active = 0;
u32 wb_active = 0;
+ u32 cwb_active = 0;
u32 mode_sel = 0;
/* CTL_TOP[31:28] carries group_id to collate CTL paths
@@ -561,6 +576,7 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
intf_active = DPU_REG_READ(c, CTL_INTF_ACTIVE);
wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
+ cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE);
dsc_active = DPU_REG_READ(c, CTL_DSC_ACTIVE);
if (cfg->intf)
@@ -569,12 +585,16 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->wb)
wb_active |= BIT(cfg->wb - WB_0);
+ if (cfg->cwb)
+ cwb_active |= cfg->cwb;
+
if (cfg->dsc)
dsc_active |= cfg->dsc;
DPU_REG_WRITE(c, CTL_TOP, mode_sel);
DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
DPU_REG_WRITE(c, CTL_WB_ACTIVE, wb_active);
+ DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
DPU_REG_WRITE(c, CTL_DSC_ACTIVE, dsc_active);
if (cfg->merge_3d)
@@ -624,6 +644,7 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
struct dpu_hw_blk_reg_map *c = &ctx->hw;
u32 intf_active = 0;
u32 wb_active = 0;
+ u32 cwb_active = 0;
u32 merge3d_active = 0;
u32 dsc_active;
u32 cdm_active;
@@ -651,6 +672,12 @@ static void dpu_hw_ctl_reset_intf_cfg_v1(struct dpu_hw_ctl *ctx,
DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active);
}
+ if (cfg->cwb) {
+ cwb_active = DPU_REG_READ(c, CTL_CWB_ACTIVE);
+ cwb_active &= ~cfg->cwb;
+ DPU_REG_WRITE(c, CTL_CWB_ACTIVE, cwb_active);
+ }
+
if (cfg->wb) {
wb_active = DPU_REG_READ(c, CTL_WB_ACTIVE);
wb_active &= ~BIT(cfg->wb - WB_0);
@@ -703,6 +730,7 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->update_pending_flush_merge_3d =
dpu_hw_ctl_update_pending_flush_merge_3d_v1;
ops->update_pending_flush_wb = dpu_hw_ctl_update_pending_flush_wb_v1;
+ ops->update_pending_flush_cwb = dpu_hw_ctl_update_pending_flush_cwb_v1;
ops->update_pending_flush_dsc =
dpu_hw_ctl_update_pending_flush_dsc_v1;
ops->update_pending_flush_cdm = dpu_hw_ctl_update_pending_flush_cdm_v1;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 85c6c835cc8780e6cb66f3a262d9897c91962935..080a9550a0cc6530b4115165dd737857b6213d15 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _DPU_HW_CTL_H
@@ -42,6 +42,7 @@ struct dpu_hw_stage_cfg {
* @cdm: CDM block used
* @stream_sel: Stream selection for multi-stream interfaces
* @dsc: DSC BIT masks used
+ * @cwb: CWB BIT masks used
*/
struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -51,6 +52,7 @@ struct dpu_hw_intf_cfg {
enum dpu_ctl_mode_sel intf_mode_sel;
enum dpu_cdm cdm;
int stream_sel;
+ unsigned int cwb;
unsigned int dsc;
};
@@ -114,6 +116,15 @@ struct dpu_hw_ctl_ops {
void (*update_pending_flush_wb)(struct dpu_hw_ctl *ctx,
enum dpu_wb blk);
+ /**
+ * OR in the given flushbits to the cached pending_(cwb_)flush_mask
+ * No effect on hardware
+ * @ctx : ctl path ctx pointer
+ * @blk : concurrent writeback block index
+ */
+ void (*update_pending_flush_cwb)(struct dpu_hw_ctl *ctx,
+ enum dpu_cwb blk);
+
/**
* OR in the given flushbits to the cached pending_(intf_)flush_mask
* No effect on hardware
@@ -258,6 +269,7 @@ struct dpu_hw_ctl_ops {
* @pending_flush_mask: storage for pending ctl_flush managed via ops
* @pending_intf_flush_mask: pending INTF flush
* @pending_wb_flush_mask: pending WB flush
+ * @pending_cwb_flush_mask: pending CWB flush
* @pending_dsc_flush_mask: pending DSC flush
* @pending_cdm_flush_mask: pending CDM flush
* @ops: operation list
@@ -274,6 +286,7 @@ struct dpu_hw_ctl {
u32 pending_flush_mask;
u32 pending_intf_flush_mask;
u32 pending_wb_flush_mask;
+ u32 pending_cwb_flush_mask;
u32 pending_periph_flush_mask;
u32 pending_merge_3d_flush_mask;
u32 pending_dspp_flush_mask[DSPP_MAX - DSPP_0];
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 21/25] drm/msm/dpu: Adjust writeback phys encoder setup for CWB
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (19 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 20/25] drm/msm/dpu: Support CWB in dpu_hw_ctl Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 22/25] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
` (6 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Adjust QoS remapper, OT limit, and CDP parameters to account for
concurrent writeback
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 648e6b3aab84957ca0401cbbc25889f0bd64b71a..849fea580a4ca55fc4a742c6b6dee7dfcdd788e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -68,7 +68,7 @@ static void dpu_encoder_phys_wb_set_ot_limit(
ot_params.num = hw_wb->idx - WB_0;
ot_params.width = phys_enc->cached_mode.hdisplay;
ot_params.height = phys_enc->cached_mode.vdisplay;
- ot_params.is_wfd = true;
+ ot_params.is_wfd = !dpu_encoder_helper_get_cwb_mask(phys_enc);
ot_params.frame_rate = drm_mode_vrefresh(&phys_enc->cached_mode);
ot_params.vbif_idx = hw_wb->caps->vbif_idx;
ot_params.rd = false;
@@ -111,7 +111,7 @@ static void dpu_encoder_phys_wb_set_qos_remap(
qos_params.vbif_idx = hw_wb->caps->vbif_idx;
qos_params.xin_id = hw_wb->caps->xin_id;
qos_params.num = hw_wb->idx - WB_0;
- qos_params.is_rt = false;
+ qos_params.is_rt = dpu_encoder_helper_get_cwb_mask(phys_enc);
DPU_DEBUG("[qos_remap] wb:%d vbif:%d xin:%d is_rt:%d\n",
qos_params.num,
@@ -174,6 +174,7 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
struct dpu_hw_wb *hw_wb;
struct dpu_hw_wb_cfg *wb_cfg;
+ u32 cdp_usage;
if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) {
DPU_ERROR("invalid encoder\n");
@@ -182,6 +183,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
hw_wb = phys_enc->hw_wb;
wb_cfg = &wb_enc->wb_cfg;
+ if (dpu_encoder_helper_get_cwb_mask(phys_enc))
+ cdp_usage = DPU_PERF_CDP_USAGE_RT;
+ else
+ cdp_usage = DPU_PERF_CDP_USAGE_NRT;
wb_cfg->intf_mode = phys_enc->intf_mode;
wb_cfg->roi.x1 = 0;
@@ -199,7 +204,7 @@ static void dpu_encoder_phys_wb_setup_fb(struct dpu_encoder_phys *phys_enc,
const struct dpu_perf_cfg *perf = phys_enc->dpu_kms->catalog->perf;
hw_wb->ops.setup_cdp(hw_wb, format,
- perf->cdp_cfg[DPU_PERF_CDP_USAGE_NRT].wr_enable);
+ perf->cdp_cfg[cdp_usage].wr_enable);
}
if (hw_wb->ops.setup_outaddress)
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 22/25] drm/msm/dpu: Start frame done timer after encoder kickoff
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (20 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 21/25] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 23/25] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
` (5 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Starting the frame done timer before the encoder is finished kicking off
can lead to unnecessary frame done timeouts when the device is
experiencing heavy load (ex. when debug logs are enabled).
Thus, create a separate API for starting the encoder frame done timer and
call it after the encoder kickoff is finished
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 +++-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 27 +++++++++++++++++++--------
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 4 +++-
3 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a6372eee916e8aba702bbefc3615d8882ddcaad9..05b5f494305c6b44a7093928a3909e3840a94b97 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -992,8 +992,10 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
dpu_vbif_clear_errors(dpu_kms);
- drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
+ drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) {
dpu_encoder_kickoff(encoder);
+ dpu_encoder_start_frame_done_timer(encoder);
+ }
reinit_completion(&dpu_crtc->frame_done_comp);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0af813aae626853a7f75f4994999cf1ca137d342..905a4a096c00a6bd0700eea6d908da03d8b3c89d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2087,6 +2087,25 @@ bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc)
return true;
}
+/**
+ * dpu_encoder_start_frame_done_timer - Start the encoder frame done timer
+ * @drm_enc: Pointer to drm encoder structure
+ */
+void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc)
+{
+ struct dpu_encoder_virt *dpu_enc;
+ unsigned long timeout_ms;
+
+ dpu_enc = to_dpu_encoder_virt(drm_enc);
+ timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 /
+ drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode);
+
+ atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms);
+ mod_timer(&dpu_enc->frame_done_timer,
+ jiffies + msecs_to_jiffies(timeout_ms));
+
+}
+
/**
* dpu_encoder_kickoff - trigger a double buffer flip of the ctl path
* (i.e. ctl flush and start) immediately.
@@ -2096,7 +2115,6 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
{
struct dpu_encoder_virt *dpu_enc;
struct dpu_encoder_phys *phys;
- unsigned long timeout_ms;
unsigned int i;
DPU_ATRACE_BEGIN("encoder_kickoff");
@@ -2104,13 +2122,6 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
trace_dpu_enc_kickoff(DRMID(drm_enc));
- timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 /
- drm_mode_vrefresh(&drm_enc->crtc->state->adjusted_mode);
-
- atomic_set(&dpu_enc->frame_done_timeout_ms, timeout_ms);
- mod_timer(&dpu_enc->frame_done_timer,
- jiffies + msecs_to_jiffies(timeout_ms));
-
/* All phys encs are ready to go, trigger the kickoff */
_dpu_encoder_kickoff_phys(dpu_enc);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 3db3ea076c377ad5411ec85006bcf4cd9757eb1d..a121c5ec9a7213deeb304894378a5a354025fdb8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
@@ -96,4 +96,6 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc);
+void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc);
+
#endif /* __DPU_ENCODER_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 23/25] drm/msm/dpu: Skip trigger flush and start for CWB
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (21 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 22/25] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
` (4 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
For concurrent writeback, the real time encoder is responsible for
trigger flush and trigger start. Return early for trigger start and
trigger flush for the concurrent writeback encoders.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 905a4a096c00a6bd0700eea6d908da03d8b3c89d..f21be3bf19958834a735d797170f80424b8407f7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1607,6 +1607,7 @@ static void dpu_encoder_off_work(struct work_struct *work)
static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phys, uint32_t extra_flush_bits)
{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
struct dpu_hw_ctl *ctl;
int pending_kickoff_cnt;
u32 ret = UINT_MAX;
@@ -1624,6 +1625,15 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
pending_kickoff_cnt = dpu_encoder_phys_inc_pending(phys);
+ /* Return early if encoder is writeback and in clone mode */
+ if (drm_enc->encoder_type == DRM_MODE_ENCODER_VIRTUAL &&
+ dpu_enc->cwb_mask) {
+ DPU_DEBUG("encoder %d skip flush for concurrent writeback encoder\n",
+ DRMID(drm_enc));
+ return;
+ }
+
+
if (extra_flush_bits && ctl->ops.update_pending_flush)
ctl->ops.update_pending_flush(ctl, extra_flush_bits);
@@ -1646,6 +1656,8 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
*/
static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys)
{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(phys->parent);
+
if (!phys) {
DPU_ERROR("invalid argument(s)\n");
return;
@@ -1656,6 +1668,12 @@ static void _dpu_encoder_trigger_start(struct dpu_encoder_phys *phys)
return;
}
+ if (phys->parent->encoder_type == DRM_MODE_ENCODER_VIRTUAL &&
+ dpu_enc->cwb_mask) {
+ DPU_DEBUG("encoder %d CWB enabled, skipping\n", DRMID(phys->parent));
+ return;
+ }
+
if (phys->ops.trigger_start && phys->enable_state != DPU_ENC_DISABLED)
phys->ops.trigger_start(phys);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff for CWB
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (22 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 23/25] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 6:00 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 25/25] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
` (3 subsequent siblings)
27 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Add a helper that will handle the correct order of the encoder kickoffs
for concurrent writeback.
For concurrent writeback, the realtime encoder must always kickoff last
as it will call the trigger flush and start.
This avoids the following scenario where the writeback encoder
increments the pending kickoff count after the WB_DONE interrupt is
fired:
If the realtime encoder is kicked off first, the encoder kickoff will
flush/start the encoder and increment the pending kickoff count. The
WB_DONE interrupt then fires (before the writeback encoder is kicked
off). When the writeback encoder enters its kickoff, it will skip the
flush/start (due to CWB being enabled) and hit a frame done timeout
as the frame was kicked off (and the WB_DONE interrupt fired) without
the pending kickoff count being incremented.
In addition, the writeback timer should only start after the realtime
encoder is kicked off to ensure that we don't get timeouts when the
system has a heavy load (ex. when debug logs are enabled)
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 74 ++++++++++++++++++++++++++------
1 file changed, 60 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 05b5f494305c6b44a7093928a3909e3840a94b97..ddf91e727e3d54568b55c1a3bc5ffdb2eaac7233 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -946,6 +946,45 @@ static int _dpu_crtc_wait_for_frame_done(struct drm_crtc *crtc)
return rc;
}
+static int dpu_crtc_kickoff_clone_mode(struct drm_crtc *crtc)
+{
+ struct drm_encoder *encoder;
+ struct drm_encoder *rt_encoder = NULL, *wb_encoder;
+ struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
+
+ /* Find encoder for real time display */
+ drm_for_each_encoder_mask(encoder, crtc->dev,
+ crtc->state->encoder_mask) {
+ if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
+ wb_encoder = encoder;
+ else
+ rt_encoder = encoder;
+ }
+
+ if (!rt_encoder || !wb_encoder) {
+ DRM_DEBUG_ATOMIC("real time or wb encoder not found\n");
+ return -EINVAL;
+ }
+
+ dpu_encoder_prepare_for_kickoff(wb_encoder);
+ dpu_encoder_prepare_for_kickoff(rt_encoder);
+
+ dpu_vbif_clear_errors(dpu_kms);
+
+ /*
+ * Kickoff real time encoder last as it's the encoder that
+ * will do the flush
+ */
+ dpu_encoder_kickoff(wb_encoder);
+ dpu_encoder_kickoff(rt_encoder);
+
+ /* Don't start frame done timers until the kickoffs have finished */
+ dpu_encoder_start_frame_done_timer(wb_encoder);
+ dpu_encoder_start_frame_done_timer(rt_encoder);
+
+ return 0;
+}
+
/**
* dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
* @crtc: Pointer to drm crtc object
@@ -974,13 +1013,27 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
goto end;
}
}
- /*
- * Encoder will flush/start now, unless it has a tx pending. If so, it
- * may delay and flush at an irq event (e.g. ppdone)
- */
- drm_for_each_encoder_mask(encoder, crtc->dev,
- crtc->state->encoder_mask)
- dpu_encoder_prepare_for_kickoff(encoder);
+
+ if (drm_crtc_in_clone_mode(crtc->state)) {
+ if (dpu_crtc_kickoff_clone_mode(crtc))
+ goto end;
+ } else {
+ /*
+ * Encoder will flush/start now, unless it has a tx pending.
+ * If so, it may delay and flush at an irq event (e.g. ppdone)
+ */
+ drm_for_each_encoder_mask(encoder, crtc->dev,
+ crtc->state->encoder_mask)
+ dpu_encoder_prepare_for_kickoff(encoder);
+
+ dpu_vbif_clear_errors(dpu_kms);
+
+ drm_for_each_encoder_mask(encoder, crtc->dev,
+ crtc->state->encoder_mask) {
+ dpu_encoder_kickoff(encoder);
+ dpu_encoder_start_frame_done_timer(encoder);
+ }
+ }
if (atomic_inc_return(&dpu_crtc->frame_pending) == 1) {
/* acquire bandwidth and other resources */
@@ -990,13 +1043,6 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
dpu_crtc->play_count++;
- dpu_vbif_clear_errors(dpu_kms);
-
- drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask) {
- dpu_encoder_kickoff(encoder);
- dpu_encoder_start_frame_done_timer(encoder);
- }
-
reinit_completion(&dpu_crtc->frame_done_comp);
end:
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* [PATCH v4 25/25] drm/msm/dpu: Set possible clones for all encoders
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (23 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
@ 2024-12-17 0:43 ` Jessica Zhang
2024-12-20 5:11 ` [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Dmitry Baryshkov
` (2 subsequent siblings)
27 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-17 0:43 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä, Jessica Zhang
Set writeback encoders as possible clones for DSI encoders and vice
versa.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 32 +++++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 2 ++
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 7 +++++--
3 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index f21be3bf19958834a735d797170f80424b8407f7..5293abd14c3b1318e9ab21d0b430d61b1cded531 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2558,6 +2558,38 @@ static int dpu_encoder_virt_add_phys_encs(
return 0;
}
+/**
+ * dpu_encoder_get_clones - Calculate the possible_clones for DPU encoder
+ * @drm_enc: DRM encoder pointer
+ * Returns: possible_clones mask
+ */
+uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc)
+{
+ struct drm_encoder *curr;
+ int type = drm_enc->encoder_type;
+ uint32_t clone_mask = drm_encoder_mask(drm_enc);
+
+ /*
+ * Set writeback as possible clones of real-time DSI encoders and vice
+ * versa
+ *
+ * Writeback encoders can't be clones of each other and DSI
+ * encoders can't be clones of each other.
+ *
+ * TODO: Add DP encoders as valid possible clones for writeback encoders
+ * (and vice versa) once concurrent writeback has been validated for DP
+ */
+ drm_for_each_encoder(curr, drm_enc->dev) {
+ if ((type == DRM_MODE_ENCODER_VIRTUAL &&
+ curr->encoder_type == DRM_MODE_ENCODER_DSI) ||
+ (type == DRM_MODE_ENCODER_DSI &&
+ curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL))
+ clone_mask |= drm_encoder_mask(curr);
+ }
+
+ return clone_mask;
+}
+
static int dpu_encoder_setup_display(struct dpu_encoder_virt *dpu_enc,
struct dpu_kms *dpu_kms,
struct msm_display_info *disp_info)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index a121c5ec9a7213deeb304894378a5a354025fdb8..8ffbdb070370c6fdb9da4e0799cc5280c731cefc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -61,6 +61,8 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder);
void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
+uint32_t dpu_encoder_get_clones(struct drm_encoder *drm_enc);
+
struct drm_encoder *dpu_encoder_init(struct drm_device *dev,
int drm_enc_mode,
struct msm_display_info *disp_info);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index d244bee94162cef97e2ae6f7ff5203640903f41d..cc71ea3c00abfe4dae6b28b92f0a40eba55a72f0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -2,7 +2,7 @@
/*
* Copyright (C) 2013 Red Hat
* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*
* Author: Rob Clark <robdclark@gmail.com>
*/
@@ -808,8 +808,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
return ret;
num_encoders = 0;
- drm_for_each_encoder(encoder, dev)
+ drm_for_each_encoder(encoder, dev) {
num_encoders++;
+ if (catalog->cwb_count > 0)
+ encoder->possible_clones = dpu_encoder_get_clones(encoder);
+ }
max_crtc_count = min(catalog->mixer_count, num_encoders);
--
2.34.1
^ permalink raw reply related [flat|nested] 77+ messages in thread
* Re: [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements
2024-12-17 0:43 ` [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
@ 2024-12-17 1:26 ` Dmitry Baryshkov
2024-12-17 2:11 ` Abhinav Kumar
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-17 1:26 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:16PM -0800, Jessica Zhang wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> The struct dpu_rm_requirements was used to wrap display topology and
> hw resources, which meant INTF indices. As of commit ef58e0ad3436
> ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
> resources struct was removed, leaving struct dpu_rm_requirements
> containing a single field (topology). Remove the useless wrapper.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 71 ++++++++++-------------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 +-
> 3 files changed, 25 insertions(+), 50 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 83de7564e2c1fe14fcf8c4f82335cafc937e1b99..5172ab4dea995a154cd88d05c3842d7425fc34ce 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -800,7 +800,7 @@ 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);
> + drm_enc, crtc_state, &topology);
> if (!ret)
> dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> global_state, crtc_state);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index c247af03dc8ef7174eedf3d5cc267d64f17a8656..cd5960af4a151428cc6fb7154c3ffdb65ebcf287 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -5,6 +5,7 @@
> */
>
> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
> +#include "msm_drv.h"
Why is it necessary? struct msm_display_topology has been moved to
dpu_rm.h
> #include "dpu_kms.h"
> #include "dpu_hw_lm.h"
> #include "dpu_hw_ctl.h"
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
2024-12-17 0:43 ` [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
@ 2024-12-17 1:39 ` Abhinav Kumar
2024-12-20 2:40 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Abhinav Kumar @ 2024-12-17 1:39 UTC (permalink / raw)
To: Jessica Zhang, Rob Clark, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> Stop poking into CRTC state from dpu_encoder.c, fill CRTC HW resources
> from dpu_crtc_assign_resources().
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> [quic_abhinavk@quicinc.com: cleaned up formatting]
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 +++++++++++++++++++++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++--
> 2 files changed, 31 insertions(+), 2 deletions(-)
>
<snip>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 2b999a0558b2a016644ed5d25bf54ab45c38d1d9..a895d48fe81ccc71d265e089992786e8b6268b1b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -1138,7 +1138,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> 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_dsc[MAX_CHANNELS_PER_ENC];
> - int num_ctl, num_pp, num_dsc;
> + int num_pp, num_dsc, num_ctl;
> unsigned int dsc_mask = 0;
> int i;
>
> @@ -1166,7 +1166,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> ARRAY_SIZE(hw_pp));
> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>
> for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
>
This chunk of diff is unnecessary. You are just changing the order of
defines and fixing alignment. Does not have to be in this change.
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-17 0:43 ` [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
@ 2024-12-17 1:47 ` Abhinav Kumar
2024-12-20 2:32 ` Dmitry Baryshkov
2024-12-24 5:02 ` Dmitry Baryshkov
1 sibling, 1 reply; 77+ messages in thread
From: Abhinav Kumar @ 2024-12-17 1:47 UTC (permalink / raw)
To: Jessica Zhang, Rob Clark, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> All resource allocation is centered around the LMs. Then other blocks
> (except DSCs) are allocated basing on the LMs that was selected, and LM
> powers up the CRTC rather than the encoder.
>
> Moreover if at some point the driver supports encoder cloning,
> allocating resources from the encoder will be incorrect, as all clones
> will have different encoder IDs, while LMs are to be shared by these
> encoders.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> [quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> [quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
> 3 files changed, 181 insertions(+), 169 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
> return false;
> }
>
<snip>
> +static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
> {
> - 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> - ARRAY_SIZE(hw_dspp));
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> + u32 num_intf = 0;
> + u32 num_dsc = 0;
> + int i;
>
> - for (i = 0; i < num_lm; i++) {
> - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
> + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> + if (dpu_enc->phys_encs[i])
> + num_intf++;
>
> - 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;
> - }
> + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
> + if (dpu_enc->dsc)
> + num_dsc += 2;
>
As we requested in v3, can you please explain why we have num_dsc +=2
instead of just num_dsc = 2? If we are hard-coding 2:2:1, this should be
just num_dsc = 2.
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 01/25] drm: add clone mode check for CRTC
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
@ 2024-12-17 1:49 ` Abhinav Kumar
2024-12-17 17:16 ` Maxime Ripard
1 sibling, 0 replies; 77+ messages in thread
From: Abhinav Kumar @ 2024-12-17 1:49 UTC (permalink / raw)
To: Jessica Zhang, Rob Clark, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> Add a common helper to check if the given CRTC state is in clone mode.
> This can be used by drivers to help detect if a CRTC is being shared by
> multiple encoders
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/drm_crtc.c | 20 ++++++++++++++++++++
> include/drm/drm_crtc.h | 2 +-
> 2 files changed, 21 insertions(+), 1 deletion(-)
>
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode()
2024-12-17 0:43 ` [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode() Jessica Zhang
@ 2024-12-17 2:06 ` Abhinav Kumar
2024-12-17 17:17 ` Maxime Ripard
1 sibling, 0 replies; 77+ messages in thread
From: Abhinav Kumar @ 2024-12-17 2:06 UTC (permalink / raw)
To: Jessica Zhang, Rob Clark, Dmitry Baryshkov, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, Simona Vetter, Simona Vetter
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> Add kunit test to validate drm_crtc_in_clone_mode() helper
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/tests/drm_atomic_state_test.c | 62 ++++++++++++++++++++++++++-
> 1 file changed, 61 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/tests/drm_atomic_state_test.c b/drivers/gpu/drm/tests/drm_atomic_state_test.c
> index be1f780249450ead7fbfd19ea98c96b442a94478..79bc5a9aedbf77aaf4b369a5fe62b6344e6859cf 100644
> --- a/drivers/gpu/drm/tests/drm_atomic_state_test.c
> +++ b/drivers/gpu/drm/tests/drm_atomic_state_test.c
> @@ -17,6 +17,12 @@
>
> #define DRM_TEST_CONN_0 BIT(0)
>
> +struct drm_clone_mode_test {
> + const char *name;
> + u32 encoder_mask;
> + int expected_result;
> +};
> +
> static const struct drm_display_mode drm_atomic_test_mode = {
> DRM_MODE("1024x768", 0, 65000, 1024, 1048,
> 1184, 1344, 0, 768, 771, 777, 806, 0,
> @@ -227,17 +233,71 @@ static void drm_test_check_connector_changed_modeset(struct kunit *test)
> KUNIT_ASSERT_EQ(test, modeset_counter, initial_modeset_count + 1);
> }
>
> +/*
> + * Test that the drm_crtc_in_clone_mode() helper can detect if a given CRTC
> + * state is in clone mode
> + */
> +static void drm_test_check_in_clone_mode(struct kunit *test)
> +{
> + bool ret;
> + const struct drm_clone_mode_test *param = test->param_value;
> + struct drm_crtc_state *crtc_state;
> +
> + crtc_state = kunit_kzalloc(test, sizeof(*crtc_state), GFP_KERNEL);
> + KUNIT_ASSERT_NOT_NULL(test, crtc_state);
> +
> + crtc_state->encoder_mask = param->encoder_mask;
> +
> + ret = drm_crtc_in_clone_mode(crtc_state);
> +
> + KUNIT_ASSERT_EQ(test, ret, param->expected_result);
> +}
> +
> +static void drm_check_in_clone_mode_desc(const struct drm_clone_mode_test *t,
> + char *desc)
> +{
> + sprintf(desc, "%s", t->name);
> +}
> +
> +static const struct drm_clone_mode_test drm_clone_mode_tests[] = {
> + {
> + .name = "in_clone_mode",
> + .encoder_mask = DRM_TEST_ENC_0 | DRM_TEST_ENC_1,
> + .expected_result = true,
> + },
> + {
> + .name = "not_in_clone_mode",
> + .encoder_mask = DRM_TEST_ENC_0,
> + .expected_result = false,
> + },
> +};
I think now, this series also depends on
https://patchwork.kernel.org/project/dri-devel/list/?series=916960 for
these ENC defines. Please indicate it in the cover letter and if we get
an ack to merge it through msm tree, we can absorb in in this series itself.
LGTM otherwise,
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> +
> +KUNIT_ARRAY_PARAM(drm_check_in_clone_mode, drm_clone_mode_tests,
> + drm_check_in_clone_mode_desc);
> +
> static struct kunit_case drm_test_check_modeset_test[] = {
> KUNIT_CASE(drm_test_check_connector_changed_modeset),
> {}
> };
>
> +static struct kunit_case drm_in_clone_mode_check_test[] = {
> + KUNIT_CASE_PARAM(drm_test_check_in_clone_mode,
> + drm_check_in_clone_mode_gen_params),
> + {}
> +};
> +
> static struct kunit_suite drm_test_check_modeset_test_suite = {
> .name = "drm_validate_modeset",
> .test_cases = drm_test_check_modeset_test,
> };
>
> -kunit_test_suite(drm_test_check_modeset_test_suite);
> +static struct kunit_suite drm_in_clone_mode_check_test_suite = {
> + .name = "drm_validate_clone_mode",
> + .test_cases = drm_in_clone_mode_check_test,
> +};
> +
> +kunit_test_suites(&drm_in_clone_mode_check_test_suite,
> + &drm_test_check_modeset_test_suite);
>
> MODULE_AUTHOR("Jessica Zhang <quic_jesszhan@quicinc.com");
> MODULE_DESCRIPTION("Test cases for the drm_atomic_helper functions");
>
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements
2024-12-17 1:26 ` Dmitry Baryshkov
@ 2024-12-17 2:11 ` Abhinav Kumar
0 siblings, 0 replies; 77+ messages in thread
From: Abhinav Kumar @ 2024-12-17 2:11 UTC (permalink / raw)
To: Dmitry Baryshkov, Jessica Zhang
Cc: Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/16/2024 5:26 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:16PM -0800, Jessica Zhang wrote:
>> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>
>> The struct dpu_rm_requirements was used to wrap display topology and
>> hw resources, which meant INTF indices. As of commit ef58e0ad3436
>> ("drm/msm/dpu: get INTF blocks directly rather than through RM") the hw
>> resources struct was removed, leaving struct dpu_rm_requirements
>> containing a single field (topology). Remove the useless wrapper.
>>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 2 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 71 ++++++++++-------------------
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 +-
>> 3 files changed, 25 insertions(+), 50 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index 83de7564e2c1fe14fcf8c4f82335cafc937e1b99..5172ab4dea995a154cd88d05c3842d7425fc34ce 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -800,7 +800,7 @@ 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);
>> + drm_enc, crtc_state, &topology);
>> if (!ret)
>> dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
>> global_state, crtc_state);
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index c247af03dc8ef7174eedf3d5cc267d64f17a8656..cd5960af4a151428cc6fb7154c3ffdb65ebcf287 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -5,6 +5,7 @@
>> */
>>
>> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
>> +#include "msm_drv.h"
>
> Why is it necessary? struct msm_display_topology has been moved to
> dpu_rm.h
>
Yeah, will be good to check and drop this as its unnecessary. With that
fixed, this LGTM
Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset()
2024-12-17 0:43 ` [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset() Jessica Zhang
@ 2024-12-17 12:14 ` Maxime Ripard
0 siblings, 0 replies; 77+ messages in thread
From: Maxime Ripard @ 2024-12-17 12:14 UTC (permalink / raw)
To: Jessica Zhang
Cc: dri-devel, freedreno, linux-arm-msm, linux-kernel, quic_abhinavk,
quic_ebharadw, DavidAirlie, Dmitry Baryshkov, JessicaZhang,
Maarten Lankhorst, Marijn Suijten, Maxime Ripard, Rob Clark,
Rob Clark, Sean Paul, Simona Vetter, Simona Vetter,
Thomas Zimmermann, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:15 -0800, Jessica Zhang wrote:
> Add a test for drm_atomic_check_modeset() specifically to validate
> drm_atomic_check_valid_clones() helper
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 01/25] drm: add clone mode check for CRTC
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
2024-12-17 1:49 ` Abhinav Kumar
@ 2024-12-17 17:16 ` Maxime Ripard
1 sibling, 0 replies; 77+ messages in thread
From: Maxime Ripard @ 2024-12-17 17:16 UTC (permalink / raw)
To: Jessica Zhang
Cc: dri-devel, freedreno, linux-arm-msm, linux-kernel, quic_abhinavk,
quic_ebharadw, DavidAirlie, Dmitry Baryshkov, JessicaZhang,
Maarten Lankhorst, Marijn Suijten, Maxime Ripard, Rob Clark,
Rob Clark, Sean Paul, Simona Vetter, Simona Vetter,
Thomas Zimmermann, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:12 -0800, Jessica Zhang wrote:
> Add a common helper to check if the given CRTC state is in clone mode.
> This can be used by drivers to help detect if a CRTC is being shared by
> multiple encoders
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>
> [ ... ]
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode()
2024-12-17 0:43 ` [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode() Jessica Zhang
2024-12-17 2:06 ` Abhinav Kumar
@ 2024-12-17 17:17 ` Maxime Ripard
1 sibling, 0 replies; 77+ messages in thread
From: Maxime Ripard @ 2024-12-17 17:17 UTC (permalink / raw)
To: Jessica Zhang
Cc: dri-devel, freedreno, linux-arm-msm, linux-kernel, quic_abhinavk,
quic_ebharadw, DavidAirlie, Dmitry Baryshkov, JessicaZhang,
Maarten Lankhorst, Marijn Suijten, Maxime Ripard, Rob Clark,
Rob Clark, Sean Paul, Simona Vetter, Simona Vetter,
Thomas Zimmermann, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:13 -0800, Jessica Zhang wrote:
> Add kunit test to validate drm_crtc_in_clone_mode() helper
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 03/25] drm: Add valid clones check
2024-12-17 0:43 ` [PATCH v4 03/25] drm: Add valid clones check Jessica Zhang
@ 2024-12-17 17:17 ` Maxime Ripard
0 siblings, 0 replies; 77+ messages in thread
From: Maxime Ripard @ 2024-12-17 17:17 UTC (permalink / raw)
To: Jessica Zhang
Cc: dri-devel, freedreno, linux-arm-msm, linux-kernel, quic_abhinavk,
quic_ebharadw, DavidAirlie, Dmitry Baryshkov, JessicaZhang,
Maarten Lankhorst, Marijn Suijten, Maxime Ripard, Rob Clark,
Rob Clark, Sean Paul, Simona Vetter, Simona Vetter,
Thomas Zimmermann, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:14 -0800, Jessica Zhang wrote:
> Check that all encoders attached to a given CRTC are valid
> possible_clones of each other.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
Reviewed-by: Maxime Ripard <mripard@kernel.org>
Thanks!
Maxime
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-17 1:47 ` Abhinav Kumar
@ 2024-12-20 2:32 ` Dmitry Baryshkov
2024-12-20 2:50 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 2:32 UTC (permalink / raw)
To: Abhinav Kumar
Cc: Jessica Zhang, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 05:47:50PM -0800, Abhinav Kumar wrote:
>
>
> On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >
> > All resource allocation is centered around the LMs. Then other blocks
> > (except DSCs) are allocated basing on the LMs that was selected, and LM
> > powers up the CRTC rather than the encoder.
> >
> > Moreover if at some point the driver supports encoder cloning,
> > allocating resources from the encoder will be incorrect, as all clones
> > will have different encoder IDs, while LMs are to be shared by these
> > encoders.
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > [quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
> > Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > [quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
> > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > ---
> > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
> > 3 files changed, 181 insertions(+), 169 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
> > return false;
> > }
>
> <snip>
>
> > +static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
> > {
> > - 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> > - ARRAY_SIZE(hw_dspp));
> > + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> > + u32 num_intf = 0;
> > + u32 num_dsc = 0;
> > + int i;
> > - for (i = 0; i < num_lm; i++) {
> > - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
> > + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> > + if (dpu_enc->phys_encs[i])
> > + num_intf++;
> > - 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;
> > - }
> > + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
> > + if (dpu_enc->dsc)
> > + num_dsc += 2;
>
> As we requested in v3, can you please explain why we have num_dsc +=2
> instead of just num_dsc = 2? If we are hard-coding 2:2:1, this should be
> just num_dsc = 2.
I'll drop it while applying a first part of the series. Granted that
num_dsc is initialized to 0 few lines above, it should be fine.
If later there is a need to change the lane, it can be done in a
consequent patch.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
2024-12-17 1:39 ` Abhinav Kumar
@ 2024-12-20 2:40 ` Dmitry Baryshkov
2024-12-20 2:52 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 2:40 UTC (permalink / raw)
To: Abhinav Kumar
Cc: Jessica Zhang, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 05:39:15PM -0800, Abhinav Kumar wrote:
>
>
> On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >
> > Stop poking into CRTC state from dpu_encoder.c, fill CRTC HW resources
> > from dpu_crtc_assign_resources().
> >
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > [quic_abhinavk@quicinc.com: cleaned up formatting]
> > Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > ---
> > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 +++++++++++++++++++++++++++++
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++--
> > 2 files changed, 31 insertions(+), 2 deletions(-)
> >
>
> <snip>
>
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 2b999a0558b2a016644ed5d25bf54ab45c38d1d9..a895d48fe81ccc71d265e089992786e8b6268b1b 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -1138,7 +1138,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > 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_dsc[MAX_CHANNELS_PER_ENC];
> > - int num_ctl, num_pp, num_dsc;
> > + int num_pp, num_dsc, num_ctl;
> > unsigned int dsc_mask = 0;
> > int i;
> > @@ -1166,7 +1166,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > ARRAY_SIZE(hw_pp));
> > num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> >
>
> This chunk of diff is unnecessary. You are just changing the order of
> defines and fixing alignment. Does not have to be in this change.
I can drop it while applying.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-20 2:32 ` Dmitry Baryshkov
@ 2024-12-20 2:50 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 2:50 UTC (permalink / raw)
To: Abhinav Kumar
Cc: Jessica Zhang, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Fri, Dec 20, 2024 at 04:32:34AM +0200, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 05:47:50PM -0800, Abhinav Kumar wrote:
> >
> >
> > On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> > > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > >
> > > All resource allocation is centered around the LMs. Then other blocks
> > > (except DSCs) are allocated basing on the LMs that was selected, and LM
> > > powers up the CRTC rather than the encoder.
> > >
> > > Moreover if at some point the driver supports encoder cloning,
> > > allocating resources from the encoder will be incorrect, as all clones
> > > will have different encoder IDs, while LMs are to be shared by these
> > > encoders.
> > >
> > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > [quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
> > > Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > > [quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
> > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > ---
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
> > > 3 files changed, 181 insertions(+), 169 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > @@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
> > > return false;
> > > }
> >
> > <snip>
> >
> > > +static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
> > > {
> > > - 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > - drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > > - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > - drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> > > - ARRAY_SIZE(hw_dspp));
> > > + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> > > + u32 num_intf = 0;
> > > + u32 num_dsc = 0;
> > > + int i;
> > > - for (i = 0; i < num_lm; i++) {
> > > - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
> > > + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> > > + if (dpu_enc->phys_encs[i])
> > > + num_intf++;
> > > - 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;
> > > - }
> > > + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
> > > + if (dpu_enc->dsc)
> > > + num_dsc += 2;
> >
> > As we requested in v3, can you please explain why we have num_dsc +=2
> > instead of just num_dsc = 2? If we are hard-coding 2:2:1, this should be
> > just num_dsc = 2.
>
> I'll drop it while applying a first part of the series. Granted that
> num_dsc is initialized to 0 few lines above, it should be fine.
>
> If later there is a need to change the lane, it can be done in a
> consequent patch.
Forgot to add:
With that change,
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
2024-12-20 2:40 ` Dmitry Baryshkov
@ 2024-12-20 2:52 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 2:52 UTC (permalink / raw)
To: Abhinav Kumar
Cc: Jessica Zhang, Rob Clark, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Fri, Dec 20, 2024 at 04:40:52AM +0200, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 05:39:15PM -0800, Abhinav Kumar wrote:
> >
> >
> > On 12/16/2024 4:43 PM, Jessica Zhang wrote:
> > > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > >
> > > Stop poking into CRTC state from dpu_encoder.c, fill CRTC HW resources
> > > from dpu_crtc_assign_resources().
> > >
> > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > [quic_abhinavk@quicinc.com: cleaned up formatting]
> > > Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > ---
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 29 +++++++++++++++++++++++++++++
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 4 ++--
> > > 2 files changed, 31 insertions(+), 2 deletions(-)
> > >
> >
> > <snip>
> >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > index 2b999a0558b2a016644ed5d25bf54ab45c38d1d9..a895d48fe81ccc71d265e089992786e8b6268b1b 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > @@ -1138,7 +1138,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > 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_dsc[MAX_CHANNELS_PER_ENC];
> > > - int num_ctl, num_pp, num_dsc;
> > > + int num_pp, num_dsc, num_ctl;
> > > unsigned int dsc_mask = 0;
> > > int i;
> > > @@ -1166,7 +1166,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > ARRAY_SIZE(hw_pp));
> > > num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > - drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > >
> >
> > This chunk of diff is unnecessary. You are just changing the order of
> > defines and fixing alignment. Does not have to be in this change.
>
> I can drop it while applying.
And with that in place:
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2024-12-17 0:43 ` [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
@ 2024-12-20 5:03 ` Dmitry Baryshkov
2025-01-03 18:03 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:03 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
> to account for concurrent writeback
Why?
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
> 3 files changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> &crtc_state->adjusted_mode);
>
> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
> +
> /*
> * Datapath topology selection
> *
> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> *
> * Add dspps to the reservation requirements if ctm is requested
> + *
> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
> + * enabled. This is because in cases where CWB is enabled, num_intf will
> + * count both the WB and real-time phys encoders.
> + *
> + * For non-DSC CWB usecases, have the num_lm be decided by the
> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
> */
>
> - if (topology.num_intf == 2)
> + if (topology.num_intf == 2 && !topology.cwb_enabled)
> topology.num_lm = 2;
> else if (topology.num_dsc == 2)
> topology.num_lm = 2;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
> int i = 0, j, num_ctls;
> bool needs_split_display;
>
> - /* each hw_intf needs its own hw_ctrl to program its control path */
> - num_ctls = top->num_intf;
> + /*
> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
> + * control path. Hardcode num_ctls to 1 if CWB is enabled
> + */
Why?
> + if (top->cwb_enabled)
> + num_ctls = 1;
> + else
> + num_ctls = top->num_intf;
>
> needs_split_display = _dpu_rm_needs_split_display(top);
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -46,6 +46,7 @@ struct dpu_rm {
> * @num_dspp: number of dspp blocks used
> * @num_dsc: number of Display Stream Compression (DSC) blocks used
> * @needs_cdm: indicates whether cdm block is needed for this display topology
> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
> */
> struct msm_display_topology {
> u32 num_lm;
> @@ -53,6 +54,7 @@ struct msm_display_topology {
> u32 num_dspp;
> u32 num_dsc;
> bool needs_cdm;
> + bool cwb_enabled;
> };
>
> int dpu_rm_init(struct drm_device *dev,
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (24 preceding siblings ...)
2024-12-17 0:43 ` [PATCH v4 25/25] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
@ 2024-12-20 5:11 ` Dmitry Baryshkov
2024-12-20 18:46 ` Jessica Zhang
2024-12-24 20:41 ` Dmitry Baryshkov
2025-01-07 23:50 ` (subset) " Dmitry Baryshkov
27 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:11 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:11PM -0800, Jessica Zhang wrote:
> DPU supports a single writeback session running concurrently with primary
> display when the CWB mux is configured properly. This series enables
> clone mode for DPU driver and adds support for programming the CWB mux
> in cases where the hardware has dedicated CWB pingpong blocks. Currently,
> the CWB hardware blocks have only been added to the SM8650
> hardware catalog and only DSI has been exposed as a possible_clone of WB.
>
> This changes are split into two parts:
>
> The first part of the series will pull in Dmitry's patches to refactor
> the DPU resource manager to be based off of CRTC instead of encoder.
> This includes some changes (noted in the relevant commits) by me and
> Abhinav to fix some issues with getting the global state and refactoring
> the CDM allocation to work with Dmitry's changes.
To provide a sensible baseline for both CWB and Quad-Pipe changes I'm
going to pull patches 5-14 (those which refactor the resource allocation
and also those adding support for the CWB hardware block). The core DRM
patches should probably go in through drm-misc-next.
>
> The second part of the series will add support for CWB by doing the
> following:
>
> 1) Add a DRM helper to detect if the current CRTC state is in clone mode
> and add an "in_clone_mode" entry to the atomic state print
> 2) Add the CWB mux to the hardware catalog and clarify the pingpong
> block index enum to specifiy which pingpong blocks are dedicated to
> CWB only and which ones are general use pingpong blocks
> 3) Add CWB as part of the devcoredump
> 4) Add support for configuring the CWB mux via dpu_hw_cwb ops
> 5) Add pending flush support for CWB
> 6) Add support for validating clone mode in the DPU CRTC and setting up
> CWB within the encoder
> 7) Adjust the encoder trigger flush, trigger start, and kickoff order to
> accomodate clone mode
> 8) Adjust when the frame done timer is started for clone mode
> 9) Define the possible clones for DPU encoders so that
>
> The feature was tested on SM8650 using IGT's kms_writeback test with the
> following change [1] and dumping the writeback framebuffer when in clone
> mode. I haven't gotten the chance to test it on DP yet, but I've
> validated both single and dual LM on DSI.
>
> To test CWB with IGT, you'll need to apply this series [1] and this
> driver patch [2]. Run the following command to dump the writeback buffer:
>
> IGT_FRAME_DUMP_PATH=<dump path> FRAME_PNG_FILE_NAME=<file name> \
> ./build/tests/kms_writeback -d [--run-subtest dump-valid-clones] \
>
> You can also do CRC validation by running this command:
>
> ./build/tests/kms_writeback [--run-subtest dump-valid-clones]
>
> [1] https://patchwork.freedesktop.org/series/137933/
> [2] https://patchwork.freedesktop.org/series/138284/
>
> ---
> Changes in v4:
> - Rebased onto latest msm-next
> - Added kunit tests for framework changes
> - Skip valid clone check for encoders that don't have any possible clones set
> (this is to avoid failing kunit tests, specifically the HDMI state helper tests)
> - Link to v3: https://lore.kernel.org/r/20241016-concurrent-wb-v3-0-a33cf9b93835@quicinc.com
>
> Changes in v3:
> - Dropped support for CWB on DP connectors for now
> - Dropped unnecessary PINGPONG array in *_setup_cwb()
> - Add a check to make sure CWB and CDM aren't supported simultaneously
> (Dmitry)
> - Document cwb_enabled checks in dpu_crtc_get_topology() (Dmitry)
> - Moved implementation of drm_crtc_in_clone_mode() to drm_crtc.c (Jani)
> - Dropped duplicate error message for reserving CWB resources (Dmitry)
> - Added notes in framework changes about posting a separate series to
> add proper KUnit tests (Maxime)
> - Added commit message note addressing Sima's comment on handling
> mode_changed (Dmitry)
> - Formatting fixes (Dmitry)
> - Added proper kerneldocs (Dmitry)
> - Renamed dpu_encoder_helper_get_cwb() -> *_get_cwb_mask() (Dmitry)
> - Capitalize all instances of "pingpong" in comments (Dmitry)
> - Link to v2: https://lore.kernel.org/r/20240924-concurrent-wb-v2-0-7849f900e863@quicinc.com
>
> Changes in v2:
> - Moved CWB hardware programming to its own dpu_hw_cwb abstraction
> (Dmitry)
> - Reserve and get assigned CWB muxes using RM API and KMS global state
> (Dmitry)
> - Dropped requirement to have only one CWB session at a time
> - Moved valid clone mode check to DRM framework (Dmitry and Ville)
> - Switch to default CWB tap point to LM as the DSPP
> - Dropped printing clone mode status in atomic state (Dmitry)
> - Call dpu_vbif_clear_errors() before dpu_encoder_kickoff() (Dmitry)
> - Squashed setup_input_ctrl() and setup_input_mode() into a single
> dpu_hw_cwb op (Dmitry)
> - Moved function comment docs to correct place and fixed wording of
> comments/commit messages (Dmitry)
> - Grabbed old CRTC state using proper drm_atomic_state API in
> dpu_crtc_atomic_check() (Dmitry)
> - Split HW catalog changes of adding the CWB mux block and changing the
> dedicated CWB pingpong indices into 2 separate commits (Dmitry)
> - Moved clearing the dpu_crtc_state.num_mixers to "drm/msm/dpu: fill
> CRTC resources in dpu_crtc.c" (Dmitry)
> - Fixed alignment and other formatting issues (Dmitry)
> - Link to v1: https://lore.kernel.org/r/20240829-concurrent-wb-v1-0-502b16ae2ebb@quicinc.com
>
> ---
> Dmitry Baryshkov (4):
> drm/msm/dpu: get rid of struct dpu_rm_requirements
> drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
> drm/msm/dpu: move resource allocation to CRTC
> drm/msm/dpu: fill CRTC resources in dpu_crtc.c
>
> Esha Bharadwaj (3):
> drm/msm/dpu: Add CWB entry to catalog for SM8650
> drm/msm/dpu: add devcoredumps for cwb registers
> drm/msm/dpu: add CWB support to dpu_hw_wb
>
> Jessica Zhang (18):
> drm: add clone mode check for CRTC
> drm/tests: Add test for drm_crtc_in_clone_mode()
> drm: Add valid clones check
> drm/tests: Add test for drm_atomic_helper_check_modeset()
> drm/msm/dpu: Specify dedicated CWB pingpong blocks
> drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block
> drm/msm/dpu: Add RM support for allocating CWB
> drm/msm/dpu: Add CWB to msm_display_topology
> drm/msm/dpu: Require modeset if clone mode status changes
> drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
> drm/msm/dpu: Reserve resources for CWB
> drm/msm/dpu: Configure CWB in writeback encoder
> drm/msm/dpu: Support CWB in dpu_hw_ctl
> drm/msm/dpu: Adjust writeback phys encoder setup for CWB
> drm/msm/dpu: Start frame done timer after encoder kickoff
> drm/msm/dpu: Skip trigger flush and start for CWB
> drm/msm/dpu: Reorder encoder kickoff for CWB
> drm/msm/dpu: Set possible clones for all encoders
>
> drivers/gpu/drm/drm_atomic_helper.c | 28 ++
> drivers/gpu/drm/drm_crtc.c | 20 +
> drivers/gpu/drm/msm/Makefile | 1 +
> .../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +-
> .../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 4 +-
> .../drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 4 +-
> .../gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 4 +-
> .../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 4 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 208 ++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 463 ++++++++++++---------
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 14 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 7 +-
> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 16 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 13 +
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 15 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c | 73 ++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h | 70 ++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 15 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 4 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 13 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 361 +++++++++-------
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 13 +-
> drivers/gpu/drm/tests/drm_atomic_state_test.c | 133 +++++-
> include/drm/drm_crtc.h | 2 +-
> 26 files changed, 1172 insertions(+), 384 deletions(-)
> ---
> base-commit: 86313a9cd152330c634b25d826a281c6a002eb77
> change-id: 20240618-concurrent-wb-97d62387f952
> prerequisite-change-id: 20241209-abhinavk-modeset-fix-74864f1de08d:v3
> prerequisite-patch-id: a197a0cd4647cb189ea20a96583ea78d0c98b638
> prerequisite-patch-id: 112c8f1795cbed989beb02b72561854c0ccd59dd
>
> Best regards,
> --
> Jessica Zhang <quic_jesszhan@quicinc.com>
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes
2024-12-17 0:43 ` [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
@ 2024-12-20 5:41 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:41 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:27PM -0800, Jessica Zhang wrote:
> If the clone mode enabled status is changing, a modeset needs to happen
> so that the resources can be reassigned
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
>
> NOTE: As noted by Sima in the v1 [1], the DPU driver doesn't handle
> crtc_state->mode_changed correctly. However, fixing this is out of the
> scope of this series.
>
> We will post a separate series addressing these issues across the driver
I'd rather fix the isssue first, as suggested by Sima, then we can see
how this function will evolve.
>
> [1] https://lore.kernel.org/dri-devel/ZtW_S0j5AEr4g0QW@phenom.ffwll.local/
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index b063c8fe4c0594772d84401fa56c9c21afc0ad18..9bb920d28bae2706b3892c167fe2bec3fd8857f4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1297,6 +1297,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> {
> struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
> crtc);
> + struct drm_crtc_state *old_crtc_state = drm_atomic_get_old_crtc_state(state,
> + crtc);
> struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
> struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>
> @@ -1308,6 +1310,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> int rc = 0;
>
> bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
> + bool clone_mode_enabled = drm_crtc_in_clone_mode(old_crtc_state);
> + bool clone_mode_requested = drm_crtc_in_clone_mode(crtc_state);
>
> /* there might be cases where encoder needs a modeset too */
> drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
> @@ -1315,6 +1319,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> crtc_state->mode_changed = true;
> }
>
> + if ((clone_mode_requested && !clone_mode_enabled) ||
> + (!clone_mode_requested && clone_mode_enabled))
> + crtc_state->mode_changed = true;
> +
> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> rc = dpu_crtc_assign_resources(crtc, crtc_state);
> if (rc < 0)
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
2024-12-17 0:43 ` [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled Jessica Zhang
@ 2024-12-20 5:44 ` Dmitry Baryshkov
2024-12-26 22:51 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:44 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:28PM -0800, Jessica Zhang wrote:
> We cannot support both CWB and CDM simultaneously as this would require
> 2 CDM blocks and currently our hardware only supports 1 CDM block at
> most.
Why would CWB require a second CDM block? I think that YUV output over
DP (needs_cdm = true) and RGB output over WB (cwb_enabled = true) should
work. Am I wrong?
>
> Thus return an error if both CWB and CDM are enabled.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 9bb920d28bae2706b3892c167fe2bec3fd8857f4..a6372eee916e8aba702bbefc3615d8882ddcaad9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1261,6 +1261,10 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
> return 0;
>
> topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
> +
> + if (topology.cwb_enabled && topology.needs_cdm)
> + return -EINVAL;
> +
> ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> crtc, &topology);
> if (ret)
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-17 0:43 ` [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
@ 2024-12-20 5:52 ` Dmitry Baryshkov
2024-12-21 0:12 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:52 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
>
> For concurrent writeback, even-indexed CWB muxes must be assigned to
> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
> even/odd rule applies for dedicated CWB PINGPONGs.
>
> Track the CWB muxes in the global state and add a CWB-specific helper to
> reserve the correct CWB muxes and dedicated PINGPONGs following the
> even/odd rule.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
> 4 files changed, 116 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2,7 +2,7 @@
> /*
> * Copyright (C) 2013 Red Hat
> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> *
> * Author: Rob Clark <robdclark@gmail.com>
> */
> @@ -28,6 +28,7 @@
> #include "dpu_hw_dsc.h"
> #include "dpu_hw_merge3d.h"
> #include "dpu_hw_cdm.h"
> +#include "dpu_hw_cwb.h"
> #include "dpu_formats.h"
> #include "dpu_encoder_phys.h"
> #include "dpu_crtc.h"
> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
> * @cur_slave: As above but for the slave encoder.
> * @hw_pp: Handle to the pingpong blocks used for the display. No.
> * pingpong blocks can be different than num_phys_encs.
> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
> + * display. Number of CWB muxes can be different than
> + * num_phys_encs.
> * @hw_dsc: Handle to the DSC blocks used for the display.
> * @dsc_mask: Bitmask of used DSC blocks.
> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
> struct dpu_encoder_phys *cur_master;
> struct dpu_encoder_phys *cur_slave;
> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
>
> unsigned int dsc_mask;
> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> 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_dsc[MAX_CHANNELS_PER_ENC];
> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
> int num_pp, num_dsc, num_ctl;
> + int num_cwb = 0;
> + bool is_cwb_encoder;
> unsigned int dsc_mask = 0;
> int i;
>
> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>
> priv = drm_enc->dev->dev_private;
> dpu_kms = to_dpu_kms(priv->kms);
> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
> + dpu_enc->disp_info.intf_type == INTF_WB;
>
> global_state = dpu_kms_get_existing_global_state(dpu_kms);
> if (IS_ERR_OR_NULL(global_state)) {
> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> trace_dpu_enc_mode_set(DRMID(drm_enc));
>
> /* Query resource that have been reserved in atomic check step. */
> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> - ARRAY_SIZE(hw_pp));
> + if (is_cwb_encoder) {
> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> + drm_enc->crtc,
> + DPU_HW_BLK_DCWB_PINGPONG,
> + hw_pp, ARRAY_SIZE(hw_pp));
> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> + drm_enc->crtc,
> + DPU_HW_BLK_CWB,
> + hw_cwb, ARRAY_SIZE(hw_cwb));
> + } else {
> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> + drm_enc->crtc,
> + DPU_HW_BLK_PINGPONG, hw_pp,
> + ARRAY_SIZE(hw_pp));
> + }
> +
> + for (i = 0; i < num_cwb; i++)
> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
> +
> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
> DPU_HW_BLK_LM,
> DPU_HW_BLK_CTL,
> DPU_HW_BLK_PINGPONG,
> + DPU_HW_BLK_DCWB_PINGPONG,
> DPU_HW_BLK_INTF,
> DPU_HW_BLK_WB,
> DPU_HW_BLK_DSPP,
> DPU_HW_BLK_MERGE_3D,
> DPU_HW_BLK_DSC,
> DPU_HW_BLK_CDM,
> + DPU_HW_BLK_CWB,
> DPU_HW_BLK_MAX,
> };
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -128,6 +128,7 @@ struct dpu_global_state {
> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> uint32_t cdm_to_crtc_id;
> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
> };
>
> struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> return -EINVAL;
> }
>
> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
> + struct dpu_global_state *global_state,
> + uint32_t crtc_id,
> + struct msm_display_topology *topology)
> +{
> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
> + int cwb_pp_idx[MAX_BLOCKS];
> + int cwb_mux_idx[MAX_BLOCKS];
> +
> + /*
> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
> + * mixer
> + *
> + * TODO: add support reserving resources for platforms with no
> + * PINGPONG_CWB
What about doing it other way around: allocate CWBs first as required
(even/odd, proper count, etc). Then for each of CWBs allocate a PP block
(I think it's enough to simply make CWB blocks have a corresponding PP
index as a property). This way the driver can handle both legacy and
current platforms.
> + */
> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> + cwb_pp_count < num_cwb_pp; i++) {
> + for (int j = cwb_pp_start_idx;
> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
> + /*
> + * Odd LMs must be assigned to odd PINGPONGs and even
> + * LMs with even PINGPONGs
> + */
> + if (reserved_by_other(global_state->pingpong_to_crtc_id, j, crtc_id) ||
> + i % 2 != j % 2)
> + continue;
> +
> + cwb_pp_idx[cwb_pp_count] = j;
> + cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
> + cwb_pp_count++;
> + break;
> + }
> + }
> +
> + if (cwb_pp_count != num_cwb_pp) {
> + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
> + return -ENAVAIL;
> + }
> +
> + for (int i = 0; i < cwb_pp_count; i++) {
> + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
> + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
> + }
> +
> + return 0;
> +}
> +
> /**
> * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
> * proposed use case requirements, incl. hardwired dependent blocks like
> @@ -614,6 +663,12 @@ static int _dpu_rm_make_reservation(
> return ret;
> }
>
> + if (topology->cwb_enabled) {
> + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
> + crtc_id, topology);
> + if (ret)
> + return ret;
> + }
>
> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> topology);
> @@ -671,6 +726,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
> + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
> }
>
> /**
> @@ -733,6 +790,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>
> switch (type) {
> case DPU_HW_BLK_PINGPONG:
> + case DPU_HW_BLK_DCWB_PINGPONG:
> hw_blks = rm->pingpong_blks;
> hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->pingpong_blks);
> @@ -762,6 +820,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> max_blks = 1;
> break;
> + case DPU_HW_BLK_CWB:
> + hw_blks = rm->cwb_blks;
> + hw_to_crtc_id = global_state->cwb_to_crtc_id;
> + max_blks = ARRAY_SIZE(rm->cwb_blks);
> + break;
> default:
> DPU_ERROR("blk type %d not managed by rm\n", type);
> return 0;
> @@ -772,6 +835,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> if (hw_to_crtc_id[i] != crtc_id)
> continue;
>
> + if (type == DPU_HW_BLK_PINGPONG) {
> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
> +
> + if (pp->idx >= PINGPONG_CWB_0)
> + continue;
> + }
> +
> + if (type == DPU_HW_BLK_DCWB_PINGPONG) {
> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
> +
> + if (pp->idx < PINGPONG_CWB_0)
> + continue;
> + }
> +
> if (num_blks == blks_size) {
> DPU_ERROR("More than %d resources assigned to crtc %d\n",
> blks_size, crtc_id);
> @@ -847,4 +924,10 @@ void dpu_rm_print_state(struct drm_printer *p,
> dpu_rm_print_state_helper(p, rm->cdm_blk,
> global_state->cdm_to_crtc_id);
> drm_puts(p, "\n");
> +
> + drm_puts(p, "\tcwb=");
> + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
> + dpu_rm_print_state_helper(p, rm->cwb_blks[i],
> + global_state->cwb_to_crtc_id[i]);
> + drm_puts(p, "\n");
> }
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder
2024-12-17 0:43 ` [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
@ 2024-12-20 5:55 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 5:55 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:30PM -0800, Jessica Zhang wrote:
> Cache the CWB block mask in the DPU virtual encoder and configure CWB
> according to the CWB block mask within the writeback phys encoder
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 75 +++++++++++++++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 7 +-
> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 4 +-
> 3 files changed, 83 insertions(+), 3 deletions(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff for CWB
2024-12-17 0:43 ` [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
@ 2024-12-20 6:00 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-20 6:00 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:35PM -0800, Jessica Zhang wrote:
> Add a helper that will handle the correct order of the encoder kickoffs
> for concurrent writeback.
>
> For concurrent writeback, the realtime encoder must always kickoff last
> as it will call the trigger flush and start.
>
> This avoids the following scenario where the writeback encoder
> increments the pending kickoff count after the WB_DONE interrupt is
> fired:
>
> If the realtime encoder is kicked off first, the encoder kickoff will
> flush/start the encoder and increment the pending kickoff count. The
> WB_DONE interrupt then fires (before the writeback encoder is kicked
> off). When the writeback encoder enters its kickoff, it will skip the
> flush/start (due to CWB being enabled) and hit a frame done timeout
> as the frame was kicked off (and the WB_DONE interrupt fired) without
> the pending kickoff count being incremented.
>
> In addition, the writeback timer should only start after the realtime
> encoder is kicked off to ensure that we don't get timeouts when the
> system has a heavy load (ex. when debug logs are enabled)
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 74 ++++++++++++++++++++++++++------
> 1 file changed, 60 insertions(+), 14 deletions(-)
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+
2024-12-20 5:11 ` [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Dmitry Baryshkov
@ 2024-12-20 18:46 ` Jessica Zhang
0 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-20 18:46 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/19/2024 9:11 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:11PM -0800, Jessica Zhang wrote:
>> DPU supports a single writeback session running concurrently with primary
>> display when the CWB mux is configured properly. This series enables
>> clone mode for DPU driver and adds support for programming the CWB mux
>> in cases where the hardware has dedicated CWB pingpong blocks. Currently,
>> the CWB hardware blocks have only been added to the SM8650
>> hardware catalog and only DSI has been exposed as a possible_clone of WB.
>>
>> This changes are split into two parts:
>>
>> The first part of the series will pull in Dmitry's patches to refactor
>> the DPU resource manager to be based off of CRTC instead of encoder.
>> This includes some changes (noted in the relevant commits) by me and
>> Abhinav to fix some issues with getting the global state and refactoring
>> the CDM allocation to work with Dmitry's changes.
>
> To provide a sensible baseline for both CWB and Quad-Pipe changes I'm
> going to pull patches 5-14 (those which refactor the resource allocation
> and also those adding support for the CWB hardware block). The core DRM
> patches should probably go in through drm-misc-next.
Ack, thanks for all the help with reviews!
- Jessica Zhang
>
>>
>> The second part of the series will add support for CWB by doing the
>> following:
>>
>> 1) Add a DRM helper to detect if the current CRTC state is in clone mode
>> and add an "in_clone_mode" entry to the atomic state print
>> 2) Add the CWB mux to the hardware catalog and clarify the pingpong
>> block index enum to specifiy which pingpong blocks are dedicated to
>> CWB only and which ones are general use pingpong blocks
>> 3) Add CWB as part of the devcoredump
>> 4) Add support for configuring the CWB mux via dpu_hw_cwb ops
>> 5) Add pending flush support for CWB
>> 6) Add support for validating clone mode in the DPU CRTC and setting up
>> CWB within the encoder
>> 7) Adjust the encoder trigger flush, trigger start, and kickoff order to
>> accomodate clone mode
>> 8) Adjust when the frame done timer is started for clone mode
>> 9) Define the possible clones for DPU encoders so that
>>
>> The feature was tested on SM8650 using IGT's kms_writeback test with the
>> following change [1] and dumping the writeback framebuffer when in clone
>> mode. I haven't gotten the chance to test it on DP yet, but I've
>> validated both single and dual LM on DSI.
>>
>> To test CWB with IGT, you'll need to apply this series [1] and this
>> driver patch [2]. Run the following command to dump the writeback buffer:
>>
>> IGT_FRAME_DUMP_PATH=<dump path> FRAME_PNG_FILE_NAME=<file name> \
>> ./build/tests/kms_writeback -d [--run-subtest dump-valid-clones] \
>>
>> You can also do CRC validation by running this command:
>>
>> ./build/tests/kms_writeback [--run-subtest dump-valid-clones]
>>
>> [1] https://patchwork.freedesktop.org/series/137933/
>> [2] https://patchwork.freedesktop.org/series/138284/
>>
>> ---
>> Changes in v4:
>> - Rebased onto latest msm-next
>> - Added kunit tests for framework changes
>> - Skip valid clone check for encoders that don't have any possible clones set
>> (this is to avoid failing kunit tests, specifically the HDMI state helper tests)
>> - Link to v3: https://lore.kernel.org/r/20241016-concurrent-wb-v3-0-a33cf9b93835@quicinc.com
>>
>> Changes in v3:
>> - Dropped support for CWB on DP connectors for now
>> - Dropped unnecessary PINGPONG array in *_setup_cwb()
>> - Add a check to make sure CWB and CDM aren't supported simultaneously
>> (Dmitry)
>> - Document cwb_enabled checks in dpu_crtc_get_topology() (Dmitry)
>> - Moved implementation of drm_crtc_in_clone_mode() to drm_crtc.c (Jani)
>> - Dropped duplicate error message for reserving CWB resources (Dmitry)
>> - Added notes in framework changes about posting a separate series to
>> add proper KUnit tests (Maxime)
>> - Added commit message note addressing Sima's comment on handling
>> mode_changed (Dmitry)
>> - Formatting fixes (Dmitry)
>> - Added proper kerneldocs (Dmitry)
>> - Renamed dpu_encoder_helper_get_cwb() -> *_get_cwb_mask() (Dmitry)
>> - Capitalize all instances of "pingpong" in comments (Dmitry)
>> - Link to v2: https://lore.kernel.org/r/20240924-concurrent-wb-v2-0-7849f900e863@quicinc.com
>>
>> Changes in v2:
>> - Moved CWB hardware programming to its own dpu_hw_cwb abstraction
>> (Dmitry)
>> - Reserve and get assigned CWB muxes using RM API and KMS global state
>> (Dmitry)
>> - Dropped requirement to have only one CWB session at a time
>> - Moved valid clone mode check to DRM framework (Dmitry and Ville)
>> - Switch to default CWB tap point to LM as the DSPP
>> - Dropped printing clone mode status in atomic state (Dmitry)
>> - Call dpu_vbif_clear_errors() before dpu_encoder_kickoff() (Dmitry)
>> - Squashed setup_input_ctrl() and setup_input_mode() into a single
>> dpu_hw_cwb op (Dmitry)
>> - Moved function comment docs to correct place and fixed wording of
>> comments/commit messages (Dmitry)
>> - Grabbed old CRTC state using proper drm_atomic_state API in
>> dpu_crtc_atomic_check() (Dmitry)
>> - Split HW catalog changes of adding the CWB mux block and changing the
>> dedicated CWB pingpong indices into 2 separate commits (Dmitry)
>> - Moved clearing the dpu_crtc_state.num_mixers to "drm/msm/dpu: fill
>> CRTC resources in dpu_crtc.c" (Dmitry)
>> - Fixed alignment and other formatting issues (Dmitry)
>> - Link to v1: https://lore.kernel.org/r/20240829-concurrent-wb-v1-0-502b16ae2ebb@quicinc.com
>>
>> ---
>> Dmitry Baryshkov (4):
>> drm/msm/dpu: get rid of struct dpu_rm_requirements
>> drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
>> drm/msm/dpu: move resource allocation to CRTC
>> drm/msm/dpu: fill CRTC resources in dpu_crtc.c
>>
>> Esha Bharadwaj (3):
>> drm/msm/dpu: Add CWB entry to catalog for SM8650
>> drm/msm/dpu: add devcoredumps for cwb registers
>> drm/msm/dpu: add CWB support to dpu_hw_wb
>>
>> Jessica Zhang (18):
>> drm: add clone mode check for CRTC
>> drm/tests: Add test for drm_crtc_in_clone_mode()
>> drm: Add valid clones check
>> drm/tests: Add test for drm_atomic_helper_check_modeset()
>> drm/msm/dpu: Specify dedicated CWB pingpong blocks
>> drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block
>> drm/msm/dpu: Add RM support for allocating CWB
>> drm/msm/dpu: Add CWB to msm_display_topology
>> drm/msm/dpu: Require modeset if clone mode status changes
>> drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
>> drm/msm/dpu: Reserve resources for CWB
>> drm/msm/dpu: Configure CWB in writeback encoder
>> drm/msm/dpu: Support CWB in dpu_hw_ctl
>> drm/msm/dpu: Adjust writeback phys encoder setup for CWB
>> drm/msm/dpu: Start frame done timer after encoder kickoff
>> drm/msm/dpu: Skip trigger flush and start for CWB
>> drm/msm/dpu: Reorder encoder kickoff for CWB
>> drm/msm/dpu: Set possible clones for all encoders
>>
>> drivers/gpu/drm/drm_atomic_helper.c | 28 ++
>> drivers/gpu/drm/drm_crtc.c | 20 +
>> drivers/gpu/drm/msm/Makefile | 1 +
>> .../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +-
>> .../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h | 4 +-
>> .../drm/msm/disp/dpu1/catalog/dpu_8_4_sa8775p.h | 4 +-
>> .../gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h | 4 +-
>> .../drm/msm/disp/dpu1/catalog/dpu_9_2_x1e80100.h | 4 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 208 ++++++++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 463 ++++++++++++---------
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 14 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 7 +-
>> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 16 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h | 13 +
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 15 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.c | 73 ++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_cwb.h | 70 ++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 15 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 4 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 12 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 13 +-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 361 +++++++++-------
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 13 +-
>> drivers/gpu/drm/tests/drm_atomic_state_test.c | 133 +++++-
>> include/drm/drm_crtc.h | 2 +-
>> 26 files changed, 1172 insertions(+), 384 deletions(-)
>> ---
>> base-commit: 86313a9cd152330c634b25d826a281c6a002eb77
>> change-id: 20240618-concurrent-wb-97d62387f952
>> prerequisite-change-id: 20241209-abhinavk-modeset-fix-74864f1de08d:v3
>> prerequisite-patch-id: a197a0cd4647cb189ea20a96583ea78d0c98b638
>> prerequisite-patch-id: 112c8f1795cbed989beb02b72561854c0ccd59dd
>>
>> Best regards,
>> --
>> Jessica Zhang <quic_jesszhan@quicinc.com>
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-20 5:52 ` Dmitry Baryshkov
@ 2024-12-21 0:12 ` Jessica Zhang
2024-12-21 1:07 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-21 0:12 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
>> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
>>
>> For concurrent writeback, even-indexed CWB muxes must be assigned to
>> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
>> even/odd rule applies for dedicated CWB PINGPONGs.
>>
>> Track the CWB muxes in the global state and add a CWB-specific helper to
>> reserve the correct CWB muxes and dedicated PINGPONGs following the
>> even/odd rule.
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
>> 4 files changed, 116 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -2,7 +2,7 @@
>> /*
>> * Copyright (C) 2013 Red Hat
>> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> *
>> * Author: Rob Clark <robdclark@gmail.com>
>> */
>> @@ -28,6 +28,7 @@
>> #include "dpu_hw_dsc.h"
>> #include "dpu_hw_merge3d.h"
>> #include "dpu_hw_cdm.h"
>> +#include "dpu_hw_cwb.h"
>> #include "dpu_formats.h"
>> #include "dpu_encoder_phys.h"
>> #include "dpu_crtc.h"
>> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
>> * @cur_slave: As above but for the slave encoder.
>> * @hw_pp: Handle to the pingpong blocks used for the display. No.
>> * pingpong blocks can be different than num_phys_encs.
>> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
>> + * display. Number of CWB muxes can be different than
>> + * num_phys_encs.
>> * @hw_dsc: Handle to the DSC blocks used for the display.
>> * @dsc_mask: Bitmask of used DSC blocks.
>> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
>> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
>> struct dpu_encoder_phys *cur_master;
>> struct dpu_encoder_phys *cur_slave;
>> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
>> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
>> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
>>
>> unsigned int dsc_mask;
>> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>> 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_dsc[MAX_CHANNELS_PER_ENC];
>> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
>> int num_pp, num_dsc, num_ctl;
>> + int num_cwb = 0;
>> + bool is_cwb_encoder;
>> unsigned int dsc_mask = 0;
>> int i;
>>
>> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>
>> priv = drm_enc->dev->dev_private;
>> dpu_kms = to_dpu_kms(priv->kms);
>> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
>> + dpu_enc->disp_info.intf_type == INTF_WB;
>>
>> global_state = dpu_kms_get_existing_global_state(dpu_kms);
>> if (IS_ERR_OR_NULL(global_state)) {
>> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>> trace_dpu_enc_mode_set(DRMID(drm_enc));
>>
>> /* Query resource that have been reserved in atomic check step. */
>> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>> - ARRAY_SIZE(hw_pp));
>> + if (is_cwb_encoder) {
>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> + drm_enc->crtc,
>> + DPU_HW_BLK_DCWB_PINGPONG,
>> + hw_pp, ARRAY_SIZE(hw_pp));
>> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> + drm_enc->crtc,
>> + DPU_HW_BLK_CWB,
>> + hw_cwb, ARRAY_SIZE(hw_cwb));
>> + } else {
>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> + drm_enc->crtc,
>> + DPU_HW_BLK_PINGPONG, hw_pp,
>> + ARRAY_SIZE(hw_pp));
>> + }
>> +
>> + for (i = 0; i < num_cwb; i++)
>> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
>> +
>> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
>> DPU_HW_BLK_LM,
>> DPU_HW_BLK_CTL,
>> DPU_HW_BLK_PINGPONG,
>> + DPU_HW_BLK_DCWB_PINGPONG,
>> DPU_HW_BLK_INTF,
>> DPU_HW_BLK_WB,
>> DPU_HW_BLK_DSPP,
>> DPU_HW_BLK_MERGE_3D,
>> DPU_HW_BLK_DSC,
>> DPU_HW_BLK_CDM,
>> + DPU_HW_BLK_CWB,
>> DPU_HW_BLK_MAX,
>> };
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>> @@ -128,6 +128,7 @@ struct dpu_global_state {
>> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>> uint32_t cdm_to_crtc_id;
>> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
>> };
>>
>> struct dpu_global_state
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>> return -EINVAL;
>> }
>>
>> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
>> + struct dpu_global_state *global_state,
>> + uint32_t crtc_id,
>> + struct msm_display_topology *topology)
>> +{
>> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
>> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
>> + int cwb_pp_idx[MAX_BLOCKS];
>> + int cwb_mux_idx[MAX_BLOCKS];
>> +
>> + /*
>> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
>> + * mixer
>> + *
>> + * TODO: add support reserving resources for platforms with no
>> + * PINGPONG_CWB
>
> What about doing it other way around: allocate CWBs first as required
> (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
> (I think it's enough to simply make CWB blocks have a corresponding PP
> index as a property). This way the driver can handle both legacy and
> current platforms.
Hi Dmitry,
Sorry if I'm misunderstanding your suggestion, but the main change
needed to support platforms with no dedicated PINGPONG_CWB is where in
the rm->pingpong_blks list to start assigning pingpong blocks for the
CWB mux. I'm not sure how changing the order in which CWBs and the
pingpong blocks are assigned will address that.
(FWIW, the only change necessary to add support for non-dedicated
PINGPONG_CWBs platforms for this function should just be changing the
initialization value of cwb_pp_start_idx)
Thanks,
Jessica Zhang
>
>> + */
>> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>> + cwb_pp_count < num_cwb_pp; i++) {
>> + for (int j = cwb_pp_start_idx;
>> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
>> + /*
>> + * Odd LMs must be assigned to odd PINGPONGs and even
>> + * LMs with even PINGPONGs
>> + */
>> + if (reserved_by_other(global_state->pingpong_to_crtc_id, j, crtc_id) ||
>> + i % 2 != j % 2)
>> + continue;
>> +
>> + cwb_pp_idx[cwb_pp_count] = j;
>> + cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
>> + cwb_pp_count++;
>> + break;
>> + }
>> + }
>> +
>> + if (cwb_pp_count != num_cwb_pp) {
>> + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
>> + return -ENAVAIL;
>> + }
>> +
>> + for (int i = 0; i < cwb_pp_count; i++) {
>> + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
>> + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> /**
>> * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
>> * proposed use case requirements, incl. hardwired dependent blocks like
>> @@ -614,6 +663,12 @@ static int _dpu_rm_make_reservation(
>> return ret;
>> }
>>
>> + if (topology->cwb_enabled) {
>> + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
>> + crtc_id, topology);
>> + if (ret)
>> + return ret;
>> + }
>>
>> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>> topology);
>> @@ -671,6 +726,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>> _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
>> ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
>> _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
>> + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
>> + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
>> }
>>
>> /**
>> @@ -733,6 +790,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>
>> switch (type) {
>> case DPU_HW_BLK_PINGPONG:
>> + case DPU_HW_BLK_DCWB_PINGPONG:
>> hw_blks = rm->pingpong_blks;
>> hw_to_crtc_id = global_state->pingpong_to_crtc_id;
>> max_blks = ARRAY_SIZE(rm->pingpong_blks);
>> @@ -762,6 +820,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>> hw_to_crtc_id = &global_state->cdm_to_crtc_id;
>> max_blks = 1;
>> break;
>> + case DPU_HW_BLK_CWB:
>> + hw_blks = rm->cwb_blks;
>> + hw_to_crtc_id = global_state->cwb_to_crtc_id;
>> + max_blks = ARRAY_SIZE(rm->cwb_blks);
>> + break;
>> default:
>> DPU_ERROR("blk type %d not managed by rm\n", type);
>> return 0;
>> @@ -772,6 +835,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>> if (hw_to_crtc_id[i] != crtc_id)
>> continue;
>>
>> + if (type == DPU_HW_BLK_PINGPONG) {
>> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
>> +
>> + if (pp->idx >= PINGPONG_CWB_0)
>> + continue;
>> + }
>> +
>> + if (type == DPU_HW_BLK_DCWB_PINGPONG) {
>> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
>> +
>> + if (pp->idx < PINGPONG_CWB_0)
>> + continue;
>> + }
>> +
>> if (num_blks == blks_size) {
>> DPU_ERROR("More than %d resources assigned to crtc %d\n",
>> blks_size, crtc_id);
>> @@ -847,4 +924,10 @@ void dpu_rm_print_state(struct drm_printer *p,
>> dpu_rm_print_state_helper(p, rm->cdm_blk,
>> global_state->cdm_to_crtc_id);
>> drm_puts(p, "\n");
>> +
>> + drm_puts(p, "\tcwb=");
>> + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
>> + dpu_rm_print_state_helper(p, rm->cwb_blks[i],
>> + global_state->cwb_to_crtc_id[i]);
>> + drm_puts(p, "\n");
>> }
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-21 0:12 ` Jessica Zhang
@ 2024-12-21 1:07 ` Dmitry Baryshkov
2024-12-26 22:49 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-21 1:07 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
>
>
> On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
> > On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
> > > Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
> > >
> > > For concurrent writeback, even-indexed CWB muxes must be assigned to
> > > even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
> > > even/odd rule applies for dedicated CWB PINGPONGs.
> > >
> > > Track the CWB muxes in the global state and add a CWB-specific helper to
> > > reserve the correct CWB muxes and dedicated PINGPONGs following the
> > > even/odd rule.
> > >
> > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > ---
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
> > > 4 files changed, 116 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > @@ -2,7 +2,7 @@
> > > /*
> > > * Copyright (C) 2013 Red Hat
> > > * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
> > > - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> > > + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> > > *
> > > * Author: Rob Clark <robdclark@gmail.com>
> > > */
> > > @@ -28,6 +28,7 @@
> > > #include "dpu_hw_dsc.h"
> > > #include "dpu_hw_merge3d.h"
> > > #include "dpu_hw_cdm.h"
> > > +#include "dpu_hw_cwb.h"
> > > #include "dpu_formats.h"
> > > #include "dpu_encoder_phys.h"
> > > #include "dpu_crtc.h"
> > > @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
> > > * @cur_slave: As above but for the slave encoder.
> > > * @hw_pp: Handle to the pingpong blocks used for the display. No.
> > > * pingpong blocks can be different than num_phys_encs.
> > > + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
> > > + * display. Number of CWB muxes can be different than
> > > + * num_phys_encs.
> > > * @hw_dsc: Handle to the DSC blocks used for the display.
> > > * @dsc_mask: Bitmask of used DSC blocks.
> > > * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> > > @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
> > > struct dpu_encoder_phys *cur_master;
> > > struct dpu_encoder_phys *cur_slave;
> > > struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> > > + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> > > unsigned int dsc_mask;
> > > @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > 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_dsc[MAX_CHANNELS_PER_ENC];
> > > + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > int num_pp, num_dsc, num_ctl;
> > > + int num_cwb = 0;
> > > + bool is_cwb_encoder;
> > > unsigned int dsc_mask = 0;
> > > int i;
> > > @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > priv = drm_enc->dev->dev_private;
> > > dpu_kms = to_dpu_kms(priv->kms);
> > > + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
> > > + dpu_enc->disp_info.intf_type == INTF_WB;
> > > global_state = dpu_kms_get_existing_global_state(dpu_kms);
> > > if (IS_ERR_OR_NULL(global_state)) {
> > > @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > trace_dpu_enc_mode_set(DRMID(drm_enc));
> > > /* Query resource that have been reserved in atomic check step. */
> > > - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > - ARRAY_SIZE(hw_pp));
> > > + if (is_cwb_encoder) {
> > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > + drm_enc->crtc,
> > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > + hw_pp, ARRAY_SIZE(hw_pp));
> > > + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > + drm_enc->crtc,
> > > + DPU_HW_BLK_CWB,
> > > + hw_cwb, ARRAY_SIZE(hw_cwb));
> > > + } else {
> > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > + drm_enc->crtc,
> > > + DPU_HW_BLK_PINGPONG, hw_pp,
> > > + ARRAY_SIZE(hw_pp));
> > > + }
> > > +
> > > + for (i = 0; i < num_cwb; i++)
> > > + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
> > > +
> > > num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
> > > DPU_HW_BLK_LM,
> > > DPU_HW_BLK_CTL,
> > > DPU_HW_BLK_PINGPONG,
> > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > DPU_HW_BLK_INTF,
> > > DPU_HW_BLK_WB,
> > > DPU_HW_BLK_DSPP,
> > > DPU_HW_BLK_MERGE_3D,
> > > DPU_HW_BLK_DSC,
> > > DPU_HW_BLK_CDM,
> > > + DPU_HW_BLK_CWB,
> > > DPU_HW_BLK_MAX,
> > > };
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > @@ -128,6 +128,7 @@ struct dpu_global_state {
> > > uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > > uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > > uint32_t cdm_to_crtc_id;
> > > + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
> > > };
> > > struct dpu_global_state
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > return -EINVAL;
> > > }
> > > +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
> > > + struct dpu_global_state *global_state,
> > > + uint32_t crtc_id,
> > > + struct msm_display_topology *topology)
> > > +{
> > > + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
> > > + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
> > > + int cwb_pp_idx[MAX_BLOCKS];
> > > + int cwb_mux_idx[MAX_BLOCKS];
> > > +
> > > + /*
> > > + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
> > > + * mixer
> > > + *
> > > + * TODO: add support reserving resources for platforms with no
> > > + * PINGPONG_CWB
> >
> > What about doing it other way around: allocate CWBs first as required
> > (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
> > (I think it's enough to simply make CWB blocks have a corresponding PP
> > index as a property). This way the driver can handle both legacy and
> > current platforms.
>
> Hi Dmitry,
>
> Sorry if I'm misunderstanding your suggestion, but the main change needed to
> support platforms with no dedicated PINGPONG_CWB is where in the
> rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
> I'm not sure how changing the order in which CWBs and the pingpong blocks
> are assigned will address that.
>
> (FWIW, the only change necessary to add support for non-dedicated
> PINGPONG_CWBs platforms for this function should just be changing the
> initialization value of cwb_pp_start_idx)
If I remember correctly, we have identified several generations of DPU
wrt. CWB handling:
- 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
- 7.2, dedicated PP_1?
- 5.0+, shared PP blocks
- older DPUs, special handling of PP
If the driver allocates PP first and then first it has to allocated PP
(in a platform-specific way) and then go from PINGPONG to CWB (in a
platform-specific way). If CWB is allocated first, then you have only
one platform-specific piece of code that gets PINGPONG for the CWB (and
as this function is called after the CWB allocation, the major part of
the CWB / PP allocation is generic).
>
> Thanks,
>
> Jessica Zhang
>
> >
> > > + */
> > > + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> > > + cwb_pp_count < num_cwb_pp; i++) {
> > > + for (int j = cwb_pp_start_idx;
> > > + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
> > > + /*
> > > + * Odd LMs must be assigned to odd PINGPONGs and even
> > > + * LMs with even PINGPONGs
> > > + */
> > > + if (reserved_by_other(global_state->pingpong_to_crtc_id, j, crtc_id) ||
> > > + i % 2 != j % 2)
> > > + continue;
> > > +
> > > + cwb_pp_idx[cwb_pp_count] = j;
> > > + cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
> > > + cwb_pp_count++;
> > > + break;
> > > + }
> > > + }
> > > +
> > > + if (cwb_pp_count != num_cwb_pp) {
> > > + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
> > > + return -ENAVAIL;
> > > + }
> > > +
> > > + for (int i = 0; i < cwb_pp_count; i++) {
> > > + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
> > > + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
> > > + }
> > > +
> > > + return 0;
> > > +}
> > > +
> > > /**
> > > * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
> > > * proposed use case requirements, incl. hardwired dependent blocks like
> > > @@ -614,6 +663,12 @@ static int _dpu_rm_make_reservation(
> > > return ret;
> > > }
> > > + if (topology->cwb_enabled) {
> > > + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
> > > + crtc_id, topology);
> > > + if (ret)
> > > + return ret;
> > > + }
> > > ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> > > topology);
> > > @@ -671,6 +726,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> > > _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> > > ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> > > _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> > > + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
> > > + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
> > > }
> > > /**
> > > @@ -733,6 +790,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > switch (type) {
> > > case DPU_HW_BLK_PINGPONG:
> > > + case DPU_HW_BLK_DCWB_PINGPONG:
> > > hw_blks = rm->pingpong_blks;
> > > hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> > > max_blks = ARRAY_SIZE(rm->pingpong_blks);
> > > @@ -762,6 +820,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> > > max_blks = 1;
> > > break;
> > > + case DPU_HW_BLK_CWB:
> > > + hw_blks = rm->cwb_blks;
> > > + hw_to_crtc_id = global_state->cwb_to_crtc_id;
> > > + max_blks = ARRAY_SIZE(rm->cwb_blks);
> > > + break;
> > > default:
> > > DPU_ERROR("blk type %d not managed by rm\n", type);
> > > return 0;
> > > @@ -772,6 +835,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > if (hw_to_crtc_id[i] != crtc_id)
> > > continue;
> > > + if (type == DPU_HW_BLK_PINGPONG) {
> > > + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
> > > +
> > > + if (pp->idx >= PINGPONG_CWB_0)
> > > + continue;
> > > + }
> > > +
> > > + if (type == DPU_HW_BLK_DCWB_PINGPONG) {
> > > + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
> > > +
> > > + if (pp->idx < PINGPONG_CWB_0)
> > > + continue;
> > > + }
> > > +
> > > if (num_blks == blks_size) {
> > > DPU_ERROR("More than %d resources assigned to crtc %d\n",
> > > blks_size, crtc_id);
> > > @@ -847,4 +924,10 @@ void dpu_rm_print_state(struct drm_printer *p,
> > > dpu_rm_print_state_helper(p, rm->cdm_blk,
> > > global_state->cdm_to_crtc_id);
> > > drm_puts(p, "\n");
> > > +
> > > + drm_puts(p, "\tcwb=");
> > > + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
> > > + dpu_rm_print_state_helper(p, rm->cwb_blks[i],
> > > + global_state->cwb_to_crtc_id[i]);
> > > + drm_puts(p, "\n");
> > > }
> > >
> > > --
> > > 2.34.1
> > >
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2024-12-17 0:43 ` [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
@ 2024-12-24 4:45 ` Dmitry Baryshkov
2024-12-24 20:00 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-24 4:45 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> Up to now the driver has been using encoder to allocate hardware
> resources. Switch it to use CRTC id in preparation for the next step.
>
> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> Changes in v4 (due to rebase):
>
> - moved *_get_assigned_resources() changes for DSPP and LM from
> encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
> 4 files changed, 110 insertions(+), 118 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
> 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));
> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
And this crashes because drm_enc->crtc isn't set yet. Was this commit
tested? Or was it only tested as a part of the patchset, after this code
has been rewritten by the subsequent patches? I will replace this with
crtc_state->crtc, but generatlly this looks bad.
> 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));
> + drm_enc->crtc, 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,
> + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> ARRAY_SIZE(hw_dspp));
>
> for (i = 0; i < num_lm; i++) {
> @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
> * Dont allocate when active is false.
> */
> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> - dpu_rm_release(global_state, drm_enc);
> + dpu_rm_release(global_state, crtc_state->crtc);
>
> if (!crtc_state->active_changed || crtc_state->enable)
> ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> - drm_enc, crtc_state, &topology);
> + crtc_state->crtc, &topology);
> if (!ret)
> dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> global_state, crtc_state);
> @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>
> /* Query resource that have been reserved in atomic check step. */
> num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
> + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> 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));
> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>
> for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> : NULL;
>
> num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->base.id, DPU_HW_BLK_DSC,
> + drm_enc->crtc, DPU_HW_BLK_DSC,
> hw_dsc, ARRAY_SIZE(hw_dsc));
> for (i = 0; i < num_dsc; i++) {
> dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
> @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> struct dpu_hw_blk *hw_cdm = NULL;
>
> dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->base.id, DPU_HW_BLK_CDM,
> + drm_enc->crtc, DPU_HW_BLK_CDM,
> &hw_cdm, 1);
> dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> }
> @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
>
> num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
> - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>
> for (i = 0; i < num_lm; i++) {
> hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> @@ -122,12 +122,12 @@ struct dpu_global_state {
>
> struct dpu_rm *rm;
>
> - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> - uint32_t cdm_to_enc_id;
> + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
> + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
> + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
> + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> + uint32_t cdm_to_crtc_id;
> };
>
> struct dpu_global_state
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -22,9 +22,9 @@
>
>
> static inline bool reserved_by_other(uint32_t *res_map, int idx,
> - uint32_t enc_id)
> + uint32_t crtc_id)
> {
> - return res_map[idx] && res_map[idx] != enc_id;
> + return res_map[idx] && res_map[idx] != crtc_id;
> }
>
> /**
> @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> * pingpong
> * @rm: dpu resource manager handle
> * @global_state: resources shared across multiple kms objects
> - * @enc_id: encoder id requesting for allocation
> + * @crtc_id: crtc id requesting for allocation
> * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
> * if lm, and all other hardwired blocks connected to the lm (pp) is
> * available and appropriate
> @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> */
> static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> struct msm_display_topology *topology)
> {
> const struct dpu_lm_cfg *lm_cfg;
> int idx;
>
> /* Already reserved? */
> - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
> + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
> DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
> return false;
> }
> @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> return false;
> }
>
> - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
> + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
> DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
> lm_cfg->pingpong);
> return false;
> @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> return false;
> }
>
> - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
> + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
> DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
> lm_cfg->dspp);
> return false;
> @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>
> static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - uint32_t enc_id,
> + uint32_t crtc_id,
> struct msm_display_topology *topology)
>
> {
> @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> lm_idx[lm_count] = i;
>
> if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> - enc_id, i, &pp_idx[lm_count],
> + crtc_id, i, &pp_idx[lm_count],
> &dspp_idx[lm_count], topology)) {
> continue;
> }
> @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> continue;
>
> if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> - global_state, enc_id, j,
> + global_state, crtc_id, j,
> &pp_idx[lm_count], &dspp_idx[lm_count],
> topology)) {
> continue;
> @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> }
>
> for (i = 0; i < lm_count; i++) {
> - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> - global_state->dspp_to_enc_id[dspp_idx[i]] =
> - topology->num_dspp ? enc_id : 0;
> + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
> + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
> + global_state->dspp_to_crtc_id[dspp_idx[i]] =
> + topology->num_dspp ? crtc_id : 0;
>
> - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
> pp_idx[i] + PINGPONG_0);
> }
>
> @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> static int _dpu_rm_reserve_ctls(
> struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - uint32_t enc_id,
> + uint32_t crtc_id,
> const struct msm_display_topology *top)
> {
> int ctl_idx[MAX_BLOCKS];
> @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
>
> if (!rm->ctl_blks[j])
> continue;
> - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
> + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
> continue;
>
> ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
> @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
> return -ENAVAIL;
>
> for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
> - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
> - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
> + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
> + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
> }
>
> return 0;
> @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
>
> static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
> int start,
> - uint32_t enc_id)
> + uint32_t crtc_id)
> {
> int i;
>
> for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
> - if (global_state->pingpong_to_enc_id[i] == enc_id)
> + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
> return i;
> }
>
> @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
>
> static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - uint32_t enc_id,
> + uint32_t crtc_id,
> const struct msm_display_topology *top)
> {
> int num_dsc = 0;
> @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> if (!rm->dsc_blks[dsc_idx])
> continue;
>
> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
> continue;
>
> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> if (pp_idx < 0)
> return -ENAVAIL;
>
> @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> if (ret)
> return -ENAVAIL;
>
> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> num_dsc++;
> pp_idx++;
> }
> @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>
> static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - uint32_t enc_id,
> + uint32_t crtc_id,
> const struct msm_display_topology *top)
> {
> int num_dsc = 0;
> @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> continue;
>
> /* consective dsc index to be paired */
> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
> - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
> + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
> continue;
>
> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> if (pp_idx < 0)
> return -ENAVAIL;
>
> @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> continue;
> }
>
> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
> if (pp_idx < 0)
> return -ENAVAIL;
>
> @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> continue;
> }
>
> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
> num_dsc += 2;
> pp_idx++; /* start for next pair */
> }
> @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>
> static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - struct drm_encoder *enc,
> + uint32_t crtc_id,
> const struct msm_display_topology *top)
> {
> - uint32_t enc_id = enc->base.id;
> -
> if (!top->num_dsc || !top->num_intf)
> return 0;
>
> @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>
> /* num_dsc should be either 1, 2 or 4 */
> if (top->num_dsc > top->num_intf) /* merge mode */
> - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
> + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
> else
> - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
> + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
>
> return 0;
> }
>
> static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - struct drm_encoder *enc)
> + uint32_t crtc_id)
> {
> /* try allocating only one CDM block */
> if (!rm->cdm_blk) {
> @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> return -EIO;
> }
>
> - if (global_state->cdm_to_enc_id) {
> + if (global_state->cdm_to_crtc_id) {
> DPU_ERROR("CDM_0 is already allocated\n");
> return -EIO;
> }
>
> - global_state->cdm_to_enc_id = enc->base.id;
> + global_state->cdm_to_crtc_id = crtc_id;
>
> return 0;
> }
> @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> static int _dpu_rm_make_reservation(
> struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - struct drm_encoder *enc,
> + uint32_t crtc_id,
> struct msm_display_topology *topology)
> {
> int ret;
>
> - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
> if (ret) {
> DPU_ERROR("unable to find appropriate mixers\n");
> return ret;
> }
>
> - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> +
> + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> topology);
> if (ret) {
> DPU_ERROR("unable to find appropriate CTL\n");
> return ret;
> }
>
> - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
> if (ret)
> return ret;
>
> if (topology->needs_cdm) {
> - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
> if (ret) {
> DPU_ERROR("unable to find CDM blk\n");
> return ret;
> @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
> }
>
> static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> - uint32_t enc_id)
> + uint32_t crtc_id)
> {
> int i;
>
> for (i = 0; i < cnt; i++) {
> - if (res_mapping[i] == enc_id)
> + if (res_mapping[i] == crtc_id)
> res_mapping[i] = 0;
> }
> }
> @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> * dpu_rm_release - Given the encoder for the display chain, release any
> * HW blocks previously reserved for that use case.
> * @global_state: resources shared across multiple kms objects
> - * @enc: DRM Encoder handle
> + * @crtc: DRM CRTC handle
> * @return: 0 on Success otherwise -ERROR
> */
> void dpu_rm_release(struct dpu_global_state *global_state,
> - struct drm_encoder *enc)
> + struct drm_crtc *crtc)
> {
> - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
> - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
> - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
> - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
> - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
> - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
> - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> + uint32_t crtc_id = crtc->base.id;
> +
> + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
> + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
> + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
> + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
> + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
> + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
> + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
> + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
> + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> }
>
> /**
> @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> * HW Reservations should be released via dpu_rm_release_hw.
> * @rm: DPU Resource Manager handle
> * @global_state: resources shared across multiple kms objects
> - * @enc: DRM Encoder handle
> - * @crtc_state: Proposed Atomic DRM CRTC State handle
> + * @crtc: DRM CRTC handle
> * @topology: Pointer to topology info for the display
> * @return: 0 on Success otherwise -ERROR
> */
> int dpu_rm_reserve(
> struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - struct drm_encoder *enc,
> - struct drm_crtc_state *crtc_state,
> + struct drm_crtc *crtc,
> struct msm_display_topology *topology)
> {
> int ret;
>
> - /* Check if this is just a page-flip */
> - if (!drm_atomic_crtc_needs_modeset(crtc_state))
> - return 0;
> -
> if (IS_ERR(global_state)) {
> DPU_ERROR("failed to global state\n");
> return PTR_ERR(global_state);
> }
>
> - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> - enc->base.id, crtc_state->crtc->base.id);
> + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
>
> DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> topology->num_lm, topology->num_dsc,
> topology->num_intf);
>
> - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
> if (ret)
> DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>
> -
> -
> return ret;
> }
>
> @@ -705,48 +697,49 @@ int dpu_rm_reserve(
> * assigned to this encoder
> * @rm: DPU Resource Manager handle
> * @global_state: resources shared across multiple kms objects
> - * @enc_id: encoder id requesting for allocation
> + * @crtc: DRM CRTC handle
> * @type: resource type to return data for
> * @blks: pointer to the array to be filled by HW resources
> * @blks_size: size of the @blks array
> */
> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> - struct dpu_global_state *global_state, uint32_t enc_id,
> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
> {
> + uint32_t crtc_id = crtc->base.id;
> struct dpu_hw_blk **hw_blks;
> - uint32_t *hw_to_enc_id;
> + uint32_t *hw_to_crtc_id;
> int i, num_blks, max_blks;
>
> switch (type) {
> case DPU_HW_BLK_PINGPONG:
> hw_blks = rm->pingpong_blks;
> - hw_to_enc_id = global_state->pingpong_to_enc_id;
> + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->pingpong_blks);
> break;
> case DPU_HW_BLK_LM:
> hw_blks = rm->mixer_blks;
> - hw_to_enc_id = global_state->mixer_to_enc_id;
> + hw_to_crtc_id = global_state->mixer_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->mixer_blks);
> break;
> case DPU_HW_BLK_CTL:
> hw_blks = rm->ctl_blks;
> - hw_to_enc_id = global_state->ctl_to_enc_id;
> + hw_to_crtc_id = global_state->ctl_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->ctl_blks);
> break;
> case DPU_HW_BLK_DSPP:
> hw_blks = rm->dspp_blks;
> - hw_to_enc_id = global_state->dspp_to_enc_id;
> + hw_to_crtc_id = global_state->dspp_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->dspp_blks);
> break;
> case DPU_HW_BLK_DSC:
> hw_blks = rm->dsc_blks;
> - hw_to_enc_id = global_state->dsc_to_enc_id;
> + hw_to_crtc_id = global_state->dsc_to_crtc_id;
> max_blks = ARRAY_SIZE(rm->dsc_blks);
> break;
> case DPU_HW_BLK_CDM:
> hw_blks = &rm->cdm_blk;
> - hw_to_enc_id = &global_state->cdm_to_enc_id;
> + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> max_blks = 1;
> break;
> default:
> @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>
> num_blks = 0;
> for (i = 0; i < max_blks; i++) {
> - if (hw_to_enc_id[i] != enc_id)
> + if (hw_to_crtc_id[i] != crtc_id)
> continue;
>
> if (num_blks == blks_size) {
> - DPU_ERROR("More than %d resources assigned to enc %d\n",
> - blks_size, enc_id);
> + DPU_ERROR("More than %d resources assigned to crtc %d\n",
> + blks_size, crtc_id);
> break;
> }
> if (!hw_blks[i]) {
> - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
> - type, enc_id);
> + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
> + type, crtc_id);
> break;
> }
> blks[num_blks++] = hw_blks[i];
> @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
>
> drm_puts(p, "resource mapping:\n");
> drm_puts(p, "\tpingpong=");
> - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
> + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
> dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
> - global_state->pingpong_to_enc_id[i]);
> + global_state->pingpong_to_crtc_id[i]);
> drm_puts(p, "\n");
>
> drm_puts(p, "\tmixer=");
> - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
> + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
> dpu_rm_print_state_helper(p, rm->mixer_blks[i],
> - global_state->mixer_to_enc_id[i]);
> + global_state->mixer_to_crtc_id[i]);
> drm_puts(p, "\n");
>
> drm_puts(p, "\tctl=");
> - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
> + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
> dpu_rm_print_state_helper(p, rm->ctl_blks[i],
> - global_state->ctl_to_enc_id[i]);
> + global_state->ctl_to_crtc_id[i]);
> drm_puts(p, "\n");
>
> drm_puts(p, "\tdspp=");
> - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
> + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
> dpu_rm_print_state_helper(p, rm->dspp_blks[i],
> - global_state->dspp_to_enc_id[i]);
> + global_state->dspp_to_crtc_id[i]);
> drm_puts(p, "\n");
>
> drm_puts(p, "\tdsc=");
> - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
> + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
> dpu_rm_print_state_helper(p, rm->dsc_blks[i],
> - global_state->dsc_to_enc_id[i]);
> + global_state->dsc_to_crtc_id[i]);
> drm_puts(p, "\n");
>
> drm_puts(p, "\tcdm=");
> dpu_rm_print_state_helper(p, rm->cdm_blk,
> - global_state->cdm_to_enc_id);
> + global_state->cdm_to_crtc_id);
> drm_puts(p, "\n");
> }
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
>
> int dpu_rm_reserve(struct dpu_rm *rm,
> struct dpu_global_state *global_state,
> - struct drm_encoder *drm_enc,
> - struct drm_crtc_state *crtc_state,
> + struct drm_crtc *crtc,
> struct msm_display_topology *topology);
>
> void dpu_rm_release(struct dpu_global_state *global_state,
> - struct drm_encoder *enc);
> + struct drm_crtc *crtc);
>
> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> - struct dpu_global_state *global_state, uint32_t enc_id,
> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
>
> void dpu_rm_print_state(struct drm_printer *p,
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-17 0:43 ` [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
2024-12-17 1:47 ` Abhinav Kumar
@ 2024-12-24 5:02 ` Dmitry Baryshkov
2024-12-26 18:14 ` Jessica Zhang
1 sibling, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-24 5:02 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Mon, Dec 16, 2024 at 04:43:18PM -0800, Jessica Zhang wrote:
> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>
> All resource allocation is centered around the LMs. Then other blocks
> (except DSCs) are allocated basing on the LMs that was selected, and LM
> powers up the CRTC rather than the encoder.
>
> Moreover if at some point the driver supports encoder cloning,
> allocating resources from the encoder will be incorrect, as all clones
> will have different encoder IDs, while LMs are to be shared by these
> encoders.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> [quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> [quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
> 3 files changed, 181 insertions(+), 169 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
> return false;
> }
>
> +#define MAX_HDISPLAY_SPLIT 1080
> +
> +static struct msm_display_topology dpu_crtc_get_topology(
> + struct drm_crtc *crtc,
> + struct dpu_kms *dpu_kms,
> + struct drm_crtc_state *crtc_state)
> +{
> + struct drm_display_mode *mode = &crtc_state->adjusted_mode;
> + struct msm_display_topology topology = {0};
> + struct drm_encoder *drm_enc;
> +
> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
> + dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> + &crtc_state->adjusted_mode);
> +
> + /*
> + * Datapath topology selection
> + *
> + * Dual display
> + * 2 LM, 2 INTF ( Split display using 2 interfaces)
> + *
> + * Single display
> + * 1 LM, 1 INTF
> + * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> + *
> + * Add dspps to the reservation requirements if ctm is requested
> + */
> +
> + if (topology.num_intf == 2)
> + topology.num_lm = 2;
> + else if (topology.num_dsc == 2)
> + topology.num_lm = 2;
> + else if (dpu_kms->catalog->caps->has_3d_merge)
> + topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
> + else
> + topology.num_lm = 1;
> +
> + if (crtc_state->ctm)
> + topology.num_dspp = topology.num_lm;
> +
> + return topology;
> +}
> +
> +static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
> +{
> + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
> + struct dpu_global_state *global_state;
> + struct msm_display_topology topology;
> + int ret;
> +
> + /*
> + * Release and Allocate resources on every modeset
> + * Dont allocate when enable is false.
> + */
> + global_state = dpu_kms_get_existing_global_state(dpu_kms);
> + if (IS_ERR(global_state))
> + return PTR_ERR(global_state);
> +
> + dpu_rm_release(global_state, crtc);
> +
> + if (!crtc_state->enable)
> + return 0;
> +
> + topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
> + ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> + crtc, &topology);
> + if (ret)
> + return ret;
> +
> + return 0;
> +}
> +
> static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> struct drm_atomic_state *state)
> {
> @@ -1193,10 +1265,24 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> const struct drm_plane_state *pstate;
> struct drm_plane *plane;
>
> + struct drm_encoder *drm_enc;
> +
> int rc = 0;
>
> bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
>
> + /* there might be cases where encoder needs a modeset too */
> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
> + if (dpu_encoder_needs_modeset(drm_enc, crtc_state->state))
> + crtc_state->mode_changed = true;
I will postpone this patch for a while, pending the review of the
drm_atomic_helper_check_modeset() series
https://lore.kernel.org/dri-devel/20241222-drm-dirty-modeset-v1-0-0e76a53eceb9@linaro.org/
Not to mention that this commit looks broken, see below.
> + }
> +
> + if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> + rc = dpu_crtc_assign_resources(crtc, crtc_state);
> + if (rc < 0)
> + return rc;
> + }
> +
> if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
> DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
> crtc->base.id, crtc_state->enable,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index e6f930dd34566d01223823de82c922668e6be300..2b999a0558b2a016644ed5d25bf54ab45c38d1d9 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -58,8 +58,6 @@
>
> #define IDLE_SHORT_TIMEOUT 1
>
> -#define MAX_HDISPLAY_SPLIT 1080
> -
> /* timeout in frames waiting for frame done */
> #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
>
> @@ -609,206 +607,127 @@ void dpu_encoder_helper_split_config(
> }
> }
>
> -/**
> - * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
> - * @drm_enc: Pointer to previously created drm encoder structure
> - */
> -bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
> +void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
> + struct msm_display_topology *topology,
> + struct drm_atomic_state *state,
> + const struct drm_display_mode *adj_mode)
> {
> struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> - int i, intf_count = 0, num_dsc = 0;
> + struct drm_connector *connector;
> + struct drm_connector_state *conn_state;
> + struct msm_display_info *disp_info;
> + struct drm_framebuffer *fb;
> + struct msm_drm_private *priv;
> + int i;
>
> for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> if (dpu_enc->phys_encs[i])
> - intf_count++;
> + topology->num_intf++;
>
> - /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
> + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
> if (dpu_enc->dsc)
> - num_dsc = 2;
> -
> - return (num_dsc > 0) && (num_dsc > intf_count);
> -}
> -
> -/**
> - * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
> - * This helper function is used by physical encoder to get DSC config
> - * used for this encoder.
> - * @drm_enc: Pointer to encoder structure
> - */
> -struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
> -{
> - struct msm_drm_private *priv = drm_enc->dev->dev_private;
> - struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> - int index = dpu_enc->disp_info.h_tile_instance[0];
> + topology->num_dsc += 2;
>
> - if (dpu_enc->disp_info.intf_type == INTF_DSI)
> - return msm_dsi_get_dsc_config(priv->dsi[index]);
> + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
> + if (!connector)
> + return;
> + conn_state = drm_atomic_get_new_connector_state(state, connector);
> + if (!conn_state)
> + return;
>
> - return NULL;
> -}
> + disp_info = &dpu_enc->disp_info;
>
> -static struct msm_display_topology dpu_encoder_get_topology(
> - struct dpu_encoder_virt *dpu_enc,
> - struct dpu_kms *dpu_kms,
> - struct drm_display_mode *mode,
> - struct drm_crtc_state *crtc_state,
> - struct drm_dsc_config *dsc)
> -{
> - struct msm_display_topology topology = {0};
> - int i, intf_count = 0;
> + priv = drm_enc->dev->dev_private;
>
> - for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> - if (dpu_enc->phys_encs[i])
> - intf_count++;
> -
> - /* Datapath topology selection
> - *
> - * Dual display
> - * 2 LM, 2 INTF ( Split display using 2 interfaces)
> - *
> - * Single display
> - * 1 LM, 1 INTF
> - * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> - *
> - * Add dspps to the reservation requirements if ctm is requested
> + /*
> + * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
> + * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
> + * earlier.
> */
> - if (intf_count == 2)
> - topology.num_lm = 2;
> - else if (!dpu_kms->catalog->caps->has_3d_merge)
> - topology.num_lm = 1;
> - else
> - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
> -
> - if (crtc_state->ctm)
> - topology.num_dspp = topology.num_lm;
> -
> - topology.num_intf = intf_count;
> + if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
> + fb = conn_state->writeback_job->fb;
>
> - if (dsc) {
> - /*
> - * In case of Display Stream Compression (DSC), we would use
> - * 2 DSC encoders, 2 layer mixers and 1 interface
> - * this is power optimal and can drive up to (including) 4k
> - * screens
> - */
> - topology.num_dsc = 2;
> - topology.num_lm = 2;
> - topology.num_intf = 1;
> + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
> + topology->needs_cdm = true;
> + } else if (disp_info->intf_type == INTF_DP) {
> + if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
> + topology->needs_cdm = true;
> }
> -
> - 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)
> +static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
> {
> - 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> - drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> - ARRAY_SIZE(hw_dspp));
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> + u32 num_intf = 0;
> + u32 num_dsc = 0;
> + int i;
>
> - for (i = 0; i < num_lm; i++) {
> - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
> + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
> + if (dpu_enc->phys_encs[i])
> + num_intf++;
>
> - 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;
> - }
> + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
> + if (dpu_enc->dsc)
> + num_dsc += 2;
>
> - cstate->num_mixers = num_lm;
> + return (num_dsc > 0) && (num_dsc > num_intf);
Ok, so after all the rebases this commit removes CRTC resource
assignment from dpu_encoder.c, but they are added to dpu_crtc.c only in
the next commit! So after this one the tree is broken. This isn't really
acceptable. After each commit the tree should work, otherwise git-bisect
might return incorrect results.
Historically this patch just moved the allocation to the
dpu_crtc_atomic_check(), while cstate has been maniputated in
dpu_encoder_virt_atomic_mode_set(). Commit 3ae133b0192b ("drm/msm/dpu:
move CRTC resource assignment to dpu_encoder_virt_atomic_check") moved
resource handling to the atomic_check() stage. I think at this point you
need to take one step back, return to the previous commits, but revert
their order: first move cstate manipulation to happen during the
dpu_crtc_atomic_check() function call, leaving dpu_rm_release() /
dpu_rm_reserve() out of dpu_crtc_assign_resources() (in
dpu_encoder_virt_atomic_check() as they are now). Then can come this
patch, which moves topology handling, resource reservation, etc. to
dpu_crtc.c.
> }
>
> -static int dpu_encoder_virt_atomic_check(
> - struct drm_encoder *drm_enc,
> - struct drm_crtc_state *crtc_state,
> - struct drm_connector_state *conn_state)
> +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state)
> {
> - struct dpu_encoder_virt *dpu_enc;
> - struct msm_drm_private *priv;
> - struct dpu_kms *dpu_kms;
> - struct drm_display_mode *adj_mode;
> - struct msm_display_topology topology;
> - struct msm_display_info *disp_info;
> - struct dpu_global_state *global_state;
> + struct drm_connector *connector;
> + struct drm_connector_state *conn_state;
> struct drm_framebuffer *fb;
> - struct drm_dsc_config *dsc;
> - int ret = 0;
> -
> - if (!drm_enc || !crtc_state || !conn_state) {
> - DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
> - drm_enc != NULL, crtc_state != NULL, conn_state != NULL);
> - return -EINVAL;
> - }
> -
> - dpu_enc = to_dpu_encoder_virt(drm_enc);
> - DPU_DEBUG_ENC(dpu_enc, "\n");
> -
> - priv = drm_enc->dev->dev_private;
> - disp_info = &dpu_enc->disp_info;
> - dpu_kms = to_dpu_kms(priv->kms);
> - adj_mode = &crtc_state->adjusted_mode;
> - global_state = dpu_kms_get_global_state(crtc_state->state);
> - if (IS_ERR(global_state))
> - return PTR_ERR(global_state);
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>
> - trace_dpu_enc_atomic_check(DRMID(drm_enc));
> + if (!drm_enc || !state)
> + return false;
>
> - dsc = dpu_encoder_get_dsc_config(drm_enc);
> + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
> + if (!connector)
> + return false;
>
> - topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc);
> + conn_state = drm_atomic_get_new_connector_state(state, connector);
>
> - /*
> - * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
> - * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
> - * earlier.
> - */
> - if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
> + if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
> fb = conn_state->writeback_job->fb;
> -
> - if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
> - topology.needs_cdm = true;
> - } else if (disp_info->intf_type == INTF_DP) {
> - if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
> - topology.needs_cdm = true;
> + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) {
> + if (!dpu_enc->cur_master->hw_cdm)
> + return true;
> + } else {
> + if (dpu_enc->cur_master->hw_cdm)
> + return true;
> + }
> }
>
> - if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
> - crtc_state->mode_changed = true;
> - else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
> - crtc_state->mode_changed = true;
> - /*
> - * Release and Allocate resources on every modeset
> - * Dont allocate when active is false.
> - */
> - if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> - dpu_rm_release(global_state, crtc_state->crtc);
> + return false;
> +}
>
> - if (!crtc_state->active_changed || crtc_state->enable)
> - ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> - crtc_state->crtc, &topology);
> - if (!ret)
> - dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> - global_state, crtc_state);
> - }
> +/**
> + * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
> + * This helper function is used by physical encoder to get DSC config
> + * used for this encoder.
> + * @drm_enc: Pointer to encoder structure
> + */
> +struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
> +{
> + struct msm_drm_private *priv = drm_enc->dev->dev_private;
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
> + int index = dpu_enc->disp_info.h_tile_instance[0];
>
> - trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
> + if (dpu_enc->disp_info.intf_type == INTF_DSI)
> + return msm_dsi_get_dsc_config(priv->dsi[index]);
>
> - return ret;
> + return NULL;
> +}
> +
> +/**
> + * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
> + * @drm_enc: Pointer to previously created drm encoder structure
> + */
> +bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
> +{
> + return dpu_encoder_needs_dsc_merge(drm_enc);
> }
>
> static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
> @@ -2627,7 +2546,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
> .atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
> .atomic_disable = dpu_encoder_virt_atomic_disable,
> .atomic_enable = dpu_encoder_virt_atomic_enable,
> - .atomic_check = dpu_encoder_virt_atomic_check,
> };
>
> static const struct drm_encoder_funcs dpu_encoder_funcs = {
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> index 92b5ee390788d16e85e195a664417896a2bf1cae..3db3ea076c377ad5411ec85006bcf4cd9757eb1d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> @@ -11,6 +11,7 @@
>
> #include <drm/drm_crtc.h>
> #include "dpu_hw_mdss.h"
> +#include "dpu_kms.h"
>
> #define DPU_ENCODER_FRAME_EVENT_DONE BIT(0)
> #define DPU_ENCODER_FRAME_EVENT_ERROR BIT(1)
> @@ -80,6 +81,13 @@ int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
>
> bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
>
> +void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
> + struct msm_display_topology *topology,
> + struct drm_atomic_state *state,
> + const struct drm_display_mode *adj_mode);
> +
> +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
> +
> void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
> struct drm_writeback_job *job);
>
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2024-12-24 4:45 ` Dmitry Baryshkov
@ 2024-12-24 20:00 ` Dmitry Baryshkov
2025-01-15 5:28 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-24 20:00 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Tue, Dec 24, 2024 at 06:45:07AM +0200, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
> > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >
> > Up to now the driver has been using encoder to allocate hardware
> > resources. Switch it to use CRTC id in preparation for the next step.
> >
> > Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > ---
> > Changes in v4 (due to rebase):
> >
> > - moved *_get_assigned_resources() changes for DSPP and LM from
> > encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
> > ---
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
> > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
> > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
> > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
> > 4 files changed, 110 insertions(+), 118 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
> > 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));
> > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>
> And this crashes because drm_enc->crtc isn't set yet. Was this commit
> tested? Or was it only tested as a part of the patchset, after this code
> has been rewritten by the subsequent patches? I will replace this with
> crtc_state->crtc, but generatlly this looks bad.
Even with this in place, it fails the kms_color@ctm-max for pipe-B-eDP-1
on SC7180 (pipe-A-eDP-1 succeeds). See job log at [1].
corresponding excerpt from the log:
[IGT] kms_color: starting dynamic subtest pipe-B-eDP-1
[drm:_dpu_rm_check_lm_and_get_connected_blks] [dpu error]failed to get dspp on lm 0
[drm:_dpu_rm_make_reservation] [dpu error]unable to find appropriate mixers
[drm:dpu_rm_reserve] [dpu error]failed to reserve hw resources: -119
[IGT] kms_color: finished subtest pipe-B-eDP-1, FAIL
FWIW it looks like during an attempt to use second CRTC the driver
doesn't release resources for the first one. I'll drop this patch for
now, leaving just HW_CWB patches in.
[1] https://gitlab.freedesktop.org/drm/msm/-/jobs/68614460/viewer
>
> > 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));
> > + drm_enc->crtc, 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,
> > + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
>
>
> > ARRAY_SIZE(hw_dspp));
> >
> > for (i = 0; i < num_lm; i++) {
> > @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
> > * Dont allocate when active is false.
> > */
> > if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> > - dpu_rm_release(global_state, drm_enc);
> > + dpu_rm_release(global_state, crtc_state->crtc);
> >
> > if (!crtc_state->active_changed || crtc_state->enable)
> > ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> > - drm_enc, crtc_state, &topology);
> > + crtc_state->crtc, &topology);
> > if (!ret)
> > dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> > global_state, crtc_state);
> > @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >
> > /* Query resource that have been reserved in atomic check step. */
> > num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
> > + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > 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));
> > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> >
> > for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > : NULL;
> >
> > num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->base.id, DPU_HW_BLK_DSC,
> > + drm_enc->crtc, DPU_HW_BLK_DSC,
> > hw_dsc, ARRAY_SIZE(hw_dsc));
> > for (i = 0; i < num_dsc; i++) {
> > dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
> > @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > struct dpu_hw_blk *hw_cdm = NULL;
> >
> > dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > - drm_enc->base.id, DPU_HW_BLK_CDM,
> > + drm_enc->crtc, DPU_HW_BLK_CDM,
> > &hw_cdm, 1);
> > dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> > }
> > @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> > global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
> >
> > num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
> > - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> >
> > for (i = 0; i < num_lm; i++) {
> > hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > @@ -122,12 +122,12 @@ struct dpu_global_state {
> >
> > struct dpu_rm *rm;
> >
> > - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> > - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> > - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> > - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> > - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> > - uint32_t cdm_to_enc_id;
> > + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
> > + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
> > + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
> > + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > + uint32_t cdm_to_crtc_id;
> > };
> >
> > struct dpu_global_state
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > @@ -22,9 +22,9 @@
> >
> >
> > static inline bool reserved_by_other(uint32_t *res_map, int idx,
> > - uint32_t enc_id)
> > + uint32_t crtc_id)
> > {
> > - return res_map[idx] && res_map[idx] != enc_id;
> > + return res_map[idx] && res_map[idx] != crtc_id;
> > }
> >
> > /**
> > @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > * pingpong
> > * @rm: dpu resource manager handle
> > * @global_state: resources shared across multiple kms objects
> > - * @enc_id: encoder id requesting for allocation
> > + * @crtc_id: crtc id requesting for allocation
> > * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
> > * if lm, and all other hardwired blocks connected to the lm (pp) is
> > * available and appropriate
> > @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > */
> > static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > struct msm_display_topology *topology)
> > {
> > const struct dpu_lm_cfg *lm_cfg;
> > int idx;
> >
> > /* Already reserved? */
> > - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
> > + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
> > DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
> > return false;
> > }
> > @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > return false;
> > }
> >
> > - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
> > + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
> > DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
> > lm_cfg->pingpong);
> > return false;
> > @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > return false;
> > }
> >
> > - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
> > + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
> > DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
> > lm_cfg->dspp);
> > return false;
> > @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> >
> > static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - uint32_t enc_id,
> > + uint32_t crtc_id,
> > struct msm_display_topology *topology)
> >
> > {
> > @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > lm_idx[lm_count] = i;
> >
> > if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> > - enc_id, i, &pp_idx[lm_count],
> > + crtc_id, i, &pp_idx[lm_count],
> > &dspp_idx[lm_count], topology)) {
> > continue;
> > }
> > @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > continue;
> >
> > if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> > - global_state, enc_id, j,
> > + global_state, crtc_id, j,
> > &pp_idx[lm_count], &dspp_idx[lm_count],
> > topology)) {
> > continue;
> > @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > }
> >
> > for (i = 0; i < lm_count; i++) {
> > - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> > - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> > - global_state->dspp_to_enc_id[dspp_idx[i]] =
> > - topology->num_dspp ? enc_id : 0;
> > + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
> > + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
> > + global_state->dspp_to_crtc_id[dspp_idx[i]] =
> > + topology->num_dspp ? crtc_id : 0;
> >
> > - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> > + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
> > pp_idx[i] + PINGPONG_0);
> > }
> >
> > @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > static int _dpu_rm_reserve_ctls(
> > struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - uint32_t enc_id,
> > + uint32_t crtc_id,
> > const struct msm_display_topology *top)
> > {
> > int ctl_idx[MAX_BLOCKS];
> > @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
> >
> > if (!rm->ctl_blks[j])
> > continue;
> > - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
> > + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
> > continue;
> >
> > ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
> > @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
> > return -ENAVAIL;
> >
> > for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
> > - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
> > - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
> > + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
> > + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
> > }
> >
> > return 0;
> > @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
> >
> > static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
> > int start,
> > - uint32_t enc_id)
> > + uint32_t crtc_id)
> > {
> > int i;
> >
> > for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
> > - if (global_state->pingpong_to_enc_id[i] == enc_id)
> > + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
> > return i;
> > }
> >
> > @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
> >
> > static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - uint32_t enc_id,
> > + uint32_t crtc_id,
> > const struct msm_display_topology *top)
> > {
> > int num_dsc = 0;
> > @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > if (!rm->dsc_blks[dsc_idx])
> > continue;
> >
> > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
> > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
> > continue;
> >
> > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > if (pp_idx < 0)
> > return -ENAVAIL;
> >
> > @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > if (ret)
> > return -ENAVAIL;
> >
> > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > num_dsc++;
> > pp_idx++;
> > }
> > @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> >
> > static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - uint32_t enc_id,
> > + uint32_t crtc_id,
> > const struct msm_display_topology *top)
> > {
> > int num_dsc = 0;
> > @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > continue;
> >
> > /* consective dsc index to be paired */
> > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
> > - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
> > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
> > + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
> > continue;
> >
> > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > if (pp_idx < 0)
> > return -ENAVAIL;
> >
> > @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > continue;
> > }
> >
> > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
> > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
> > if (pp_idx < 0)
> > return -ENAVAIL;
> >
> > @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > continue;
> > }
> >
> > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
> > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
> > num_dsc += 2;
> > pp_idx++; /* start for next pair */
> > }
> > @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> >
> > static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - struct drm_encoder *enc,
> > + uint32_t crtc_id,
> > const struct msm_display_topology *top)
> > {
> > - uint32_t enc_id = enc->base.id;
> > -
> > if (!top->num_dsc || !top->num_intf)
> > return 0;
> >
> > @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> >
> > /* num_dsc should be either 1, 2 or 4 */
> > if (top->num_dsc > top->num_intf) /* merge mode */
> > - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
> > + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
> > else
> > - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
> > + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
> >
> > return 0;
> > }
> >
> > static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - struct drm_encoder *enc)
> > + uint32_t crtc_id)
> > {
> > /* try allocating only one CDM block */
> > if (!rm->cdm_blk) {
> > @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > return -EIO;
> > }
> >
> > - if (global_state->cdm_to_enc_id) {
> > + if (global_state->cdm_to_crtc_id) {
> > DPU_ERROR("CDM_0 is already allocated\n");
> > return -EIO;
> > }
> >
> > - global_state->cdm_to_enc_id = enc->base.id;
> > + global_state->cdm_to_crtc_id = crtc_id;
> >
> > return 0;
> > }
> > @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > static int _dpu_rm_make_reservation(
> > struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - struct drm_encoder *enc,
> > + uint32_t crtc_id,
> > struct msm_display_topology *topology)
> > {
> > int ret;
> >
> > - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> > + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
> > if (ret) {
> > DPU_ERROR("unable to find appropriate mixers\n");
> > return ret;
> > }
> >
> > - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> > +
> > + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> > topology);
> > if (ret) {
> > DPU_ERROR("unable to find appropriate CTL\n");
> > return ret;
> > }
> >
> > - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> > + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
> > if (ret)
> > return ret;
> >
> > if (topology->needs_cdm) {
> > - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> > + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
> > if (ret) {
> > DPU_ERROR("unable to find CDM blk\n");
> > return ret;
> > @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
> > }
> >
> > static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > - uint32_t enc_id)
> > + uint32_t crtc_id)
> > {
> > int i;
> >
> > for (i = 0; i < cnt; i++) {
> > - if (res_mapping[i] == enc_id)
> > + if (res_mapping[i] == crtc_id)
> > res_mapping[i] = 0;
> > }
> > }
> > @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > * dpu_rm_release - Given the encoder for the display chain, release any
> > * HW blocks previously reserved for that use case.
> > * @global_state: resources shared across multiple kms objects
> > - * @enc: DRM Encoder handle
> > + * @crtc: DRM CRTC handle
> > * @return: 0 on Success otherwise -ERROR
> > */
> > void dpu_rm_release(struct dpu_global_state *global_state,
> > - struct drm_encoder *enc)
> > + struct drm_crtc *crtc)
> > {
> > - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
> > - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
> > - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
> > - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
> > - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
> > - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
> > - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> > - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> > - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> > - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> > - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> > + uint32_t crtc_id = crtc->base.id;
> > +
> > + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
> > + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
> > + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
> > + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
> > + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
> > + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
> > + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
> > + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
> > + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> > + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> > + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> > }
> >
> > /**
> > @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> > * HW Reservations should be released via dpu_rm_release_hw.
> > * @rm: DPU Resource Manager handle
> > * @global_state: resources shared across multiple kms objects
> > - * @enc: DRM Encoder handle
> > - * @crtc_state: Proposed Atomic DRM CRTC State handle
> > + * @crtc: DRM CRTC handle
> > * @topology: Pointer to topology info for the display
> > * @return: 0 on Success otherwise -ERROR
> > */
> > int dpu_rm_reserve(
> > struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - struct drm_encoder *enc,
> > - struct drm_crtc_state *crtc_state,
> > + struct drm_crtc *crtc,
> > struct msm_display_topology *topology)
> > {
> > int ret;
> >
> > - /* Check if this is just a page-flip */
> > - if (!drm_atomic_crtc_needs_modeset(crtc_state))
> > - return 0;
> > -
> > if (IS_ERR(global_state)) {
> > DPU_ERROR("failed to global state\n");
> > return PTR_ERR(global_state);
> > }
> >
> > - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> > - enc->base.id, crtc_state->crtc->base.id);
> > + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
> >
> > DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> > topology->num_lm, topology->num_dsc,
> > topology->num_intf);
> >
> > - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> > + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
> > if (ret)
> > DPU_ERROR("failed to reserve hw resources: %d\n", ret);
> >
> > -
> > -
> > return ret;
> > }
> >
> > @@ -705,48 +697,49 @@ int dpu_rm_reserve(
> > * assigned to this encoder
> > * @rm: DPU Resource Manager handle
> > * @global_state: resources shared across multiple kms objects
> > - * @enc_id: encoder id requesting for allocation
> > + * @crtc: DRM CRTC handle
> > * @type: resource type to return data for
> > * @blks: pointer to the array to be filled by HW resources
> > * @blks_size: size of the @blks array
> > */
> > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > - struct dpu_global_state *global_state, uint32_t enc_id,
> > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
> > {
> > + uint32_t crtc_id = crtc->base.id;
> > struct dpu_hw_blk **hw_blks;
> > - uint32_t *hw_to_enc_id;
> > + uint32_t *hw_to_crtc_id;
> > int i, num_blks, max_blks;
> >
> > switch (type) {
> > case DPU_HW_BLK_PINGPONG:
> > hw_blks = rm->pingpong_blks;
> > - hw_to_enc_id = global_state->pingpong_to_enc_id;
> > + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> > max_blks = ARRAY_SIZE(rm->pingpong_blks);
> > break;
> > case DPU_HW_BLK_LM:
> > hw_blks = rm->mixer_blks;
> > - hw_to_enc_id = global_state->mixer_to_enc_id;
> > + hw_to_crtc_id = global_state->mixer_to_crtc_id;
> > max_blks = ARRAY_SIZE(rm->mixer_blks);
> > break;
> > case DPU_HW_BLK_CTL:
> > hw_blks = rm->ctl_blks;
> > - hw_to_enc_id = global_state->ctl_to_enc_id;
> > + hw_to_crtc_id = global_state->ctl_to_crtc_id;
> > max_blks = ARRAY_SIZE(rm->ctl_blks);
> > break;
> > case DPU_HW_BLK_DSPP:
> > hw_blks = rm->dspp_blks;
> > - hw_to_enc_id = global_state->dspp_to_enc_id;
> > + hw_to_crtc_id = global_state->dspp_to_crtc_id;
> > max_blks = ARRAY_SIZE(rm->dspp_blks);
> > break;
> > case DPU_HW_BLK_DSC:
> > hw_blks = rm->dsc_blks;
> > - hw_to_enc_id = global_state->dsc_to_enc_id;
> > + hw_to_crtc_id = global_state->dsc_to_crtc_id;
> > max_blks = ARRAY_SIZE(rm->dsc_blks);
> > break;
> > case DPU_HW_BLK_CDM:
> > hw_blks = &rm->cdm_blk;
> > - hw_to_enc_id = &global_state->cdm_to_enc_id;
> > + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> > max_blks = 1;
> > break;
> > default:
> > @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> >
> > num_blks = 0;
> > for (i = 0; i < max_blks; i++) {
> > - if (hw_to_enc_id[i] != enc_id)
> > + if (hw_to_crtc_id[i] != crtc_id)
> > continue;
> >
> > if (num_blks == blks_size) {
> > - DPU_ERROR("More than %d resources assigned to enc %d\n",
> > - blks_size, enc_id);
> > + DPU_ERROR("More than %d resources assigned to crtc %d\n",
> > + blks_size, crtc_id);
> > break;
> > }
> > if (!hw_blks[i]) {
> > - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
> > - type, enc_id);
> > + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
> > + type, crtc_id);
> > break;
> > }
> > blks[num_blks++] = hw_blks[i];
> > @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
> >
> > drm_puts(p, "resource mapping:\n");
> > drm_puts(p, "\tpingpong=");
> > - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
> > + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
> > dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
> > - global_state->pingpong_to_enc_id[i]);
> > + global_state->pingpong_to_crtc_id[i]);
> > drm_puts(p, "\n");
> >
> > drm_puts(p, "\tmixer=");
> > - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
> > + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
> > dpu_rm_print_state_helper(p, rm->mixer_blks[i],
> > - global_state->mixer_to_enc_id[i]);
> > + global_state->mixer_to_crtc_id[i]);
> > drm_puts(p, "\n");
> >
> > drm_puts(p, "\tctl=");
> > - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
> > + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
> > dpu_rm_print_state_helper(p, rm->ctl_blks[i],
> > - global_state->ctl_to_enc_id[i]);
> > + global_state->ctl_to_crtc_id[i]);
> > drm_puts(p, "\n");
> >
> > drm_puts(p, "\tdspp=");
> > - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
> > + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
> > dpu_rm_print_state_helper(p, rm->dspp_blks[i],
> > - global_state->dspp_to_enc_id[i]);
> > + global_state->dspp_to_crtc_id[i]);
> > drm_puts(p, "\n");
> >
> > drm_puts(p, "\tdsc=");
> > - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
> > + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
> > dpu_rm_print_state_helper(p, rm->dsc_blks[i],
> > - global_state->dsc_to_enc_id[i]);
> > + global_state->dsc_to_crtc_id[i]);
> > drm_puts(p, "\n");
> >
> > drm_puts(p, "\tcdm=");
> > dpu_rm_print_state_helper(p, rm->cdm_blk,
> > - global_state->cdm_to_enc_id);
> > + global_state->cdm_to_crtc_id);
> > drm_puts(p, "\n");
> > }
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
> >
> > int dpu_rm_reserve(struct dpu_rm *rm,
> > struct dpu_global_state *global_state,
> > - struct drm_encoder *drm_enc,
> > - struct drm_crtc_state *crtc_state,
> > + struct drm_crtc *crtc,
> > struct msm_display_topology *topology);
> >
> > void dpu_rm_release(struct dpu_global_state *global_state,
> > - struct drm_encoder *enc);
> > + struct drm_crtc *crtc);
> >
> > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > - struct dpu_global_state *global_state, uint32_t enc_id,
> > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
> >
> > void dpu_rm_print_state(struct drm_printer *p,
> >
> > --
> > 2.34.1
> >
>
> --
> With best wishes
> Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (25 preceding siblings ...)
2024-12-20 5:11 ` [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Dmitry Baryshkov
@ 2024-12-24 20:41 ` Dmitry Baryshkov
2025-01-07 23:50 ` (subset) " Dmitry Baryshkov
27 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-24 20:41 UTC (permalink / raw)
To: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, Jessica Zhang
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:11 -0800, Jessica Zhang wrote:
> DPU supports a single writeback session running concurrently with primary
> display when the CWB mux is configured properly. This series enables
> clone mode for DPU driver and adds support for programming the CWB mux
> in cases where the hardware has dedicated CWB pingpong blocks. Currently,
> the CWB hardware blocks have only been added to the SM8650
> hardware catalog and only DSI has been exposed as a possible_clone of WB.
>
> [...]
Applied, thanks!
[05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements
https://gitlab.freedesktop.org/lumag/msm/-/commit/835d10620445
[09/25] drm/msm/dpu: Add CWB entry to catalog for SM8650
https://gitlab.freedesktop.org/lumag/msm/-/commit/989412edae5b
[10/25] drm/msm/dpu: Specify dedicated CWB pingpong blocks
https://gitlab.freedesktop.org/lumag/msm/-/commit/d1fe88dd53ae
[11/25] drm/msm/dpu: add devcoredumps for cwb registers
https://gitlab.freedesktop.org/lumag/msm/-/commit/675c1edfa92d
[12/25] drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block
https://gitlab.freedesktop.org/lumag/msm/-/commit/aae8736426c6
[13/25] drm/msm/dpu: add CWB support to dpu_hw_wb
https://gitlab.freedesktop.org/lumag/msm/-/commit/a31a610fd44b
[14/25] drm/msm/dpu: Add RM support for allocating CWB
https://gitlab.freedesktop.org/lumag/msm/-/commit/a5463629299b
Best regards,
--
Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC
2024-12-24 5:02 ` Dmitry Baryshkov
@ 2024-12-26 18:14 ` Jessica Zhang
0 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2024-12-26 18:14 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/23/2024 9:02 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:18PM -0800, Jessica Zhang wrote:
>> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>
>> All resource allocation is centered around the LMs. Then other blocks
>> (except DSCs) are allocated basing on the LMs that was selected, and LM
>> powers up the CRTC rather than the encoder.
>>
>> Moreover if at some point the driver supports encoder cloning,
>> allocating resources from the encoder will be incorrect, as all clones
>> will have different encoder IDs, while LMs are to be shared by these
>> encoders.
>>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> [quic_abhinavk@quicinc.com: Refactored resource allocation for CDM]
>> Signed-off-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>> [quic_jesszhan@quicinc.com: Changed to grabbing exising global state]
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 86 ++++++++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 256 ++++++++++------------------
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 8 +
>> 3 files changed, 181 insertions(+), 169 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 9f6ffd344693ecfb633095772a31ada5613345dc..186ed84f59f16997716fe216e635b8dce07a63a1 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1182,6 +1182,78 @@ static bool dpu_crtc_needs_dirtyfb(struct drm_crtc_state *cstate)
>> return false;
>> }
>>
>> +#define MAX_HDISPLAY_SPLIT 1080
>> +
>> +static struct msm_display_topology dpu_crtc_get_topology(
>> + struct drm_crtc *crtc,
>> + struct dpu_kms *dpu_kms,
>> + struct drm_crtc_state *crtc_state)
>> +{
>> + struct drm_display_mode *mode = &crtc_state->adjusted_mode;
>> + struct msm_display_topology topology = {0};
>> + struct drm_encoder *drm_enc;
>> +
>> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
>> + dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>> + &crtc_state->adjusted_mode);
>> +
>> + /*
>> + * Datapath topology selection
>> + *
>> + * Dual display
>> + * 2 LM, 2 INTF ( Split display using 2 interfaces)
>> + *
>> + * Single display
>> + * 1 LM, 1 INTF
>> + * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>> + *
>> + * Add dspps to the reservation requirements if ctm is requested
>> + */
>> +
>> + if (topology.num_intf == 2)
>> + topology.num_lm = 2;
>> + else if (topology.num_dsc == 2)
>> + topology.num_lm = 2;
>> + else if (dpu_kms->catalog->caps->has_3d_merge)
>> + topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
>> + else
>> + topology.num_lm = 1;
>> +
>> + if (crtc_state->ctm)
>> + topology.num_dspp = topology.num_lm;
>> +
>> + return topology;
>> +}
>> +
>> +static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_state *crtc_state)
>> +{
>> + struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
>> + struct dpu_global_state *global_state;
>> + struct msm_display_topology topology;
>> + int ret;
>> +
>> + /*
>> + * Release and Allocate resources on every modeset
>> + * Dont allocate when enable is false.
>> + */
>> + global_state = dpu_kms_get_existing_global_state(dpu_kms);
>> + if (IS_ERR(global_state))
>> + return PTR_ERR(global_state);
>> +
>> + dpu_rm_release(global_state, crtc);
>> +
>> + if (!crtc_state->enable)
>> + return 0;
>> +
>> + topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
>> + ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> + crtc, &topology);
>> + if (ret)
>> + return ret;
>> +
>> + return 0;
>> +}
>> +
>> static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>> struct drm_atomic_state *state)
>> {
>> @@ -1193,10 +1265,24 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>> const struct drm_plane_state *pstate;
>> struct drm_plane *plane;
>>
>> + struct drm_encoder *drm_enc;
>> +
>> int rc = 0;
>>
>> bool needs_dirtyfb = dpu_crtc_needs_dirtyfb(crtc_state);
>>
>> + /* there might be cases where encoder needs a modeset too */
>> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
>> + if (dpu_encoder_needs_modeset(drm_enc, crtc_state->state))
>> + crtc_state->mode_changed = true;
>
> I will postpone this patch for a while, pending the review of the
> drm_atomic_helper_check_modeset() series
>
> https://lore.kernel.org/dri-devel/20241222-drm-dirty-modeset-v1-0-0e76a53eceb9@linaro.org/
>
> Not to mention that this commit looks broken, see below.
>
>> + }
>> +
>> + if (drm_atomic_crtc_needs_modeset(crtc_state)) {
>> + rc = dpu_crtc_assign_resources(crtc, crtc_state);
>> + if (rc < 0)
>> + return rc;
>> + }
>> +
>> if (!crtc_state->enable || !drm_atomic_crtc_effectively_active(crtc_state)) {
>> DRM_DEBUG_ATOMIC("crtc%d -> enable %d, active %d, skip atomic_check\n",
>> crtc->base.id, crtc_state->enable,
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> index e6f930dd34566d01223823de82c922668e6be300..2b999a0558b2a016644ed5d25bf54ab45c38d1d9 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -58,8 +58,6 @@
>>
>> #define IDLE_SHORT_TIMEOUT 1
>>
>> -#define MAX_HDISPLAY_SPLIT 1080
>> -
>> /* timeout in frames waiting for frame done */
>> #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
>>
>> @@ -609,206 +607,127 @@ void dpu_encoder_helper_split_config(
>> }
>> }
>>
>> -/**
>> - * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
>> - * @drm_enc: Pointer to previously created drm encoder structure
>> - */
>> -bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
>> +void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
>> + struct msm_display_topology *topology,
>> + struct drm_atomic_state *state,
>> + const struct drm_display_mode *adj_mode)
>> {
>> struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>> - int i, intf_count = 0, num_dsc = 0;
>> + struct drm_connector *connector;
>> + struct drm_connector_state *conn_state;
>> + struct msm_display_info *disp_info;
>> + struct drm_framebuffer *fb;
>> + struct msm_drm_private *priv;
>> + int i;
>>
>> for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
>> if (dpu_enc->phys_encs[i])
>> - intf_count++;
>> + topology->num_intf++;
>>
>> - /* See dpu_encoder_get_topology, we only support 2:2:1 topology */
>> + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
>> if (dpu_enc->dsc)
>> - num_dsc = 2;
>> -
>> - return (num_dsc > 0) && (num_dsc > intf_count);
>> -}
>> -
>> -/**
>> - * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
>> - * This helper function is used by physical encoder to get DSC config
>> - * used for this encoder.
>> - * @drm_enc: Pointer to encoder structure
>> - */
>> -struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
>> -{
>> - struct msm_drm_private *priv = drm_enc->dev->dev_private;
>> - struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>> - int index = dpu_enc->disp_info.h_tile_instance[0];
>> + topology->num_dsc += 2;
>>
>> - if (dpu_enc->disp_info.intf_type == INTF_DSI)
>> - return msm_dsi_get_dsc_config(priv->dsi[index]);
>> + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
>> + if (!connector)
>> + return;
>> + conn_state = drm_atomic_get_new_connector_state(state, connector);
>> + if (!conn_state)
>> + return;
>>
>> - return NULL;
>> -}
>> + disp_info = &dpu_enc->disp_info;
>>
>> -static struct msm_display_topology dpu_encoder_get_topology(
>> - struct dpu_encoder_virt *dpu_enc,
>> - struct dpu_kms *dpu_kms,
>> - struct drm_display_mode *mode,
>> - struct drm_crtc_state *crtc_state,
>> - struct drm_dsc_config *dsc)
>> -{
>> - struct msm_display_topology topology = {0};
>> - int i, intf_count = 0;
>> + priv = drm_enc->dev->dev_private;
>>
>> - for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
>> - if (dpu_enc->phys_encs[i])
>> - intf_count++;
>> -
>> - /* Datapath topology selection
>> - *
>> - * Dual display
>> - * 2 LM, 2 INTF ( Split display using 2 interfaces)
>> - *
>> - * Single display
>> - * 1 LM, 1 INTF
>> - * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>> - *
>> - * Add dspps to the reservation requirements if ctm is requested
>> + /*
>> + * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
>> + * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
>> + * earlier.
>> */
>> - if (intf_count == 2)
>> - topology.num_lm = 2;
>> - else if (!dpu_kms->catalog->caps->has_3d_merge)
>> - topology.num_lm = 1;
>> - else
>> - topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
>> -
>> - if (crtc_state->ctm)
>> - topology.num_dspp = topology.num_lm;
>> -
>> - topology.num_intf = intf_count;
>> + if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
>> + fb = conn_state->writeback_job->fb;
>>
>> - if (dsc) {
>> - /*
>> - * In case of Display Stream Compression (DSC), we would use
>> - * 2 DSC encoders, 2 layer mixers and 1 interface
>> - * this is power optimal and can drive up to (including) 4k
>> - * screens
>> - */
>> - topology.num_dsc = 2;
>> - topology.num_lm = 2;
>> - topology.num_intf = 1;
>> + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
>> + topology->needs_cdm = true;
>> + } else if (disp_info->intf_type == INTF_DP) {
>> + if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
>> + topology->needs_cdm = true;
>> }
>> -
>> - 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)
>> +static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
>> {
>> - 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->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>> - num_lm = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> - drm_enc->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>> - num_dspp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>> - drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
>> - ARRAY_SIZE(hw_dspp));
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>> + u32 num_intf = 0;
>> + u32 num_dsc = 0;
>> + int i;
>>
>> - for (i = 0; i < num_lm; i++) {
>> - int ctl_idx = (i < num_ctl) ? i : (num_ctl-1);
>> + for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
>> + if (dpu_enc->phys_encs[i])
>> + num_intf++;
>>
>> - 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;
>> - }
>> + /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
>> + if (dpu_enc->dsc)
>> + num_dsc += 2;
>>
>> - cstate->num_mixers = num_lm;
>> + return (num_dsc > 0) && (num_dsc > num_intf);
>
> Ok, so after all the rebases this commit removes CRTC resource
> assignment from dpu_encoder.c, but they are added to dpu_crtc.c only in
> the next commit! So after this one the tree is broken. This isn't really
> acceptable. After each commit the tree should work, otherwise git-bisect
> might return incorrect results.
>
> Historically this patch just moved the allocation to the
> dpu_crtc_atomic_check(), while cstate has been maniputated in
> dpu_encoder_virt_atomic_mode_set(). Commit 3ae133b0192b ("drm/msm/dpu:
> move CRTC resource assignment to dpu_encoder_virt_atomic_check") moved
> resource handling to the atomic_check() stage. I think at this point you
> need to take one step back, return to the previous commits, but revert
> their order: first move cstate manipulation to happen during the
> dpu_crtc_atomic_check() function call, leaving dpu_rm_release() /
> dpu_rm_reserve() out of dpu_crtc_assign_resources() (in
> dpu_encoder_virt_atomic_check() as they are now). Then can come this
> patch, which moves topology handling, resource reservation, etc. to
> dpu_crtc.c.
Hey Dmitry,
Thanks for the heads up! I'll get this fixed.
- Jessica Zhang
>
>> }
>>
>> -static int dpu_encoder_virt_atomic_check(
>> - struct drm_encoder *drm_enc,
>> - struct drm_crtc_state *crtc_state,
>> - struct drm_connector_state *conn_state)
>> +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state)
>> {
>> - struct dpu_encoder_virt *dpu_enc;
>> - struct msm_drm_private *priv;
>> - struct dpu_kms *dpu_kms;
>> - struct drm_display_mode *adj_mode;
>> - struct msm_display_topology topology;
>> - struct msm_display_info *disp_info;
>> - struct dpu_global_state *global_state;
>> + struct drm_connector *connector;
>> + struct drm_connector_state *conn_state;
>> struct drm_framebuffer *fb;
>> - struct drm_dsc_config *dsc;
>> - int ret = 0;
>> -
>> - if (!drm_enc || !crtc_state || !conn_state) {
>> - DPU_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
>> - drm_enc != NULL, crtc_state != NULL, conn_state != NULL);
>> - return -EINVAL;
>> - }
>> -
>> - dpu_enc = to_dpu_encoder_virt(drm_enc);
>> - DPU_DEBUG_ENC(dpu_enc, "\n");
>> -
>> - priv = drm_enc->dev->dev_private;
>> - disp_info = &dpu_enc->disp_info;
>> - dpu_kms = to_dpu_kms(priv->kms);
>> - adj_mode = &crtc_state->adjusted_mode;
>> - global_state = dpu_kms_get_global_state(crtc_state->state);
>> - if (IS_ERR(global_state))
>> - return PTR_ERR(global_state);
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>>
>> - trace_dpu_enc_atomic_check(DRMID(drm_enc));
>> + if (!drm_enc || !state)
>> + return false;
>>
>> - dsc = dpu_encoder_get_dsc_config(drm_enc);
>> + connector = drm_atomic_get_new_connector_for_encoder(state, drm_enc);
>> + if (!connector)
>> + return false;
>>
>> - topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode, crtc_state, dsc);
>> + conn_state = drm_atomic_get_new_connector_state(state, connector);
>>
>> - /*
>> - * Use CDM only for writeback or DP at the moment as other interfaces cannot handle it.
>> - * If writeback itself cannot handle cdm for some reason it will fail in its atomic_check()
>> - * earlier.
>> - */
>> - if (disp_info->intf_type == INTF_WB && conn_state->writeback_job) {
>> + if (dpu_enc->disp_info.intf_type == INTF_WB && conn_state->writeback_job) {
>> fb = conn_state->writeback_job->fb;
>> -
>> - if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb)))
>> - topology.needs_cdm = true;
>> - } else if (disp_info->intf_type == INTF_DP) {
>> - if (msm_dp_is_yuv_420_enabled(priv->dp[disp_info->h_tile_instance[0]], adj_mode))
>> - topology.needs_cdm = true;
>> + if (fb && MSM_FORMAT_IS_YUV(msm_framebuffer_format(fb))) {
>> + if (!dpu_enc->cur_master->hw_cdm)
>> + return true;
>> + } else {
>> + if (dpu_enc->cur_master->hw_cdm)
>> + return true;
>> + }
>> }
>>
>> - if (topology.needs_cdm && !dpu_enc->cur_master->hw_cdm)
>> - crtc_state->mode_changed = true;
>> - else if (!topology.needs_cdm && dpu_enc->cur_master->hw_cdm)
>> - crtc_state->mode_changed = true;
>> - /*
>> - * Release and Allocate resources on every modeset
>> - * Dont allocate when active is false.
>> - */
>> - if (drm_atomic_crtc_needs_modeset(crtc_state)) {
>> - dpu_rm_release(global_state, crtc_state->crtc);
>> + return false;
>> +}
>>
>> - if (!crtc_state->active_changed || crtc_state->enable)
>> - ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> - crtc_state->crtc, &topology);
>> - if (!ret)
>> - dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
>> - global_state, crtc_state);
>> - }
>> +/**
>> + * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
>> + * This helper function is used by physical encoder to get DSC config
>> + * used for this encoder.
>> + * @drm_enc: Pointer to encoder structure
>> + */
>> +struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
>> +{
>> + struct msm_drm_private *priv = drm_enc->dev->dev_private;
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
>> + int index = dpu_enc->disp_info.h_tile_instance[0];
>>
>> - trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
>> + if (dpu_enc->disp_info.intf_type == INTF_DSI)
>> + return msm_dsi_get_dsc_config(priv->dsi[index]);
>>
>> - return ret;
>> + return NULL;
>> +}
>> +
>> +/**
>> + * dpu_encoder_use_dsc_merge - returns true if the encoder uses DSC merge topology.
>> + * @drm_enc: Pointer to previously created drm encoder structure
>> + */
>> +bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc)
>> +{
>> + return dpu_encoder_needs_dsc_merge(drm_enc);
>> }
>>
>> static void _dpu_encoder_update_vsync_source(struct dpu_encoder_virt *dpu_enc,
>> @@ -2627,7 +2546,6 @@ static const struct drm_encoder_helper_funcs dpu_encoder_helper_funcs = {
>> .atomic_mode_set = dpu_encoder_virt_atomic_mode_set,
>> .atomic_disable = dpu_encoder_virt_atomic_disable,
>> .atomic_enable = dpu_encoder_virt_atomic_enable,
>> - .atomic_check = dpu_encoder_virt_atomic_check,
>> };
>>
>> static const struct drm_encoder_funcs dpu_encoder_funcs = {
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> index 92b5ee390788d16e85e195a664417896a2bf1cae..3db3ea076c377ad5411ec85006bcf4cd9757eb1d 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> @@ -11,6 +11,7 @@
>>
>> #include <drm/drm_crtc.h>
>> #include "dpu_hw_mdss.h"
>> +#include "dpu_kms.h"
>>
>> #define DPU_ENCODER_FRAME_EVENT_DONE BIT(0)
>> #define DPU_ENCODER_FRAME_EVENT_ERROR BIT(1)
>> @@ -80,6 +81,13 @@ int dpu_encoder_get_crc(const struct drm_encoder *drm_enc, u32 *crcs, int pos);
>>
>> bool dpu_encoder_use_dsc_merge(struct drm_encoder *drm_enc);
>>
>> +void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
>> + struct msm_display_topology *topology,
>> + struct drm_atomic_state *state,
>> + const struct drm_display_mode *adj_mode);
>> +
>> +bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
>> +
>> void dpu_encoder_prepare_wb_job(struct drm_encoder *drm_enc,
>> struct drm_writeback_job *job);
>>
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-21 1:07 ` Dmitry Baryshkov
@ 2024-12-26 22:49 ` Jessica Zhang
2024-12-29 4:47 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-26 22:49 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
> On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
>>
>>
>> On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
>>> On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
>>>> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
>>>>
>>>> For concurrent writeback, even-indexed CWB muxes must be assigned to
>>>> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
>>>> even/odd rule applies for dedicated CWB PINGPONGs.
>>>>
>>>> Track the CWB muxes in the global state and add a CWB-specific helper to
>>>> reserve the correct CWB muxes and dedicated PINGPONGs following the
>>>> even/odd rule.
>>>>
>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
>>>> 4 files changed, 116 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>> @@ -2,7 +2,7 @@
>>>> /*
>>>> * Copyright (C) 2013 Red Hat
>>>> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
>>>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
>>>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>>> *
>>>> * Author: Rob Clark <robdclark@gmail.com>
>>>> */
>>>> @@ -28,6 +28,7 @@
>>>> #include "dpu_hw_dsc.h"
>>>> #include "dpu_hw_merge3d.h"
>>>> #include "dpu_hw_cdm.h"
>>>> +#include "dpu_hw_cwb.h"
>>>> #include "dpu_formats.h"
>>>> #include "dpu_encoder_phys.h"
>>>> #include "dpu_crtc.h"
>>>> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
>>>> * @cur_slave: As above but for the slave encoder.
>>>> * @hw_pp: Handle to the pingpong blocks used for the display. No.
>>>> * pingpong blocks can be different than num_phys_encs.
>>>> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
>>>> + * display. Number of CWB muxes can be different than
>>>> + * num_phys_encs.
>>>> * @hw_dsc: Handle to the DSC blocks used for the display.
>>>> * @dsc_mask: Bitmask of used DSC blocks.
>>>> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
>>>> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
>>>> struct dpu_encoder_phys *cur_master;
>>>> struct dpu_encoder_phys *cur_slave;
>>>> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
>>>> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
>>>> unsigned int dsc_mask;
>>>> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>> 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_dsc[MAX_CHANNELS_PER_ENC];
>>>> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>> int num_pp, num_dsc, num_ctl;
>>>> + int num_cwb = 0;
>>>> + bool is_cwb_encoder;
>>>> unsigned int dsc_mask = 0;
>>>> int i;
>>>> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>> priv = drm_enc->dev->dev_private;
>>>> dpu_kms = to_dpu_kms(priv->kms);
>>>> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
>>>> + dpu_enc->disp_info.intf_type == INTF_WB;
>>>> global_state = dpu_kms_get_existing_global_state(dpu_kms);
>>>> if (IS_ERR_OR_NULL(global_state)) {
>>>> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>> trace_dpu_enc_mode_set(DRMID(drm_enc));
>>>> /* Query resource that have been reserved in atomic check step. */
>>>> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>>>> - ARRAY_SIZE(hw_pp));
>>>> + if (is_cwb_encoder) {
>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>> + drm_enc->crtc,
>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>> + hw_pp, ARRAY_SIZE(hw_pp));
>>>> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>> + drm_enc->crtc,
>>>> + DPU_HW_BLK_CWB,
>>>> + hw_cwb, ARRAY_SIZE(hw_cwb));
>>>> + } else {
>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>> + drm_enc->crtc,
>>>> + DPU_HW_BLK_PINGPONG, hw_pp,
>>>> + ARRAY_SIZE(hw_pp));
>>>> + }
>>>> +
>>>> + for (i = 0; i < num_cwb; i++)
>>>> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
>>>> +
>>>> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
>>>> DPU_HW_BLK_LM,
>>>> DPU_HW_BLK_CTL,
>>>> DPU_HW_BLK_PINGPONG,
>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>> DPU_HW_BLK_INTF,
>>>> DPU_HW_BLK_WB,
>>>> DPU_HW_BLK_DSPP,
>>>> DPU_HW_BLK_MERGE_3D,
>>>> DPU_HW_BLK_DSC,
>>>> DPU_HW_BLK_CDM,
>>>> + DPU_HW_BLK_CWB,
>>>> DPU_HW_BLK_MAX,
>>>> };
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>> @@ -128,6 +128,7 @@ struct dpu_global_state {
>>>> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>>> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>>> uint32_t cdm_to_crtc_id;
>>>> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
>>>> };
>>>> struct dpu_global_state
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>> return -EINVAL;
>>>> }
>>>> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
>>>> + struct dpu_global_state *global_state,
>>>> + uint32_t crtc_id,
>>>> + struct msm_display_topology *topology)
>>>> +{
>>>> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
>>>> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
>>>> + int cwb_pp_idx[MAX_BLOCKS];
>>>> + int cwb_mux_idx[MAX_BLOCKS];
>>>> +
>>>> + /*
>>>> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
>>>> + * mixer
>>>> + *
>>>> + * TODO: add support reserving resources for platforms with no
>>>> + * PINGPONG_CWB
>>>
>>> What about doing it other way around: allocate CWBs first as required
>>> (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
>>> (I think it's enough to simply make CWB blocks have a corresponding PP
>>> index as a property). This way the driver can handle both legacy and
>>> current platforms.
>>
>> Hi Dmitry,
>>
>> Sorry if I'm misunderstanding your suggestion, but the main change needed to
>> support platforms with no dedicated PINGPONG_CWB is where in the
>> rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
>> I'm not sure how changing the order in which CWBs and the pingpong blocks
>> are assigned will address that.
>>
>> (FWIW, the only change necessary to add support for non-dedicated
>> PINGPONG_CWBs platforms for this function should just be changing the
>> initialization value of cwb_pp_start_idx)
>
> If I remember correctly, we have identified several generations of DPU
> wrt. CWB handling:
> - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
> - 7.2, dedicated PP_1?
> - 5.0+, shared PP blocks
> - older DPUs, special handling of PP
>
> If the driver allocates PP first and then first it has to allocated PP
> (in a platform-specific way) and then go from PINGPONG to CWB (in a
> platform-specific way). If CWB is allocated first, then you have only
> one platform-specific piece of code that gets PINGPONG for the CWB (and
> as this function is called after the CWB allocation, the major part of
> the CWB / PP allocation is generic).
The issue with breaking this into separate helpers/functions is that the
CWB mux and PPB indices are dependent on each other. But I agree that we
can reserve CWB mux and the PPBs in 2 separate loops within this helper
to minimize the special platform-specific handling.
Also wanted to note that the comment doc on the PPB odd/even rule is
inaccurate -- technically the odd/even rule applies specifically to the
CWB mux as odd/even LMs are hardwired to their respective CWB muxes.
Will correct the comment doc to be more accurate.
Thanks,
Jessica Zhang
>
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>>>
>>>> + */
>>>> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>>>> + cwb_pp_count < num_cwb_pp; i++) {
>>>> + for (int j = cwb_pp_start_idx;
>>>> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
>>>> + /*
>>>> + * Odd LMs must be assigned to odd PINGPONGs and even
>>>> + * LMs with even PINGPONGs
>>>> + */
>>>> + if (reserved_by_other(global_state->pingpong_to_crtc_id, j, crtc_id) ||
>>>> + i % 2 != j % 2)
>>>> + continue;
>>>> +
>>>> + cwb_pp_idx[cwb_pp_count] = j;
>>>> + cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
>>>> + cwb_pp_count++;
>>>> + break;
>>>> + }
>>>> + }
>>>> +
>>>> + if (cwb_pp_count != num_cwb_pp) {
>>>> + DPU_ERROR("Unable to reserve all CWB PINGPONGs\n");
>>>> + return -ENAVAIL;
>>>> + }
>>>> +
>>>> + for (int i = 0; i < cwb_pp_count; i++) {
>>>> + global_state->pingpong_to_crtc_id[cwb_pp_idx[i]] = crtc_id;
>>>> + global_state->cwb_to_crtc_id[cwb_mux_idx[i]] = crtc_id;
>>>> + }
>>>> +
>>>> + return 0;
>>>> +}
>>>> +
>>>> /**
>>>> * _dpu_rm_check_lm_and_get_connected_blks - check if proposed layer mixer meets
>>>> * proposed use case requirements, incl. hardwired dependent blocks like
>>>> @@ -614,6 +663,12 @@ static int _dpu_rm_make_reservation(
>>>> return ret;
>>>> }
>>>> + if (topology->cwb_enabled) {
>>>> + ret = _dpu_rm_reserve_cwb_mux_and_pingpongs(rm, global_state,
>>>> + crtc_id, topology);
>>>> + if (ret)
>>>> + return ret;
>>>> + }
>>>> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>>>> topology);
>>>> @@ -671,6 +726,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>>>> _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
>>>> ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
>>>> _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
>>>> + _dpu_rm_clear_mapping(global_state->cwb_to_crtc_id,
>>>> + ARRAY_SIZE(global_state->cwb_to_crtc_id), crtc_id);
>>>> }
>>>> /**
>>>> @@ -733,6 +790,7 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>> switch (type) {
>>>> case DPU_HW_BLK_PINGPONG:
>>>> + case DPU_HW_BLK_DCWB_PINGPONG:
>>>> hw_blks = rm->pingpong_blks;
>>>> hw_to_crtc_id = global_state->pingpong_to_crtc_id;
>>>> max_blks = ARRAY_SIZE(rm->pingpong_blks);
>>>> @@ -762,6 +820,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>> hw_to_crtc_id = &global_state->cdm_to_crtc_id;
>>>> max_blks = 1;
>>>> break;
>>>> + case DPU_HW_BLK_CWB:
>>>> + hw_blks = rm->cwb_blks;
>>>> + hw_to_crtc_id = global_state->cwb_to_crtc_id;
>>>> + max_blks = ARRAY_SIZE(rm->cwb_blks);
>>>> + break;
>>>> default:
>>>> DPU_ERROR("blk type %d not managed by rm\n", type);
>>>> return 0;
>>>> @@ -772,6 +835,20 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>> if (hw_to_crtc_id[i] != crtc_id)
>>>> continue;
>>>> + if (type == DPU_HW_BLK_PINGPONG) {
>>>> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
>>>> +
>>>> + if (pp->idx >= PINGPONG_CWB_0)
>>>> + continue;
>>>> + }
>>>> +
>>>> + if (type == DPU_HW_BLK_DCWB_PINGPONG) {
>>>> + struct dpu_hw_pingpong *pp = to_dpu_hw_pingpong(hw_blks[i]);
>>>> +
>>>> + if (pp->idx < PINGPONG_CWB_0)
>>>> + continue;
>>>> + }
>>>> +
>>>> if (num_blks == blks_size) {
>>>> DPU_ERROR("More than %d resources assigned to crtc %d\n",
>>>> blks_size, crtc_id);
>>>> @@ -847,4 +924,10 @@ void dpu_rm_print_state(struct drm_printer *p,
>>>> dpu_rm_print_state_helper(p, rm->cdm_blk,
>>>> global_state->cdm_to_crtc_id);
>>>> drm_puts(p, "\n");
>>>> +
>>>> + drm_puts(p, "\tcwb=");
>>>> + for (i = 0; i < ARRAY_SIZE(global_state->cwb_to_crtc_id); i++)
>>>> + dpu_rm_print_state_helper(p, rm->cwb_blks[i],
>>>> + global_state->cwb_to_crtc_id[i]);
>>>> + drm_puts(p, "\n");
>>>> }
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
2024-12-20 5:44 ` Dmitry Baryshkov
@ 2024-12-26 22:51 ` Jessica Zhang
2024-12-30 23:59 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2024-12-26 22:51 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/19/2024 9:44 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:28PM -0800, Jessica Zhang wrote:
>> We cannot support both CWB and CDM simultaneously as this would require
>> 2 CDM blocks and currently our hardware only supports 1 CDM block at
>> most.
>
> Why would CWB require a second CDM block? I think that YUV output over
> DP (needs_cdm = true) and RGB output over WB (cwb_enabled = true) should
> work. Am I wrong?
Hey Dmitry,
No, I think your usecase should work. In that case, I can change this so
that it only fails if both DP and WB are requesting CDM simultaneously.
Thanks,
Jessica Zhang
>
>>
>> Thus return an error if both CWB and CDM are enabled.
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 9bb920d28bae2706b3892c167fe2bec3fd8857f4..a6372eee916e8aba702bbefc3615d8882ddcaad9 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1261,6 +1261,10 @@ static int dpu_crtc_assign_resources(struct drm_crtc *crtc, struct drm_crtc_stat
>> return 0;
>>
>> topology = dpu_crtc_get_topology(crtc, dpu_kms, crtc_state);
>> +
>> + if (topology.cwb_enabled && topology.needs_cdm)
>> + return -EINVAL;
>> +
>> ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>> crtc, &topology);
>> if (ret)
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-26 22:49 ` Jessica Zhang
@ 2024-12-29 4:47 ` Dmitry Baryshkov
2025-01-09 21:26 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-29 4:47 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, Dec 26, 2024 at 02:49:28PM -0800, Jessica Zhang wrote:
>
>
> On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
> > On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
> > >
> > >
> > > On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
> > > > On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
> > > > > Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
> > > > >
> > > > > For concurrent writeback, even-indexed CWB muxes must be assigned to
> > > > > even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
> > > > > even/odd rule applies for dedicated CWB PINGPONGs.
> > > > >
> > > > > Track the CWB muxes in the global state and add a CWB-specific helper to
> > > > > reserve the correct CWB muxes and dedicated PINGPONGs following the
> > > > > even/odd rule.
> > > > >
> > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > ---
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
> > > > > 4 files changed, 116 insertions(+), 4 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > @@ -2,7 +2,7 @@
> > > > > /*
> > > > > * Copyright (C) 2013 Red Hat
> > > > > * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
> > > > > - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> > > > > + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> > > > > *
> > > > > * Author: Rob Clark <robdclark@gmail.com>
> > > > > */
> > > > > @@ -28,6 +28,7 @@
> > > > > #include "dpu_hw_dsc.h"
> > > > > #include "dpu_hw_merge3d.h"
> > > > > #include "dpu_hw_cdm.h"
> > > > > +#include "dpu_hw_cwb.h"
> > > > > #include "dpu_formats.h"
> > > > > #include "dpu_encoder_phys.h"
> > > > > #include "dpu_crtc.h"
> > > > > @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
> > > > > * @cur_slave: As above but for the slave encoder.
> > > > > * @hw_pp: Handle to the pingpong blocks used for the display. No.
> > > > > * pingpong blocks can be different than num_phys_encs.
> > > > > + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
> > > > > + * display. Number of CWB muxes can be different than
> > > > > + * num_phys_encs.
> > > > > * @hw_dsc: Handle to the DSC blocks used for the display.
> > > > > * @dsc_mask: Bitmask of used DSC blocks.
> > > > > * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> > > > > @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
> > > > > struct dpu_encoder_phys *cur_master;
> > > > > struct dpu_encoder_phys *cur_slave;
> > > > > struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> > > > > + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > > > struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> > > > > unsigned int dsc_mask;
> > > > > @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > 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_dsc[MAX_CHANNELS_PER_ENC];
> > > > > + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > > > int num_pp, num_dsc, num_ctl;
> > > > > + int num_cwb = 0;
> > > > > + bool is_cwb_encoder;
> > > > > unsigned int dsc_mask = 0;
> > > > > int i;
> > > > > @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > priv = drm_enc->dev->dev_private;
> > > > > dpu_kms = to_dpu_kms(priv->kms);
> > > > > + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
> > > > > + dpu_enc->disp_info.intf_type == INTF_WB;
> > > > > global_state = dpu_kms_get_existing_global_state(dpu_kms);
> > > > > if (IS_ERR_OR_NULL(global_state)) {
> > > > > @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > trace_dpu_enc_mode_set(DRMID(drm_enc));
> > > > > /* Query resource that have been reserved in atomic check step. */
> > > > > - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > - ARRAY_SIZE(hw_pp));
> > > > > + if (is_cwb_encoder) {
> > > > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > + drm_enc->crtc,
> > > > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > > > + hw_pp, ARRAY_SIZE(hw_pp));
> > > > > + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > + drm_enc->crtc,
> > > > > + DPU_HW_BLK_CWB,
> > > > > + hw_cwb, ARRAY_SIZE(hw_cwb));
> > > > > + } else {
> > > > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > + drm_enc->crtc,
> > > > > + DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > + ARRAY_SIZE(hw_pp));
> > > > > + }
> > > > > +
> > > > > + for (i = 0; i < num_cwb; i++)
> > > > > + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
> > > > > +
> > > > > num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
> > > > > DPU_HW_BLK_LM,
> > > > > DPU_HW_BLK_CTL,
> > > > > DPU_HW_BLK_PINGPONG,
> > > > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > > > DPU_HW_BLK_INTF,
> > > > > DPU_HW_BLK_WB,
> > > > > DPU_HW_BLK_DSPP,
> > > > > DPU_HW_BLK_MERGE_3D,
> > > > > DPU_HW_BLK_DSC,
> > > > > DPU_HW_BLK_CDM,
> > > > > + DPU_HW_BLK_CWB,
> > > > > DPU_HW_BLK_MAX,
> > > > > };
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > @@ -128,6 +128,7 @@ struct dpu_global_state {
> > > > > uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > > > > uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > > > > uint32_t cdm_to_crtc_id;
> > > > > + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
> > > > > };
> > > > > struct dpu_global_state
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > > return -EINVAL;
> > > > > }
> > > > > +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
> > > > > + struct dpu_global_state *global_state,
> > > > > + uint32_t crtc_id,
> > > > > + struct msm_display_topology *topology)
> > > > > +{
> > > > > + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
> > > > > + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
> > > > > + int cwb_pp_idx[MAX_BLOCKS];
> > > > > + int cwb_mux_idx[MAX_BLOCKS];
> > > > > +
> > > > > + /*
> > > > > + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
> > > > > + * mixer
> > > > > + *
> > > > > + * TODO: add support reserving resources for platforms with no
> > > > > + * PINGPONG_CWB
> > > >
> > > > What about doing it other way around: allocate CWBs first as required
> > > > (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
> > > > (I think it's enough to simply make CWB blocks have a corresponding PP
> > > > index as a property). This way the driver can handle both legacy and
> > > > current platforms.
> > >
> > > Hi Dmitry,
> > >
> > > Sorry if I'm misunderstanding your suggestion, but the main change needed to
> > > support platforms with no dedicated PINGPONG_CWB is where in the
> > > rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
> > > I'm not sure how changing the order in which CWBs and the pingpong blocks
> > > are assigned will address that.
> > >
> > > (FWIW, the only change necessary to add support for non-dedicated
> > > PINGPONG_CWBs platforms for this function should just be changing the
> > > initialization value of cwb_pp_start_idx)
> >
> > If I remember correctly, we have identified several generations of DPU
> > wrt. CWB handling:
> > - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
> > - 7.2, dedicated PP_1?
> > - 5.0+, shared PP blocks
> > - older DPUs, special handling of PP
> >
> > If the driver allocates PP first and then first it has to allocated PP
> > (in a platform-specific way) and then go from PINGPONG to CWB (in a
> > platform-specific way). If CWB is allocated first, then you have only
> > one platform-specific piece of code that gets PINGPONG for the CWB (and
> > as this function is called after the CWB allocation, the major part of
> > the CWB / PP allocation is generic).
>
> The issue with breaking this into separate helpers/functions is that the CWB
> mux and PPB indices are dependent on each other. But I agree that we can
> reserve CWB mux and the PPBs in 2 separate loops within this helper to
> minimize the special platform-specific handling.
Doesn't it just PPB depend on CWB?
>
> Also wanted to note that the comment doc on the PPB odd/even rule is
> inaccurate -- technically the odd/even rule applies specifically to the CWB
> mux as odd/even LMs are hardwired to their respective CWB muxes. Will
> correct the comment doc to be more accurate.
Yes, please fix that.
>
> Thanks,
>
> Jessica Zhang
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled
2024-12-26 22:51 ` Jessica Zhang
@ 2024-12-30 23:59 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2024-12-30 23:59 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, Dec 26, 2024 at 02:51:12PM -0800, Jessica Zhang wrote:
>
>
> On 12/19/2024 9:44 PM, Dmitry Baryshkov wrote:
> > On Mon, Dec 16, 2024 at 04:43:28PM -0800, Jessica Zhang wrote:
> > > We cannot support both CWB and CDM simultaneously as this would require
> > > 2 CDM blocks and currently our hardware only supports 1 CDM block at
> > > most.
> >
> > Why would CWB require a second CDM block? I think that YUV output over
> > DP (needs_cdm = true) and RGB output over WB (cwb_enabled = true) should
> > work. Am I wrong?
>
> Hey Dmitry,
>
> No, I think your usecase should work. In that case, I can change this so
> that it only fails if both DP and WB are requesting CDM simultaneously.
Sounds good to me, thank you!.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2024-12-20 5:03 ` Dmitry Baryshkov
@ 2025-01-03 18:03 ` Jessica Zhang
2025-01-03 18:16 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-03 18:03 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
>> to account for concurrent writeback
>
> Why?
Hi Dmitry,
This flag is necessary to specify that CWB mux(es) need to be assigned
for the given reqeusted topology.
>
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>> &crtc_state->adjusted_mode);
>>
>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
>> +
>> /*
>> * Datapath topology selection
>> *
>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>> *
>> * Add dspps to the reservation requirements if ctm is requested
>> + *
>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
>> + * enabled. This is because in cases where CWB is enabled, num_intf will
>> + * count both the WB and real-time phys encoders.
>> + *
>> + * For non-DSC CWB usecases, have the num_lm be decided by the
>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
>> */
>>
>> - if (topology.num_intf == 2)
>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
>> topology.num_lm = 2;
>> else if (topology.num_dsc == 2)
>> topology.num_lm = 2;
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
>> int i = 0, j, num_ctls;
>> bool needs_split_display;
>>
>> - /* each hw_intf needs its own hw_ctrl to program its control path */
>> - num_ctls = top->num_intf;
>> + /*
>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
>> + */
>
> Why?
This is because num_intf is based on the number of phys_encs. Since in
the CWB case, the WB and real-time encoders will be driven by the same
CTL. I can add this to the comment doc.
Thanks,
Jessica Zhang
>
>> + if (top->cwb_enabled)
>> + num_ctls = 1;
>> + else
>> + num_ctls = top->num_intf;
>>
>> needs_split_display = _dpu_rm_needs_split_display(top);
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>> @@ -46,6 +46,7 @@ struct dpu_rm {
>> * @num_dspp: number of dspp blocks used
>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
>> * @needs_cdm: indicates whether cdm block is needed for this display topology
>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
>> */
>> struct msm_display_topology {
>> u32 num_lm;
>> @@ -53,6 +54,7 @@ struct msm_display_topology {
>> u32 num_dspp;
>> u32 num_dsc;
>> bool needs_cdm;
>> + bool cwb_enabled;
>> };
>>
>> int dpu_rm_init(struct drm_device *dev,
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-03 18:03 ` Jessica Zhang
@ 2025-01-03 18:16 ` Dmitry Baryshkov
2025-01-09 22:34 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-03 18:16 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
>
>
> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
> > On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
> > > Add the cwb_enabled flag to msm_display topology and adjust the toplogy
> > > to account for concurrent writeback
> >
> > Why?
>
> Hi Dmitry,
>
> This flag is necessary to specify that CWB mux(es) need to be assigned for
> the given reqeusted topology.
Why is necessary? Please rephrase your statement (we need foo bar, so do
baz).
>
> >
> > >
> > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > ---
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
> > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
> > > 3 files changed, 20 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> > > &crtc_state->adjusted_mode);
> > > + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
> > > +
> > > /*
> > > * Datapath topology selection
> > > *
> > > @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> > > *
> > > * Add dspps to the reservation requirements if ctm is requested
> > > + *
> > > + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
> > > + * enabled. This is because in cases where CWB is enabled, num_intf will
> > > + * count both the WB and real-time phys encoders.
> > > + *
> > > + * For non-DSC CWB usecases, have the num_lm be decided by the
> > > + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
> > > */
> > > - if (topology.num_intf == 2)
> > > + if (topology.num_intf == 2 && !topology.cwb_enabled)
> > > topology.num_lm = 2;
> > > else if (topology.num_dsc == 2)
> > > topology.num_lm = 2;
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
> > > int i = 0, j, num_ctls;
> > > bool needs_split_display;
> > > - /* each hw_intf needs its own hw_ctrl to program its control path */
> > > - num_ctls = top->num_intf;
> > > + /*
> > > + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
> > > + * control path. Hardcode num_ctls to 1 if CWB is enabled
> > > + */
> >
> > Why?
>
> This is because num_intf is based on the number of phys_encs. Since in the
> CWB case, the WB and real-time encoders will be driven by the same CTL. I
> can add this to the comment doc.
Why are they driven by the same CTL? Is it also the case for platforms
before DPU 5.x?
>
> Thanks,
>
> Jessica Zhang
>
> >
> > > + if (top->cwb_enabled)
> > > + num_ctls = 1;
> > > + else
> > > + num_ctls = top->num_intf;
> > > needs_split_display = _dpu_rm_needs_split_display(top);
> > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
> > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > @@ -46,6 +46,7 @@ struct dpu_rm {
> > > * @num_dspp: number of dspp blocks used
> > > * @num_dsc: number of Display Stream Compression (DSC) blocks used
> > > * @needs_cdm: indicates whether cdm block is needed for this display topology
> > > + * @cwb_enabled: indicates whether CWB is enabled for this display topology
> > > */
> > > struct msm_display_topology {
> > > u32 num_lm;
> > > @@ -53,6 +54,7 @@ struct msm_display_topology {
> > > u32 num_dspp;
> > > u32 num_dsc;
> > > bool needs_cdm;
> > > + bool cwb_enabled;
> > > };
> > > int dpu_rm_init(struct drm_device *dev,
> > >
> > > --
> > > 2.34.1
> > >
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: (subset) [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (26 preceding siblings ...)
2024-12-24 20:41 ` Dmitry Baryshkov
@ 2025-01-07 23:50 ` Dmitry Baryshkov
27 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-07 23:50 UTC (permalink / raw)
To: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, Jessica Zhang
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Ville Syrjälä
On Mon, 16 Dec 2024 16:43:11 -0800, Jessica Zhang wrote:
> DPU supports a single writeback session running concurrently with primary
> display when the CWB mux is configured properly. This series enables
> clone mode for DPU driver and adds support for programming the CWB mux
> in cases where the hardware has dedicated CWB pingpong blocks. Currently,
> the CWB hardware blocks have only been added to the SM8650
> hardware catalog and only DSI has been exposed as a possible_clone of WB.
>
> [...]
Applied to drm-misc-next, thanks!
[01/25] drm: add clone mode check for CRTC
commit: eee0912a7185d5dc0a700d48f7ff620bb7f5389b
[02/25] drm/tests: Add test for drm_crtc_in_clone_mode()
commit: 5a6e8c369486a79493ab300a1987cc6aad16cf6a
[03/25] drm: Add valid clones check
commit: 41b4b11da02157c7474caf41d56baae0e941d01a
[04/25] drm/tests: Add test for drm_atomic_helper_check_modeset()
commit: 88849f24e2abba8a8951aa76ea60a72fba916afe
Best regards,
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2024-12-29 4:47 ` Dmitry Baryshkov
@ 2025-01-09 21:26 ` Jessica Zhang
2025-01-09 22:13 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-09 21:26 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/28/2024 8:47 PM, Dmitry Baryshkov wrote:
> On Thu, Dec 26, 2024 at 02:49:28PM -0800, Jessica Zhang wrote:
>>
>>
>> On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
>>> On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
>>>>
>>>>
>>>> On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
>>>>> On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
>>>>>> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
>>>>>>
>>>>>> For concurrent writeback, even-indexed CWB muxes must be assigned to
>>>>>> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
>>>>>> even/odd rule applies for dedicated CWB PINGPONGs.
>>>>>>
>>>>>> Track the CWB muxes in the global state and add a CWB-specific helper to
>>>>>> reserve the correct CWB muxes and dedicated PINGPONGs following the
>>>>>> even/odd rule.
>>>>>>
>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
>>>>>> 4 files changed, 116 insertions(+), 4 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>> @@ -2,7 +2,7 @@
>>>>>> /*
>>>>>> * Copyright (C) 2013 Red Hat
>>>>>> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
>>>>>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
>>>>>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>>>>> *
>>>>>> * Author: Rob Clark <robdclark@gmail.com>
>>>>>> */
>>>>>> @@ -28,6 +28,7 @@
>>>>>> #include "dpu_hw_dsc.h"
>>>>>> #include "dpu_hw_merge3d.h"
>>>>>> #include "dpu_hw_cdm.h"
>>>>>> +#include "dpu_hw_cwb.h"
>>>>>> #include "dpu_formats.h"
>>>>>> #include "dpu_encoder_phys.h"
>>>>>> #include "dpu_crtc.h"
>>>>>> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
>>>>>> * @cur_slave: As above but for the slave encoder.
>>>>>> * @hw_pp: Handle to the pingpong blocks used for the display. No.
>>>>>> * pingpong blocks can be different than num_phys_encs.
>>>>>> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
>>>>>> + * display. Number of CWB muxes can be different than
>>>>>> + * num_phys_encs.
>>>>>> * @hw_dsc: Handle to the DSC blocks used for the display.
>>>>>> * @dsc_mask: Bitmask of used DSC blocks.
>>>>>> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
>>>>>> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
>>>>>> struct dpu_encoder_phys *cur_master;
>>>>>> struct dpu_encoder_phys *cur_slave;
>>>>>> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
>>>>>> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>>>> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
>>>>>> unsigned int dsc_mask;
>>>>>> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>> 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_dsc[MAX_CHANNELS_PER_ENC];
>>>>>> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>>>> int num_pp, num_dsc, num_ctl;
>>>>>> + int num_cwb = 0;
>>>>>> + bool is_cwb_encoder;
>>>>>> unsigned int dsc_mask = 0;
>>>>>> int i;
>>>>>> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>> priv = drm_enc->dev->dev_private;
>>>>>> dpu_kms = to_dpu_kms(priv->kms);
>>>>>> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
>>>>>> + dpu_enc->disp_info.intf_type == INTF_WB;
>>>>>> global_state = dpu_kms_get_existing_global_state(dpu_kms);
>>>>>> if (IS_ERR_OR_NULL(global_state)) {
>>>>>> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>> trace_dpu_enc_mode_set(DRMID(drm_enc));
>>>>>> /* Query resource that have been reserved in atomic check step. */
>>>>>> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>>>>>> - ARRAY_SIZE(hw_pp));
>>>>>> + if (is_cwb_encoder) {
>>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>> + drm_enc->crtc,
>>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>>>> + hw_pp, ARRAY_SIZE(hw_pp));
>>>>>> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>> + drm_enc->crtc,
>>>>>> + DPU_HW_BLK_CWB,
>>>>>> + hw_cwb, ARRAY_SIZE(hw_cwb));
>>>>>> + } else {
>>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>> + drm_enc->crtc,
>>>>>> + DPU_HW_BLK_PINGPONG, hw_pp,
>>>>>> + ARRAY_SIZE(hw_pp));
>>>>>> + }
>>>>>> +
>>>>>> + for (i = 0; i < num_cwb; i++)
>>>>>> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
>>>>>> +
>>>>>> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
>>>>>> DPU_HW_BLK_LM,
>>>>>> DPU_HW_BLK_CTL,
>>>>>> DPU_HW_BLK_PINGPONG,
>>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>>>> DPU_HW_BLK_INTF,
>>>>>> DPU_HW_BLK_WB,
>>>>>> DPU_HW_BLK_DSPP,
>>>>>> DPU_HW_BLK_MERGE_3D,
>>>>>> DPU_HW_BLK_DSC,
>>>>>> DPU_HW_BLK_CDM,
>>>>>> + DPU_HW_BLK_CWB,
>>>>>> DPU_HW_BLK_MAX,
>>>>>> };
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>> @@ -128,6 +128,7 @@ struct dpu_global_state {
>>>>>> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>>>>> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>>>>> uint32_t cdm_to_crtc_id;
>>>>>> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
>>>>>> };
>>>>>> struct dpu_global_state
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>>>> return -EINVAL;
>>>>>> }
>>>>>> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
>>>>>> + struct dpu_global_state *global_state,
>>>>>> + uint32_t crtc_id,
>>>>>> + struct msm_display_topology *topology)
>>>>>> +{
>>>>>> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
>>>>>> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
>>>>>> + int cwb_pp_idx[MAX_BLOCKS];
>>>>>> + int cwb_mux_idx[MAX_BLOCKS];
>>>>>> +
>>>>>> + /*
>>>>>> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
>>>>>> + * mixer
>>>>>> + *
>>>>>> + * TODO: add support reserving resources for platforms with no
>>>>>> + * PINGPONG_CWB
>>>>>
>>>>> What about doing it other way around: allocate CWBs first as required
>>>>> (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
>>>>> (I think it's enough to simply make CWB blocks have a corresponding PP
>>>>> index as a property). This way the driver can handle both legacy and
>>>>> current platforms.
>>>>
>>>> Hi Dmitry,
>>>>
>>>> Sorry if I'm misunderstanding your suggestion, but the main change needed to
>>>> support platforms with no dedicated PINGPONG_CWB is where in the
>>>> rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
>>>> I'm not sure how changing the order in which CWBs and the pingpong blocks
>>>> are assigned will address that.
>>>>
>>>> (FWIW, the only change necessary to add support for non-dedicated
>>>> PINGPONG_CWBs platforms for this function should just be changing the
>>>> initialization value of cwb_pp_start_idx)
>>>
>>> If I remember correctly, we have identified several generations of DPU
>>> wrt. CWB handling:
>>> - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
>>> - 7.2, dedicated PP_1?
>>> - 5.0+, shared PP blocks
>>> - older DPUs, special handling of PP
>>>
>>> If the driver allocates PP first and then first it has to allocated PP
>>> (in a platform-specific way) and then go from PINGPONG to CWB (in a
>>> platform-specific way). If CWB is allocated first, then you have only
>>> one platform-specific piece of code that gets PINGPONG for the CWB (and
>>> as this function is called after the CWB allocation, the major part of
>>> the CWB / PP allocation is generic).
>>
>> The issue with breaking this into separate helpers/functions is that the CWB
>> mux and PPB indices are dependent on each other. But I agree that we can
>> reserve CWB mux and the PPBs in 2 separate loops within this helper to
>> minimize the special platform-specific handling.
>
> Doesn't it just PPB depend on CWB?
Sorry, poor wording on my part. Was referring specifically to this part
of the logic within the code chunk:
```
cwb_pp_idx[cwb_pp_count] = j;
cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
```
The point I wanted to make was that I think we can keep the CWB-specific
reservation of the the PPBs and muxes in this function, but I agree with
your suggestion to reserve the CWBs first and the PPBs second (just in
separate loops rather than separate functions).
>
>
>>
>> Also wanted to note that the comment doc on the PPB odd/even rule is
>> inaccurate -- technically the odd/even rule applies specifically to the CWB
>> mux as odd/even LMs are hardwired to their respective CWB muxes. Will
>> correct the comment doc to be more accurate.
>
> Yes, please fix that.
>
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2025-01-09 21:26 ` Jessica Zhang
@ 2025-01-09 22:13 ` Dmitry Baryshkov
2025-01-09 22:53 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-09 22:13 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, 9 Jan 2025 at 23:26, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 12/28/2024 8:47 PM, Dmitry Baryshkov wrote:
> > On Thu, Dec 26, 2024 at 02:49:28PM -0800, Jessica Zhang wrote:
> >>
> >>
> >> On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
> >>> On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
> >>>>
> >>>>
> >>>> On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
> >>>>> On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
> >>>>>> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
> >>>>>>
> >>>>>> For concurrent writeback, even-indexed CWB muxes must be assigned to
> >>>>>> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
> >>>>>> even/odd rule applies for dedicated CWB PINGPONGs.
> >>>>>>
> >>>>>> Track the CWB muxes in the global state and add a CWB-specific helper to
> >>>>>> reserve the correct CWB muxes and dedicated PINGPONGs following the
> >>>>>> even/odd rule.
> >>>>>>
> >>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >>>>>> ---
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
> >>>>>> 4 files changed, 116 insertions(+), 4 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >>>>>> @@ -2,7 +2,7 @@
> >>>>>> /*
> >>>>>> * Copyright (C) 2013 Red Hat
> >>>>>> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
> >>>>>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> >>>>>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> >>>>>> *
> >>>>>> * Author: Rob Clark <robdclark@gmail.com>
> >>>>>> */
> >>>>>> @@ -28,6 +28,7 @@
> >>>>>> #include "dpu_hw_dsc.h"
> >>>>>> #include "dpu_hw_merge3d.h"
> >>>>>> #include "dpu_hw_cdm.h"
> >>>>>> +#include "dpu_hw_cwb.h"
> >>>>>> #include "dpu_formats.h"
> >>>>>> #include "dpu_encoder_phys.h"
> >>>>>> #include "dpu_crtc.h"
> >>>>>> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
> >>>>>> * @cur_slave: As above but for the slave encoder.
> >>>>>> * @hw_pp: Handle to the pingpong blocks used for the display. No.
> >>>>>> * pingpong blocks can be different than num_phys_encs.
> >>>>>> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
> >>>>>> + * display. Number of CWB muxes can be different than
> >>>>>> + * num_phys_encs.
> >>>>>> * @hw_dsc: Handle to the DSC blocks used for the display.
> >>>>>> * @dsc_mask: Bitmask of used DSC blocks.
> >>>>>> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> >>>>>> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
> >>>>>> struct dpu_encoder_phys *cur_master;
> >>>>>> struct dpu_encoder_phys *cur_slave;
> >>>>>> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> >>>>>> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
> >>>>>> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> >>>>>> unsigned int dsc_mask;
> >>>>>> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >>>>>> 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_dsc[MAX_CHANNELS_PER_ENC];
> >>>>>> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
> >>>>>> int num_pp, num_dsc, num_ctl;
> >>>>>> + int num_cwb = 0;
> >>>>>> + bool is_cwb_encoder;
> >>>>>> unsigned int dsc_mask = 0;
> >>>>>> int i;
> >>>>>> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >>>>>> priv = drm_enc->dev->dev_private;
> >>>>>> dpu_kms = to_dpu_kms(priv->kms);
> >>>>>> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
> >>>>>> + dpu_enc->disp_info.intf_type == INTF_WB;
> >>>>>> global_state = dpu_kms_get_existing_global_state(dpu_kms);
> >>>>>> if (IS_ERR_OR_NULL(global_state)) {
> >>>>>> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >>>>>> trace_dpu_enc_mode_set(DRMID(drm_enc));
> >>>>>> /* Query resource that have been reserved in atomic check step. */
> >>>>>> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> >>>>>> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> >>>>>> - ARRAY_SIZE(hw_pp));
> >>>>>> + if (is_cwb_encoder) {
> >>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> >>>>>> + drm_enc->crtc,
> >>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
> >>>>>> + hw_pp, ARRAY_SIZE(hw_pp));
> >>>>>> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> >>>>>> + drm_enc->crtc,
> >>>>>> + DPU_HW_BLK_CWB,
> >>>>>> + hw_cwb, ARRAY_SIZE(hw_cwb));
> >>>>>> + } else {
> >>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> >>>>>> + drm_enc->crtc,
> >>>>>> + DPU_HW_BLK_PINGPONG, hw_pp,
> >>>>>> + ARRAY_SIZE(hw_pp));
> >>>>>> + }
> >>>>>> +
> >>>>>> + for (i = 0; i < num_cwb; i++)
> >>>>>> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
> >>>>>> +
> >>>>>> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> >>>>>> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>>>> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >>>>>> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
> >>>>>> DPU_HW_BLK_LM,
> >>>>>> DPU_HW_BLK_CTL,
> >>>>>> DPU_HW_BLK_PINGPONG,
> >>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
> >>>>>> DPU_HW_BLK_INTF,
> >>>>>> DPU_HW_BLK_WB,
> >>>>>> DPU_HW_BLK_DSPP,
> >>>>>> DPU_HW_BLK_MERGE_3D,
> >>>>>> DPU_HW_BLK_DSC,
> >>>>>> DPU_HW_BLK_CDM,
> >>>>>> + DPU_HW_BLK_CWB,
> >>>>>> DPU_HW_BLK_MAX,
> >>>>>> };
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >>>>>> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> >>>>>> @@ -128,6 +128,7 @@ struct dpu_global_state {
> >>>>>> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> >>>>>> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> >>>>>> uint32_t cdm_to_crtc_id;
> >>>>>> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
> >>>>>> };
> >>>>>> struct dpu_global_state
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> >>>>>> return -EINVAL;
> >>>>>> }
> >>>>>> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
> >>>>>> + struct dpu_global_state *global_state,
> >>>>>> + uint32_t crtc_id,
> >>>>>> + struct msm_display_topology *topology)
> >>>>>> +{
> >>>>>> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
> >>>>>> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
> >>>>>> + int cwb_pp_idx[MAX_BLOCKS];
> >>>>>> + int cwb_mux_idx[MAX_BLOCKS];
> >>>>>> +
> >>>>>> + /*
> >>>>>> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
> >>>>>> + * mixer
> >>>>>> + *
> >>>>>> + * TODO: add support reserving resources for platforms with no
> >>>>>> + * PINGPONG_CWB
> >>>>>
> >>>>> What about doing it other way around: allocate CWBs first as required
> >>>>> (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
> >>>>> (I think it's enough to simply make CWB blocks have a corresponding PP
> >>>>> index as a property). This way the driver can handle both legacy and
> >>>>> current platforms.
> >>>>
> >>>> Hi Dmitry,
> >>>>
> >>>> Sorry if I'm misunderstanding your suggestion, but the main change needed to
> >>>> support platforms with no dedicated PINGPONG_CWB is where in the
> >>>> rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
> >>>> I'm not sure how changing the order in which CWBs and the pingpong blocks
> >>>> are assigned will address that.
> >>>>
> >>>> (FWIW, the only change necessary to add support for non-dedicated
> >>>> PINGPONG_CWBs platforms for this function should just be changing the
> >>>> initialization value of cwb_pp_start_idx)
> >>>
> >>> If I remember correctly, we have identified several generations of DPU
> >>> wrt. CWB handling:
> >>> - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
> >>> - 7.2, dedicated PP_1?
> >>> - 5.0+, shared PP blocks
> >>> - older DPUs, special handling of PP
> >>>
> >>> If the driver allocates PP first and then first it has to allocated PP
> >>> (in a platform-specific way) and then go from PINGPONG to CWB (in a
> >>> platform-specific way). If CWB is allocated first, then you have only
> >>> one platform-specific piece of code that gets PINGPONG for the CWB (and
> >>> as this function is called after the CWB allocation, the major part of
> >>> the CWB / PP allocation is generic).
> >>
> >> The issue with breaking this into separate helpers/functions is that the CWB
> >> mux and PPB indices are dependent on each other. But I agree that we can
> >> reserve CWB mux and the PPBs in 2 separate loops within this helper to
> >> minimize the special platform-specific handling.
> >
> > Doesn't it just PPB depend on CWB?
>
> Sorry, poor wording on my part. Was referring specifically to this part
> of the logic within the code chunk:
>
> ```
> cwb_pp_idx[cwb_pp_count] = j;
> cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
> ```
>
> The point I wanted to make was that I think we can keep the CWB-specific
> reservation of the the PPBs and muxes in this function, but I agree with
> your suggestion to reserve the CWBs first and the PPBs second (just in
> separate loops rather than separate functions).
Sounds fine with me. I don't think you even need a second loop, just
simple maths should be fine.
>
>
> >
> >
> >>
> >> Also wanted to note that the comment doc on the PPB odd/even rule is
> >> inaccurate -- technically the odd/even rule applies specifically to the CWB
> >> mux as odd/even LMs are hardwired to their respective CWB muxes. Will
> >> correct the comment doc to be more accurate.
> >
> > Yes, please fix that.
> >
> >>
> >> Thanks,
> >>
> >> Jessica Zhang
> >>
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-03 18:16 ` Dmitry Baryshkov
@ 2025-01-09 22:34 ` Jessica Zhang
2025-01-10 0:00 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-09 22:34 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
> On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
>>
>>
>> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
>>> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
>>>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
>>>> to account for concurrent writeback
>>>
>>> Why?
>>
>> Hi Dmitry,
>>
>> This flag is necessary to specify that CWB mux(es) need to be assigned for
>> the given reqeusted topology.
>
> Why is necessary? Please rephrase your statement (we need foo bar, so do
> baz).
Ack, what do you think of rephrasing the commit msg to this:
```
Add support for adjusting topology based on if concurrent writeback is
enabled.
Currently, the topology is calculated based on the assumption that the
user cannot request real-time and writeback simultaneously. For example,
the number of LMs and CTLs are currently based off the number of phys
encoders under the assumption there will be at least 1 LM/CTL per phys
encoder.
This will not hold true for concurrent writeback as 2 phys encoders (1
real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
writeback is enabled.
To account for this, add a cwb_enabled flag and only adjust the number
of CTL/LMs needed by a given topology based on the number of phys
encoders only if CWB is not enabled.
```
>
>>
>>>
>>>>
>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
>>>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>>>> &crtc_state->adjusted_mode);
>>>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
>>>> +
>>>> /*
>>>> * Datapath topology selection
>>>> *
>>>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>>>> *
>>>> * Add dspps to the reservation requirements if ctm is requested
>>>> + *
>>>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
>>>> + * enabled. This is because in cases where CWB is enabled, num_intf will
>>>> + * count both the WB and real-time phys encoders.
>>>> + *
>>>> + * For non-DSC CWB usecases, have the num_lm be decided by the
>>>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
>>>> */
>>>> - if (topology.num_intf == 2)
>>>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
>>>> topology.num_lm = 2;
>>>> else if (topology.num_dsc == 2)
>>>> topology.num_lm = 2;
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
>>>> int i = 0, j, num_ctls;
>>>> bool needs_split_display;
>>>> - /* each hw_intf needs its own hw_ctrl to program its control path */
>>>> - num_ctls = top->num_intf;
>>>> + /*
>>>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
>>>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
>>>> + */
>>>
>>> Why?
>>
>> This is because num_intf is based on the number of phys_encs. Since in the
>> CWB case, the WB and real-time encoders will be driven by the same CTL. I
>> can add this to the comment doc.
>
> Why are they driven by the same CTL? Is it also the case for platforms
> before DPU 5.x?
This is because the WB and real-time path for a given topology would be
driven by the same data path so the same CTL should enable the real-time
and WB active bits.
This is the same for pre-DPU 5.x.
>
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>>>
>>>> + if (top->cwb_enabled)
>>>> + num_ctls = 1;
>>>> + else
>>>> + num_ctls = top->num_intf;
>>>> needs_split_display = _dpu_rm_needs_split_display(top);
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>> @@ -46,6 +46,7 @@ struct dpu_rm {
>>>> * @num_dspp: number of dspp blocks used
>>>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
>>>> * @needs_cdm: indicates whether cdm block is needed for this display topology
>>>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
>>>> */
>>>> struct msm_display_topology {
>>>> u32 num_lm;
>>>> @@ -53,6 +54,7 @@ struct msm_display_topology {
>>>> u32 num_dspp;
>>>> u32 num_dsc;
>>>> bool needs_cdm;
>>>> + bool cwb_enabled;
>>>> };
>>>> int dpu_rm_init(struct drm_device *dev,
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2025-01-09 22:13 ` Dmitry Baryshkov
@ 2025-01-09 22:53 ` Jessica Zhang
2025-01-10 0:02 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-09 22:53 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/9/2025 2:13 PM, Dmitry Baryshkov wrote:
> On Thu, 9 Jan 2025 at 23:26, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>
>>
>>
>> On 12/28/2024 8:47 PM, Dmitry Baryshkov wrote:
>>> On Thu, Dec 26, 2024 at 02:49:28PM -0800, Jessica Zhang wrote:
>>>>
>>>>
>>>> On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
>>>>> On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
>>>>>>
>>>>>>
>>>>>> On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
>>>>>>> On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
>>>>>>>> Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
>>>>>>>>
>>>>>>>> For concurrent writeback, even-indexed CWB muxes must be assigned to
>>>>>>>> even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
>>>>>>>> even/odd rule applies for dedicated CWB PINGPONGs.
>>>>>>>>
>>>>>>>> Track the CWB muxes in the global state and add a CWB-specific helper to
>>>>>>>> reserve the correct CWB muxes and dedicated PINGPONGs following the
>>>>>>>> even/odd rule.
>>>>>>>>
>>>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>>>> ---
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
>>>>>>>> 4 files changed, 116 insertions(+), 4 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>>>>> @@ -2,7 +2,7 @@
>>>>>>>> /*
>>>>>>>> * Copyright (C) 2013 Red Hat
>>>>>>>> * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
>>>>>>>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
>>>>>>>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>>>>>>>> *
>>>>>>>> * Author: Rob Clark <robdclark@gmail.com>
>>>>>>>> */
>>>>>>>> @@ -28,6 +28,7 @@
>>>>>>>> #include "dpu_hw_dsc.h"
>>>>>>>> #include "dpu_hw_merge3d.h"
>>>>>>>> #include "dpu_hw_cdm.h"
>>>>>>>> +#include "dpu_hw_cwb.h"
>>>>>>>> #include "dpu_formats.h"
>>>>>>>> #include "dpu_encoder_phys.h"
>>>>>>>> #include "dpu_crtc.h"
>>>>>>>> @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
>>>>>>>> * @cur_slave: As above but for the slave encoder.
>>>>>>>> * @hw_pp: Handle to the pingpong blocks used for the display. No.
>>>>>>>> * pingpong blocks can be different than num_phys_encs.
>>>>>>>> + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
>>>>>>>> + * display. Number of CWB muxes can be different than
>>>>>>>> + * num_phys_encs.
>>>>>>>> * @hw_dsc: Handle to the DSC blocks used for the display.
>>>>>>>> * @dsc_mask: Bitmask of used DSC blocks.
>>>>>>>> * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
>>>>>>>> @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
>>>>>>>> struct dpu_encoder_phys *cur_master;
>>>>>>>> struct dpu_encoder_phys *cur_slave;
>>>>>>>> struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
>>>>>>>> + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>>>>>> struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
>>>>>>>> unsigned int dsc_mask;
>>>>>>>> @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>>>> 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_dsc[MAX_CHANNELS_PER_ENC];
>>>>>>>> + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
>>>>>>>> int num_pp, num_dsc, num_ctl;
>>>>>>>> + int num_cwb = 0;
>>>>>>>> + bool is_cwb_encoder;
>>>>>>>> unsigned int dsc_mask = 0;
>>>>>>>> int i;
>>>>>>>> @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>>>> priv = drm_enc->dev->dev_private;
>>>>>>>> dpu_kms = to_dpu_kms(priv->kms);
>>>>>>>> + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
>>>>>>>> + dpu_enc->disp_info.intf_type == INTF_WB;
>>>>>>>> global_state = dpu_kms_get_existing_global_state(dpu_kms);
>>>>>>>> if (IS_ERR_OR_NULL(global_state)) {
>>>>>>>> @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>>>>> trace_dpu_enc_mode_set(DRMID(drm_enc));
>>>>>>>> /* Query resource that have been reserved in atomic check step. */
>>>>>>>> - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>>>> - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>>>>>>>> - ARRAY_SIZE(hw_pp));
>>>>>>>> + if (is_cwb_encoder) {
>>>>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>>>> + drm_enc->crtc,
>>>>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>>>>>> + hw_pp, ARRAY_SIZE(hw_pp));
>>>>>>>> + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>>>> + drm_enc->crtc,
>>>>>>>> + DPU_HW_BLK_CWB,
>>>>>>>> + hw_cwb, ARRAY_SIZE(hw_cwb));
>>>>>>>> + } else {
>>>>>>>> + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>>>> + drm_enc->crtc,
>>>>>>>> + DPU_HW_BLK_PINGPONG, hw_pp,
>>>>>>>> + ARRAY_SIZE(hw_pp));
>>>>>>>> + }
>>>>>>>> +
>>>>>>>> + for (i = 0; i < num_cwb; i++)
>>>>>>>> + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
>>>>>>>> +
>>>>>>>> num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>>>>> drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>>>> index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>>>>>> @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
>>>>>>>> DPU_HW_BLK_LM,
>>>>>>>> DPU_HW_BLK_CTL,
>>>>>>>> DPU_HW_BLK_PINGPONG,
>>>>>>>> + DPU_HW_BLK_DCWB_PINGPONG,
>>>>>>>> DPU_HW_BLK_INTF,
>>>>>>>> DPU_HW_BLK_WB,
>>>>>>>> DPU_HW_BLK_DSPP,
>>>>>>>> DPU_HW_BLK_MERGE_3D,
>>>>>>>> DPU_HW_BLK_DSC,
>>>>>>>> DPU_HW_BLK_CDM,
>>>>>>>> + DPU_HW_BLK_CWB,
>>>>>>>> DPU_HW_BLK_MAX,
>>>>>>>> };
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>>>> index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>>>>> @@ -128,6 +128,7 @@ struct dpu_global_state {
>>>>>>>> uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>>>>>>> uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>>>>>>> uint32_t cdm_to_crtc_id;
>>>>>>>> + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
>>>>>>>> };
>>>>>>>> struct dpu_global_state
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>>>>>> return -EINVAL;
>>>>>>>> }
>>>>>>>> +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
>>>>>>>> + struct dpu_global_state *global_state,
>>>>>>>> + uint32_t crtc_id,
>>>>>>>> + struct msm_display_topology *topology)
>>>>>>>> +{
>>>>>>>> + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
>>>>>>>> + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
>>>>>>>> + int cwb_pp_idx[MAX_BLOCKS];
>>>>>>>> + int cwb_mux_idx[MAX_BLOCKS];
>>>>>>>> +
>>>>>>>> + /*
>>>>>>>> + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
>>>>>>>> + * mixer
>>>>>>>> + *
>>>>>>>> + * TODO: add support reserving resources for platforms with no
>>>>>>>> + * PINGPONG_CWB
>>>>>>>
>>>>>>> What about doing it other way around: allocate CWBs first as required
>>>>>>> (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
>>>>>>> (I think it's enough to simply make CWB blocks have a corresponding PP
>>>>>>> index as a property). This way the driver can handle both legacy and
>>>>>>> current platforms.
>>>>>>
>>>>>> Hi Dmitry,
>>>>>>
>>>>>> Sorry if I'm misunderstanding your suggestion, but the main change needed to
>>>>>> support platforms with no dedicated PINGPONG_CWB is where in the
>>>>>> rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
>>>>>> I'm not sure how changing the order in which CWBs and the pingpong blocks
>>>>>> are assigned will address that.
>>>>>>
>>>>>> (FWIW, the only change necessary to add support for non-dedicated
>>>>>> PINGPONG_CWBs platforms for this function should just be changing the
>>>>>> initialization value of cwb_pp_start_idx)
>>>>>
>>>>> If I remember correctly, we have identified several generations of DPU
>>>>> wrt. CWB handling:
>>>>> - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
>>>>> - 7.2, dedicated PP_1?
>>>>> - 5.0+, shared PP blocks
>>>>> - older DPUs, special handling of PP
>>>>>
>>>>> If the driver allocates PP first and then first it has to allocated PP
>>>>> (in a platform-specific way) and then go from PINGPONG to CWB (in a
>>>>> platform-specific way). If CWB is allocated first, then you have only
>>>>> one platform-specific piece of code that gets PINGPONG for the CWB (and
>>>>> as this function is called after the CWB allocation, the major part of
>>>>> the CWB / PP allocation is generic).
>>>>
>>>> The issue with breaking this into separate helpers/functions is that the CWB
>>>> mux and PPB indices are dependent on each other. But I agree that we can
>>>> reserve CWB mux and the PPBs in 2 separate loops within this helper to
>>>> minimize the special platform-specific handling.
>>>
>>> Doesn't it just PPB depend on CWB?
>>
>> Sorry, poor wording on my part. Was referring specifically to this part
>> of the logic within the code chunk:
>>
>> ```
>> cwb_pp_idx[cwb_pp_count] = j;
>> cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
>> ```
>>
>> The point I wanted to make was that I think we can keep the CWB-specific
>> reservation of the the PPBs and muxes in this function, but I agree with
>> your suggestion to reserve the CWBs first and the PPBs second (just in
>> separate loops rather than separate functions).
>
> Sounds fine with me. I don't think you even need a second loop, just
> simple maths should be fine.
Got it.. do you mean just swapping the current for loop logic to loop
over all the CWB blocks instead?
So something like:
```
for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
cwb_pp_count < num_cwb_pp; i++) {
for (int j = cwb_pp_start_idx;
j < ARRAY_SIZE(rm->cwb_blks); j++) {
/*
* Odd LMs must be assigned to odd PINGPONGs and even
* LMs with even PINGPONGs
*/
if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) ||
i % 2 != j % 2)
continue;
cwb_mux_idx[cwb_pp_count] = j;
cwb_pp_idx[cwb_pp_count] = j + cwb_pp_start_idx;
cwb_pp_count++;
break;
}
}
```
>
>>
>>
>>>
>>>
>>>>
>>>> Also wanted to note that the comment doc on the PPB odd/even rule is
>>>> inaccurate -- technically the odd/even rule applies specifically to the CWB
>>>> mux as odd/even LMs are hardwired to their respective CWB muxes. Will
>>>> correct the comment doc to be more accurate.
>>>
>>> Yes, please fix that.
>>>
>>>>
>>>> Thanks,
>>>>
>>>> Jessica Zhang
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-09 22:34 ` Jessica Zhang
@ 2025-01-10 0:00 ` Dmitry Baryshkov
2025-01-10 0:30 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-10 0:00 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
>
>
> On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
> > On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
> > >
> > >
> > > On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
> > > > On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
> > > > > Add the cwb_enabled flag to msm_display topology and adjust the toplogy
> > > > > to account for concurrent writeback
> > > >
> > > > Why?
> > >
> > > Hi Dmitry,
> > >
> > > This flag is necessary to specify that CWB mux(es) need to be assigned for
> > > the given reqeusted topology.
> >
> > Why is necessary? Please rephrase your statement (we need foo bar, so do
> > baz).
>
> Ack, what do you think of rephrasing the commit msg to this:
>
> ```
> Add support for adjusting topology based on if concurrent writeback is
> enabled.
>
> Currently, the topology is calculated based on the assumption that the user
> cannot request real-time and writeback simultaneously. For example, the
> number of LMs and CTLs are currently based off the number of phys encoders
> under the assumption there will be at least 1 LM/CTL per phys encoder.
>
> This will not hold true for concurrent writeback as 2 phys encoders (1
> real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
> writeback is enabled.
>
> To account for this, add a cwb_enabled flag and only adjust the number of
> CTL/LMs needed by a given topology based on the number of phys encoders only
> if CWB is not enabled.
>
> ```
>
> >
> > >
> > > >
> > > > >
> > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > ---
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
> > > > > 3 files changed, 20 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > > > dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> > > > > &crtc_state->adjusted_mode);
> > > > > + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
> > > > > +
> > > > > /*
> > > > > * Datapath topology selection
> > > > > *
> > > > > @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > > > * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> > > > > *
> > > > > * Add dspps to the reservation requirements if ctm is requested
> > > > > + *
> > > > > + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
> > > > > + * enabled. This is because in cases where CWB is enabled, num_intf will
> > > > > + * count both the WB and real-time phys encoders.
> > > > > + *
> > > > > + * For non-DSC CWB usecases, have the num_lm be decided by the
> > > > > + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
> > > > > */
> > > > > - if (topology.num_intf == 2)
> > > > > + if (topology.num_intf == 2 && !topology.cwb_enabled)
> > > > > topology.num_lm = 2;
> > > > > else if (topology.num_dsc == 2)
> > > > > topology.num_lm = 2;
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
> > > > > int i = 0, j, num_ctls;
> > > > > bool needs_split_display;
> > > > > - /* each hw_intf needs its own hw_ctrl to program its control path */
> > > > > - num_ctls = top->num_intf;
> > > > > + /*
> > > > > + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
> > > > > + * control path. Hardcode num_ctls to 1 if CWB is enabled
> > > > > + */
> > > >
> > > > Why?
> > >
> > > This is because num_intf is based on the number of phys_encs. Since in the
> > > CWB case, the WB and real-time encoders will be driven by the same CTL. I
> > > can add this to the comment doc.
> >
> > Why are they driven by the same CTL? Is it also the case for platforms
> > before DPU 5.x?
>
> This is because the WB and real-time path for a given topology would be
> driven by the same data path so the same CTL should enable the real-time and
> WB active bits.
>
> This is the same for pre-DPU 5.x.
But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
separte CTL for each of the physical encoders.
>
> >
> > >
> > > Thanks,
> > >
> > > Jessica Zhang
> > >
> > > >
> > > > > + if (top->cwb_enabled)
> > > > > + num_ctls = 1;
> > > > > + else
> > > > > + num_ctls = top->num_intf;
> > > > > needs_split_display = _dpu_rm_needs_split_display(top);
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > @@ -46,6 +46,7 @@ struct dpu_rm {
> > > > > * @num_dspp: number of dspp blocks used
> > > > > * @num_dsc: number of Display Stream Compression (DSC) blocks used
> > > > > * @needs_cdm: indicates whether cdm block is needed for this display topology
> > > > > + * @cwb_enabled: indicates whether CWB is enabled for this display topology
> > > > > */
> > > > > struct msm_display_topology {
> > > > > u32 num_lm;
> > > > > @@ -53,6 +54,7 @@ struct msm_display_topology {
> > > > > u32 num_dspp;
> > > > > u32 num_dsc;
> > > > > bool needs_cdm;
> > > > > + bool cwb_enabled;
> > > > > };
> > > > > int dpu_rm_init(struct drm_device *dev,
> > > > >
> > > > > --
> > > > > 2.34.1
> > > > >
> > > >
> > > > --
> > > > With best wishes
> > > > Dmitry
> > >
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB
2025-01-09 22:53 ` Jessica Zhang
@ 2025-01-10 0:02 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-10 0:02 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, Jan 09, 2025 at 02:53:40PM -0800, Jessica Zhang wrote:
>
>
> On 1/9/2025 2:13 PM, Dmitry Baryshkov wrote:
> > On Thu, 9 Jan 2025 at 23:26, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> > >
> > >
> > >
> > > On 12/28/2024 8:47 PM, Dmitry Baryshkov wrote:
> > > > On Thu, Dec 26, 2024 at 02:49:28PM -0800, Jessica Zhang wrote:
> > > > >
> > > > >
> > > > > On 12/20/2024 5:07 PM, Dmitry Baryshkov wrote:
> > > > > > On Fri, Dec 20, 2024 at 04:12:29PM -0800, Jessica Zhang wrote:
> > > > > > >
> > > > > > >
> > > > > > > On 12/19/2024 9:52 PM, Dmitry Baryshkov wrote:
> > > > > > > > On Mon, Dec 16, 2024 at 04:43:29PM -0800, Jessica Zhang wrote:
> > > > > > > > > Add support for RM to reserve dedicated CWB PINGPONGs and CWB muxes
> > > > > > > > >
> > > > > > > > > For concurrent writeback, even-indexed CWB muxes must be assigned to
> > > > > > > > > even-indexed LMs and odd-indexed CWB muxes for odd-indexed LMs. The same
> > > > > > > > > even/odd rule applies for dedicated CWB PINGPONGs.
> > > > > > > > >
> > > > > > > > > Track the CWB muxes in the global state and add a CWB-specific helper to
> > > > > > > > > reserve the correct CWB muxes and dedicated PINGPONGs following the
> > > > > > > > > even/odd rule.
> > > > > > > > >
> > > > > > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > > > > > ---
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 34 ++++++++++--
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 2 +
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 1 +
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 83 +++++++++++++++++++++++++++++
> > > > > > > > > 4 files changed, 116 insertions(+), 4 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > > > > index a895d48fe81ccc71d265e089992786e8b6268b1b..a95dc1f0c6a422485c7ba98743e944e1a4f43539 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > > > > @@ -2,7 +2,7 @@
> > > > > > > > > /*
> > > > > > > > > * Copyright (C) 2013 Red Hat
> > > > > > > > > * Copyright (c) 2014-2018, 2020-2021 The Linux Foundation. All rights reserved.
> > > > > > > > > - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> > > > > > > > > + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> > > > > > > > > *
> > > > > > > > > * Author: Rob Clark <robdclark@gmail.com>
> > > > > > > > > */
> > > > > > > > > @@ -28,6 +28,7 @@
> > > > > > > > > #include "dpu_hw_dsc.h"
> > > > > > > > > #include "dpu_hw_merge3d.h"
> > > > > > > > > #include "dpu_hw_cdm.h"
> > > > > > > > > +#include "dpu_hw_cwb.h"
> > > > > > > > > #include "dpu_formats.h"
> > > > > > > > > #include "dpu_encoder_phys.h"
> > > > > > > > > #include "dpu_crtc.h"
> > > > > > > > > @@ -133,6 +134,9 @@ enum dpu_enc_rc_states {
> > > > > > > > > * @cur_slave: As above but for the slave encoder.
> > > > > > > > > * @hw_pp: Handle to the pingpong blocks used for the display. No.
> > > > > > > > > * pingpong blocks can be different than num_phys_encs.
> > > > > > > > > + * @hw_cwb: Handle to the CWB muxes used for concurrent writeback
> > > > > > > > > + * display. Number of CWB muxes can be different than
> > > > > > > > > + * num_phys_encs.
> > > > > > > > > * @hw_dsc: Handle to the DSC blocks used for the display.
> > > > > > > > > * @dsc_mask: Bitmask of used DSC blocks.
> > > > > > > > > * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
> > > > > > > > > @@ -177,6 +181,7 @@ struct dpu_encoder_virt {
> > > > > > > > > struct dpu_encoder_phys *cur_master;
> > > > > > > > > struct dpu_encoder_phys *cur_slave;
> > > > > > > > > struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
> > > > > > > > > + struct dpu_hw_cwb *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > > > > > > > struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
> > > > > > > > > unsigned int dsc_mask;
> > > > > > > > > @@ -1138,7 +1143,10 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > > > > > 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_dsc[MAX_CHANNELS_PER_ENC];
> > > > > > > > > + struct dpu_hw_blk *hw_cwb[MAX_CHANNELS_PER_ENC];
> > > > > > > > > int num_pp, num_dsc, num_ctl;
> > > > > > > > > + int num_cwb = 0;
> > > > > > > > > + bool is_cwb_encoder;
> > > > > > > > > unsigned int dsc_mask = 0;
> > > > > > > > > int i;
> > > > > > > > > @@ -1152,6 +1160,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > > > > > priv = drm_enc->dev->dev_private;
> > > > > > > > > dpu_kms = to_dpu_kms(priv->kms);
> > > > > > > > > + is_cwb_encoder = drm_crtc_in_clone_mode(crtc_state) &&
> > > > > > > > > + dpu_enc->disp_info.intf_type == INTF_WB;
> > > > > > > > > global_state = dpu_kms_get_existing_global_state(dpu_kms);
> > > > > > > > > if (IS_ERR_OR_NULL(global_state)) {
> > > > > > > > > @@ -1162,9 +1172,25 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > > > > > trace_dpu_enc_mode_set(DRMID(drm_enc));
> > > > > > > > > /* Query resource that have been reserved in atomic check step. */
> > > > > > > > > - num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > > > > - drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > > > > > - ARRAY_SIZE(hw_pp));
> > > > > > > > > + if (is_cwb_encoder) {
> > > > > > > > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > > > > + drm_enc->crtc,
> > > > > > > > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > > > > > > > + hw_pp, ARRAY_SIZE(hw_pp));
> > > > > > > > > + num_cwb = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > > > > + drm_enc->crtc,
> > > > > > > > > + DPU_HW_BLK_CWB,
> > > > > > > > > + hw_cwb, ARRAY_SIZE(hw_cwb));
> > > > > > > > > + } else {
> > > > > > > > > + num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > > > > + drm_enc->crtc,
> > > > > > > > > + DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > > > > > + ARRAY_SIZE(hw_pp));
> > > > > > > > > + }
> > > > > > > > > +
> > > > > > > > > + for (i = 0; i < num_cwb; i++)
> > > > > > > > > + dpu_enc->hw_cwb[i] = to_dpu_hw_cwb(hw_cwb[i]);
> > > > > > > > > +
> > > > > > > > > num_ctl = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > > > > drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > > > > > index ba7bb05efe9b8cac01a908e53121117e130f91ec..8d820cd1b5545d247515763039b341184e814e32 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> > > > > > > > > @@ -77,12 +77,14 @@ enum dpu_hw_blk_type {
> > > > > > > > > DPU_HW_BLK_LM,
> > > > > > > > > DPU_HW_BLK_CTL,
> > > > > > > > > DPU_HW_BLK_PINGPONG,
> > > > > > > > > + DPU_HW_BLK_DCWB_PINGPONG,
> > > > > > > > > DPU_HW_BLK_INTF,
> > > > > > > > > DPU_HW_BLK_WB,
> > > > > > > > > DPU_HW_BLK_DSPP,
> > > > > > > > > DPU_HW_BLK_MERGE_3D,
> > > > > > > > > DPU_HW_BLK_DSC,
> > > > > > > > > DPU_HW_BLK_CDM,
> > > > > > > > > + DPU_HW_BLK_CWB,
> > > > > > > > > DPU_HW_BLK_MAX,
> > > > > > > > > };
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > > index 48d756d8f8c6e4ab94b72bac0418320f7dc8cda8..1fc8abda927fc094b369e0d1efc795b71d6a7fcb 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > > > > @@ -128,6 +128,7 @@ struct dpu_global_state {
> > > > > > > > > uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > > > > > > > > uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > > > > > > > > uint32_t cdm_to_crtc_id;
> > > > > > > > > + uint32_t cwb_to_crtc_id[CWB_MAX - CWB_0];
> > > > > > > > > };
> > > > > > > > > struct dpu_global_state
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > index 85adaf256b2c705d2d7df378b6ffc0e578f52bc3..ead24bb0ceb5d8ec4705f0d32330294d0b45b216 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > @@ -234,6 +234,55 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > > > > > > return -EINVAL;
> > > > > > > > > }
> > > > > > > > > +static int _dpu_rm_reserve_cwb_mux_and_pingpongs(struct dpu_rm *rm,
> > > > > > > > > + struct dpu_global_state *global_state,
> > > > > > > > > + uint32_t crtc_id,
> > > > > > > > > + struct msm_display_topology *topology)
> > > > > > > > > +{
> > > > > > > > > + int num_cwb_pp = topology->num_lm, cwb_pp_count = 0;
> > > > > > > > > + int cwb_pp_start_idx = PINGPONG_CWB_0 - PINGPONG_0;
> > > > > > > > > + int cwb_pp_idx[MAX_BLOCKS];
> > > > > > > > > + int cwb_mux_idx[MAX_BLOCKS];
> > > > > > > > > +
> > > > > > > > > + /*
> > > > > > > > > + * Reserve additional dedicated CWB PINGPONG blocks and muxes for each
> > > > > > > > > + * mixer
> > > > > > > > > + *
> > > > > > > > > + * TODO: add support reserving resources for platforms with no
> > > > > > > > > + * PINGPONG_CWB
> > > > > > > >
> > > > > > > > What about doing it other way around: allocate CWBs first as required
> > > > > > > > (even/odd, proper count, etc). Then for each of CWBs allocate a PP block
> > > > > > > > (I think it's enough to simply make CWB blocks have a corresponding PP
> > > > > > > > index as a property). This way the driver can handle both legacy and
> > > > > > > > current platforms.
> > > > > > >
> > > > > > > Hi Dmitry,
> > > > > > >
> > > > > > > Sorry if I'm misunderstanding your suggestion, but the main change needed to
> > > > > > > support platforms with no dedicated PINGPONG_CWB is where in the
> > > > > > > rm->pingpong_blks list to start assigning pingpong blocks for the CWB mux.
> > > > > > > I'm not sure how changing the order in which CWBs and the pingpong blocks
> > > > > > > are assigned will address that.
> > > > > > >
> > > > > > > (FWIW, the only change necessary to add support for non-dedicated
> > > > > > > PINGPONG_CWBs platforms for this function should just be changing the
> > > > > > > initialization value of cwb_pp_start_idx)
> > > > > >
> > > > > > If I remember correctly, we have identified several generations of DPU
> > > > > > wrt. CWB handling:
> > > > > > - 8.1+ (or 8.0+?), DCWB, dedicated PP blocks
> > > > > > - 7.2, dedicated PP_1?
> > > > > > - 5.0+, shared PP blocks
> > > > > > - older DPUs, special handling of PP
> > > > > >
> > > > > > If the driver allocates PP first and then first it has to allocated PP
> > > > > > (in a platform-specific way) and then go from PINGPONG to CWB (in a
> > > > > > platform-specific way). If CWB is allocated first, then you have only
> > > > > > one platform-specific piece of code that gets PINGPONG for the CWB (and
> > > > > > as this function is called after the CWB allocation, the major part of
> > > > > > the CWB / PP allocation is generic).
> > > > >
> > > > > The issue with breaking this into separate helpers/functions is that the CWB
> > > > > mux and PPB indices are dependent on each other. But I agree that we can
> > > > > reserve CWB mux and the PPBs in 2 separate loops within this helper to
> > > > > minimize the special platform-specific handling.
> > > >
> > > > Doesn't it just PPB depend on CWB?
> > >
> > > Sorry, poor wording on my part. Was referring specifically to this part
> > > of the logic within the code chunk:
> > >
> > > ```
> > > cwb_pp_idx[cwb_pp_count] = j;
> > > cwb_mux_idx[cwb_pp_count] = j - cwb_pp_start_idx;
> > > ```
> > >
> > > The point I wanted to make was that I think we can keep the CWB-specific
> > > reservation of the the PPBs and muxes in this function, but I agree with
> > > your suggestion to reserve the CWBs first and the PPBs second (just in
> > > separate loops rather than separate functions).
> >
> > Sounds fine with me. I don't think you even need a second loop, just
> > simple maths should be fine.
>
> Got it.. do you mean just swapping the current for loop logic to loop over
> all the CWB blocks instead?
>
> So something like:
>
> ```
> for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> cwb_pp_count < num_cwb_pp; i++) {
> for (int j = cwb_pp_start_idx;
> j < ARRAY_SIZE(rm->cwb_blks); j++) {
> /*
> * Odd LMs must be assigned to odd PINGPONGs and even
> * LMs with even PINGPONGs
> */
> if (reserved_by_other(global_state->cwb_to_crtc_id, j, crtc_id) ||
> i % 2 != j % 2)
> continue;
>
> cwb_mux_idx[cwb_pp_count] = j;
> cwb_pp_idx[cwb_pp_count] = j + cwb_pp_start_idx;
> cwb_pp_count++;
> break;
> }
> }
> ```
Yes. Then pre-8.0 platforms will have to change only the cwb_pp_idx
assignment line.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-10 0:00 ` Dmitry Baryshkov
@ 2025-01-10 0:30 ` Jessica Zhang
2025-01-10 1:42 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-10 0:30 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/9/2025 4:00 PM, Dmitry Baryshkov wrote:
> On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
>>
>>
>> On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
>>> On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
>>>>
>>>>
>>>> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
>>>>> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
>>>>>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
>>>>>> to account for concurrent writeback
>>>>>
>>>>> Why?
>>>>
>>>> Hi Dmitry,
>>>>
>>>> This flag is necessary to specify that CWB mux(es) need to be assigned for
>>>> the given reqeusted topology.
>>>
>>> Why is necessary? Please rephrase your statement (we need foo bar, so do
>>> baz).
>>
>> Ack, what do you think of rephrasing the commit msg to this:
>>
>> ```
>> Add support for adjusting topology based on if concurrent writeback is
>> enabled.
>>
>> Currently, the topology is calculated based on the assumption that the user
>> cannot request real-time and writeback simultaneously. For example, the
>> number of LMs and CTLs are currently based off the number of phys encoders
>> under the assumption there will be at least 1 LM/CTL per phys encoder.
>>
>> This will not hold true for concurrent writeback as 2 phys encoders (1
>> real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
>> writeback is enabled.
>>
>> To account for this, add a cwb_enabled flag and only adjust the number of
>> CTL/LMs needed by a given topology based on the number of phys encoders only
>> if CWB is not enabled.
>>
>> ```
>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
>>>>>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>>>>>> &crtc_state->adjusted_mode);
>>>>>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
>>>>>> +
>>>>>> /*
>>>>>> * Datapath topology selection
>>>>>> *
>>>>>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>>>>>> *
>>>>>> * Add dspps to the reservation requirements if ctm is requested
>>>>>> + *
>>>>>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
>>>>>> + * enabled. This is because in cases where CWB is enabled, num_intf will
>>>>>> + * count both the WB and real-time phys encoders.
>>>>>> + *
>>>>>> + * For non-DSC CWB usecases, have the num_lm be decided by the
>>>>>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
>>>>>> */
>>>>>> - if (topology.num_intf == 2)
>>>>>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
>>>>>> topology.num_lm = 2;
>>>>>> else if (topology.num_dsc == 2)
>>>>>> topology.num_lm = 2;
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
>>>>>> int i = 0, j, num_ctls;
>>>>>> bool needs_split_display;
>>>>>> - /* each hw_intf needs its own hw_ctrl to program its control path */
>>>>>> - num_ctls = top->num_intf;
>>>>>> + /*
>>>>>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
>>>>>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
>>>>>> + */
>>>>>
>>>>> Why?
>>>>
>>>> This is because num_intf is based on the number of phys_encs. Since in the
>>>> CWB case, the WB and real-time encoders will be driven by the same CTL. I
>>>> can add this to the comment doc.
>>>
>>> Why are they driven by the same CTL? Is it also the case for platforms
>>> before DPU 5.x?
>>
>> This is because the WB and real-time path for a given topology would be
>> driven by the same data path so the same CTL should enable the real-time and
>> WB active bits.
>>
>> This is the same for pre-DPU 5.x.
>
> But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
> separte CTL for each of the physical encoders.
For pre-DPU 5.x, enabling CWB would mean configuring the registers under
both the WB and MODE_SEL_* cases here [1]
[1]
https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c#L588
>
>>
>>>
>>>>
>>>> Thanks,
>>>>
>>>> Jessica Zhang
>>>>
>>>>>
>>>>>> + if (top->cwb_enabled)
>>>>>> + num_ctls = 1;
>>>>>> + else
>>>>>> + num_ctls = top->num_intf;
>>>>>> needs_split_display = _dpu_rm_needs_split_display(top);
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>> @@ -46,6 +46,7 @@ struct dpu_rm {
>>>>>> * @num_dspp: number of dspp blocks used
>>>>>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
>>>>>> * @needs_cdm: indicates whether cdm block is needed for this display topology
>>>>>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
>>>>>> */
>>>>>> struct msm_display_topology {
>>>>>> u32 num_lm;
>>>>>> @@ -53,6 +54,7 @@ struct msm_display_topology {
>>>>>> u32 num_dspp;
>>>>>> u32 num_dsc;
>>>>>> bool needs_cdm;
>>>>>> + bool cwb_enabled;
>>>>>> };
>>>>>> int dpu_rm_init(struct drm_device *dev,
>>>>>>
>>>>>> --
>>>>>> 2.34.1
>>>>>>
>>>>>
>>>>> --
>>>>> With best wishes
>>>>> Dmitry
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-10 0:30 ` Jessica Zhang
@ 2025-01-10 1:42 ` Dmitry Baryshkov
2025-01-10 1:50 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-10 1:42 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Fri, 10 Jan 2025 at 02:30, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 1/9/2025 4:00 PM, Dmitry Baryshkov wrote:
> > On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
> >>
> >>
> >> On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
> >>> On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
> >>>>
> >>>>
> >>>> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
> >>>>> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
> >>>>>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
> >>>>>> to account for concurrent writeback
> >>>>>
> >>>>> Why?
> >>>>
> >>>> Hi Dmitry,
> >>>>
> >>>> This flag is necessary to specify that CWB mux(es) need to be assigned for
> >>>> the given reqeusted topology.
> >>>
> >>> Why is necessary? Please rephrase your statement (we need foo bar, so do
> >>> baz).
> >>
> >> Ack, what do you think of rephrasing the commit msg to this:
> >>
> >> ```
> >> Add support for adjusting topology based on if concurrent writeback is
> >> enabled.
> >>
> >> Currently, the topology is calculated based on the assumption that the user
> >> cannot request real-time and writeback simultaneously. For example, the
> >> number of LMs and CTLs are currently based off the number of phys encoders
> >> under the assumption there will be at least 1 LM/CTL per phys encoder.
> >>
> >> This will not hold true for concurrent writeback as 2 phys encoders (1
> >> real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
> >> writeback is enabled.
> >>
> >> To account for this, add a cwb_enabled flag and only adjust the number of
> >> CTL/LMs needed by a given topology based on the number of phys encoders only
> >> if CWB is not enabled.
> >>
> >> ```
> >>
> >>>
> >>>>
> >>>>>
> >>>>>>
> >>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >>>>>> ---
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
> >>>>>> 3 files changed, 20 insertions(+), 3 deletions(-)
> >>>>>>
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >>>>>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
> >>>>>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> >>>>>> &crtc_state->adjusted_mode);
> >>>>>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
> >>>>>> +
> >>>>>> /*
> >>>>>> * Datapath topology selection
> >>>>>> *
> >>>>>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
> >>>>>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> >>>>>> *
> >>>>>> * Add dspps to the reservation requirements if ctm is requested
> >>>>>> + *
> >>>>>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
> >>>>>> + * enabled. This is because in cases where CWB is enabled, num_intf will
> >>>>>> + * count both the WB and real-time phys encoders.
> >>>>>> + *
> >>>>>> + * For non-DSC CWB usecases, have the num_lm be decided by the
> >>>>>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
> >>>>>> */
> >>>>>> - if (topology.num_intf == 2)
> >>>>>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
> >>>>>> topology.num_lm = 2;
> >>>>>> else if (topology.num_dsc == 2)
> >>>>>> topology.num_lm = 2;
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
> >>>>>> int i = 0, j, num_ctls;
> >>>>>> bool needs_split_display;
> >>>>>> - /* each hw_intf needs its own hw_ctrl to program its control path */
> >>>>>> - num_ctls = top->num_intf;
> >>>>>> + /*
> >>>>>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
> >>>>>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
> >>>>>> + */
> >>>>>
> >>>>> Why?
> >>>>
> >>>> This is because num_intf is based on the number of phys_encs. Since in the
> >>>> CWB case, the WB and real-time encoders will be driven by the same CTL. I
> >>>> can add this to the comment doc.
> >>>
> >>> Why are they driven by the same CTL? Is it also the case for platforms
> >>> before DPU 5.x?
> >>
> >> This is because the WB and real-time path for a given topology would be
> >> driven by the same data path so the same CTL should enable the real-time and
> >> WB active bits.
> >>
> >> This is the same for pre-DPU 5.x.
> >
> > But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
> > separte CTL for each of the physical encoders.
>
> For pre-DPU 5.x, enabling CWB would mean configuring the registers under
> both the WB and MODE_SEL_* cases here [1]
But do we still have to use a single CTL or would we use two different
CTLs, one for the main output and one for WB?
>
> [1]
> https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c#L588
>
> >
> >>
> >>>
> >>>>
> >>>> Thanks,
> >>>>
> >>>> Jessica Zhang
> >>>>
> >>>>>
> >>>>>> + if (top->cwb_enabled)
> >>>>>> + num_ctls = 1;
> >>>>>> + else
> >>>>>> + num_ctls = top->num_intf;
> >>>>>> needs_split_display = _dpu_rm_needs_split_display(top);
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>>>>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> >>>>>> @@ -46,6 +46,7 @@ struct dpu_rm {
> >>>>>> * @num_dspp: number of dspp blocks used
> >>>>>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
> >>>>>> * @needs_cdm: indicates whether cdm block is needed for this display topology
> >>>>>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
> >>>>>> */
> >>>>>> struct msm_display_topology {
> >>>>>> u32 num_lm;
> >>>>>> @@ -53,6 +54,7 @@ struct msm_display_topology {
> >>>>>> u32 num_dspp;
> >>>>>> u32 num_dsc;
> >>>>>> bool needs_cdm;
> >>>>>> + bool cwb_enabled;
> >>>>>> };
> >>>>>> int dpu_rm_init(struct drm_device *dev,
> >>>>>>
> >>>>>> --
> >>>>>> 2.34.1
> >>>>>>
> >>>>>
> >>>>> --
> >>>>> With best wishes
> >>>>> Dmitry
> >>>>
> >>>
> >>> --
> >>> With best wishes
> >>> Dmitry
> >>
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-10 1:42 ` Dmitry Baryshkov
@ 2025-01-10 1:50 ` Jessica Zhang
2025-01-10 2:10 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-10 1:50 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/9/2025 5:42 PM, Dmitry Baryshkov wrote:
> On Fri, 10 Jan 2025 at 02:30, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>
>>
>>
>> On 1/9/2025 4:00 PM, Dmitry Baryshkov wrote:
>>> On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
>>>>
>>>>
>>>> On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
>>>>> On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
>>>>>>
>>>>>>
>>>>>> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
>>>>>>> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
>>>>>>>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
>>>>>>>> to account for concurrent writeback
>>>>>>>
>>>>>>> Why?
>>>>>>
>>>>>> Hi Dmitry,
>>>>>>
>>>>>> This flag is necessary to specify that CWB mux(es) need to be assigned for
>>>>>> the given reqeusted topology.
>>>>>
>>>>> Why is necessary? Please rephrase your statement (we need foo bar, so do
>>>>> baz).
>>>>
>>>> Ack, what do you think of rephrasing the commit msg to this:
>>>>
>>>> ```
>>>> Add support for adjusting topology based on if concurrent writeback is
>>>> enabled.
>>>>
>>>> Currently, the topology is calculated based on the assumption that the user
>>>> cannot request real-time and writeback simultaneously. For example, the
>>>> number of LMs and CTLs are currently based off the number of phys encoders
>>>> under the assumption there will be at least 1 LM/CTL per phys encoder.
>>>>
>>>> This will not hold true for concurrent writeback as 2 phys encoders (1
>>>> real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
>>>> writeback is enabled.
>>>>
>>>> To account for this, add a cwb_enabled flag and only adjust the number of
>>>> CTL/LMs needed by a given topology based on the number of phys encoders only
>>>> if CWB is not enabled.
>>>>
>>>> ```
>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>>>> ---
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
>>>>>>>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>>>>>>>
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>>>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>>>>>>>> &crtc_state->adjusted_mode);
>>>>>>>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
>>>>>>>> +
>>>>>>>> /*
>>>>>>>> * Datapath topology selection
>>>>>>>> *
>>>>>>>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>>>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>>>>>>>> *
>>>>>>>> * Add dspps to the reservation requirements if ctm is requested
>>>>>>>> + *
>>>>>>>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
>>>>>>>> + * enabled. This is because in cases where CWB is enabled, num_intf will
>>>>>>>> + * count both the WB and real-time phys encoders.
>>>>>>>> + *
>>>>>>>> + * For non-DSC CWB usecases, have the num_lm be decided by the
>>>>>>>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
>>>>>>>> */
>>>>>>>> - if (topology.num_intf == 2)
>>>>>>>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
>>>>>>>> topology.num_lm = 2;
>>>>>>>> else if (topology.num_dsc == 2)
>>>>>>>> topology.num_lm = 2;
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
>>>>>>>> int i = 0, j, num_ctls;
>>>>>>>> bool needs_split_display;
>>>>>>>> - /* each hw_intf needs its own hw_ctrl to program its control path */
>>>>>>>> - num_ctls = top->num_intf;
>>>>>>>> + /*
>>>>>>>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
>>>>>>>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
>>>>>>>> + */
>>>>>>>
>>>>>>> Why?
>>>>>>
>>>>>> This is because num_intf is based on the number of phys_encs. Since in the
>>>>>> CWB case, the WB and real-time encoders will be driven by the same CTL. I
>>>>>> can add this to the comment doc.
>>>>>
>>>>> Why are they driven by the same CTL? Is it also the case for platforms
>>>>> before DPU 5.x?
>>>>
>>>> This is because the WB and real-time path for a given topology would be
>>>> driven by the same data path so the same CTL should enable the real-time and
>>>> WB active bits.
>>>>
>>>> This is the same for pre-DPU 5.x.
>>>
>>> But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
>>> separte CTL for each of the physical encoders.
>>
>> For pre-DPU 5.x, enabling CWB would mean configuring the registers under
>> both the WB and MODE_SEL_* cases here [1]
>
> But do we still have to use a single CTL or would we use two different
> CTLs, one for the main output and one for WB?
We would have to enable both WB and the real-time output on the same CTL
>
>>
>> [1]
>> https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c#L588
>>
>>>
>>>>
>>>>>
>>>>>>
>>>>>> Thanks,
>>>>>>
>>>>>> Jessica Zhang
>>>>>>
>>>>>>>
>>>>>>>> + if (top->cwb_enabled)
>>>>>>>> + num_ctls = 1;
>>>>>>>> + else
>>>>>>>> + num_ctls = top->num_intf;
>>>>>>>> needs_split_display = _dpu_rm_needs_split_display(top);
>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>> @@ -46,6 +46,7 @@ struct dpu_rm {
>>>>>>>> * @num_dspp: number of dspp blocks used
>>>>>>>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
>>>>>>>> * @needs_cdm: indicates whether cdm block is needed for this display topology
>>>>>>>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
>>>>>>>> */
>>>>>>>> struct msm_display_topology {
>>>>>>>> u32 num_lm;
>>>>>>>> @@ -53,6 +54,7 @@ struct msm_display_topology {
>>>>>>>> u32 num_dspp;
>>>>>>>> u32 num_dsc;
>>>>>>>> bool needs_cdm;
>>>>>>>> + bool cwb_enabled;
>>>>>>>> };
>>>>>>>> int dpu_rm_init(struct drm_device *dev,
>>>>>>>>
>>>>>>>> --
>>>>>>>> 2.34.1
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> With best wishes
>>>>>>> Dmitry
>>>>>>
>>>>>
>>>>> --
>>>>> With best wishes
>>>>> Dmitry
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-10 1:50 ` Jessica Zhang
@ 2025-01-10 2:10 ` Dmitry Baryshkov
2025-01-10 22:08 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-10 2:10 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Thu, Jan 09, 2025 at 05:50:16PM -0800, Jessica Zhang wrote:
>
>
> On 1/9/2025 5:42 PM, Dmitry Baryshkov wrote:
> > On Fri, 10 Jan 2025 at 02:30, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> > >
> > >
> > >
> > > On 1/9/2025 4:00 PM, Dmitry Baryshkov wrote:
> > > > On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
> > > > >
> > > > >
> > > > > On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
> > > > > > On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
> > > > > > >
> > > > > > >
> > > > > > > On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
> > > > > > > > On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
> > > > > > > > > Add the cwb_enabled flag to msm_display topology and adjust the toplogy
> > > > > > > > > to account for concurrent writeback
> > > > > > > >
> > > > > > > > Why?
> > > > > > >
> > > > > > > Hi Dmitry,
> > > > > > >
> > > > > > > This flag is necessary to specify that CWB mux(es) need to be assigned for
> > > > > > > the given reqeusted topology.
> > > > > >
> > > > > > Why is necessary? Please rephrase your statement (we need foo bar, so do
> > > > > > baz).
> > > > >
> > > > > Ack, what do you think of rephrasing the commit msg to this:
> > > > >
> > > > > ```
> > > > > Add support for adjusting topology based on if concurrent writeback is
> > > > > enabled.
> > > > >
> > > > > Currently, the topology is calculated based on the assumption that the user
> > > > > cannot request real-time and writeback simultaneously. For example, the
> > > > > number of LMs and CTLs are currently based off the number of phys encoders
> > > > > under the assumption there will be at least 1 LM/CTL per phys encoder.
> > > > >
> > > > > This will not hold true for concurrent writeback as 2 phys encoders (1
> > > > > real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
> > > > > writeback is enabled.
> > > > >
> > > > > To account for this, add a cwb_enabled flag and only adjust the number of
> > > > > CTL/LMs needed by a given topology based on the number of phys encoders only
> > > > > if CWB is not enabled.
> > > > >
> > > > > ```
> > > > >
> > > > > >
> > > > > > >
> > > > > > > >
> > > > > > > > >
> > > > > > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > > > > > ---
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
> > > > > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
> > > > > > > > > 3 files changed, 20 insertions(+), 3 deletions(-)
> > > > > > > > >
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > > index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > > > > > > > > @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > > > > > > > dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
> > > > > > > > > &crtc_state->adjusted_mode);
> > > > > > > > > + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
> > > > > > > > > +
> > > > > > > > > /*
> > > > > > > > > * Datapath topology selection
> > > > > > > > > *
> > > > > > > > > @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > > > > > > > > * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
> > > > > > > > > *
> > > > > > > > > * Add dspps to the reservation requirements if ctm is requested
> > > > > > > > > + *
> > > > > > > > > + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
> > > > > > > > > + * enabled. This is because in cases where CWB is enabled, num_intf will
> > > > > > > > > + * count both the WB and real-time phys encoders.
> > > > > > > > > + *
> > > > > > > > > + * For non-DSC CWB usecases, have the num_lm be decided by the
> > > > > > > > > + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
> > > > > > > > > */
> > > > > > > > > - if (topology.num_intf == 2)
> > > > > > > > > + if (topology.num_intf == 2 && !topology.cwb_enabled)
> > > > > > > > > topology.num_lm = 2;
> > > > > > > > > else if (topology.num_dsc == 2)
> > > > > > > > > topology.num_lm = 2;
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > > > > @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
> > > > > > > > > int i = 0, j, num_ctls;
> > > > > > > > > bool needs_split_display;
> > > > > > > > > - /* each hw_intf needs its own hw_ctrl to program its control path */
> > > > > > > > > - num_ctls = top->num_intf;
> > > > > > > > > + /*
> > > > > > > > > + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
> > > > > > > > > + * control path. Hardcode num_ctls to 1 if CWB is enabled
> > > > > > > > > + */
> > > > > > > >
> > > > > > > > Why?
> > > > > > >
> > > > > > > This is because num_intf is based on the number of phys_encs. Since in the
> > > > > > > CWB case, the WB and real-time encoders will be driven by the same CTL. I
> > > > > > > can add this to the comment doc.
> > > > > >
> > > > > > Why are they driven by the same CTL? Is it also the case for platforms
> > > > > > before DPU 5.x?
> > > > >
> > > > > This is because the WB and real-time path for a given topology would be
> > > > > driven by the same data path so the same CTL should enable the real-time and
> > > > > WB active bits.
> > > > >
> > > > > This is the same for pre-DPU 5.x.
> > > >
> > > > But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
> > > > separte CTL for each of the physical encoders.
> > >
> > > For pre-DPU 5.x, enabling CWB would mean configuring the registers under
> > > both the WB and MODE_SEL_* cases here [1]
> >
> > But do we still have to use a single CTL or would we use two different
> > CTLs, one for the main output and one for WB?
>
> We would have to enable both WB and the real-time output on the same CTL
Thanks for the confirmation. Then the text your wrote above should be
mostly okay. Please drop the first ("Add support...") sentence and s/can
be driven by/must be driven by/ .
>
> >
> > >
> > > [1]
> > > https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c#L588
> > >
> > > >
> > > > >
> > > > > >
> > > > > > >
> > > > > > > Thanks,
> > > > > > >
> > > > > > > Jessica Zhang
> > > > > > >
> > > > > > > >
> > > > > > > > > + if (top->cwb_enabled)
> > > > > > > > > + num_ctls = 1;
> > > > > > > > > + else
> > > > > > > > > + num_ctls = top->num_intf;
> > > > > > > > > needs_split_display = _dpu_rm_needs_split_display(top);
> > > > > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > > > > index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
> > > > > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > > > > @@ -46,6 +46,7 @@ struct dpu_rm {
> > > > > > > > > * @num_dspp: number of dspp blocks used
> > > > > > > > > * @num_dsc: number of Display Stream Compression (DSC) blocks used
> > > > > > > > > * @needs_cdm: indicates whether cdm block is needed for this display topology
> > > > > > > > > + * @cwb_enabled: indicates whether CWB is enabled for this display topology
> > > > > > > > > */
> > > > > > > > > struct msm_display_topology {
> > > > > > > > > u32 num_lm;
> > > > > > > > > @@ -53,6 +54,7 @@ struct msm_display_topology {
> > > > > > > > > u32 num_dspp;
> > > > > > > > > u32 num_dsc;
> > > > > > > > > bool needs_cdm;
> > > > > > > > > + bool cwb_enabled;
> > > > > > > > > };
> > > > > > > > > int dpu_rm_init(struct drm_device *dev,
> > > > > > > > >
> > > > > > > > > --
> > > > > > > > > 2.34.1
> > > > > > > > >
> > > > > > > >
> > > > > > > > --
> > > > > > > > With best wishes
> > > > > > > > Dmitry
> > > > > > >
> > > > > >
> > > > > > --
> > > > > > With best wishes
> > > > > > Dmitry
> > > > >
> > > >
> > > > --
> > > > With best wishes
> > > > Dmitry
> > >
> >
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology
2025-01-10 2:10 ` Dmitry Baryshkov
@ 2025-01-10 22:08 ` Jessica Zhang
0 siblings, 0 replies; 77+ messages in thread
From: Jessica Zhang @ 2025-01-10 22:08 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/9/2025 6:10 PM, Dmitry Baryshkov wrote:
> On Thu, Jan 09, 2025 at 05:50:16PM -0800, Jessica Zhang wrote:
>>
>>
>> On 1/9/2025 5:42 PM, Dmitry Baryshkov wrote:
>>> On Fri, 10 Jan 2025 at 02:30, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 1/9/2025 4:00 PM, Dmitry Baryshkov wrote:
>>>>> On Thu, Jan 09, 2025 at 02:34:44PM -0800, Jessica Zhang wrote:
>>>>>>
>>>>>>
>>>>>> On 1/3/2025 10:16 AM, Dmitry Baryshkov wrote:
>>>>>>> On Fri, Jan 03, 2025 at 10:03:35AM -0800, Jessica Zhang wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On 12/19/2024 9:03 PM, Dmitry Baryshkov wrote:
>>>>>>>>> On Mon, Dec 16, 2024 at 04:43:26PM -0800, Jessica Zhang wrote:
>>>>>>>>>> Add the cwb_enabled flag to msm_display topology and adjust the toplogy
>>>>>>>>>> to account for concurrent writeback
>>>>>>>>>
>>>>>>>>> Why?
>>>>>>>>
>>>>>>>> Hi Dmitry,
>>>>>>>>
>>>>>>>> This flag is necessary to specify that CWB mux(es) need to be assigned for
>>>>>>>> the given reqeusted topology.
>>>>>>>
>>>>>>> Why is necessary? Please rephrase your statement (we need foo bar, so do
>>>>>>> baz).
>>>>>>
>>>>>> Ack, what do you think of rephrasing the commit msg to this:
>>>>>>
>>>>>> ```
>>>>>> Add support for adjusting topology based on if concurrent writeback is
>>>>>> enabled.
>>>>>>
>>>>>> Currently, the topology is calculated based on the assumption that the user
>>>>>> cannot request real-time and writeback simultaneously. For example, the
>>>>>> number of LMs and CTLs are currently based off the number of phys encoders
>>>>>> under the assumption there will be at least 1 LM/CTL per phys encoder.
>>>>>>
>>>>>> This will not hold true for concurrent writeback as 2 phys encoders (1
>>>>>> real-time and 1 writeback) can be driven by 1 LM/CTL when concurrent
>>>>>> writeback is enabled.
>>>>>>
>>>>>> To account for this, add a cwb_enabled flag and only adjust the number of
>>>>>> CTL/LMs needed by a given topology based on the number of phys encoders only
>>>>>> if CWB is not enabled.
>>>>>>
>>>>>> ```
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>>>>>> ---
>>>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 11 ++++++++++-
>>>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 10 ++++++++--
>>>>>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 2 ++
>>>>>>>>>> 3 files changed, 20 insertions(+), 3 deletions(-)
>>>>>>>>>>
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>>>> index b4bfded3d53025853cee112ca598533ece290318..b063c8fe4c0594772d84401fa56c9c21afc0ad18 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>>>>>>>>>> @@ -1198,6 +1198,8 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>>>>>> dpu_encoder_update_topology(drm_enc, &topology, crtc_state->state,
>>>>>>>>>> &crtc_state->adjusted_mode);
>>>>>>>>>> + topology.cwb_enabled = drm_crtc_in_clone_mode(crtc_state);
>>>>>>>>>> +
>>>>>>>>>> /*
>>>>>>>>>> * Datapath topology selection
>>>>>>>>>> *
>>>>>>>>>> @@ -1209,9 +1211,16 @@ static struct msm_display_topology dpu_crtc_get_topology(
>>>>>>>>>> * 2 LM, 1 INTF (stream merge to support high resolution interfaces)
>>>>>>>>>> *
>>>>>>>>>> * Add dspps to the reservation requirements if ctm is requested
>>>>>>>>>> + *
>>>>>>>>>> + * Only hardcode num_lm to 2 for cases where num_intf == 2 and CWB is not
>>>>>>>>>> + * enabled. This is because in cases where CWB is enabled, num_intf will
>>>>>>>>>> + * count both the WB and real-time phys encoders.
>>>>>>>>>> + *
>>>>>>>>>> + * For non-DSC CWB usecases, have the num_lm be decided by the
>>>>>>>>>> + * (mode->hdisplay > MAX_HDISPLAY_SPLIT) check.
>>>>>>>>>> */
>>>>>>>>>> - if (topology.num_intf == 2)
>>>>>>>>>> + if (topology.num_intf == 2 && !topology.cwb_enabled)
>>>>>>>>>> topology.num_lm = 2;
>>>>>>>>>> else if (topology.num_dsc == 2)
>>>>>>>>>> topology.num_lm = 2;
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>>>> index b763ef19f4c60ae8a35df6a6ffb19e8411bc63f8..85adaf256b2c705d2d7df378b6ffc0e578f52bc3 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>>>>>> @@ -382,8 +382,14 @@ static int _dpu_rm_reserve_ctls(
>>>>>>>>>> int i = 0, j, num_ctls;
>>>>>>>>>> bool needs_split_display;
>>>>>>>>>> - /* each hw_intf needs its own hw_ctrl to program its control path */
>>>>>>>>>> - num_ctls = top->num_intf;
>>>>>>>>>> + /*
>>>>>>>>>> + * For non-CWB mode, each hw_intf needs its own hw_ctl to program its
>>>>>>>>>> + * control path. Hardcode num_ctls to 1 if CWB is enabled
>>>>>>>>>> + */
>>>>>>>>>
>>>>>>>>> Why?
>>>>>>>>
>>>>>>>> This is because num_intf is based on the number of phys_encs. Since in the
>>>>>>>> CWB case, the WB and real-time encoders will be driven by the same CTL. I
>>>>>>>> can add this to the comment doc.
>>>>>>>
>>>>>>> Why are they driven by the same CTL? Is it also the case for platforms
>>>>>>> before DPU 5.x?
>>>>>>
>>>>>> This is because the WB and real-time path for a given topology would be
>>>>>> driven by the same data path so the same CTL should enable the real-time and
>>>>>> WB active bits.
>>>>>>
>>>>>> This is the same for pre-DPU 5.x.
>>>>>
>>>>> But pre-5.x platforms didn't have ACTIVE_CTL, so they should be using
>>>>> separte CTL for each of the physical encoders.
>>>>
>>>> For pre-DPU 5.x, enabling CWB would mean configuring the registers under
>>>> both the WB and MODE_SEL_* cases here [1]
>>>
>>> But do we still have to use a single CTL or would we use two different
>>> CTLs, one for the main output and one for WB?
>>
>> We would have to enable both WB and the real-time output on the same CTL
>
> Thanks for the confirmation. Then the text your wrote above should be
> mostly okay. Please drop the first ("Add support...") sentence and s/can
> be driven by/must be driven by/ .
Ack, sounds good
>
>>
>>>
>>>>
>>>> [1]
>>>> https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c#L588
>>>>
>>>>>
>>>>>>
>>>>>>>
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>>
>>>>>>>> Jessica Zhang
>>>>>>>>
>>>>>>>>>
>>>>>>>>>> + if (top->cwb_enabled)
>>>>>>>>>> + num_ctls = 1;
>>>>>>>>>> + else
>>>>>>>>>> + num_ctls = top->num_intf;
>>>>>>>>>> needs_split_display = _dpu_rm_needs_split_display(top);
>>>>>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>>>> index b061dfdab52e04ab7d777e912a30173273cb3db7..12db21a2403ec6930894c36a58e898c5d94c2568 100644
>>>>>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>>>>>>> @@ -46,6 +46,7 @@ struct dpu_rm {
>>>>>>>>>> * @num_dspp: number of dspp blocks used
>>>>>>>>>> * @num_dsc: number of Display Stream Compression (DSC) blocks used
>>>>>>>>>> * @needs_cdm: indicates whether cdm block is needed for this display topology
>>>>>>>>>> + * @cwb_enabled: indicates whether CWB is enabled for this display topology
>>>>>>>>>> */
>>>>>>>>>> struct msm_display_topology {
>>>>>>>>>> u32 num_lm;
>>>>>>>>>> @@ -53,6 +54,7 @@ struct msm_display_topology {
>>>>>>>>>> u32 num_dspp;
>>>>>>>>>> u32 num_dsc;
>>>>>>>>>> bool needs_cdm;
>>>>>>>>>> + bool cwb_enabled;
>>>>>>>>>> };
>>>>>>>>>> int dpu_rm_init(struct drm_device *dev,
>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> 2.34.1
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> With best wishes
>>>>>>>>> Dmitry
>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> With best wishes
>>>>>>> Dmitry
>>>>>>
>>>>>
>>>>> --
>>>>> With best wishes
>>>>> Dmitry
>>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2024-12-24 20:00 ` Dmitry Baryshkov
@ 2025-01-15 5:28 ` Jessica Zhang
2025-01-15 9:56 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-15 5:28 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 12/24/2024 12:00 PM, Dmitry Baryshkov wrote:
> On Tue, Dec 24, 2024 at 06:45:07AM +0200, Dmitry Baryshkov wrote:
>> On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
>>> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>
>>> Up to now the driver has been using encoder to allocate hardware
>>> resources. Switch it to use CRTC id in preparation for the next step.
>>>
>>> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>> ---
>>> Changes in v4 (due to rebase):
>>>
>>> - moved *_get_assigned_resources() changes for DSPP and LM from
>>> encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
>>> ---
>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
>>> 4 files changed, 110 insertions(+), 118 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>> @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
>>> 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));
>>> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>
>> And this crashes because drm_enc->crtc isn't set yet. Was this commit
>> tested? Or was it only tested as a part of the patchset, after this code
>> has been rewritten by the subsequent patches? I will replace this with
>> crtc_state->crtc, but generatlly this looks bad.
>
> Even with this in place, it fails the kms_color@ctm-max for pipe-B-eDP-1
> on SC7180 (pipe-A-eDP-1 succeeds). See job log at [1].
>
> corresponding excerpt from the log:
>
> [IGT] kms_color: starting dynamic subtest pipe-B-eDP-1
> [drm:_dpu_rm_check_lm_and_get_connected_blks] [dpu error]failed to get dspp on lm 0
> [drm:_dpu_rm_make_reservation] [dpu error]unable to find appropriate mixers
> [drm:dpu_rm_reserve] [dpu error]failed to reserve hw resources: -119
> [IGT] kms_color: finished subtest pipe-B-eDP-1, FAIL
>
> FWIW it looks like during an attempt to use second CRTC the driver
> doesn't release resources for the first one. I'll drop this patch for
> now, leaving just HW_CWB patches in.
>
> [1] https://gitlab.freedesktop.org/drm/msm/-/jobs/68614460/viewer
Hi Dmitry,
Thanks for catching this -- it seems like the issue is because a
disabling commit will not call into the encoder atomic check.
During the disabling commit at the end of the IGT test [2], the
connector is detached from the crtc it was testing on. Because of this,
we end up skipping over any connector that doesn't have the best_encoder
or crtc set [1] within mode_fixup().
So we'll never release the dspp block from the pipe-A/crtc-0 subtest,
which will cause the "failed to reserve hw resources" error for
pipe-b/crtc-1.
Overall, I think the issue stems from the fact that we're trying to
update a crtc-based component within an encoder-specific callback. Maybe
the right call here would be to squash this commit with "drm/msm/dpu:
move resource allocation to CRTC".
What do you think?
Thanks,
Jessica Zhang
[1]
https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/drm_atomic_helper.c#L441
[2]
https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tests/kms_color.c#L603
>
>>
>>> 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));
>>> + drm_enc->crtc, 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,
>>> + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
>>
>>
>>> ARRAY_SIZE(hw_dspp));
>>>
>>> for (i = 0; i < num_lm; i++) {
>>> @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
>>> * Dont allocate when active is false.
>>> */
>>> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
>>> - dpu_rm_release(global_state, drm_enc);
>>> + dpu_rm_release(global_state, crtc_state->crtc);
>>>
>>> if (!crtc_state->active_changed || crtc_state->enable)
>>> ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>>> - drm_enc, crtc_state, &topology);
>>> + crtc_state->crtc, &topology);
>>> if (!ret)
>>> dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
>>> global_state, crtc_state);
>>> @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>
>>> /* Query resource that have been reserved in atomic check step. */
>>> num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>> - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
>>> + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>>> 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));
>>> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>
>>> for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
>>> dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
>>> : NULL;
>>>
>>> num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>> - drm_enc->base.id, DPU_HW_BLK_DSC,
>>> + drm_enc->crtc, DPU_HW_BLK_DSC,
>>> hw_dsc, ARRAY_SIZE(hw_dsc));
>>> for (i = 0; i < num_dsc; i++) {
>>> dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
>>> @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>> struct dpu_hw_blk *hw_cdm = NULL;
>>>
>>> dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>> - drm_enc->base.id, DPU_HW_BLK_CDM,
>>> + drm_enc->crtc, DPU_HW_BLK_CDM,
>>> &hw_cdm, 1);
>>> dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
>>> }
>>> @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
>>> global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
>>>
>>> num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
>>> - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>>> + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>>>
>>> for (i = 0; i < num_lm; i++) {
>>> hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>> @@ -122,12 +122,12 @@ struct dpu_global_state {
>>>
>>> struct dpu_rm *rm;
>>>
>>> - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
>>> - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
>>> - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>>> - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>>> - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>>> - uint32_t cdm_to_enc_id;
>>> + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
>>> + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
>>> + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
>>> + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>> + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>> + uint32_t cdm_to_crtc_id;
>>> };
>>>
>>> struct dpu_global_state
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>> @@ -22,9 +22,9 @@
>>>
>>>
>>> static inline bool reserved_by_other(uint32_t *res_map, int idx,
>>> - uint32_t enc_id)
>>> + uint32_t crtc_id)
>>> {
>>> - return res_map[idx] && res_map[idx] != enc_id;
>>> + return res_map[idx] && res_map[idx] != crtc_id;
>>> }
>>>
>>> /**
>>> @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>> * pingpong
>>> * @rm: dpu resource manager handle
>>> * @global_state: resources shared across multiple kms objects
>>> - * @enc_id: encoder id requesting for allocation
>>> + * @crtc_id: crtc id requesting for allocation
>>> * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
>>> * if lm, and all other hardwired blocks connected to the lm (pp) is
>>> * available and appropriate
>>> @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>> */
>>> static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>> + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>> struct msm_display_topology *topology)
>>> {
>>> const struct dpu_lm_cfg *lm_cfg;
>>> int idx;
>>>
>>> /* Already reserved? */
>>> - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
>>> + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
>>> DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
>>> return false;
>>> }
>>> @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>> return false;
>>> }
>>>
>>> - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
>>> + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
>>> DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
>>> lm_cfg->pingpong);
>>> return false;
>>> @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>> return false;
>>> }
>>>
>>> - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
>>> + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
>>> DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
>>> lm_cfg->dspp);
>>> return false;
>>> @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>
>>> static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - uint32_t enc_id,
>>> + uint32_t crtc_id,
>>> struct msm_display_topology *topology)
>>>
>>> {
>>> @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>> lm_idx[lm_count] = i;
>>>
>>> if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
>>> - enc_id, i, &pp_idx[lm_count],
>>> + crtc_id, i, &pp_idx[lm_count],
>>> &dspp_idx[lm_count], topology)) {
>>> continue;
>>> }
>>> @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>> continue;
>>>
>>> if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
>>> - global_state, enc_id, j,
>>> + global_state, crtc_id, j,
>>> &pp_idx[lm_count], &dspp_idx[lm_count],
>>> topology)) {
>>> continue;
>>> @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>> }
>>>
>>> for (i = 0; i < lm_count; i++) {
>>> - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
>>> - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
>>> - global_state->dspp_to_enc_id[dspp_idx[i]] =
>>> - topology->num_dspp ? enc_id : 0;
>>> + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
>>> + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
>>> + global_state->dspp_to_crtc_id[dspp_idx[i]] =
>>> + topology->num_dspp ? crtc_id : 0;
>>>
>>> - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
>>> + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
>>> pp_idx[i] + PINGPONG_0);
>>> }
>>>
>>> @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>> static int _dpu_rm_reserve_ctls(
>>> struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - uint32_t enc_id,
>>> + uint32_t crtc_id,
>>> const struct msm_display_topology *top)
>>> {
>>> int ctl_idx[MAX_BLOCKS];
>>> @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
>>>
>>> if (!rm->ctl_blks[j])
>>> continue;
>>> - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
>>> + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
>>> continue;
>>>
>>> ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
>>> @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
>>> return -ENAVAIL;
>>>
>>> for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
>>> - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
>>> - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
>>> + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
>>> + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
>>> }
>>>
>>> return 0;
>>> @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
>>>
>>> static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
>>> int start,
>>> - uint32_t enc_id)
>>> + uint32_t crtc_id)
>>> {
>>> int i;
>>>
>>> for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
>>> - if (global_state->pingpong_to_enc_id[i] == enc_id)
>>> + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
>>> return i;
>>> }
>>>
>>> @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
>>>
>>> static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - uint32_t enc_id,
>>> + uint32_t crtc_id,
>>> const struct msm_display_topology *top)
>>> {
>>> int num_dsc = 0;
>>> @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>> if (!rm->dsc_blks[dsc_idx])
>>> continue;
>>>
>>> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
>>> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
>>> continue;
>>>
>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
>>> if (pp_idx < 0)
>>> return -ENAVAIL;
>>>
>>> @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>> if (ret)
>>> return -ENAVAIL;
>>>
>>> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
>>> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
>>> num_dsc++;
>>> pp_idx++;
>>> }
>>> @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>>
>>> static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - uint32_t enc_id,
>>> + uint32_t crtc_id,
>>> const struct msm_display_topology *top)
>>> {
>>> int num_dsc = 0;
>>> @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>> continue;
>>>
>>> /* consective dsc index to be paired */
>>> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
>>> - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
>>> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
>>> + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
>>> continue;
>>>
>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
>>> if (pp_idx < 0)
>>> return -ENAVAIL;
>>>
>>> @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>> continue;
>>> }
>>>
>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
>>> if (pp_idx < 0)
>>> return -ENAVAIL;
>>>
>>> @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>> continue;
>>> }
>>>
>>> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
>>> - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
>>> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
>>> + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
>>> num_dsc += 2;
>>> pp_idx++; /* start for next pair */
>>> }
>>> @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>
>>> static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc,
>>> + uint32_t crtc_id,
>>> const struct msm_display_topology *top)
>>> {
>>> - uint32_t enc_id = enc->base.id;
>>> -
>>> if (!top->num_dsc || !top->num_intf)
>>> return 0;
>>>
>>> @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>>
>>> /* num_dsc should be either 1, 2 or 4 */
>>> if (top->num_dsc > top->num_intf) /* merge mode */
>>> - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
>>> + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
>>> else
>>> - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
>>> + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
>>>
>>> return 0;
>>> }
>>>
>>> static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc)
>>> + uint32_t crtc_id)
>>> {
>>> /* try allocating only one CDM block */
>>> if (!rm->cdm_blk) {
>>> @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>> return -EIO;
>>> }
>>>
>>> - if (global_state->cdm_to_enc_id) {
>>> + if (global_state->cdm_to_crtc_id) {
>>> DPU_ERROR("CDM_0 is already allocated\n");
>>> return -EIO;
>>> }
>>>
>>> - global_state->cdm_to_enc_id = enc->base.id;
>>> + global_state->cdm_to_crtc_id = crtc_id;
>>>
>>> return 0;
>>> }
>>> @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>> static int _dpu_rm_make_reservation(
>>> struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc,
>>> + uint32_t crtc_id,
>>> struct msm_display_topology *topology)
>>> {
>>> int ret;
>>>
>>> - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
>>> + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
>>> if (ret) {
>>> DPU_ERROR("unable to find appropriate mixers\n");
>>> return ret;
>>> }
>>>
>>> - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
>>> +
>>> + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>>> topology);
>>> if (ret) {
>>> DPU_ERROR("unable to find appropriate CTL\n");
>>> return ret;
>>> }
>>>
>>> - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
>>> + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
>>> if (ret)
>>> return ret;
>>>
>>> if (topology->needs_cdm) {
>>> - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
>>> + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
>>> if (ret) {
>>> DPU_ERROR("unable to find CDM blk\n");
>>> return ret;
>>> @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
>>> }
>>>
>>> static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>> - uint32_t enc_id)
>>> + uint32_t crtc_id)
>>> {
>>> int i;
>>>
>>> for (i = 0; i < cnt; i++) {
>>> - if (res_mapping[i] == enc_id)
>>> + if (res_mapping[i] == crtc_id)
>>> res_mapping[i] = 0;
>>> }
>>> }
>>> @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>> * dpu_rm_release - Given the encoder for the display chain, release any
>>> * HW blocks previously reserved for that use case.
>>> * @global_state: resources shared across multiple kms objects
>>> - * @enc: DRM Encoder handle
>>> + * @crtc: DRM CRTC handle
>>> * @return: 0 on Success otherwise -ERROR
>>> */
>>> void dpu_rm_release(struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc)
>>> + struct drm_crtc *crtc)
>>> {
>>> - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
>>> - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
>>> - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
>>> - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
>>> - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
>>> - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
>>> - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
>>> - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>>> - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>>> - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
>>> - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>>> + uint32_t crtc_id = crtc->base.id;
>>> +
>>> + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
>>> + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
>>> + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
>>> + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
>>> + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
>>> + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
>>> + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
>>> + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
>>> + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
>>> + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
>>> + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
>>> }
>>>
>>> /**
>>> @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>>> * HW Reservations should be released via dpu_rm_release_hw.
>>> * @rm: DPU Resource Manager handle
>>> * @global_state: resources shared across multiple kms objects
>>> - * @enc: DRM Encoder handle
>>> - * @crtc_state: Proposed Atomic DRM CRTC State handle
>>> + * @crtc: DRM CRTC handle
>>> * @topology: Pointer to topology info for the display
>>> * @return: 0 on Success otherwise -ERROR
>>> */
>>> int dpu_rm_reserve(
>>> struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc,
>>> - struct drm_crtc_state *crtc_state,
>>> + struct drm_crtc *crtc,
>>> struct msm_display_topology *topology)
>>> {
>>> int ret;
>>>
>>> - /* Check if this is just a page-flip */
>>> - if (!drm_atomic_crtc_needs_modeset(crtc_state))
>>> - return 0;
>>> -
>>> if (IS_ERR(global_state)) {
>>> DPU_ERROR("failed to global state\n");
>>> return PTR_ERR(global_state);
>>> }
>>>
>>> - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>> - enc->base.id, crtc_state->crtc->base.id);
>>> + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
>>>
>>> DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>> topology->num_lm, topology->num_dsc,
>>> topology->num_intf);
>>>
>>> - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
>>> + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
>>> if (ret)
>>> DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>>>
>>> -
>>> -
>>> return ret;
>>> }
>>>
>>> @@ -705,48 +697,49 @@ int dpu_rm_reserve(
>>> * assigned to this encoder
>>> * @rm: DPU Resource Manager handle
>>> * @global_state: resources shared across multiple kms objects
>>> - * @enc_id: encoder id requesting for allocation
>>> + * @crtc: DRM CRTC handle
>>> * @type: resource type to return data for
>>> * @blks: pointer to the array to be filled by HW resources
>>> * @blks_size: size of the @blks array
>>> */
>>> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>> - struct dpu_global_state *global_state, uint32_t enc_id,
>>> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
>>> {
>>> + uint32_t crtc_id = crtc->base.id;
>>> struct dpu_hw_blk **hw_blks;
>>> - uint32_t *hw_to_enc_id;
>>> + uint32_t *hw_to_crtc_id;
>>> int i, num_blks, max_blks;
>>>
>>> switch (type) {
>>> case DPU_HW_BLK_PINGPONG:
>>> hw_blks = rm->pingpong_blks;
>>> - hw_to_enc_id = global_state->pingpong_to_enc_id;
>>> + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
>>> max_blks = ARRAY_SIZE(rm->pingpong_blks);
>>> break;
>>> case DPU_HW_BLK_LM:
>>> hw_blks = rm->mixer_blks;
>>> - hw_to_enc_id = global_state->mixer_to_enc_id;
>>> + hw_to_crtc_id = global_state->mixer_to_crtc_id;
>>> max_blks = ARRAY_SIZE(rm->mixer_blks);
>>> break;
>>> case DPU_HW_BLK_CTL:
>>> hw_blks = rm->ctl_blks;
>>> - hw_to_enc_id = global_state->ctl_to_enc_id;
>>> + hw_to_crtc_id = global_state->ctl_to_crtc_id;
>>> max_blks = ARRAY_SIZE(rm->ctl_blks);
>>> break;
>>> case DPU_HW_BLK_DSPP:
>>> hw_blks = rm->dspp_blks;
>>> - hw_to_enc_id = global_state->dspp_to_enc_id;
>>> + hw_to_crtc_id = global_state->dspp_to_crtc_id;
>>> max_blks = ARRAY_SIZE(rm->dspp_blks);
>>> break;
>>> case DPU_HW_BLK_DSC:
>>> hw_blks = rm->dsc_blks;
>>> - hw_to_enc_id = global_state->dsc_to_enc_id;
>>> + hw_to_crtc_id = global_state->dsc_to_crtc_id;
>>> max_blks = ARRAY_SIZE(rm->dsc_blks);
>>> break;
>>> case DPU_HW_BLK_CDM:
>>> hw_blks = &rm->cdm_blk;
>>> - hw_to_enc_id = &global_state->cdm_to_enc_id;
>>> + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
>>> max_blks = 1;
>>> break;
>>> default:
>>> @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>
>>> num_blks = 0;
>>> for (i = 0; i < max_blks; i++) {
>>> - if (hw_to_enc_id[i] != enc_id)
>>> + if (hw_to_crtc_id[i] != crtc_id)
>>> continue;
>>>
>>> if (num_blks == blks_size) {
>>> - DPU_ERROR("More than %d resources assigned to enc %d\n",
>>> - blks_size, enc_id);
>>> + DPU_ERROR("More than %d resources assigned to crtc %d\n",
>>> + blks_size, crtc_id);
>>> break;
>>> }
>>> if (!hw_blks[i]) {
>>> - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
>>> - type, enc_id);
>>> + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
>>> + type, crtc_id);
>>> break;
>>> }
>>> blks[num_blks++] = hw_blks[i];
>>> @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
>>>
>>> drm_puts(p, "resource mapping:\n");
>>> drm_puts(p, "\tpingpong=");
>>> - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
>>> + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
>>> dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
>>> - global_state->pingpong_to_enc_id[i]);
>>> + global_state->pingpong_to_crtc_id[i]);
>>> drm_puts(p, "\n");
>>>
>>> drm_puts(p, "\tmixer=");
>>> - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
>>> + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
>>> dpu_rm_print_state_helper(p, rm->mixer_blks[i],
>>> - global_state->mixer_to_enc_id[i]);
>>> + global_state->mixer_to_crtc_id[i]);
>>> drm_puts(p, "\n");
>>>
>>> drm_puts(p, "\tctl=");
>>> - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
>>> + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
>>> dpu_rm_print_state_helper(p, rm->ctl_blks[i],
>>> - global_state->ctl_to_enc_id[i]);
>>> + global_state->ctl_to_crtc_id[i]);
>>> drm_puts(p, "\n");
>>>
>>> drm_puts(p, "\tdspp=");
>>> - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
>>> + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
>>> dpu_rm_print_state_helper(p, rm->dspp_blks[i],
>>> - global_state->dspp_to_enc_id[i]);
>>> + global_state->dspp_to_crtc_id[i]);
>>> drm_puts(p, "\n");
>>>
>>> drm_puts(p, "\tdsc=");
>>> - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
>>> + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
>>> dpu_rm_print_state_helper(p, rm->dsc_blks[i],
>>> - global_state->dsc_to_enc_id[i]);
>>> + global_state->dsc_to_crtc_id[i]);
>>> drm_puts(p, "\n");
>>>
>>> drm_puts(p, "\tcdm=");
>>> dpu_rm_print_state_helper(p, rm->cdm_blk,
>>> - global_state->cdm_to_enc_id);
>>> + global_state->cdm_to_crtc_id);
>>> drm_puts(p, "\n");
>>> }
>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>> @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
>>>
>>> int dpu_rm_reserve(struct dpu_rm *rm,
>>> struct dpu_global_state *global_state,
>>> - struct drm_encoder *drm_enc,
>>> - struct drm_crtc_state *crtc_state,
>>> + struct drm_crtc *crtc,
>>> struct msm_display_topology *topology);
>>>
>>> void dpu_rm_release(struct dpu_global_state *global_state,
>>> - struct drm_encoder *enc);
>>> + struct drm_crtc *crtc);
>>>
>>> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>> - struct dpu_global_state *global_state, uint32_t enc_id,
>>> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
>>>
>>> void dpu_rm_print_state(struct drm_printer *p,
>>>
>>> --
>>> 2.34.1
>>>
>>
>> --
>> With best wishes
>> Dmitry
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2025-01-15 5:28 ` Jessica Zhang
@ 2025-01-15 9:56 ` Dmitry Baryshkov
2025-01-16 4:13 ` Jessica Zhang
0 siblings, 1 reply; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-15 9:56 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Tue, Jan 14, 2025 at 09:28:50PM -0800, Jessica Zhang wrote:
>
>
> On 12/24/2024 12:00 PM, Dmitry Baryshkov wrote:
> > On Tue, Dec 24, 2024 at 06:45:07AM +0200, Dmitry Baryshkov wrote:
> > > On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
> > > > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > >
> > > > Up to now the driver has been using encoder to allocate hardware
> > > > resources. Switch it to use CRTC id in preparation for the next step.
> > > >
> > > > Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > ---
> > > > Changes in v4 (due to rebase):
> > > >
> > > > - moved *_get_assigned_resources() changes for DSPP and LM from
> > > > encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
> > > > ---
> > > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
> > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
> > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
> > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
> > > > 4 files changed, 110 insertions(+), 118 deletions(-)
> > > >
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
> > > > 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));
> > > > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > >
> > > And this crashes because drm_enc->crtc isn't set yet. Was this commit
> > > tested? Or was it only tested as a part of the patchset, after this code
> > > has been rewritten by the subsequent patches? I will replace this with
> > > crtc_state->crtc, but generatlly this looks bad.
> >
> > Even with this in place, it fails the kms_color@ctm-max for pipe-B-eDP-1
> > on SC7180 (pipe-A-eDP-1 succeeds). See job log at [1].
> >
> > corresponding excerpt from the log:
> >
> > [IGT] kms_color: starting dynamic subtest pipe-B-eDP-1
> > [drm:_dpu_rm_check_lm_and_get_connected_blks] [dpu error]failed to get dspp on lm 0
> > [drm:_dpu_rm_make_reservation] [dpu error]unable to find appropriate mixers
> > [drm:dpu_rm_reserve] [dpu error]failed to reserve hw resources: -119
> > [IGT] kms_color: finished subtest pipe-B-eDP-1, FAIL
> >
> > FWIW it looks like during an attempt to use second CRTC the driver
> > doesn't release resources for the first one. I'll drop this patch for
> > now, leaving just HW_CWB patches in.
> >
> > [1] https://gitlab.freedesktop.org/drm/msm/-/jobs/68614460/viewer
>
> Hi Dmitry,
>
> Thanks for catching this -- it seems like the issue is because a disabling
> commit will not call into the encoder atomic check.
>
> During the disabling commit at the end of the IGT test [2], the connector is
> detached from the crtc it was testing on. Because of this, we end up
> skipping over any connector that doesn't have the best_encoder or crtc set
> [1] within mode_fixup().
>
> So we'll never release the dspp block from the pipe-A/crtc-0 subtest, which
> will cause the "failed to reserve hw resources" error for pipe-b/crtc-1.
And currently the test works because the encoder isn't changed, so all
resources are kept from the previous run, even though the routing has
changed from CRTC 0 to 1. Fun.
> Overall, I think the issue stems from the fact that we're trying to update a
> crtc-based component within an encoder-specific callback. Maybe the right
> call here would be to squash this commit with "drm/msm/dpu: move resource
> allocation to CRTC".
I'd rather not. Those two changes are big enough and independent. Can
you change the order of those two commits instead?
>
> What do you think?
>
> Thanks,
>
> Jessica Zhang
>
> [1] https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/drm_atomic_helper.c#L441
> [2] https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tests/kms_color.c#L603
>
> >
> > >
> > > > 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));
> > > > + drm_enc->crtc, 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,
> > > > + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> > >
> > >
> > > > ARRAY_SIZE(hw_dspp));
> > > > for (i = 0; i < num_lm; i++) {
> > > > @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
> > > > * Dont allocate when active is false.
> > > > */
> > > > if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> > > > - dpu_rm_release(global_state, drm_enc);
> > > > + dpu_rm_release(global_state, crtc_state->crtc);
> > > > if (!crtc_state->active_changed || crtc_state->enable)
> > > > ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> > > > - drm_enc, crtc_state, &topology);
> > > > + crtc_state->crtc, &topology);
> > > > if (!ret)
> > > > dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> > > > global_state, crtc_state);
> > > > @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > /* Query resource that have been reserved in atomic check step. */
> > > > num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > 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));
> > > > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > > for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > > > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > > > : NULL;
> > > > num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > - drm_enc->base.id, DPU_HW_BLK_DSC,
> > > > + drm_enc->crtc, DPU_HW_BLK_DSC,
> > > > hw_dsc, ARRAY_SIZE(hw_dsc));
> > > > for (i = 0; i < num_dsc; i++) {
> > > > dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
> > > > @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > struct dpu_hw_blk *hw_cdm = NULL;
> > > > dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > - drm_enc->base.id, DPU_HW_BLK_CDM,
> > > > + drm_enc->crtc, DPU_HW_BLK_CDM,
> > > > &hw_cdm, 1);
> > > > dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> > > > }
> > > > @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> > > > global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
> > > > num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
> > > > - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > > > + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > > > for (i = 0; i < num_lm; i++) {
> > > > hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > @@ -122,12 +122,12 @@ struct dpu_global_state {
> > > > struct dpu_rm *rm;
> > > > - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> > > > - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> > > > - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> > > > - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> > > > - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> > > > - uint32_t cdm_to_enc_id;
> > > > + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
> > > > + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
> > > > + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
> > > > + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > > > + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > > > + uint32_t cdm_to_crtc_id;
> > > > };
> > > > struct dpu_global_state
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > @@ -22,9 +22,9 @@
> > > > static inline bool reserved_by_other(uint32_t *res_map, int idx,
> > > > - uint32_t enc_id)
> > > > + uint32_t crtc_id)
> > > > {
> > > > - return res_map[idx] && res_map[idx] != enc_id;
> > > > + return res_map[idx] && res_map[idx] != crtc_id;
> > > > }
> > > > /**
> > > > @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > * pingpong
> > > > * @rm: dpu resource manager handle
> > > > * @global_state: resources shared across multiple kms objects
> > > > - * @enc_id: encoder id requesting for allocation
> > > > + * @crtc_id: crtc id requesting for allocation
> > > > * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
> > > > * if lm, and all other hardwired blocks connected to the lm (pp) is
> > > > * available and appropriate
> > > > @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > */
> > > > static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > > > + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > > > struct msm_display_topology *topology)
> > > > {
> > > > const struct dpu_lm_cfg *lm_cfg;
> > > > int idx;
> > > > /* Already reserved? */
> > > > - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
> > > > + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
> > > > DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
> > > > return false;
> > > > }
> > > > @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > return false;
> > > > }
> > > > - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
> > > > + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
> > > > DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
> > > > lm_cfg->pingpong);
> > > > return false;
> > > > @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > return false;
> > > > }
> > > > - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
> > > > + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
> > > > DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
> > > > lm_cfg->dspp);
> > > > return false;
> > > > @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - uint32_t enc_id,
> > > > + uint32_t crtc_id,
> > > > struct msm_display_topology *topology)
> > > > {
> > > > @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > lm_idx[lm_count] = i;
> > > > if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> > > > - enc_id, i, &pp_idx[lm_count],
> > > > + crtc_id, i, &pp_idx[lm_count],
> > > > &dspp_idx[lm_count], topology)) {
> > > > continue;
> > > > }
> > > > @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > continue;
> > > > if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> > > > - global_state, enc_id, j,
> > > > + global_state, crtc_id, j,
> > > > &pp_idx[lm_count], &dspp_idx[lm_count],
> > > > topology)) {
> > > > continue;
> > > > @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > }
> > > > for (i = 0; i < lm_count; i++) {
> > > > - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> > > > - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> > > > - global_state->dspp_to_enc_id[dspp_idx[i]] =
> > > > - topology->num_dspp ? enc_id : 0;
> > > > + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
> > > > + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
> > > > + global_state->dspp_to_crtc_id[dspp_idx[i]] =
> > > > + topology->num_dspp ? crtc_id : 0;
> > > > - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> > > > + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
> > > > pp_idx[i] + PINGPONG_0);
> > > > }
> > > > @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > static int _dpu_rm_reserve_ctls(
> > > > struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - uint32_t enc_id,
> > > > + uint32_t crtc_id,
> > > > const struct msm_display_topology *top)
> > > > {
> > > > int ctl_idx[MAX_BLOCKS];
> > > > @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
> > > > if (!rm->ctl_blks[j])
> > > > continue;
> > > > - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
> > > > + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
> > > > continue;
> > > > ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
> > > > @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
> > > > return -ENAVAIL;
> > > > for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
> > > > - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
> > > > - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
> > > > + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
> > > > + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
> > > > }
> > > > return 0;
> > > > @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
> > > > static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
> > > > int start,
> > > > - uint32_t enc_id)
> > > > + uint32_t crtc_id)
> > > > {
> > > > int i;
> > > > for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
> > > > - if (global_state->pingpong_to_enc_id[i] == enc_id)
> > > > + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
> > > > return i;
> > > > }
> > > > @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
> > > > static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - uint32_t enc_id,
> > > > + uint32_t crtc_id,
> > > > const struct msm_display_topology *top)
> > > > {
> > > > int num_dsc = 0;
> > > > @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > if (!rm->dsc_blks[dsc_idx])
> > > > continue;
> > > > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
> > > > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
> > > > continue;
> > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > > > if (pp_idx < 0)
> > > > return -ENAVAIL;
> > > > @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > if (ret)
> > > > return -ENAVAIL;
> > > > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > > > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > > > num_dsc++;
> > > > pp_idx++;
> > > > }
> > > > @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - uint32_t enc_id,
> > > > + uint32_t crtc_id,
> > > > const struct msm_display_topology *top)
> > > > {
> > > > int num_dsc = 0;
> > > > @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > continue;
> > > > /* consective dsc index to be paired */
> > > > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
> > > > - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
> > > > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
> > > > + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
> > > > continue;
> > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > > > if (pp_idx < 0)
> > > > return -ENAVAIL;
> > > > @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > continue;
> > > > }
> > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
> > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
> > > > if (pp_idx < 0)
> > > > return -ENAVAIL;
> > > > @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > continue;
> > > > }
> > > > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > > > - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
> > > > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > > > + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
> > > > num_dsc += 2;
> > > > pp_idx++; /* start for next pair */
> > > > }
> > > > @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc,
> > > > + uint32_t crtc_id,
> > > > const struct msm_display_topology *top)
> > > > {
> > > > - uint32_t enc_id = enc->base.id;
> > > > -
> > > > if (!top->num_dsc || !top->num_intf)
> > > > return 0;
> > > > @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> > > > /* num_dsc should be either 1, 2 or 4 */
> > > > if (top->num_dsc > top->num_intf) /* merge mode */
> > > > - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
> > > > + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
> > > > else
> > > > - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
> > > > + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
> > > > return 0;
> > > > }
> > > > static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc)
> > > > + uint32_t crtc_id)
> > > > {
> > > > /* try allocating only one CDM block */
> > > > if (!rm->cdm_blk) {
> > > > @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > return -EIO;
> > > > }
> > > > - if (global_state->cdm_to_enc_id) {
> > > > + if (global_state->cdm_to_crtc_id) {
> > > > DPU_ERROR("CDM_0 is already allocated\n");
> > > > return -EIO;
> > > > }
> > > > - global_state->cdm_to_enc_id = enc->base.id;
> > > > + global_state->cdm_to_crtc_id = crtc_id;
> > > > return 0;
> > > > }
> > > > @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > static int _dpu_rm_make_reservation(
> > > > struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc,
> > > > + uint32_t crtc_id,
> > > > struct msm_display_topology *topology)
> > > > {
> > > > int ret;
> > > > - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> > > > + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
> > > > if (ret) {
> > > > DPU_ERROR("unable to find appropriate mixers\n");
> > > > return ret;
> > > > }
> > > > - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> > > > +
> > > > + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> > > > topology);
> > > > if (ret) {
> > > > DPU_ERROR("unable to find appropriate CTL\n");
> > > > return ret;
> > > > }
> > > > - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> > > > + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
> > > > if (ret)
> > > > return ret;
> > > > if (topology->needs_cdm) {
> > > > - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> > > > + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
> > > > if (ret) {
> > > > DPU_ERROR("unable to find CDM blk\n");
> > > > return ret;
> > > > @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
> > > > }
> > > > static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > > > - uint32_t enc_id)
> > > > + uint32_t crtc_id)
> > > > {
> > > > int i;
> > > > for (i = 0; i < cnt; i++) {
> > > > - if (res_mapping[i] == enc_id)
> > > > + if (res_mapping[i] == crtc_id)
> > > > res_mapping[i] = 0;
> > > > }
> > > > }
> > > > @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > > > * dpu_rm_release - Given the encoder for the display chain, release any
> > > > * HW blocks previously reserved for that use case.
> > > > * @global_state: resources shared across multiple kms objects
> > > > - * @enc: DRM Encoder handle
> > > > + * @crtc: DRM CRTC handle
> > > > * @return: 0 on Success otherwise -ERROR
> > > > */
> > > > void dpu_rm_release(struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc)
> > > > + struct drm_crtc *crtc)
> > > > {
> > > > - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
> > > > - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
> > > > - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
> > > > - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
> > > > - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
> > > > - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
> > > > - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> > > > - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> > > > - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> > > > - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> > > > - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> > > > + uint32_t crtc_id = crtc->base.id;
> > > > +
> > > > + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
> > > > + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
> > > > + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
> > > > + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
> > > > + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
> > > > + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
> > > > + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
> > > > + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
> > > > + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> > > > + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> > > > + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> > > > }
> > > > /**
> > > > @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> > > > * HW Reservations should be released via dpu_rm_release_hw.
> > > > * @rm: DPU Resource Manager handle
> > > > * @global_state: resources shared across multiple kms objects
> > > > - * @enc: DRM Encoder handle
> > > > - * @crtc_state: Proposed Atomic DRM CRTC State handle
> > > > + * @crtc: DRM CRTC handle
> > > > * @topology: Pointer to topology info for the display
> > > > * @return: 0 on Success otherwise -ERROR
> > > > */
> > > > int dpu_rm_reserve(
> > > > struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc,
> > > > - struct drm_crtc_state *crtc_state,
> > > > + struct drm_crtc *crtc,
> > > > struct msm_display_topology *topology)
> > > > {
> > > > int ret;
> > > > - /* Check if this is just a page-flip */
> > > > - if (!drm_atomic_crtc_needs_modeset(crtc_state))
> > > > - return 0;
> > > > -
> > > > if (IS_ERR(global_state)) {
> > > > DPU_ERROR("failed to global state\n");
> > > > return PTR_ERR(global_state);
> > > > }
> > > > - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> > > > - enc->base.id, crtc_state->crtc->base.id);
> > > > + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
> > > > DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> > > > topology->num_lm, topology->num_dsc,
> > > > topology->num_intf);
> > > > - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> > > > + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
> > > > if (ret)
> > > > DPU_ERROR("failed to reserve hw resources: %d\n", ret);
> > > > -
> > > > -
> > > > return ret;
> > > > }
> > > > @@ -705,48 +697,49 @@ int dpu_rm_reserve(
> > > > * assigned to this encoder
> > > > * @rm: DPU Resource Manager handle
> > > > * @global_state: resources shared across multiple kms objects
> > > > - * @enc_id: encoder id requesting for allocation
> > > > + * @crtc: DRM CRTC handle
> > > > * @type: resource type to return data for
> > > > * @blks: pointer to the array to be filled by HW resources
> > > > * @blks_size: size of the @blks array
> > > > */
> > > > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > - struct dpu_global_state *global_state, uint32_t enc_id,
> > > > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > > > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
> > > > {
> > > > + uint32_t crtc_id = crtc->base.id;
> > > > struct dpu_hw_blk **hw_blks;
> > > > - uint32_t *hw_to_enc_id;
> > > > + uint32_t *hw_to_crtc_id;
> > > > int i, num_blks, max_blks;
> > > > switch (type) {
> > > > case DPU_HW_BLK_PINGPONG:
> > > > hw_blks = rm->pingpong_blks;
> > > > - hw_to_enc_id = global_state->pingpong_to_enc_id;
> > > > + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> > > > max_blks = ARRAY_SIZE(rm->pingpong_blks);
> > > > break;
> > > > case DPU_HW_BLK_LM:
> > > > hw_blks = rm->mixer_blks;
> > > > - hw_to_enc_id = global_state->mixer_to_enc_id;
> > > > + hw_to_crtc_id = global_state->mixer_to_crtc_id;
> > > > max_blks = ARRAY_SIZE(rm->mixer_blks);
> > > > break;
> > > > case DPU_HW_BLK_CTL:
> > > > hw_blks = rm->ctl_blks;
> > > > - hw_to_enc_id = global_state->ctl_to_enc_id;
> > > > + hw_to_crtc_id = global_state->ctl_to_crtc_id;
> > > > max_blks = ARRAY_SIZE(rm->ctl_blks);
> > > > break;
> > > > case DPU_HW_BLK_DSPP:
> > > > hw_blks = rm->dspp_blks;
> > > > - hw_to_enc_id = global_state->dspp_to_enc_id;
> > > > + hw_to_crtc_id = global_state->dspp_to_crtc_id;
> > > > max_blks = ARRAY_SIZE(rm->dspp_blks);
> > > > break;
> > > > case DPU_HW_BLK_DSC:
> > > > hw_blks = rm->dsc_blks;
> > > > - hw_to_enc_id = global_state->dsc_to_enc_id;
> > > > + hw_to_crtc_id = global_state->dsc_to_crtc_id;
> > > > max_blks = ARRAY_SIZE(rm->dsc_blks);
> > > > break;
> > > > case DPU_HW_BLK_CDM:
> > > > hw_blks = &rm->cdm_blk;
> > > > - hw_to_enc_id = &global_state->cdm_to_enc_id;
> > > > + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> > > > max_blks = 1;
> > > > break;
> > > > default:
> > > > @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > num_blks = 0;
> > > > for (i = 0; i < max_blks; i++) {
> > > > - if (hw_to_enc_id[i] != enc_id)
> > > > + if (hw_to_crtc_id[i] != crtc_id)
> > > > continue;
> > > > if (num_blks == blks_size) {
> > > > - DPU_ERROR("More than %d resources assigned to enc %d\n",
> > > > - blks_size, enc_id);
> > > > + DPU_ERROR("More than %d resources assigned to crtc %d\n",
> > > > + blks_size, crtc_id);
> > > > break;
> > > > }
> > > > if (!hw_blks[i]) {
> > > > - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
> > > > - type, enc_id);
> > > > + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
> > > > + type, crtc_id);
> > > > break;
> > > > }
> > > > blks[num_blks++] = hw_blks[i];
> > > > @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
> > > > drm_puts(p, "resource mapping:\n");
> > > > drm_puts(p, "\tpingpong=");
> > > > - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
> > > > + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
> > > > dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
> > > > - global_state->pingpong_to_enc_id[i]);
> > > > + global_state->pingpong_to_crtc_id[i]);
> > > > drm_puts(p, "\n");
> > > > drm_puts(p, "\tmixer=");
> > > > - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
> > > > + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
> > > > dpu_rm_print_state_helper(p, rm->mixer_blks[i],
> > > > - global_state->mixer_to_enc_id[i]);
> > > > + global_state->mixer_to_crtc_id[i]);
> > > > drm_puts(p, "\n");
> > > > drm_puts(p, "\tctl=");
> > > > - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
> > > > + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
> > > > dpu_rm_print_state_helper(p, rm->ctl_blks[i],
> > > > - global_state->ctl_to_enc_id[i]);
> > > > + global_state->ctl_to_crtc_id[i]);
> > > > drm_puts(p, "\n");
> > > > drm_puts(p, "\tdspp=");
> > > > - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
> > > > + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
> > > > dpu_rm_print_state_helper(p, rm->dspp_blks[i],
> > > > - global_state->dspp_to_enc_id[i]);
> > > > + global_state->dspp_to_crtc_id[i]);
> > > > drm_puts(p, "\n");
> > > > drm_puts(p, "\tdsc=");
> > > > - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
> > > > + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
> > > > dpu_rm_print_state_helper(p, rm->dsc_blks[i],
> > > > - global_state->dsc_to_enc_id[i]);
> > > > + global_state->dsc_to_crtc_id[i]);
> > > > drm_puts(p, "\n");
> > > > drm_puts(p, "\tcdm=");
> > > > dpu_rm_print_state_helper(p, rm->cdm_blk,
> > > > - global_state->cdm_to_enc_id);
> > > > + global_state->cdm_to_crtc_id);
> > > > drm_puts(p, "\n");
> > > > }
> > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
> > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
> > > > int dpu_rm_reserve(struct dpu_rm *rm,
> > > > struct dpu_global_state *global_state,
> > > > - struct drm_encoder *drm_enc,
> > > > - struct drm_crtc_state *crtc_state,
> > > > + struct drm_crtc *crtc,
> > > > struct msm_display_topology *topology);
> > > > void dpu_rm_release(struct dpu_global_state *global_state,
> > > > - struct drm_encoder *enc);
> > > > + struct drm_crtc *crtc);
> > > > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > - struct dpu_global_state *global_state, uint32_t enc_id,
> > > > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > > > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
> > > > void dpu_rm_print_state(struct drm_printer *p,
> > > >
> > > > --
> > > > 2.34.1
> > > >
> > >
> > > --
> > > With best wishes
> > > Dmitry
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2025-01-15 9:56 ` Dmitry Baryshkov
@ 2025-01-16 4:13 ` Jessica Zhang
2025-01-16 7:32 ` Dmitry Baryshkov
0 siblings, 1 reply; 77+ messages in thread
From: Jessica Zhang @ 2025-01-16 4:13 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On 1/15/2025 1:56 AM, Dmitry Baryshkov wrote:
> On Tue, Jan 14, 2025 at 09:28:50PM -0800, Jessica Zhang wrote:
>>
>>
>> On 12/24/2024 12:00 PM, Dmitry Baryshkov wrote:
>>> On Tue, Dec 24, 2024 at 06:45:07AM +0200, Dmitry Baryshkov wrote:
>>>> On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
>>>>> From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>>
>>>>> Up to now the driver has been using encoder to allocate hardware
>>>>> resources. Switch it to use CRTC id in preparation for the next step.
>>>>>
>>>>> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>> ---
>>>>> Changes in v4 (due to rebase):
>>>>>
>>>>> - moved *_get_assigned_resources() changes for DSPP and LM from
>>>>> encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
>>>>> ---
>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
>>>>> 4 files changed, 110 insertions(+), 118 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>> index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>>>>> @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
>>>>> 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));
>>>>> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>>
>>>> And this crashes because drm_enc->crtc isn't set yet. Was this commit
>>>> tested? Or was it only tested as a part of the patchset, after this code
>>>> has been rewritten by the subsequent patches? I will replace this with
>>>> crtc_state->crtc, but generatlly this looks bad.
>>>
>>> Even with this in place, it fails the kms_color@ctm-max for pipe-B-eDP-1
>>> on SC7180 (pipe-A-eDP-1 succeeds). See job log at [1].
>>>
>>> corresponding excerpt from the log:
>>>
>>> [IGT] kms_color: starting dynamic subtest pipe-B-eDP-1
>>> [drm:_dpu_rm_check_lm_and_get_connected_blks] [dpu error]failed to get dspp on lm 0
>>> [drm:_dpu_rm_make_reservation] [dpu error]unable to find appropriate mixers
>>> [drm:dpu_rm_reserve] [dpu error]failed to reserve hw resources: -119
>>> [IGT] kms_color: finished subtest pipe-B-eDP-1, FAIL
>>>
>>> FWIW it looks like during an attempt to use second CRTC the driver
>>> doesn't release resources for the first one. I'll drop this patch for
>>> now, leaving just HW_CWB patches in.
>>>
>>> [1] https://gitlab.freedesktop.org/drm/msm/-/jobs/68614460/viewer
>>
>> Hi Dmitry,
>>
>> Thanks for catching this -- it seems like the issue is because a disabling
>> commit will not call into the encoder atomic check.
>>
>> During the disabling commit at the end of the IGT test [2], the connector is
>> detached from the crtc it was testing on. Because of this, we end up
>> skipping over any connector that doesn't have the best_encoder or crtc set
>> [1] within mode_fixup().
>>
>> So we'll never release the dspp block from the pipe-A/crtc-0 subtest, which
>> will cause the "failed to reserve hw resources" error for pipe-b/crtc-1.
>
> And currently the test works because the encoder isn't changed, so all
> resources are kept from the previous run, even though the routing has
> changed from CRTC 0 to 1. Fun.
>
>> Overall, I think the issue stems from the fact that we're trying to update a
>> crtc-based component within an encoder-specific callback. Maybe the right
>> call here would be to squash this commit with "drm/msm/dpu: move resource
>> allocation to CRTC".
>
> I'd rather not. Those two changes are big enough and independent. Can
> you change the order of those two commits instead?
Ack. So, basically the order of changes will be:
1. fill CRTC resources
2. move resource allocation to CRTC
3. Switch RM to use crtc_id
>
>>
>> What do you think?
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>> [1] https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/drm_atomic_helper.c#L441
>> [2] https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tests/kms_color.c#L603
>>
>>>
>>>>
>>>>> 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));
>>>>> + drm_enc->crtc, 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,
>>>>> + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
>>>>
>>>>
>>>>> ARRAY_SIZE(hw_dspp));
>>>>> for (i = 0; i < num_lm; i++) {
>>>>> @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
>>>>> * Dont allocate when active is false.
>>>>> */
>>>>> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
>>>>> - dpu_rm_release(global_state, drm_enc);
>>>>> + dpu_rm_release(global_state, crtc_state->crtc);
>>>>> if (!crtc_state->active_changed || crtc_state->enable)
>>>>> ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
>>>>> - drm_enc, crtc_state, &topology);
>>>>> + crtc_state->crtc, &topology);
>>>>> if (!ret)
>>>>> dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
>>>>> global_state, crtc_state);
>>>>> @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>> /* Query resource that have been reserved in atomic check step. */
>>>>> num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>> - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
>>>>> + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
>>>>> 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));
>>>>> + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
>>>>> for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
>>>>> dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
>>>>> : NULL;
>>>>> num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>> - drm_enc->base.id, DPU_HW_BLK_DSC,
>>>>> + drm_enc->crtc, DPU_HW_BLK_DSC,
>>>>> hw_dsc, ARRAY_SIZE(hw_dsc));
>>>>> for (i = 0; i < num_dsc; i++) {
>>>>> dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
>>>>> @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>>> struct dpu_hw_blk *hw_cdm = NULL;
>>>>> dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
>>>>> - drm_enc->base.id, DPU_HW_BLK_CDM,
>>>>> + drm_enc->crtc, DPU_HW_BLK_CDM,
>>>>> &hw_cdm, 1);
>>>>> dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
>>>>> }
>>>>> @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
>>>>> global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
>>>>> num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
>>>>> - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>>>>> + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
>>>>> for (i = 0; i < num_lm; i++) {
>>>>> hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>> index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
>>>>> @@ -122,12 +122,12 @@ struct dpu_global_state {
>>>>> struct dpu_rm *rm;
>>>>> - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
>>>>> - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
>>>>> - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
>>>>> - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
>>>>> - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
>>>>> - uint32_t cdm_to_enc_id;
>>>>> + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
>>>>> + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
>>>>> + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
>>>>> + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
>>>>> + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
>>>>> + uint32_t cdm_to_crtc_id;
>>>>> };
>>>>> struct dpu_global_state
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>> index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>> @@ -22,9 +22,9 @@
>>>>> static inline bool reserved_by_other(uint32_t *res_map, int idx,
>>>>> - uint32_t enc_id)
>>>>> + uint32_t crtc_id)
>>>>> {
>>>>> - return res_map[idx] && res_map[idx] != enc_id;
>>>>> + return res_map[idx] && res_map[idx] != crtc_id;
>>>>> }
>>>>> /**
>>>>> @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>>> * pingpong
>>>>> * @rm: dpu resource manager handle
>>>>> * @global_state: resources shared across multiple kms objects
>>>>> - * @enc_id: encoder id requesting for allocation
>>>>> + * @crtc_id: crtc id requesting for allocation
>>>>> * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
>>>>> * if lm, and all other hardwired blocks connected to the lm (pp) is
>>>>> * available and appropriate
>>>>> @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>>> */
>>>>> static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>>>> + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
>>>>> struct msm_display_topology *topology)
>>>>> {
>>>>> const struct dpu_lm_cfg *lm_cfg;
>>>>> int idx;
>>>>> /* Already reserved? */
>>>>> - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
>>>>> + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
>>>>> DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
>>>>> return false;
>>>>> }
>>>>> @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>> return false;
>>>>> }
>>>>> - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
>>>>> + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
>>>>> DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
>>>>> lm_cfg->pingpong);
>>>>> return false;
>>>>> @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>> return false;
>>>>> }
>>>>> - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
>>>>> + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
>>>>> DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
>>>>> lm_cfg->dspp);
>>>>> return false;
>>>>> @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
>>>>> static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - uint32_t enc_id,
>>>>> + uint32_t crtc_id,
>>>>> struct msm_display_topology *topology)
>>>>> {
>>>>> @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>> lm_idx[lm_count] = i;
>>>>> if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
>>>>> - enc_id, i, &pp_idx[lm_count],
>>>>> + crtc_id, i, &pp_idx[lm_count],
>>>>> &dspp_idx[lm_count], topology)) {
>>>>> continue;
>>>>> }
>>>>> @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>> continue;
>>>>> if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
>>>>> - global_state, enc_id, j,
>>>>> + global_state, crtc_id, j,
>>>>> &pp_idx[lm_count], &dspp_idx[lm_count],
>>>>> topology)) {
>>>>> continue;
>>>>> @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>> }
>>>>> for (i = 0; i < lm_count; i++) {
>>>>> - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
>>>>> - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
>>>>> - global_state->dspp_to_enc_id[dspp_idx[i]] =
>>>>> - topology->num_dspp ? enc_id : 0;
>>>>> + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
>>>>> + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
>>>>> + global_state->dspp_to_crtc_id[dspp_idx[i]] =
>>>>> + topology->num_dspp ? crtc_id : 0;
>>>>> - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
>>>>> + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
>>>>> pp_idx[i] + PINGPONG_0);
>>>>> }
>>>>> @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
>>>>> static int _dpu_rm_reserve_ctls(
>>>>> struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - uint32_t enc_id,
>>>>> + uint32_t crtc_id,
>>>>> const struct msm_display_topology *top)
>>>>> {
>>>>> int ctl_idx[MAX_BLOCKS];
>>>>> @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
>>>>> if (!rm->ctl_blks[j])
>>>>> continue;
>>>>> - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
>>>>> + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
>>>>> continue;
>>>>> ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
>>>>> @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
>>>>> return -ENAVAIL;
>>>>> for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
>>>>> - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
>>>>> - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
>>>>> + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
>>>>> + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
>>>>> }
>>>>> return 0;
>>>>> @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
>>>>> static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
>>>>> int start,
>>>>> - uint32_t enc_id)
>>>>> + uint32_t crtc_id)
>>>>> {
>>>>> int i;
>>>>> for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
>>>>> - if (global_state->pingpong_to_enc_id[i] == enc_id)
>>>>> + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
>>>>> return i;
>>>>> }
>>>>> @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
>>>>> static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - uint32_t enc_id,
>>>>> + uint32_t crtc_id,
>>>>> const struct msm_display_topology *top)
>>>>> {
>>>>> int num_dsc = 0;
>>>>> @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>>>> if (!rm->dsc_blks[dsc_idx])
>>>>> continue;
>>>>> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
>>>>> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
>>>>> continue;
>>>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
>>>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
>>>>> if (pp_idx < 0)
>>>>> return -ENAVAIL;
>>>>> @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>>>> if (ret)
>>>>> return -ENAVAIL;
>>>>> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
>>>>> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
>>>>> num_dsc++;
>>>>> pp_idx++;
>>>>> }
>>>>> @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
>>>>> static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - uint32_t enc_id,
>>>>> + uint32_t crtc_id,
>>>>> const struct msm_display_topology *top)
>>>>> {
>>>>> int num_dsc = 0;
>>>>> @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>>> continue;
>>>>> /* consective dsc index to be paired */
>>>>> - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
>>>>> - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
>>>>> + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
>>>>> + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
>>>>> continue;
>>>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
>>>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
>>>>> if (pp_idx < 0)
>>>>> return -ENAVAIL;
>>>>> @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>>> continue;
>>>>> }
>>>>> - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
>>>>> + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
>>>>> if (pp_idx < 0)
>>>>> return -ENAVAIL;
>>>>> @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>>> continue;
>>>>> }
>>>>> - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
>>>>> - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
>>>>> + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
>>>>> + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
>>>>> num_dsc += 2;
>>>>> pp_idx++; /* start for next pair */
>>>>> }
>>>>> @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
>>>>> static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc,
>>>>> + uint32_t crtc_id,
>>>>> const struct msm_display_topology *top)
>>>>> {
>>>>> - uint32_t enc_id = enc->base.id;
>>>>> -
>>>>> if (!top->num_dsc || !top->num_intf)
>>>>> return 0;
>>>>> @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
>>>>> /* num_dsc should be either 1, 2 or 4 */
>>>>> if (top->num_dsc > top->num_intf) /* merge mode */
>>>>> - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
>>>>> + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
>>>>> else
>>>>> - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
>>>>> + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
>>>>> return 0;
>>>>> }
>>>>> static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc)
>>>>> + uint32_t crtc_id)
>>>>> {
>>>>> /* try allocating only one CDM block */
>>>>> if (!rm->cdm_blk) {
>>>>> @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>>>> return -EIO;
>>>>> }
>>>>> - if (global_state->cdm_to_enc_id) {
>>>>> + if (global_state->cdm_to_crtc_id) {
>>>>> DPU_ERROR("CDM_0 is already allocated\n");
>>>>> return -EIO;
>>>>> }
>>>>> - global_state->cdm_to_enc_id = enc->base.id;
>>>>> + global_state->cdm_to_crtc_id = crtc_id;
>>>>> return 0;
>>>>> }
>>>>> @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
>>>>> static int _dpu_rm_make_reservation(
>>>>> struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc,
>>>>> + uint32_t crtc_id,
>>>>> struct msm_display_topology *topology)
>>>>> {
>>>>> int ret;
>>>>> - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
>>>>> + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
>>>>> if (ret) {
>>>>> DPU_ERROR("unable to find appropriate mixers\n");
>>>>> return ret;
>>>>> }
>>>>> - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
>>>>> +
>>>>> + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>>>>> topology);
>>>>> if (ret) {
>>>>> DPU_ERROR("unable to find appropriate CTL\n");
>>>>> return ret;
>>>>> }
>>>>> - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
>>>>> + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
>>>>> if (ret)
>>>>> return ret;
>>>>> if (topology->needs_cdm) {
>>>>> - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
>>>>> + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
>>>>> if (ret) {
>>>>> DPU_ERROR("unable to find CDM blk\n");
>>>>> return ret;
>>>>> @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
>>>>> }
>>>>> static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>>>> - uint32_t enc_id)
>>>>> + uint32_t crtc_id)
>>>>> {
>>>>> int i;
>>>>> for (i = 0; i < cnt; i++) {
>>>>> - if (res_mapping[i] == enc_id)
>>>>> + if (res_mapping[i] == crtc_id)
>>>>> res_mapping[i] = 0;
>>>>> }
>>>>> }
>>>>> @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
>>>>> * dpu_rm_release - Given the encoder for the display chain, release any
>>>>> * HW blocks previously reserved for that use case.
>>>>> * @global_state: resources shared across multiple kms objects
>>>>> - * @enc: DRM Encoder handle
>>>>> + * @crtc: DRM CRTC handle
>>>>> * @return: 0 on Success otherwise -ERROR
>>>>> */
>>>>> void dpu_rm_release(struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc)
>>>>> + struct drm_crtc *crtc)
>>>>> {
>>>>> - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
>>>>> - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
>>>>> - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
>>>>> - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
>>>>> - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
>>>>> - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
>>>>> - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
>>>>> - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
>>>>> - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
>>>>> - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
>>>>> - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
>>>>> + uint32_t crtc_id = crtc->base.id;
>>>>> +
>>>>> + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
>>>>> + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
>>>>> + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
>>>>> + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
>>>>> + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
>>>>> + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
>>>>> + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
>>>>> + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
>>>>> + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
>>>>> + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
>>>>> + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
>>>>> }
>>>>> /**
>>>>> @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
>>>>> * HW Reservations should be released via dpu_rm_release_hw.
>>>>> * @rm: DPU Resource Manager handle
>>>>> * @global_state: resources shared across multiple kms objects
>>>>> - * @enc: DRM Encoder handle
>>>>> - * @crtc_state: Proposed Atomic DRM CRTC State handle
>>>>> + * @crtc: DRM CRTC handle
>>>>> * @topology: Pointer to topology info for the display
>>>>> * @return: 0 on Success otherwise -ERROR
>>>>> */
>>>>> int dpu_rm_reserve(
>>>>> struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc,
>>>>> - struct drm_crtc_state *crtc_state,
>>>>> + struct drm_crtc *crtc,
>>>>> struct msm_display_topology *topology)
>>>>> {
>>>>> int ret;
>>>>> - /* Check if this is just a page-flip */
>>>>> - if (!drm_atomic_crtc_needs_modeset(crtc_state))
>>>>> - return 0;
>>>>> -
>>>>> if (IS_ERR(global_state)) {
>>>>> DPU_ERROR("failed to global state\n");
>>>>> return PTR_ERR(global_state);
>>>>> }
>>>>> - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
>>>>> - enc->base.id, crtc_state->crtc->base.id);
>>>>> + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
>>>>> DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
>>>>> topology->num_lm, topology->num_dsc,
>>>>> topology->num_intf);
>>>>> - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
>>>>> + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
>>>>> if (ret)
>>>>> DPU_ERROR("failed to reserve hw resources: %d\n", ret);
>>>>> -
>>>>> -
>>>>> return ret;
>>>>> }
>>>>> @@ -705,48 +697,49 @@ int dpu_rm_reserve(
>>>>> * assigned to this encoder
>>>>> * @rm: DPU Resource Manager handle
>>>>> * @global_state: resources shared across multiple kms objects
>>>>> - * @enc_id: encoder id requesting for allocation
>>>>> + * @crtc: DRM CRTC handle
>>>>> * @type: resource type to return data for
>>>>> * @blks: pointer to the array to be filled by HW resources
>>>>> * @blks_size: size of the @blks array
>>>>> */
>>>>> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>>> - struct dpu_global_state *global_state, uint32_t enc_id,
>>>>> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>>>> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
>>>>> {
>>>>> + uint32_t crtc_id = crtc->base.id;
>>>>> struct dpu_hw_blk **hw_blks;
>>>>> - uint32_t *hw_to_enc_id;
>>>>> + uint32_t *hw_to_crtc_id;
>>>>> int i, num_blks, max_blks;
>>>>> switch (type) {
>>>>> case DPU_HW_BLK_PINGPONG:
>>>>> hw_blks = rm->pingpong_blks;
>>>>> - hw_to_enc_id = global_state->pingpong_to_enc_id;
>>>>> + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
>>>>> max_blks = ARRAY_SIZE(rm->pingpong_blks);
>>>>> break;
>>>>> case DPU_HW_BLK_LM:
>>>>> hw_blks = rm->mixer_blks;
>>>>> - hw_to_enc_id = global_state->mixer_to_enc_id;
>>>>> + hw_to_crtc_id = global_state->mixer_to_crtc_id;
>>>>> max_blks = ARRAY_SIZE(rm->mixer_blks);
>>>>> break;
>>>>> case DPU_HW_BLK_CTL:
>>>>> hw_blks = rm->ctl_blks;
>>>>> - hw_to_enc_id = global_state->ctl_to_enc_id;
>>>>> + hw_to_crtc_id = global_state->ctl_to_crtc_id;
>>>>> max_blks = ARRAY_SIZE(rm->ctl_blks);
>>>>> break;
>>>>> case DPU_HW_BLK_DSPP:
>>>>> hw_blks = rm->dspp_blks;
>>>>> - hw_to_enc_id = global_state->dspp_to_enc_id;
>>>>> + hw_to_crtc_id = global_state->dspp_to_crtc_id;
>>>>> max_blks = ARRAY_SIZE(rm->dspp_blks);
>>>>> break;
>>>>> case DPU_HW_BLK_DSC:
>>>>> hw_blks = rm->dsc_blks;
>>>>> - hw_to_enc_id = global_state->dsc_to_enc_id;
>>>>> + hw_to_crtc_id = global_state->dsc_to_crtc_id;
>>>>> max_blks = ARRAY_SIZE(rm->dsc_blks);
>>>>> break;
>>>>> case DPU_HW_BLK_CDM:
>>>>> hw_blks = &rm->cdm_blk;
>>>>> - hw_to_enc_id = &global_state->cdm_to_enc_id;
>>>>> + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
>>>>> max_blks = 1;
>>>>> break;
>>>>> default:
>>>>> @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>>> num_blks = 0;
>>>>> for (i = 0; i < max_blks; i++) {
>>>>> - if (hw_to_enc_id[i] != enc_id)
>>>>> + if (hw_to_crtc_id[i] != crtc_id)
>>>>> continue;
>>>>> if (num_blks == blks_size) {
>>>>> - DPU_ERROR("More than %d resources assigned to enc %d\n",
>>>>> - blks_size, enc_id);
>>>>> + DPU_ERROR("More than %d resources assigned to crtc %d\n",
>>>>> + blks_size, crtc_id);
>>>>> break;
>>>>> }
>>>>> if (!hw_blks[i]) {
>>>>> - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
>>>>> - type, enc_id);
>>>>> + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
>>>>> + type, crtc_id);
>>>>> break;
>>>>> }
>>>>> blks[num_blks++] = hw_blks[i];
>>>>> @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
>>>>> drm_puts(p, "resource mapping:\n");
>>>>> drm_puts(p, "\tpingpong=");
>>>>> - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
>>>>> + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
>>>>> dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
>>>>> - global_state->pingpong_to_enc_id[i]);
>>>>> + global_state->pingpong_to_crtc_id[i]);
>>>>> drm_puts(p, "\n");
>>>>> drm_puts(p, "\tmixer=");
>>>>> - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
>>>>> + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
>>>>> dpu_rm_print_state_helper(p, rm->mixer_blks[i],
>>>>> - global_state->mixer_to_enc_id[i]);
>>>>> + global_state->mixer_to_crtc_id[i]);
>>>>> drm_puts(p, "\n");
>>>>> drm_puts(p, "\tctl=");
>>>>> - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
>>>>> + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
>>>>> dpu_rm_print_state_helper(p, rm->ctl_blks[i],
>>>>> - global_state->ctl_to_enc_id[i]);
>>>>> + global_state->ctl_to_crtc_id[i]);
>>>>> drm_puts(p, "\n");
>>>>> drm_puts(p, "\tdspp=");
>>>>> - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
>>>>> + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
>>>>> dpu_rm_print_state_helper(p, rm->dspp_blks[i],
>>>>> - global_state->dspp_to_enc_id[i]);
>>>>> + global_state->dspp_to_crtc_id[i]);
>>>>> drm_puts(p, "\n");
>>>>> drm_puts(p, "\tdsc=");
>>>>> - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
>>>>> + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
>>>>> dpu_rm_print_state_helper(p, rm->dsc_blks[i],
>>>>> - global_state->dsc_to_enc_id[i]);
>>>>> + global_state->dsc_to_crtc_id[i]);
>>>>> drm_puts(p, "\n");
>>>>> drm_puts(p, "\tcdm=");
>>>>> dpu_rm_print_state_helper(p, rm->cdm_blk,
>>>>> - global_state->cdm_to_enc_id);
>>>>> + global_state->cdm_to_crtc_id);
>>>>> drm_puts(p, "\n");
>>>>> }
>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>> index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
>>>>> @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
>>>>> int dpu_rm_reserve(struct dpu_rm *rm,
>>>>> struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *drm_enc,
>>>>> - struct drm_crtc_state *crtc_state,
>>>>> + struct drm_crtc *crtc,
>>>>> struct msm_display_topology *topology);
>>>>> void dpu_rm_release(struct dpu_global_state *global_state,
>>>>> - struct drm_encoder *enc);
>>>>> + struct drm_crtc *crtc);
>>>>> int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
>>>>> - struct dpu_global_state *global_state, uint32_t enc_id,
>>>>> + struct dpu_global_state *global_state, struct drm_crtc *crtc,
>>>>> enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
>>>>> void dpu_rm_print_state(struct drm_printer *p,
>>>>>
>>>>> --
>>>>> 2.34.1
>>>>>
>>>>
>>>> --
>>>> With best wishes
>>>> Dmitry
>>>
>>> --
>>> With best wishes
>>> Dmitry
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
* Re: [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2025-01-16 4:13 ` Jessica Zhang
@ 2025-01-16 7:32 ` Dmitry Baryshkov
0 siblings, 0 replies; 77+ messages in thread
From: Dmitry Baryshkov @ 2025-01-16 7:32 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Simona Vetter, Simona Vetter, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark,
Ville Syrjälä
On Wed, Jan 15, 2025 at 08:13:37PM -0800, Jessica Zhang wrote:
>
>
> On 1/15/2025 1:56 AM, Dmitry Baryshkov wrote:
> > On Tue, Jan 14, 2025 at 09:28:50PM -0800, Jessica Zhang wrote:
> > >
> > >
> > > On 12/24/2024 12:00 PM, Dmitry Baryshkov wrote:
> > > > On Tue, Dec 24, 2024 at 06:45:07AM +0200, Dmitry Baryshkov wrote:
> > > > > On Mon, Dec 16, 2024 at 04:43:17PM -0800, Jessica Zhang wrote:
> > > > > > From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > > > >
> > > > > > Up to now the driver has been using encoder to allocate hardware
> > > > > > resources. Switch it to use CRTC id in preparation for the next step.
> > > > > >
> > > > > > Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> > > > > > Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> > > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > > ---
> > > > > > Changes in v4 (due to rebase):
> > > > > >
> > > > > > - moved *_get_assigned_resources() changes for DSPP and LM from
> > > > > > encoder *_virt_atomic_mode_set() to *_assign_crtc_resources()
> > > > > > ---
> > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 20 +--
> > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
> > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 189 ++++++++++++++--------------
> > > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 7 +-
> > > > > > 4 files changed, 110 insertions(+), 118 deletions(-)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > index 5172ab4dea995a154cd88d05c3842d7425fc34ce..e6f930dd34566d01223823de82c922668e6be300 100644
> > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> > > > > > @@ -715,11 +715,11 @@ static void dpu_encoder_assign_crtc_resources(struct dpu_kms *dpu_kms,
> > > > > > 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));
> > > > > > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > > >
> > > > > And this crashes because drm_enc->crtc isn't set yet. Was this commit
> > > > > tested? Or was it only tested as a part of the patchset, after this code
> > > > > has been rewritten by the subsequent patches? I will replace this with
> > > > > crtc_state->crtc, but generatlly this looks bad.
> > > >
> > > > Even with this in place, it fails the kms_color@ctm-max for pipe-B-eDP-1
> > > > on SC7180 (pipe-A-eDP-1 succeeds). See job log at [1].
> > > >
> > > > corresponding excerpt from the log:
> > > >
> > > > [IGT] kms_color: starting dynamic subtest pipe-B-eDP-1
> > > > [drm:_dpu_rm_check_lm_and_get_connected_blks] [dpu error]failed to get dspp on lm 0
> > > > [drm:_dpu_rm_make_reservation] [dpu error]unable to find appropriate mixers
> > > > [drm:dpu_rm_reserve] [dpu error]failed to reserve hw resources: -119
> > > > [IGT] kms_color: finished subtest pipe-B-eDP-1, FAIL
> > > >
> > > > FWIW it looks like during an attempt to use second CRTC the driver
> > > > doesn't release resources for the first one. I'll drop this patch for
> > > > now, leaving just HW_CWB patches in.
> > > >
> > > > [1] https://gitlab.freedesktop.org/drm/msm/-/jobs/68614460/viewer
> > >
> > > Hi Dmitry,
> > >
> > > Thanks for catching this -- it seems like the issue is because a disabling
> > > commit will not call into the encoder atomic check.
> > >
> > > During the disabling commit at the end of the IGT test [2], the connector is
> > > detached from the crtc it was testing on. Because of this, we end up
> > > skipping over any connector that doesn't have the best_encoder or crtc set
> > > [1] within mode_fixup().
> > >
> > > So we'll never release the dspp block from the pipe-A/crtc-0 subtest, which
> > > will cause the "failed to reserve hw resources" error for pipe-b/crtc-1.
> >
> > And currently the test works because the encoder isn't changed, so all
> > resources are kept from the previous run, even though the routing has
> > changed from CRTC 0 to 1. Fun.
> >
> > > Overall, I think the issue stems from the fact that we're trying to update a
> > > crtc-based component within an encoder-specific callback. Maybe the right
> > > call here would be to squash this commit with "drm/msm/dpu: move resource
> > > allocation to CRTC".
> >
> > I'd rather not. Those two changes are big enough and independent. Can
> > you change the order of those two commits instead?
>
> Ack. So, basically the order of changes will be:
>
> 1. fill CRTC resources
> 2. move resource allocation to CRTC
> 3. Switch RM to use crtc_id
This might be a bit troublesome as there is no CRTC -> encoder link.
However as we do not support clone mode, it should be possible, the
first matching connector / encoder is the only one. Also note, that
atomic_check() for a CRTC is called after the encoder's one.
>
> >
> > >
> > > What do you think?
> > >
> > > Thanks,
> > >
> > > Jessica Zhang
> > >
> > > [1] https://elixir.bootlin.com/linux/v6.12.6/source/drivers/gpu/drm/drm_atomic_helper.c#L441
> > > [2] https://gitlab.freedesktop.org/drm/igt-gpu-tools/-/blob/master/tests/kms_color.c#L603
> > >
> > > >
> > > > >
> > > > > > 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));
> > > > > > + drm_enc->crtc, 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,
> > > > > > + drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
> > > > >
> > > > >
> > > > > > ARRAY_SIZE(hw_dspp));
> > > > > > for (i = 0; i < num_lm; i++) {
> > > > > > @@ -796,11 +796,11 @@ static int dpu_encoder_virt_atomic_check(
> > > > > > * Dont allocate when active is false.
> > > > > > */
> > > > > > if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> > > > > > - dpu_rm_release(global_state, drm_enc);
> > > > > > + dpu_rm_release(global_state, crtc_state->crtc);
> > > > > > if (!crtc_state->active_changed || crtc_state->enable)
> > > > > > ret = dpu_rm_reserve(&dpu_kms->rm, global_state,
> > > > > > - drm_enc, crtc_state, &topology);
> > > > > > + crtc_state->crtc, &topology);
> > > > > > if (!ret)
> > > > > > dpu_encoder_assign_crtc_resources(dpu_kms, drm_enc,
> > > > > > global_state, crtc_state);
> > > > > > @@ -1244,17 +1244,17 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > > /* Query resource that have been reserved in atomic check step. */
> > > > > > num_pp = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > - drm_enc->base.id, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > > + drm_enc->crtc, DPU_HW_BLK_PINGPONG, hw_pp,
> > > > > > 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));
> > > > > > + drm_enc->crtc, DPU_HW_BLK_CTL, hw_ctl, ARRAY_SIZE(hw_ctl));
> > > > > > for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
> > > > > > dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
> > > > > > : NULL;
> > > > > > num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > - drm_enc->base.id, DPU_HW_BLK_DSC,
> > > > > > + drm_enc->crtc, DPU_HW_BLK_DSC,
> > > > > > hw_dsc, ARRAY_SIZE(hw_dsc));
> > > > > > for (i = 0; i < num_dsc; i++) {
> > > > > > dpu_enc->hw_dsc[i] = to_dpu_hw_dsc(hw_dsc[i]);
> > > > > > @@ -1268,7 +1268,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> > > > > > struct dpu_hw_blk *hw_cdm = NULL;
> > > > > > dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
> > > > > > - drm_enc->base.id, DPU_HW_BLK_CDM,
> > > > > > + drm_enc->crtc, DPU_HW_BLK_CDM,
> > > > > > &hw_cdm, 1);
> > > > > > dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
> > > > > > }
> > > > > > @@ -2189,7 +2189,7 @@ static void dpu_encoder_helper_reset_mixers(struct dpu_encoder_phys *phys_enc)
> > > > > > global_state = dpu_kms_get_existing_global_state(phys_enc->dpu_kms);
> > > > > > num_lm = dpu_rm_get_assigned_resources(&phys_enc->dpu_kms->rm, global_state,
> > > > > > - phys_enc->parent->base.id, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > > > > > + phys_enc->parent->crtc, DPU_HW_BLK_LM, hw_lm, ARRAY_SIZE(hw_lm));
> > > > > > for (i = 0; i < num_lm; i++) {
> > > > > > hw_mixer[i] = to_dpu_hw_mixer(hw_lm[i]);
> > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > index 88d64d43ea1a8226b414f04bf76551f7dda94ef6..48d756d8f8c6e4ab94b72bac0418320f7dc8cda8 100644
> > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
> > > > > > @@ -122,12 +122,12 @@ struct dpu_global_state {
> > > > > > struct dpu_rm *rm;
> > > > > > - uint32_t pingpong_to_enc_id[PINGPONG_MAX - PINGPONG_0];
> > > > > > - uint32_t mixer_to_enc_id[LM_MAX - LM_0];
> > > > > > - uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
> > > > > > - uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
> > > > > > - uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
> > > > > > - uint32_t cdm_to_enc_id;
> > > > > > + uint32_t pingpong_to_crtc_id[PINGPONG_MAX - PINGPONG_0];
> > > > > > + uint32_t mixer_to_crtc_id[LM_MAX - LM_0];
> > > > > > + uint32_t ctl_to_crtc_id[CTL_MAX - CTL_0];
> > > > > > + uint32_t dspp_to_crtc_id[DSPP_MAX - DSPP_0];
> > > > > > + uint32_t dsc_to_crtc_id[DSC_MAX - DSC_0];
> > > > > > + uint32_t cdm_to_crtc_id;
> > > > > > };
> > > > > > struct dpu_global_state
> > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > index cd5960af4a151428cc6fb7154c3ffdb65ebcf287..2f227e6826b5f90bdab508bd1e87075d8b4274fd 100644
> > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > > @@ -22,9 +22,9 @@
> > > > > > static inline bool reserved_by_other(uint32_t *res_map, int idx,
> > > > > > - uint32_t enc_id)
> > > > > > + uint32_t crtc_id)
> > > > > > {
> > > > > > - return res_map[idx] && res_map[idx] != enc_id;
> > > > > > + return res_map[idx] && res_map[idx] != crtc_id;
> > > > > > }
> > > > > > /**
> > > > > > @@ -226,7 +226,7 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > > > * pingpong
> > > > > > * @rm: dpu resource manager handle
> > > > > > * @global_state: resources shared across multiple kms objects
> > > > > > - * @enc_id: encoder id requesting for allocation
> > > > > > + * @crtc_id: crtc id requesting for allocation
> > > > > > * @lm_idx: index of proposed layer mixer in rm->mixer_blks[], function checks
> > > > > > * if lm, and all other hardwired blocks connected to the lm (pp) is
> > > > > > * available and appropriate
> > > > > > @@ -239,14 +239,14 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> > > > > > */
> > > > > > static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - uint32_t enc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > > > > > + uint32_t crtc_id, int lm_idx, int *pp_idx, int *dspp_idx,
> > > > > > struct msm_display_topology *topology)
> > > > > > {
> > > > > > const struct dpu_lm_cfg *lm_cfg;
> > > > > > int idx;
> > > > > > /* Already reserved? */
> > > > > > - if (reserved_by_other(global_state->mixer_to_enc_id, lm_idx, enc_id)) {
> > > > > > + if (reserved_by_other(global_state->mixer_to_crtc_id, lm_idx, crtc_id)) {
> > > > > > DPU_DEBUG("lm %d already reserved\n", lm_idx + LM_0);
> > > > > > return false;
> > > > > > }
> > > > > > @@ -258,7 +258,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > > > return false;
> > > > > > }
> > > > > > - if (reserved_by_other(global_state->pingpong_to_enc_id, idx, enc_id)) {
> > > > > > + if (reserved_by_other(global_state->pingpong_to_crtc_id, idx, crtc_id)) {
> > > > > > DPU_DEBUG("lm %d pp %d already reserved\n", lm_cfg->id,
> > > > > > lm_cfg->pingpong);
> > > > > > return false;
> > > > > > @@ -274,7 +274,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > > > return false;
> > > > > > }
> > > > > > - if (reserved_by_other(global_state->dspp_to_enc_id, idx, enc_id)) {
> > > > > > + if (reserved_by_other(global_state->dspp_to_crtc_id, idx, crtc_id)) {
> > > > > > DPU_DEBUG("lm %d dspp %d already reserved\n", lm_cfg->id,
> > > > > > lm_cfg->dspp);
> > > > > > return false;
> > > > > > @@ -286,7 +286,7 @@ static bool _dpu_rm_check_lm_and_get_connected_blks(struct dpu_rm *rm,
> > > > > > static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - uint32_t enc_id,
> > > > > > + uint32_t crtc_id,
> > > > > > struct msm_display_topology *topology)
> > > > > > {
> > > > > > @@ -310,7 +310,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > > > lm_idx[lm_count] = i;
> > > > > > if (!_dpu_rm_check_lm_and_get_connected_blks(rm, global_state,
> > > > > > - enc_id, i, &pp_idx[lm_count],
> > > > > > + crtc_id, i, &pp_idx[lm_count],
> > > > > > &dspp_idx[lm_count], topology)) {
> > > > > > continue;
> > > > > > }
> > > > > > @@ -329,7 +329,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > > > continue;
> > > > > > if (!_dpu_rm_check_lm_and_get_connected_blks(rm,
> > > > > > - global_state, enc_id, j,
> > > > > > + global_state, crtc_id, j,
> > > > > > &pp_idx[lm_count], &dspp_idx[lm_count],
> > > > > > topology)) {
> > > > > > continue;
> > > > > > @@ -346,12 +346,12 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > > > }
> > > > > > for (i = 0; i < lm_count; i++) {
> > > > > > - global_state->mixer_to_enc_id[lm_idx[i]] = enc_id;
> > > > > > - global_state->pingpong_to_enc_id[pp_idx[i]] = enc_id;
> > > > > > - global_state->dspp_to_enc_id[dspp_idx[i]] =
> > > > > > - topology->num_dspp ? enc_id : 0;
> > > > > > + global_state->mixer_to_crtc_id[lm_idx[i]] = crtc_id;
> > > > > > + global_state->pingpong_to_crtc_id[pp_idx[i]] = crtc_id;
> > > > > > + global_state->dspp_to_crtc_id[dspp_idx[i]] =
> > > > > > + topology->num_dspp ? crtc_id : 0;
> > > > > > - trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, enc_id,
> > > > > > + trace_dpu_rm_reserve_lms(lm_idx[i] + LM_0, crtc_id,
> > > > > > pp_idx[i] + PINGPONG_0);
> > > > > > }
> > > > > > @@ -361,7 +361,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm,
> > > > > > static int _dpu_rm_reserve_ctls(
> > > > > > struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - uint32_t enc_id,
> > > > > > + uint32_t crtc_id,
> > > > > > const struct msm_display_topology *top)
> > > > > > {
> > > > > > int ctl_idx[MAX_BLOCKS];
> > > > > > @@ -380,7 +380,7 @@ static int _dpu_rm_reserve_ctls(
> > > > > > if (!rm->ctl_blks[j])
> > > > > > continue;
> > > > > > - if (reserved_by_other(global_state->ctl_to_enc_id, j, enc_id))
> > > > > > + if (reserved_by_other(global_state->ctl_to_crtc_id, j, crtc_id))
> > > > > > continue;
> > > > > > ctl = to_dpu_hw_ctl(rm->ctl_blks[j]);
> > > > > > @@ -404,8 +404,8 @@ static int _dpu_rm_reserve_ctls(
> > > > > > return -ENAVAIL;
> > > > > > for (i = 0; i < ARRAY_SIZE(ctl_idx) && i < num_ctls; i++) {
> > > > > > - global_state->ctl_to_enc_id[ctl_idx[i]] = enc_id;
> > > > > > - trace_dpu_rm_reserve_ctls(i + CTL_0, enc_id);
> > > > > > + global_state->ctl_to_crtc_id[ctl_idx[i]] = crtc_id;
> > > > > > + trace_dpu_rm_reserve_ctls(i + CTL_0, crtc_id);
> > > > > > }
> > > > > > return 0;
> > > > > > @@ -413,12 +413,12 @@ static int _dpu_rm_reserve_ctls(
> > > > > > static int _dpu_rm_pingpong_next_index(struct dpu_global_state *global_state,
> > > > > > int start,
> > > > > > - uint32_t enc_id)
> > > > > > + uint32_t crtc_id)
> > > > > > {
> > > > > > int i;
> > > > > > for (i = start; i < (PINGPONG_MAX - PINGPONG_0); i++) {
> > > > > > - if (global_state->pingpong_to_enc_id[i] == enc_id)
> > > > > > + if (global_state->pingpong_to_crtc_id[i] == crtc_id)
> > > > > > return i;
> > > > > > }
> > > > > > @@ -439,7 +439,7 @@ static int _dpu_rm_pingpong_dsc_check(int dsc_idx, int pp_idx)
> > > > > > static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - uint32_t enc_id,
> > > > > > + uint32_t crtc_id,
> > > > > > const struct msm_display_topology *top)
> > > > > > {
> > > > > > int num_dsc = 0;
> > > > > > @@ -452,10 +452,10 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > > > if (!rm->dsc_blks[dsc_idx])
> > > > > > continue;
> > > > > > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id))
> > > > > > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id))
> > > > > > continue;
> > > > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > > > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > > > > > if (pp_idx < 0)
> > > > > > return -ENAVAIL;
> > > > > > @@ -463,7 +463,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > > > if (ret)
> > > > > > return -ENAVAIL;
> > > > > > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > > > > > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > > > > > num_dsc++;
> > > > > > pp_idx++;
> > > > > > }
> > > > > > @@ -479,7 +479,7 @@ static int _dpu_rm_dsc_alloc(struct dpu_rm *rm,
> > > > > > static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - uint32_t enc_id,
> > > > > > + uint32_t crtc_id,
> > > > > > const struct msm_display_topology *top)
> > > > > > {
> > > > > > int num_dsc = 0;
> > > > > > @@ -494,11 +494,11 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > > > continue;
> > > > > > /* consective dsc index to be paired */
> > > > > > - if (reserved_by_other(global_state->dsc_to_enc_id, dsc_idx, enc_id) ||
> > > > > > - reserved_by_other(global_state->dsc_to_enc_id, dsc_idx + 1, enc_id))
> > > > > > + if (reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx, crtc_id) ||
> > > > > > + reserved_by_other(global_state->dsc_to_crtc_id, dsc_idx + 1, crtc_id))
> > > > > > continue;
> > > > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, enc_id);
> > > > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx, crtc_id);
> > > > > > if (pp_idx < 0)
> > > > > > return -ENAVAIL;
> > > > > > @@ -508,7 +508,7 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > > > continue;
> > > > > > }
> > > > > > - pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, enc_id);
> > > > > > + pp_idx = _dpu_rm_pingpong_next_index(global_state, pp_idx + 1, crtc_id);
> > > > > > if (pp_idx < 0)
> > > > > > return -ENAVAIL;
> > > > > > @@ -518,8 +518,8 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > > > continue;
> > > > > > }
> > > > > > - global_state->dsc_to_enc_id[dsc_idx] = enc_id;
> > > > > > - global_state->dsc_to_enc_id[dsc_idx + 1] = enc_id;
> > > > > > + global_state->dsc_to_crtc_id[dsc_idx] = crtc_id;
> > > > > > + global_state->dsc_to_crtc_id[dsc_idx + 1] = crtc_id;
> > > > > > num_dsc += 2;
> > > > > > pp_idx++; /* start for next pair */
> > > > > > }
> > > > > > @@ -535,11 +535,9 @@ static int _dpu_rm_dsc_alloc_pair(struct dpu_rm *rm,
> > > > > > static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc,
> > > > > > + uint32_t crtc_id,
> > > > > > const struct msm_display_topology *top)
> > > > > > {
> > > > > > - uint32_t enc_id = enc->base.id;
> > > > > > -
> > > > > > if (!top->num_dsc || !top->num_intf)
> > > > > > return 0;
> > > > > > @@ -555,16 +553,16 @@ static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
> > > > > > /* num_dsc should be either 1, 2 or 4 */
> > > > > > if (top->num_dsc > top->num_intf) /* merge mode */
> > > > > > - return _dpu_rm_dsc_alloc_pair(rm, global_state, enc_id, top);
> > > > > > + return _dpu_rm_dsc_alloc_pair(rm, global_state, crtc_id, top);
> > > > > > else
> > > > > > - return _dpu_rm_dsc_alloc(rm, global_state, enc_id, top);
> > > > > > + return _dpu_rm_dsc_alloc(rm, global_state, crtc_id, top);
> > > > > > return 0;
> > > > > > }
> > > > > > static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc)
> > > > > > + uint32_t crtc_id)
> > > > > > {
> > > > > > /* try allocating only one CDM block */
> > > > > > if (!rm->cdm_blk) {
> > > > > > @@ -572,12 +570,12 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > > > return -EIO;
> > > > > > }
> > > > > > - if (global_state->cdm_to_enc_id) {
> > > > > > + if (global_state->cdm_to_crtc_id) {
> > > > > > DPU_ERROR("CDM_0 is already allocated\n");
> > > > > > return -EIO;
> > > > > > }
> > > > > > - global_state->cdm_to_enc_id = enc->base.id;
> > > > > > + global_state->cdm_to_crtc_id = crtc_id;
> > > > > > return 0;
> > > > > > }
> > > > > > @@ -585,30 +583,31 @@ static int _dpu_rm_reserve_cdm(struct dpu_rm *rm,
> > > > > > static int _dpu_rm_make_reservation(
> > > > > > struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc,
> > > > > > + uint32_t crtc_id,
> > > > > > struct msm_display_topology *topology)
> > > > > > {
> > > > > > int ret;
> > > > > > - ret = _dpu_rm_reserve_lms(rm, global_state, enc->base.id, topology);
> > > > > > + ret = _dpu_rm_reserve_lms(rm, global_state, crtc_id, topology);
> > > > > > if (ret) {
> > > > > > DPU_ERROR("unable to find appropriate mixers\n");
> > > > > > return ret;
> > > > > > }
> > > > > > - ret = _dpu_rm_reserve_ctls(rm, global_state, enc->base.id,
> > > > > > +
> > > > > > + ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> > > > > > topology);
> > > > > > if (ret) {
> > > > > > DPU_ERROR("unable to find appropriate CTL\n");
> > > > > > return ret;
> > > > > > }
> > > > > > - ret = _dpu_rm_reserve_dsc(rm, global_state, enc, topology);
> > > > > > + ret = _dpu_rm_reserve_dsc(rm, global_state, crtc_id, topology);
> > > > > > if (ret)
> > > > > > return ret;
> > > > > > if (topology->needs_cdm) {
> > > > > > - ret = _dpu_rm_reserve_cdm(rm, global_state, enc);
> > > > > > + ret = _dpu_rm_reserve_cdm(rm, global_state, crtc_id);
> > > > > > if (ret) {
> > > > > > DPU_ERROR("unable to find CDM blk\n");
> > > > > > return ret;
> > > > > > @@ -619,12 +618,12 @@ static int _dpu_rm_make_reservation(
> > > > > > }
> > > > > > static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > > > > > - uint32_t enc_id)
> > > > > > + uint32_t crtc_id)
> > > > > > {
> > > > > > int i;
> > > > > > for (i = 0; i < cnt; i++) {
> > > > > > - if (res_mapping[i] == enc_id)
> > > > > > + if (res_mapping[i] == crtc_id)
> > > > > > res_mapping[i] = 0;
> > > > > > }
> > > > > > }
> > > > > > @@ -633,23 +632,25 @@ static void _dpu_rm_clear_mapping(uint32_t *res_mapping, int cnt,
> > > > > > * dpu_rm_release - Given the encoder for the display chain, release any
> > > > > > * HW blocks previously reserved for that use case.
> > > > > > * @global_state: resources shared across multiple kms objects
> > > > > > - * @enc: DRM Encoder handle
> > > > > > + * @crtc: DRM CRTC handle
> > > > > > * @return: 0 on Success otherwise -ERROR
> > > > > > */
> > > > > > void dpu_rm_release(struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc)
> > > > > > + struct drm_crtc *crtc)
> > > > > > {
> > > > > > - _dpu_rm_clear_mapping(global_state->pingpong_to_enc_id,
> > > > > > - ARRAY_SIZE(global_state->pingpong_to_enc_id), enc->base.id);
> > > > > > - _dpu_rm_clear_mapping(global_state->mixer_to_enc_id,
> > > > > > - ARRAY_SIZE(global_state->mixer_to_enc_id), enc->base.id);
> > > > > > - _dpu_rm_clear_mapping(global_state->ctl_to_enc_id,
> > > > > > - ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
> > > > > > - _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
> > > > > > - ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
> > > > > > - _dpu_rm_clear_mapping(global_state->dspp_to_enc_id,
> > > > > > - ARRAY_SIZE(global_state->dspp_to_enc_id), enc->base.id);
> > > > > > - _dpu_rm_clear_mapping(&global_state->cdm_to_enc_id, 1, enc->base.id);
> > > > > > + uint32_t crtc_id = crtc->base.id;
> > > > > > +
> > > > > > + _dpu_rm_clear_mapping(global_state->pingpong_to_crtc_id,
> > > > > > + ARRAY_SIZE(global_state->pingpong_to_crtc_id), crtc_id);
> > > > > > + _dpu_rm_clear_mapping(global_state->mixer_to_crtc_id,
> > > > > > + ARRAY_SIZE(global_state->mixer_to_crtc_id), crtc_id);
> > > > > > + _dpu_rm_clear_mapping(global_state->ctl_to_crtc_id,
> > > > > > + ARRAY_SIZE(global_state->ctl_to_crtc_id), crtc_id);
> > > > > > + _dpu_rm_clear_mapping(global_state->dsc_to_crtc_id,
> > > > > > + ARRAY_SIZE(global_state->dsc_to_crtc_id), crtc_id);
> > > > > > + _dpu_rm_clear_mapping(global_state->dspp_to_crtc_id,
> > > > > > + ARRAY_SIZE(global_state->dspp_to_crtc_id), crtc_id);
> > > > > > + _dpu_rm_clear_mapping(&global_state->cdm_to_crtc_id, 1, crtc_id);
> > > > > > }
> > > > > > /**
> > > > > > @@ -661,42 +662,33 @@ void dpu_rm_release(struct dpu_global_state *global_state,
> > > > > > * HW Reservations should be released via dpu_rm_release_hw.
> > > > > > * @rm: DPU Resource Manager handle
> > > > > > * @global_state: resources shared across multiple kms objects
> > > > > > - * @enc: DRM Encoder handle
> > > > > > - * @crtc_state: Proposed Atomic DRM CRTC State handle
> > > > > > + * @crtc: DRM CRTC handle
> > > > > > * @topology: Pointer to topology info for the display
> > > > > > * @return: 0 on Success otherwise -ERROR
> > > > > > */
> > > > > > int dpu_rm_reserve(
> > > > > > struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc,
> > > > > > - struct drm_crtc_state *crtc_state,
> > > > > > + struct drm_crtc *crtc,
> > > > > > struct msm_display_topology *topology)
> > > > > > {
> > > > > > int ret;
> > > > > > - /* Check if this is just a page-flip */
> > > > > > - if (!drm_atomic_crtc_needs_modeset(crtc_state))
> > > > > > - return 0;
> > > > > > -
> > > > > > if (IS_ERR(global_state)) {
> > > > > > DPU_ERROR("failed to global state\n");
> > > > > > return PTR_ERR(global_state);
> > > > > > }
> > > > > > - DRM_DEBUG_KMS("reserving hw for enc %d crtc %d\n",
> > > > > > - enc->base.id, crtc_state->crtc->base.id);
> > > > > > + DRM_DEBUG_KMS("reserving hw for crtc %d\n", crtc->base.id);
> > > > > > DRM_DEBUG_KMS("num_lm: %d num_dsc: %d num_intf: %d\n",
> > > > > > topology->num_lm, topology->num_dsc,
> > > > > > topology->num_intf);
> > > > > > - ret = _dpu_rm_make_reservation(rm, global_state, enc, topology);
> > > > > > + ret = _dpu_rm_make_reservation(rm, global_state, crtc->base.id, topology);
> > > > > > if (ret)
> > > > > > DPU_ERROR("failed to reserve hw resources: %d\n", ret);
> > > > > > -
> > > > > > -
> > > > > > return ret;
> > > > > > }
> > > > > > @@ -705,48 +697,49 @@ int dpu_rm_reserve(
> > > > > > * assigned to this encoder
> > > > > > * @rm: DPU Resource Manager handle
> > > > > > * @global_state: resources shared across multiple kms objects
> > > > > > - * @enc_id: encoder id requesting for allocation
> > > > > > + * @crtc: DRM CRTC handle
> > > > > > * @type: resource type to return data for
> > > > > > * @blks: pointer to the array to be filled by HW resources
> > > > > > * @blks_size: size of the @blks array
> > > > > > */
> > > > > > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > > > - struct dpu_global_state *global_state, uint32_t enc_id,
> > > > > > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > > > > > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size)
> > > > > > {
> > > > > > + uint32_t crtc_id = crtc->base.id;
> > > > > > struct dpu_hw_blk **hw_blks;
> > > > > > - uint32_t *hw_to_enc_id;
> > > > > > + uint32_t *hw_to_crtc_id;
> > > > > > int i, num_blks, max_blks;
> > > > > > switch (type) {
> > > > > > case DPU_HW_BLK_PINGPONG:
> > > > > > hw_blks = rm->pingpong_blks;
> > > > > > - hw_to_enc_id = global_state->pingpong_to_enc_id;
> > > > > > + hw_to_crtc_id = global_state->pingpong_to_crtc_id;
> > > > > > max_blks = ARRAY_SIZE(rm->pingpong_blks);
> > > > > > break;
> > > > > > case DPU_HW_BLK_LM:
> > > > > > hw_blks = rm->mixer_blks;
> > > > > > - hw_to_enc_id = global_state->mixer_to_enc_id;
> > > > > > + hw_to_crtc_id = global_state->mixer_to_crtc_id;
> > > > > > max_blks = ARRAY_SIZE(rm->mixer_blks);
> > > > > > break;
> > > > > > case DPU_HW_BLK_CTL:
> > > > > > hw_blks = rm->ctl_blks;
> > > > > > - hw_to_enc_id = global_state->ctl_to_enc_id;
> > > > > > + hw_to_crtc_id = global_state->ctl_to_crtc_id;
> > > > > > max_blks = ARRAY_SIZE(rm->ctl_blks);
> > > > > > break;
> > > > > > case DPU_HW_BLK_DSPP:
> > > > > > hw_blks = rm->dspp_blks;
> > > > > > - hw_to_enc_id = global_state->dspp_to_enc_id;
> > > > > > + hw_to_crtc_id = global_state->dspp_to_crtc_id;
> > > > > > max_blks = ARRAY_SIZE(rm->dspp_blks);
> > > > > > break;
> > > > > > case DPU_HW_BLK_DSC:
> > > > > > hw_blks = rm->dsc_blks;
> > > > > > - hw_to_enc_id = global_state->dsc_to_enc_id;
> > > > > > + hw_to_crtc_id = global_state->dsc_to_crtc_id;
> > > > > > max_blks = ARRAY_SIZE(rm->dsc_blks);
> > > > > > break;
> > > > > > case DPU_HW_BLK_CDM:
> > > > > > hw_blks = &rm->cdm_blk;
> > > > > > - hw_to_enc_id = &global_state->cdm_to_enc_id;
> > > > > > + hw_to_crtc_id = &global_state->cdm_to_crtc_id;
> > > > > > max_blks = 1;
> > > > > > break;
> > > > > > default:
> > > > > > @@ -756,17 +749,17 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > > > num_blks = 0;
> > > > > > for (i = 0; i < max_blks; i++) {
> > > > > > - if (hw_to_enc_id[i] != enc_id)
> > > > > > + if (hw_to_crtc_id[i] != crtc_id)
> > > > > > continue;
> > > > > > if (num_blks == blks_size) {
> > > > > > - DPU_ERROR("More than %d resources assigned to enc %d\n",
> > > > > > - blks_size, enc_id);
> > > > > > + DPU_ERROR("More than %d resources assigned to crtc %d\n",
> > > > > > + blks_size, crtc_id);
> > > > > > break;
> > > > > > }
> > > > > > if (!hw_blks[i]) {
> > > > > > - DPU_ERROR("Allocated resource %d unavailable to assign to enc %d\n",
> > > > > > - type, enc_id);
> > > > > > + DPU_ERROR("Allocated resource %d unavailable to assign to crtc %d\n",
> > > > > > + type, crtc_id);
> > > > > > break;
> > > > > > }
> > > > > > blks[num_blks++] = hw_blks[i];
> > > > > > @@ -801,37 +794,37 @@ void dpu_rm_print_state(struct drm_printer *p,
> > > > > > drm_puts(p, "resource mapping:\n");
> > > > > > drm_puts(p, "\tpingpong=");
> > > > > > - for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_enc_id); i++)
> > > > > > + for (i = 0; i < ARRAY_SIZE(global_state->pingpong_to_crtc_id); i++)
> > > > > > dpu_rm_print_state_helper(p, rm->pingpong_blks[i],
> > > > > > - global_state->pingpong_to_enc_id[i]);
> > > > > > + global_state->pingpong_to_crtc_id[i]);
> > > > > > drm_puts(p, "\n");
> > > > > > drm_puts(p, "\tmixer=");
> > > > > > - for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_enc_id); i++)
> > > > > > + for (i = 0; i < ARRAY_SIZE(global_state->mixer_to_crtc_id); i++)
> > > > > > dpu_rm_print_state_helper(p, rm->mixer_blks[i],
> > > > > > - global_state->mixer_to_enc_id[i]);
> > > > > > + global_state->mixer_to_crtc_id[i]);
> > > > > > drm_puts(p, "\n");
> > > > > > drm_puts(p, "\tctl=");
> > > > > > - for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_enc_id); i++)
> > > > > > + for (i = 0; i < ARRAY_SIZE(global_state->ctl_to_crtc_id); i++)
> > > > > > dpu_rm_print_state_helper(p, rm->ctl_blks[i],
> > > > > > - global_state->ctl_to_enc_id[i]);
> > > > > > + global_state->ctl_to_crtc_id[i]);
> > > > > > drm_puts(p, "\n");
> > > > > > drm_puts(p, "\tdspp=");
> > > > > > - for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_enc_id); i++)
> > > > > > + for (i = 0; i < ARRAY_SIZE(global_state->dspp_to_crtc_id); i++)
> > > > > > dpu_rm_print_state_helper(p, rm->dspp_blks[i],
> > > > > > - global_state->dspp_to_enc_id[i]);
> > > > > > + global_state->dspp_to_crtc_id[i]);
> > > > > > drm_puts(p, "\n");
> > > > > > drm_puts(p, "\tdsc=");
> > > > > > - for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_enc_id); i++)
> > > > > > + for (i = 0; i < ARRAY_SIZE(global_state->dsc_to_crtc_id); i++)
> > > > > > dpu_rm_print_state_helper(p, rm->dsc_blks[i],
> > > > > > - global_state->dsc_to_enc_id[i]);
> > > > > > + global_state->dsc_to_crtc_id[i]);
> > > > > > drm_puts(p, "\n");
> > > > > > drm_puts(p, "\tcdm=");
> > > > > > dpu_rm_print_state_helper(p, rm->cdm_blk,
> > > > > > - global_state->cdm_to_enc_id);
> > > > > > + global_state->cdm_to_crtc_id);
> > > > > > drm_puts(p, "\n");
> > > > > > }
> > > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > index 2240275080c4e97e91f52eae329a3457ec2bc538..893344bf1141046a45f32a1834f857a56aa2b9b6 100644
> > > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
> > > > > > @@ -61,15 +61,14 @@ int dpu_rm_init(struct drm_device *dev,
> > > > > > int dpu_rm_reserve(struct dpu_rm *rm,
> > > > > > struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *drm_enc,
> > > > > > - struct drm_crtc_state *crtc_state,
> > > > > > + struct drm_crtc *crtc,
> > > > > > struct msm_display_topology *topology);
> > > > > > void dpu_rm_release(struct dpu_global_state *global_state,
> > > > > > - struct drm_encoder *enc);
> > > > > > + struct drm_crtc *crtc);
> > > > > > int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
> > > > > > - struct dpu_global_state *global_state, uint32_t enc_id,
> > > > > > + struct dpu_global_state *global_state, struct drm_crtc *crtc,
> > > > > > enum dpu_hw_blk_type type, struct dpu_hw_blk **blks, int blks_size);
> > > > > > void dpu_rm_print_state(struct drm_printer *p,
> > > > > >
> > > > > > --
> > > > > > 2.34.1
> > > > > >
> > > > >
> > > > > --
> > > > > With best wishes
> > > > > Dmitry
> > > >
> > > > --
> > > > With best wishes
> > > > Dmitry
> > >
> >
> > --
> > With best wishes
> > Dmitry
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 77+ messages in thread
end of thread, other threads:[~2025-01-16 7:32 UTC | newest]
Thread overview: 77+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-17 0:43 [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 01/25] drm: add clone mode check for CRTC Jessica Zhang
2024-12-17 1:49 ` Abhinav Kumar
2024-12-17 17:16 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 02/25] drm/tests: Add test for drm_crtc_in_clone_mode() Jessica Zhang
2024-12-17 2:06 ` Abhinav Kumar
2024-12-17 17:17 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 03/25] drm: Add valid clones check Jessica Zhang
2024-12-17 17:17 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 04/25] drm/tests: Add test for drm_atomic_helper_check_modeset() Jessica Zhang
2024-12-17 12:14 ` Maxime Ripard
2024-12-17 0:43 ` [PATCH v4 05/25] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
2024-12-17 1:26 ` Dmitry Baryshkov
2024-12-17 2:11 ` Abhinav Kumar
2024-12-17 0:43 ` [PATCH v4 06/25] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
2024-12-24 4:45 ` Dmitry Baryshkov
2024-12-24 20:00 ` Dmitry Baryshkov
2025-01-15 5:28 ` Jessica Zhang
2025-01-15 9:56 ` Dmitry Baryshkov
2025-01-16 4:13 ` Jessica Zhang
2025-01-16 7:32 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 07/25] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
2024-12-17 1:47 ` Abhinav Kumar
2024-12-20 2:32 ` Dmitry Baryshkov
2024-12-20 2:50 ` Dmitry Baryshkov
2024-12-24 5:02 ` Dmitry Baryshkov
2024-12-26 18:14 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 08/25] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
2024-12-17 1:39 ` Abhinav Kumar
2024-12-20 2:40 ` Dmitry Baryshkov
2024-12-20 2:52 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 09/25] drm/msm/dpu: Add CWB entry to catalog for SM8650 Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 10/25] drm/msm/dpu: Specify dedicated CWB pingpong blocks Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 11/25] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 12/25] drm/msm/dpu: Add dpu_hw_cwb abstraction for CWB block Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 13/25] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 14/25] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 15/25] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
2024-12-20 5:03 ` Dmitry Baryshkov
2025-01-03 18:03 ` Jessica Zhang
2025-01-03 18:16 ` Dmitry Baryshkov
2025-01-09 22:34 ` Jessica Zhang
2025-01-10 0:00 ` Dmitry Baryshkov
2025-01-10 0:30 ` Jessica Zhang
2025-01-10 1:42 ` Dmitry Baryshkov
2025-01-10 1:50 ` Jessica Zhang
2025-01-10 2:10 ` Dmitry Baryshkov
2025-01-10 22:08 ` Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 16/25] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
2024-12-20 5:41 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 17/25] drm/msm/dpu: Fail atomic_check if CWB and CDM are enabled Jessica Zhang
2024-12-20 5:44 ` Dmitry Baryshkov
2024-12-26 22:51 ` Jessica Zhang
2024-12-30 23:59 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 18/25] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
2024-12-20 5:52 ` Dmitry Baryshkov
2024-12-21 0:12 ` Jessica Zhang
2024-12-21 1:07 ` Dmitry Baryshkov
2024-12-26 22:49 ` Jessica Zhang
2024-12-29 4:47 ` Dmitry Baryshkov
2025-01-09 21:26 ` Jessica Zhang
2025-01-09 22:13 ` Dmitry Baryshkov
2025-01-09 22:53 ` Jessica Zhang
2025-01-10 0:02 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 19/25] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
2024-12-20 5:55 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 20/25] drm/msm/dpu: Support CWB in dpu_hw_ctl Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 21/25] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 22/25] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 23/25] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
2024-12-17 0:43 ` [PATCH v4 24/25] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
2024-12-20 6:00 ` Dmitry Baryshkov
2024-12-17 0:43 ` [PATCH v4 25/25] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
2024-12-20 5:11 ` [PATCH v4 00/25] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Dmitry Baryshkov
2024-12-20 18:46 ` Jessica Zhang
2024-12-24 20:41 ` Dmitry Baryshkov
2025-01-07 23:50 ` (subset) " Dmitry Baryshkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).