* [PATCH 01/21] drm: add clone mode check for CRTC
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-29 20:48 ` [PATCH 02/21] drm: print clone mode status in atomic state Jessica Zhang
` (19 subsequent siblings)
20 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Add helper to check if the given CRTC state is in clone mode
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
include/drm/drm_crtc.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 8b48a1974da3..ecb93e2c4afc 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1323,5 +1323,12 @@ 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);
+static inline bool drm_crtc_in_clone_mode(struct drm_crtc_state *crtc_state)
+{
+ if (!crtc_state)
+ return false;
+
+ return hweight32(crtc_state->encoder_mask) > 1;
+}
#endif /* __DRM_CRTC_H__ */
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* [PATCH 02/21] drm: print clone mode status in atomic state
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
2024-08-29 20:48 ` [PATCH 01/21] drm: add clone mode check for CRTC Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 16:38 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 03/21] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
` (18 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Add clone mode status to the DRM atomic print state
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/drm_atomic.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index 07b4b394e3bf..145d6a758d4d 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -455,6 +455,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
+ drm_printf(p, "\tin_clone_mode=%d\n", drm_crtc_in_clone_mode(crtc->state));
if (crtc->funcs->atomic_print_state)
crtc->funcs->atomic_print_state(p, state);
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 02/21] drm: print clone mode status in atomic state
2024-08-29 20:48 ` [PATCH 02/21] drm: print clone mode status in atomic state Jessica Zhang
@ 2024-08-30 16:38 ` Dmitry Baryshkov
2024-08-30 19:42 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 16:38 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:23PM GMT, Jessica Zhang wrote:
> Add clone mode status to the DRM atomic print state
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/drm_atomic.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
> index 07b4b394e3bf..145d6a758d4d 100644
> --- a/drivers/gpu/drm/drm_atomic.c
> +++ b/drivers/gpu/drm/drm_atomic.c
> @@ -455,6 +455,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
> drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
> drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
> drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
> + drm_printf(p, "\tin_clone_mode=%d\n", drm_crtc_in_clone_mode(crtc->state));
We have encoder_mask two lines above. What is the benefit of having the
separate in_clone_mode?
>
> if (crtc->funcs->atomic_print_state)
> crtc->funcs->atomic_print_state(p, state);
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [PATCH 02/21] drm: print clone mode status in atomic state
2024-08-30 16:38 ` Dmitry Baryshkov
@ 2024-08-30 19:42 ` Jessica Zhang
0 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-30 19:42 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 9:38 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:23PM GMT, Jessica Zhang wrote:
>> Add clone mode status to the DRM atomic print state
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/drm_atomic.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
>> index 07b4b394e3bf..145d6a758d4d 100644
>> --- a/drivers/gpu/drm/drm_atomic.c
>> +++ b/drivers/gpu/drm/drm_atomic.c
>> @@ -455,6 +455,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
>> drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
>> drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
>> drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
>> + drm_printf(p, "\tin_clone_mode=%d\n", drm_crtc_in_clone_mode(crtc->state));
>
> We have encoder_mask two lines above. What is the benefit of having the
> separate in_clone_mode?
Hi Dmitry,
I was thinking that this would be an easy way to note if a CRTC was in
clone mode, but I can see why this is redundant.
Will drop this patch.
Thanks,
Jessica Zhang
>
>>
>> if (crtc->funcs->atomic_print_state)
>> crtc->funcs->atomic_print_state(p, state);
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 03/21] drm/msm/dpu: get rid of struct dpu_rm_requirements
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
2024-08-29 20:48 ` [PATCH 01/21] drm: add clone mode check for CRTC Jessica Zhang
2024-08-29 20:48 ` [PATCH 02/21] drm: print clone mode status in atomic state Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-29 20:48 ` [PATCH 04/21] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
` (17 subsequent siblings)
20 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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 3b171bf227d1..6293e716a1c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -691,7 +691,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);
}
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 44938ba7a2b7..8193c3d579df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -4,6 +4,7 @@
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include "msm_drv.h"
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
#include "dpu_kms.h"
#include "dpu_hw_lm.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;
-};
-
int dpu_rm_init(struct drm_device *dev,
struct dpu_rm *rm,
const struct dpu_mdss_cfg *cat,
@@ -231,14 +224,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;
@@ -263,7 +255,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;
@@ -285,7 +277,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];
@@ -293,14 +285,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;
@@ -309,14 +301,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 */
@@ -329,7 +321,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;
}
@@ -338,7 +330,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;
}
@@ -347,7 +339,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);
@@ -584,28 +576,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");
@@ -616,20 +608,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)
{
@@ -662,9 +640,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 */
@@ -679,13 +656,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 e63db8ace6b9..62cc2edd2ee0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -70,7 +70,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);
/**
* dpu_rm_reserve - Given the encoder for the display chain, release any
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* [PATCH 04/21] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (2 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 03/21] drm/msm/dpu: get rid of struct dpu_rm_requirements Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-29 20:48 ` [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
` (16 subsequent siblings)
20 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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.
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 | 18 +--
drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 12 +-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 182 ++++++++++++++--------------
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 12 +-
4 files changed, 108 insertions(+), 116 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 6293e716a1c3..4a9edcfbcaae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -687,11 +687,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);
}
trace_dpu_enc_atomic_check_flags(DRMID(drm_enc), adj_mode->flags);
@@ -1125,14 +1125,14 @@ 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));
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));
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 < MAX_CHANNELS_PER_ENC; i++)
@@ -1140,7 +1140,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
: 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]);
@@ -1154,7 +1154,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;
}
@@ -2021,7 +2021,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 935ff6fd172c..4fdc5f933261 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 8193c3d579df..bc99b04eae3a 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;
}
int dpu_rm_init(struct drm_device *dev,
@@ -216,7 +216,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: encoder 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
@@ -229,14 +229,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;
}
@@ -248,7 +248,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;
@@ -264,7 +264,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;
@@ -276,7 +276,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)
{
@@ -300,7 +300,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;
}
@@ -319,7 +319,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;
@@ -336,12 +336,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);
}
@@ -351,7 +351,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];
@@ -370,7 +370,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]);
@@ -394,8 +394,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;
@@ -403,12 +403,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;
}
@@ -429,7 +429,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;
@@ -442,10 +442,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;
@@ -453,7 +453,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++;
}
@@ -469,7 +469,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;
@@ -484,11 +484,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;
@@ -498,7 +498,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;
@@ -508,8 +508,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 */
}
@@ -525,11 +525,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;
@@ -545,16 +543,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) {
@@ -562,12 +560,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;
}
@@ -575,30 +573,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;
@@ -609,103 +608,98 @@ 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;
}
}
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);
}
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;
}
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:
@@ -715,17 +709,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];
@@ -755,37 +749,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 62cc2edd2ee0..36a0b6ed628d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -61,32 +61,30 @@ int dpu_rm_init(struct drm_device *dev,
* HW blocks can then be accessed through dpu_rm_get_* functions.
* HW Reservations should be released via dpu_rm_release_hw.
* @rm: DPU Resource Manager handle
- * @drm_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 *drm_enc,
- struct drm_crtc_state *crtc_state,
+ struct drm_crtc *crtc,
struct msm_display_topology *topology);
/**
* dpu_rm_reserve - Given the encoder for the display chain, release any
* HW blocks previously reserved for that use case.
* @rm: DPU Resource Manager handle
- * @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);
/**
* Get hw resources of the given type that are assigned to this encoder.
*/
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);
/**
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (3 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 04/21] drm/msm/dpu: switch RM to use crtc_id rather than enc_id for allocation Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 16:42 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 06/21] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
` (15 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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 and
dropped clearing num_mixers in crtc_disable]
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 89 +++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 201 +++++++++++-----------------
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 19 +++
3 files changed, 183 insertions(+), 126 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 4c1be2f0555f..3296b0650056 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1091,9 +1091,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
dpu_core_perf_crtc_update(crtc, 0);
- memset(cstate->mixers, 0, sizeof(cstate->mixers));
- cstate->num_mixers = 0;
-
/* disable clk & bw control until clk & bw properties are set */
cstate->bw_control = false;
cstate->bw_split_vote = false;
@@ -1163,6 +1160,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)
{
@@ -1174,10 +1243,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 4a9edcfbcaae..ada9119326ca 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
@@ -544,159 +542,117 @@ void dpu_encoder_helper_split_config(
}
}
-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;
+ topology->num_dsc += 2;
- return (num_dsc > 0) && (num_dsc > intf_count);
-}
+ 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;
-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];
+ disp_info = &dpu_enc->disp_info;
- if (dpu_enc->disp_info.intf_type == INTF_DSI)
- return msm_dsi_get_dsc_config(priv->dsi[index]);
+ priv = drm_enc->dev->dev_private;
- return NULL;
+ /*
+ * 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) {
+ 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;
+ }
}
-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)
+static bool dpu_encoder_needs_dsc_merge(struct drm_encoder *drm_enc)
{
- struct msm_display_topology topology = {0};
- int i, intf_count = 0;
+ 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 < 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
- */
- 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;
+ num_intf++;
- 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;
- }
+ /* We only support 2 DSC mode (with 2 LM and 1 INTF) */
+ if (dpu_enc->dsc)
+ num_dsc += 2;
- return topology;
+ 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);
- }
+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;
+}
+
+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,
@@ -2449,7 +2405,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 f7465a1774aa..0d27e50384f0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -169,6 +169,25 @@ 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);
+/**
+ * dpu_encoder_update_topology - update topology with the requirements for the encoder
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @topology: Topology to be updated
+ * @state: Current DRM atomic state
+ * @adj_mode: Current DRM display mode associated with the crtc
+ */
+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);
+
+/**
+ * dpu_encoder_update_topology - update topology with the requirements for the encoder
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @topology: Current DRM atomic state
+ */
+bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
+
/**
* dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
* @drm_enc: Pointer to previously created drm encoder structure
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC
2024-08-29 20:48 ` [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
@ 2024-08-30 16:42 ` Dmitry Baryshkov
2024-08-30 17:01 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 16:42 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:26PM GMT, 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 and
> dropped clearing num_mixers in crtc_disable]
Hmm, I still see the chunk in dpu_crtc_disable(). I think the chunk is
correct so that if there is a disable/enable pair of calls with no
intermediate mode_set then num_mixers carry over the correct value.
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 89 +++++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 201 +++++++++++-----------------
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 19 +++
> 3 files changed, 183 insertions(+), 126 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 4c1be2f0555f..3296b0650056 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1091,9 +1091,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
>
> dpu_core_perf_crtc_update(crtc, 0);
>
> - memset(cstate->mixers, 0, sizeof(cstate->mixers));
> - cstate->num_mixers = 0;
> -
> /* disable clk & bw control until clk & bw properties are set */
> cstate->bw_control = false;
> cstate->bw_split_vote = false;
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* Re: [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC
2024-08-30 16:42 ` Dmitry Baryshkov
@ 2024-08-30 17:01 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:01 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Fri, Aug 30, 2024 at 07:42:52PM GMT, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:26PM GMT, 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 and
> > dropped clearing num_mixers in crtc_disable]
>
> Hmm, I still see the chunk in dpu_crtc_disable(). I think the chunk is
> correct so that if there is a disable/enable pair of calls with no
> intermediate mode_set then num_mixers carry over the correct value.
As a second thought: maybe it should be moved to the next patch.
>
> > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > ---
> > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 89 +++++++++++-
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 201 +++++++++++-----------------
> > drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 19 +++
> > 3 files changed, 183 insertions(+), 126 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 4c1be2f0555f..3296b0650056 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -1091,9 +1091,6 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
> >
> > dpu_core_perf_crtc_update(crtc, 0);
> >
> > - memset(cstate->mixers, 0, sizeof(cstate->mixers));
> > - cstate->num_mixers = 0;
> > -
> > /* disable clk & bw control until clk & bw properties are set */
> > cstate->bw_control = false;
> > cstate->bw_split_vote = false;
>
> --
> With best wishes
> Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 06/21] drm/msm/dpu: fill CRTC resources in dpu_crtc.c
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (4 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 05/21] drm/msm/dpu: move resource allocation to CRTC Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-29 20:48 ` [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones Jessica Zhang
` (14 subsequent siblings)
20 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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 | 26 ++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 24 ++----------------------
2 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 3296b0650056..5ec1b5a38922 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1161,6 +1161,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,
@@ -1205,9 +1206,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;
/*
@@ -1229,6 +1235,26 @@ 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 ada9119326ca..36b677cf9c7a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1049,14 +1049,11 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
struct dpu_kms *dpu_kms;
- struct dpu_crtc_state *cstate;
struct dpu_global_state *global_state;
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_lm[MAX_CHANNELS_PER_ENC];
- struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
- int num_lm, num_ctl, num_pp, num_dsc;
+ int num_pp, num_dsc;
unsigned int dsc_mask = 0;
int i;
@@ -1083,13 +1080,8 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
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));
- 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));
dpu_rm_get_assigned_resources(&dpu_kms->rm, global_state,
- drm_enc->crtc, DPU_HW_BLK_DSPP, hw_dspp,
- ARRAY_SIZE(hw_dspp));
+ 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])
@@ -1115,18 +1107,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
dpu_enc->cur_master->hw_cdm = hw_cdm ? to_dpu_hw_cdm(hw_cdm) : NULL;
}
- cstate = to_dpu_crtc_state(crtc_state);
-
- 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]);
- cstate->mixers[i].hw_dspp = to_dpu_hw_dspp(hw_dspp[i]);
- }
-
- cstate->num_mixers = num_lm;
-
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (5 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 06/21] drm/msm/dpu: fill CRTC resources in dpu_crtc.c Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:00 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650 Jessica Zhang
` (13 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Check that each encoder in the CRTC state's encoder_mask is marked as a
possible clone for all other encoders in the encoder_mask and that only
one CRTC is in clone mode at a time
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 36 +++++++++++++++++++++++++++++++-
1 file changed, 35 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 5ec1b5a38922..bebae365c036 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
@@ -1204,6 +1204,36 @@ static struct msm_display_topology dpu_crtc_get_topology(
return topology;
}
+static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ struct drm_encoder *drm_enc;
+ struct drm_crtc *temp_crtc;
+ int num_cwb_sessions = 0;
+
+ drm_for_each_crtc(temp_crtc, crtc->dev)
+ if (drm_crtc_in_clone_mode(temp_crtc->state))
+ num_cwb_sessions++;
+
+ /*
+ * Only support a single concurrent writeback session running
+ * at a time
+ */
+ if (num_cwb_sessions > 1)
+ return false;
+
+ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
+ if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
+ crtc_state->encoder_mask) {
+ DPU_ERROR("crtc%d failed valid clone check for mask 0x%x\n",
+ crtc->base.id, crtc_state->encoder_mask);
+ return false;
+ }
+ }
+
+ return true;
+}
+
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];
@@ -1287,6 +1317,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
return rc;
}
+ if (drm_crtc_in_clone_mode(crtc_state) &&
+ !dpu_crtc_has_valid_clones(crtc, crtc_state))
+ return -EINVAL;
+
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,
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones
2024-08-29 20:48 ` [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones Jessica Zhang
@ 2024-08-30 17:00 ` Dmitry Baryshkov
2024-09-03 22:18 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:00 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:28PM GMT, Jessica Zhang wrote:
> Check that each encoder in the CRTC state's encoder_mask is marked as a
> possible clone for all other encoders in the encoder_mask and that only
> one CRTC is in clone mode at a time
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 36 +++++++++++++++++++++++++++++++-
> 1 file changed, 35 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 5ec1b5a38922..bebae365c036 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
> * Copyright (C) 2013 Red Hat
> * Author: Rob Clark <robdclark@gmail.com>
> @@ -1204,6 +1204,36 @@ static struct msm_display_topology dpu_crtc_get_topology(
> return topology;
> }
>
> +static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
> + struct drm_crtc_state *crtc_state)
> +{
> + struct drm_encoder *drm_enc;
> + struct drm_crtc *temp_crtc;
> + int num_cwb_sessions = 0;
> +
> + drm_for_each_crtc(temp_crtc, crtc->dev)
> + if (drm_crtc_in_clone_mode(temp_crtc->state))
No, get the state from drm_atomic_state. temp_crtc->state might be
irrelevant.
> + num_cwb_sessions++;
Even simpler:
if (temp_crtc != crtc && drm_crtc_in_clone_mode(...))
return false;
> +
> + /*
> + * Only support a single concurrent writeback session running
> + * at a time
If it is not a hardware limitation, please add:
FIXME: support more than one session
> + */
> + if (num_cwb_sessions > 1)
> + return false;
> +
> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
> + if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
> + crtc_state->encoder_mask) {
Align to opening bracket, please. Granted that other drivers don't
perform this check, is it really necessary? Doesn't
validate_encoder_possible_clones() ensure the same, but during the
encoder registration?
> + DPU_ERROR("crtc%d failed valid clone check for mask 0x%x\n",
DPU_DEBUG, don't let users spam dmesg.
> + crtc->base.id, crtc_state->encoder_mask);
> + return false;
> + }
> + }
> +
> + return true;
> +}
> +
> 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];
> @@ -1287,6 +1317,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> return rc;
> }
>
> + if (drm_crtc_in_clone_mode(crtc_state) &&
> + !dpu_crtc_has_valid_clones(crtc, crtc_state))
Align to opening bracket.
> + return -EINVAL;
> +
> 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,
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones
2024-08-30 17:00 ` Dmitry Baryshkov
@ 2024-09-03 22:18 ` Jessica Zhang
2024-09-04 18:41 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-09-03 22:18 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:00 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:28PM GMT, Jessica Zhang wrote:
>> Check that each encoder in the CRTC state's encoder_mask is marked as a
>> possible clone for all other encoders in the encoder_mask and that only
>> one CRTC is in clone mode at a time
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 36 +++++++++++++++++++++++++++++++-
>> 1 file changed, 35 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> index 5ec1b5a38922..bebae365c036 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1,6 +1,6 @@
>> // SPDX-License-Identifier: GPL-2.0-only
>> /*
>> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
>> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
>> * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
>> * Copyright (C) 2013 Red Hat
>> * Author: Rob Clark <robdclark@gmail.com>
>> @@ -1204,6 +1204,36 @@ static struct msm_display_topology dpu_crtc_get_topology(
>> return topology;
>> }
>>
>> +static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
>> + struct drm_crtc_state *crtc_state)
>> +{
>> + struct drm_encoder *drm_enc;
>> + struct drm_crtc *temp_crtc;
>> + int num_cwb_sessions = 0;
>> +
>> + drm_for_each_crtc(temp_crtc, crtc->dev)
>> + if (drm_crtc_in_clone_mode(temp_crtc->state))
>
> No, get the state from drm_atomic_state. temp_crtc->state might be
> irrelevant.
Hi Dmitry,
Ack.
>
>> + num_cwb_sessions++;
>
> Even simpler:
> if (temp_crtc != crtc && drm_crtc_in_clone_mode(...))
> return false;
Ack.
>
>> +
>> + /*
>> + * Only support a single concurrent writeback session running
>> + * at a time
>
> If it is not a hardware limitation, please add:
> FIXME: support more than one session
This is a hardware limitation.
>
>> + */
>> + if (num_cwb_sessions > 1)
>> + return false;
>> +
>> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
>> + if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
>> + crtc_state->encoder_mask) {
>
> Align to opening bracket, please. Granted that other drivers don't
> perform this check, is it really necessary? Doesn't
> validate_encoder_possible_clones() ensure the same, but during the
> encoder registration?
The difference here is that validate_encoder_possible_clones() is only
called when the drm device is initially registered.
The check here is to make sure that the encoders userspace is proposing
to be cloned are actually possible clones of each other. This might not
be necessary for drivers where all encoders are all possible clones of
each other. But for MSM (and CWB), real-time display encoders can only
be clones of writeback (and vice versa).
>
>> + DPU_ERROR("crtc%d failed valid clone check for mask 0x%x\n",
>
> DPU_DEBUG, don't let users spam dmesg.
Ack.
>
>> + crtc->base.id, crtc_state->encoder_mask);
>> + return false;
>> + }
>> + }
>> +
>> + return true;
>> +}
>> +
>> 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];
>> @@ -1287,6 +1317,10 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>> return rc;
>> }
>>
>> + if (drm_crtc_in_clone_mode(crtc_state) &&
>> + !dpu_crtc_has_valid_clones(crtc, crtc_state))
>
> Align to opening bracket.
Ack
Thanks,
Jessica Zhang
>
>> + return -EINVAL;
>> +
>> 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,
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones
2024-09-03 22:18 ` Jessica Zhang
@ 2024-09-04 18:41 ` Dmitry Baryshkov
2024-09-04 19:23 ` Ville Syrjälä
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-09-04 18:41 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Wed, 4 Sept 2024 at 01:18, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 8/30/2024 10:00 AM, Dmitry Baryshkov wrote:
> > On Thu, Aug 29, 2024 at 01:48:28PM GMT, Jessica Zhang wrote:
> >> Check that each encoder in the CRTC state's encoder_mask is marked as a
> >> possible clone for all other encoders in the encoder_mask and that only
> >> one CRTC is in clone mode at a time
> >>
> >> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >> ---
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 36 +++++++++++++++++++++++++++++++-
> >> 1 file changed, 35 insertions(+), 1 deletion(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> index 5ec1b5a38922..bebae365c036 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> @@ -1,6 +1,6 @@
> >> // SPDX-License-Identifier: GPL-2.0-only
> >> /*
> >> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> >> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> >> * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
> >> * Copyright (C) 2013 Red Hat
> >> * Author: Rob Clark <robdclark@gmail.com>
> >> @@ -1204,6 +1204,36 @@ static struct msm_display_topology dpu_crtc_get_topology(
> >> return topology;
> >> }
> >>
> >> +static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
> >> + struct drm_crtc_state *crtc_state)
> >> +{
> >> + struct drm_encoder *drm_enc;
> >> + struct drm_crtc *temp_crtc;
> >> + int num_cwb_sessions = 0;
> >> +
> >> + drm_for_each_crtc(temp_crtc, crtc->dev)
> >> + if (drm_crtc_in_clone_mode(temp_crtc->state))
> >
> > No, get the state from drm_atomic_state. temp_crtc->state might be
> > irrelevant.
>
> Hi Dmitry,
>
> Ack.
>
> >
> >> + num_cwb_sessions++;
> >
> > Even simpler:
> > if (temp_crtc != crtc && drm_crtc_in_clone_mode(...))
> > return false;
>
> Ack.
>
> >
> >> +
> >> + /*
> >> + * Only support a single concurrent writeback session running
> >> + * at a time
> >
> > If it is not a hardware limitation, please add:
> > FIXME: support more than one session
>
> This is a hardware limitation.
>
> >
> >> + */
> >> + if (num_cwb_sessions > 1)
> >> + return false;
> >> +
> >> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
> >> + if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
> >> + crtc_state->encoder_mask) {
> >
> > Align to opening bracket, please. Granted that other drivers don't
> > perform this check, is it really necessary? Doesn't
> > validate_encoder_possible_clones() ensure the same, but during the
> > encoder registration?
>
> The difference here is that validate_encoder_possible_clones() is only
> called when the drm device is initially registered.
>
> The check here is to make sure that the encoders userspace is proposing
> to be cloned are actually possible clones of each other. This might not
> be necessary for drivers where all encoders are all possible clones of
> each other. But for MSM (and CWB), real-time display encoders can only
> be clones of writeback (and vice versa).
I had the feeling that encoder_mask should already take care of that,
but it seems I was wrong.
Please extract this piece as a generic helper. I think it should be
called from the generic atomic_check() codepath.
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones
2024-09-04 18:41 ` Dmitry Baryshkov
@ 2024-09-04 19:23 ` Ville Syrjälä
0 siblings, 0 replies; 59+ messages in thread
From: Ville Syrjälä @ 2024-09-04 19:23 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Jessica Zhang, Rob Clark, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark
On Wed, Sep 04, 2024 at 09:41:23PM +0300, Dmitry Baryshkov wrote:
> On Wed, 4 Sept 2024 at 01:18, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> >
> >
> >
> > On 8/30/2024 10:00 AM, Dmitry Baryshkov wrote:
> > > On Thu, Aug 29, 2024 at 01:48:28PM GMT, Jessica Zhang wrote:
> > >> Check that each encoder in the CRTC state's encoder_mask is marked as a
> > >> possible clone for all other encoders in the encoder_mask and that only
> > >> one CRTC is in clone mode at a time
> > >>
> > >> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > >> ---
> > >> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 36 +++++++++++++++++++++++++++++++-
> > >> 1 file changed, 35 insertions(+), 1 deletion(-)
> > >>
> > >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > >> index 5ec1b5a38922..bebae365c036 100644
> > >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > >> @@ -1,6 +1,6 @@
> > >> // SPDX-License-Identifier: GPL-2.0-only
> > >> /*
> > >> - * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
> > >> + * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
> > >> * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
> > >> * Copyright (C) 2013 Red Hat
> > >> * Author: Rob Clark <robdclark@gmail.com>
> > >> @@ -1204,6 +1204,36 @@ static struct msm_display_topology dpu_crtc_get_topology(
> > >> return topology;
> > >> }
> > >>
> > >> +static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
> > >> + struct drm_crtc_state *crtc_state)
> > >> +{
> > >> + struct drm_encoder *drm_enc;
> > >> + struct drm_crtc *temp_crtc;
> > >> + int num_cwb_sessions = 0;
> > >> +
> > >> + drm_for_each_crtc(temp_crtc, crtc->dev)
> > >> + if (drm_crtc_in_clone_mode(temp_crtc->state))
> > >
> > > No, get the state from drm_atomic_state. temp_crtc->state might be
> > > irrelevant.
> >
> > Hi Dmitry,
> >
> > Ack.
> >
> > >
> > >> + num_cwb_sessions++;
> > >
> > > Even simpler:
> > > if (temp_crtc != crtc && drm_crtc_in_clone_mode(...))
> > > return false;
> >
> > Ack.
> >
> > >
> > >> +
> > >> + /*
> > >> + * Only support a single concurrent writeback session running
> > >> + * at a time
> > >
> > > If it is not a hardware limitation, please add:
> > > FIXME: support more than one session
> >
> > This is a hardware limitation.
> >
> > >
> > >> + */
> > >> + if (num_cwb_sessions > 1)
> > >> + return false;
> > >> +
> > >> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask) {
> > >> + if ((crtc_state->encoder_mask & drm_enc->possible_clones) !=
> > >> + crtc_state->encoder_mask) {
> > >
> > > Align to opening bracket, please. Granted that other drivers don't
> > > perform this check, is it really necessary? Doesn't
> > > validate_encoder_possible_clones() ensure the same, but during the
> > > encoder registration?
> >
> > The difference here is that validate_encoder_possible_clones() is only
> > called when the drm device is initially registered.
> >
> > The check here is to make sure that the encoders userspace is proposing
> > to be cloned are actually possible clones of each other. This might not
> > be necessary for drivers where all encoders are all possible clones of
> > each other. But for MSM (and CWB), real-time display encoders can only
> > be clones of writeback (and vice versa).
>
> I had the feeling that encoder_mask should already take care of that,
> but it seems I was wrong.
> Please extract this piece as a generic helper. I think it should be
> called from the generic atomic_check() codepath.
Yeah, if we are semi-assured that drivers aren't screwing up those
bitmasks anymore we could shove the cloning checks into
drm_atomic_helper_check_modeset(). It already checks possible_crtcs.
We could then throw out the equavalent code from i915 as well...
Are there decent IGTs to make sure the kernel properly rejects
illegal cloning configurations?
--
Ville Syrjälä
Intel
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (6 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 07/21] drm/msm/dpu: Check CRTC encoders are valid clones Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:13 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 09/21] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
` (12 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Add new block for concurrent writeback mux to HW catalog and change
pingpong index names to distinguish between general use pingpong blocks
and pingpong blocks dedicated for concurrent writeback
Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
.../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +++++++++++++++++++---
.../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.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_hw_catalog.h | 13 ++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 8 +++---
6 files changed, 48 insertions(+), 14 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 eb5dfff2ec4f..ce2773029763 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_6", .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_7", .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_8", .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_9", .id = PINGPONG_CWB_3,
.base = 0x7e400, .len = 0,
.features = BIT(DPU_PINGPONG_DITHER),
.sblk = &sc7280_pp_sblk,
@@ -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/catalog/dpu_8_1_sm8450.h b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
index a1779c5597ae..c5c95c6654dd 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_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 ad48defa154f..31c4a3025e51 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_6", .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_7", .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 a3e60ac70689..24bb6b13eaba 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_6", .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_7", .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_catalog.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 37e18e820a20..b42d8b3640e2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -621,6 +621,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
@@ -823,6 +833,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;
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 a2eff36a2224..c17d2d356f7a 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] 59+ messages in thread* Re: [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650
2024-08-29 20:48 ` [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650 Jessica Zhang
@ 2024-08-30 17:13 ` Dmitry Baryshkov
2024-09-03 22:20 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:13 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:29PM GMT, Jessica Zhang wrote:
> From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>
> Add new block for concurrent writeback mux to HW catalog and change
> pingpong index names to distinguish between general use pingpong blocks
> and pingpong blocks dedicated for concurrent writeback
Please split into two commits.
>
> Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> .../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +++++++++++++++++++---
> .../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.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_hw_catalog.h | 13 ++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 8 +++---
> 6 files changed, 48 insertions(+), 14 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 eb5dfff2ec4f..ce2773029763 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_6", .id = PINGPONG_CWB_0,
Should we also rename such blocks?
> .base = 0x66000, .len = 0,
> .features = BIT(DPU_PINGPONG_DITHER),
> .sblk = &sc7280_pp_sblk,
> .merge_3d = MERGE_3D_3,
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650
2024-08-30 17:13 ` Dmitry Baryshkov
@ 2024-09-03 22:20 ` Jessica Zhang
0 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-09-03 22:20 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:13 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:29PM GMT, Jessica Zhang wrote:
>> From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>>
>> Add new block for concurrent writeback mux to HW catalog and change
>> pingpong index names to distinguish between general use pingpong blocks
>> and pingpong blocks dedicated for concurrent writeback
>
> Please split into two commits.
Hi Dmitry,
Sounds good
>
>>
>> Signed-off-by: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> .../drm/msm/disp/dpu1/catalog/dpu_10_0_sm8650.h | 29 +++++++++++++++++++---
>> .../gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.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_hw_catalog.h | 13 ++++++++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 8 +++---
>> 6 files changed, 48 insertions(+), 14 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 eb5dfff2ec4f..ce2773029763 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_6", .id = PINGPONG_CWB_0,
>
> Should we also rename such blocks?
Sure, I can change the name to match the id
Thanks,
Jessica Zhang
>
>> .base = 0x66000, .len = 0,
>> .features = BIT(DPU_PINGPONG_DITHER),
>> .sblk = &sc7280_pp_sblk,
>> .merge_3d = MERGE_3D_3,
>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 09/21] drm/msm/dpu: add devcoredumps for cwb registers
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (7 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 08/21] drm/msm/dpu: add CWB entry to catalog for SM8650 Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:02 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
` (11 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Implement instance of snapshot function to dump new registers used
for cwb
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 d1e2143110f2..87526d3c224a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -989,6 +989,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] 59+ messages in thread* Re: [PATCH 09/21] drm/msm/dpu: add devcoredumps for cwb registers
2024-08-29 20:48 ` [PATCH 09/21] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
@ 2024-08-30 17:02 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:02 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:30PM GMT, Jessica Zhang wrote:
> From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>
> Implement instance of snapshot function to dump new registers used
> for cwb
>
> 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(+)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (8 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 09/21] drm/msm/dpu: add devcoredumps for cwb registers Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:41 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
` (10 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
Add function ops to allow hw_wb to configure CWB registers and adjust
the WB_MUX configuration to account for using dedicated CWB pingpong
blocks.
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_hw_wb.c | 69 ++++++++++++++++++++++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 34 +++++++++++++++
2 files changed, 102 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 93ff01c889b5..998c9fbd22a6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
@@ -51,6 +51,12 @@
#define WB_CDP_CNTL 0x2B4
#define WB_OUT_IMAGE_SIZE 0x2C0
#define WB_OUT_XY 0x2C4
+#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_wb_setup_outaddress(struct dpu_hw_wb *ctx,
struct dpu_hw_wb_cfg *data)
@@ -173,7 +179,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;
@@ -237,3 +245,62 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
return c;
}
+
+static void dpu_hw_cwb_setup_input_ctrl(struct dpu_hw_wb *ctx,
+ enum dpu_cwb cwb_idx,
+ const enum dpu_pingpong pp)
+{
+ struct dpu_hw_blk_reg_map *c;
+ int cwb_mux_cfg = 0xF;
+
+ if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX)
+ return;
+
+ c = &ctx->cwb_hw[cwb_idx - CWB_0];
+
+ /*
+ * The CWB_MUX register takes the pingpong index relative to
+ * PINGPONG_CWB_0 and not PINGPONG_0
+ */
+ if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX))
+ cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_CWB_0);
+
+ DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg);
+}
+
+static void dpu_hw_cwb_setup_input_mode(struct dpu_hw_wb *ctx,
+ enum dpu_cwb cwb_idx,
+ const enum cwb_mode_input input)
+{
+ struct dpu_hw_blk_reg_map *c;
+ int cwb_mux_cfg;
+
+ if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX || input >= INPUT_MODE_MAX)
+ return;
+
+ c = &ctx->cwb_hw[cwb_idx - CWB_0];
+ cwb_mux_cfg = FIELD_PREP(CWB_MODE_MASK, input);
+
+ DPU_REG_WRITE(c, CWB_MODE, cwb_mux_cfg);
+}
+
+static void _setup_cwb_ops(struct dpu_hw_wb_ops *ops)
+{
+ ops->setup_input_ctrl = dpu_hw_cwb_setup_input_ctrl;
+ ops->setup_input_mode = dpu_hw_cwb_setup_input_mode;
+}
+
+struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
+ const struct dpu_wb_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_version *mdss_rev,
+ struct dpu_hw_blk_reg_map *cwb_hw)
+{
+ struct dpu_hw_wb *c = dpu_hw_wb_init(dev, cfg, addr, mdss_rev);
+
+ c->cwb_hw = cwb_hw;
+
+ _setup_cwb_ops(&c->ops);
+
+ return c;
+}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
index 37497473e16c..1ff40f8325e5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
@@ -21,6 +21,12 @@ struct dpu_hw_wb_cfg {
struct drm_rect crop;
};
+enum cwb_mode_input {
+ INPUT_MODE_LM_OUT,
+ INPUT_MODE_DSPP_OUT,
+ INPUT_MODE_MAX
+};
+
/**
*
* struct dpu_hw_wb_ops : Interface to the wb hw driver functions
@@ -31,6 +37,8 @@ struct dpu_hw_wb_cfg {
* @setup_cdp: setup chroma down prefetch block for writeback block
* @setup_clk_force_ctrl: setup clock force control
* @bind_pingpong_blk: enable/disable the connection with ping-pong block
+ * @setup_ctrl: setup ctrl register for cwb
+ * @setup_mode: setup mode register for cwb
*/
struct dpu_hw_wb_ops {
void (*setup_outaddress)(struct dpu_hw_wb *ctx,
@@ -54,11 +62,20 @@ struct dpu_hw_wb_ops {
void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx,
const enum dpu_pingpong pp);
+
+ void (*setup_input_ctrl)(struct dpu_hw_wb *ctx,
+ enum dpu_cwb cwb_idx,
+ const enum dpu_pingpong pp);
+
+ void (*setup_input_mode)(struct dpu_hw_wb *ctx,
+ enum dpu_cwb cwb_idx,
+ const enum cwb_mode_input input);
};
/**
* struct dpu_hw_wb : WB driver object
* @hw: block hardware details
+ * @cwb_hw: block hardware details of cwb_muxes
* @idx: hardware index number within type
* @wb_hw_caps: hardware capabilities
* @ops: function pointers
@@ -66,6 +83,9 @@ struct dpu_hw_wb_ops {
struct dpu_hw_wb {
struct dpu_hw_blk_reg_map hw;
+ /* cwb data */
+ struct dpu_hw_blk_reg_map *cwb_hw;
+
/* wb path */
int idx;
const struct dpu_wb_cfg *caps;
@@ -87,4 +107,18 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
void __iomem *addr,
const struct dpu_mdss_version *mdss_rev);
+/**
+ * dpu_hw_wb_init_with_cwb() - 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
+ * @hw: array of cwb muxes
+ * Return: Error code or allocated dpu_hw_wb context
+ */
+struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
+ const struct dpu_wb_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_version *mdss_rev,
+ struct dpu_hw_blk_reg_map *hw);
+
#endif /*_DPU_HW_WB_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb
2024-08-29 20:48 ` [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
@ 2024-08-30 17:41 ` Dmitry Baryshkov
2024-09-03 22:22 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:41 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:31PM GMT, Jessica Zhang wrote:
> From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>
> Add function ops to allow hw_wb to configure CWB registers and adjust
> the WB_MUX configuration to account for using dedicated CWB pingpong
> blocks.
>
> 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_hw_wb.c | 69 ++++++++++++++++++++++++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 34 +++++++++++++++
> 2 files changed, 102 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 93ff01c889b5..998c9fbd22a6 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
> @@ -51,6 +51,12 @@
> #define WB_CDP_CNTL 0x2B4
> #define WB_OUT_IMAGE_SIZE 0x2C0
> #define WB_OUT_XY 0x2C4
Empty line
> +#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_wb_setup_outaddress(struct dpu_hw_wb *ctx,
> struct dpu_hw_wb_cfg *data)
> @@ -173,7 +179,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;
> @@ -237,3 +245,62 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
>
> return c;
> }
> +
> +static void dpu_hw_cwb_setup_input_ctrl(struct dpu_hw_wb *ctx,
> + enum dpu_cwb cwb_idx,
> + const enum dpu_pingpong pp)
Align to opening bracket, please.
> +{
> + struct dpu_hw_blk_reg_map *c;
> + int cwb_mux_cfg = 0xF;
> +
> + if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX)
> + return;
> +
> + c = &ctx->cwb_hw[cwb_idx - CWB_0];
> +
> + /*
> + * The CWB_MUX register takes the pingpong index relative to
> + * PINGPONG_CWB_0 and not PINGPONG_0
> + */
> + if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX))
> + cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_CWB_0);
> +
> + DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg);
> +}
> +
> +static void dpu_hw_cwb_setup_input_mode(struct dpu_hw_wb *ctx,
> + enum dpu_cwb cwb_idx,
> + const enum cwb_mode_input input)
> +{
> + struct dpu_hw_blk_reg_map *c;
> + int cwb_mux_cfg;
> +
> + if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX || input >= INPUT_MODE_MAX)
> + return;
> +
> + c = &ctx->cwb_hw[cwb_idx - CWB_0];
> + cwb_mux_cfg = FIELD_PREP(CWB_MODE_MASK, input);
> +
> + DPU_REG_WRITE(c, CWB_MODE, cwb_mux_cfg);
> +}
> +
> +static void _setup_cwb_ops(struct dpu_hw_wb_ops *ops)
> +{
> + ops->setup_input_ctrl = dpu_hw_cwb_setup_input_ctrl;
> + ops->setup_input_mode = dpu_hw_cwb_setup_input_mode;
> +}
> +
> +struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
> + const struct dpu_wb_cfg *cfg,
> + void __iomem *addr,
> + const struct dpu_mdss_version *mdss_rev,
> + struct dpu_hw_blk_reg_map *cwb_hw)
> +{
> + struct dpu_hw_wb *c = dpu_hw_wb_init(dev, cfg, addr, mdss_rev);
> +
> + c->cwb_hw = cwb_hw;
> +
> + _setup_cwb_ops(&c->ops);
> +
> + return c;
> +}
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
> index 37497473e16c..1ff40f8325e5 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
> @@ -21,6 +21,12 @@ struct dpu_hw_wb_cfg {
> struct drm_rect crop;
> };
>
> +enum cwb_mode_input {
> + INPUT_MODE_LM_OUT,
> + INPUT_MODE_DSPP_OUT,
> + INPUT_MODE_MAX
> +};
> +
> /**
> *
> * struct dpu_hw_wb_ops : Interface to the wb hw driver functions
> @@ -31,6 +37,8 @@ struct dpu_hw_wb_cfg {
> * @setup_cdp: setup chroma down prefetch block for writeback block
> * @setup_clk_force_ctrl: setup clock force control
> * @bind_pingpong_blk: enable/disable the connection with ping-pong block
> + * @setup_ctrl: setup ctrl register for cwb
> + * @setup_mode: setup mode register for cwb
> */
> struct dpu_hw_wb_ops {
> void (*setup_outaddress)(struct dpu_hw_wb *ctx,
> @@ -54,11 +62,20 @@ struct dpu_hw_wb_ops {
>
> void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx,
> const enum dpu_pingpong pp);
> +
> + void (*setup_input_ctrl)(struct dpu_hw_wb *ctx,
> + enum dpu_cwb cwb_idx,
> + const enum dpu_pingpong pp);
> +
> + void (*setup_input_mode)(struct dpu_hw_wb *ctx,
> + enum dpu_cwb cwb_idx,
> + const enum cwb_mode_input input);
Judging by the usage, could you please add single setup_cwb() callback
and let WB code call corresponding functions internally.
> };
>
> /**
> * struct dpu_hw_wb : WB driver object
> * @hw: block hardware details
> + * @cwb_hw: block hardware details of cwb_muxes
> * @idx: hardware index number within type
> * @wb_hw_caps: hardware capabilities
> * @ops: function pointers
> @@ -66,6 +83,9 @@ struct dpu_hw_wb_ops {
> struct dpu_hw_wb {
> struct dpu_hw_blk_reg_map hw;
>
> + /* cwb data */
> + struct dpu_hw_blk_reg_map *cwb_hw;
> +
> /* wb path */
> int idx;
> const struct dpu_wb_cfg *caps;
> @@ -87,4 +107,18 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
> void __iomem *addr,
> const struct dpu_mdss_version *mdss_rev);
>
> +/**
> + * dpu_hw_wb_init_with_cwb() - 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
> + * @hw: array of cwb muxes
> + * Return: Error code or allocated dpu_hw_wb context
> + */
Please move the comment to the function body. This way make W=1 will
check that it is valid.
> +struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
> + const struct dpu_wb_cfg *cfg,
> + void __iomem *addr,
> + const struct dpu_mdss_version *mdss_rev,
> + struct dpu_hw_blk_reg_map *hw);
> +
> #endif /*_DPU_HW_WB_H */
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb
2024-08-30 17:41 ` Dmitry Baryshkov
@ 2024-09-03 22:22 ` Jessica Zhang
0 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-09-03 22:22 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:41 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:31PM GMT, Jessica Zhang wrote:
>> From: Esha Bharadwaj <quic_ebharadw@quicinc.com>
>>
>> Add function ops to allow hw_wb to configure CWB registers and adjust
>> the WB_MUX configuration to account for using dedicated CWB pingpong
>> blocks.
>>
>> 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_hw_wb.c | 69 ++++++++++++++++++++++++++++++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 34 +++++++++++++++
>> 2 files changed, 102 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 93ff01c889b5..998c9fbd22a6 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c
>> @@ -51,6 +51,12 @@
>> #define WB_CDP_CNTL 0x2B4
>> #define WB_OUT_IMAGE_SIZE 0x2C0
>> #define WB_OUT_XY 0x2C4
>
> Empty line
>
>> +#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_wb_setup_outaddress(struct dpu_hw_wb *ctx,
>> struct dpu_hw_wb_cfg *data)
>> @@ -173,7 +179,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;
>> @@ -237,3 +245,62 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
>>
>> return c;
>> }
>> +
>> +static void dpu_hw_cwb_setup_input_ctrl(struct dpu_hw_wb *ctx,
>> + enum dpu_cwb cwb_idx,
>> + const enum dpu_pingpong pp)
>
> Align to opening bracket, please.
Hi Dmitry,
Acked for all comments here -- I'll squash the 2 cwb ops together.
Thanks,
Jessica Zhang
>
>> +{
>> + struct dpu_hw_blk_reg_map *c;
>> + int cwb_mux_cfg = 0xF;
>> +
>> + if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX)
>> + return;
>> +
>> + c = &ctx->cwb_hw[cwb_idx - CWB_0];
>> +
>> + /*
>> + * The CWB_MUX register takes the pingpong index relative to
>> + * PINGPONG_CWB_0 and not PINGPONG_0
>> + */
>> + if ((pp != PINGPONG_NONE) && (pp < PINGPONG_MAX))
>> + cwb_mux_cfg = FIELD_PREP(CWB_MUX_MASK, pp - PINGPONG_CWB_0);
>> +
>> + DPU_REG_WRITE(c, CWB_MUX, cwb_mux_cfg);
>> +}
>> +
>> +static void dpu_hw_cwb_setup_input_mode(struct dpu_hw_wb *ctx,
>> + enum dpu_cwb cwb_idx,
>> + const enum cwb_mode_input input)
>> +{
>> + struct dpu_hw_blk_reg_map *c;
>> + int cwb_mux_cfg;
>> +
>> + if (cwb_idx < CWB_0 || cwb_idx >= CWB_MAX || input >= INPUT_MODE_MAX)
>> + return;
>> +
>> + c = &ctx->cwb_hw[cwb_idx - CWB_0];
>> + cwb_mux_cfg = FIELD_PREP(CWB_MODE_MASK, input);
>> +
>> + DPU_REG_WRITE(c, CWB_MODE, cwb_mux_cfg);
>> +}
>> +
>> +static void _setup_cwb_ops(struct dpu_hw_wb_ops *ops)
>> +{
>> + ops->setup_input_ctrl = dpu_hw_cwb_setup_input_ctrl;
>> + ops->setup_input_mode = dpu_hw_cwb_setup_input_mode;
>> +}
>> +
>> +struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
>> + const struct dpu_wb_cfg *cfg,
>> + void __iomem *addr,
>> + const struct dpu_mdss_version *mdss_rev,
>> + struct dpu_hw_blk_reg_map *cwb_hw)
>> +{
>> + struct dpu_hw_wb *c = dpu_hw_wb_init(dev, cfg, addr, mdss_rev);
>> +
>> + c->cwb_hw = cwb_hw;
>> +
>> + _setup_cwb_ops(&c->ops);
>> +
>> + return c;
>> +}
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
>> index 37497473e16c..1ff40f8325e5 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h
>> @@ -21,6 +21,12 @@ struct dpu_hw_wb_cfg {
>> struct drm_rect crop;
>> };
>>
>> +enum cwb_mode_input {
>> + INPUT_MODE_LM_OUT,
>> + INPUT_MODE_DSPP_OUT,
>> + INPUT_MODE_MAX
>> +};
>> +
>> /**
>> *
>> * struct dpu_hw_wb_ops : Interface to the wb hw driver functions
>> @@ -31,6 +37,8 @@ struct dpu_hw_wb_cfg {
>> * @setup_cdp: setup chroma down prefetch block for writeback block
>> * @setup_clk_force_ctrl: setup clock force control
>> * @bind_pingpong_blk: enable/disable the connection with ping-pong block
>> + * @setup_ctrl: setup ctrl register for cwb
>> + * @setup_mode: setup mode register for cwb
>> */
>> struct dpu_hw_wb_ops {
>> void (*setup_outaddress)(struct dpu_hw_wb *ctx,
>> @@ -54,11 +62,20 @@ struct dpu_hw_wb_ops {
>>
>> void (*bind_pingpong_blk)(struct dpu_hw_wb *ctx,
>> const enum dpu_pingpong pp);
>> +
>> + void (*setup_input_ctrl)(struct dpu_hw_wb *ctx,
>> + enum dpu_cwb cwb_idx,
>> + const enum dpu_pingpong pp);
>> +
>> + void (*setup_input_mode)(struct dpu_hw_wb *ctx,
>> + enum dpu_cwb cwb_idx,
>> + const enum cwb_mode_input input);
>
> Judging by the usage, could you please add single setup_cwb() callback
> and let WB code call corresponding functions internally.
>
>> };
>>
>> /**
>> * struct dpu_hw_wb : WB driver object
>> * @hw: block hardware details
>> + * @cwb_hw: block hardware details of cwb_muxes
>> * @idx: hardware index number within type
>> * @wb_hw_caps: hardware capabilities
>> * @ops: function pointers
>> @@ -66,6 +83,9 @@ struct dpu_hw_wb_ops {
>> struct dpu_hw_wb {
>> struct dpu_hw_blk_reg_map hw;
>>
>> + /* cwb data */
>> + struct dpu_hw_blk_reg_map *cwb_hw;
>> +
>> /* wb path */
>> int idx;
>> const struct dpu_wb_cfg *caps;
>> @@ -87,4 +107,18 @@ struct dpu_hw_wb *dpu_hw_wb_init(struct drm_device *dev,
>> void __iomem *addr,
>> const struct dpu_mdss_version *mdss_rev);
>>
>> +/**
>> + * dpu_hw_wb_init_with_cwb() - 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
>> + * @hw: array of cwb muxes
>> + * Return: Error code or allocated dpu_hw_wb context
>> + */
>
> Please move the comment to the function body. This way make W=1 will
> check that it is valid.
>
>> +struct dpu_hw_wb *dpu_hw_wb_init_with_cwb(struct drm_device *dev,
>> + const struct dpu_wb_cfg *cfg,
>> + void __iomem *addr,
>> + const struct dpu_mdss_version *mdss_rev,
>> + struct dpu_hw_blk_reg_map *hw);
>> +
>> #endif /*_DPU_HW_WB_H */
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (9 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 10/21] drm/msm/dpu: add CWB support to dpu_hw_wb Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:18 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 12/21] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
` (9 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Add support for allocating the concurrent writeback mux as part of the
WB allocation
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
2 files changed, 32 insertions(+), 3 deletions(-)
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 c17d2d356f7a..c43cb55fe1d2 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
@@ -352,6 +354,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
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index bc99b04eae3a..738e9a081b10 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -1,9 +1,10 @@
// 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.
*/
+#include <drm/drm_managed.h>
#include "msm_drv.h"
#define pr_fmt(fmt) "[drm:%s] " fmt, __func__
#include "dpu_kms.h"
@@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
void __iomem *mmio)
{
int rc, i;
+ struct dpu_hw_blk_reg_map *cwb_reg_map;
if (!rm || !cat || !mmio) {
DPU_ERROR("invalid kms\n");
@@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
rm->hw_intf[intf->id - INTF_0] = hw;
}
+ if (cat->cwb_count > 0) {
+ cwb_reg_map = drmm_kzalloc(dev,
+ sizeof(*cwb_reg_map) * cat->cwb_count,
+ GFP_KERNEL);
+
+ if (!cwb_reg_map) {
+ DPU_ERROR("failed cwb object creation\n");
+ return -ENOMEM;
+ }
+ }
+
+
+ for (i = 0; i < cat->cwb_count; i++) {
+ struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
+
+ cwb->blk_addr = mmio + cat->cwb[i].base;
+ cwb->log_mask = DPU_DBG_MASK_CWB;
+ }
+
for (i = 0; i < cat->wb_count; i++) {
struct dpu_hw_wb *hw;
const struct dpu_wb_cfg *wb = &cat->wb[i];
- hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
+ if (cat->cwb)
+ hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
+ cat->mdss_ver, cwb_reg_map);
+ else
+ hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
+
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed wb object creation: err %d\n", rc);
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-08-29 20:48 ` [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
@ 2024-08-30 17:18 ` Dmitry Baryshkov
2024-08-30 19:28 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:18 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
> Add support for allocating the concurrent writeback mux as part of the
> WB allocation
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
> 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 c17d2d356f7a..c43cb55fe1d2 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
> @@ -352,6 +354,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
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index bc99b04eae3a..738e9a081b10 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -1,9 +1,10 @@
> // 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.
> */
>
> +#include <drm/drm_managed.h>
> #include "msm_drv.h"
> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
> #include "dpu_kms.h"
> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
> void __iomem *mmio)
> {
> int rc, i;
> + struct dpu_hw_blk_reg_map *cwb_reg_map;
>
> if (!rm || !cat || !mmio) {
> DPU_ERROR("invalid kms\n");
> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
> rm->hw_intf[intf->id - INTF_0] = hw;
> }
>
> + if (cat->cwb_count > 0) {
> + cwb_reg_map = drmm_kzalloc(dev,
> + sizeof(*cwb_reg_map) * cat->cwb_count,
> + GFP_KERNEL);
Please move CWB block pointers to dpu_rm. There is no need to allocate a
separate array.
> +
> + if (!cwb_reg_map) {
> + DPU_ERROR("failed cwb object creation\n");
> + return -ENOMEM;
> + }
> + }
> +
> +
> + for (i = 0; i < cat->cwb_count; i++) {
> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
> +
> + cwb->blk_addr = mmio + cat->cwb[i].base;
> + cwb->log_mask = DPU_DBG_MASK_CWB;
> + }
> +
> for (i = 0; i < cat->wb_count; i++) {
> struct dpu_hw_wb *hw;
> const struct dpu_wb_cfg *wb = &cat->wb[i];
>
> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> + if (cat->cwb)
> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
> + cat->mdss_ver, cwb_reg_map);
> + else
> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> +
> if (IS_ERR(hw)) {
> rc = PTR_ERR(hw);
> DPU_ERROR("failed wb object creation: err %d\n", rc);
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-08-30 17:18 ` Dmitry Baryshkov
@ 2024-08-30 19:28 ` Jessica Zhang
2024-08-30 22:16 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-30 19:28 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
>> Add support for allocating the concurrent writeback mux as part of the
>> WB allocation
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>
>> 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 c17d2d356f7a..c43cb55fe1d2 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
>> @@ -352,6 +354,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
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index bc99b04eae3a..738e9a081b10 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -1,9 +1,10 @@
>> // 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.
>> */
>>
>> +#include <drm/drm_managed.h>
>> #include "msm_drv.h"
>> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
>> #include "dpu_kms.h"
>> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
>> void __iomem *mmio)
>> {
>> int rc, i;
>> + struct dpu_hw_blk_reg_map *cwb_reg_map;
>>
>> if (!rm || !cat || !mmio) {
>> DPU_ERROR("invalid kms\n");
>> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
>> rm->hw_intf[intf->id - INTF_0] = hw;
>> }
>>
>> + if (cat->cwb_count > 0) {
>> + cwb_reg_map = drmm_kzalloc(dev,
>> + sizeof(*cwb_reg_map) * cat->cwb_count,
>> + GFP_KERNEL);
>
> Please move CWB block pointers to dpu_rm. There is no need to allocate a
> separate array.
Hi Dmitry,
Sorry, I'm not sure what you mean here. Can you clarify your comment?
This is just allocating an array of the CWB register addresses so that
the hw_wb block can use it to configure the CWB mux registers.
Thanks,
Jessica Zhang
>
>> +
>> + if (!cwb_reg_map) {
>> + DPU_ERROR("failed cwb object creation\n");
>> + return -ENOMEM;
>> + }
>> + }
>> +
>> +
>> + for (i = 0; i < cat->cwb_count; i++) {
>> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
>> +
>> + cwb->blk_addr = mmio + cat->cwb[i].base;
>> + cwb->log_mask = DPU_DBG_MASK_CWB;
>> + }
>> +
>> for (i = 0; i < cat->wb_count; i++) {
>> struct dpu_hw_wb *hw;
>> const struct dpu_wb_cfg *wb = &cat->wb[i];
>>
>> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>> + if (cat->cwb)
>> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
>> + cat->mdss_ver, cwb_reg_map);
>> + else
>> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>> +
>> if (IS_ERR(hw)) {
>> rc = PTR_ERR(hw);
>> DPU_ERROR("failed wb object creation: err %d\n", rc);
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-08-30 19:28 ` Jessica Zhang
@ 2024-08-30 22:16 ` Dmitry Baryshkov
2024-09-04 1:04 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 22:16 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Fri, 30 Aug 2024 at 22:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
> > On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
> >> Add support for allocating the concurrent writeback mux as part of the
> >> WB allocation
> >>
> >> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >> ---
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
> >> 2 files changed, 32 insertions(+), 3 deletions(-)
> >>
> >> 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 c17d2d356f7a..c43cb55fe1d2 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
> >> @@ -352,6 +354,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
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> index bc99b04eae3a..738e9a081b10 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> @@ -1,9 +1,10 @@
> >> // 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.
> >> */
> >>
> >> +#include <drm/drm_managed.h>
> >> #include "msm_drv.h"
> >> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
> >> #include "dpu_kms.h"
> >> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
> >> void __iomem *mmio)
> >> {
> >> int rc, i;
> >> + struct dpu_hw_blk_reg_map *cwb_reg_map;
> >>
> >> if (!rm || !cat || !mmio) {
> >> DPU_ERROR("invalid kms\n");
> >> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
> >> rm->hw_intf[intf->id - INTF_0] = hw;
> >> }
> >>
> >> + if (cat->cwb_count > 0) {
> >> + cwb_reg_map = drmm_kzalloc(dev,
> >> + sizeof(*cwb_reg_map) * cat->cwb_count,
> >> + GFP_KERNEL);
> >
> > Please move CWB block pointers to dpu_rm. There is no need to allocate a
> > separate array.
>
> Hi Dmitry,
>
> Sorry, I'm not sure what you mean here. Can you clarify your comment?
>
> This is just allocating an array of the CWB register addresses so that
> the hw_wb block can use it to configure the CWB mux registers.
Excuse me. I asked to make the cwb_reg_map array a part of the
existing dpu_rm structure. This way other subblocks can access it
through dpu_rm API.
>
> Thanks,
>
> Jessica Zhang
>
> >
> >> +
> >> + if (!cwb_reg_map) {
> >> + DPU_ERROR("failed cwb object creation\n");
> >> + return -ENOMEM;
> >> + }
> >> + }
> >> +
> >> +
> >> + for (i = 0; i < cat->cwb_count; i++) {
> >> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
> >> +
> >> + cwb->blk_addr = mmio + cat->cwb[i].base;
> >> + cwb->log_mask = DPU_DBG_MASK_CWB;
> >> + }
> >> +
> >> for (i = 0; i < cat->wb_count; i++) {
> >> struct dpu_hw_wb *hw;
> >> const struct dpu_wb_cfg *wb = &cat->wb[i];
> >>
> >> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> >> + if (cat->cwb)
> >> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
> >> + cat->mdss_ver, cwb_reg_map);
> >> + else
> >> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> >> +
> >> if (IS_ERR(hw)) {
> >> rc = PTR_ERR(hw);
> >> DPU_ERROR("failed wb object creation: err %d\n", rc);
> >>
> >> --
> >> 2.34.1
> >>
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-08-30 22:16 ` Dmitry Baryshkov
@ 2024-09-04 1:04 ` Jessica Zhang
2024-09-05 13:30 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-09-04 1:04 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 3:16 PM, Dmitry Baryshkov wrote:
> On Fri, 30 Aug 2024 at 22:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
>>> On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
>>>> Add support for allocating the concurrent writeback mux as part of the
>>>> WB allocation
>>>>
>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
>>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>>
>>>> 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 c17d2d356f7a..c43cb55fe1d2 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
>>>> @@ -352,6 +354,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
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index bc99b04eae3a..738e9a081b10 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -1,9 +1,10 @@
>>>> // 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.
>>>> */
>>>>
>>>> +#include <drm/drm_managed.h>
>>>> #include "msm_drv.h"
>>>> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
>>>> #include "dpu_kms.h"
>>>> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
>>>> void __iomem *mmio)
>>>> {
>>>> int rc, i;
>>>> + struct dpu_hw_blk_reg_map *cwb_reg_map;
>>>>
>>>> if (!rm || !cat || !mmio) {
>>>> DPU_ERROR("invalid kms\n");
>>>> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
>>>> rm->hw_intf[intf->id - INTF_0] = hw;
>>>> }
>>>>
>>>> + if (cat->cwb_count > 0) {
>>>> + cwb_reg_map = drmm_kzalloc(dev,
>>>> + sizeof(*cwb_reg_map) * cat->cwb_count,
>>>> + GFP_KERNEL);
>>>
>>> Please move CWB block pointers to dpu_rm. There is no need to allocate a
>>> separate array.
>>
>> Hi Dmitry,
>>
>> Sorry, I'm not sure what you mean here. Can you clarify your comment?
>>
>> This is just allocating an array of the CWB register addresses so that
>> the hw_wb block can use it to configure the CWB mux registers.
>
> Excuse me. I asked to make the cwb_reg_map array a part of the
> existing dpu_rm structure. This way other subblocks can access it
> through dpu_rm API.
Got it, thanks for the clarification. Just wondering, is the intent here
to add CWB to rm's get_assigned_resourced?
The CWB registers will be handled by hw_wb and isn't referenced anywhere
outside of hw_wb (aside from when it's being allocated and passed into
hw_wb_init) so I'm not sure what's the benefit of adding it to the
dpu_rm struct.
>
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>>>
>>>> +
>>>> + if (!cwb_reg_map) {
>>>> + DPU_ERROR("failed cwb object creation\n");
>>>> + return -ENOMEM;
>>>> + }
>>>> + }
>>>> +
>>>> +
>>>> + for (i = 0; i < cat->cwb_count; i++) {
>>>> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
>>>> +
>>>> + cwb->blk_addr = mmio + cat->cwb[i].base;
>>>> + cwb->log_mask = DPU_DBG_MASK_CWB;
>>>> + }
>>>> +
>>>> for (i = 0; i < cat->wb_count; i++) {
>>>> struct dpu_hw_wb *hw;
>>>> const struct dpu_wb_cfg *wb = &cat->wb[i];
>>>>
>>>> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>>>> + if (cat->cwb)
>>>> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
>>>> + cat->mdss_ver, cwb_reg_map);
>>>> + else
>>>> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>>>> +
>>>> if (IS_ERR(hw)) {
>>>> rc = PTR_ERR(hw);
>>>> DPU_ERROR("failed wb object creation: err %d\n", rc);
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>
>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-09-04 1:04 ` Jessica Zhang
@ 2024-09-05 13:30 ` Dmitry Baryshkov
2024-09-06 16:53 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-09-05 13:30 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Tue, Sep 03, 2024 at 06:04:13PM GMT, Jessica Zhang wrote:
>
>
> On 8/30/2024 3:16 PM, Dmitry Baryshkov wrote:
> > On Fri, 30 Aug 2024 at 22:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> > >
> > >
> > >
> > > On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
> > > > On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
> > > > > Add support for allocating the concurrent writeback mux as part of the
> > > > > WB allocation
> > > > >
> > > > > Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> > > > > ---
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
> > > > > drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
> > > > > 2 files changed, 32 insertions(+), 3 deletions(-)
> > > > >
> > > > > 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 c17d2d356f7a..c43cb55fe1d2 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
> > > > > @@ -352,6 +354,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
> > > > > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > index bc99b04eae3a..738e9a081b10 100644
> > > > > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> > > > > @@ -1,9 +1,10 @@
> > > > > // 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.
> > > > > */
> > > > >
> > > > > +#include <drm/drm_managed.h>
> > > > > #include "msm_drv.h"
> > > > > #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
> > > > > #include "dpu_kms.h"
> > > > > @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
> > > > > void __iomem *mmio)
> > > > > {
> > > > > int rc, i;
> > > > > + struct dpu_hw_blk_reg_map *cwb_reg_map;
> > > > >
> > > > > if (!rm || !cat || !mmio) {
> > > > > DPU_ERROR("invalid kms\n");
> > > > > @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
> > > > > rm->hw_intf[intf->id - INTF_0] = hw;
> > > > > }
> > > > >
> > > > > + if (cat->cwb_count > 0) {
> > > > > + cwb_reg_map = drmm_kzalloc(dev,
> > > > > + sizeof(*cwb_reg_map) * cat->cwb_count,
> > > > > + GFP_KERNEL);
> > > >
> > > > Please move CWB block pointers to dpu_rm. There is no need to allocate a
> > > > separate array.
> > >
> > > Hi Dmitry,
> > >
> > > Sorry, I'm not sure what you mean here. Can you clarify your comment?
> > >
> > > This is just allocating an array of the CWB register addresses so that
> > > the hw_wb block can use it to configure the CWB mux registers.
> >
> > Excuse me. I asked to make the cwb_reg_map array a part of the
> > existing dpu_rm structure. This way other subblocks can access it
> > through dpu_rm API.
>
> Got it, thanks for the clarification. Just wondering, is the intent here to
> add CWB to rm's get_assigned_resourced?
>
> The CWB registers will be handled by hw_wb and isn't referenced anywhere
> outside of hw_wb (aside from when it's being allocated and passed into
> hw_wb_init) so I'm not sure what's the benefit of adding it to the dpu_rm
> struct.
To have a single point where all the blocks are handled, pretty much
like we have a single catalog where all blocks are allocated. Note how
e.g. how MERGE_3D is handled. Or how we return harware instances for
INTF or WB.
>
> >
> > >
> > > Thanks,
> > >
> > > Jessica Zhang
> > >
> > > >
> > > > > +
> > > > > + if (!cwb_reg_map) {
> > > > > + DPU_ERROR("failed cwb object creation\n");
> > > > > + return -ENOMEM;
> > > > > + }
> > > > > + }
> > > > > +
> > > > > +
> > > > > + for (i = 0; i < cat->cwb_count; i++) {
> > > > > + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
> > > > > +
> > > > > + cwb->blk_addr = mmio + cat->cwb[i].base;
> > > > > + cwb->log_mask = DPU_DBG_MASK_CWB;
> > > > > + }
> > > > > +
> > > > > for (i = 0; i < cat->wb_count; i++) {
> > > > > struct dpu_hw_wb *hw;
> > > > > const struct dpu_wb_cfg *wb = &cat->wb[i];
> > > > >
> > > > > - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> > > > > + if (cat->cwb)
> > > > > + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
> > > > > + cat->mdss_ver, cwb_reg_map);
> > > > > + else
> > > > > + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> > > > > +
> > > > > if (IS_ERR(hw)) {
> > > > > rc = PTR_ERR(hw);
> > > > > DPU_ERROR("failed wb object creation: err %d\n", rc);
> > > > >
> > > > > --
> > > > > 2.34.1
> > > > >
> > > >
> > > > --
> > > > With best wishes
> > > > Dmitry
> >
> >
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-09-05 13:30 ` Dmitry Baryshkov
@ 2024-09-06 16:53 ` Jessica Zhang
2024-09-06 17:58 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-09-06 16:53 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 9/5/2024 6:30 AM, Dmitry Baryshkov wrote:
> On Tue, Sep 03, 2024 at 06:04:13PM GMT, Jessica Zhang wrote:
>>
>>
>> On 8/30/2024 3:16 PM, Dmitry Baryshkov wrote:
>>> On Fri, 30 Aug 2024 at 22:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>>>
>>>>
>>>>
>>>> On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
>>>>> On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
>>>>>> Add support for allocating the concurrent writeback mux as part of the
>>>>>> WB allocation
>>>>>>
>>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>>>> ---
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
>>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
>>>>>> 2 files changed, 32 insertions(+), 3 deletions(-)
>>>>>>
>>>>>> 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 c17d2d356f7a..c43cb55fe1d2 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
>>>>>> @@ -352,6 +354,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
>>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> index bc99b04eae3a..738e9a081b10 100644
>>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>>>> @@ -1,9 +1,10 @@
>>>>>> // 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.
>>>>>> */
>>>>>>
>>>>>> +#include <drm/drm_managed.h>
>>>>>> #include "msm_drv.h"
>>>>>> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
>>>>>> #include "dpu_kms.h"
>>>>>> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
>>>>>> void __iomem *mmio)
>>>>>> {
>>>>>> int rc, i;
>>>>>> + struct dpu_hw_blk_reg_map *cwb_reg_map;
>>>>>>
>>>>>> if (!rm || !cat || !mmio) {
>>>>>> DPU_ERROR("invalid kms\n");
>>>>>> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
>>>>>> rm->hw_intf[intf->id - INTF_0] = hw;
>>>>>> }
>>>>>>
>>>>>> + if (cat->cwb_count > 0) {
>>>>>> + cwb_reg_map = drmm_kzalloc(dev,
>>>>>> + sizeof(*cwb_reg_map) * cat->cwb_count,
>>>>>> + GFP_KERNEL);
>>>>>
>>>>> Please move CWB block pointers to dpu_rm. There is no need to allocate a
>>>>> separate array.
>>>>
>>>> Hi Dmitry,
>>>>
>>>> Sorry, I'm not sure what you mean here. Can you clarify your comment?
>>>>
>>>> This is just allocating an array of the CWB register addresses so that
>>>> the hw_wb block can use it to configure the CWB mux registers.
>>>
>>> Excuse me. I asked to make the cwb_reg_map array a part of the
>>> existing dpu_rm structure. This way other subblocks can access it
>>> through dpu_rm API.
>>
>> Got it, thanks for the clarification. Just wondering, is the intent here to
>> add CWB to rm's get_assigned_resourced?
>>
>> The CWB registers will be handled by hw_wb and isn't referenced anywhere
>> outside of hw_wb (aside from when it's being allocated and passed into
>> hw_wb_init) so I'm not sure what's the benefit of adding it to the dpu_rm
>> struct.
>
> To have a single point where all the blocks are handled, pretty much
> like we have a single catalog where all blocks are allocated. Note how
> e.g. how MERGE_3D is handled. Or how we return harware instances for
> INTF or WB.
Got it, seems like you're leaning towards having CWB as a completely
independent hardware block with its own dpu_hw_cwb file and struct.
FWIW, we did consider this approach at the very beginning, but decided
to go with having the CWB registers configured by dpu_hw_wb under the
hood because we thought it would be overkill to create a completely new
struct just to program 2 registers via 1 function op.
We ended up adding the CWB mux programming to dpu_hw_wb because CWB is
closely tied with WB and it mirrored how downstream code was programming
CWB mux [1]
If you prefer to have CWB mux completely independent, I can switch to
that instead.
[1]
https://android.googlesource.com/kernel/msm-extra/display-drivers/+/e18d8e759a344ad4d86b31bbf8160cfe4c65b772/msm/sde/sde_hw_wb.c#265
>
>>
>>>
>>>>
>>>> Thanks,
>>>>
>>>> Jessica Zhang
>>>>
>>>>>
>>>>>> +
>>>>>> + if (!cwb_reg_map) {
>>>>>> + DPU_ERROR("failed cwb object creation\n");
>>>>>> + return -ENOMEM;
>>>>>> + }
>>>>>> + }
>>>>>> +
>>>>>> +
>>>>>> + for (i = 0; i < cat->cwb_count; i++) {
>>>>>> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
>>>>>> +
>>>>>> + cwb->blk_addr = mmio + cat->cwb[i].base;
>>>>>> + cwb->log_mask = DPU_DBG_MASK_CWB;
>>>>>> + }
>>>>>> +
>>>>>> for (i = 0; i < cat->wb_count; i++) {
>>>>>> struct dpu_hw_wb *hw;
>>>>>> const struct dpu_wb_cfg *wb = &cat->wb[i];
>>>>>>
>>>>>> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>>>>>> + if (cat->cwb)
>>>>>> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
>>>>>> + cat->mdss_ver, cwb_reg_map);
>>>>>> + else
>>>>>> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
>>>>>> +
>>>>>> if (IS_ERR(hw)) {
>>>>>> rc = PTR_ERR(hw);
>>>>>> DPU_ERROR("failed wb object creation: err %d\n", rc);
>>>>>>
>>>>>> --
>>>>>> 2.34.1
>>>>>>
>>>>>
>>>>> --
>>>>> With best wishes
>>>>> Dmitry
>>>
>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB
2024-09-06 16:53 ` Jessica Zhang
@ 2024-09-06 17:58 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-09-06 17:58 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Fri, 6 Sept 2024 at 19:53, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 9/5/2024 6:30 AM, Dmitry Baryshkov wrote:
> > On Tue, Sep 03, 2024 at 06:04:13PM GMT, Jessica Zhang wrote:
> >>
> >>
> >> On 8/30/2024 3:16 PM, Dmitry Baryshkov wrote:
> >>> On Fri, 30 Aug 2024 at 22:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 8/30/2024 10:18 AM, Dmitry Baryshkov wrote:
> >>>>> On Thu, Aug 29, 2024 at 01:48:32PM GMT, Jessica Zhang wrote:
> >>>>>> Add support for allocating the concurrent writeback mux as part of the
> >>>>>> WB allocation
> >>>>>>
> >>>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >>>>>> ---
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 5 ++++-
> >>>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 30 +++++++++++++++++++++++++++--
> >>>>>> 2 files changed, 32 insertions(+), 3 deletions(-)
> >>>>>>
> >>>>>> 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 c17d2d356f7a..c43cb55fe1d2 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
> >>>>>> @@ -352,6 +354,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
> >>>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> index bc99b04eae3a..738e9a081b10 100644
> >>>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >>>>>> @@ -1,9 +1,10 @@
> >>>>>> // 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.
> >>>>>> */
> >>>>>>
> >>>>>> +#include <drm/drm_managed.h>
> >>>>>> #include "msm_drv.h"
> >>>>>> #define pr_fmt(fmt) "[drm:%s] " fmt, __func__
> >>>>>> #include "dpu_kms.h"
> >>>>>> @@ -34,6 +35,7 @@ int dpu_rm_init(struct drm_device *dev,
> >>>>>> void __iomem *mmio)
> >>>>>> {
> >>>>>> int rc, i;
> >>>>>> + struct dpu_hw_blk_reg_map *cwb_reg_map;
> >>>>>>
> >>>>>> if (!rm || !cat || !mmio) {
> >>>>>> DPU_ERROR("invalid kms\n");
> >>>>>> @@ -100,11 +102,35 @@ int dpu_rm_init(struct drm_device *dev,
> >>>>>> rm->hw_intf[intf->id - INTF_0] = hw;
> >>>>>> }
> >>>>>>
> >>>>>> + if (cat->cwb_count > 0) {
> >>>>>> + cwb_reg_map = drmm_kzalloc(dev,
> >>>>>> + sizeof(*cwb_reg_map) * cat->cwb_count,
> >>>>>> + GFP_KERNEL);
> >>>>>
> >>>>> Please move CWB block pointers to dpu_rm. There is no need to allocate a
> >>>>> separate array.
> >>>>
> >>>> Hi Dmitry,
> >>>>
> >>>> Sorry, I'm not sure what you mean here. Can you clarify your comment?
> >>>>
> >>>> This is just allocating an array of the CWB register addresses so that
> >>>> the hw_wb block can use it to configure the CWB mux registers.
> >>>
> >>> Excuse me. I asked to make the cwb_reg_map array a part of the
> >>> existing dpu_rm structure. This way other subblocks can access it
> >>> through dpu_rm API.
> >>
> >> Got it, thanks for the clarification. Just wondering, is the intent here to
> >> add CWB to rm's get_assigned_resourced?
> >>
> >> The CWB registers will be handled by hw_wb and isn't referenced anywhere
> >> outside of hw_wb (aside from when it's being allocated and passed into
> >> hw_wb_init) so I'm not sure what's the benefit of adding it to the dpu_rm
> >> struct.
> >
> > To have a single point where all the blocks are handled, pretty much
> > like we have a single catalog where all blocks are allocated. Note how
> > e.g. how MERGE_3D is handled. Or how we return harware instances for
> > INTF or WB.
>
> Got it, seems like you're leaning towards having CWB as a completely
> independent hardware block with its own dpu_hw_cwb file and struct.
>
> FWIW, we did consider this approach at the very beginning, but decided
> to go with having the CWB registers configured by dpu_hw_wb under the
> hood because we thought it would be overkill to create a completely new
> struct just to program 2 registers via 1 function op.
>
> We ended up adding the CWB mux programming to dpu_hw_wb because CWB is
> closely tied with WB and it mirrored how downstream code was programming
> CWB mux [1]
>
> If you prefer to have CWB mux completely independent, I can switch to
> that instead.
Well, I'd suggest to check a separate single-function interface
approach. The reason is pretty simple: for DPU 3.x/4.x we'd need a
completely different programming approach. And if at some point we
will consider going for an sblk / non-sblk implementation for DPU 8.x+
/ 5.x-7.x we'd also need to change that. Thus I think it's better to
have less ties between hw_wb and hw_cwb.
>
> [1]
> https://android.googlesource.com/kernel/msm-extra/display-drivers/+/e18d8e759a344ad4d86b31bbf8160cfe4c65b772/msm/sde/sde_hw_wb.c#265
>
> >
> >>
> >>>
> >>>>
> >>>> Thanks,
> >>>>
> >>>> Jessica Zhang
> >>>>
> >>>>>
> >>>>>> +
> >>>>>> + if (!cwb_reg_map) {
> >>>>>> + DPU_ERROR("failed cwb object creation\n");
> >>>>>> + return -ENOMEM;
> >>>>>> + }
> >>>>>> + }
> >>>>>> +
> >>>>>> +
> >>>>>> + for (i = 0; i < cat->cwb_count; i++) {
> >>>>>> + struct dpu_hw_blk_reg_map *cwb = &cwb_reg_map[i];
> >>>>>> +
> >>>>>> + cwb->blk_addr = mmio + cat->cwb[i].base;
> >>>>>> + cwb->log_mask = DPU_DBG_MASK_CWB;
> >>>>>> + }
> >>>>>> +
> >>>>>> for (i = 0; i < cat->wb_count; i++) {
> >>>>>> struct dpu_hw_wb *hw;
> >>>>>> const struct dpu_wb_cfg *wb = &cat->wb[i];
> >>>>>>
> >>>>>> - hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> >>>>>> + if (cat->cwb)
> >>>>>> + hw = dpu_hw_wb_init_with_cwb(dev, wb, mmio,
> >>>>>> + cat->mdss_ver, cwb_reg_map);
> >>>>>> + else
> >>>>>> + hw = dpu_hw_wb_init(dev, wb, mmio, cat->mdss_ver);
> >>>>>> +
> >>>>>> if (IS_ERR(hw)) {
> >>>>>> rc = PTR_ERR(hw);
> >>>>>> DPU_ERROR("failed wb object creation: err %d\n", rc);
> >>>>>>
> >>>>>> --
> >>>>>> 2.34.1
> >>>>>>
> >>>>>
> >>>>> --
> >>>>> With best wishes
> >>>>> Dmitry
> >>>
> >>>
> >>>
> >>> --
> >>> With best wishes
> >>> Dmitry
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 12/21] drm/msm/dpu: Add CWB to msm_display_topology
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (10 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 11/21] drm/msm/dpu: Add RM support for allocating CWB Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:21 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
` (8 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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 | 6 ++++--
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 11 +++++++++--
drivers/gpu/drm/msm/msm_drv.h | 2 ++
3 files changed, 15 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index bebae365c036..1b0cc899e8c1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1176,6 +1176,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
*
@@ -1189,9 +1191,9 @@ static struct msm_display_topology dpu_crtc_get_topology(
* Add dspps to the reservation requirements if ctm is requested
*/
- if (topology.num_intf == 2)
+ if (topology.num_intf == 2 && !topology.cwb_enabled)
topology.num_lm = 2;
- else if (topology.num_dsc == 2)
+ else if (topology.num_dsc == 2 && !topology.cwb_enabled)
topology.num_lm = 2;
else if (dpu_kms->catalog->caps->has_3d_merge)
topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 738e9a081b10..13f84375e15d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -384,8 +384,15 @@ 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. Since only one CWB session can run at a time, 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/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index be016d7b4ef1..315895937832 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
@@ -88,6 +89,7 @@ struct msm_display_topology {
u32 num_dspp;
u32 num_dsc;
bool needs_cdm;
+ bool cwb_enabled;
};
/* Commit/Event thread specific structure */
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 12/21] drm/msm/dpu: Add CWB to msm_display_topology
2024-08-29 20:48 ` [PATCH 12/21] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
@ 2024-08-30 17:21 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:21 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:33PM GMT, Jessica Zhang wrote:
> 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 | 6 ++++--
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 11 +++++++++--
> drivers/gpu/drm/msm/msm_drv.h | 2 ++
> 3 files changed, 15 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index bebae365c036..1b0cc899e8c1 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1176,6 +1176,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
> *
> @@ -1189,9 +1191,9 @@ static struct msm_display_topology dpu_crtc_get_topology(
> * Add dspps to the reservation requirements if ctm is requested
> */
>
> - if (topology.num_intf == 2)
> + if (topology.num_intf == 2 && !topology.cwb_enabled)
> topology.num_lm = 2;
> - else if (topology.num_dsc == 2)
> + else if (topology.num_dsc == 2 && !topology.cwb_enabled)
> topology.num_lm = 2;
> else if (dpu_kms->catalog->caps->has_3d_merge)
> topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 738e9a081b10..13f84375e15d 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -384,8 +384,15 @@ 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. Since only one CWB session can run at a time, hardcode
> + * num_ctls to 1 if CWB is enabled
I don't think that havign one session is relevant here. Just specify
that we need to use a single CTL if CWB is in play.
> + */
> + 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/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index be016d7b4ef1..315895937832 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -1,5 +1,6 @@
> /* SPDX-License-Identifier: GPL-2.0-only */
> /*
> + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
> * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
> * Copyright (C) 2013 Red Hat
> * Author: Rob Clark <robdclark@gmail.com>
> @@ -88,6 +89,7 @@ struct msm_display_topology {
> u32 num_dspp;
> u32 num_dsc;
> bool needs_cdm;
> + bool cwb_enabled;
> };
>
> /* Commit/Event thread specific structure */
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (11 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 12/21] drm/msm/dpu: Add CWB to msm_display_topology Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:22 ` Dmitry Baryshkov
2024-09-02 13:36 ` Daniel Vetter
2024-08-29 20:48 ` [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
` (7 subsequent siblings)
20 siblings, 2 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 1b0cc899e8c1..99eaaca405a4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1306,6 +1306,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_requested = drm_crtc_in_clone_mode(crtc->state);
+ bool clone_mode_enabled = 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) {
@@ -1313,6 +1315,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] 59+ messages in thread* Re: [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes
2024-08-29 20:48 ` [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
@ 2024-08-30 17:22 ` Dmitry Baryshkov
2024-09-02 13:36 ` Daniel Vetter
1 sibling, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:22 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:34PM GMT, 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>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 1b0cc899e8c1..99eaaca405a4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1306,6 +1306,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_requested = drm_crtc_in_clone_mode(crtc->state);
No, use old CRTC state from drm_atomic_state.
> + bool clone_mode_enabled = 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) {
> @@ -1313,6 +1315,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))
PLease align to opening bracket. Drop extra brackets.
> + 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] 59+ messages in thread* Re: [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes
2024-08-29 20:48 ` [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
2024-08-30 17:22 ` Dmitry Baryshkov
@ 2024-09-02 13:36 ` Daniel Vetter
2024-09-02 19:20 ` Dmitry Baryshkov
1 sibling, 1 reply; 59+ messages in thread
From: Daniel Vetter @ 2024-09-02 13:36 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, quic_ebharadw, linux-arm-msm,
dri-devel, freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:34PM -0700, 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>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index 1b0cc899e8c1..99eaaca405a4 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1306,6 +1306,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_requested = drm_crtc_in_clone_mode(crtc->state);
> + bool clone_mode_enabled = 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) {
> @@ -1313,6 +1315,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;
So two things, and kinda about the overall patch series:
- msm is confused about crtc_state->mode_changed, e.g. it sets it if
crtc_state->active_changed, which is wrong. Or msm dpu code doesn't use
drm_atomic_crtc_needs_modeset() correctly.
- changing crtc_state->mode_changed from your crtc or plane callbacks
means you cannot use drm_atomic_helper_check directly, but need to roll
your own that calls drm_atomic_helper_check_modesets again as needed.
See the kerneldoc comment for drm_atomic_helper_check_modesets()
- the same holds if you set mode_changed from your encoder or bridge
functions, but I think this doesn't apply here for this patch.
I think it'd be really good to
- review existing kerneldoc and please submit patches where it's not clear
or detailed enough
- add checks to the atomic helper code to catch this. I think the best way
would be to check if drm_atomic_crtc_needs_modeset() changes outside of
areas where the helper code allows it already (essentially connector
functions setting ->connectors_changed), and set a new
drm_atomic_state->dirty_needs_modeset. Which
drm_atomic_helper_check_modeset would clear, and which would result in a
WARN_ON in drm_atomic_check if it's not yet cleared when the driver
returns with success.
Otherwise there's just no way I think to make sure drivers get this
right.
Can I please sign you up for these patches?
Thanks, Sima
> +
> if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> rc = dpu_crtc_assign_resources(crtc, crtc_state);
> if (rc < 0)
>
> --
> 2.34.1
>
--
Simona Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes
2024-09-02 13:36 ` Daniel Vetter
@ 2024-09-02 19:20 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-09-02 19:20 UTC (permalink / raw)
To: Jessica Zhang, Rob Clark, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Mon, Sep 02, 2024 at 03:36:11PM GMT, Daniel Vetter wrote:
> On Thu, Aug 29, 2024 at 01:48:34PM -0700, 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>
> > ---
> > drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 6 ++++++
> > 1 file changed, 6 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index 1b0cc899e8c1..99eaaca405a4 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -1306,6 +1306,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_requested = drm_crtc_in_clone_mode(crtc->state);
> > + bool clone_mode_enabled = 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) {
> > @@ -1313,6 +1315,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;
>
> So two things, and kinda about the overall patch series:
>
> - msm is confused about crtc_state->mode_changed, e.g. it sets it if
> crtc_state->active_changed, which is wrong. Or msm dpu code doesn't use
> drm_atomic_crtc_needs_modeset() correctly.
This seems to be a leftover from prehistoric times and it should be
removed or reworked. I'll take a look during the next development cycle.
>
> - changing crtc_state->mode_changed from your crtc or plane callbacks
> means you cannot use drm_atomic_helper_check directly, but need to roll
> your own that calls drm_atomic_helper_check_modesets again as needed.
> See the kerneldoc comment for drm_atomic_helper_check_modesets()
>
> - the same holds if you set mode_changed from your encoder or bridge
> functions, but I think this doesn't apply here for this patch.
Yes. But we have it already in dpu_encoder.c. And we didn't notice that.
We have the code in dpu_encoder.c which makes sure that the hardware
resources get reallocated if required. As we already have code in
msm_atomic.c which sets mode_changed for this purpose (before calling
drm_atomic_helper_check()) it might simply make sense to add pre-check
callbacks to msm/dpu encoder. I will try working on that during or after
the LPC if Abhinav doesn't pick up that issue.
In the end we still have debt regarding the allow_modeset in
msm_atomic_check(), I remember.
>
> I think it'd be really good to
>
> - review existing kerneldoc and please submit patches where it's not clear
> or detailed enough
>
> - add checks to the atomic helper code to catch this. I think the best way
> would be to check if drm_atomic_crtc_needs_modeset() changes outside of
> areas where the helper code allows it already (essentially connector
> functions setting ->connectors_changed), and set a new
> drm_atomic_state->dirty_needs_modeset. Which
> drm_atomic_helper_check_modeset would clear, and which would result in a
> WARN_ON in drm_atomic_check if it's not yet cleared when the driver
> returns with success.
>
> Otherwise there's just no way I think to make sure drivers get this
> right.
>
> Can I please sign you up for these patches?
Ack.
Thanks a lot for pointing out the issue!
>
> Thanks, Sima
>
> > +
> > if (drm_atomic_crtc_needs_modeset(crtc_state)) {
> > rc = dpu_crtc_assign_resources(crtc, crtc_state);
> > if (rc < 0)
> >
> > --
> > 2.34.1
> >
>
> --
> Simona Vetter
> Software Engineer, Intel Corporation
> http://blog.ffwll.ch
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (12 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 13/21] drm/msm/dpu: Require modeset if clone mode status changes Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:25 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
` (6 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Reserve dedicated pingpong blocks for CWB
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
*/
@@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
int num_pp, num_dsc;
+ bool is_cwb_encoder;
unsigned int dsc_mask = 0;
int i;
@@ -1067,6 +1068,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)) {
@@ -1077,9 +1080,15 @@ 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));
+ 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));
+
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 c43cb55fe1d2..c87790a1b940 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
@@ -77,6 +77,7 @@ 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,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 13f84375e15d..afad26556cd5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
return -EINVAL;
}
+static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
+
+ /*
+ * Reserve additional dedicated CWB pingpong blocks for each mixer
+ *
+ * TODO: add support for reserving non-dedicated CWB pingpong blocks
+ */
+ for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
+ cwb_pp_count < num_cwb_pp; i++) {
+ for (int j = PINGPONG_CWB_0 - PINGPONG_0;
+ 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_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;
+
+ 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
@@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
return ret;
}
+ if (topology->cwb_enabled) {
+ ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
+ crtc_id, topology);
+ if (ret) {
+ DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
+ return ret;
+ }
+ }
ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
topology);
@@ -706,6 +756,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);
@@ -745,6 +796,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);
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB
2024-08-29 20:48 ` [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
@ 2024-08-30 17:25 ` Dmitry Baryshkov
2024-08-30 20:28 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:25 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
> Reserve dedicated pingpong blocks for CWB
Please explain design ideas. Having just a single phrase is usually not
enough.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
> */
> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
> int num_pp, num_dsc;
> + bool is_cwb_encoder;
> unsigned int dsc_mask = 0;
> int i;
>
> @@ -1067,6 +1068,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)) {
> @@ -1077,9 +1080,15 @@ 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));
> + 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));
Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
> +
> 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 c43cb55fe1d2..c87790a1b940 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> @@ -77,6 +77,7 @@ 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,
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> index 13f84375e15d..afad26556cd5 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> return -EINVAL;
> }
>
> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
> +
> + /*
> + * Reserve additional dedicated CWB pingpong blocks for each mixer
> + *
> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
> + */
> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> + cwb_pp_count < num_cwb_pp; i++) {
> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
Alignment...
> + /*
> + * 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_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;
> +
> + 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
> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
> return ret;
> }
>
> + if (topology->cwb_enabled) {
> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
> + crtc_id, topology);
> + if (ret) {
> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
> + return ret;
> + }
> + }
>
> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> topology);
> @@ -706,6 +756,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);
> @@ -745,6 +796,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);
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB
2024-08-30 17:25 ` Dmitry Baryshkov
@ 2024-08-30 20:28 ` Jessica Zhang
2024-08-30 22:27 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-30 20:28 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:25 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
>> Reserve dedicated pingpong blocks for CWB
>
> Please explain design ideas. Having just a single phrase is usually not
> enough.
>
>>
>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>> ---
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
>> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
>> */
>> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
>> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
>> int num_pp, num_dsc;
>> + bool is_cwb_encoder;
>> unsigned int dsc_mask = 0;
>> int i;
>>
>> @@ -1067,6 +1068,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)) {
>> @@ -1077,9 +1080,15 @@ 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));
>> + 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));
>
> Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
Hi Dmitry,
Since both regular non-cwb pingpongs and pingpongs dedicated for cwb
both share the same pingpong_to_crtc_id map, I need a way to distinguish
between the real-time and dedicated cwb pingpongs.
If I don't do that, get_assigned_resources would populate the hw_pp
array for both the real-time and WB encoders with *only* the real-time
display pingpongs.
>
>> +
>> 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 c43cb55fe1d2..c87790a1b940 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>> @@ -77,6 +77,7 @@ 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,
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> index 13f84375e15d..afad26556cd5 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>> return -EINVAL;
>> }
>>
>> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
>> +
>> + /*
>> + * Reserve additional dedicated CWB pingpong blocks for each mixer
>> + *
>> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
>> + */
>> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>> + cwb_pp_count < num_cwb_pp; i++) {
>> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
>> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
>
> Alignment...
Ack -- for future reference, should I always align the second line with
the bracket of the previous line?
I thought the general guideline was 2 tabs, but I might be misremembering.
Thanks,
Jessica Zhang
>
>> + /*
>> + * 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_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;
>> +
>> + 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
>> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
>> return ret;
>> }
>>
>> + if (topology->cwb_enabled) {
>> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
>> + crtc_id, topology);
>> + if (ret) {
>> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
>> + return ret;
>> + }
>> + }
>>
>> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>> topology);
>> @@ -706,6 +756,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);
>> @@ -745,6 +796,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);
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB
2024-08-30 20:28 ` Jessica Zhang
@ 2024-08-30 22:27 ` Dmitry Baryshkov
2024-09-04 22:15 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 22:27 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Fri, 30 Aug 2024 at 23:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
> On 8/30/2024 10:25 AM, Dmitry Baryshkov wrote:
> > On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
> >> Reserve dedicated pingpong blocks for CWB
> >
> > Please explain design ideas. Having just a single phrase is usually not
> > enough.
> >
> >>
> >> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >> ---
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
> >> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
> >> */
> >> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> >> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
> >> int num_pp, num_dsc;
> >> + bool is_cwb_encoder;
> >> unsigned int dsc_mask = 0;
> >> int i;
> >>
> >> @@ -1067,6 +1068,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)) {
> >> @@ -1077,9 +1080,15 @@ 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));
> >> + 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));
> >
> > Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
>
> Hi Dmitry,
>
> Since both regular non-cwb pingpongs and pingpongs dedicated for cwb
> both share the same pingpong_to_crtc_id map, I need a way to distinguish
> between the real-time and dedicated cwb pingpongs.
>
> If I don't do that, get_assigned_resources would populate the hw_pp
> array for both the real-time and WB encoders with *only* the real-time
> display pingpongs.
I see. It looks like PINGPONG blocks should be allocated / filled
per-encoder, not per-CRTC. Likewise CDM is encoder-specific, not
CRTC-specific.
Does that solve the issue?
>
> >
> >> +
> >> 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 c43cb55fe1d2..c87790a1b940 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -77,6 +77,7 @@ 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,
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> index 13f84375e15d..afad26556cd5 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> >> return -EINVAL;
> >> }
> >>
> >> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
> >> +
> >> + /*
> >> + * Reserve additional dedicated CWB pingpong blocks for each mixer
> >> + *
> >> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
> >> + */
> >> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> >> + cwb_pp_count < num_cwb_pp; i++) {
> >> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
> >> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
> >
> > Alignment...
>
> Ack -- for future reference, should I always align the second line with
> the bracket of the previous line?
>
> I thought the general guideline was 2 tabs, but I might be misremembering.
I can't find the textual reference, however .clang-format in the root
dir has 'AlignAfterOpenBracket: Align'. I'm more or less ignorant for
the function argument alignment (especially if an old function is
being modified), but aligning the conditions and loops makes it easier
to read the code.
>
> Thanks,
>
> Jessica Zhang
>
> >
> >> + /*
> >> + * 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_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;
> >> +
> >> + 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
> >> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
> >> return ret;
> >> }
> >>
> >> + if (topology->cwb_enabled) {
> >> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
> >> + crtc_id, topology);
> >> + if (ret) {
> >> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
> >> + return ret;
> >> + }
> >> + }
> >>
> >> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> >> topology);
> >> @@ -706,6 +756,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);
> >> @@ -745,6 +796,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);
> >>
> >> --
> >> 2.34.1
> >>
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
On Fri, 30 Aug 2024 at 23:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 8/30/2024 10:25 AM, Dmitry Baryshkov wrote:
> > On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
> >> Reserve dedicated pingpong blocks for CWB
> >
> > Please explain design ideas. Having just a single phrase is usually not
> > enough.
> >
> >>
> >> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> >> ---
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
> >> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
> >> */
> >> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
> >> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
> >> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
> >> int num_pp, num_dsc;
> >> + bool is_cwb_encoder;
> >> unsigned int dsc_mask = 0;
> >> int i;
> >>
> >> @@ -1067,6 +1068,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)) {
> >> @@ -1077,9 +1080,15 @@ 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));
> >> + 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));
> >
> > Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
>
> Hi Dmitry,
>
> Since both regular non-cwb pingpongs and pingpongs dedicated for cwb
> both share the same pingpong_to_crtc_id map, I need a way to distinguish
> between the real-time and dedicated cwb pingpongs.
>
> If I don't do that, get_assigned_resources would populate the hw_pp
> array for both the real-time and WB encoders with *only* the real-time
> display pingpongs.
>
> >
> >> +
> >> 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 c43cb55fe1d2..c87790a1b940 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
> >> @@ -77,6 +77,7 @@ 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,
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> index 13f84375e15d..afad26556cd5 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
> >> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
> >> return -EINVAL;
> >> }
> >>
> >> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
> >> +
> >> + /*
> >> + * Reserve additional dedicated CWB pingpong blocks for each mixer
> >> + *
> >> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
> >> + */
> >> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
> >> + cwb_pp_count < num_cwb_pp; i++) {
> >> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
> >> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
> >
> > Alignment...
>
> Ack -- for future reference, should I always align the second line with
> the bracket of the previous line?
>
> I thought the general guideline was 2 tabs, but I might be misremembering.
>
> Thanks,
>
> Jessica Zhang
>
> >
> >> + /*
> >> + * 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_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;
> >> +
> >> + 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
> >> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
> >> return ret;
> >> }
> >>
> >> + if (topology->cwb_enabled) {
> >> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
> >> + crtc_id, topology);
> >> + if (ret) {
> >> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
> >> + return ret;
> >> + }
> >> + }
> >>
> >> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
> >> topology);
> >> @@ -706,6 +756,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);
> >> @@ -745,6 +796,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);
> >>
> >> --
> >> 2.34.1
> >>
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB
2024-08-30 22:27 ` Dmitry Baryshkov
@ 2024-09-04 22:15 ` Jessica Zhang
0 siblings, 0 replies; 59+ messages in thread
From: Jessica Zhang @ 2024-09-04 22:15 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 3:27 PM, Dmitry Baryshkov wrote:
> On Fri, 30 Aug 2024 at 23:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>> On 8/30/2024 10:25 AM, Dmitry Baryshkov wrote:
>>> On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
>>>> Reserve dedicated pingpong blocks for CWB
>>>
>>> Please explain design ideas. Having just a single phrase is usually not
>>> enough.
>>>
>>>>
>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
>>>> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
>>>> */
>>>> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
>>>> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
>>>> int num_pp, num_dsc;
>>>> + bool is_cwb_encoder;
>>>> unsigned int dsc_mask = 0;
>>>> int i;
>>>>
>>>> @@ -1067,6 +1068,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)) {
>>>> @@ -1077,9 +1080,15 @@ 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));
>>>> + 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));
>>>
>>> Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
>>
>> Hi Dmitry,
>>
>> Since both regular non-cwb pingpongs and pingpongs dedicated for cwb
>> both share the same pingpong_to_crtc_id map, I need a way to distinguish
>> between the real-time and dedicated cwb pingpongs.
>>
>> If I don't do that, get_assigned_resources would populate the hw_pp
>> array for both the real-time and WB encoders with *only* the real-time
>> display pingpongs.
>
> I see. It looks like PINGPONG blocks should be allocated / filled
> per-encoder, not per-CRTC. Likewise CDM is encoder-specific, not
> CRTC-specific.
> Does that solve the issue?
As discussed offline, let's keep all resources allocated per-CRTC
>
>>
>>>
>>>> +
>>>> 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 c43cb55fe1d2..c87790a1b940 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> @@ -77,6 +77,7 @@ 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,
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index 13f84375e15d..afad26556cd5 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>> return -EINVAL;
>>>> }
>>>>
>>>> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
>>>> +
>>>> + /*
>>>> + * Reserve additional dedicated CWB pingpong blocks for each mixer
>>>> + *
>>>> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
>>>> + */
>>>> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>>>> + cwb_pp_count < num_cwb_pp; i++) {
>>>> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
>>>> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
>>>
>>> Alignment...
>>
>> Ack -- for future reference, should I always align the second line with
>> the bracket of the previous line?
>>
>> I thought the general guideline was 2 tabs, but I might be misremembering.
>
> I can't find the textual reference, however .clang-format in the root
> dir has 'AlignAfterOpenBracket: Align'. I'm more or less ignorant for
> the function argument alignment (especially if an old function is
> being modified), but aligning the conditions and loops makes it easier
> to read the code.
Ah, got it. I'll configure my editor to keep to these guidelines then.
Thanks,
Jessica Zhang
>
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>>>
>>>> + /*
>>>> + * 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_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;
>>>> +
>>>> + 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
>>>> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
>>>> return ret;
>>>> }
>>>>
>>>> + if (topology->cwb_enabled) {
>>>> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
>>>> + crtc_id, topology);
>>>> + if (ret) {
>>>> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
>>>> + return ret;
>>>> + }
>>>> + }
>>>>
>>>> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>>>> topology);
>>>> @@ -706,6 +756,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);
>>>> @@ -745,6 +796,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);
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>
>
>
> --
> With best wishes
> Dmitry
>
> On Fri, 30 Aug 2024 at 23:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>>
>>
>>
>> On 8/30/2024 10:25 AM, Dmitry Baryshkov wrote:
>>> On Thu, Aug 29, 2024 at 01:48:35PM GMT, Jessica Zhang wrote:
>>>> Reserve dedicated pingpong blocks for CWB
>>>
>>> Please explain design ideas. Having just a single phrase is usually not
>>> enough.
>>>
>>>>
>>>> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
>>>> ---
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 17 ++++++--
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h | 1 +
>>>> drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 65 +++++++++++++++++++++++++++++
>>>> 3 files changed, 79 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 36b677cf9c7a..f1bd14d1f89e 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>
>>>> */
>>>> @@ -1054,6 +1054,7 @@ static void dpu_encoder_virt_atomic_mode_set(struct drm_encoder *drm_enc,
>>>> struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
>>>> struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
>>>> int num_pp, num_dsc;
>>>> + bool is_cwb_encoder;
>>>> unsigned int dsc_mask = 0;
>>>> int i;
>>>>
>>>> @@ -1067,6 +1068,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)) {
>>>> @@ -1077,9 +1080,15 @@ 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));
>>>> + 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));
>>>
>>> Why is this necessary? Can we still use DPU_HW_BLK_PINGPONG?
>>
>> Hi Dmitry,
>>
>> Since both regular non-cwb pingpongs and pingpongs dedicated for cwb
>> both share the same pingpong_to_crtc_id map, I need a way to distinguish
>> between the real-time and dedicated cwb pingpongs.
>>
>> If I don't do that, get_assigned_resources would populate the hw_pp
>> array for both the real-time and WB encoders with *only* the real-time
>> display pingpongs.
>>
>>>
>>>> +
>>>> 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 c43cb55fe1d2..c87790a1b940 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h
>>>> @@ -77,6 +77,7 @@ 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,
>>>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> index 13f84375e15d..afad26556cd5 100644
>>>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
>>>> @@ -236,6 +236,48 @@ static int _dpu_rm_get_lm_peer(struct dpu_rm *rm, int primary_idx)
>>>> return -EINVAL;
>>>> }
>>>>
>>>> +static int _dpu_rm_reserve_cwb_pingpong(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_idx[MAX_BLOCKS];
>>>> +
>>>> + /*
>>>> + * Reserve additional dedicated CWB pingpong blocks for each mixer
>>>> + *
>>>> + * TODO: add support for reserving non-dedicated CWB pingpong blocks
>>>> + */
>>>> + for (int i = 0; i < ARRAY_SIZE(rm->mixer_blks) &&
>>>> + cwb_pp_count < num_cwb_pp; i++) {
>>>> + for (int j = PINGPONG_CWB_0 - PINGPONG_0;
>>>> + j < ARRAY_SIZE(rm->pingpong_blks); j++) {
>>>
>>> Alignment...
>>
>> Ack -- for future reference, should I always align the second line with
>> the bracket of the previous line?
>>
>> I thought the general guideline was 2 tabs, but I might be misremembering.
>>
>> Thanks,
>>
>> Jessica Zhang
>>
>>>
>>>> + /*
>>>> + * 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_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;
>>>> +
>>>> + 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
>>>> @@ -617,6 +659,14 @@ static int _dpu_rm_make_reservation(
>>>> return ret;
>>>> }
>>>>
>>>> + if (topology->cwb_enabled) {
>>>> + ret = _dpu_rm_reserve_cwb_pingpong(rm, global_state,
>>>> + crtc_id, topology);
>>>> + if (ret) {
>>>> + DPU_ERROR("unable to find appropriate dcwb pingpongs\n");
>>>> + return ret;
>>>> + }
>>>> + }
>>>>
>>>> ret = _dpu_rm_reserve_ctls(rm, global_state, crtc_id,
>>>> topology);
>>>> @@ -706,6 +756,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);
>>>> @@ -745,6 +796,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);
>>>>
>>>> --
>>>> 2.34.1
>>>>
>>>
>>> --
>>> With best wishes
>>> Dmitry
>
>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (13 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 14/21] drm/msm/dpu: Reserve resources for CWB Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:47 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 16/21] drm/msm/dpu: Program hw_ctl to support CWB Jessica Zhang
` (5 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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_crtc.c | 29 +++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 43 ++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 9 ++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 ++++++++-
.../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 43 +++++++++++++++++++++-
5 files changed, 139 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 99eaaca405a4..c8ef59af444c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1236,6 +1236,33 @@ static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
return true;
}
+static void dpu_crtc_set_encoder_cwb_mask(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
+{
+ struct drm_encoder *drm_enc;
+ struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
+ int cwb_idx = 0;
+ u32 cwb_mask = 0;
+
+ /*
+ * Since there can only be one CWB session at a time, if the CRTC LM
+ * starts with an even index we start with CWB_0. If the LM index is
+ * odd, we start with CWB_1
+ */
+ if (cstate->mixers[0].hw_lm)
+ cwb_idx = (cstate->mixers[0].hw_lm->idx - LM_0) % 2;
+
+ if (drm_crtc_in_clone_mode(crtc_state)) {
+ for (int i = 0; i < cstate->num_mixers; i++) {
+ cwb_mask |= (1 << cwb_idx);
+ cwb_idx++;
+ }
+ }
+
+ drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
+ dpu_encoder_set_cwb_mask(drm_enc, cwb_mask);
+}
+
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];
@@ -1329,6 +1356,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
!dpu_crtc_has_valid_clones(crtc, crtc_state))
return -EINVAL;
+ dpu_crtc_set_encoder_cwb_mask(crtc, crtc_state);
+
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 f1bd14d1f89e..0f8f6c0182d5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -162,6 +162,7 @@ enum dpu_enc_rc_states {
* clks and resources after IDLE_TIMEOUT time.
* @topology: topology of the display
* @idle_timeout: idle timeout duration in milliseconds
+ * @cwb_mask: current encoder is in clone mode
* @wide_bus_en: wide bus is enabled on this interface
* @dsc: drm_dsc_config pointer, for DSC-enabled encoders
*/
@@ -202,6 +203,7 @@ struct dpu_encoder_virt {
struct msm_display_topology topology;
u32 idle_timeout;
+ u32 cwb_mask;
bool wide_bus_en;
@@ -638,6 +640,33 @@ bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_st
return false;
}
+void dpu_encoder_set_cwb_mask(struct drm_encoder *enc, u32 cwb_mask)
+{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
+
+ dpu_enc->cwb_mask = cwb_mask;
+}
+
+u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc)
+{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
+
+ if (!dpu_enc)
+ return 0;
+
+ return dpu_enc->cwb_mask;
+}
+
+bool dpu_encoder_in_clone_mode(struct drm_encoder *enc)
+{
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
+
+ if (!dpu_enc)
+ return 0;
+
+ return dpu_enc->cwb_mask != 0;
+}
+
struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
{
struct msm_drm_private *priv = drm_enc->dev->dev_private;
@@ -2019,6 +2048,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
struct dpu_hw_intf_cfg intf_cfg = { 0 };
int i;
+ enum dpu_cwb cwb_idx;
struct dpu_encoder_virt *dpu_enc;
dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
@@ -2040,6 +2070,19 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
/* mark WB flush as pending */
if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx);
+
+ if (dpu_enc->cwb_mask) {
+ for (i = 0; i < hweight32(dpu_enc->cwb_mask); i++) {
+ if (!(dpu_enc->cwb_mask & (1 << i)))
+ continue;
+
+ cwb_idx = i + CWB_0;
+
+ if (phys_enc->hw_wb->ops.setup_input_ctrl)
+ phys_enc->hw_wb->ops.setup_input_ctrl(phys_enc->hw_wb,
+ cwb_idx, PINGPONG_NONE);
+ }
+ }
} else {
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
index 0d27e50384f0..131bb8b2c0ee 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>
@@ -188,6 +188,13 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
*/
bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
+/**
+ * dpu_encoder_set_cwb_mask - set the CWB blocks mask for the encoder
+ * @drm_enc: Pointer to previously created drm encoder structure
+ * @cwb_mask: CWB blocks mask to set for the encoder
+ */
+void dpu_encoder_set_cwb_mask(struct drm_encoder *drm_enc, u32 cwb_mask);
+
/**
* dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
* @drm_enc: Pointer to previously created drm encoder structure
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 e77ebe3a68da..f0e5c5b073e5 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.
*/
@@ -339,6 +339,22 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
*/
unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
+/**
+ * dpu_encoder_get_cwb_mask - get CWB blocks mask for DPU encoder
+ * This helper function is used by physical encoders to get the CWB blocks
+ * mask used for this encoder.
+ * @enc: Pointer to DRM encoder structure
+ */
+u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc);
+
+/**
+ * dpu_encoder_in_clone_mode - determine if DPU encoder is in clone mode
+ * This helper is used by physical encoders to determine if the encoder is in
+ * clone mode.
+ * @enc: Pointer to DRM encoder structure
+ */
+bool dpu_encoder_in_clone_mode(struct drm_encoder *enc);
+
/**
* dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
* This helper function is used by physical encoder to get DSC config
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 882c717859ce..e1ec64ffc742 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__
@@ -264,6 +264,45 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
}
}
+static void dpu_encoder_phys_wb_setup_cwb(struct dpu_encoder_phys *phys_enc)
+{
+ struct dpu_hw_wb *hw_wb;
+ struct dpu_hw_ctl *hw_ctl;
+ struct dpu_hw_pingpong *hw_pp;
+ u32 cwb_mask, cwb_idx;
+
+ if (!phys_enc)
+ return;
+
+ hw_wb = phys_enc->hw_wb;
+ hw_ctl = phys_enc->hw_ctl;
+ hw_pp = phys_enc->hw_pp;
+
+ if (!hw_wb || !hw_ctl || !hw_pp) {
+ DPU_DEBUG("[wb:%d] no ctl or pp assigned\n", hw_wb->idx - WB_0);
+ return;
+ }
+
+ cwb_mask = dpu_encoder_get_cwb_mask(phys_enc->parent);
+
+ for (int i = 0; i < hweight32(cwb_mask); i++) {
+ if (!(cwb_mask & (1 << i)))
+ continue;
+
+ cwb_idx = i + CWB_0;
+
+ if (hw_wb->ops.setup_input_ctrl)
+ hw_wb->ops.setup_input_ctrl(hw_wb, cwb_idx, hw_pp->idx + i);
+
+ /*
+ * The CWB mux supports using LM or DSPP as tap points. For now,
+ * always use DSPP tap point
+ */
+ if (hw_wb->ops.setup_input_mode)
+ hw_wb->ops.setup_input_mode(hw_wb, cwb_idx, INPUT_MODE_DSPP_OUT);
+ }
+}
+
/**
* _dpu_encoder_phys_wb_update_flush - flush hardware update
* @phys_enc: Pointer to physical encoder
@@ -342,6 +381,8 @@ static void dpu_encoder_phys_wb_setup(
dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
+ dpu_encoder_phys_wb_setup_cwb(phys_enc);
+
dpu_encoder_phys_wb_setup_ctl(phys_enc);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 59+ messages in thread* Re: [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder
2024-08-29 20:48 ` [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
@ 2024-08-30 17:47 ` Dmitry Baryshkov
2024-08-30 20:28 ` Jessica Zhang
0 siblings, 1 reply; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:47 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:36PM GMT, 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_crtc.c | 29 +++++++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 43 ++++++++++++++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 9 ++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 ++++++++-
> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 43 +++++++++++++++++++++-
> 5 files changed, 139 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 99eaaca405a4..c8ef59af444c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -1236,6 +1236,33 @@ static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
> return true;
> }
>
> +static void dpu_crtc_set_encoder_cwb_mask(struct drm_crtc *crtc,
> + struct drm_crtc_state *crtc_state)
> +{
> + struct drm_encoder *drm_enc;
> + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
> + int cwb_idx = 0;
> + u32 cwb_mask = 0;
> +
> + /*
> + * Since there can only be one CWB session at a time, if the CRTC LM
> + * starts with an even index we start with CWB_0. If the LM index is
> + * odd, we start with CWB_1
I'd prefer to get indices from RM. They can be set during mode_set /
atomic_check calls.
> + */
> + if (cstate->mixers[0].hw_lm)
> + cwb_idx = (cstate->mixers[0].hw_lm->idx - LM_0) % 2;
> +
> + if (drm_crtc_in_clone_mode(crtc_state)) {
> + for (int i = 0; i < cstate->num_mixers; i++) {
> + cwb_mask |= (1 << cwb_idx);
> + cwb_idx++;
> + }
> + }
> +
> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
> + dpu_encoder_set_cwb_mask(drm_enc, cwb_mask);
Ugh, no. This function writes to dpu_enc, however there is being called
from atomic_check(). You can not write non-state variables here as the
commit can get completely dropped.
> +}
> +
> 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];
> @@ -1329,6 +1356,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> !dpu_crtc_has_valid_clones(crtc, crtc_state))
> return -EINVAL;
>
> + dpu_crtc_set_encoder_cwb_mask(crtc, crtc_state);
> +
> 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 f1bd14d1f89e..0f8f6c0182d5 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -162,6 +162,7 @@ enum dpu_enc_rc_states {
> * clks and resources after IDLE_TIMEOUT time.
> * @topology: topology of the display
> * @idle_timeout: idle timeout duration in milliseconds
> + * @cwb_mask: current encoder is in clone mode
> * @wide_bus_en: wide bus is enabled on this interface
> * @dsc: drm_dsc_config pointer, for DSC-enabled encoders
> */
> @@ -202,6 +203,7 @@ struct dpu_encoder_virt {
> struct msm_display_topology topology;
>
> u32 idle_timeout;
> + u32 cwb_mask;
>
> bool wide_bus_en;
>
> @@ -638,6 +640,33 @@ bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_st
> return false;
> }
>
> +void dpu_encoder_set_cwb_mask(struct drm_encoder *enc, u32 cwb_mask)
> +{
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> +
> + dpu_enc->cwb_mask = cwb_mask;
> +}
> +
> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc)
> +{
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> +
> + if (!dpu_enc)
> + return 0;
> +
> + return dpu_enc->cwb_mask;
> +}
> +
> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc)
> +{
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> +
> + if (!dpu_enc)
> + return 0;
> +
> + return dpu_enc->cwb_mask != 0;
> +}
> +
> struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
> {
> struct msm_drm_private *priv = drm_enc->dev->dev_private;
> @@ -2019,6 +2048,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
> struct dpu_hw_intf_cfg intf_cfg = { 0 };
> int i;
> + enum dpu_cwb cwb_idx;
> struct dpu_encoder_virt *dpu_enc;
>
> dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
> @@ -2040,6 +2070,19 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> /* mark WB flush as pending */
> if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
> phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx);
> +
> + if (dpu_enc->cwb_mask) {
> + for (i = 0; i < hweight32(dpu_enc->cwb_mask); i++) {
This will break if cwb_mask starts from bit 1: hweight will count bits,
so the loop will not cover the highest bit set.
> + if (!(dpu_enc->cwb_mask & (1 << i)))
> + continue;
> +
> + cwb_idx = i + CWB_0;
> +
> + if (phys_enc->hw_wb->ops.setup_input_ctrl)
> + phys_enc->hw_wb->ops.setup_input_ctrl(phys_enc->hw_wb,
> + cwb_idx, PINGPONG_NONE);
> + }
> + }
> } else {
> for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk)
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> index 0d27e50384f0..131bb8b2c0ee 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>
> @@ -188,6 +188,13 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
> */
> bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
>
> +/**
> + * dpu_encoder_set_cwb_mask - set the CWB blocks mask for the encoder
> + * @drm_enc: Pointer to previously created drm encoder structure
> + * @cwb_mask: CWB blocks mask to set for the encoder
> + */
> +void dpu_encoder_set_cwb_mask(struct drm_encoder *drm_enc, u32 cwb_mask);
> +
> /**
> * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
> * @drm_enc: Pointer to previously created drm encoder structure
> 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 e77ebe3a68da..f0e5c5b073e5 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.
> */
>
> @@ -339,6 +339,22 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
> */
> unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
>
> +/**
> + * dpu_encoder_get_cwb_mask - get CWB blocks mask for DPU encoder
> + * This helper function is used by physical encoders to get the CWB blocks
> + * mask used for this encoder.
> + * @enc: Pointer to DRM encoder structure
> + */
> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc);
> +
> +/**
> + * dpu_encoder_in_clone_mode - determine if DPU encoder is in clone mode
> + * This helper is used by physical encoders to determine if the encoder is in
> + * clone mode.
> + * @enc: Pointer to DRM encoder structure
> + */
> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc);
> +
> /**
> * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
> * This helper function is used by physical encoder to get DSC config
> 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 882c717859ce..e1ec64ffc742 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__
> @@ -264,6 +264,45 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> }
> }
>
> +static void dpu_encoder_phys_wb_setup_cwb(struct dpu_encoder_phys *phys_enc)
> +{
> + struct dpu_hw_wb *hw_wb;
> + struct dpu_hw_ctl *hw_ctl;
> + struct dpu_hw_pingpong *hw_pp;
> + u32 cwb_mask, cwb_idx;
> +
> + if (!phys_enc)
> + return;
> +
> + hw_wb = phys_enc->hw_wb;
> + hw_ctl = phys_enc->hw_ctl;
> + hw_pp = phys_enc->hw_pp;
> +
> + if (!hw_wb || !hw_ctl || !hw_pp) {
> + DPU_DEBUG("[wb:%d] no ctl or pp assigned\n", hw_wb->idx - WB_0);
> + return;
> + }
> +
> + cwb_mask = dpu_encoder_get_cwb_mask(phys_enc->parent);
> +
> + for (int i = 0; i < hweight32(cwb_mask); i++) {
> + if (!(cwb_mask & (1 << i)))
> + continue;
> +
> + cwb_idx = i + CWB_0;
> +
> + if (hw_wb->ops.setup_input_ctrl)
> + hw_wb->ops.setup_input_ctrl(hw_wb, cwb_idx, hw_pp->idx + i);
> +
> + /*
> + * The CWB mux supports using LM or DSPP as tap points. For now,
> + * always use DSPP tap point
> + */
> + if (hw_wb->ops.setup_input_mode)
> + hw_wb->ops.setup_input_mode(hw_wb, cwb_idx, INPUT_MODE_DSPP_OUT);
> + }
> +}
> +
> /**
> * _dpu_encoder_phys_wb_update_flush - flush hardware update
> * @phys_enc: Pointer to physical encoder
> @@ -342,6 +381,8 @@ static void dpu_encoder_phys_wb_setup(
>
> dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
>
> + dpu_encoder_phys_wb_setup_cwb(phys_enc);
> +
> dpu_encoder_phys_wb_setup_ctl(phys_enc);
> }
>
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder
2024-08-30 17:47 ` Dmitry Baryshkov
@ 2024-08-30 20:28 ` Jessica Zhang
2024-08-30 22:57 ` Dmitry Baryshkov
0 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-30 20:28 UTC (permalink / raw)
To: Dmitry Baryshkov
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On 8/30/2024 10:47 AM, Dmitry Baryshkov wrote:
> On Thu, Aug 29, 2024 at 01:48:36PM GMT, 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_crtc.c | 29 +++++++++++++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 43 ++++++++++++++++++++++
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 9 ++++-
>> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 ++++++++-
>> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 43 +++++++++++++++++++++-
>> 5 files changed, 139 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 99eaaca405a4..c8ef59af444c 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
>> @@ -1236,6 +1236,33 @@ static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
>> return true;
>> }
>>
>> +static void dpu_crtc_set_encoder_cwb_mask(struct drm_crtc *crtc,
>> + struct drm_crtc_state *crtc_state)
>> +{
>> + struct drm_encoder *drm_enc;
>> + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
>> + int cwb_idx = 0;
>> + u32 cwb_mask = 0;
>> +
>> + /*
>> + * Since there can only be one CWB session at a time, if the CRTC LM
>> + * starts with an even index we start with CWB_0. If the LM index is
>> + * odd, we start with CWB_1
>
> I'd prefer to get indices from RM. They can be set during mode_set /
> atomic_check calls.
Hi Dmitry,
Do you mean having CWB being managed by RM or using rm's
get_assigned_blks() to grab the LM indices?
>
>> + */
>> + if (cstate->mixers[0].hw_lm)
>> + cwb_idx = (cstate->mixers[0].hw_lm->idx - LM_0) % 2;
>> +
>> + if (drm_crtc_in_clone_mode(crtc_state)) {
>> + for (int i = 0; i < cstate->num_mixers; i++) {
>> + cwb_mask |= (1 << cwb_idx);
>> + cwb_idx++;
>> + }
>> + }
>> +
>> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
>> + dpu_encoder_set_cwb_mask(drm_enc, cwb_mask);
>
> Ugh, no. This function writes to dpu_enc, however there is being called
> from atomic_check(). You can not write non-state variables here as the
> commit can get completely dropped.
Ack -- will change this API to `dpu_crtc_get_cwb_mask()` and call it
from dpu_encoder_virt_mode_set() instead.
>
>> +}
>> +
>> 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];
>> @@ -1329,6 +1356,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
>> !dpu_crtc_has_valid_clones(crtc, crtc_state))
>> return -EINVAL;
>>
>> + dpu_crtc_set_encoder_cwb_mask(crtc, crtc_state);
>> +
>> 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 f1bd14d1f89e..0f8f6c0182d5 100644
>> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
>> @@ -162,6 +162,7 @@ enum dpu_enc_rc_states {
>> * clks and resources after IDLE_TIMEOUT time.
>> * @topology: topology of the display
>> * @idle_timeout: idle timeout duration in milliseconds
>> + * @cwb_mask: current encoder is in clone mode
>> * @wide_bus_en: wide bus is enabled on this interface
>> * @dsc: drm_dsc_config pointer, for DSC-enabled encoders
>> */
>> @@ -202,6 +203,7 @@ struct dpu_encoder_virt {
>> struct msm_display_topology topology;
>>
>> u32 idle_timeout;
>> + u32 cwb_mask;
>>
>> bool wide_bus_en;
>>
>> @@ -638,6 +640,33 @@ bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_st
>> return false;
>> }
>>
>> +void dpu_encoder_set_cwb_mask(struct drm_encoder *enc, u32 cwb_mask)
>> +{
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
>> +
>> + dpu_enc->cwb_mask = cwb_mask;
>> +}
>> +
>> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc)
>> +{
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
>> +
>> + if (!dpu_enc)
>> + return 0;
>> +
>> + return dpu_enc->cwb_mask;
>> +}
>> +
>> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc)
>> +{
>> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
>> +
>> + if (!dpu_enc)
>> + return 0;
>> +
>> + return dpu_enc->cwb_mask != 0;
>> +}
>> +
>> struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
>> {
>> struct msm_drm_private *priv = drm_enc->dev->dev_private;
>> @@ -2019,6 +2048,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>> struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
>> struct dpu_hw_intf_cfg intf_cfg = { 0 };
>> int i;
>> + enum dpu_cwb cwb_idx;
>> struct dpu_encoder_virt *dpu_enc;
>>
>> dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
>> @@ -2040,6 +2070,19 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
>> /* mark WB flush as pending */
>> if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
>> phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx);
>> +
>> + if (dpu_enc->cwb_mask) {
>> + for (i = 0; i < hweight32(dpu_enc->cwb_mask); i++) {
>
> This will break if cwb_mask starts from bit 1: hweight will count bits,
> so the loop will not cover the highest bit set.
Ah, good point. I should be doing `hweight() + 1` here instead.
>
>> + if (!(dpu_enc->cwb_mask & (1 << i)))
>> + continue;
>> +
>> + cwb_idx = i + CWB_0;
>> +
>> + if (phys_enc->hw_wb->ops.setup_input_ctrl)
>> + phys_enc->hw_wb->ops.setup_input_ctrl(phys_enc->hw_wb,
>> + cwb_idx, PINGPONG_NONE);
>> + }
>> + }
>> } else {
>> for (i = 0; i < dpu_enc->num_phys_encs; i++) {
>> if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk)
>> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
>> index 0d27e50384f0..131bb8b2c0ee 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>
>> @@ -188,6 +188,13 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
>> */
>> bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
>>
>> +/**
>> + * dpu_encoder_set_cwb_mask - set the CWB blocks mask for the encoder
>> + * @drm_enc: Pointer to previously created drm encoder structure
>> + * @cwb_mask: CWB blocks mask to set for the encoder
>> + */
>> +void dpu_encoder_set_cwb_mask(struct drm_encoder *drm_enc, u32 cwb_mask);
>> +
>> /**
>> * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
>> * @drm_enc: Pointer to previously created drm encoder structure
>> 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 e77ebe3a68da..f0e5c5b073e5 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.
>> */
>>
>> @@ -339,6 +339,22 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
>> */
>> unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
>>
>> +/**
>> + * dpu_encoder_get_cwb_mask - get CWB blocks mask for DPU encoder
>> + * This helper function is used by physical encoders to get the CWB blocks
>> + * mask used for this encoder.
>> + * @enc: Pointer to DRM encoder structure
>> + */
>> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc);
>> +
>> +/**
>> + * dpu_encoder_in_clone_mode - determine if DPU encoder is in clone mode
>> + * This helper is used by physical encoders to determine if the encoder is in
>> + * clone mode.
>> + * @enc: Pointer to DRM encoder structure
>> + */
>> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc);
>> +
>> /**
>> * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
>> * This helper function is used by physical encoder to get DSC config
>> 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 882c717859ce..e1ec64ffc742 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__
>> @@ -264,6 +264,45 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
>> }
>> }
>>
>> +static void dpu_encoder_phys_wb_setup_cwb(struct dpu_encoder_phys *phys_enc)
>> +{
>> + struct dpu_hw_wb *hw_wb;
>> + struct dpu_hw_ctl *hw_ctl;
>> + struct dpu_hw_pingpong *hw_pp;
>> + u32 cwb_mask, cwb_idx;
>> +
>> + if (!phys_enc)
>> + return;
>> +
>> + hw_wb = phys_enc->hw_wb;
>> + hw_ctl = phys_enc->hw_ctl;
>> + hw_pp = phys_enc->hw_pp;
>> +
>> + if (!hw_wb || !hw_ctl || !hw_pp) {
>> + DPU_DEBUG("[wb:%d] no ctl or pp assigned\n", hw_wb->idx - WB_0);
>> + return;
>> + }
>> +
>> + cwb_mask = dpu_encoder_get_cwb_mask(phys_enc->parent);
>> +
>> + for (int i = 0; i < hweight32(cwb_mask); i++) {
>> + if (!(cwb_mask & (1 << i)))
>> + continue;
>> +
>> + cwb_idx = i + CWB_0;
>> +
>> + if (hw_wb->ops.setup_input_ctrl)
>> + hw_wb->ops.setup_input_ctrl(hw_wb, cwb_idx, hw_pp->idx + i);
Just wanted to note that the value being programmed here is incorrect.
Instead of passing in the index of the dedicated cwb pingpong, it should
instead be the index of the *real time display* pingpong.
To grab the correct value, I'm thinking of adding a DPU encoder API to
query the RM for (non-dedicated CWB) HW_BLK_PINGPONG to grab the
pingpong indices for the real-time encoder. I'll then call that API here
and pass the resulting real-time hw_pp index.
Please let me know if you have any feedback on this proposal or
alternate solutions.
Thanks,
Jessica Zhang
>> +
>> + /*
>> + * The CWB mux supports using LM or DSPP as tap points. For now,
>> + * always use DSPP tap point
>> + */
>> + if (hw_wb->ops.setup_input_mode)
>> + hw_wb->ops.setup_input_mode(hw_wb, cwb_idx, INPUT_MODE_DSPP_OUT);
>> + }
>> +}
>> +
>> /**
>> * _dpu_encoder_phys_wb_update_flush - flush hardware update
>> * @phys_enc: Pointer to physical encoder
>> @@ -342,6 +381,8 @@ static void dpu_encoder_phys_wb_setup(
>>
>> dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
>>
>> + dpu_encoder_phys_wb_setup_cwb(phys_enc);
>> +
>> dpu_encoder_phys_wb_setup_ctl(phys_enc);
>> }
>>
>>
>> --
>> 2.34.1
>>
>
> --
> With best wishes
> Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread* Re: [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder
2024-08-30 20:28 ` Jessica Zhang
@ 2024-08-30 22:57 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 22:57 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Fri, 30 Aug 2024 at 23:28, Jessica Zhang <quic_jesszhan@quicinc.com> wrote:
>
>
>
> On 8/30/2024 10:47 AM, Dmitry Baryshkov wrote:
> > On Thu, Aug 29, 2024 at 01:48:36PM GMT, 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_crtc.c | 29 +++++++++++++++
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 43 ++++++++++++++++++++++
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 9 ++++-
> >> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 18 ++++++++-
> >> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 43 +++++++++++++++++++++-
> >> 5 files changed, 139 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 99eaaca405a4..c8ef59af444c 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> >> @@ -1236,6 +1236,33 @@ static bool dpu_crtc_has_valid_clones(struct drm_crtc *crtc,
> >> return true;
> >> }
> >>
> >> +static void dpu_crtc_set_encoder_cwb_mask(struct drm_crtc *crtc,
> >> + struct drm_crtc_state *crtc_state)
> >> +{
> >> + struct drm_encoder *drm_enc;
> >> + struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc_state);
> >> + int cwb_idx = 0;
> >> + u32 cwb_mask = 0;
> >> +
> >> + /*
> >> + * Since there can only be one CWB session at a time, if the CRTC LM
> >> + * starts with an even index we start with CWB_0. If the LM index is
> >> + * odd, we start with CWB_1
> >
> > I'd prefer to get indices from RM. They can be set during mode_set /
> > atomic_check calls.
>
> Hi Dmitry,
>
> Do you mean having CWB being managed by RM or using rm's
> get_assigned_blks() to grab the LM indices?
I was thinking of using either get_assigned_blks() or a new
CWB-specific API. This way such odd-even requirements get abstracted
in the RM.
> >> + */
> >> + if (cstate->mixers[0].hw_lm)
> >> + cwb_idx = (cstate->mixers[0].hw_lm->idx - LM_0) % 2;
> >> +
> >> + if (drm_crtc_in_clone_mode(crtc_state)) {
> >> + for (int i = 0; i < cstate->num_mixers; i++) {
> >> + cwb_mask |= (1 << cwb_idx);
> >> + cwb_idx++;
> >> + }
> >> + }
> >> +
> >> + drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc_state->encoder_mask)
> >> + dpu_encoder_set_cwb_mask(drm_enc, cwb_mask);
> >
> > Ugh, no. This function writes to dpu_enc, however there is being called
> > from atomic_check(). You can not write non-state variables here as the
> > commit can get completely dropped.
>
> Ack -- will change this API to `dpu_crtc_get_cwb_mask()` and call it
> from dpu_encoder_virt_mode_set() instead.
LGTM.
>
> >
> >> +}
> >> +
> >> 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];
> >> @@ -1329,6 +1356,8 @@ static int dpu_crtc_atomic_check(struct drm_crtc *crtc,
> >> !dpu_crtc_has_valid_clones(crtc, crtc_state))
> >> return -EINVAL;
> >>
> >> + dpu_crtc_set_encoder_cwb_mask(crtc, crtc_state);
> >> +
> >> 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 f1bd14d1f89e..0f8f6c0182d5 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> >> @@ -162,6 +162,7 @@ enum dpu_enc_rc_states {
> >> * clks and resources after IDLE_TIMEOUT time.
> >> * @topology: topology of the display
> >> * @idle_timeout: idle timeout duration in milliseconds
> >> + * @cwb_mask: current encoder is in clone mode
> >> * @wide_bus_en: wide bus is enabled on this interface
> >> * @dsc: drm_dsc_config pointer, for DSC-enabled encoders
> >> */
> >> @@ -202,6 +203,7 @@ struct dpu_encoder_virt {
> >> struct msm_display_topology topology;
> >>
> >> u32 idle_timeout;
> >> + u32 cwb_mask;
> >>
> >> bool wide_bus_en;
> >>
> >> @@ -638,6 +640,33 @@ bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_st
> >> return false;
> >> }
> >>
> >> +void dpu_encoder_set_cwb_mask(struct drm_encoder *enc, u32 cwb_mask)
> >> +{
> >> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> >> +
> >> + dpu_enc->cwb_mask = cwb_mask;
> >> +}
> >> +
> >> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc)
> >> +{
> >> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> >> +
> >> + if (!dpu_enc)
> >> + return 0;
> >> +
> >> + return dpu_enc->cwb_mask;
> >> +}
> >> +
> >> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc)
> >> +{
> >> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(enc);
> >> +
> >> + if (!dpu_enc)
> >> + return 0;
> >> +
> >> + return dpu_enc->cwb_mask != 0;
> >> +}
> >> +
> >> struct drm_dsc_config *dpu_encoder_get_dsc_config(struct drm_encoder *drm_enc)
> >> {
> >> struct msm_drm_private *priv = drm_enc->dev->dev_private;
> >> @@ -2019,6 +2048,7 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> >> struct dpu_hw_ctl *ctl = phys_enc->hw_ctl;
> >> struct dpu_hw_intf_cfg intf_cfg = { 0 };
> >> int i;
> >> + enum dpu_cwb cwb_idx;
> >> struct dpu_encoder_virt *dpu_enc;
> >>
> >> dpu_enc = to_dpu_encoder_virt(phys_enc->parent);
> >> @@ -2040,6 +2070,19 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
> >> /* mark WB flush as pending */
> >> if (phys_enc->hw_ctl->ops.update_pending_flush_wb)
> >> phys_enc->hw_ctl->ops.update_pending_flush_wb(ctl, phys_enc->hw_wb->idx);
> >> +
> >> + if (dpu_enc->cwb_mask) {
> >> + for (i = 0; i < hweight32(dpu_enc->cwb_mask); i++) {
> >
> > This will break if cwb_mask starts from bit 1: hweight will count bits,
> > so the loop will not cover the highest bit set.
>
> Ah, good point. I should be doing `hweight() + 1` here instead.
Not quite. I think it might be easier to loop up from CWB_0 to
CWB_MAX. The optimization gain from using hweight32 should be
negligible and using CWB constants will improve readability.
>
> >
> >> + if (!(dpu_enc->cwb_mask & (1 << i)))
> >> + continue;
> >> +
> >> + cwb_idx = i + CWB_0;
> >> +
> >> + if (phys_enc->hw_wb->ops.setup_input_ctrl)
> >> + phys_enc->hw_wb->ops.setup_input_ctrl(phys_enc->hw_wb,
> >> + cwb_idx, PINGPONG_NONE);
> >> + }
> >> + }
> >> } else {
> >> for (i = 0; i < dpu_enc->num_phys_encs; i++) {
> >> if (dpu_enc->phys_encs[i] && phys_enc->hw_intf->ops.bind_pingpong_blk)
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> >> index 0d27e50384f0..131bb8b2c0ee 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>
> >> @@ -188,6 +188,13 @@ void dpu_encoder_update_topology(struct drm_encoder *drm_enc,
> >> */
> >> bool dpu_encoder_needs_modeset(struct drm_encoder *drm_enc, struct drm_atomic_state *state);
> >>
> >> +/**
> >> + * dpu_encoder_set_cwb_mask - set the CWB blocks mask for the encoder
> >> + * @drm_enc: Pointer to previously created drm encoder structure
> >> + * @cwb_mask: CWB blocks mask to set for the encoder
> >> + */
> >> +void dpu_encoder_set_cwb_mask(struct drm_encoder *drm_enc, u32 cwb_mask);
> >> +
> >> /**
> >> * dpu_encoder_prepare_wb_job - prepare writeback job for the encoder.
> >> * @drm_enc: Pointer to previously created drm encoder structure
> >> 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 e77ebe3a68da..f0e5c5b073e5 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.
> >> */
> >>
> >> @@ -339,6 +339,22 @@ static inline enum dpu_3d_blend_mode dpu_encoder_helper_get_3d_blend_mode(
> >> */
> >> unsigned int dpu_encoder_helper_get_dsc(struct dpu_encoder_phys *phys_enc);
> >>
> >> +/**
> >> + * dpu_encoder_get_cwb_mask - get CWB blocks mask for DPU encoder
> >> + * This helper function is used by physical encoders to get the CWB blocks
> >> + * mask used for this encoder.
> >> + * @enc: Pointer to DRM encoder structure
> >> + */
> >> +u32 dpu_encoder_get_cwb_mask(struct drm_encoder *enc);
> >> +
> >> +/**
> >> + * dpu_encoder_in_clone_mode - determine if DPU encoder is in clone mode
> >> + * This helper is used by physical encoders to determine if the encoder is in
> >> + * clone mode.
> >> + * @enc: Pointer to DRM encoder structure
> >> + */
> >> +bool dpu_encoder_in_clone_mode(struct drm_encoder *enc);
> >> +
> >> /**
> >> * dpu_encoder_get_dsc_config - get DSC config for the DPU encoder
> >> * This helper function is used by physical encoder to get DSC config
> >> 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 882c717859ce..e1ec64ffc742 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__
> >> @@ -264,6 +264,45 @@ static void dpu_encoder_phys_wb_setup_ctl(struct dpu_encoder_phys *phys_enc)
> >> }
> >> }
> >>
> >> +static void dpu_encoder_phys_wb_setup_cwb(struct dpu_encoder_phys *phys_enc)
> >> +{
> >> + struct dpu_hw_wb *hw_wb;
> >> + struct dpu_hw_ctl *hw_ctl;
> >> + struct dpu_hw_pingpong *hw_pp;
> >> + u32 cwb_mask, cwb_idx;
> >> +
> >> + if (!phys_enc)
> >> + return;
> >> +
> >> + hw_wb = phys_enc->hw_wb;
> >> + hw_ctl = phys_enc->hw_ctl;
> >> + hw_pp = phys_enc->hw_pp;
> >> +
> >> + if (!hw_wb || !hw_ctl || !hw_pp) {
> >> + DPU_DEBUG("[wb:%d] no ctl or pp assigned\n", hw_wb->idx - WB_0);
> >> + return;
> >> + }
> >> +
> >> + cwb_mask = dpu_encoder_get_cwb_mask(phys_enc->parent);
> >> +
> >> + for (int i = 0; i < hweight32(cwb_mask); i++) {
> >> + if (!(cwb_mask & (1 << i)))
> >> + continue;
> >> +
> >> + cwb_idx = i + CWB_0;
> >> +
> >> + if (hw_wb->ops.setup_input_ctrl)
> >> + hw_wb->ops.setup_input_ctrl(hw_wb, cwb_idx, hw_pp->idx + i);
>
> Just wanted to note that the value being programmed here is incorrect.
>
> Instead of passing in the index of the dedicated cwb pingpong, it should
> instead be the index of the *real time display* pingpong.
>
> To grab the correct value, I'm thinking of adding a DPU encoder API to
> query the RM for (non-dedicated CWB) HW_BLK_PINGPONG to grab the
> pingpong indices for the real-time encoder. I'll then call that API here
> and pass the resulting real-time hw_pp index.
Hmm. Having SDM845 and below and LM_2 / LM_5 pair in mind I thought
that we might need to get a list of PPs. But then I noticed that this
pair uses PP_2 / PP_3 pair of pingpong blocks. Yes, the proposed API
sounds good.
>
> Please let me know if you have any feedback on this proposal or
> alternate solutions.
>
> Thanks,
>
> Jessica Zhang
>
> >> +
> >> + /*
> >> + * The CWB mux supports using LM or DSPP as tap points. For now,
> >> + * always use DSPP tap point
> >> + */
> >> + if (hw_wb->ops.setup_input_mode)
> >> + hw_wb->ops.setup_input_mode(hw_wb, cwb_idx, INPUT_MODE_DSPP_OUT);
> >> + }
> >> +}
> >> +
> >> /**
> >> * _dpu_encoder_phys_wb_update_flush - flush hardware update
> >> * @phys_enc: Pointer to physical encoder
> >> @@ -342,6 +381,8 @@ static void dpu_encoder_phys_wb_setup(
> >>
> >> dpu_encoder_helper_phys_setup_cdm(phys_enc, dpu_fmt, CDM_CDWN_OUTPUT_WB);
> >>
> >> + dpu_encoder_phys_wb_setup_cwb(phys_enc);
> >> +
> >> dpu_encoder_phys_wb_setup_ctl(phys_enc);
> >> }
> >>
> >>
> >> --
> >> 2.34.1
> >>
> >
> > --
> > With best wishes
> > Dmitry
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 16/21] drm/msm/dpu: Program hw_ctl to support CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (14 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 15/21] drm/msm/dpu: Configure CWB in writeback encoder Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:29 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 17/21] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
` (4 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Add support for configuring the CWB pending flush and active bits
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 8 +++++-
.../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 13 ++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +++++++++++++++++++++-
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 14 +++++++++-
4 files changed, 62 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 0f8f6c0182d5..bde385318018 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2081,6 +2081,10 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
if (phys_enc->hw_wb->ops.setup_input_ctrl)
phys_enc->hw_wb->ops.setup_input_ctrl(phys_enc->hw_wb,
cwb_idx, PINGPONG_NONE);
+
+ /* mark CWB flush as pending */
+ if (phys_enc->hw_ctl->ops.update_pending_flush_cwb)
+ phys_enc->hw_ctl->ops.update_pending_flush_cwb(ctl, cwb_idx);
}
}
} else {
@@ -2126,8 +2130,10 @@ void dpu_encoder_helper_phys_cleanup(struct dpu_encoder_phys *phys_enc)
if (phys_enc->hw_intf)
intf_cfg.intf = phys_enc->hw_intf->idx;
- if (phys_enc->hw_wb)
+ if (phys_enc->hw_wb) {
intf_cfg.wb = phys_enc->hw_wb->idx;
+ intf_cfg.cwb = dpu_enc->cwb_mask;
+ }
if (phys_enc->hw_pp && phys_enc->hw_pp->merge_3d)
intf_cfg.merge_3d = phys_enc->hw_pp->merge_3d->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 e1ec64ffc742..6d93e6ae442d 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_get_cwb_mask(phys_enc->parent);
if (mode_3d && hw_pp && hw_pp->merge_3d)
intf_cfg.merge_3d = hw_pp->merge_3d->idx;
@@ -314,6 +315,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
struct dpu_hw_pingpong *hw_pp;
struct dpu_hw_cdm *hw_cdm;
u32 pending_flush = 0;
+ u32 cwb_mask, cwb_idx;
if (!phys_enc)
return;
@@ -322,6 +324,7 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
hw_pp = phys_enc->hw_pp;
hw_ctl = phys_enc->hw_ctl;
hw_cdm = phys_enc->hw_cdm;
+ cwb_mask = dpu_encoder_get_cwb_mask(phys_enc->parent);
DPU_DEBUG("[wb:%d]\n", hw_wb->idx - WB_0);
@@ -340,6 +343,16 @@ static void _dpu_encoder_phys_wb_update_flush(struct dpu_encoder_phys *phys_enc)
if (hw_cdm && hw_ctl->ops.update_pending_flush_cdm)
hw_ctl->ops.update_pending_flush_cdm(hw_ctl, hw_cdm->idx);
+ for (int i = 0; i < hweight32(cwb_mask); i++) {
+ if (!(cwb_mask & (1 << i)))
+ continue;
+
+ cwb_idx = i + CWB_0;
+
+ if (hw_ctl->ops.update_pending_flush_cwb)
+ hw_ctl->ops.update_pending_flush_cwb(hw_ctl, cwb_idx);
+ }
+
if (hw_ctl->ops.get_pending_flush)
pending_flush = hw_ctl->ops.get_pending_flush(hw_ctl);
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 2e50049f2f85..792687b010ee 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 4401fdc0f3e4..6972fc86d986 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
@@ -51,6 +51,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 +115,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 +268,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 +285,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] 59+ messages in thread* Re: [PATCH 16/21] drm/msm/dpu: Program hw_ctl to support CWB
2024-08-29 20:48 ` [PATCH 16/21] drm/msm/dpu: Program hw_ctl to support CWB Jessica Zhang
@ 2024-08-30 17:29 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:29 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:37PM GMT, Jessica Zhang wrote:
> Add support for configuring the CWB pending flush and active bits
Details are appreciated.
Other than that:
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 | 8 +++++-
> .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 13 ++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 30 +++++++++++++++++++++-
> drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h | 14 +++++++++-
> 4 files changed, 62 insertions(+), 3 deletions(-)
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 17/21] drm/msm/dpu: Adjust writeback phys encoder setup for CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (15 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 16/21] drm/msm/dpu: Program hw_ctl to support CWB Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:30 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 18/21] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
` (3 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Adjust QoS remapper, OT limit, and CDP parameters to account for
concurrent writeback
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 6d93e6ae442d..56b5e44132da 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_in_clone_mode(phys_enc->parent);
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_in_clone_mode(phys_enc->parent);
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_in_clone_mode(phys_enc->parent))
+ 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, wb_cfg->dest.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] 59+ messages in thread* Re: [PATCH 17/21] drm/msm/dpu: Adjust writeback phys encoder setup for CWB
2024-08-29 20:48 ` [PATCH 17/21] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
@ 2024-08-30 17:30 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:30 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:38PM GMT, Jessica Zhang wrote:
> Adjust QoS remapper, OT limit, and CDP parameters to account for
> concurrent writeback
>
> 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(-)
>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 18/21] drm/msm/dpu: Start frame done timer after encoder kickoff
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (16 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 17/21] drm/msm/dpu: Adjust writeback phys encoder setup for CWB Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:31 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 19/21] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
` (2 subsequent siblings)
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Create a separate API for starting the encoder frame done timer and call
it after the encoder kickoff is finished
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 | 21 ++++++++++++++-------
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 1 +
3 files changed, 18 insertions(+), 8 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index c8ef59af444c..daf5f751f584 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -970,8 +970,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 bde385318018..9d495a186eb8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1945,18 +1945,12 @@ bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc)
return true;
}
-void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
+void dpu_encoder_start_frame_done_timer(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");
dpu_enc = to_dpu_encoder_virt(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);
@@ -1964,6 +1958,19 @@ void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
mod_timer(&dpu_enc->frame_done_timer,
jiffies + msecs_to_jiffies(timeout_ms));
+}
+
+void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
+{
+ struct dpu_encoder_virt *dpu_enc;
+ struct dpu_encoder_phys *phys;
+ unsigned int i;
+
+ DPU_ATRACE_BEGIN("encoder_kickoff");
+ dpu_enc = to_dpu_encoder_virt(drm_enc);
+
+ trace_dpu_enc_kickoff(DRMID(drm_enc));
+
/* 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 131bb8b2c0ee..7ab5f9380bf5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -216,5 +216,6 @@ void dpu_encoder_cleanup_wb_job(struct drm_encoder *drm_enc,
* @drm_enc: Pointer to drm encoder structure
*/
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] 59+ messages in thread* Re: [PATCH 18/21] drm/msm/dpu: Start frame done timer after encoder kickoff
2024-08-29 20:48 ` [PATCH 18/21] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
@ 2024-08-30 17:31 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:31 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:39PM GMT, Jessica Zhang wrote:
> Create a separate API for starting the encoder frame done timer and call
> it after the encoder kickoff is finished
>
> 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 | 21 ++++++++++++++-------
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 1 +
> 3 files changed, 18 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index c8ef59af444c..daf5f751f584 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -970,8 +970,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 bde385318018..9d495a186eb8 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -1945,18 +1945,12 @@ bool dpu_encoder_is_valid_for_commit(struct drm_encoder *drm_enc)
> return true;
> }
>
> -void dpu_encoder_kickoff(struct drm_encoder *drm_enc)
> +void dpu_encoder_start_frame_done_timer(struct drm_encoder *drm_enc)
Docs please. With this fixed and with the reason for the change being
added to the commit message:
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> {
> struct dpu_encoder_virt *dpu_enc;
> - struct dpu_encoder_phys *phys;
> unsigned long timeout_ms;
> - unsigned int i;
>
> - DPU_ATRACE_BEGIN("encoder_kickoff");
> dpu_enc = to_dpu_encoder_virt(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);
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 19/21] drm/msm/dpu: Skip trigger flush and start for CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (17 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 18/21] drm/msm/dpu: Start frame done timer after encoder kickoff Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:33 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 20/21] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
2024-08-29 20:48 ` [PATCH 21/21] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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.
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 9d495a186eb8..47b5a5994234 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1493,6 +1493,7 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
struct dpu_encoder_phys *phys, uint32_t extra_flush_bits)
{
struct dpu_hw_ctl *ctl;
+ struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
int pending_kickoff_cnt;
u32 ret = UINT_MAX;
@@ -1509,6 +1510,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);
@@ -1531,6 +1541,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;
@@ -1541,6 +1553,13 @@ 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] 59+ messages in thread* Re: [PATCH 19/21] drm/msm/dpu: Skip trigger flush and start for CWB
2024-08-29 20:48 ` [PATCH 19/21] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
@ 2024-08-30 17:33 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:33 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:40PM GMT, Jessica Zhang wrote:
> 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.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 19 +++++++++++++++++++
> 1 file changed, 19 insertions(+)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index 9d495a186eb8..47b5a5994234 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -1493,6 +1493,7 @@ static void _dpu_encoder_trigger_flush(struct drm_encoder *drm_enc,
> struct dpu_encoder_phys *phys, uint32_t extra_flush_bits)
> {
> struct dpu_hw_ctl *ctl;
> + struct dpu_encoder_virt *dpu_enc = to_dpu_encoder_virt(drm_enc);
Please move one line up.
> int pending_kickoff_cnt;
> u32 ret = UINT_MAX;
>
> @@ -1509,6 +1510,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) {
Alignment
> + 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);
>
> @@ -1531,6 +1541,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;
> @@ -1541,6 +1553,13 @@ 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) {
Align to open bracket. Please adapt your editor (e.g. 'set cino=(0' in Vim).
> + DPU_DEBUG("encoder %d CWB enabled, skipping\n",
> + DRMID(phys->parent));
Single line, please.
> + return;
> + }
> +
> if (phys->ops.trigger_start && phys->enable_state != DPU_ENC_DISABLED)
> phys->ops.trigger_start(phys);
> }
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 20/21] drm/msm/dpu: Reorder encoder kickoff for CWB
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (18 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 19/21] drm/msm/dpu: Skip trigger flush and start for CWB Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:35 ` Dmitry Baryshkov
2024-08-29 20:48 ` [PATCH 21/21] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, 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 | 67 ++++++++++++++++++++++++++------
1 file changed, 55 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index daf5f751f584..d2f91e89eba7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -928,6 +928,42 @@ 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;
+
+ /* 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);
+
+ /*
+ * 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;
+}
+
void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
{
struct drm_encoder *encoder;
@@ -952,13 +988,25 @@ 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);
+
+ 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 */
@@ -970,11 +1018,6 @@ 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) {
- 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] 59+ messages in thread* Re: [PATCH 20/21] drm/msm/dpu: Reorder encoder kickoff for CWB
2024-08-29 20:48 ` [PATCH 20/21] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
@ 2024-08-30 17:35 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:35 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:41PM GMT, 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 | 67 ++++++++++++++++++++++++++------
> 1 file changed, 55 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index daf5f751f584..d2f91e89eba7 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -928,6 +928,42 @@ 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;
> +
> + /* 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);
> +
> + /*
> + * 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;
> +}
> +
> void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
> {
> struct drm_encoder *encoder;
> @@ -952,13 +988,25 @@ 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);
> +
> + 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 */
> @@ -970,11 +1018,6 @@ 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) {
> - dpu_encoder_kickoff(encoder);
> - dpu_encoder_start_frame_done_timer(encoder);
> - }
> -
I think I understand why you wanted to move the kickoff before the
frame_pending, etc. However at the same time dpu_vbif_clear_errors()
should be called before kickoff.
> reinit_completion(&dpu_crtc->frame_done_comp);
>
> end:
>
> --
> 2.34.1
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread
* [PATCH 21/21] drm/msm/dpu: Set possible clones for all encoders
2024-08-29 20:48 [PATCH 00/21] drm/msm/dpu: Add Concurrent Writeback Support for DPU 10.x+ Jessica Zhang
` (19 preceding siblings ...)
2024-08-29 20:48 ` [PATCH 20/21] drm/msm/dpu: Reorder encoder kickoff " Jessica Zhang
@ 2024-08-29 20:48 ` Jessica Zhang
2024-08-30 17:39 ` Dmitry Baryshkov
20 siblings, 1 reply; 59+ messages in thread
From: Jessica Zhang @ 2024-08-29 20:48 UTC (permalink / raw)
To: Rob Clark, Dmitry Baryshkov, quic_abhinavk, Sean Paul,
Marijn Suijten, David Airlie, Daniel Vetter, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann
Cc: quic_ebharadw, linux-arm-msm, dri-devel, freedreno, linux-kernel,
Rob Clark, Jessica Zhang
Set writeback encoders as possible clones for non-writeback encoders and
vice versa.
Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
---
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 27 +++++++++++++++++++++++++++
drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 7 +++++++
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 47b5a5994234..aad659e6d35b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2352,6 +2352,33 @@ static int dpu_encoder_virt_add_phys_encs(
return 0;
}
+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 encoders and real-time
+ * encoders as clones of writeback.
+ *
+ * Writeback encoders can't be clones of each other and real-time
+ * encoders can't be clones of each other.
+ */
+ drm_for_each_encoder(curr, drm_enc->dev) {
+ if (type == DRM_MODE_ENCODER_VIRTUAL &&
+ curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
+ continue;
+ if (type != DRM_MODE_ENCODER_VIRTUAL &&
+ curr->encoder_type != DRM_MODE_ENCODER_VIRTUAL)
+ continue;
+
+ 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 7ab5f9380bf5..70eda127488a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
@@ -98,6 +98,13 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder);
*/
void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
+/**
+ * dpu_encoder_get_clones - set 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);
+
/**
* dpu_encoder_init - initialize virtual encoder object
* @dev: Pointer to drm device structure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 87526d3c224a..1a82aa61d217 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>
*/
@@ -793,8 +793,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] 59+ messages in thread* Re: [PATCH 21/21] drm/msm/dpu: Set possible clones for all encoders
2024-08-29 20:48 ` [PATCH 21/21] drm/msm/dpu: Set possible clones for all encoders Jessica Zhang
@ 2024-08-30 17:39 ` Dmitry Baryshkov
0 siblings, 0 replies; 59+ messages in thread
From: Dmitry Baryshkov @ 2024-08-30 17:39 UTC (permalink / raw)
To: Jessica Zhang
Cc: Rob Clark, quic_abhinavk, Sean Paul, Marijn Suijten, David Airlie,
Daniel Vetter, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, quic_ebharadw, linux-arm-msm, dri-devel,
freedreno, linux-kernel, Rob Clark
On Thu, Aug 29, 2024 at 01:48:42PM GMT, Jessica Zhang wrote:
> Set writeback encoders as possible clones for non-writeback encoders and
> vice versa.
>
> Signed-off-by: Jessica Zhang <quic_jesszhan@quicinc.com>
> ---
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 27 +++++++++++++++++++++++++++
> drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 7 +++++++
> 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 47b5a5994234..aad659e6d35b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -2352,6 +2352,33 @@ static int dpu_encoder_virt_add_phys_encs(
> return 0;
> }
>
Docs should go here.
> +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 encoders and real-time
> + * encoders as clones of writeback.
> + *
> + * Writeback encoders can't be clones of each other and real-time
> + * encoders can't be clones of each other.
> + */
> + drm_for_each_encoder(curr, drm_enc->dev) {
> + if (type == DRM_MODE_ENCODER_VIRTUAL &&
> + curr->encoder_type == DRM_MODE_ENCODER_VIRTUAL)
> + continue;
> + if (type != DRM_MODE_ENCODER_VIRTUAL &&
> + curr->encoder_type != DRM_MODE_ENCODER_VIRTUAL)
Align to opening brackets.
> + continue;
> +
> + 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 7ab5f9380bf5..70eda127488a 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h
> @@ -98,6 +98,13 @@ enum dpu_intf_mode dpu_encoder_get_intf_mode(struct drm_encoder *encoder);
> */
> void dpu_encoder_virt_runtime_resume(struct drm_encoder *encoder);
>
> +/**
> + * dpu_encoder_get_clones - set 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);
> +
> /**
> * dpu_encoder_init - initialize virtual encoder object
> * @dev: Pointer to drm device structure
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index 87526d3c224a..1a82aa61d217 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>
> */
> @@ -793,8 +793,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
>
--
With best wishes
Dmitry
^ permalink raw reply [flat|nested] 59+ messages in thread