Re: [PATCH 3/5] accel/qaic: Add consistent integer overflow checks

2023-07-07 Thread Pranjal Ramajor Asha Kanojiya




On 7/8/2023 12:21 AM, Jeffrey Hugo wrote:

On 6/21/2023 1:22 AM, Dan Carpenter wrote:

The encode_dma() function has integer overflow checks.  The
encode_passthrough(), encode_activate() and encode_status() functions
did not.  I added integer overflow checking everywhere.  I also
updated the integer overflow checking in encode_dma() to use size_add()
so everything is consistent.

Fixes: 129776ac2e38 ("accel/qaic: Add control path")
Signed-off-by: Dan Carpenter 


Reviewed-by: Jeffrey Hugo 


Looks good to me. Just the #include  as Jeff suggested.

Reviewed-by: Pranjal Ramajor Asha Kanojiya 


Re: [PATCH 5/5] accel/qaic: Fix a leak in map_user_pages()

2023-07-07 Thread Pranjal Ramajor Asha Kanojiya




On 6/21/2023 12:52 PM, Dan Carpenter wrote:

If get_user_pages_fast() allocates some pages but not as many as we
wanted, then the current code leaks those pages.  Call put_page() on
the pages before returning.

Fixes: 129776ac2e38 ("accel/qaic: Add control path")
Signed-off-by: Dan Carpenter 
---
  drivers/accel/qaic/qaic_control.c | 7 +--
  1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/accel/qaic/qaic_control.c 
b/drivers/accel/qaic/qaic_control.c
index 03932197f1ac..7c3f9009617f 100644
--- a/drivers/accel/qaic/qaic_control.c
+++ b/drivers/accel/qaic/qaic_control.c
@@ -424,9 +424,12 @@ static int find_and_map_user_pages(struct qaic_device 
*qdev,
}
  
  	ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);

-   if (ret < 0 || ret != nr_pages) {
-   ret = -EFAULT;
+   if (ret < 0)
goto free_page_list;
+   if (ret != nr_pages) {
+   nr_pages = ret;
+   ret = -EFAULT;
+   goto put_pages;
}
  
  	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);


Thank you for catching this :)

Reviewed-by: Pranjal Ramajor Asha Kanojiya 


Re: [PATCH 2/2] drm/msm/dpu: fix DSC 1.2 enc subblock length

2023-07-07 Thread Abhinav Kumar




On 6/22/2023 6:37 PM, Dmitry Baryshkov wrote:

Both struct dpu_dsc_sub_blks instances declare enc subblock length to be
0x100, while the actual length is 0x9c (last register having offset 0x98).
Reduce subblock length to remove the empty register space from being
dumped.

Fixes: 0d1b10c63346 ("drm/msm/dpu: add DSC 1.2 hw blocks for relevant chipsets")
Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)



Reviewed-by: Abhinav Kumar 


Re: [PATCH v5 0/6] Add support to print sub-block registers in dpu hw catalog

2023-07-07 Thread Abhinav Kumar




On 7/7/2023 6:24 PM, Ryan McCann wrote:

The purpose of this patch series is to add support to print the registers
of sub-blocks in the DPU hardware catalog and fix the order in which all
hardware blocks are dumped for a device core dump. This involves:



Nice work on completing this feature and working patiently through all 
the comments !




1. Changing data structure from stack to queue to fix the printing order
of the device core dump.

2. Removing redundant suffix of sub-block names.

3. Removing redundant prefix of sub-block names.

4. Eliminating unused variable from relevant macros.

5. Defining names for sub-blocks that have not yet been defined.

6. Implementing wrapper function that prints the registers of sub-blocks
when there is a need.

Sample Output of the sspp_0 block and its sub-blocks for devcore dump:
==sspp_0==
...registers
...
sspp_0_scaler
...
...
sspp_0_csc
...
...
next_block
...

This series depends on https://patchwork.freedesktop.org/series/119776/.

---
Changes in v5:
- Fixed indentation in refactor main block printing patch
- Fixed formatting issues to satisfy checkpatch
- Instead of passing 0 for DSC block, used actual length thanks to 
https://patchwork.freedesktop.org/series/119776/
- Link to v4: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v4-0-e304ddbe9...@quicinc.com

Changes in v4:
- Added review tags
- Link to v3: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v3-0-83601b72e...@quicinc.com

Changes in v3:
- Split sub-block changes and main block changes into two commits
- Corrected typo in comment located in DSC for loop block
- Eliminated variables mmio and base
- Dropped unnecessary "%s"
- Link to v2: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v2-0-9e90a87d3...@quicinc.com

Changes in v2:
- Changed spelling "sub block" to "sub-block" or "sblk".
- Capitalized DPU.
- Eliminated multiplexer/wrapper function. Inlined instead.
- Changed if statements from feature checks to length checks.
- Squashed prefix and suffix patch into one.
- Link to v1: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v1-0-3b2cdcc6a...@quicinc.com

---
Ryan McCann (6):
   drm/msm: Update dev core dump to not print backwards
   drm/msm/dpu: Drop unused num argument from relevant macros
   drm/msm/dpu: Define names for unnamed sblks
   drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks
   drm/msm/dpu: Refactor printing of main blocks in device core dump
   drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 90 +++
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 74 +++
  drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c |  2 +-
  3 files changed, 104 insertions(+), 62 deletions(-)
---
base-commit: a92b5625851098af521cd92e4c518429b661c8f4
change-id: 20230622-devcoredump_patch-df7e8f6fd632

Best regards,


Re: [PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

2023-07-07 Thread Abhinav Kumar




On 7/7/2023 6:24 PM, Ryan McCann wrote:

Currently, the device core dump mechanism does not dump registers of
sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit
dpu_kms_mdp_snapshot function to account for sub-blocks.

Signed-off-by: Ryan McCann 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++--
  1 file changed, 54 insertions(+), 12 deletions(-)



Overall, I like this one.

Reviewed-by: Abhinav Kumar 


Re: [PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 04:24, Ryan McCann wrote:

Currently, the device core dump mechanism does not dump registers of
sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit
dpu_kms_mdp_snapshot function to account for sub-blocks.

Signed-off-by: Ryan McCann 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++--
  1 file changed, 54 insertions(+), 12 deletions(-)


Reviewed-by: Dmitry Baryshkov 



diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 7a2787279ba0..f7199a5c45ab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -890,6 +890,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
int i;
struct dpu_kms *dpu_kms;
const struct dpu_mdss_cfg *cat;
+   void __iomem *base;
  
  	dpu_kms = to_dpu_kms(kms);
  
@@ -903,9 +904,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state *disp_state, struct msm_k

dpu_kms->mmio + cat->ctl[i].base, 
cat->ctl[i].name);
  
  	/* dump DSPP sub-blocks HW regs info */

-   for (i = 0; i < cat->dspp_count; i++)
-   msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len,
-   dpu_kms->mmio + cat->dspp[i].base, 
cat->dspp[i].name);
+   for (i = 0; i < cat->dspp_count; i++) {
+   base = dpu_kms->mmio + cat->dspp[i].base;
+   msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, 
cat->dspp[i].name);
+
+   if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0)
+   msm_disp_snapshot_add_block(disp_state, 
cat->dspp[i].sblk->pcc.len,
+   base + cat->dspp[i].sblk->pcc.base, 
"%s_%s",
+   cat->dspp[i].name,
+   
cat->dspp[i].sblk->pcc.name);


Nit (no need to resend to correct this): the "%s_%s" logically fits the 
next line, as it it related to the names rather than base address.



+   }
  
  	/* dump INTF sub-blocks HW regs info */

for (i = 0; i < cat->intf_count; i++)


--
With best wishes
Dmitry



Re: [PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 04:24, Ryan McCann wrote:

Currently, the names of main blocks are hardcoded into the
msm_disp_snapshot_add_block function rather than using the name that
already exists in the catalog. Change this to take the name directly from
the catalog instead of hardcoding it.

Signed-off-by: Ryan McCann 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 
  1 file changed, 8 insertions(+), 8 deletions(-)


Reviewed-by: Dmitry Baryshkov 

--
With best wishes
Dmitry



Re: [PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump

2023-07-07 Thread Abhinav Kumar




On 7/7/2023 6:24 PM, Ryan McCann wrote:

Currently, the names of main blocks are hardcoded into the
msm_disp_snapshot_add_block function rather than using the name that
already exists in the catalog. Change this to take the name directly from
the catalog instead of hardcoding it.

Signed-off-by: Ryan McCann 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 
  1 file changed, 8 insertions(+), 8 deletions(-)



Reviewed-by: Abhinav Kumar 


[PATCH v5 4/6] drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks

2023-07-07 Thread Ryan McCann
For a device core dump, the registers of sub-blocks are printed under a
title formatted as . For example, the csc sub-block
for an SSPP main block "sspp_0" would be printed "sspp_0_sspp_csc0". The
title is clearly redundant due to the duplicate "sspp" and "0" that exist
in both the mainBlkName and sblkName. To eliminate this redundancy, remove
the secondary "sspp" and "0" that exist in the sub-block name by
elimanting the "sspp_" prefix and the concatenation of "num" that results
in the redundant "0" suffix. Remove num parameter altogether from relevant
macros as a consequence of it no longer being used.

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 50 +-
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index e2879cc84ee0..2a903ab29964 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -252,15 +252,15 @@ static const uint32_t wb2_formats[] = {
  */
 
 /* SSPP common configuration */
-#define _VIG_SBLK(num, sdma_pri, qseed_ver) \
+#define _VIG_SBLK(sdma_pri, qseed_ver) \
{ \
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
-   .scaler_blk = {.name = STRCAT("sspp_scaler", num), \
+   .scaler_blk = {.name = "scaler", \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
-   .csc_blk = {.name = STRCAT("sspp_csc", num), \
+   .csc_blk = {.name = "csc", \
.id = DPU_SSPP_CSC_10BIT, \
.base = 0x1a00, .len = 0x100,}, \
.format_list = plane_formats_yuv, \
@@ -270,15 +270,15 @@ static const uint32_t wb2_formats[] = {
.rotation_cfg = NULL, \
}
 
-#define _VIG_SBLK_ROT(num, sdma_pri, qseed_ver, rot_cfg) \
+#define _VIG_SBLK_ROT(sdma_pri, qseed_ver, rot_cfg) \
{ \
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
-   .scaler_blk = {.name = STRCAT("sspp_scaler", num), \
+   .scaler_blk = {.name = "scaler", \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
-   .csc_blk = {.name = STRCAT("sspp_csc", num), \
+   .csc_blk = {.name = "csc", \
.id = DPU_SSPP_CSC_10BIT, \
.base = 0x1a00, .len = 0x100,}, \
.format_list = plane_formats_yuv, \
@@ -300,13 +300,13 @@ static const uint32_t wb2_formats[] = {
}
 
 static const struct dpu_sspp_sub_blks msm8998_vig_sblk_0 =
-   _VIG_SBLK("0", 0, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks msm8998_vig_sblk_1 =
-   _VIG_SBLK("1", 0, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks msm8998_vig_sblk_2 =
-   _VIG_SBLK("2", 0, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks msm8998_vig_sblk_3 =
-   _VIG_SBLK("3", 0, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(0, DPU_SSPP_SCALER_QSEED3);
 
 static const struct dpu_rotation_cfg dpu_rot_sc7280_cfg_v2 = {
.rot_maxheight = 1088,
@@ -315,13 +315,13 @@ static const struct dpu_rotation_cfg 
dpu_rot_sc7280_cfg_v2 = {
 };
 
 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_0 =
-   _VIG_SBLK("0", 5, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(5, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_1 =
-   _VIG_SBLK("1", 6, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(6, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 =
-   _VIG_SBLK("2", 7, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(7, DPU_SSPP_SCALER_QSEED3);
 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 =
-   _VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3);
+   _VIG_SBLK(8, DPU_SSPP_SCALER_QSEED3);
 
 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK(1);
 static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK(2);
@@ -341,31 +341,31 @@ static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = 
_DMA_SBLK(4);
}
 
 static const struct dpu_sspp_sub_blks sc7180_vig_sblk_0 =
-   _VIG_SBLK("0", 4, DPU_SSPP_SCALER_QSEED4);
+  

[PATCH v5 1/6] drm/msm: Update dev core dump to not print backwards

2023-07-07 Thread Ryan McCann
Device core dump add block method adds hardware blocks to dumping queue
with stack behavior which causes the hardware blocks to be printed in
reverse order. Change the addition to dumping queue data structure
from "list_add" to "list_add_tail" for FIFO queue behavior.

Fixes: 98659487b845 ("drm/msm: add support to take dpu snapshot")
Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Abhinav Kumar 
Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c 
b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
index acfe1b31e079..add72bbc28b1 100644
--- a/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
+++ b/drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c
@@ -192,5 +192,5 @@ void msm_disp_snapshot_add_block(struct msm_disp_state 
*disp_state, u32 len,
new_blk->base_addr = base_addr;
 
msm_disp_state_dump_regs(_blk->state, new_blk->size, base_addr);
-   list_add(_blk->node, _state->blocks);
+   list_add_tail(_blk->node, _state->blocks);
 }

-- 
2.25.1



[PATCH v5 3/6] drm/msm/dpu: Define names for unnamed sblks

2023-07-07 Thread Ryan McCann
Some sub-blocks in the hw catalog have not been given a name, so when the
registers from that block are dumped, there is no name to reference.
Define names for relevant sub-blocks to fix this.

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 1291251e4c90..e2879cc84ee0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -444,12 +444,12 @@ static const struct dpu_lm_sub_blks qcm2290_lm_sblk = {
  * DSPP sub blocks config
  */
 static const struct dpu_dspp_sub_blks msm8998_dspp_sblk = {
-   .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
+   .pcc = {.name = "pcc", .id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x10007},
 };
 
 static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
-   .pcc = {.id = DPU_DSPP_PCC, .base = 0x1700,
+   .pcc = {.name = "pcc", .id = DPU_DSPP_PCC, .base = 0x1700,
.len = 0x90, .version = 0x4},
 };
 
@@ -465,19 +465,19 @@ static const struct dpu_dspp_sub_blks sm8150_dspp_sblk = {
  * PINGPONG sub blocks config
  */
 static const struct dpu_pingpong_sub_blks sdm845_pp_sblk_te = {
-   .te2 = {.id = DPU_PINGPONG_TE2, .base = 0x2000, .len = 0x0,
+   .te2 = {.name = "te2", .id = DPU_PINGPONG_TE2, .base = 0x2000, .len = 
0x0,
.version = 0x1},
-   .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0,
+   .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0x30e0,
.len = 0x20, .version = 0x1},
 };
 
 static const struct dpu_pingpong_sub_blks sdm845_pp_sblk = {
-   .dither = {.id = DPU_PINGPONG_DITHER, .base = 0x30e0,
+   .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0x30e0,
.len = 0x20, .version = 0x1},
 };
 
 static const struct dpu_pingpong_sub_blks sc7280_pp_sblk = {
-   .dither = {.id = DPU_PINGPONG_DITHER, .base = 0xe0,
+   .dither = {.name = "dither", .id = DPU_PINGPONG_DITHER, .base = 0xe0,
.len = 0x20, .version = 0x2},
 };
 
@@ -517,13 +517,13 @@ static const struct dpu_pingpong_sub_blks sc7280_pp_sblk 
= {
  * DSC sub blocks config
  */
 static const struct dpu_dsc_sub_blks dsc_sblk_0 = {
-   .enc = {.base = 0x100, .len = 0x9c},
-   .ctl = {.base = 0xF00, .len = 0x10},
+   .enc = {.name = "enc", .base = 0x100, .len = 0x9c},
+   .ctl = {.name = "ctl", .base = 0xF00, .len = 0x10},
 };
 
 static const struct dpu_dsc_sub_blks dsc_sblk_1 = {
-   .enc = {.base = 0x200, .len = 0x9c},
-   .ctl = {.base = 0xF80, .len = 0x10},
+   .enc = {.name = "enc", .base = 0x200, .len = 0x9c},
+   .ctl = {.name = "ctl", .base = 0xF80, .len = 0x10},
 };
 
 #define DSC_BLK(_name, _id, _base, _features) \

-- 
2.25.1



[PATCH v5 2/6] drm/msm/dpu: Drop unused num argument from relevant macros

2023-07-07 Thread Ryan McCann
Drop unused parameter "num" from VIG_SBLK_NOSCALE and DMA sub-block
macros. Update calls to relevant macros to reflect change.

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 20 ++--
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index dd2f89ada043..1291251e4c90 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -288,7 +288,7 @@ static const uint32_t wb2_formats[] = {
.rotation_cfg = rot_cfg, \
}
 
-#define _DMA_SBLK(num, sdma_pri) \
+#define _DMA_SBLK(sdma_pri) \
{ \
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
@@ -323,10 +323,10 @@ static const struct dpu_sspp_sub_blks sdm845_vig_sblk_2 =
 static const struct dpu_sspp_sub_blks sdm845_vig_sblk_3 =
_VIG_SBLK("3", 8, DPU_SSPP_SCALER_QSEED3);
 
-static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK("8", 1);
-static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK("9", 2);
-static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK("10", 3);
-static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK("11", 4);
+static const struct dpu_sspp_sub_blks sdm845_dma_sblk_0 = _DMA_SBLK(1);
+static const struct dpu_sspp_sub_blks sdm845_dma_sblk_1 = _DMA_SBLK(2);
+static const struct dpu_sspp_sub_blks sdm845_dma_sblk_2 = _DMA_SBLK(3);
+static const struct dpu_sspp_sub_blks sdm845_dma_sblk_3 = _DMA_SBLK(4);
 
 #define SSPP_BLK(_name, _id, _base, _len, _features, \
_sblk, _xinid, _type, _clkctrl) \
@@ -366,10 +366,10 @@ static const struct dpu_sspp_sub_blks sm8550_vig_sblk_2 =
_VIG_SBLK("2", 9, DPU_SSPP_SCALER_QSEED4);
 static const struct dpu_sspp_sub_blks sm8550_vig_sblk_3 =
_VIG_SBLK("3", 10, DPU_SSPP_SCALER_QSEED4);
-static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK("12", 5);
-static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK("13", 6);
+static const struct dpu_sspp_sub_blks sm8550_dma_sblk_4 = _DMA_SBLK(5);
+static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = _DMA_SBLK(6);
 
-#define _VIG_SBLK_NOSCALE(num, sdma_pri) \
+#define _VIG_SBLK_NOSCALE(sdma_pri) \
{ \
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
@@ -380,8 +380,8 @@ static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = 
_DMA_SBLK("13", 6);
.virt_num_formats = ARRAY_SIZE(plane_formats), \
}
 
-static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = 
_VIG_SBLK_NOSCALE("0", 2);
-static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK("8", 1);
+static const struct dpu_sspp_sub_blks qcm2290_vig_sblk_0 = 
_VIG_SBLK_NOSCALE(2);
+static const struct dpu_sspp_sub_blks qcm2290_dma_sblk_0 = _DMA_SBLK(1);
 
 /*
  * MIXER sub blocks config

-- 
2.25.1



[PATCH v5 0/6] Add support to print sub-block registers in dpu hw catalog

2023-07-07 Thread Ryan McCann
The purpose of this patch series is to add support to print the registers
of sub-blocks in the DPU hardware catalog and fix the order in which all
hardware blocks are dumped for a device core dump. This involves:

1. Changing data structure from stack to queue to fix the printing order
of the device core dump.

2. Removing redundant suffix of sub-block names.

3. Removing redundant prefix of sub-block names.

4. Eliminating unused variable from relevant macros.

5. Defining names for sub-blocks that have not yet been defined.

6. Implementing wrapper function that prints the registers of sub-blocks
when there is a need.

Sample Output of the sspp_0 block and its sub-blocks for devcore dump:
==sspp_0==
...registers
...
sspp_0_scaler
...
...
sspp_0_csc
...
...
next_block
...

This series depends on https://patchwork.freedesktop.org/series/119776/.

---
Changes in v5:
- Fixed indentation in refactor main block printing patch
- Fixed formatting issues to satisfy checkpatch
- Instead of passing 0 for DSC block, used actual length thanks to 
https://patchwork.freedesktop.org/series/119776/
- Link to v4: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v4-0-e304ddbe9...@quicinc.com

Changes in v4:
- Added review tags
- Link to v3: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v3-0-83601b72e...@quicinc.com

Changes in v3:
- Split sub-block changes and main block changes into two commits
- Corrected typo in comment located in DSC for loop block
- Eliminated variables mmio and base
- Dropped unnecessary "%s"
- Link to v2: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v2-0-9e90a87d3...@quicinc.com

Changes in v2:
- Changed spelling "sub block" to "sub-block" or "sblk".
- Capitalized DPU.
- Eliminated multiplexer/wrapper function. Inlined instead.
- Changed if statements from feature checks to length checks.
- Squashed prefix and suffix patch into one.
- Link to v1: 
https://lore.kernel.org/r/20230622-devcoredump_patch-v1-0-3b2cdcc6a...@quicinc.com

---
Ryan McCann (6):
  drm/msm: Update dev core dump to not print backwards
  drm/msm/dpu: Drop unused num argument from relevant macros
  drm/msm/dpu: Define names for unnamed sblks
  drm/msm/dpu: Remove redundant prefix/suffix in name of sub-blocks
  drm/msm/dpu: Refactor printing of main blocks in device core dump
  drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 90 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 74 +++
 drivers/gpu/drm/msm/disp/msm_disp_snapshot_util.c |  2 +-
 3 files changed, 104 insertions(+), 62 deletions(-)
---
base-commit: a92b5625851098af521cd92e4c518429b661c8f4
change-id: 20230622-devcoredump_patch-df7e8f6fd632

Best regards,
-- 
Ryan McCann 



[PATCH v5 5/6] drm/msm/dpu: Refactor printing of main blocks in device core dump

2023-07-07 Thread Ryan McCann
Currently, the names of main blocks are hardcoded into the
msm_disp_snapshot_add_block function rather than using the name that
already exists in the catalog. Change this to take the name directly from
the catalog instead of hardcoding it.

Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 16 
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index aa8499de1b9f..7a2787279ba0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -900,37 +900,37 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
/* dump CTL sub-blocks HW regs info */
for (i = 0; i < cat->ctl_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->ctl[i].len,
-   dpu_kms->mmio + cat->ctl[i].base, "ctl_%d", i);
+   dpu_kms->mmio + cat->ctl[i].base, 
cat->ctl[i].name);
 
/* dump DSPP sub-blocks HW regs info */
for (i = 0; i < cat->dspp_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len,
-   dpu_kms->mmio + cat->dspp[i].base, "dspp_%d", 
i);
+   dpu_kms->mmio + cat->dspp[i].base, 
cat->dspp[i].name);
 
/* dump INTF sub-blocks HW regs info */
for (i = 0; i < cat->intf_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->intf[i].len,
-   dpu_kms->mmio + cat->intf[i].base, "intf_%d", 
i);
+   dpu_kms->mmio + cat->intf[i].base, 
cat->intf[i].name);
 
/* dump PP sub-blocks HW regs info */
for (i = 0; i < cat->pingpong_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len,
-   dpu_kms->mmio + cat->pingpong[i].base, 
"pingpong_%d", i);
+   dpu_kms->mmio + cat->pingpong[i].base, 
cat->pingpong[i].name);
 
/* dump SSPP sub-blocks HW regs info */
for (i = 0; i < cat->sspp_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len,
-   dpu_kms->mmio + cat->sspp[i].base, "sspp_%d", 
i);
+   dpu_kms->mmio + cat->sspp[i].base, 
cat->sspp[i].name);
 
/* dump LM sub-blocks HW regs info */
for (i = 0; i < cat->mixer_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len,
-   dpu_kms->mmio + cat->mixer[i].base, "lm_%d", i);
+   dpu_kms->mmio + cat->mixer[i].base, 
cat->mixer[i].name);
 
/* dump WB sub-blocks HW regs info */
for (i = 0; i < cat->wb_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->wb[i].len,
-   dpu_kms->mmio + cat->wb[i].base, "wb_%d", i);
+   dpu_kms->mmio + cat->wb[i].base, 
cat->wb[i].name);
 
if (cat->mdp[0].features & BIT(DPU_MDP_PERIPH_0_REMOVED)) {
msm_disp_snapshot_add_block(disp_state, MDP_PERIPH_TOP0,
@@ -945,7 +945,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
/* dump DSC sub-blocks HW regs info */
for (i = 0; i < cat->dsc_count; i++)
msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len,
-   dpu_kms->mmio + cat->dsc[i].base, "dsc_%d", i);
+   dpu_kms->mmio + cat->dsc[i].base, 
cat->dsc[i].name);
 
pm_runtime_put_sync(_kms->pdev->dev);
 }

-- 
2.25.1



[PATCH v5 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

2023-07-07 Thread Ryan McCann
Currently, the device core dump mechanism does not dump registers of
sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit
dpu_kms_mdp_snapshot function to account for sub-blocks.

Signed-off-by: Ryan McCann 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 +++--
 1 file changed, 54 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 7a2787279ba0..f7199a5c45ab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -890,6 +890,7 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
int i;
struct dpu_kms *dpu_kms;
const struct dpu_mdss_cfg *cat;
+   void __iomem *base;
 
dpu_kms = to_dpu_kms(kms);
 
@@ -903,9 +904,16 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
dpu_kms->mmio + cat->ctl[i].base, 
cat->ctl[i].name);
 
/* dump DSPP sub-blocks HW regs info */
-   for (i = 0; i < cat->dspp_count; i++)
-   msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len,
-   dpu_kms->mmio + cat->dspp[i].base, 
cat->dspp[i].name);
+   for (i = 0; i < cat->dspp_count; i++) {
+   base = dpu_kms->mmio + cat->dspp[i].base;
+   msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, base, 
cat->dspp[i].name);
+
+   if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0)
+   msm_disp_snapshot_add_block(disp_state, 
cat->dspp[i].sblk->pcc.len,
+   base + 
cat->dspp[i].sblk->pcc.base, "%s_%s",
+   cat->dspp[i].name,
+   
cat->dspp[i].sblk->pcc.name);
+   }
 
/* dump INTF sub-blocks HW regs info */
for (i = 0; i < cat->intf_count; i++)
@@ -913,14 +921,37 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
dpu_kms->mmio + cat->intf[i].base, 
cat->intf[i].name);
 
/* dump PP sub-blocks HW regs info */
-   for (i = 0; i < cat->pingpong_count; i++)
-   msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len,
-   dpu_kms->mmio + cat->pingpong[i].base, 
cat->pingpong[i].name);
+   for (i = 0; i < cat->pingpong_count; i++) {
+   base = dpu_kms->mmio + cat->pingpong[i].base;
+   msm_disp_snapshot_add_block(disp_state, cat->pingpong[i].len, 
base,
+   cat->pingpong[i].name);
+
+   /* TE2 sub-block has length of 0, so will not print it */
+
+   if (cat->pingpong[i].sblk && cat->pingpong[i].sblk->dither.len 
> 0)
+   msm_disp_snapshot_add_block(disp_state, 
cat->pingpong[i].sblk->dither.len,
+   base + 
cat->pingpong[i].sblk->dither.base,
+   "%s_%s", 
cat->pingpong[i].name,
+   
cat->pingpong[i].sblk->dither.name);
+   }
 
/* dump SSPP sub-blocks HW regs info */
-   for (i = 0; i < cat->sspp_count; i++)
-   msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len,
-   dpu_kms->mmio + cat->sspp[i].base, 
cat->sspp[i].name);
+   for (i = 0; i < cat->sspp_count; i++) {
+   base = dpu_kms->mmio + cat->sspp[i].base;
+   msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, base, 
cat->sspp[i].name);
+
+   if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0)
+   msm_disp_snapshot_add_block(disp_state, 
cat->sspp[i].sblk->scaler_blk.len,
+   base + 
cat->sspp[i].sblk->scaler_blk.base,
+   "%s_%s", cat->sspp[i].name,
+   
cat->sspp[i].sblk->scaler_blk.name);
+
+   if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0)
+   msm_disp_snapshot_add_block(disp_state, 
cat->sspp[i].sblk->csc_blk.len,
+   base + 
cat->sspp[i].sblk->csc_blk.base,
+   "%s_%s", cat->sspp[i].name,
+   
cat->sspp[i].sblk->csc_blk.name);
+   }
 
/* dump LM sub-blocks HW regs info */
for (i = 0; i < cat->mixer_count; i++)
@@ -943,9 +974,20 @@ static void dpu_kms_mdp_snapshot(struct msm_disp_state 
*disp_state, struct msm_k
}
 
/* dump DSC sub-blocks HW regs info */
-   for (i = 0; i < cat->dsc_count; i++)
-   

[Patch v2] drm/ttm: Use init_on_free to delay release TTM BOs

2023-07-07 Thread Rajneesh Bhardwaj
Delay release TTM BOs when the kernel default setting is init_on_free.
This offloads the overhead of clearing the system memory to the work
item and potentially a different CPU. This could be very beneficial when
the application does a lot of malloc/free style allocations of system
memory.

Reviewed-by: Christian König .
Signed-off-by: Rajneesh Bhardwaj 
---
Changes in v2:
- Updated commit message as per Christian's feedback

 drivers/gpu/drm/ttm/ttm_bo.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 326a3d13a829..bd2e7e4f497a 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -347,6 +347,7 @@ static void ttm_bo_release(struct kref *kref)
 
if (!dma_resv_test_signaled(bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP) ||
+   (want_init_on_free() && (bo->ttm != NULL)) ||
!dma_resv_trylock(bo->base.resv)) {
/* The BO is not idle, resurrect it for delayed destroy 
*/
ttm_bo_flush_all_fences(bo);
-- 
2.17.1



[PATCH 17/17] drm/msm: drop mdp_get_formats()

2023-07-07 Thread Dmitry Baryshkov
Drop the function mdp_get_formats(), which became unused after
converting both MDP4 and MDP5 planes to use static formats arrays.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp_format.c | 24 
 drivers/gpu/drm/msm/disp/mdp_kms.h|  1 -
 2 files changed, 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c 
b/drivers/gpu/drm/msm/disp/mdp_format.c
index ba9abe8b3acc..0fe430af9523 100644
--- a/drivers/gpu/drm/msm/disp/mdp_format.c
+++ b/drivers/gpu/drm/msm/disp/mdp_format.c
@@ -183,30 +183,6 @@ const uint32_t mdp_rgb_yuv_formats[] = {
 
 size_t mdp_rgb_yuv_num_formats = ARRAY_SIZE(mdp_rgb_yuv_formats);
 
-/*
- * Note:
- * @rgb_only must be set to true, when requesting
- * supported formats for RGB pipes.
- */
-uint32_t mdp_get_formats(uint32_t *pixel_formats, uint32_t max_formats,
-   bool rgb_only)
-{
-   uint32_t i;
-   for (i = 0; i < ARRAY_SIZE(formats); i++) {
-   const struct mdp_format *f = [i];
-
-   if (i == max_formats)
-   break;
-
-   if (rgb_only && MDP_FORMAT_IS_YUV(f))
-   break;
-
-   pixel_formats[i] = f->base.pixel_format;
-   }
-
-   return i;
-}
-
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format,
uint64_t modifier)
 {
diff --git a/drivers/gpu/drm/msm/disp/mdp_kms.h 
b/drivers/gpu/drm/msm/disp/mdp_kms.h
index 11402a859574..1b2ccf7e7de6 100644
--- a/drivers/gpu/drm/msm/disp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/disp/mdp_kms.h
@@ -91,7 +91,6 @@ struct mdp_format {
 #define to_mdp_format(x) container_of(x, struct mdp_format, base)
 #define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->is_yuv)
 
-uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool 
rgb_only);
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, 
uint64_t modifier);
 
 extern const uint32_t mdp_rgb_formats[];
-- 
2.39.2



[PATCH 15/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_lcdc_encoder

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp4_lcdc_encoder allocation to use drmm_encoder_alloc().
This removes the need to perform any actions on this encoder
destruction.

Signed-off-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 36 ---
 1 file changed, 7 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
index 67c118bb30ca..576995ddce37 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
@@ -30,18 +30,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-static void mdp4_lcdc_encoder_destroy(struct drm_encoder *encoder)
-{
-   struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
-   to_mdp4_lcdc_encoder(encoder);
-   drm_encoder_cleanup(encoder);
-   kfree(mdp4_lcdc_encoder);
-}
-
-static const struct drm_encoder_funcs mdp4_lcdc_encoder_funcs = {
-   .destroy = mdp4_lcdc_encoder_destroy,
-};
-
 /* this should probably be a helper: */
 static struct drm_connector *get_connector(struct drm_encoder *encoder)
 {
@@ -377,30 +365,26 @@ long mdp4_lcdc_round_pixclk(struct drm_encoder *encoder, 
unsigned long rate)
 struct drm_encoder *mdp4_lcdc_encoder_init(struct drm_device *dev,
struct device_node *panel_node)
 {
-   struct drm_encoder *encoder = NULL;
+   struct drm_encoder *encoder;
struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
int ret;
 
-   mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
-   if (!mdp4_lcdc_encoder) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   mdp4_lcdc_encoder = drmm_encoder_alloc(dev, struct mdp4_lcdc_encoder, 
base,
+  NULL, DRM_MODE_ENCODER_LVDS, 
NULL);
+   if (IS_ERR(mdp4_lcdc_encoder))
+   return ERR_CAST(mdp4_lcdc_encoder);
 
mdp4_lcdc_encoder->panel_node = panel_node;
 
encoder = _lcdc_encoder->base;
 
-   drm_encoder_init(dev, encoder, _lcdc_encoder_funcs,
-DRM_MODE_ENCODER_LVDS, NULL);
drm_encoder_helper_add(encoder, _lcdc_encoder_helper_funcs);
 
/* TODO: do we need different pll in other cases? */
mdp4_lcdc_encoder->lcdc_clk = mpd4_lvds_pll_init(dev);
if (IS_ERR(mdp4_lcdc_encoder->lcdc_clk)) {
DRM_DEV_ERROR(dev->dev, "failed to get lvds_clk\n");
-   ret = PTR_ERR(mdp4_lcdc_encoder->lcdc_clk);
-   goto fail;
+   return ERR_CAST(mdp4_lcdc_encoder->lcdc_clk);
}
 
/* TODO: different regulators in other cases? */
@@ -412,13 +396,7 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct 
drm_device *dev,
  ARRAY_SIZE(mdp4_lcdc_encoder->regs),
  mdp4_lcdc_encoder->regs);
if (ret)
-   goto fail;
+   return ERR_PTR(ret);
 
return encoder;
-
-fail:
-   if (encoder)
-   mdp4_lcdc_encoder_destroy(encoder);
-
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 11/17] drm/msm/mdp4: use bulk regulators API for LCDC encoder

2023-07-07 Thread Dmitry Baryshkov
Switch mdp4_lcdc_encoder to using regulator_bulk_* API instead of
enumerating regulators by hand.

Signed-off-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 51 ++-
 1 file changed, 15 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
index 10eb3e5b218e..67c118bb30ca 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c
@@ -18,7 +18,7 @@ struct mdp4_lcdc_encoder {
struct drm_panel *panel;
struct clk *lcdc_clk;
unsigned long int pixclock;
-   struct regulator *regs[3];
+   struct regulator_bulk_data regs[3];
bool enabled;
uint32_t bsc;
 };
@@ -271,12 +271,10 @@ static void mdp4_lcdc_encoder_mode_set(struct drm_encoder 
*encoder,
 
 static void mdp4_lcdc_encoder_disable(struct drm_encoder *encoder)
 {
-   struct drm_device *dev = encoder->dev;
struct mdp4_lcdc_encoder *mdp4_lcdc_encoder =
to_mdp4_lcdc_encoder(encoder);
struct mdp4_kms *mdp4_kms = get_kms(encoder);
struct drm_panel *panel;
-   int i, ret;
 
if (WARN_ON(!mdp4_lcdc_encoder->enabled))
return;
@@ -301,11 +299,8 @@ static void mdp4_lcdc_encoder_disable(struct drm_encoder 
*encoder)
 
clk_disable_unprepare(mdp4_lcdc_encoder->lcdc_clk);
 
-   for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
-   ret = regulator_disable(mdp4_lcdc_encoder->regs[i]);
-   if (ret)
-   DRM_DEV_ERROR(dev->dev, "failed to disable regulator: 
%d\n", ret);
-   }
+   regulator_bulk_disable(ARRAY_SIZE(mdp4_lcdc_encoder->regs),
+  mdp4_lcdc_encoder->regs);
 
mdp4_lcdc_encoder->enabled = false;
 }
@@ -319,7 +314,7 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder 
*encoder)
struct mdp4_kms *mdp4_kms = get_kms(encoder);
struct drm_panel *panel;
uint32_t config;
-   int i, ret;
+   int ret;
 
if (WARN_ON(mdp4_lcdc_encoder->enabled))
return;
@@ -339,11 +334,10 @@ static void mdp4_lcdc_encoder_enable(struct drm_encoder 
*encoder)
mdp4_crtc_set_config(encoder->crtc, config);
mdp4_crtc_set_intf(encoder->crtc, INTF_LCDC_DTV, 0);
 
-   for (i = 0; i < ARRAY_SIZE(mdp4_lcdc_encoder->regs); i++) {
-   ret = regulator_enable(mdp4_lcdc_encoder->regs[i]);
-   if (ret)
-   DRM_DEV_ERROR(dev->dev, "failed to enable regulator: 
%d\n", ret);
-   }
+   ret = regulator_bulk_enable(ARRAY_SIZE(mdp4_lcdc_encoder->regs),
+   mdp4_lcdc_encoder->regs);
+   if (ret)
+   DRM_DEV_ERROR(dev->dev, "failed to enable regulators: %d\n", 
ret);
 
DBG("setting lcdc_clk=%lu", pc);
ret = clk_set_rate(mdp4_lcdc_encoder->lcdc_clk, pc);
@@ -385,7 +379,6 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct 
drm_device *dev,
 {
struct drm_encoder *encoder = NULL;
struct mdp4_lcdc_encoder *mdp4_lcdc_encoder;
-   struct regulator *reg;
int ret;
 
mdp4_lcdc_encoder = kzalloc(sizeof(*mdp4_lcdc_encoder), GFP_KERNEL);
@@ -411,29 +404,15 @@ struct drm_encoder *mdp4_lcdc_encoder_init(struct 
drm_device *dev,
}
 
/* TODO: different regulators in other cases? */
-   reg = devm_regulator_get(dev->dev, "lvds-vccs-3p3v");
-   if (IS_ERR(reg)) {
-   ret = PTR_ERR(reg);
-   DRM_DEV_ERROR(dev->dev, "failed to get lvds-vccs-3p3v: %d\n", 
ret);
-   goto fail;
-   }
-   mdp4_lcdc_encoder->regs[0] = reg;
-
-   reg = devm_regulator_get(dev->dev, "lvds-pll-vdda");
-   if (IS_ERR(reg)) {
-   ret = PTR_ERR(reg);
-   DRM_DEV_ERROR(dev->dev, "failed to get lvds-pll-vdda: %d\n", 
ret);
-   goto fail;
-   }
-   mdp4_lcdc_encoder->regs[1] = reg;
+   mdp4_lcdc_encoder->regs[0].supply = "lvds-vccs-3p3v";
+   mdp4_lcdc_encoder->regs[1].supply = "lvds-vccs-3p3v";
+   mdp4_lcdc_encoder->regs[2].supply = "lvds-vdda";
 
-   reg = devm_regulator_get(dev->dev, "lvds-vdda");
-   if (IS_ERR(reg)) {
-   ret = PTR_ERR(reg);
-   DRM_DEV_ERROR(dev->dev, "failed to get lvds-vdda: %d\n", ret);
+   ret = devm_regulator_bulk_get(dev->dev,
+ ARRAY_SIZE(mdp4_lcdc_encoder->regs),
+ mdp4_lcdc_encoder->regs);
+   if (ret)
goto fail;
-   }
-   mdp4_lcdc_encoder->regs[2] = reg;
 
return encoder;
 
-- 
2.39.2



[PATCH 14/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_dtv_encoder

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp4_dtv_encoder allocation to use drmm_encoder_alloc().
This removes the need to perform any actions on this encoder
destruction.

Signed-off-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c  | 37 ---
 1 file changed, 7 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c
index 88645dbc3785..3b70764b48c4 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c
@@ -25,17 +25,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-static void mdp4_dtv_encoder_destroy(struct drm_encoder *encoder)
-{
-   struct mdp4_dtv_encoder *mdp4_dtv_encoder = 
to_mdp4_dtv_encoder(encoder);
-   drm_encoder_cleanup(encoder);
-   kfree(mdp4_dtv_encoder);
-}
-
-static const struct drm_encoder_funcs mdp4_dtv_encoder_funcs = {
-   .destroy = mdp4_dtv_encoder_destroy,
-};
-
 static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
@@ -173,41 +162,29 @@ long mdp4_dtv_round_pixclk(struct drm_encoder *encoder, 
unsigned long rate)
 /* initialize encoder */
 struct drm_encoder *mdp4_dtv_encoder_init(struct drm_device *dev)
 {
-   struct drm_encoder *encoder = NULL;
+   struct drm_encoder *encoder;
struct mdp4_dtv_encoder *mdp4_dtv_encoder;
-   int ret;
 
-   mdp4_dtv_encoder = kzalloc(sizeof(*mdp4_dtv_encoder), GFP_KERNEL);
-   if (!mdp4_dtv_encoder) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   mdp4_dtv_encoder = drmm_encoder_alloc(dev, struct mdp4_dtv_encoder, 
base,
+ NULL, DRM_MODE_ENCODER_TMDS, 
NULL);
+   if (IS_ERR(mdp4_dtv_encoder))
+   return ERR_CAST(mdp4_dtv_encoder);
 
encoder = _dtv_encoder->base;
 
-   drm_encoder_init(dev, encoder, _dtv_encoder_funcs,
-DRM_MODE_ENCODER_TMDS, NULL);
drm_encoder_helper_add(encoder, _dtv_encoder_helper_funcs);
 
mdp4_dtv_encoder->hdmi_clk = devm_clk_get(dev->dev, "hdmi_clk");
if (IS_ERR(mdp4_dtv_encoder->hdmi_clk)) {
DRM_DEV_ERROR(dev->dev, "failed to get hdmi_clk\n");
-   ret = PTR_ERR(mdp4_dtv_encoder->hdmi_clk);
-   goto fail;
+   return ERR_CAST(mdp4_dtv_encoder->hdmi_clk);
}
 
mdp4_dtv_encoder->mdp_clk = devm_clk_get(dev->dev, "tv_clk");
if (IS_ERR(mdp4_dtv_encoder->mdp_clk)) {
DRM_DEV_ERROR(dev->dev, "failed to get tv_clk\n");
-   ret = PTR_ERR(mdp4_dtv_encoder->mdp_clk);
-   goto fail;
+   return ERR_CAST(mdp4_dtv_encoder->mdp_clk);
}
 
return encoder;
-
-fail:
-   if (encoder)
-   mdp4_dtv_encoder_destroy(encoder);
-
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 16/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_plane

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp4_plane allocation to use drmm_plane_alloc(). This
removes the need to perform any actions on plane destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c | 59 --
 1 file changed, 20 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
index b689b618da78..1149e6721534 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c
@@ -20,12 +20,6 @@ struct mdp4_plane {
const char *name;
 
enum mdp4_pipe pipe;
-
-   uint32_t caps;
-   uint32_t nformats;
-   uint32_t formats[32];
-
-   bool enabled;
 };
 #define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
 
@@ -59,15 +53,6 @@ static struct mdp4_kms *get_kms(struct drm_plane *plane)
return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-static void mdp4_plane_destroy(struct drm_plane *plane)
-{
-   struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
-
-   drm_plane_cleanup(plane);
-
-   kfree(mdp4_plane);
-}
-
 /* helper to install properties which are common to planes and crtcs */
 static void mdp4_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj)
@@ -85,7 +70,6 @@ static int mdp4_plane_set_property(struct drm_plane *plane,
 static const struct drm_plane_funcs mdp4_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
-   .destroy = mdp4_plane_destroy,
.set_property = mdp4_plane_set_property,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = 
drm_atomic_helper_plane_duplicate_state,
@@ -377,31 +361,34 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
 {
struct drm_plane *plane = NULL;
struct mdp4_plane *mdp4_plane;
-   int ret;
enum drm_plane_type type;
+   uint32_t pipe_caps;
+   const uint32_t *formats;
+   size_t nformats;
 
-   mdp4_plane = kzalloc(sizeof(*mdp4_plane), GFP_KERNEL);
-   if (!mdp4_plane) {
-   ret = -ENOMEM;
-   goto fail;
+   type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
+
+   pipe_caps = mdp4_pipe_caps(pipe_id);
+   if (pipe_supports_yuv(pipe_caps)) {
+   formats = mdp_rgb_yuv_formats;
+   nformats = mdp_rgb_yuv_num_formats;
+   } else {
+   formats = mdp_rgb_formats;
+   nformats = mdp_rgb_num_formats;
}
 
+   mdp4_plane = drmm_universal_plane_alloc(dev, struct mdp4_plane, base,
+   0xff, _plane_funcs,
+   formats, nformats,
+   supported_format_modifiers,
+   type, NULL);
+   if (IS_ERR(mdp4_plane))
+   return ERR_CAST(mdp4_plane);
+
plane = _plane->base;
 
mdp4_plane->pipe = pipe_id;
mdp4_plane->name = pipe_names[pipe_id];
-   mdp4_plane->caps = mdp4_pipe_caps(pipe_id);
-
-   mdp4_plane->nformats = mdp_get_formats(mdp4_plane->formats,
-   ARRAY_SIZE(mdp4_plane->formats),
-   !pipe_supports_yuv(mdp4_plane->caps));
-
-   type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY;
-   ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs,
-mdp4_plane->formats, mdp4_plane->nformats,
-supported_format_modifiers, type, NULL);
-   if (ret)
-   goto fail;
 
drm_plane_helper_add(plane, _plane_helper_funcs);
 
@@ -410,10 +397,4 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev,
drm_plane_enable_fb_damage_clips(plane);
 
return plane;
-
-fail:
-   if (plane)
-   mdp4_plane_destroy(plane);
-
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 09/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_encoder

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp5_encoder allocation to use drmm_encoder_alloc(). This
removes the need to perform any actions on encoder destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c | 29 +++-
 1 file changed, 4 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
index 79d67c495780..8db97083e14d 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c
@@ -16,17 +16,6 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
return to_mdp5_kms(to_mdp_kms(priv->kms));
 }
 
-static void mdp5_encoder_destroy(struct drm_encoder *encoder)
-{
-   struct mdp5_encoder *mdp5_encoder = to_mdp5_encoder(encoder);
-   drm_encoder_cleanup(encoder);
-   kfree(mdp5_encoder);
-}
-
-static const struct drm_encoder_funcs mdp5_encoder_funcs = {
-   .destroy = mdp5_encoder_destroy,
-};
-
 static void mdp5_vid_encoder_mode_set(struct drm_encoder *encoder,
  struct drm_display_mode *mode,
  struct drm_display_mode *adjusted_mode)
@@ -342,13 +331,11 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device 
*dev,
struct mdp5_encoder *mdp5_encoder;
int enc_type = (intf->type == INTF_DSI) ?
DRM_MODE_ENCODER_DSI : DRM_MODE_ENCODER_TMDS;
-   int ret;
 
-   mdp5_encoder = kzalloc(sizeof(*mdp5_encoder), GFP_KERNEL);
-   if (!mdp5_encoder) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   mdp5_encoder = drmm_encoder_alloc(dev, struct mdp5_encoder, base,
+ NULL, enc_type, NULL);
+   if (IS_ERR(mdp5_encoder))
+   return ERR_CAST(mdp5_encoder);
 
encoder = _encoder->base;
mdp5_encoder->ctl = ctl;
@@ -356,15 +343,7 @@ struct drm_encoder *mdp5_encoder_init(struct drm_device 
*dev,
 
spin_lock_init(_encoder->intf_lock);
 
-   drm_encoder_init(dev, encoder, _encoder_funcs, enc_type, NULL);
-
drm_encoder_helper_add(encoder, _encoder_helper_funcs);
 
return encoder;
-
-fail:
-   if (encoder)
-   mdp5_encoder_destroy(encoder);
-
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 13/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_dsi_encoder

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp4_dsi_encoder allocation to use drmm_encoder_alloc().
This removes the need to perform any actions on this encoder
destruction.

Signed-off-by: Dmitry Baryshkov 
---
 .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c  | 32 +++
 1 file changed, 5 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
index 39b8fe53c29d..74dafe7106be 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c
@@ -26,18 +26,6 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
return to_mdp4_kms(to_mdp_kms(priv->kms));
 }
 
-static void mdp4_dsi_encoder_destroy(struct drm_encoder *encoder)
-{
-   struct mdp4_dsi_encoder *mdp4_dsi_encoder = 
to_mdp4_dsi_encoder(encoder);
-
-   drm_encoder_cleanup(encoder);
-   kfree(mdp4_dsi_encoder);
-}
-
-static const struct drm_encoder_funcs mdp4_dsi_encoder_funcs = {
-   .destroy = mdp4_dsi_encoder_destroy,
-};
-
 static void mdp4_dsi_encoder_mode_set(struct drm_encoder *encoder,
  struct drm_display_mode *mode,
  struct drm_display_mode *adjusted_mode)
@@ -148,28 +136,18 @@ static const struct drm_encoder_helper_funcs 
mdp4_dsi_encoder_helper_funcs = {
 /* initialize encoder */
 struct drm_encoder *mdp4_dsi_encoder_init(struct drm_device *dev)
 {
-   struct drm_encoder *encoder = NULL;
+   struct drm_encoder *encoder;
struct mdp4_dsi_encoder *mdp4_dsi_encoder;
-   int ret;
 
-   mdp4_dsi_encoder = kzalloc(sizeof(*mdp4_dsi_encoder), GFP_KERNEL);
-   if (!mdp4_dsi_encoder) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   mdp4_dsi_encoder = drmm_encoder_alloc(dev, struct mdp4_dsi_encoder, 
base,
+ NULL, DRM_MODE_ENCODER_DSI, NULL);
+   if (IS_ERR(mdp4_dsi_encoder))
+   return ERR_CAST(mdp4_dsi_encoder);
 
encoder = _dsi_encoder->base;
 
-   drm_encoder_init(dev, encoder, _dsi_encoder_funcs,
-DRM_MODE_ENCODER_DSI, NULL);
drm_encoder_helper_add(encoder, _dsi_encoder_helper_funcs);
 
return encoder;
-
-fail:
-   if (encoder)
-   mdp4_dsi_encoder_destroy(encoder);
-
-   return ERR_PTR(ret);
 }
 #endif /* CONFIG_DRM_MSM_DSI */
-- 
2.39.2



[PATCH 12/17] drm/msm/mdp4: use drmm-managed allocation for mdp4_crtc

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp4_crtc allocation to use drmm_crtc_alloc(). This
removes the need to perform any actions on CRTC destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 33 ---
 1 file changed, 17 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
index 169f9de4a12a..5e5c31b44a8a 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c
@@ -6,6 +6,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -123,16 +124,6 @@ static void unref_cursor_worker(struct drm_flip_work 
*work, void *val)
drm_gem_object_put(val);
 }
 
-static void mdp4_crtc_destroy(struct drm_crtc *crtc)
-{
-   struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
-
-   drm_crtc_cleanup(crtc);
-   drm_flip_work_cleanup(_crtc->unref_cursor_work);
-
-   kfree(mdp4_crtc);
-}
-
 /* statically (for now) map planes to mixer stage (z-order): */
 static const int idxs[] = {
[VG1]  = 1,
@@ -475,7 +466,6 @@ static int mdp4_crtc_cursor_move(struct drm_crtc *crtc, int 
x, int y)
 
 static const struct drm_crtc_funcs mdp4_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = mdp4_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.cursor_set = mdp4_crtc_cursor_set,
.cursor_move = mdp4_crtc_cursor_move,
@@ -616,6 +606,13 @@ static const char *dma_names[] = {
"DMA_P", "DMA_S", "DMA_E",
 };
 
+static void mdp4_crtc_flip_cleanup(struct drm_device *dev, void *ptr)
+{
+   struct mdp4_crtc *mdp4_crtc = ptr;
+
+   drm_flip_work_cleanup(_crtc->unref_cursor_work);
+}
+
 /* initialize crtc */
 struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
struct drm_plane *plane, int id, int ovlp_id,
@@ -623,10 +620,13 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 {
struct drm_crtc *crtc = NULL;
struct mdp4_crtc *mdp4_crtc;
+   int ret;
 
-   mdp4_crtc = kzalloc(sizeof(*mdp4_crtc), GFP_KERNEL);
-   if (!mdp4_crtc)
-   return ERR_PTR(-ENOMEM);
+   mdp4_crtc = drmm_crtc_alloc_with_planes(dev, struct mdp4_crtc, base,
+   plane, NULL,
+   _crtc_funcs, NULL);
+   if (IS_ERR(mdp4_crtc))
+   return ERR_CAST(mdp4_crtc);
 
crtc = _crtc->base;
 
@@ -648,9 +648,10 @@ struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
 
drm_flip_work_init(_crtc->unref_cursor_work,
"unref cursor", unref_cursor_worker);
+   ret = drmm_add_action_or_reset(dev, mdp4_crtc_flip_cleanup, mdp4_crtc);
+   if (ret)
+   return ERR_PTR(ret);
 
-   drm_crtc_init_with_planes(dev, crtc, plane, NULL, _crtc_funcs,
- NULL);
drm_crtc_helper_add(crtc, _crtc_helper_funcs);
 
return crtc;
-- 
2.39.2



[PATCH 08/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_crtc

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp5_crtc allocation to use drmm_crtc_alloc(). This
removes the need to perform any actions on CRTC destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 30 +++
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
index 86036dd4e1e8..4a3db2ea1689 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c
@@ -13,6 +13,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -172,14 +173,11 @@ static void unref_cursor_worker(struct drm_flip_work 
*work, void *val)
drm_gem_object_put(val);
 }
 
-static void mdp5_crtc_destroy(struct drm_crtc *crtc)
+static void mdp5_crtc_flip_cleanup(struct drm_device *dev, void *ptr)
 {
-   struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+   struct mdp5_crtc *mdp5_crtc = ptr;
 
-   drm_crtc_cleanup(crtc);
drm_flip_work_cleanup(_crtc->unref_cursor_work);
-
-   kfree(mdp5_crtc);
 }
 
 static inline u32 mdp5_lm_use_fg_alpha_mask(enum mdp_mixer_stage_id stage)
@@ -1147,7 +1145,6 @@ static void mdp5_crtc_reset(struct drm_crtc *crtc)
 
 static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = mdp5_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = mdp5_crtc_reset,
.atomic_duplicate_state = mdp5_crtc_duplicate_state,
@@ -1161,7 +1158,6 @@ static const struct drm_crtc_funcs 
mdp5_crtc_no_lm_cursor_funcs = {
 
 static const struct drm_crtc_funcs mdp5_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = mdp5_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = mdp5_crtc_reset,
.atomic_duplicate_state = mdp5_crtc_duplicate_state,
@@ -1327,10 +1323,16 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 {
struct drm_crtc *crtc = NULL;
struct mdp5_crtc *mdp5_crtc;
+   int ret;
 
-   mdp5_crtc = kzalloc(sizeof(*mdp5_crtc), GFP_KERNEL);
-   if (!mdp5_crtc)
-   return ERR_PTR(-ENOMEM);
+   mdp5_crtc = drmm_crtc_alloc_with_planes(dev, struct mdp5_crtc, base,
+   plane, cursor_plane,
+   cursor_plane ?
+   _crtc_no_lm_cursor_funcs :
+   _crtc_funcs,
+   NULL);
+   if (IS_ERR(mdp5_crtc))
+   return ERR_CAST(mdp5_crtc);
 
crtc = _crtc->base;
 
@@ -1346,13 +1348,11 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
 
mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true;
 
-   drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane,
- cursor_plane ?
- _crtc_no_lm_cursor_funcs :
- _crtc_funcs, NULL);
-
drm_flip_work_init(_crtc->unref_cursor_work,
"unref cursor", unref_cursor_worker);
+   ret = drmm_add_action_or_reset(dev, mdp5_crtc_flip_cleanup, mdp5_crtc);
+   if (ret)
+   return ERR_PTR(ret);
 
drm_crtc_helper_add(crtc, _crtc_helper_funcs);
 
-- 
2.39.2



[PATCH 10/17] drm/msm/mdp5: use drmm-managed allocation for mdp5_plane

2023-07-07 Thread Dmitry Baryshkov
Change struct mdp5_plane allocation to use drmm_plane_alloc(). This
removes the need to perform any actions on plane destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c | 40 --
 1 file changed, 6 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
index bd2c4ac45601..177fc1a56aad 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c
@@ -17,9 +17,6 @@
 
 struct mdp5_plane {
struct drm_plane base;
-
-   uint32_t nformats;
-   uint32_t formats[32];
 };
 #define to_mdp5_plane(x) container_of(x, struct mdp5_plane, base)
 
@@ -38,15 +35,6 @@ static bool plane_enabled(struct drm_plane_state *state)
return state->visible;
 }
 
-static void mdp5_plane_destroy(struct drm_plane *plane)
-{
-   struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
-
-   drm_plane_cleanup(plane);
-
-   kfree(mdp5_plane);
-}
-
 /* helper to install properties which are common to planes and crtcs */
 static void mdp5_plane_install_properties(struct drm_plane *plane,
struct drm_mode_object *obj)
@@ -139,7 +127,6 @@ static void mdp5_plane_destroy_state(struct drm_plane 
*plane,
 static const struct drm_plane_funcs mdp5_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
-   .destroy = mdp5_plane_destroy,
.reset = mdp5_plane_reset,
.atomic_duplicate_state = mdp5_plane_duplicate_state,
.atomic_destroy_state = mdp5_plane_destroy_state,
@@ -1014,25 +1001,16 @@ struct drm_plane *mdp5_plane_init(struct drm_device 
*dev,
 {
struct drm_plane *plane = NULL;
struct mdp5_plane *mdp5_plane;
-   int ret;
 
-   mdp5_plane = kzalloc(sizeof(*mdp5_plane), GFP_KERNEL);
-   if (!mdp5_plane) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   mdp5_plane = drmm_universal_plane_alloc(dev, struct mdp5_plane, base,
+   0xff, _plane_funcs,
+   mdp_rgb_yuv_formats, 
mdp_rgb_yuv_num_formats,
+   NULL, type, NULL);
+   if (IS_ERR(mdp5_plane))
+   return ERR_CAST(mdp5_plane);
 
plane = _plane->base;
 
-   mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats,
-   ARRAY_SIZE(mdp5_plane->formats), false);
-
-   ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs,
-   mdp5_plane->formats, mdp5_plane->nformats,
-   NULL, type, NULL);
-   if (ret)
-   goto fail;
-
drm_plane_helper_add(plane, _plane_helper_funcs);
 
mdp5_plane_install_properties(plane, >base);
@@ -1040,10 +1018,4 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev,
drm_plane_enable_fb_damage_clips(plane);
 
return plane;
-
-fail:
-   if (plane)
-   mdp5_plane_destroy(plane);
-
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 06/17] drm/msm/mdp5: use devres-managed allocation for SMP data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create SMP data structure. This allows us
to remove corresponding kfree and drop mdp5_smp_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c |  3 ---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c | 19 ---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h |  1 -
 3 files changed, 4 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index be4338a48e52..0a85777625d3 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -618,9 +618,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
 {
int i;
 
-   if (mdp5_kms->smp)
-   mdp5_smp_destroy(mdp5_kms->smp);
-
for (i = 0; i < mdp5_kms->num_intfs; i++)
kfree(mdp5_kms->intfs[i]);
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
index 56a3063545ec..d7c957207255 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c
@@ -370,23 +370,17 @@ void mdp5_smp_dump(struct mdp5_smp *smp, struct 
drm_printer *p)
drm_modeset_unlock(_kms->glob_state_lock);
 }
 
-void mdp5_smp_destroy(struct mdp5_smp *smp)
-{
-   kfree(smp);
-}
 
 struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, const struct 
mdp5_smp_block *cfg)
 {
+   struct drm_device *dev = mdp5_kms->dev;
struct mdp5_smp_state *state;
struct mdp5_global_state *global_state;
struct mdp5_smp *smp = NULL;
-   int ret;
 
-   smp = kzalloc(sizeof(*smp), GFP_KERNEL);
-   if (unlikely(!smp)) {
-   ret = -ENOMEM;
-   goto fail;
-   }
+   smp = devm_kzalloc(dev->dev, sizeof(*smp), GFP_KERNEL);
+   if (unlikely(!smp))
+   return ERR_PTR(-ENOMEM);
 
smp->dev = mdp5_kms->dev;
smp->blk_cnt = cfg->mmb_count;
@@ -400,9 +394,4 @@ struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms, 
const struct mdp5_smp_
memcpy(smp->reserved, cfg->reserved, sizeof(smp->reserved));
 
return smp;
-fail:
-   if (smp)
-   mdp5_smp_destroy(smp);
-
-   return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h
index ba5618e136c3..d8b6a11413d9 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h
@@ -68,7 +68,6 @@ struct mdp5_smp;
 
 struct mdp5_smp *mdp5_smp_init(struct mdp5_kms *mdp5_kms,
const struct mdp5_smp_block *cfg);
-void  mdp5_smp_destroy(struct mdp5_smp *smp);
 
 void mdp5_smp_dump(struct mdp5_smp *smp, struct drm_printer *p);
 
-- 
2.39.2



[PATCH 00/17] drm/msm/mdp[45]: use managed memory allocations

2023-07-07 Thread Dmitry Baryshkov
Follow the DPU patchset ([1]) and use devm_ and drmm_ functions to
allocate long-living data structures in mdp4 and mdp5 drivers.

[1] https://patchwork.freedesktop.org/series/120366/

Dmitry Baryshkov (17):
  drm/msm: add arrays listing formats supported by MDP4/MDP5 hardware
  drm/msm/mdp5: use devres-managed allocation for configuration data
  drm/msm/mdp5: use devres-managed allocation for CTL manager data
  drm/msm/mdp5: use devres-managed allocation for mixer data
  drm/msm/mdp5: use devres-managed allocation for pipe data
  drm/msm/mdp5: use devres-managed allocation for SMP data
  drm/msm/mdp5: use devres-managed allocation for INTF data
  drm/msm/mdp5: use drmm-managed allocation for mdp5_crtc
  drm/msm/mdp5: use drmm-managed allocation for mdp5_encoder
  drm/msm/mdp5: use drmm-managed allocation for mdp5_plane
  drm/msm/mdp4: use bulk regulators API for LCDC encoder
  drm/msm/mdp4: use drmm-managed allocation for mdp4_crtc
  drm/msm/mdp4: use drmm-managed allocation for mdp4_dsi_encoder
  drm/msm/mdp4: use drmm-managed allocation for mdp4_dtv_encoder
  drm/msm/mdp4: use drmm-managed allocation for mdp4_lcdc_encoder
  drm/msm/mdp4: use drmm-managed allocation for mdp4_plane
  drm/msm: drop mdp_get_formats()

 drivers/gpu/drm/msm/disp/mdp4/mdp4_crtc.c | 33 +++
 .../gpu/drm/msm/disp/mdp4/mdp4_dsi_encoder.c  | 32 ++-
 .../gpu/drm/msm/disp/mdp4/mdp4_dtv_encoder.c  | 37 ++--
 .../gpu/drm/msm/disp/mdp4/mdp4_lcdc_encoder.c | 87 +--
 drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c| 59 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c  | 24 ++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h  |  1 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_crtc.c | 30 +++
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c  | 21 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h  |  1 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_encoder.c  | 29 +--
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c  | 25 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c| 10 +--
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h|  4 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 10 +--
 drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h |  4 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_plane.c| 40 ++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.c  | 19 +---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_smp.h  |  1 -
 drivers/gpu/drm/msm/disp/mdp_format.c | 67 +-
 drivers/gpu/drm/msm/disp/mdp_kms.h|  6 +-
 21 files changed, 171 insertions(+), 369 deletions(-)

-- 
2.39.2



[PATCH 05/17] drm/msm/mdp5: use devres-managed allocation for pipe data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create pipe data structure. This allows us
to remove corresponding kfree and drop mdp5_pipe_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c  |  6 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c | 10 +++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h |  4 ++--
 3 files changed, 6 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index b4a49d369f0d..be4338a48e52 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -209,10 +209,6 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
 {
struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(kms));
struct msm_gem_address_space *aspace = kms->aspace;
-   int i;
-
-   for (i = 0; i < mdp5_kms->num_hwpipes; i++)
-   mdp5_pipe_destroy(mdp5_kms->hwpipes[i]);
 
if (aspace) {
aspace->mmu->funcs->detach(aspace->mmu);
@@ -645,7 +641,7 @@ static int construct_pipes(struct mdp5_kms *mdp5_kms, int 
cnt,
for (i = 0; i < cnt; i++) {
struct mdp5_hw_pipe *hwpipe;
 
-   hwpipe = mdp5_pipe_init(pipes[i], offsets[i], caps);
+   hwpipe = mdp5_pipe_init(dev, pipes[i], offsets[i], caps);
if (IS_ERR(hwpipe)) {
ret = PTR_ERR(hwpipe);
DRM_DEV_ERROR(dev->dev, "failed to construct pipe for 
%s (%d)\n",
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
index e4b8a789835a..99b2c30b1d48 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.c
@@ -151,17 +151,13 @@ int mdp5_pipe_release(struct drm_atomic_state *s, struct 
mdp5_hw_pipe *hwpipe)
return 0;
 }
 
-void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe)
-{
-   kfree(hwpipe);
-}
-
-struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+struct mdp5_hw_pipe *mdp5_pipe_init(struct drm_device *dev,
+   enum mdp5_pipe pipe,
uint32_t reg_offset, uint32_t caps)
 {
struct mdp5_hw_pipe *hwpipe;
 
-   hwpipe = kzalloc(sizeof(*hwpipe), GFP_KERNEL);
+   hwpipe = devm_kzalloc(dev->dev, sizeof(*hwpipe), GFP_KERNEL);
if (!hwpipe)
return ERR_PTR(-ENOMEM);
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h
index cca67938cab2..452138821f60 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_pipe.h
@@ -39,8 +39,8 @@ int mdp5_pipe_assign(struct drm_atomic_state *s, struct 
drm_plane *plane,
 struct mdp5_hw_pipe **r_hwpipe);
 int mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe);
 
-struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe,
+struct mdp5_hw_pipe *mdp5_pipe_init(struct drm_device *dev,
+   enum mdp5_pipe pipe,
uint32_t reg_offset, uint32_t caps);
-void mdp5_pipe_destroy(struct mdp5_hw_pipe *hwpipe);
 
 #endif /* __MDP5_PIPE_H__ */
-- 
2.39.2



[PATCH 07/17] drm/msm/mdp5: use devres-managed allocation for INTF data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create INTF data structure. This allows us
to remove corresponding kfree() call.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 0a85777625d3..fb2b3bf081ee 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -616,11 +616,6 @@ static int mdp5_kms_init(struct drm_device *dev)
 
 static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
 {
-   int i;
-
-   for (i = 0; i < mdp5_kms->num_intfs; i++)
-   kfree(mdp5_kms->intfs[i]);
-
if (mdp5_kms->rpm_enabled)
pm_runtime_disable(_kms->pdev->dev);
 
@@ -741,7 +736,7 @@ static int interface_init(struct mdp5_kms *mdp5_kms)
if (intf_types[i] == INTF_DISABLED)
continue;
 
-   intf = kzalloc(sizeof(*intf), GFP_KERNEL);
+   intf = devm_kzalloc(dev->dev, sizeof(*intf), GFP_KERNEL);
if (!intf) {
DRM_DEV_ERROR(dev->dev, "failed to construct INTF%d\n", 
i);
return -ENOMEM;
-- 
2.39.2



[PATCH 01/17] drm/msm: add arrays listing formats supported by MDP4/MDP5 hardware

2023-07-07 Thread Dmitry Baryshkov
MDP4 and MDP5 drivers enumerate supported formats each time the plane is
created. As the list of supported image formats is constant, create
corresponding data arrays to be used by MDP4 and MDP5 drivers.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp_format.c | 49 +--
 drivers/gpu/drm/msm/disp/mdp_kms.h|  5 +++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp_format.c 
b/drivers/gpu/drm/msm/disp/mdp_format.c
index 025595336f26..ba9abe8b3acc 100644
--- a/drivers/gpu/drm/msm/disp/mdp_format.c
+++ b/drivers/gpu/drm/msm/disp/mdp_format.c
@@ -81,8 +81,8 @@ static struct csc_cfg csc_convert[CSC_MAX] = {
 #define BPC0A 0
 
 /*
- * Note: Keep RGB formats 1st, followed by YUV formats to avoid breaking
- * mdp_get_rgb_formats()'s implementation.
+ * Note: Keep mdp_rgb_formats and mdp_rgb_yuv_formats in sync when adding
+ * entries to this array.
  */
 static const struct mdp_format formats[] = {
/*  name  a  r  g  b   e0 e1 e2 e3  alpha   tight  cpp cnt ... */
@@ -138,6 +138,51 @@ static const struct mdp_format formats[] = {
MDP_PLANE_PLANAR, CHROMA_420, true),
 };
 
+const uint32_t mdp_rgb_formats[] = {
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_XRGB,
+   DRM_FORMAT_XBGR,
+   DRM_FORMAT_RGBX,
+   DRM_FORMAT_BGRX,
+   DRM_FORMAT_RGB888,
+   DRM_FORMAT_BGR888,
+   DRM_FORMAT_RGB565,
+   DRM_FORMAT_BGR565,
+};
+
+size_t mdp_rgb_num_formats = ARRAY_SIZE(mdp_rgb_formats);
+
+const uint32_t mdp_rgb_yuv_formats[] = {
+   DRM_FORMAT_ARGB,
+   DRM_FORMAT_ABGR,
+   DRM_FORMAT_RGBA,
+   DRM_FORMAT_BGRA,
+   DRM_FORMAT_XRGB,
+   DRM_FORMAT_XBGR,
+   DRM_FORMAT_RGBX,
+   DRM_FORMAT_BGRX,
+   DRM_FORMAT_RGB888,
+   DRM_FORMAT_BGR888,
+   DRM_FORMAT_RGB565,
+   DRM_FORMAT_BGR565,
+
+   DRM_FORMAT_NV12,
+   DRM_FORMAT_NV21,
+   DRM_FORMAT_NV16,
+   DRM_FORMAT_NV61,
+   DRM_FORMAT_VYUY,
+   DRM_FORMAT_UYVY,
+   DRM_FORMAT_YUYV,
+   DRM_FORMAT_YVYU,
+   DRM_FORMAT_YUV420,
+   DRM_FORMAT_YVU420,
+};
+
+size_t mdp_rgb_yuv_num_formats = ARRAY_SIZE(mdp_rgb_yuv_formats);
+
 /*
  * Note:
  * @rgb_only must be set to true, when requesting
diff --git a/drivers/gpu/drm/msm/disp/mdp_kms.h 
b/drivers/gpu/drm/msm/disp/mdp_kms.h
index b0286d5d5130..11402a859574 100644
--- a/drivers/gpu/drm/msm/disp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/disp/mdp_kms.h
@@ -94,6 +94,11 @@ struct mdp_format {
 uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool 
rgb_only);
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format, 
uint64_t modifier);
 
+extern const uint32_t mdp_rgb_formats[];
+extern size_t mdp_rgb_num_formats;
+extern const uint32_t mdp_rgb_yuv_formats[];
+extern size_t mdp_rgb_yuv_num_formats;
+
 /* MDP capabilities */
 #define MDP_CAP_SMPBIT(0)  /* Shared Memory Pool */
 #define MDP_CAP_DSCBIT(1)  /* VESA Display Stream Compression*/
-- 
2.39.2



[PATCH 03/17] drm/msm/mdp5: use devres-managed allocation for CTL manager data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create CTL manager data structure. This allows us
to remove corresponding kfree and drop mdp5_ctlm_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c | 21 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h |  1 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c |  2 --
 3 files changed, 4 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
index 1220f2b20e05..666de99a46a5 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.c
@@ -681,11 +681,6 @@ void mdp5_ctlm_hw_reset(struct mdp5_ctl_manager *ctl_mgr)
}
 }
 
-void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctl_mgr)
-{
-   kfree(ctl_mgr);
-}
-
 struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd)
 {
@@ -697,18 +692,16 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device 
*dev,
unsigned long flags;
int c, ret;
 
-   ctl_mgr = kzalloc(sizeof(*ctl_mgr), GFP_KERNEL);
+   ctl_mgr = devm_kzalloc(dev->dev, sizeof(*ctl_mgr), GFP_KERNEL);
if (!ctl_mgr) {
DRM_DEV_ERROR(dev->dev, "failed to allocate CTL manager\n");
-   ret = -ENOMEM;
-   goto fail;
+   return ERR_PTR(-ENOMEM);
}
 
if (WARN_ON(ctl_cfg->count > MAX_CTL)) {
DRM_DEV_ERROR(dev->dev, "Increase static pool size to at least 
%d\n",
ctl_cfg->count);
-   ret = -ENOSPC;
-   goto fail;
+   return ERR_PTR(-ENOSPC);
}
 
/* initialize the CTL manager: */
@@ -727,7 +720,7 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device 
*dev,
DRM_DEV_ERROR(dev->dev, "CTL_%d: base is null!\n", c);
ret = -EINVAL;
spin_unlock_irqrestore(_mgr->pool_lock, flags);
-   goto fail;
+   return ERR_PTR(ret);
}
ctl->ctlm = ctl_mgr;
ctl->id = c;
@@ -755,10 +748,4 @@ struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device 
*dev,
DBG("Pool of %d CTLs created.", ctl_mgr->nctl);
 
return ctl_mgr;
-
-fail:
-   if (ctl_mgr)
-   mdp5_ctlm_destroy(ctl_mgr);
-
-   return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
index c2af68aa77ae..9020e8efc4e4 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_ctl.h
@@ -17,7 +17,6 @@ struct mdp5_ctl_manager;
 struct mdp5_ctl_manager *mdp5_ctlm_init(struct drm_device *dev,
void __iomem *mmio_base, struct mdp5_cfg_handler *cfg_hnd);
 void mdp5_ctlm_hw_reset(struct mdp5_ctl_manager *ctlm);
-void mdp5_ctlm_destroy(struct mdp5_ctl_manager *ctlm);
 
 /*
  * CTL prototypes:
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 828634206185..e20ead138602 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -625,8 +625,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
 {
int i;
 
-   if (mdp5_kms->ctlm)
-   mdp5_ctlm_destroy(mdp5_kms->ctlm);
if (mdp5_kms->smp)
mdp5_smp_destroy(mdp5_kms->smp);
 
-- 
2.39.2



[PATCH 04/17] drm/msm/mdp5: use devres-managed allocation for mixer data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create mixer data structure. This allows us
to remove corresponding kfree and drop mdp5_mixer_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c   |  5 +
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c | 10 +++---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h |  4 ++--
 3 files changed, 6 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index e20ead138602..b4a49d369f0d 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -211,9 +211,6 @@ static void mdp5_kms_destroy(struct msm_kms *kms)
struct msm_gem_address_space *aspace = kms->aspace;
int i;
 
-   for (i = 0; i < mdp5_kms->num_hwmixers; i++)
-   mdp5_mixer_destroy(mdp5_kms->hwmixers[i]);
-
for (i = 0; i < mdp5_kms->num_hwpipes; i++)
mdp5_pipe_destroy(mdp5_kms->hwpipes[i]);
 
@@ -720,7 +717,7 @@ static int hwmixer_init(struct mdp5_kms *mdp5_kms)
for (i = 0; i < hw_cfg->lm.count; i++) {
struct mdp5_hw_mixer *mixer;
 
-   mixer = mdp5_mixer_init(_cfg->lm.instances[i]);
+   mixer = mdp5_mixer_init(dev, _cfg->lm.instances[i]);
if (IS_ERR(mixer)) {
ret = PTR_ERR(mixer);
DRM_DEV_ERROR(dev->dev, "failed to construct LM%d 
(%d)\n",
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
index 2536def2a000..2822b533f807 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.c
@@ -140,20 +140,16 @@ int mdp5_mixer_release(struct drm_atomic_state *s, struct 
mdp5_hw_mixer *mixer)
return 0;
 }
 
-void mdp5_mixer_destroy(struct mdp5_hw_mixer *mixer)
-{
-   kfree(mixer);
-}
-
 static const char * const mixer_names[] = {
"LM0", "LM1", "LM2", "LM3", "LM4", "LM5",
 };
 
-struct mdp5_hw_mixer *mdp5_mixer_init(const struct mdp5_lm_instance *lm)
+struct mdp5_hw_mixer *mdp5_mixer_init(struct drm_device *dev,
+ const struct mdp5_lm_instance *lm)
 {
struct mdp5_hw_mixer *mixer;
 
-   mixer = kzalloc(sizeof(*mixer), GFP_KERNEL);
+   mixer = devm_kzalloc(dev->dev, sizeof(*mixer), GFP_KERNEL);
if (!mixer)
return ERR_PTR(-ENOMEM);
 
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h
index 545ee223b9d7..2bedd75835bc 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_mixer.h
@@ -25,8 +25,8 @@ struct mdp5_hw_mixer_state {
struct drm_crtc *hwmixer_to_crtc[8];
 };
 
-struct mdp5_hw_mixer *mdp5_mixer_init(const struct mdp5_lm_instance *lm);
-void mdp5_mixer_destroy(struct mdp5_hw_mixer *lm);
+struct mdp5_hw_mixer *mdp5_mixer_init(struct drm_device *dev,
+ const struct mdp5_lm_instance *lm);
 int mdp5_mixer_assign(struct drm_atomic_state *s, struct drm_crtc *crtc,
  uint32_t caps, struct mdp5_hw_mixer **mixer,
  struct mdp5_hw_mixer **r_mixer);
-- 
2.39.2



[PATCH 02/17] drm/msm/mdp5: use devres-managed allocation for configuration data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create configuration data structure. This allows us
to remove corresponding kfree and drop mdp5_cfg_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 24 +---
 drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h |  1 -
 drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c |  2 --
 3 files changed, 5 insertions(+), 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index 694d54341337..c5179e4c393c 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -1350,23 +1350,17 @@ int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler 
*cfg_handler)
return cfg_handler->revision;
 }
 
-void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_handler)
-{
-   kfree(cfg_handler);
-}
-
 struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
uint32_t major, uint32_t minor)
 {
struct drm_device *dev = mdp5_kms->dev;
struct mdp5_cfg_handler *cfg_handler;
const struct mdp5_cfg_handler *cfg_handlers;
-   int i, ret = 0, num_handlers;
+   int i, num_handlers;
 
-   cfg_handler = kzalloc(sizeof(*cfg_handler), GFP_KERNEL);
+   cfg_handler = devm_kzalloc(dev->dev, sizeof(*cfg_handler), GFP_KERNEL);
if (unlikely(!cfg_handler)) {
-   ret = -ENOMEM;
-   goto fail;
+   return ERR_PTR(-ENOMEM);
}
 
switch (major) {
@@ -1381,8 +1375,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms 
*mdp5_kms,
default:
DRM_DEV_ERROR(dev->dev, "unexpected MDP major version: 
v%d.%d\n",
major, minor);
-   ret = -ENXIO;
-   goto fail;
+   return ERR_PTR(-ENXIO);
}
 
/* only after mdp5_cfg global pointer's init can we access the hw */
@@ -1396,8 +1389,7 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms 
*mdp5_kms,
if (unlikely(!mdp5_cfg)) {
DRM_DEV_ERROR(dev->dev, "unexpected MDP minor revision: 
v%d.%d\n",
major, minor);
-   ret = -ENXIO;
-   goto fail;
+   return ERR_PTR(-ENXIO);
}
 
cfg_handler->revision = minor;
@@ -1406,10 +1398,4 @@ struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms 
*mdp5_kms,
DBG("MDP5: %s hw config selected", mdp5_cfg->name);
 
return cfg_handler;
-
-fail:
-   if (cfg_handler)
-   mdp5_cfg_destroy(cfg_handler);
-
-   return ERR_PTR(ret);
 }
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h
index c2502cc33864..26c5d8b4ab46 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.h
@@ -121,6 +121,5 @@ int mdp5_cfg_get_hw_rev(struct mdp5_cfg_handler *cfg_hnd);
 
 struct mdp5_cfg_handler *mdp5_cfg_init(struct mdp5_kms *mdp5_kms,
uint32_t major, uint32_t minor);
-void mdp5_cfg_destroy(struct mdp5_cfg_handler *cfg_hnd);
 
 #endif /* __MDP5_CFG_H__ */
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 52f176e08690..828634206185 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -629,8 +629,6 @@ static void mdp5_destroy(struct mdp5_kms *mdp5_kms)
mdp5_ctlm_destroy(mdp5_kms->ctlm);
if (mdp5_kms->smp)
mdp5_smp_destroy(mdp5_kms->smp);
-   if (mdp5_kms->cfg)
-   mdp5_cfg_destroy(mdp5_kms->cfg);
 
for (i = 0; i < mdp5_kms->num_intfs; i++)
kfree(mdp5_kms->intfs[i]);
-- 
2.39.2



Re: [PATCH v1 0/5] incorporate pm runtime framework and eDP clean up

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

Incorporate pm runtime framework into DP driver and clean up eDP
by moving of_dp_aux_populate_bus() to probe()


Please use sensible prefix for cover letters too. It helps people 
understand, which driver/area is touched by the patchset.




Kuogee Hsieh (5):
   drm/msm/dp: remove pm_runtime_xxx() from dp_power.c
   drm/msm/dp: incorporate pm_runtime framework into DP driver
   drm/msm/dp: delete EV_HPD_INIT_SETUP
   drm/msm/dp: move relevant dp initialization code from bind() to
 probe()
   drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP

  drivers/gpu/drm/msm/dp/dp_aux.c |  28 +
  drivers/gpu/drm/msm/dp/dp_display.c | 204 +---
  drivers/gpu/drm/msm/dp/dp_display.h |   1 -
  drivers/gpu/drm/msm/dp/dp_power.c   |   9 --
  4 files changed, 145 insertions(+), 97 deletions(-)



--
With best wishes
Dmitry



Re: [PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

EV_HPD_INIT_SETUP flag is used to trigger the initialization of external
DP host controller. Since external DP host controller initialization had
been incorporated into pm_runtime_resume(), this flag become obsolete.
Lets get rid of it.


And another question. Between patches #2 and #3 we have both INIT_SETUP 
event and the PM doing dp_display_host_init(). Will it work correctly?




Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 12 
  1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 2c5706a..44580c2 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -55,7 +55,6 @@ enum {
  enum {
EV_NO_EVENT,
/* hpd events */
-   EV_HPD_INIT_SETUP,
EV_HPD_PLUG_INT,
EV_IRQ_HPD_INT,
EV_HPD_UNPLUG_INT,
@@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data)
spin_unlock_irqrestore(_priv->event_lock, flag);
  
  		switch (todo->event_id) {

-   case EV_HPD_INIT_SETUP:
-   dp_display_host_init(dp_priv);
-   break;
case EV_HPD_PLUG_INT:
dp_hpd_plug_handle(dp_priv, todo->data);
break;
@@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void)
  
  void msm_dp_irq_postinstall(struct msm_dp *dp_display)

  {
-   struct dp_display_private *dp;
-
-   if (!dp_display)
-   return;
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
  
-	if (!dp_display->is_edp)

-   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0);
  }
  
  bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)


--
With best wishes
Dmitry



Re: [PATCH v1 5/5] drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

Move of_dp_aux_populate_bus() to dp_display_probe() for eDP
from dp_display_bind() so that probe deferral cases can be
handled effectively

Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_aux.c | 25 
  drivers/gpu/drm/msm/dp/dp_display.c | 79 +++--
  2 files changed, 65 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index c592064..c1baffb 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -505,6 +505,21 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux)
drm_dp_aux_unregister(dp_aux);
  }
  
+static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,

+unsigned long wait_us)
+{
+   int ret;
+   struct dp_aux_private *aux;
+
+   aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+   pm_runtime_get_sync(aux->dev);
+   ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
+   pm_runtime_put_sync(aux->dev);
+
+   return ret;
+}
+
  struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
  bool is_edp)
  {
@@ -528,6 +543,16 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct 
dp_catalog *catalog,
aux->catalog = catalog;
aux->retry_cnt = 0;
  
+	/*

+* Use the drm_dp_aux_init() to use the aux adapter
+* before registering aux with the DRM device.
+*/
+   aux->dp_aux.name = "dpu_dp_aux";
+   aux->dp_aux.dev = dev;
+   aux->dp_aux.transfer = dp_aux_transfer;
+   aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted;
+   drm_dp_aux_init(>dp_aux);
+
return >dp_aux;
  }
  
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c

index 185f1eb..7ed4bea 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -302,10 +302,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
  
-	pm_runtime_enable(dev);

-   pm_runtime_set_autosuspend_delay(dev, 1000);
-   pm_runtime_use_autosuspend(dev);
-
return 0;
  end:
return rc;
@@ -322,8 +318,6 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
  
  	kthread_stop(dp->ev_tsk);
  
-	of_dp_aux_depopulate_bus(dp->aux);

-
dp_power_client_deinit(dp->power);
dp_unregister_audio_driver(dev, dp->audio);
dp_aux_unregister(dp->aux);
@@ -1245,6 +1239,29 @@ static const struct msm_dp_desc 
*dp_display_get_desc(struct platform_device *pde
return NULL;
  }
  
+static void of_dp_aux_depopulate_bus_void(void *data)

+{
+   of_dp_aux_depopulate_bus(data);
+}
+
+static int dp_display_auxbus_emulation(struct dp_display_private *dp)


Why is it called emulation?


+{
+   struct device *dev = >pdev->dev;
+   struct device_node *aux_bus;
+   int ret = 0;
+
+   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
+
+   if (aux_bus) {
+   ret = devm_of_dp_aux_populate_bus(dp->aux, NULL);


And here you missed the whole point of why we have been asking for. 
Please add a sensible `done_probing' callback, which will call 
component_add(). This way the DP component will only be registered when 
the panel has been probed. Keeping us from the component binding retries 
and corresponding side effects.



+
+   devm_add_action_or_reset(dev, of_dp_aux_depopulate_bus_void,
+dp->aux);


Useless, it's already handled by the devm_ part of the 
devm_of_dp_aux_populate_bus().



+   }
+
+   return ret;
+}
+
  static int dp_display_probe(struct platform_device *pdev)
  {
int rc = 0;
@@ -1290,8 +1307,18 @@ static int dp_display_probe(struct platform_device *pdev)
  
  	platform_set_drvdata(pdev, >dp_display);
  
+	pm_runtime_enable(>dev);

+   pm_runtime_set_autosuspend_delay(>dev, 1000);
+   pm_runtime_use_autosuspend(>dev);


Can we have this in probe right from the patch #2?


+
dp_display_request_irq(dp);
  
+	if (dp->dp_display.is_edp) {

+   rc = dp_display_auxbus_emulation(dp);
+   if (rc)
+   DRM_ERROR("eDP aux-bus emulation failed, rc=%d\n", rc);
+   }
+
rc = component_add(>dev, _display_comp_ops);
if (rc) {
DRM_ERROR("component add failed, rc=%d\n", rc);
@@ -1306,11 +1333,14 @@ static int dp_display_remove(struct platform_device 
*pdev)
struct dp_display_private *dp = dev_get_dp_display_private(>dev);
  
  	component_del(>dev, _display_comp_ops);

-   dp_display_deinit_sub_modules(dp);
-
platform_set_drvdata(pdev, NULL);
+
+   pm_runtime_dont_use_autosuspend(>dev);
+   pm_runtime_disable(>dev);
pm_runtime_put_sync_suspend(>dev);
  
+	

Re: [PATCH v1 4/5] drm/msm/dp: move relevant dp initialization code from bind() to probe()

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

In preparation of moving edp of_dp_aux_populate_bus() to
dp_display_probe(), move dp_display_request_irq(),
dp->parser->parse() and dp_power_client_init() to dp_display_probe()
too.

Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 48 +
  drivers/gpu/drm/msm/dp/dp_display.h |  1 -
  2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 44580c2..185f1eb 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -290,12 +290,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
  
-	rc = dp_power_client_init(dp->power);

-   if (rc) {
-   DRM_ERROR("Power client create failed\n");
-   goto end;
-   }
-
rc = dp_register_audio_driver(dev, dp->audio);
if (rc) {
DRM_ERROR("Audio registration Dp failed\n");
@@ -752,6 +746,12 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error;
}
  
+	rc = dp->parser->parse(dp->parser);

+   if (rc) {
+   DRM_ERROR("device tree parsing failed\n");
+   goto error;
+   }
+
dp->catalog = dp_catalog_get(dev, >parser->io);
if (IS_ERR(dp->catalog)) {
rc = PTR_ERR(dp->catalog);
@@ -768,6 +768,12 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error;
}
  
+	rc = dp_power_client_init(dp->power);

+   if (rc) {
+   DRM_ERROR("Power client create failed\n");
+   goto error;
+   }
+
dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp);
if (IS_ERR(dp->aux)) {
rc = PTR_ERR(dp->aux);
@@ -1196,26 +1202,20 @@ static irqreturn_t dp_display_irq_handler(int irq, void 
*dev_id)
return ret;
  }
  
-int dp_display_request_irq(struct msm_dp *dp_display)

+static int dp_display_request_irq(struct dp_display_private *dp)
  {
int rc = 0;
-   struct dp_display_private *dp;
-
-   if (!dp_display) {
-   DRM_ERROR("invalid input\n");
-   return -EINVAL;
-   }
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
+   struct device *dev = >pdev->dev;
  
-	dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);

if (!dp->irq) {
-   DRM_ERROR("failed to get irq\n");
-   return -EINVAL;
+   dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);
+   if (!dp->irq) {
+   DRM_ERROR("failed to get irq\n");
+   return -EINVAL;
+   }
}


Use platform_get_irq() from probe() function.

  
-	rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq,

-   dp_display_irq_handler,
+   rc = devm_request_irq(dev, dp->irq, dp_display_irq_handler,
IRQF_TRIGGER_HIGH, "dp_display_isr", dp);




if (rc < 0) {
DRM_ERROR("failed to request IRQ%u: %d\n",
@@ -1290,6 +1290,8 @@ static int dp_display_probe(struct platform_device *pdev)
  
  	platform_set_drvdata(pdev, >dp_display);
  
+	dp_display_request_irq(dp);

+


Error checking?
Are we completely ready to handle interrupts at this point?


rc = component_add(>dev, _display_comp_ops);
if (rc) {
DRM_ERROR("component add failed, rc=%d\n", rc);
@@ -1574,12 +1576,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, 
struct drm_device *dev,
  
  	dp_priv = container_of(dp_display, struct dp_display_private, dp_display);
  
-	ret = dp_display_request_irq(dp_display);

-   if (ret) {
-   DRM_ERROR("request_irq failed, ret=%d\n", ret);
-   return ret;
-   }
-
ret = dp_display_get_next_bridge(dp_display);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 1e9415a..b3c08de 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -35,7 +35,6 @@ struct msm_dp {
  int dp_display_set_plugged_cb(struct msm_dp *dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev);
  int dp_display_get_modes(struct msm_dp *dp_display);
-int dp_display_request_irq(struct msm_dp *dp_display);
  bool dp_display_check_video_test(struct msm_dp *dp_display);
  int dp_display_get_test_bpp(struct msm_dp *dp_display);
  void dp_display_signal_audio_start(struct msm_dp *dp_display);


--
With best wishes
Dmitry



Re: [PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

EV_HPD_INIT_SETUP flag is used to trigger the initialization of external
DP host controller. Since external DP host controller initialization had
been incorporated into pm_runtime_resume(), this flag become obsolete.
Lets get rid of it.

Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_display.c | 12 
  1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 2c5706a..44580c2 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -55,7 +55,6 @@ enum {
  enum {
EV_NO_EVENT,
/* hpd events */
-   EV_HPD_INIT_SETUP,
EV_HPD_PLUG_INT,
EV_IRQ_HPD_INT,
EV_HPD_UNPLUG_INT,
@@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data)
spin_unlock_irqrestore(_priv->event_lock, flag);
  
  		switch (todo->event_id) {

-   case EV_HPD_INIT_SETUP:
-   dp_display_host_init(dp_priv);
-   break;
case EV_HPD_PLUG_INT:
dp_hpd_plug_handle(dp_priv, todo->data);
break;
@@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void)
  
  void msm_dp_irq_postinstall(struct msm_dp *dp_display)

  {
-   struct dp_display_private *dp;
-
-   if (!dp_display)
-   return;
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
  
-	if (!dp_display->is_edp)

-   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0);
  }


Why do you keep an empty function?

  
  bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)


--
With best wishes
Dmitry



Re: [PATCH] drm/nouveau/disp/g94: enable HDMI

2023-07-07 Thread Karol Herbst
On Fri, Jul 7, 2023 at 11:03 PM Lyude Paul  wrote:
>
> Reviewed-by: Lyude Paul 
>
> But seeing as I looked at this + some other patches yesterday I assume there's
> still more to this?
>

not really. All those patches are all independent and just a bunch of
fixes. I just figured this one out a bit later.

> On Fri, 2023-06-30 at 18:06 +0200, Karol Herbst wrote:
> > Cc: Ben Skeggs 
> > Cc: Lyude Paul 
> > Fixes: f530bc60a30b ("drm/nouveau/disp: move HDMI config into acquire + 
> > infoframe methods")
> > Signed-off-by: Karol Herbst 
> > ---
> >  drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1 +
> >  1 file changed, 1 insertion(+)
> >
> > diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c 
> > b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> > index a4853c4e5ee3..67ef889a0c5f 100644
> > --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> > +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> > @@ -295,6 +295,7 @@ g94_sor = {
> >   .clock = nv50_sor_clock,
> >   .war_2 = g94_sor_war_2,
> >   .war_3 = g94_sor_war_3,
> > + .hdmi = _sor_hdmi,
> >   .dp = _sor_dp,
> >  };
> >
>
> --
> Cheers,
>  Lyude Paul (she/her)
>  Software Engineer at Red Hat
>



Re: [PATCH v1 1/5] drm/msm/dp: remove pm_runtime_xxx() from dp_power.c

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

Since both pm_runtime_resume() and pm_runtime_suspend() are not
populated at dp_pm_ops. Those pm_runtime_get/put() functions within
dp_power.c will not have any effects in addition to increase/decrease
power counter.


Lie.


Also pm_runtime_xxx() should be executed at top
layer.


Why?



Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_power.c | 9 -
  1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_power.c 
b/drivers/gpu/drm/msm/dp/dp_power.c
index 5cb84ca..ed2f62a 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.c
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -152,8 +152,6 @@ int dp_power_client_init(struct dp_power *dp_power)
  
  	power = container_of(dp_power, struct dp_power_private, dp_power);
  
-	pm_runtime_enable(power->dev);

-
return dp_power_clk_init(power);
  }
  
@@ -162,8 +160,6 @@ void dp_power_client_deinit(struct dp_power *dp_power)

struct dp_power_private *power;
  
  	power = container_of(dp_power, struct dp_power_private, dp_power);

-
-   pm_runtime_disable(power->dev);
  }
  
  int dp_power_init(struct dp_power *dp_power)

@@ -173,11 +169,7 @@ int dp_power_init(struct dp_power *dp_power)
  
  	power = container_of(dp_power, struct dp_power_private, dp_power);
  
-	pm_runtime_get_sync(power->dev);

-
rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
-   if (rc)
-   pm_runtime_put_sync(power->dev);
  
  	return rc;

  }
@@ -189,7 +181,6 @@ int dp_power_deinit(struct dp_power *dp_power)
power = container_of(dp_power, struct dp_power_private, dp_power);
  
  	dp_power_clk_enable(dp_power, DP_CORE_PM, false);

-   pm_runtime_put_sync(power->dev);
return 0;
  }
  


--
With best wishes
Dmitry



Re: [PATCH v1 2/5] drm/msm/dp: incorporate pm_runtime framework into DP driver

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Kuogee Hsieh wrote:

Incorporating pm runtime framework into DP driver so that power
and clock resource handling can be centralized allowing easier
control of these resources in preparation of registering aux bus
uring probe.

Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_aux.c |  3 ++
  drivers/gpu/drm/msm/dp/dp_display.c | 75 +
  2 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 8e3b677..c592064 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -291,6 +291,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
return -EINVAL;
}
  
+	pm_runtime_get_sync(dp_aux->dev);


Let me quote the function's documentation:
Consider using pm_runtime_resume_and_get() instead of it, especially if 
its return value is checked by the caller, as this is likely to result 
in cleaner code.


So two notes concerning the whole patch:
- error checking is missing
- please use pm_runtime_resume_and_get() instead.


mutex_lock(>mutex);
if (!aux->initted) {
ret = -EIO;
@@ -364,6 +365,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
  
  exit:

mutex_unlock(>mutex);
+   pm_runtime_mark_last_busy(dp_aux->dev);
+   pm_runtime_put_autosuspend(dp_aux->dev);
  
  	return ret;

  }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 76f1395..2c5706a 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -309,6 +309,10 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
  
+	pm_runtime_enable(dev);


devm_pm_runtime_enable() removes need for a cleanup.


+   pm_runtime_set_autosuspend_delay(dev, 1000);
+   pm_runtime_use_autosuspend(dev);


Why do you want to use autosuspend here?


+
return 0;
  end:
return rc;
@@ -320,9 +324,8 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct dp_display_private *dp = dev_get_dp_display_private(dev);
struct msm_drm_private *priv = dev_get_drvdata(master);
  
-	/* disable all HPD interrupts */

-   if (dp->core_initialized)
-   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, 
false);
+   pm_runtime_dont_use_autosuspend(dev);
+   pm_runtime_disable(dev);
  
  	kthread_stop(dp->ev_tsk);
  
@@ -466,10 +469,12 @@ static void dp_display_host_init(struct dp_display_private *dp)

dp->dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
  
-	dp_power_init(dp->power);

-   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
-   dp_aux_init(dp->aux);
-   dp->core_initialized = true;
+   if (!dp->core_initialized) {
+   dp_power_init(dp->power);
+   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
+   dp_aux_init(dp->aux);
+   dp->core_initialized = true;
+   }


Is this relevant to PM runtime? I don't think so.


  }
  
  static void dp_display_host_deinit(struct dp_display_private *dp)

@@ -478,10 +483,12 @@ static void dp_display_host_deinit(struct 
dp_display_private *dp)
dp->dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
  
-	dp_ctrl_reset_irq_ctrl(dp->ctrl, false);

-   dp_aux_deinit(dp->aux);
-   dp_power_deinit(dp->power);
-   dp->core_initialized = false;
+   if (dp->core_initialized) {
+   dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
+   dp_aux_deinit(dp->aux);
+   dp_power_deinit(dp->power);
+   dp->core_initialized = false;
+   }
  }
  
  static int dp_display_usbpd_configure_cb(struct device *dev)

@@ -1304,6 +1311,39 @@ static int dp_display_remove(struct platform_device 
*pdev)
dp_display_deinit_sub_modules(dp);
  
  	platform_set_drvdata(pdev, NULL);

+   pm_runtime_put_sync_suspend(>dev);
+
+   return 0;
+}
+
+static int dp_pm_runtime_suspend(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dp *dp_display = platform_get_drvdata(pdev);
+   struct dp_display_private *dp;
+
+   dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+   dp_display_host_phy_exit(dp);
+   dp_catalog_ctrl_hpd_enable(dp->catalog);


What? NO!


+   dp_display_host_deinit(dp);
+
+   return 0;
+}
+
+static int dp_pm_runtime_resume(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dp *dp_display = platform_get_drvdata(pdev);
+   struct dp_display_private *dp;
+
+   dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+   dp_display_host_init(dp);
+   if (dp_display->is_edp) {
+

Re: [PATCH 09/12] drm/msm/adreno: Add adreno family

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:52, Rob Clark wrote:

On Thu, Jul 6, 2023 at 8:16 PM Dmitry Baryshkov
 wrote:


On 07/07/2023 02:35, Konrad Dybcio wrote:

On 6.07.2023 23:10, Rob Clark wrote:

From: Rob Clark 

Sometimes it is useful to know the sub-generation (or "family").  And in
any case, this helps us get away from infering the generation from the
numerical chip-id.

Signed-off-by: Rob Clark 
---

[...]


  .rev   = ADRENO_REV(5, 0, 8, ANY_ID),
+.family = ADRENO_5XX,
  .revn = 508,

508 is from 530 fam


  .fw = {
  [ADRENO_FW_PM4] = "a530_pm4.fw",
@@ -156,6 +168,7 @@ static const struct adreno_info gpulist[] = {
  .zapfw = "a508_zap.mdt",
  }, {
  .rev   = ADRENO_REV(5, 0, 9, ANY_ID),
+.family = ADRENO_5XX,
  .revn = 509,

509 and 512 are from 540 fam


  .fw = {
  [ADRENO_FW_PM4] = "a530_pm4.fw",
@@ -173,6 +186,7 @@ static const struct adreno_info gpulist[] = {
  .zapfw = "a512_zap.mdt",
  }, {
  .rev   = ADRENO_REV(5, 1, 0, ANY_ID),
+.family = ADRENO_5XX,
  .revn = 510,

510 is 530ish but I think it's closer to 505 or whatever the
8953 gpu was called


I'd say, there were following generations here:

- a505 / a506 / a508
- a509 / a512
- a510
- a530
- a540

Indeed a50x were close to a530 in some aspects and a509/512 being closer
to a540, but I don't think they were the same family.


As a practical matter, I chose to defer splitting a3xx/a4xx/a5xx into
sub-generations, simply because we didn't have any use for that yet.
For a2xx and a6xx there was a clear immediate use for (most of) it,
and what isn't used falls out of usage of sub-generation
classification we have in mesa, so I have a lot of confidence in the
split.

We can try and map it all out for the other gens now.. or simply just
wait until there is a use for it.  I'm not super against mapping it
out better now, but didn't feel that there was any down side to just
punting on that.  It would be easy enough to do follow-up patches that
refactor the code and split out the subgen enums at the same time.


Sure. I think this can be coupled with split of the gpulist.



BR,
-R



[...]


-priv->is_a2xx = config.rev.core == 2;
+priv->is_a2xx = info->family < ADRENO_3XX;

is this variable even needed now that there are explicit family values?

Konrad

  priv->has_cached_coherent =
  !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT);

diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index 2e62a7ce9f13..75ff7fb46099 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -1079,8 +1079,13 @@ int adreno_gpu_init(struct drm_device *drm, struct 
platform_device *pdev,
  u32 speedbin;
  int ret;

+adreno_gpu->funcs = funcs;
+adreno_gpu->info = adreno_info(config->rev);
+adreno_gpu->rev = *rev;
+
  /* Only handle the core clock when GMU is not in use (or is absent). */
-if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) {
+if (adreno_has_gmu_wrapper(adreno_gpu) ||
+adreno_gpu->info->family < ADRENO_6XX_GEN1) {
  /*
   * This can only be done before devm_pm_opp_of_add_table(), or
   * dev_pm_opp_set_config() will WARN_ON()
@@ -1096,10 +1101,6 @@ int adreno_gpu_init(struct drm_device *drm, struct 
platform_device *pdev,
  devm_pm_opp_set_clkname(dev, "core");
  }

-adreno_gpu->funcs = funcs;
-adreno_gpu->info = adreno_info(config->rev);
-adreno_gpu->rev = *rev;
-
  if (adreno_read_speedbin(dev, ) || !speedbin)
  speedbin = 0x;
  adreno_gpu->speedbin = (uint16_t) (0x & speedbin);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index 6066cfaaea52..2fa14dcd4e40 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -29,6 +29,25 @@ enum {
  ADRENO_FW_MAX,
   };

+/**
+ * @enum adreno_family: identify generation and possibly sub-generation
+ *
+ * In some cases there are distinct sub-generations within a major revision
+ * so it helps to be able to group the GPU devices by generation and if
+ * necessary sub-generation.
+ */
+enum adreno_family {
+ADRENO_2XX_GEN1,  /* a20x */
+ADRENO_2XX_GEN2,  /* a22x */
+ADRENO_3XX,
+ADRENO_4XX,
+ADRENO_5XX,
+ADRENO_6XX_GEN1,  /* a630 family */
+ADRENO_6XX_GEN2,  /* a640 family */
+ADRENO_6XX_GEN3,  /* a650 family */
+ADRENO_6XX_GEN4,  /* a660 family */
+};
+
   #define ADRENO_QUIRK_TWO_PASS_USE_WFI  BIT(0)
   #define ADRENO_QUIRK_FAULT_DETECT_MASK BIT(1)
   #define ADRENO_QUIRK_LMLOADKILL_DISABLEBIT(2)
@@ -63,6 +82,7 @@ extern const struct adreno_reglist a660_hwcg[], a690_hwcg[];
   struct adreno_info {

[PATCH v1 5/5] drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP

2023-07-07 Thread Kuogee Hsieh
Move of_dp_aux_populate_bus() to dp_display_probe() for eDP
from dp_display_bind() so that probe deferral cases can be
handled effectively

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_aux.c | 25 
 drivers/gpu/drm/msm/dp/dp_display.c | 79 +++--
 2 files changed, 65 insertions(+), 39 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index c592064..c1baffb 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -505,6 +505,21 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux)
drm_dp_aux_unregister(dp_aux);
 }
 
+static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,
+unsigned long wait_us)
+{
+   int ret;
+   struct dp_aux_private *aux;
+
+   aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+   pm_runtime_get_sync(aux->dev);
+   ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
+   pm_runtime_put_sync(aux->dev);
+
+   return ret;
+}
+
 struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
  bool is_edp)
 {
@@ -528,6 +543,16 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct 
dp_catalog *catalog,
aux->catalog = catalog;
aux->retry_cnt = 0;
 
+   /*
+* Use the drm_dp_aux_init() to use the aux adapter
+* before registering aux with the DRM device.
+*/
+   aux->dp_aux.name = "dpu_dp_aux";
+   aux->dp_aux.dev = dev;
+   aux->dp_aux.transfer = dp_aux_transfer;
+   aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted;
+   drm_dp_aux_init(>dp_aux);
+
return >dp_aux;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 185f1eb..7ed4bea 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -302,10 +302,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
 
-   pm_runtime_enable(dev);
-   pm_runtime_set_autosuspend_delay(dev, 1000);
-   pm_runtime_use_autosuspend(dev);
-
return 0;
 end:
return rc;
@@ -322,8 +318,6 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
 
kthread_stop(dp->ev_tsk);
 
-   of_dp_aux_depopulate_bus(dp->aux);
-
dp_power_client_deinit(dp->power);
dp_unregister_audio_driver(dev, dp->audio);
dp_aux_unregister(dp->aux);
@@ -1245,6 +1239,29 @@ static const struct msm_dp_desc 
*dp_display_get_desc(struct platform_device *pde
return NULL;
 }
 
+static void of_dp_aux_depopulate_bus_void(void *data)
+{
+   of_dp_aux_depopulate_bus(data);
+}
+
+static int dp_display_auxbus_emulation(struct dp_display_private *dp)
+{
+   struct device *dev = >pdev->dev;
+   struct device_node *aux_bus;
+   int ret = 0;
+
+   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
+
+   if (aux_bus) {
+   ret = devm_of_dp_aux_populate_bus(dp->aux, NULL);
+
+   devm_add_action_or_reset(dev, of_dp_aux_depopulate_bus_void,
+dp->aux);
+   }
+
+   return ret;
+}
+
 static int dp_display_probe(struct platform_device *pdev)
 {
int rc = 0;
@@ -1290,8 +1307,18 @@ static int dp_display_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, >dp_display);
 
+   pm_runtime_enable(>dev);
+   pm_runtime_set_autosuspend_delay(>dev, 1000);
+   pm_runtime_use_autosuspend(>dev);
+
dp_display_request_irq(dp);
 
+   if (dp->dp_display.is_edp) {
+   rc = dp_display_auxbus_emulation(dp);
+   if (rc)
+   DRM_ERROR("eDP aux-bus emulation failed, rc=%d\n", rc);
+   }
+
rc = component_add(>dev, _display_comp_ops);
if (rc) {
DRM_ERROR("component add failed, rc=%d\n", rc);
@@ -1306,11 +1333,14 @@ static int dp_display_remove(struct platform_device 
*pdev)
struct dp_display_private *dp = dev_get_dp_display_private(>dev);
 
component_del(>dev, _display_comp_ops);
-   dp_display_deinit_sub_modules(dp);
-
platform_set_drvdata(pdev, NULL);
+
+   pm_runtime_dont_use_autosuspend(>dev);
+   pm_runtime_disable(>dev);
pm_runtime_put_sync_suspend(>dev);
 
+   dp_display_deinit_sub_modules(dp);
+
return 0;
 }
 
@@ -1514,31 +1544,10 @@ void msm_dp_debugfs_init(struct msm_dp *dp_display, 
struct drm_minor *minor)
 
 static int dp_display_get_next_bridge(struct msm_dp *dp)
 {
-   int rc;
+   int rc = 0;
struct dp_display_private *dp_priv;
-   struct device_node *aux_bus;
-   struct device *dev;
 
dp_priv = container_of(dp, struct dp_display_private, dp_display);
-   dev = _priv->pdev->dev;
-   aux_bus = of_get_child_by_name(dev->of_node, "aux-bus");
-

[PATCH v1 4/5] drm/msm/dp: move relevant dp initialization code from bind() to probe()

2023-07-07 Thread Kuogee Hsieh
In preparation of moving edp of_dp_aux_populate_bus() to
dp_display_probe(), move dp_display_request_irq(),
dp->parser->parse() and dp_power_client_init() to dp_display_probe()
too.

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 48 +
 drivers/gpu/drm/msm/dp/dp_display.h |  1 -
 2 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 44580c2..185f1eb 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -290,12 +290,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
 
-   rc = dp_power_client_init(dp->power);
-   if (rc) {
-   DRM_ERROR("Power client create failed\n");
-   goto end;
-   }
-
rc = dp_register_audio_driver(dev, dp->audio);
if (rc) {
DRM_ERROR("Audio registration Dp failed\n");
@@ -752,6 +746,12 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error;
}
 
+   rc = dp->parser->parse(dp->parser);
+   if (rc) {
+   DRM_ERROR("device tree parsing failed\n");
+   goto error;
+   }
+
dp->catalog = dp_catalog_get(dev, >parser->io);
if (IS_ERR(dp->catalog)) {
rc = PTR_ERR(dp->catalog);
@@ -768,6 +768,12 @@ static int dp_init_sub_modules(struct dp_display_private 
*dp)
goto error;
}
 
+   rc = dp_power_client_init(dp->power);
+   if (rc) {
+   DRM_ERROR("Power client create failed\n");
+   goto error;
+   }
+
dp->aux = dp_aux_get(dev, dp->catalog, dp->dp_display.is_edp);
if (IS_ERR(dp->aux)) {
rc = PTR_ERR(dp->aux);
@@ -1196,26 +1202,20 @@ static irqreturn_t dp_display_irq_handler(int irq, void 
*dev_id)
return ret;
 }
 
-int dp_display_request_irq(struct msm_dp *dp_display)
+static int dp_display_request_irq(struct dp_display_private *dp)
 {
int rc = 0;
-   struct dp_display_private *dp;
-
-   if (!dp_display) {
-   DRM_ERROR("invalid input\n");
-   return -EINVAL;
-   }
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
+   struct device *dev = >pdev->dev;
 
-   dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);
if (!dp->irq) {
-   DRM_ERROR("failed to get irq\n");
-   return -EINVAL;
+   dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);
+   if (!dp->irq) {
+   DRM_ERROR("failed to get irq\n");
+   return -EINVAL;
+   }
}
 
-   rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq,
-   dp_display_irq_handler,
+   rc = devm_request_irq(dev, dp->irq, dp_display_irq_handler,
IRQF_TRIGGER_HIGH, "dp_display_isr", dp);
if (rc < 0) {
DRM_ERROR("failed to request IRQ%u: %d\n",
@@ -1290,6 +1290,8 @@ static int dp_display_probe(struct platform_device *pdev)
 
platform_set_drvdata(pdev, >dp_display);
 
+   dp_display_request_irq(dp);
+
rc = component_add(>dev, _display_comp_ops);
if (rc) {
DRM_ERROR("component add failed, rc=%d\n", rc);
@@ -1574,12 +1576,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, 
struct drm_device *dev,
 
dp_priv = container_of(dp_display, struct dp_display_private, 
dp_display);
 
-   ret = dp_display_request_irq(dp_display);
-   if (ret) {
-   DRM_ERROR("request_irq failed, ret=%d\n", ret);
-   return ret;
-   }
-
ret = dp_display_get_next_bridge(dp_display);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 1e9415a..b3c08de 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -35,7 +35,6 @@ struct msm_dp {
 int dp_display_set_plugged_cb(struct msm_dp *dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev);
 int dp_display_get_modes(struct msm_dp *dp_display);
-int dp_display_request_irq(struct msm_dp *dp_display);
 bool dp_display_check_video_test(struct msm_dp *dp_display);
 int dp_display_get_test_bpp(struct msm_dp *dp_display);
 void dp_display_signal_audio_start(struct msm_dp *dp_display);
-- 
2.7.4



[PATCH v1 3/5] drm/msm/dp: delete EV_HPD_INIT_SETUP

2023-07-07 Thread Kuogee Hsieh
EV_HPD_INIT_SETUP flag is used to trigger the initialization of external
DP host controller. Since external DP host controller initialization had
been incorporated into pm_runtime_resume(), this flag become obsolete.
Lets get rid of it.

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 12 
 1 file changed, 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 2c5706a..44580c2 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -55,7 +55,6 @@ enum {
 enum {
EV_NO_EVENT,
/* hpd events */
-   EV_HPD_INIT_SETUP,
EV_HPD_PLUG_INT,
EV_IRQ_HPD_INT,
EV_HPD_UNPLUG_INT,
@@ -1119,9 +1118,6 @@ static int hpd_event_thread(void *data)
spin_unlock_irqrestore(_priv->event_lock, flag);
 
switch (todo->event_id) {
-   case EV_HPD_INIT_SETUP:
-   dp_display_host_init(dp_priv);
-   break;
case EV_HPD_PLUG_INT:
dp_hpd_plug_handle(dp_priv, todo->data);
break;
@@ -1483,15 +1479,7 @@ void __exit msm_dp_unregister(void)
 
 void msm_dp_irq_postinstall(struct msm_dp *dp_display)
 {
-   struct dp_display_private *dp;
-
-   if (!dp_display)
-   return;
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
 
-   if (!dp_display->is_edp)
-   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0);
 }
 
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
-- 
2.7.4



[PATCH v1 2/5] drm/msm/dp: incorporate pm_runtime framework into DP driver

2023-07-07 Thread Kuogee Hsieh
Incorporating pm runtime framework into DP driver so that power
and clock resource handling can be centralized allowing easier
control of these resources in preparation of registering aux bus
uring probe.

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_aux.c |  3 ++
 drivers/gpu/drm/msm/dp/dp_display.c | 75 +
 2 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 8e3b677..c592064 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -291,6 +291,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
return -EINVAL;
}
 
+   pm_runtime_get_sync(dp_aux->dev);
mutex_lock(>mutex);
if (!aux->initted) {
ret = -EIO;
@@ -364,6 +365,8 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
 
 exit:
mutex_unlock(>mutex);
+   pm_runtime_mark_last_busy(dp_aux->dev);
+   pm_runtime_put_autosuspend(dp_aux->dev);
 
return ret;
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 76f1395..2c5706a 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -309,6 +309,10 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
 
+   pm_runtime_enable(dev);
+   pm_runtime_set_autosuspend_delay(dev, 1000);
+   pm_runtime_use_autosuspend(dev);
+
return 0;
 end:
return rc;
@@ -320,9 +324,8 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct dp_display_private *dp = dev_get_dp_display_private(dev);
struct msm_drm_private *priv = dev_get_drvdata(master);
 
-   /* disable all HPD interrupts */
-   if (dp->core_initialized)
-   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, 
false);
+   pm_runtime_dont_use_autosuspend(dev);
+   pm_runtime_disable(dev);
 
kthread_stop(dp->ev_tsk);
 
@@ -466,10 +469,12 @@ static void dp_display_host_init(struct 
dp_display_private *dp)
dp->dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
 
-   dp_power_init(dp->power);
-   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
-   dp_aux_init(dp->aux);
-   dp->core_initialized = true;
+   if (!dp->core_initialized) {
+   dp_power_init(dp->power);
+   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
+   dp_aux_init(dp->aux);
+   dp->core_initialized = true;
+   }
 }
 
 static void dp_display_host_deinit(struct dp_display_private *dp)
@@ -478,10 +483,12 @@ static void dp_display_host_deinit(struct 
dp_display_private *dp)
dp->dp_display.connector_type, dp->core_initialized,
dp->phy_initialized);
 
-   dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
-   dp_aux_deinit(dp->aux);
-   dp_power_deinit(dp->power);
-   dp->core_initialized = false;
+   if (dp->core_initialized) {
+   dp_ctrl_reset_irq_ctrl(dp->ctrl, false);
+   dp_aux_deinit(dp->aux);
+   dp_power_deinit(dp->power);
+   dp->core_initialized = false;
+   }
 }
 
 static int dp_display_usbpd_configure_cb(struct device *dev)
@@ -1304,6 +1311,39 @@ static int dp_display_remove(struct platform_device 
*pdev)
dp_display_deinit_sub_modules(dp);
 
platform_set_drvdata(pdev, NULL);
+   pm_runtime_put_sync_suspend(>dev);
+
+   return 0;
+}
+
+static int dp_pm_runtime_suspend(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dp *dp_display = platform_get_drvdata(pdev);
+   struct dp_display_private *dp;
+
+   dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+   dp_display_host_phy_exit(dp);
+   dp_catalog_ctrl_hpd_enable(dp->catalog);
+   dp_display_host_deinit(dp);
+
+   return 0;
+}
+
+static int dp_pm_runtime_resume(struct device *dev)
+{
+   struct platform_device *pdev = to_platform_device(dev);
+   struct msm_dp *dp_display = platform_get_drvdata(pdev);
+   struct dp_display_private *dp;
+
+   dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+   dp_display_host_init(dp);
+   if (dp_display->is_edp) {
+   dp_catalog_ctrl_hpd_enable(dp->catalog);
+   dp_display_host_phy_init(dp);
+   }
 
return 0;
 }
@@ -1409,6 +1449,7 @@ static int dp_pm_suspend(struct device *dev)
 }
 
 static const struct dev_pm_ops dp_pm_ops = {
+   SET_RUNTIME_PM_OPS(dp_pm_runtime_suspend, dp_pm_runtime_resume, NULL)
.suspend = dp_pm_suspend,
.resume =  dp_pm_resume,
 };
@@ -1493,10 +1534,6 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
aux_bus = 

[PATCH v1 1/5] drm/msm/dp: remove pm_runtime_xxx() from dp_power.c

2023-07-07 Thread Kuogee Hsieh
Since both pm_runtime_resume() and pm_runtime_suspend() are not
populated at dp_pm_ops. Those pm_runtime_get/put() functions within
dp_power.c will not have any effects in addition to increase/decrease
power counter. Also pm_runtime_xxx() should be executed at top
layer.

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_power.c | 9 -
 1 file changed, 9 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_power.c 
b/drivers/gpu/drm/msm/dp/dp_power.c
index 5cb84ca..ed2f62a 100644
--- a/drivers/gpu/drm/msm/dp/dp_power.c
+++ b/drivers/gpu/drm/msm/dp/dp_power.c
@@ -152,8 +152,6 @@ int dp_power_client_init(struct dp_power *dp_power)
 
power = container_of(dp_power, struct dp_power_private, dp_power);
 
-   pm_runtime_enable(power->dev);
-
return dp_power_clk_init(power);
 }
 
@@ -162,8 +160,6 @@ void dp_power_client_deinit(struct dp_power *dp_power)
struct dp_power_private *power;
 
power = container_of(dp_power, struct dp_power_private, dp_power);
-
-   pm_runtime_disable(power->dev);
 }
 
 int dp_power_init(struct dp_power *dp_power)
@@ -173,11 +169,7 @@ int dp_power_init(struct dp_power *dp_power)
 
power = container_of(dp_power, struct dp_power_private, dp_power);
 
-   pm_runtime_get_sync(power->dev);
-
rc = dp_power_clk_enable(dp_power, DP_CORE_PM, true);
-   if (rc)
-   pm_runtime_put_sync(power->dev);
 
return rc;
 }
@@ -189,7 +181,6 @@ int dp_power_deinit(struct dp_power *dp_power)
power = container_of(dp_power, struct dp_power_private, dp_power);
 
dp_power_clk_enable(dp_power, DP_CORE_PM, false);
-   pm_runtime_put_sync(power->dev);
return 0;
 }
 
-- 
2.7.4



Re: [PATCH 09/12] drm/msm/adreno: Add adreno family

2023-07-07 Thread Rob Clark
On Thu, Jul 6, 2023 at 8:16 PM Dmitry Baryshkov
 wrote:
>
> On 07/07/2023 02:35, Konrad Dybcio wrote:
> > On 6.07.2023 23:10, Rob Clark wrote:
> >> From: Rob Clark 
> >>
> >> Sometimes it is useful to know the sub-generation (or "family").  And in
> >> any case, this helps us get away from infering the generation from the
> >> numerical chip-id.
> >>
> >> Signed-off-by: Rob Clark 
> >> ---
> > [...]
> >
> >>  .rev   = ADRENO_REV(5, 0, 8, ANY_ID),
> >> +.family = ADRENO_5XX,
> >>  .revn = 508,
> > 508 is from 530 fam
> >
> >>  .fw = {
> >>  [ADRENO_FW_PM4] = "a530_pm4.fw",
> >> @@ -156,6 +168,7 @@ static const struct adreno_info gpulist[] = {
> >>  .zapfw = "a508_zap.mdt",
> >>  }, {
> >>  .rev   = ADRENO_REV(5, 0, 9, ANY_ID),
> >> +.family = ADRENO_5XX,
> >>  .revn = 509,
> > 509 and 512 are from 540 fam
> >
> >>  .fw = {
> >>  [ADRENO_FW_PM4] = "a530_pm4.fw",
> >> @@ -173,6 +186,7 @@ static const struct adreno_info gpulist[] = {
> >>  .zapfw = "a512_zap.mdt",
> >>  }, {
> >>  .rev   = ADRENO_REV(5, 1, 0, ANY_ID),
> >> +.family = ADRENO_5XX,
> >>  .revn = 510,
> > 510 is 530ish but I think it's closer to 505 or whatever the
> > 8953 gpu was called
>
> I'd say, there were following generations here:
>
> - a505 / a506 / a508
> - a509 / a512
> - a510
> - a530
> - a540
>
> Indeed a50x were close to a530 in some aspects and a509/512 being closer
> to a540, but I don't think they were the same family.

As a practical matter, I chose to defer splitting a3xx/a4xx/a5xx into
sub-generations, simply because we didn't have any use for that yet.
For a2xx and a6xx there was a clear immediate use for (most of) it,
and what isn't used falls out of usage of sub-generation
classification we have in mesa, so I have a lot of confidence in the
split.

We can try and map it all out for the other gens now.. or simply just
wait until there is a use for it.  I'm not super against mapping it
out better now, but didn't feel that there was any down side to just
punting on that.  It would be easy enough to do follow-up patches that
refactor the code and split out the subgen enums at the same time.

BR,
-R

> >
> > [...]
> >
> >> -priv->is_a2xx = config.rev.core == 2;
> >> +priv->is_a2xx = info->family < ADRENO_3XX;
> > is this variable even needed now that there are explicit family values?
> >
> > Konrad
> >>  priv->has_cached_coherent =
> >>  !!(info->quirks & ADRENO_QUIRK_HAS_CACHED_COHERENT);
> >>
> >> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> >> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >> index 2e62a7ce9f13..75ff7fb46099 100644
> >> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> >> @@ -1079,8 +1079,13 @@ int adreno_gpu_init(struct drm_device *drm, struct 
> >> platform_device *pdev,
> >>  u32 speedbin;
> >>  int ret;
> >>
> >> +adreno_gpu->funcs = funcs;
> >> +adreno_gpu->info = adreno_info(config->rev);
> >> +adreno_gpu->rev = *rev;
> >> +
> >>  /* Only handle the core clock when GMU is not in use (or is absent). 
> >> */
> >> -if (adreno_has_gmu_wrapper(adreno_gpu) || config->rev.core < 6) {
> >> +if (adreno_has_gmu_wrapper(adreno_gpu) ||
> >> +adreno_gpu->info->family < ADRENO_6XX_GEN1) {
> >>  /*
> >>   * This can only be done before devm_pm_opp_of_add_table(), or
> >>   * dev_pm_opp_set_config() will WARN_ON()
> >> @@ -1096,10 +1101,6 @@ int adreno_gpu_init(struct drm_device *drm, struct 
> >> platform_device *pdev,
> >>  devm_pm_opp_set_clkname(dev, "core");
> >>  }
> >>
> >> -adreno_gpu->funcs = funcs;
> >> -adreno_gpu->info = adreno_info(config->rev);
> >> -adreno_gpu->rev = *rev;
> >> -
> >>  if (adreno_read_speedbin(dev, ) || !speedbin)
> >>  speedbin = 0x;
> >>  adreno_gpu->speedbin = (uint16_t) (0x & speedbin);
> >> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h 
> >> b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> >> index 6066cfaaea52..2fa14dcd4e40 100644
> >> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> >> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
> >> @@ -29,6 +29,25 @@ enum {
> >>  ADRENO_FW_MAX,
> >>   };
> >>
> >> +/**
> >> + * @enum adreno_family: identify generation and possibly sub-generation
> >> + *
> >> + * In some cases there are distinct sub-generations within a major 
> >> revision
> >> + * so it helps to be able to group the GPU devices by generation and if
> >> + * necessary sub-generation.
> >> + */
> >> +enum adreno_family {
> >> +ADRENO_2XX_GEN1,  /* a20x */
> >> +ADRENO_2XX_GEN2,  /* a22x */
> >> +ADRENO_3XX,
> >> +ADRENO_4XX,
> >> +ADRENO_5XX,
> >> +ADRENO_6XX_GEN1,  /* a630 family */
> >> +ADRENO_6XX_GEN2,  /* a640 family */

[PATCH v1 0/5] incorporate pm runtime framework and eDP clean up

2023-07-07 Thread Kuogee Hsieh
Incorporate pm runtime framework into DP driver and clean up eDP
by moving of_dp_aux_populate_bus() to probe()

Kuogee Hsieh (5):
  drm/msm/dp: remove pm_runtime_xxx() from dp_power.c
  drm/msm/dp: incorporate pm_runtime framework into DP driver
  drm/msm/dp: delete EV_HPD_INIT_SETUP
  drm/msm/dp: move relevant dp initialization code from bind() to
probe()
  drm/msm/dp: move of_dp_aux_populate_bus() to probe for eDP

 drivers/gpu/drm/msm/dp/dp_aux.c |  28 +
 drivers/gpu/drm/msm/dp/dp_display.c | 204 +---
 drivers/gpu/drm/msm/dp/dp_display.h |   1 -
 drivers/gpu/drm/msm/dp/dp_power.c   |   9 --
 4 files changed, 145 insertions(+), 97 deletions(-)

-- 
2.7.4



Re: [PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path

2023-07-07 Thread Dmitry Baryshkov

On 08/07/2023 02:25, Konrad Dybcio wrote:

On 7.07.2023 22:37, Dmitry Baryshkov wrote:

It was noticed that dpu_kms_hw_init()'s error path contains several
labels which point to the same code path. Replace all of them with a
single label.

Suggested-by: Konrad Dybcio 

it's the first time I'm seeing this code



It is Suggested-by, not something else. And you pointed it out in 
https://lore.kernel.org/linux-arm-msm/6d598438-f10f-8678-7878-829b8b3ae...@linaro.org/



Konrad

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 +
  1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c11b3ab572ab..e7ac02e92f42 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (!dpu_kms->catalog) {
DPU_ERROR("device config not known!\n");
rc = -EINVAL;
-   goto power_error;
+   goto err_pm_put;
}
  
  	/*

@@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_mmu_init(dpu_kms);
if (rc) {
DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
  
  	rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio);

if (rc) {
DPU_ERROR("rm init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
  
  	dpu_kms->rm_init = true;

@@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_mdp);
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
dpu_kms->hw_mdp = NULL;
-   goto power_error;
+   goto err_pm_put;
}
  
  	for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {

@@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
-   goto power_error;
+   goto err_pm_put;
}
  
  		dpu_kms->hw_vbif[vbif->id] = hw;

@@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, 
max_core_clk_rate);
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
-   goto perf_err;
+   goto err_pm_put;
}
  
  	dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);

@@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
dpu_kms->hw_intr = NULL;
-   goto hw_intr_init_err;
+   goto err_pm_put;
}
  
  	dev->mode_config.min_width = 0;

@@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_drm_obj_init(dpu_kms);
if (rc) {
DPU_ERROR("modeset init failed: %d\n", rc);
-   goto drm_obj_init_err;
+   goto err_pm_put;
}
  
  	dpu_vbif_init_memtypes(dpu_kms);

@@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
  
  	return 0;
  
-drm_obj_init_err:

-hw_intr_init_err:
-perf_err:
-power_error:
+err_pm_put:
pm_runtime_put_sync(_kms->pdev->dev);
  error:
_dpu_kms_hw_destroy(dpu_kms);


--
With best wishes
Dmitry



Re: [PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path

2023-07-07 Thread Konrad Dybcio
On 7.07.2023 22:37, Dmitry Baryshkov wrote:
> It was noticed that dpu_kms_hw_init()'s error path contains several
> labels which point to the same code path. Replace all of them with a
> single label.
> 
> Suggested-by: Konrad Dybcio 
it's the first time I'm seeing this code

Konrad
> Signed-off-by: Dmitry Baryshkov 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 +
>  1 file changed, 9 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> index c11b3ab572ab..e7ac02e92f42 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> @@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   if (!dpu_kms->catalog) {
>   DPU_ERROR("device config not known!\n");
>   rc = -EINVAL;
> - goto power_error;
> + goto err_pm_put;
>   }
>  
>   /*
> @@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   rc = _dpu_kms_mmu_init(dpu_kms);
>   if (rc) {
>   DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc);
> - goto power_error;
> + goto err_pm_put;
>   }
>  
>   rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio);
>   if (rc) {
>   DPU_ERROR("rm init failed: %d\n", rc);
> - goto power_error;
> + goto err_pm_put;
>   }
>  
>   dpu_kms->rm_init = true;
> @@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   rc = PTR_ERR(dpu_kms->hw_mdp);
>   DPU_ERROR("failed to get hw_mdp: %d\n", rc);
>   dpu_kms->hw_mdp = NULL;
> - goto power_error;
> + goto err_pm_put;
>   }
>  
>   for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
> @@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   if (IS_ERR(hw)) {
>   rc = PTR_ERR(hw);
>   DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
> - goto power_error;
> + goto err_pm_put;
>   }
>  
>   dpu_kms->hw_vbif[vbif->id] = hw;
> @@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, 
> max_core_clk_rate);
>   if (rc) {
>   DPU_ERROR("failed to init perf %d\n", rc);
> - goto perf_err;
> + goto err_pm_put;
>   }
>  
>   dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
> @@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   rc = PTR_ERR(dpu_kms->hw_intr);
>   DPU_ERROR("hw_intr init failed: %d\n", rc);
>   dpu_kms->hw_intr = NULL;
> - goto hw_intr_init_err;
> + goto err_pm_put;
>   }
>  
>   dev->mode_config.min_width = 0;
> @@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>   rc = _dpu_kms_drm_obj_init(dpu_kms);
>   if (rc) {
>   DPU_ERROR("modeset init failed: %d\n", rc);
> - goto drm_obj_init_err;
> + goto err_pm_put;
>   }
>  
>   dpu_vbif_init_memtypes(dpu_kms);
> @@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
>  
>   return 0;
>  
> -drm_obj_init_err:
> -hw_intr_init_err:
> -perf_err:
> -power_error:
> +err_pm_put:
>   pm_runtime_put_sync(_kms->pdev->dev);
>  error:
>   _dpu_kms_hw_destroy(dpu_kms);


[PATCH v2 06/13] drm/msm/dpu: use devres-managed allocation for HW blocks

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create HW block structure. This allows us to remove
corresponding kfree and drop all dpu_hw_*_destroy() functions as well as
dpu_rm_destroy(), which becomes empty afterwards.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c|  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c   | 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 13 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h   |  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |  1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +--
 23 files changed, 119 insertions(+), 238 deletions(-)

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 c278fb9d2b5b..d22e3f11ae34 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -4,6 +4,9 @@
  */
 
 #include 
+
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_kms.h"
@@ -674,14 +677,15 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
 };
 
-struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
-   void __iomem *addr,
-   u32 mixer_count,
-   const struct dpu_lm_cfg *mixer)
+struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
+  const struct dpu_ctl_cfg *cfg,
+  void __iomem *addr,
+  u32 mixer_count,
+  const struct dpu_lm_cfg *mixer)
 {
struct dpu_hw_ctl *c;
 
-   c = kzalloc(sizeof(*c), GFP_KERNEL);
+   c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
 
@@ -696,8 +700,3 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg 
*cfg,
 
return c;
 }
-
-void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx)
-{
-   kfree(ctx);
-}
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 1c242298ff2e..279ebd8dfbff 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -274,20 +274,16 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct 
dpu_hw_blk *hw)
 /**
  * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
  * Should be called before accessing any ctl_path register.
+ * @dev:  Corresponding device for devres management
  * @cfg:  ctl_path catalog entry for which driver object is required
  * @addr: mapped register io address of MDP
  * @mixer_count: Number of mixers in @mixer
  * @mixer: Pointer to an array of Layer Mixers defined in the catalog
  */
-struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
-   void __iomem *addr,
-   u32 mixer_count,
-   const struct dpu_lm_cfg *mixer);
-
-/**
- * dpu_hw_ctl_destroy(): Destroys ctl driver context
- * should be called to free the context
- */
-void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx);
+struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
+  const struct dpu_ctl_cfg *cfg,
+  void __iomem *addr,
+  u32 mixer_count,
+  const struct dpu_lm_cfg *mixer);
 
 #endif /*_DPU_HW_CTL_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
index 509dbaa51d87..5e9aad1b2aa2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2020-2022, Linaro Limited
  */
 
+#include 
+
 #include 
 
 #include "dpu_kms.h"
@@ -188,12 +190,13 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk;
 };
 
-struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg,
+struct 

[PATCH v2 13/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt

2023-07-07 Thread Dmitry Baryshkov
It is incorrect to use devm-managed memory allocations for DRM data
structures exposed to userspace. They should use drmm_ allocations.
Change struct dpu_encoder allocation to use drmm_encoder_alloc(). This
removes the need to perform any actions on encoder destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 50 +
 1 file changed, 10 insertions(+), 40 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index b42176ce4a3a..65c6c863f7c6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -443,23 +443,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc)
return linecount;
 }
 
-static void dpu_encoder_destroy(struct drm_encoder *drm_enc)
-{
-   struct dpu_encoder_virt *dpu_enc = NULL;
-   int i = 0;
-
-   if (!drm_enc) {
-   DPU_ERROR("invalid encoder\n");
-   return;
-   }
-
-   dpu_enc = to_dpu_encoder_virt(drm_enc);
-   DPU_DEBUG_ENC(dpu_enc, "\n");
-
-   drm_encoder_cleanup(drm_enc);
-   mutex_destroy(_enc->enc_lock);
-}
-
 void dpu_encoder_helper_split_config(
struct dpu_encoder_phys *phys_enc,
enum dpu_intf interface)
@@ -2365,7 +2348,6 @@ static const struct drm_encoder_helper_funcs 
dpu_encoder_helper_funcs = {
 };
 
 static const struct drm_encoder_funcs dpu_encoder_funcs = {
-   .destroy = dpu_encoder_destroy,
.late_register = dpu_encoder_late_register,
.early_unregister = dpu_encoder_early_unregister,
 };
@@ -2376,20 +2358,13 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
 {
struct msm_drm_private *priv = dev->dev_private;
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
-   struct drm_encoder *drm_enc = NULL;
-   struct dpu_encoder_virt *dpu_enc = NULL;
-   int ret = 0;
+   struct dpu_encoder_virt *dpu_enc;
+   int ret;
 
-   dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
-   if (!dpu_enc)
-   return ERR_PTR(-ENOMEM);
-
-   ret = drm_encoder_init(dev, _enc->base, _encoder_funcs,
-  drm_enc_mode, NULL);
-   if (ret) {
-   devm_kfree(dev->dev, dpu_enc);
-   return ERR_PTR(ret);
-   }
+   dpu_enc = drmm_encoder_alloc(dev, struct dpu_encoder_virt, base,
+_encoder_funcs, drm_enc_mode, NULL);
+   if (IS_ERR(dpu_enc))
+   return ERR_CAST(dpu_enc);
 
drm_encoder_helper_add(_enc->base, _encoder_helper_funcs);
 
@@ -2399,8 +2374,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
mutex_init(_enc->rc_lock);
 
ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
-   if (ret)
-   goto fail;
+   if (ret) {
+   DPU_ERROR("failed to setup encoder\n");
+   return ERR_PTR(-ENOMEM);
+   }
 
atomic_set(_enc->frame_done_timeout_ms, 0);
timer_setup(_enc->frame_done_timer,
@@ -2426,13 +2403,6 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
DPU_DEBUG_ENC(dpu_enc, "created\n");
 
return _enc->base;
-
-fail:
-   DPU_ERROR("failed to create encoder\n");
-   if (drm_enc)
-   dpu_encoder_destroy(drm_enc);
-
-   return ERR_PTR(ret);
 }
 
 int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc,
-- 
2.39.2



[PATCH v2 04/13] drm/msm/dpu: use devres-managed allocation for VBIF data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create VBIF data structure. This allows us to
remove corresponding kfree and drop dpu_hw_intr_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h |  8 
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 11 +++
 3 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
index a5121a50b2bb..98e34afde2d2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
@@ -2,6 +2,8 @@
 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_catalog.h"
 #include "dpu_hw_vbif.h"
@@ -211,12 +213,13 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
ops->set_write_gather_en = dpu_hw_set_write_gather_en;
 }
 
-struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
-   void __iomem *addr)
+struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
+const struct dpu_vbif_cfg *cfg,
+void __iomem *addr)
 {
struct dpu_hw_vbif *c;
 
-   c = kzalloc(sizeof(*c), GFP_KERNEL);
+   c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
 
@@ -234,8 +237,3 @@ struct dpu_hw_vbif *dpu_hw_vbif_init(const struct 
dpu_vbif_cfg *cfg,
 
return c;
 }
-
-void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif)
-{
-   kfree(vbif);
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 7e10d2a172b4..e2b4307500e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -108,12 +108,12 @@ struct dpu_hw_vbif {
 /**
  * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed
  * VBIF catalog entry.
+ * @dev:  Corresponding device for devres management
  * @cfg:  VBIF catalog entry for which driver object is required
  * @addr: Mapped register io address of MDSS
  */
-struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
-   void __iomem *addr);
-
-void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif);
+struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
+const struct dpu_vbif_cfg *cfg,
+void __iomem *addr);
 
 #endif /*_DPU_HW_VBIF_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index ef232dc838c7..f7723f89cbbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -812,13 +812,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
/* safe to call these more than once during shutdown */
_dpu_kms_mmu_destroy(dpu_kms);
 
-   if (dpu_kms->catalog) {
-   for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
-   if (dpu_kms->hw_vbif[i]) {
-   dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]);
-   dpu_kms->hw_vbif[i] = NULL;
-   }
-   }
+   for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
+   dpu_kms->hw_vbif[i] = NULL;
}
 
if (dpu_kms->rm_init)
@@ -1070,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
struct dpu_hw_vbif *hw;
const struct dpu_vbif_cfg *vbif = _kms->catalog->vbif[i];
 
-   hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]);
+   hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif[vbif->id]);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
-- 
2.39.2



[PATCH v2 08/13] drm/msm/dpu: remove QoS teardown on plane destruction

2023-07-07 Thread Dmitry Baryshkov
There is little point in disabling QoS on plane destruction: it happens
during DPU device destruction process, after which there will be no
running planes.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index aba5185e1d66..f114efee1b57 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1173,17 +1173,10 @@ static void dpu_plane_atomic_update(struct drm_plane 
*plane,
 static void dpu_plane_destroy(struct drm_plane *plane)
 {
struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
-   struct dpu_plane_state *pstate;
 
DPU_DEBUG_PLANE(pdpu, "\n");
 
if (pdpu) {
-   pstate = to_dpu_plane_state(plane->state);
-   _dpu_plane_set_qos_ctrl(plane, >pipe, false);
-
-   if (pstate->r_pipe.sspp)
-   _dpu_plane_set_qos_ctrl(plane, >r_pipe, false);
-
/* this will destroy the states as well */
drm_plane_cleanup(plane);
 
-- 
2.39.2



[PATCH v2 10/13] drm/msm/dpu: use drmm-managed allocation for dpu_crtc

2023-07-07 Thread Dmitry Baryshkov
Change struct dpu_crtc allocation to use drmm_crtc_alloc_with_planes().
This removes the need to perform any actions on CRTC destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 25 +++-
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 214229d11e3e..a1fcb690c687 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -51,17 +51,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc 
*crtc)
return to_dpu_kms(priv->kms);
 }
 
-static void dpu_crtc_destroy(struct drm_crtc *crtc)
-{
-   struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
-
-   if (!crtc)
-   return;
-
-   drm_crtc_cleanup(crtc);
-   kfree(dpu_crtc);
-}
-
 static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -1433,7 +1422,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc)
 
 static const struct drm_crtc_funcs dpu_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = dpu_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = dpu_crtc_reset,
.atomic_duplicate_state = dpu_crtc_duplicate_state,
@@ -1467,9 +1455,13 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
struct dpu_crtc *dpu_crtc = NULL;
int i, ret;
 
-   dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
-   if (!dpu_crtc)
-   return ERR_PTR(-ENOMEM);
+   dpu_crtc = drmm_crtc_alloc_with_planes(dev, struct dpu_crtc, base,
+  plane, cursor,
+  _crtc_funcs,
+  NULL);
+
+   if (IS_ERR(dpu_crtc))
+   return ERR_CAST(dpu_crtc);
 
crtc = _crtc->base;
crtc->dev = dev;
@@ -1489,9 +1481,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
dpu_crtc_frame_event_work);
}
 
-   drm_crtc_init_with_planes(dev, crtc, plane, cursor, _crtc_funcs,
-   NULL);
-
drm_crtc_helper_add(crtc, _crtc_helper_funcs);
 
if (dpu_kms->catalog->dspp_count)
-- 
2.39.2



[PATCH v2 12/13] drm/msm/dpu: drop dpu_encoder_phys_ops::destroy

2023-07-07 Thread Dmitry Baryshkov
Drop the dpu_encoder_phys_ops' destroy() callback. No phys backend
implements it anymore, so it is useless.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 18 --
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  2 --
 2 files changed, 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 7c2cd9ce8acd..b42176ce4a3a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -456,24 +456,6 @@ static void dpu_encoder_destroy(struct drm_encoder 
*drm_enc)
dpu_enc = to_dpu_encoder_virt(drm_enc);
DPU_DEBUG_ENC(dpu_enc, "\n");
 
-   mutex_lock(_enc->enc_lock);
-
-   for (i = 0; i < dpu_enc->num_phys_encs; i++) {
-   struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
-   if (phys->ops.destroy) {
-   phys->ops.destroy(phys);
-   --dpu_enc->num_phys_encs;
-   dpu_enc->phys_encs[i] = NULL;
-   }
-   }
-
-   if (dpu_enc->num_phys_encs)
-   DPU_ERROR_ENC(dpu_enc, "expected 0 num_phys_encs not %d\n",
-   dpu_enc->num_phys_encs);
-   dpu_enc->num_phys_encs = 0;
-   mutex_unlock(_enc->enc_lock);
-
drm_encoder_cleanup(drm_enc);
mutex_destroy(_enc->enc_lock);
 }
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 4fb0d95f3061..757ce58f958b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -72,7 +72,6 @@ struct dpu_encoder_phys;
  * @enable:DRM Call. Enable a DRM mode.
  * @disable:   DRM Call. Disable mode.
  * @atomic_check:  DRM Call. Atomic check new DRM state.
- * @destroy:   DRM Call. Destroy and release resources.
  * @control_vblank_irq Register/Deregister for VBLANK IRQ
  * @wait_for_commit_done:  Wait for hardware to have flushed the
  * current pending frames to hardware
@@ -102,7 +101,6 @@ struct dpu_encoder_phys_ops {
int (*atomic_check)(struct dpu_encoder_phys *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-   void (*destroy)(struct dpu_encoder_phys *encoder);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc);
-- 
2.39.2



[PATCH v2 11/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys

2023-07-07 Thread Dmitry Baryshkov
Change struct allocation of encoder's phys backend data to use
drmm_kzalloc(). This removes the need to perform any actions on encoder
destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  9 
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  8 ---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  | 15 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 13 
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 21 ---
 5 files changed, 22 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 493905a5b63a..7c2cd9ce8acd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2199,6 +2199,7 @@ static void dpu_encoder_early_unregister(struct 
drm_encoder *encoder)
 }
 
 static int dpu_encoder_virt_add_phys_encs(
+   struct drm_device *dev,
struct msm_display_info *disp_info,
struct dpu_encoder_virt *dpu_enc,
struct dpu_enc_phys_init_params *params)
@@ -2220,7 +2221,7 @@ static int dpu_encoder_virt_add_phys_encs(
 
 
if (disp_info->intf_type == INTF_WB) {
-   enc = dpu_encoder_phys_wb_init(params);
+   enc = dpu_encoder_phys_wb_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n",
@@ -2231,7 +2232,7 @@ static int dpu_encoder_virt_add_phys_encs(
dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
++dpu_enc->num_phys_encs;
} else if (disp_info->is_cmd_mode) {
-   enc = dpu_encoder_phys_cmd_init(params);
+   enc = dpu_encoder_phys_cmd_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n",
@@ -2242,7 +2243,7 @@ static int dpu_encoder_virt_add_phys_encs(
dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
++dpu_enc->num_phys_encs;
} else {
-   enc = dpu_encoder_phys_vid_init(params);
+   enc = dpu_encoder_phys_vid_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n",
@@ -2333,7 +2334,7 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
break;
}
 
-   ret = dpu_encoder_virt_add_phys_encs(disp_info,
+   ret = dpu_encoder_virt_add_phys_encs(dpu_kms->dev, disp_info,
dpu_enc, _params);
if (ret) {
DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n");
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 d48558ede488..4fb0d95f3061 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -281,22 +281,24 @@ struct dpu_encoder_wait_info {
  * @p: Pointer to init params structure
  * Return: Error code or newly allocated encoder
  */
-struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
+struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
  * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder
+ * @dev:  Corresponding device for devres management
  * @p: Pointer to init params structure
  * Return: Error code or newly allocated encoder
  */
-struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
+struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
  * dpu_encoder_phys_wb_init - initialize writeback encoder
+ * @dev:  Corresponding device for devres management
  * @init:  Pointer to init info structure with initialization params
  */
-struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
+struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b856c6286c85..2958b64e6e5e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -13,6 +13,8 @@
 #include "dpu_trace.h"
 #include "disp/msm_disp_snapshot.h"
 
+#include 
+
 #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
(e) && (e)->base.parent ? \
(e)->base.parent->base.id : -1, \
@@ -563,14 +565,6 @@ static void dpu_encoder_phys_cmd_disable(struct 
dpu_encoder_phys *phys_enc)
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc)
-{
-  

[PATCH v2 09/13] drm/msm/dpu: use drmm-managed allocation for dpu_plane

2023-07-07 Thread Dmitry Baryshkov
Change struct dpu_plane allocation to use drmm_universal_plane_alloc().
This removes the need to perform any actions on plane destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 46 +--
 1 file changed, 10 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index f114efee1b57..9d9e1cbf0dd7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1170,20 +1170,6 @@ static void dpu_plane_atomic_update(struct drm_plane 
*plane,
}
 }
 
-static void dpu_plane_destroy(struct drm_plane *plane)
-{
-   struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
-
-   DPU_DEBUG_PLANE(pdpu, "\n");
-
-   if (pdpu) {
-   /* this will destroy the states as well */
-   drm_plane_cleanup(plane);
-
-   kfree(pdpu);
-   }
-}
-
 static void dpu_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
 {
@@ -1353,7 +1339,6 @@ static bool dpu_plane_format_mod_supported(struct 
drm_plane *plane,
 static const struct drm_plane_funcs dpu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
-   .destroy = dpu_plane_destroy,
.reset = dpu_plane_reset,
.atomic_duplicate_state = dpu_plane_duplicate_state,
.atomic_destroy_state = dpu_plane_destroy_state,
@@ -1381,35 +1366,28 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
struct dpu_hw_sspp *pipe_hw;
uint32_t num_formats;
uint32_t supported_rotations;
-   int ret = -EINVAL;
-
-   /* create and zero local structure */
-   pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL);
-   if (!pdpu) {
-   DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe);
-   ret = -ENOMEM;
-   return ERR_PTR(ret);
-   }
-
-   /* cache local stuff for later */
-   plane = >base;
-   pdpu->pipe = pipe;
+   int ret;
 
/* initialize underlying h/w driver */
pipe_hw = dpu_rm_get_sspp(>rm, pipe);
if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
DPU_ERROR("[%u]SSPP is invalid\n", pipe);
-   goto clean_plane;
+   return ERR_PTR(-EINVAL);
}
 
format_list = pipe_hw->cap->sblk->format_list;
num_formats = pipe_hw->cap->sblk->num_formats;
 
-   ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs,
+   pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base,
+   0xff, _plane_funcs,
format_list, num_formats,
supported_format_modifiers, type, NULL);
-   if (ret)
-   goto clean_plane;
+   if (IS_ERR(pdpu))
+   return ERR_CAST(pdpu);
+
+   /* cache local stuff for later */
+   plane = >base;
+   pdpu->pipe = pipe;
 
pdpu->catalog = kms->catalog;
 
@@ -1439,8 +1417,4 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
pipe, plane->base.id);
return plane;
-
-clean_plane:
-   kfree(pdpu);
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH v2 07/13] drm/msm/dpu: drop unused dpu_plane::lock

2023-07-07 Thread Dmitry Baryshkov
The field dpu_plane::lock was never used for protecting any kind of
data. Drop it now.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index c2aaaded07ed..aba5185e1d66 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -78,8 +78,6 @@ static const uint32_t qcom_compressed_supported_formats[] = {
 struct dpu_plane {
struct drm_plane base;
 
-   struct mutex lock;
-
enum dpu_sspp pipe;
 
uint32_t color_fill;
@@ -1186,8 +1184,6 @@ static void dpu_plane_destroy(struct drm_plane *plane)
if (pstate->r_pipe.sspp)
_dpu_plane_set_qos_ctrl(plane, >r_pipe, false);
 
-   mutex_destroy(>lock);
-
/* this will destroy the states as well */
drm_plane_cleanup(plane);
 
@@ -1447,8 +1443,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
/* success! finalize initialization */
drm_plane_helper_add(plane, _plane_helper_funcs);
 
-   mutex_init(>lock);
-
DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
pipe, plane->base.id);
return plane;
-- 
2.39.2



[PATCH v2 05/13] drm/msm/dpu: use devres-managed allocation for MDP TOP

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create MDP TOP structure. This allows us to remove
corresponding kfree and drop dpu_hw_mdp_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 17 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h |  8 +---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|  5 ++---
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index cff48763ce25..481b373d9ccb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -2,6 +2,8 @@
 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_catalog.h"
 #include "dpu_hw_top.h"
@@ -268,16 +270,17 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->intf_audio_select = dpu_hw_intf_audio_select;
 }
 
-struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg,
-   void __iomem *addr,
-   const struct dpu_mdss_cfg *m)
+struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
+ const struct dpu_mdp_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_cfg *m)
 {
struct dpu_hw_mdp *mdp;
 
if (!addr)
return ERR_PTR(-EINVAL);
 
-   mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
+   mdp = drmm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL);
if (!mdp)
return ERR_PTR(-ENOMEM);
 
@@ -292,9 +295,3 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct 
dpu_mdp_cfg *cfg,
 
return mdp;
 }
-
-void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp)
-{
-   kfree(mdp);
-}
-
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 8b1463d2b2f0..6f3dc98087df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -145,13 +145,15 @@ struct dpu_hw_mdp {
 
 /**
  * dpu_hw_mdptop_init - initializes the top driver for the passed config
+ * @dev:  Corresponding device for devres management
  * @cfg:  MDP TOP configuration from catalog
  * @addr: Mapped register io address of MDP
  * @m:Pointer to mdss catalog data
  */
-struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg,
-   void __iomem *addr,
-   const struct dpu_mdss_cfg *m);
+struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
+ const struct dpu_mdp_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_cfg *m);
 
 void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index f7723f89cbbc..48c3f8b6b88f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -822,8 +822,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 
dpu_kms->catalog = NULL;
 
-   if (dpu_kms->hw_mdp)
-   dpu_hw_mdp_destroy(dpu_kms->hw_mdp);
dpu_kms->hw_mdp = NULL;
 }
 
@@ -1051,7 +1049,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
dpu_kms->rm_init = true;
 
-   dpu_kms->hw_mdp = dpu_hw_mdptop_init(dpu_kms->catalog->mdp,
+   dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev,
+dpu_kms->catalog->mdp,
 dpu_kms->mmio,
 dpu_kms->catalog);
if (IS_ERR(dpu_kms->hw_mdp)) {
-- 
2.39.2



[PATCH v2 03/13] drm/msm/dpu: use devres-managed allocation for interrupts data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create interrupts data structure. This allows us to
remove corresponding kfree and drop dpu_hw_intr_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  4 +---
 3 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 5e2d68ebb113..945f34736206 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -6,6 +6,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dpu_core_irq.h"
 #include "dpu_kms.h"
 #include "dpu_hw_interrupts.h"
@@ -441,8 +443,9 @@ static void __intr_offset(const struct dpu_mdss_cfg *m,
hw->blk_addr = addr + m->mdp[0].base;
 }
 
-struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-   const struct dpu_mdss_cfg *m)
+struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
+void __iomem *addr,
+const struct dpu_mdss_cfg *m)
 {
struct dpu_hw_intr *intr;
int nirq = MDP_INTR_MAX * 32;
@@ -450,7 +453,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
if (!addr || !m)
return ERR_PTR(-EINVAL);
 
-   intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
+   intr = drmm_kzalloc(dev, struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
if (!intr)
return ERR_PTR(-ENOMEM);
 
@@ -465,11 +468,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
return intr;
 }
 
-void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
-{
-   kfree(intr);
-}
-
 int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
void (*irq_cb)(void *arg, int irq_idx),
void *irq_arg)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 1f2dabc54c22..b0d7bb073203 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -70,15 +70,12 @@ struct dpu_hw_intr {
 
 /**
  * dpu_hw_intr_init(): Initializes the interrupts hw object
+ * @dev:  Corresponding device for devres management
  * @addr: mapped register io address of MDP
  * @m:pointer to MDSS catalog data
  */
-struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-   const struct dpu_mdss_cfg *m);
+struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
+void __iomem *addr,
+const struct dpu_mdss_cfg *m);
 
-/**
- * dpu_hw_intr_destroy(): Cleanup interrutps hw object
- * @intr: pointer to interrupts hw object
- */
-void dpu_hw_intr_destroy(struct dpu_hw_intr *intr);
 #endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 85b8c9cc99ef..ef232dc838c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -807,8 +807,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 {
int i;
 
-   if (dpu_kms->hw_intr)
-   dpu_hw_intr_destroy(dpu_kms->hw_intr);
dpu_kms->hw_intr = NULL;
 
/* safe to call these more than once during shutdown */
@@ -1095,7 +1093,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto err_pm_put;
}
 
-   dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
+   dpu_kms->hw_intr = dpu_hw_intr_init(dev, dpu_kms->mmio, 
dpu_kms->catalog);
if (IS_ERR(dpu_kms->hw_intr)) {
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
-- 
2.39.2



[PATCH v2 02/13] drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling

2023-07-07 Thread Dmitry Baryshkov
Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If
the value is NULL, then the function will return 0 instead of a proper
return code. Replace IS_ERR_OR_NULL() with IS_ERR() in the
dpu_hw_intr_init() error check.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e7ac02e92f42..85b8c9cc99ef 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1096,7 +1096,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
}
 
dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
-   if (IS_ERR_OR_NULL(dpu_kms->hw_intr)) {
+   if (IS_ERR(dpu_kms->hw_intr)) {
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
dpu_kms->hw_intr = NULL;
-- 
2.39.2



[PATCH v2 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path

2023-07-07 Thread Dmitry Baryshkov
It was noticed that dpu_kms_hw_init()'s error path contains several
labels which point to the same code path. Replace all of them with a
single label.

Suggested-by: Konrad Dybcio 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c11b3ab572ab..e7ac02e92f42 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (!dpu_kms->catalog) {
DPU_ERROR("device config not known!\n");
rc = -EINVAL;
-   goto power_error;
+   goto err_pm_put;
}
 
/*
@@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_mmu_init(dpu_kms);
if (rc) {
DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
 
rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio);
if (rc) {
DPU_ERROR("rm init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
 
dpu_kms->rm_init = true;
@@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_mdp);
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
dpu_kms->hw_mdp = NULL;
-   goto power_error;
+   goto err_pm_put;
}
 
for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
@@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
-   goto power_error;
+   goto err_pm_put;
}
 
dpu_kms->hw_vbif[vbif->id] = hw;
@@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, 
max_core_clk_rate);
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
-   goto perf_err;
+   goto err_pm_put;
}
 
dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
@@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
dpu_kms->hw_intr = NULL;
-   goto hw_intr_init_err;
+   goto err_pm_put;
}
 
dev->mode_config.min_width = 0;
@@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_drm_obj_init(dpu_kms);
if (rc) {
DPU_ERROR("modeset init failed: %d\n", rc);
-   goto drm_obj_init_err;
+   goto err_pm_put;
}
 
dpu_vbif_init_memtypes(dpu_kms);
@@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
return 0;
 
-drm_obj_init_err:
-hw_intr_init_err:
-perf_err:
-power_error:
+err_pm_put:
pm_runtime_put_sync(_kms->pdev->dev);
 error:
_dpu_kms_hw_destroy(dpu_kms);
-- 
2.39.2



[PATCH v2 00/13] drm/msm/dpu: use managed memory allocations

2023-07-07 Thread Dmitry Baryshkov
Please excuse me for sending v2 on the same day, it fixes erorr paths
for drmm allocation code.

In a lots of places in DPU driver memory is allocated by using the
kzalloc and then manually freed using kfree. However thes memory chunks
have a well-defined life cycle. They are either a part of the driver's
runtime and can be devm_kzalloc'ed or are exposed to userspace via the
DRM objects and thus can be drmm_alloc'ed. Implement corresponding
runtime resource manangement for the DPU driver.

Dependencies: [1].

[1] https://patchwork.freedesktop.org/series/118839/

Changes since v1:
- Fix error handling for some of drmm_foo_alloc() functions, which
  return error pointer in case of an error rather than typical NULL.

Dmitry Baryshkov (13):
  drm/msm/dpu: cleanup dpu_kms_hw_init error path
  drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error
handling
  drm/msm/dpu: use devres-managed allocation for interrupts data
  drm/msm/dpu: use devres-managed allocation for VBIF data
  drm/msm/dpu: use devres-managed allocation for MDP TOP
  drm/msm/dpu: use devres-managed allocation for HW blocks
  drm/msm/dpu: drop unused dpu_plane::lock
  drm/msm/dpu: remove QoS teardown on plane destruction
  drm/msm/dpu: use drmm-managed allocation for dpu_plane
  drm/msm/dpu: use drmm-managed allocation for dpu_crtc
  drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys
  drm/msm/dpu: drop dpu_encoder_phys_ops::destroy
  drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  | 25 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 77 
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 10 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  | 15 +---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 13 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 21 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c|  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c   | 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h   | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 13 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h   |  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c| 17 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h|  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c   | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h   |  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 51 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |  1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 59 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +--
 36 files changed, 216 insertions(+), 476 deletions(-)

-- 
2.39.2



[PATCH v5 6/6] drm/doc: Define KMS atomic state set

2023-07-07 Thread André Almeida
From: Pekka Paalanen 

Specify how the atomic state is maintained between userspace and
kernel, plus the special case for async flips.

Signed-off-by: Pekka Paalanen 
Signed-off-by: André Almeida 
---
v4: total rework by Pekka
---
 Documentation/gpu/drm-uapi.rst | 41 ++
 1 file changed, 41 insertions(+)

diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst
index 65fb3036a580..6a1662c08901 100644
--- a/Documentation/gpu/drm-uapi.rst
+++ b/Documentation/gpu/drm-uapi.rst
@@ -486,3 +486,44 @@ and the CRTC index is its position in this array.
 
 .. kernel-doc:: include/uapi/drm/drm_mode.h
:internal:
+
+KMS atomic state
+
+
+An atomic commit can change multiple KMS properties in an atomic fashion,
+without ever applying intermediate or partial state changes.  Either the whole
+commit succeeds or fails, and it will never be applied partially. This is the
+fundamental improvement of the atomic API over the older non-atomic API which 
is
+referred to as the "legacy API".  Applying intermediate state could 
unexpectedly
+fail, cause visible glitches, or delay reaching the final state.
+
+An atomic commit can be flagged with DRM_MODE_ATOMIC_TEST_ONLY, which means the
+complete state change is validated but not applied.  Userspace should use this
+flag to validate any state change before asking to apply it. If validation 
fails
+for any reason, userspace should attempt to fall back to another, perhaps
+simpler, final state.  This allows userspace to probe for various 
configurations
+without causing visible glitches on screen and without the need to undo a
+probing change.
+
+The changes recorded in an atomic commit apply on top the current KMS state in
+the kernel. Hence, the complete new KMS state is the complete old KMS state 
with
+the committed property settings done on top. The kernel will automatically 
avoid
+no-operation changes, so it is safe and even expected for userspace to send
+redundant property settings.  No-operation changes do not count towards 
actually
+needed changes, e.g.  setting MODE_ID to a different blob with identical
+contents as the current KMS state shall not be a modeset on its own.
+
+A "modeset" is a change in KMS state that might enable, disable, or temporarily
+disrupt the emitted video signal, possibly causing visible glitches on screen. 
A
+modeset may also take considerably more time to complete than other kinds of
+changes, and the video sink might also need time to adapt to the new signal
+properties. Therefore a modeset must be explicitly allowed with the flag
+DRM_MODE_ATOMIC_ALLOW_MODESET.  This in combination with
+DRM_MODE_ATOMIC_TEST_ONLY allows userspace to determine if a state change is
+likely to cause visible disruption on screen and avoid such changes when end
+users do not expect them.
+
+An atomic commit with the flag DRM_MODE_PAGE_FLIP_ASYNC is allowed to
+effectively change only the FB_ID property on any planes. No-operation changes
+are ignored as always. Changing any other property will cause the commit to be
+rejected.
-- 
2.41.0



[PATCH v5 5/6] drm: Refuse to async flip with atomic prop changes

2023-07-07 Thread André Almeida
Given that prop changes may lead to modesetting, which would defeat the
fast path of the async flip, refuse any atomic prop change for async
flips in atomic API. The only exceptions are the framebuffer ID to flip
to and the mode ID, that could be referring to an identical mode.

Signed-off-by: André Almeida 
---
v4: new patch
---
 drivers/gpu/drm/drm_atomic_helper.c |  5 +++
 drivers/gpu/drm/drm_atomic_uapi.c   | 52 +++--
 drivers/gpu/drm/drm_crtc_internal.h |  2 +-
 drivers/gpu/drm/drm_mode_object.c   |  2 +-
 4 files changed, 56 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_helper.c 
b/drivers/gpu/drm/drm_atomic_helper.c
index 2c2c9caf0be5..1e2973f0e1f6 100644
--- a/drivers/gpu/drm/drm_atomic_helper.c
+++ b/drivers/gpu/drm/drm_atomic_helper.c
@@ -629,6 +629,11 @@ drm_atomic_helper_check_modeset(struct drm_device *dev,
WARN_ON(!drm_modeset_is_locked(>mutex));
 
if (!drm_mode_equal(_crtc_state->mode, 
_crtc_state->mode)) {
+   if (new_crtc_state->async_flip) {
+   drm_dbg_atomic(dev, "[CRTC:%d:%s] no mode 
changes allowed during async flip\n",
+  crtc->base.id, crtc->name);
+   return -EINVAL;
+   }
drm_dbg_atomic(dev, "[CRTC:%d:%s] mode changed\n",
   crtc->base.id, crtc->name);
new_crtc_state->mode_changed = true;
diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index dfd4cf7169df..536c21f53b5f 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -972,13 +972,28 @@ int drm_atomic_connector_commit_dpms(struct 
drm_atomic_state *state,
return ret;
 }
 
+static int drm_atomic_check_prop_changes(int ret, uint64_t old_val, uint64_t 
prop_value,
+struct drm_property *prop)
+{
+   if (ret != 0 || old_val != prop_value) {
+   drm_dbg_atomic(prop->dev,
+  "[PROP:%d:%s] No prop can be changed during 
async flip\n",
+  prop->base.id, prop->name);
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_file *file_priv,
struct drm_mode_object *obj,
struct drm_property *prop,
-   uint64_t prop_value)
+   uint64_t prop_value,
+   bool async_flip)
 {
struct drm_mode_object *ref;
+   uint64_t old_val;
int ret;
 
if (!drm_property_change_valid_get(prop, prop_value, ))
@@ -995,6 +1010,13 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
break;
}
 
+   if (async_flip) {
+   ret = drm_atomic_connector_get_property(connector, 
connector_state,
+   prop, _val);
+   ret = drm_atomic_check_prop_changes(ret, old_val, 
prop_value, prop);
+   break;
+   }
+
ret = drm_atomic_connector_set_property(connector,
connector_state, file_priv,
prop, prop_value);
@@ -1003,6 +1025,7 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
case DRM_MODE_OBJECT_CRTC: {
struct drm_crtc *crtc = obj_to_crtc(obj);
struct drm_crtc_state *crtc_state;
+   struct drm_mode_config *config = >dev->mode_config;
 
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state)) {
@@ -1010,6 +1033,18 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
break;
}
 
+   /*
+* We allow mode_id changes here for async flips, because we
+* check later on drm_atomic_helper_check_modeset() callers if
+* there are modeset changes or they are equal
+*/
+   if (async_flip && prop != config->prop_mode_id) {
+   ret = drm_atomic_crtc_get_property(crtc, crtc_state,
+  prop, _val);
+   ret = drm_atomic_check_prop_changes(ret, old_val, 
prop_value, prop);
+   break;
+   }
+
ret = drm_atomic_crtc_set_property(crtc,
crtc_state, prop, prop_value);
break;
@@ -1017,6 +1052,7 @@ int drm_atomic_set_property(struct drm_atomic_state 
*state,
case DRM_MODE_OBJECT_PLANE: {
struct drm_plane *plane = 

[PATCH v5 4/6] amd/display: indicate support for atomic async page-flips on DC

2023-07-07 Thread André Almeida
From: Simon Ser 

amdgpu_dm_commit_planes() already sets the flip_immediate flag for
async page-flips. This flag is used to set the UNP_FLIP_CONTROL
register. Thus, no additional change is required to handle async
page-flips with the atomic uAPI.

Signed-off-by: Simon Ser 
Reviewed-by: André Almeida 
Reviewed-by: Alex Deucher 
Signed-off-by: André Almeida 
---
v4: no changes
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 258461826140..7acd73e5004f 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3970,7 +3970,6 @@ static int amdgpu_dm_mode_config_init(struct 
amdgpu_device *adev)
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
/* indicates support for immediate flip */
adev_to_drm(adev)->mode_config.async_page_flip = true;
-   adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = 
true;
 
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
-- 
2.41.0



[PATCH v5 3/6] drm: introduce drm_mode_config.atomic_async_page_flip_not_supported

2023-07-07 Thread André Almeida
From: Simon Ser 

This new field indicates whether the driver has the necessary logic
to support async page-flips via the atomic uAPI. This is leveraged by
the next commit to allow user-space to use this functionality.

All atomic drivers setting drm_mode_config.async_page_flip are updated
to also set drm_mode_config.atomic_async_page_flip_not_supported. We
will gradually check and update these drivers to properly handle
drm_crtc_state.async_flip in their atomic logic.

The goal of this negative flag is the same as
fb_modifiers_not_supported: we want to eventually get rid of all
drivers missing atomic support for async flips. New drivers should not
set this flag, instead they should support atomic async flips (if
they support async flips at all). IOW, we don't want more drivers
with async flip support for legacy but not atomic.

Signed-off-by: Simon Ser 
Reviewed-by: André Almeida 
Reviewed-by: Alex Deucher 
Signed-off-by: André Almeida 
---
v4: no changes
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |  1 +
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c  |  1 +
 drivers/gpu/drm/i915/display/intel_display.c  |  1 +
 drivers/gpu/drm/nouveau/nouveau_display.c |  1 +
 include/drm/drm_mode_config.h | 11 +++
 5 files changed, 15 insertions(+)

diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c 
b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index 7acd73e5004f..258461826140 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3970,6 +3970,7 @@ static int amdgpu_dm_mode_config_init(struct 
amdgpu_device *adev)
adev_to_drm(adev)->mode_config.prefer_shadow = 1;
/* indicates support for immediate flip */
adev_to_drm(adev)->mode_config.async_page_flip = true;
+   adev_to_drm(adev)->mode_config.atomic_async_page_flip_not_supported = 
true;
 
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c 
b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 29603561d501..8afb22b1e730 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -639,6 +639,7 @@ static int atmel_hlcdc_dc_modeset_init(struct drm_device 
*dev)
dev->mode_config.max_height = dc->desc->max_height;
dev->mode_config.funcs = _config_funcs;
dev->mode_config.async_page_flip = true;
+   dev->mode_config.atomic_async_page_flip_not_supported = true;
 
return 0;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 0aae9a1eb3d5..a5c503ca9168 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -8318,6 +8318,7 @@ static void intel_mode_config_init(struct 
drm_i915_private *i915)
mode_config->helper_private = _mode_config_funcs;
 
mode_config->async_page_flip = HAS_ASYNC_FLIPS(i915);
+   mode_config->atomic_async_page_flip_not_supported = true;
 
/*
 * Maximum framebuffer dimensions, chosen to match
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c 
b/drivers/gpu/drm/nouveau/nouveau_display.c
index ec3487fc..f497dcd9e22f 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -709,6 +709,7 @@ nouveau_display_create(struct drm_device *dev)
dev->mode_config.async_page_flip = false;
else
dev->mode_config.async_page_flip = true;
+   dev->mode_config.atomic_async_page_flip_not_supported = true;
 
drm_kms_helper_poll_init(dev);
drm_kms_helper_poll_disable(dev);
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 973119a9176b..47b005671e6a 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -918,6 +918,17 @@ struct drm_mode_config {
 */
bool async_page_flip;
 
+   /**
+* @atomic_async_page_flip_not_supported:
+*
+* If true, the driver does not support async page-flips with the
+* atomic uAPI. This is only used by old drivers which haven't yet
+* accomodated for _crtc_state.async_flip in their atomic logic,
+* even if they have _mode_config.async_page_flip set to true.
+* New drivers shall not set this flag.
+*/
+   bool atomic_async_page_flip_not_supported;
+
/**
 * @fb_modifiers_not_supported:
 *
-- 
2.41.0



[PATCH v5 2/6] drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP

2023-07-07 Thread André Almeida
From: Simon Ser 

This new kernel capability indicates whether async page-flips are
supported via the atomic uAPI. DRM clients can use it to check
for support before feeding DRM_MODE_PAGE_FLIP_ASYNC to the kernel.

Make it clear that DRM_CAP_ASYNC_PAGE_FLIP is for legacy uAPI only.

Signed-off-by: Simon Ser 
Reviewed-by: André Almeida 
Reviewed-by: Alex Deucher 
Signed-off-by: André Almeida 
---
v4: no changes
---
 drivers/gpu/drm/drm_ioctl.c |  5 +
 include/uapi/drm/drm.h  | 10 +-
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 7c9d66ee917d..8f756b99260d 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -302,6 +302,11 @@ static int drm_getcap(struct drm_device *dev, void *data, 
struct drm_file *file_
case DRM_CAP_CRTC_IN_VBLANK_EVENT:
req->value = 1;
break;
+   case DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP:
+   req->value = drm_core_check_feature(dev, DRIVER_ATOMIC) &&
+dev->mode_config.async_page_flip &&
+
!dev->mode_config.atomic_async_page_flip_not_supported;
+   break;
default:
return -EINVAL;
}
diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h
index a87ca2d4..54c558f81f3c 100644
--- a/include/uapi/drm/drm.h
+++ b/include/uapi/drm/drm.h
@@ -706,7 +706,8 @@ struct drm_gem_open {
 /**
  * DRM_CAP_ASYNC_PAGE_FLIP
  *
- * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC.
+ * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for legacy
+ * page-flips.
  */
 #define DRM_CAP_ASYNC_PAGE_FLIP0x7
 /**
@@ -767,6 +768,13 @@ struct drm_gem_open {
  * Documentation/gpu/drm-mm.rst, section "DRM Sync Objects".
  */
 #define DRM_CAP_SYNCOBJ_TIMELINE   0x14
+/**
+ * DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
+ *
+ * If set to 1, the driver supports _MODE_PAGE_FLIP_ASYNC for atomic
+ * commits.
+ */
+#define DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP 0x15
 
 /* DRM_IOCTL_GET_CAP ioctl argument type */
 struct drm_get_cap {
-- 
2.41.0



[PATCH v5 0/6] drm: Add support for atomic async page-flip

2023-07-07 Thread André Almeida
Hi,

This work from me and Simon adds support for DRM_MODE_PAGE_FLIP_ASYNC through
the atomic API. This feature is already available via the legacy API. The use
case is to be able to present a new frame immediately (or as soon as
possible), even if after missing a vblank. This might result in tearing, but
it's useful when a high framerate is desired, such as for gaming.

Differently from earlier versions, this one refuses to flip if any prop changes
for async flips. The idea is that the fast path of immediate page flips doesn't
play well with modeset changes, so only the fb_id can be changed. The exception
is for mode_id changes, that might be referring to an identical mode (which
would skip a modeset). This is done to make the async API more similar to the
normal API.

Thanks,
André

- User-space patch: https://github.com/Plagman/gamescope/pull/595
- IGT tests: 
https://gitlab.freedesktop.org/andrealmeid/igt-gpu-tools/-/tree/atomic_async_page_flip

Changes from v4:
 - Documentation rewrote by Pekka Paalanen

v4: 
https://lore.kernel.org/dri-devel/20230701020917.143394-1-andrealm...@igalia.com/

Changes from v3:
 - Add new patch to reject prop changes
 - Add a documentation clarifying the KMS atomic state set

v3: 
https://lore.kernel.org/dri-devel/20220929184307.258331-1-cont...@emersion.fr/

André Almeida (1):
  drm: Refuse to async flip with atomic prop changes

Pekka Paalanen (1):
  drm/doc: Define KMS atomic state set

Simon Ser (4):
  drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits
  drm: introduce DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP
  drm: introduce drm_mode_config.atomic_async_page_flip_not_supported
  amd/display: indicate support for atomic async page-flips on DC

 Documentation/gpu/drm-uapi.rst   | 41 ++
 drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c |  1 +
 drivers/gpu/drm/drm_atomic_helper.c  |  5 ++
 drivers/gpu/drm/drm_atomic_uapi.c| 80 ++--
 drivers/gpu/drm/drm_crtc_internal.h  |  2 +-
 drivers/gpu/drm/drm_ioctl.c  |  5 ++
 drivers/gpu/drm/drm_mode_object.c|  2 +-
 drivers/gpu/drm/i915/display/intel_display.c |  1 +
 drivers/gpu/drm/nouveau/nouveau_display.c|  1 +
 include/drm/drm_mode_config.h| 11 +++
 include/uapi/drm/drm.h   | 10 ++-
 include/uapi/drm/drm_mode.h  |  9 +++
 12 files changed, 159 insertions(+), 9 deletions(-)

-- 
2.41.0



[PATCH v5 1/6] drm: allow DRM_MODE_PAGE_FLIP_ASYNC for atomic commits

2023-07-07 Thread André Almeida
From: Simon Ser 

If the driver supports it, allow user-space to supply the
DRM_MODE_PAGE_FLIP_ASYNC flag to request an async page-flip.
Set drm_crtc_state.async_flip accordingly.

Document that drivers will reject atomic commits if an async
flip isn't possible. This allows user-space to fall back to
something else. For instance, Xorg falls back to a blit.
Another option is to wait as close to the next vblank as
possible before performing the page-flip to reduce latency.

Signed-off-by: Simon Ser 
Reviewed-by: Alex Deucher 
Co-developed-by: André Almeida 
Signed-off-by: André Almeida 
---
v4: no changes
---
 drivers/gpu/drm/drm_atomic_uapi.c | 28 +---
 include/uapi/drm/drm_mode.h   |  9 +
 2 files changed, 34 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_atomic_uapi.c 
b/drivers/gpu/drm/drm_atomic_uapi.c
index d867e7f9f2cd..dfd4cf7169df 100644
--- a/drivers/gpu/drm/drm_atomic_uapi.c
+++ b/drivers/gpu/drm/drm_atomic_uapi.c
@@ -1286,6 +1286,18 @@ static void complete_signaling(struct drm_device *dev,
kfree(fence_state);
 }
 
+static void
+set_async_flip(struct drm_atomic_state *state)
+{
+   struct drm_crtc *crtc;
+   struct drm_crtc_state *crtc_state;
+   int i;
+
+   for_each_new_crtc_in_state(state, crtc, crtc_state, i) {
+   crtc_state->async_flip = true;
+   }
+}
+
 int drm_mode_atomic_ioctl(struct drm_device *dev,
  void *data, struct drm_file *file_priv)
 {
@@ -1326,9 +1338,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
}
 
if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC) {
-   drm_dbg_atomic(dev,
-  "commit failed: invalid flag 
DRM_MODE_PAGE_FLIP_ASYNC\n");
-   return -EINVAL;
+   if (!dev->mode_config.async_page_flip) {
+   drm_dbg_atomic(dev,
+  "commit failed: DRM_MODE_PAGE_FLIP_ASYNC 
not supported\n");
+   return -EINVAL;
+   }
+   if (dev->mode_config.atomic_async_page_flip_not_supported) {
+   drm_dbg_atomic(dev,
+  "commit failed: DRM_MODE_PAGE_FLIP_ASYNC 
not supported with atomic\n");
+   return -EINVAL;
+   }
}
 
/* can't test and expect an event at the same time. */
@@ -1426,6 +1445,9 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
if (ret)
goto out;
 
+   if (arg->flags & DRM_MODE_PAGE_FLIP_ASYNC)
+   set_async_flip(state);
+
if (arg->flags & DRM_MODE_ATOMIC_TEST_ONLY) {
ret = drm_atomic_check_only(state);
} else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) {
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 46becedf5b2f..56342ba2c11a 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -949,6 +949,15 @@ struct hdr_output_metadata {
  * Request that the page-flip is performed as soon as possible, ie. with no
  * delay due to waiting for vblank. This may cause tearing to be visible on
  * the screen.
+ *
+ * When used with atomic uAPI, the driver will return an error if the hardware
+ * doesn't support performing an asynchronous page-flip for this update.
+ * User-space should handle this, e.g. by falling back to a regular page-flip.
+ *
+ * Note, some hardware might need to perform one last synchronous page-flip
+ * before being able to switch to asynchronous page-flips. As an exception,
+ * the driver will return success even though that first page-flip is not
+ * asynchronous.
  */
 #define DRM_MODE_PAGE_FLIP_ASYNC 0x02
 #define DRM_MODE_PAGE_FLIP_TARGET_ABSOLUTE 0x4
-- 
2.41.0



[PATCH] drm/nouveau/nvkm/dp: Add hack to fix DP 1.3+ DPCD issues

2023-07-07 Thread Lyude Paul
Currently we use the drm_dp_dpcd_read_caps() helper in the DRM side of
nouveau in order to read the DPCD of a DP connector, which makes sure we do
the right thing and also check for extended DPCD caps. However, it turns
out we're not currently doing this on the nvkm side since we don't have
access to the drm_dp_aux structure there - which means that the DRM side of
the driver and the NVKM side can end up with different DPCD capabilities
for the same connector.

Ideally to fix this, we want to start setting up the drm_dp_aux device in
NVKM before we've made contact with the DRM side - which should be pretty
easy to accomplish (I'm already working on it!). Until then however, let's
workaround this problem by porting a copy of drm_dp_read_dpcd_caps() into
NVKM - which should fix this issue.

Issue: https://gitlab.freedesktop.org/drm/nouveau/-/issues/211
Signed-off-by: Lyude Paul 
---
 drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c | 48 ++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c 
b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
index 40c8ea43c42f..b8ac66b4a2c4 100644
--- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
@@ -26,6 +26,8 @@
 #include "head.h"
 #include "ior.h"
 
+#include 
+
 #include 
 #include 
 #include 
@@ -634,6 +636,50 @@ nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp)
return outp->dp.rates != 0;
 }
 
+/* XXX: This is a big fat hack, and this is just drm_dp_read_dpcd_caps()
+ * converted to work inside nvkm. This is a temporary holdover until we start
+ * passing the drm_dp_aux device through NVKM
+ */
+static int
+nvkm_dp_read_dpcd_caps(struct nvkm_outp *outp)
+{
+   struct nvkm_i2c_aux *aux = outp->dp.aux;
+   u8 dpcd_ext[DP_RECEIVER_CAP_SIZE];
+   int ret;
+
+   ret = nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, 
DP_RECEIVER_CAP_SIZE);
+   if (ret < 0)
+   return ret;
+
+   /*
+* Prior to DP1.3 the bit represented by
+* DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT was reserved.
+* If it is set DP_DPCD_REV at h could be at a value less than
+* the true capability of the panel. The only way to check is to
+* then compare h and 2200h.
+*/
+   if (!(outp->dp.dpcd[DP_TRAINING_AUX_RD_INTERVAL] &
+ DP_EXTENDED_RECEIVER_CAP_FIELD_PRESENT))
+   return 0;
+
+   ret = nvkm_rdaux(aux, DP_DP13_DPCD_REV, dpcd_ext, sizeof(dpcd_ext));
+   if (ret < 0)
+   return ret;
+
+   if (outp->dp.dpcd[DP_DPCD_REV] > dpcd_ext[DP_DPCD_REV]) {
+   OUTP_DBG(outp, "Extended DPCD rev less than base DPCD rev (%d > 
%d)\n",
+outp->dp.dpcd[DP_DPCD_REV], dpcd_ext[DP_DPCD_REV]);
+   return 0;
+   }
+
+   if (!memcmp(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext)))
+   return 0;
+
+   memcpy(outp->dp.dpcd, dpcd_ext, sizeof(dpcd_ext));
+
+   return 0;
+}
+
 void
 nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
 {
@@ -689,7 +735,7 @@ nvkm_dp_enable(struct nvkm_outp *outp, bool auxpwr)
memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr));
}
 
-   if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, 
sizeof(outp->dp.dpcd))) {
+   if (!nvkm_dp_read_dpcd_caps(outp)) {
const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 };
const u8 *rate;
int rate_max;
-- 
2.40.1



Re: [PATCH v4 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

2023-07-07 Thread Dmitry Baryshkov
On Fri, 7 Jul 2023 at 23:49, Ryan McCann  wrote:
>
> My apologies for the private email, I hit reply instead of reply all by
> accident.

No problem, it happens sometimes.

>
> On 7/6/2023 5:24 PM, Dmitry Baryshkov wrote:
> > On 06/07/2023 23:48, Ryan McCann wrote:
> >> Currently, the device core dump mechanism does not dump registers of
> >> sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit
> >> dpu_kms_mdp_snapshot function to account for sub-blocks.
> >>
> >> Signed-off-by: Ryan McCann 
> >> ---
> >>   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66
> >> ++---
> >>   1 file changed, 60 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> >> b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> >> index 70dbb1204e6c..afc45d597d65 100644
> >> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> >> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
> >> @@ -903,25 +903,58 @@ static void dpu_kms_mdp_snapshot(struct
> >> msm_disp_state *disp_state, struct msm_k
> >>   cat->ctl[i].base, cat->ctl[i].name);
> >>   /* dump DSPP sub-blocks HW regs info */
> >> -for (i = 0; i < cat->dspp_count; i++)
> >> +for (i = 0; i < cat->dspp_count; i++) {
> >>   msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len,
> >> dpu_kms->mmio +
> >>   cat->dspp[i].base, cat->dspp[i].name);
> >> +if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0)
> >> +msm_disp_snapshot_add_block(disp_state,
> >> cat->dspp[i].sblk->pcc.len,
> >> +dpu_kms->mmio + cat->dspp[i].base +
> >> +cat->dspp[i].sblk->pcc.base, "%s_%s",
> >
> > This might look simpler in the following form. Could you please consider
> > it?
> >
> >
> > void *base =  dpu_kms + cat->dspp[i].base;
> >
> > msm_disp_snapshot_add_block(..., base, cat->dspp[i].name)
> >
> > if (!cat->dspp[i].sblk)
> >  continue;
> >
> > if (cat->dspp[i].sblk->pcc.len)
> >  msm_disp_snapshot_add_block(..., base +
> > cat->dspp[i].sblk->pcc.base, ...);
>
> Regarding what we discussed in the private email, is what I had for base
> in v2
>
> (https://patchwork.freedesktop.org/patch/545690/?series=120249=1)
>
> essentially what you have in mind?
>
> >
> >> +cat->dspp[i].name,
> >> +cat->dspp[i].sblk->pcc.name);
> >> +}
> >> +
> >>   /* dump INTF sub-blocks HW regs info */
> >>   for (i = 0; i < cat->intf_count; i++)
> >>   msm_disp_snapshot_add_block(disp_state, cat->intf[i].len,
> >> dpu_kms->mmio +
> >>   cat->intf[i].base, cat->intf[i].name);
> >>   /* dump PP sub-blocks HW regs info */
> >> -for (i = 0; i < cat->pingpong_count; i++)
> >> +for (i = 0; i < cat->pingpong_count; i++) {
> >>   msm_disp_snapshot_add_block(disp_state,
> >> cat->pingpong[i].len, dpu_kms->mmio +
> >>   cat->pingpong[i].base, cat->pingpong[i].name);
> >> +/* TE2 block has length of 0, so will not print it */
> >> +
> >> +if (cat->pingpong[i].sblk &&
> >> cat->pingpong[i].sblk->dither.len > 0)
> >> +msm_disp_snapshot_add_block(disp_state,
> >> cat->pingpong[i].sblk->dither.len,
> >> +dpu_kms->mmio + cat->pingpong[i].base +
> >> +cat->pingpong[i].sblk->dither.base, "%s_%s",
> >> +cat->pingpong[i].name,
> >> +cat->pingpong[i].sblk->dither.name);
> >> +}
> >> +
> >>   /* dump SSPP sub-blocks HW regs info */
> >> -for (i = 0; i < cat->sspp_count; i++)
> >> +for (i = 0; i < cat->sspp_count; i++) {
> >>   msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len,
> >> dpu_kms->mmio +
> >>   cat->sspp[i].base, cat->sspp[i].name);
> >> +if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0)
> >> +msm_disp_snapshot_add_block(disp_state,
> >> cat->sspp[i].sblk->scaler_blk.len,
> >> +dpu_kms->mmio + cat->sspp[i].base +
> >> +cat->sspp[i].sblk->scaler_blk.base, "%s_%s",
> >> +cat->sspp[i].name,
> >> +cat->sspp[i].sblk->scaler_blk.name);
> >> +
> >> +if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0)
> >> +msm_disp_snapshot_add_block(disp_state,
> >> cat->sspp[i].sblk->csc_blk.len,
> >> +dpu_kms->mmio + cat->sspp[i].base +
> >> +cat->sspp[i].sblk->csc_blk.base, "%s_%s",
> >> +cat->sspp[i].name,
> >> +cat->sspp[i].sblk->csc_blk.name);
> >> +}
> >> +
> >>   /* dump LM sub-blocks HW regs info */
> >>   for (i = 0; i < cat->mixer_count; i++)
> >>   msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len,

[PATCH v4] drm/virtio: conditionally allocate virtio_gpu_fence

2023-07-07 Thread Gurchetan Singh
We don't want to create a fence for every command submission.  It's
only necessary when userspace provides a waitable token for submission.
This could be:

1) bo_handles, to be used with VIRTGPU_WAIT
2) out_fence_fd, to be used with dma_fence apis
3) a ring_idx provided with VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK
   + DRM event API
4) syncobjs in the future

The use case for just submitting a command to the host, and expecting
no response.  For example, gfxstream has GFXSTREAM_CONTEXT_PING that
just wakes up the host side worker threads.  There's also
CROSS_DOMAIN_CMD_SEND which just sends data to the Wayland server.

This prevents the need to signal the automatically created
virtio_gpu_fence.

In addition, VIRTGPU_EXECBUF_RING_IDX is checked when creating a
DRM event object.  VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK is
already defined in terms of per-context rings.  It was theoretically
possible to create a DRM event on the global timeline (ring_idx == 0),
if the context enabled DRM event polling.  However, that wouldn't
work and userspace (Sommelier).  Explicitly disallow it for
clarity.

Signed-off-by: Gurchetan Singh 
---
 v2: Fix indent (Dmitry)
 v3: Refactor drm fence event checks to avoid possible NULL deref (Dmitry)
 v4: More detailed commit message about addition drm fence event checks (Dmitry)

 drivers/gpu/drm/virtio/virtgpu_submit.c | 28 +
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_submit.c 
b/drivers/gpu/drm/virtio/virtgpu_submit.c
index cf3c04b16a7a..004364cf86d7 100644
--- a/drivers/gpu/drm/virtio/virtgpu_submit.c
+++ b/drivers/gpu/drm/virtio/virtgpu_submit.c
@@ -64,13 +64,9 @@ static int virtio_gpu_fence_event_create(struct drm_device 
*dev,
 struct virtio_gpu_fence *fence,
 u32 ring_idx)
 {
-   struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct virtio_gpu_fence_event *e = NULL;
int ret;
 
-   if (!(vfpriv->ring_idx_mask & BIT_ULL(ring_idx)))
-   return 0;
-
e = kzalloc(sizeof(*e), GFP_KERNEL);
if (!e)
return -ENOMEM;
@@ -161,21 +157,27 @@ static int virtio_gpu_init_submit(struct 
virtio_gpu_submit *submit,
  struct drm_file *file,
  u64 fence_ctx, u32 ring_idx)
 {
+   int err;
+   struct virtio_gpu_fence *out_fence;
struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
struct virtio_gpu_device *vgdev = dev->dev_private;
-   struct virtio_gpu_fence *out_fence;
-   int err;
+   bool drm_fence_event = (exbuf->flags & VIRTGPU_EXECBUF_RING_IDX) &&
+  (vfpriv->ring_idx_mask & BIT_ULL(ring_idx));
 
memset(submit, 0, sizeof(*submit));
 
-   out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
-   if (!out_fence)
-   return -ENOMEM;
+   if ((exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) || drm_fence_event ||
+exbuf->num_bo_handles)
+   out_fence = virtio_gpu_fence_alloc(vgdev, fence_ctx, ring_idx);
+   else
+   out_fence = NULL;
 
-   err = virtio_gpu_fence_event_create(dev, file, out_fence, ring_idx);
-   if (err) {
-   dma_fence_put(_fence->f);
-   return err;
+   if (drm_fence_event) {
+   err = virtio_gpu_fence_event_create(dev, file, out_fence, 
ring_idx);
+   if (err) {
+   dma_fence_put(_fence->f);
+   return err;
+   }
}
 
submit->out_fence = out_fence;
-- 
2.41.0.255.g8b1d071c50-goog



Re: [PATCH] drm/nouveau/disp/g94: enable HDMI

2023-07-07 Thread Lyude Paul
Reviewed-by: Lyude Paul 

But seeing as I looked at this + some other patches yesterday I assume there's
still more to this?

On Fri, 2023-06-30 at 18:06 +0200, Karol Herbst wrote:
> Cc: Ben Skeggs 
> Cc: Lyude Paul 
> Fixes: f530bc60a30b ("drm/nouveau/disp: move HDMI config into acquire + 
> infoframe methods")
> Signed-off-by: Karol Herbst 
> ---
>  drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c 
> b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> index a4853c4e5ee3..67ef889a0c5f 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
> @@ -295,6 +295,7 @@ g94_sor = {
>   .clock = nv50_sor_clock,
>   .war_2 = g94_sor_war_2,
>   .war_3 = g94_sor_war_3,
> + .hdmi = _sor_hdmi,
>   .dp = _sor_dp,
>  };
>  

-- 
Cheers,
 Lyude Paul (she/her)
 Software Engineer at Red Hat



Re: [PATCH v4 2/8] drm/atomic: Add support for mouse hotspots

2023-07-07 Thread Michael Banack




On 7/7/23 01:38, Pekka Paalanen wrote:


That statement was based on the assumption that existing hypervisors
and VM viewer applications are not prepared to deal with hotspots
outside of cursor image. Therefore, if a guest is upgraded to a version
that uses hotspots outside of cursor images, and the VM stack is not
updated, it will malfunction.

Therefore it is best to model the new UAPI in a way that is compatible
with existing VM stack, especially since allowing this new feature
(hotspots outside of cursor image) has no known benefits.

Below I see my assumption was incorrect, but it still causes you to
fall back to something less optimal.


Okay, right.  That's why I was saying that it's not a big deal either 
way to VMware, but I wanted to at least make the case for allowing 
somewhat arbitrary hotspots just because it is semantically meaningful, 
and I don't know if any other hypervisors care about allowing it more 
than we do.




Essentially setting the hotspot properties means that the hypervisor
console can choose to either draw the cursor where the plane is located,
or use the cursor-plane + hotspot information to draw the cursor where
the user's mouse is on the client.

That works the same whether the hotspot is clamped or not.  We mostly
use clamping to avoid pathological cases (like a hotspot ot MAX_UINT32),
and get away with it because real Guest applications that do this are
very rare.

My point here is that you can design the new Linux UAPI to help you:
you can rule out cases that would lead to non-optimal behaviour, like
falling back to the drawing of cursor plane you mention when it would
be better to commandeer the cursor plane with the hotspot information.


We can't though, because we can't trust the guest kernel any more than 
the kernel can trust userspace.


So we need to handle these cases one way or another, both for older 
guests, and to ensure we don't have some security issue from a malicious 
guest kernel.





The question of which input device corresponds to which cursor plane
might be good to answer too. I presume the VM runner is configured to
expose exactly one of each, so there can be only one association?

As far as I know, all of the VM consoles are written as though they
taking the place of what would the the physical monitors and input
devices on a native machine.  So they assume that there is one user,
sitting in front of one console, and all monitors/input devices are
being used by that user.

Ok, but having a single user does not mean that there cannot be
multiple independent pointers, especially on Wayland. The same with
keyboards.

True, and if the userspace is doing anything complicated here, the
hypervisor has to be responsible for ensuring that whatever it's doing
works with that, or else this system won't work.  I don't know that the
kernel is in a good position to police that.

What do you mean by policing here?

Isn't it the hypervisor that determines what virtual input devices will
be available to the guest OS? Therefore, the hypervisor is in a
position to expose exactly one pointer device and exactly one
cursor plane to guest OS which means the guest OS cannot get the
association wrong. If that's the general and expected hypervisor
policy, then there is no need to design explicit device association in
the guest kernel UAPI. If so, I'd like it to be mentioned in the kernel
docs, too.

I'm not entirely sure how to fit what you're calling a "pointer" into my
mental model of what the hypervisor is doing...

My definition: A pointer is a pointing input device that requires a
cursor image to be drawn at the right location for it to be usable.
Right, but normal desktops (and our consoles) expect multiple input 
devices to feed into a single cursor.  So the connection between the 
on-screen cursor and the corresponding input-devices is not clear to me 
when you start talking about multiple pointers, even without any 
hypervisors in the picture.





For a typical Linux Guest, we currently expose 3+ virtual mouse devices,
and choose which one to send input to based on what their guest drivers
are doing, and what kind of input we got from the client.  We expect the
input from all of those to end up in the same user desktop session,
which we expect to own all the virtual screens, and that the user the
only gets one cursor image from that.

Why do you need to expose so many pointer devices? Just curious.
For one, we don't know what drivers are actually going to be running in 
the Guest.  If someone configured the Guest to not support the PS/2 
mouse, or didn't have USB support compiled in, we still need to be able 
to send mouse input.  (We actually ran into this for years with some 
Linux distro installers, where they had frozen their installer with some 
weird/older kernel configs and just didn't support our preferred vmmouse 
device.)  So we plug them all in at boot, and then try to pick the one 
that looks the most active.


But we also need to be able to 

Re: [PATCH v4 6/6] drm/msm/dpu: Update dev core dump to dump registers of sub-blocks

2023-07-07 Thread Ryan McCann
My apologies for the private email, I hit reply instead of reply all by 
accident.


On 7/6/2023 5:24 PM, Dmitry Baryshkov wrote:

On 06/07/2023 23:48, Ryan McCann wrote:

Currently, the device core dump mechanism does not dump registers of
sub-blocks within the DSPP, SSPP, DSC, and PINGPONG blocks. Edit
dpu_kms_mdp_snapshot function to account for sub-blocks.

Signed-off-by: Ryan McCann 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 66 
++---

  1 file changed, 60 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 70dbb1204e6c..afc45d597d65 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -903,25 +903,58 @@ static void dpu_kms_mdp_snapshot(struct 
msm_disp_state *disp_state, struct msm_k

  cat->ctl[i].base, cat->ctl[i].name);
  /* dump DSPP sub-blocks HW regs info */
-    for (i = 0; i < cat->dspp_count; i++)
+    for (i = 0; i < cat->dspp_count; i++) {
  msm_disp_snapshot_add_block(disp_state, cat->dspp[i].len, 
dpu_kms->mmio +

  cat->dspp[i].base, cat->dspp[i].name);
+    if (cat->dspp[i].sblk && cat->dspp[i].sblk->pcc.len > 0)
+    msm_disp_snapshot_add_block(disp_state, 
cat->dspp[i].sblk->pcc.len,

+    dpu_kms->mmio + cat->dspp[i].base +
+    cat->dspp[i].sblk->pcc.base, "%s_%s",


This might look simpler in the following form. Could you please consider 
it?



void *base =  dpu_kms + cat->dspp[i].base;

msm_disp_snapshot_add_block(..., base, cat->dspp[i].name)

if (!cat->dspp[i].sblk)
     continue;

if (cat->dspp[i].sblk->pcc.len)
     msm_disp_snapshot_add_block(..., base + 
cat->dspp[i].sblk->pcc.base, ...);


Regarding what we discussed in the private email, is what I had for base 
in v2


(https://patchwork.freedesktop.org/patch/545690/?series=120249=1)

essentially what you have in mind?




+    cat->dspp[i].name,
+    cat->dspp[i].sblk->pcc.name);
+    }
+
  /* dump INTF sub-blocks HW regs info */
  for (i = 0; i < cat->intf_count; i++)
  msm_disp_snapshot_add_block(disp_state, cat->intf[i].len, 
dpu_kms->mmio +

  cat->intf[i].base, cat->intf[i].name);
  /* dump PP sub-blocks HW regs info */
-    for (i = 0; i < cat->pingpong_count; i++)
+    for (i = 0; i < cat->pingpong_count; i++) {
  msm_disp_snapshot_add_block(disp_state, 
cat->pingpong[i].len, dpu_kms->mmio +

  cat->pingpong[i].base, cat->pingpong[i].name);
+    /* TE2 block has length of 0, so will not print it */
+
+    if (cat->pingpong[i].sblk && 
cat->pingpong[i].sblk->dither.len > 0)
+    msm_disp_snapshot_add_block(disp_state, 
cat->pingpong[i].sblk->dither.len,

+    dpu_kms->mmio + cat->pingpong[i].base +
+    cat->pingpong[i].sblk->dither.base, "%s_%s",
+    cat->pingpong[i].name,
+    cat->pingpong[i].sblk->dither.name);
+    }
+
  /* dump SSPP sub-blocks HW regs info */
-    for (i = 0; i < cat->sspp_count; i++)
+    for (i = 0; i < cat->sspp_count; i++) {
  msm_disp_snapshot_add_block(disp_state, cat->sspp[i].len, 
dpu_kms->mmio +

  cat->sspp[i].base, cat->sspp[i].name);
+    if (cat->sspp[i].sblk && cat->sspp[i].sblk->scaler_blk.len > 0)
+    msm_disp_snapshot_add_block(disp_state, 
cat->sspp[i].sblk->scaler_blk.len,

+    dpu_kms->mmio + cat->sspp[i].base +
+    cat->sspp[i].sblk->scaler_blk.base, "%s_%s",
+    cat->sspp[i].name,
+    cat->sspp[i].sblk->scaler_blk.name);
+
+    if (cat->sspp[i].sblk && cat->sspp[i].sblk->csc_blk.len > 0)
+    msm_disp_snapshot_add_block(disp_state, 
cat->sspp[i].sblk->csc_blk.len,

+    dpu_kms->mmio + cat->sspp[i].base +
+    cat->sspp[i].sblk->csc_blk.base, "%s_%s",
+    cat->sspp[i].name,
+    cat->sspp[i].sblk->csc_blk.name);
+    }
+
  /* dump LM sub-blocks HW regs info */
  for (i = 0; i < cat->mixer_count; i++)
  msm_disp_snapshot_add_block(disp_state, cat->mixer[i].len, 
dpu_kms->mmio +
@@ -943,9 +976,30 @@ static void dpu_kms_mdp_snapshot(struct 
msm_disp_state *disp_state, struct msm_k

  }
  /* dump DSC sub-blocks HW regs info */
-    for (i = 0; i < cat->dsc_count; i++)
-    msm_disp_snapshot_add_block(disp_state, cat->dsc[i].len, 
dpu_kms->mmio +

-    cat->dsc[i].base, cat->dsc[i].name);
+    for (i = 0; i < cat->dsc_count; i++) {
+    if (cat->dsc[i].features & BIT(DPU_DSC_HW_REV_1_2)) {
+    struct dpu_dsc_blk enc = cat->dsc[i].sblk->enc;
+

[PATCH 11/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys

2023-07-07 Thread Dmitry Baryshkov
Change struct allocation of encoder's phys backend data to use
drmm_kzalloc(). This removes the need to perform any actions on encoder
destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   |  9 
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  8 ---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  | 15 -
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 13 
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 21 ---
 5 files changed, 22 insertions(+), 44 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 493905a5b63a..7c2cd9ce8acd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2199,6 +2199,7 @@ static void dpu_encoder_early_unregister(struct 
drm_encoder *encoder)
 }
 
 static int dpu_encoder_virt_add_phys_encs(
+   struct drm_device *dev,
struct msm_display_info *disp_info,
struct dpu_encoder_virt *dpu_enc,
struct dpu_enc_phys_init_params *params)
@@ -2220,7 +2221,7 @@ static int dpu_encoder_virt_add_phys_encs(
 
 
if (disp_info->intf_type == INTF_WB) {
-   enc = dpu_encoder_phys_wb_init(params);
+   enc = dpu_encoder_phys_wb_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init wb enc: %ld\n",
@@ -2231,7 +2232,7 @@ static int dpu_encoder_virt_add_phys_encs(
dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
++dpu_enc->num_phys_encs;
} else if (disp_info->is_cmd_mode) {
-   enc = dpu_encoder_phys_cmd_init(params);
+   enc = dpu_encoder_phys_cmd_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init cmd enc: %ld\n",
@@ -2242,7 +2243,7 @@ static int dpu_encoder_virt_add_phys_encs(
dpu_enc->phys_encs[dpu_enc->num_phys_encs] = enc;
++dpu_enc->num_phys_encs;
} else {
-   enc = dpu_encoder_phys_vid_init(params);
+   enc = dpu_encoder_phys_vid_init(dev, params);
 
if (IS_ERR(enc)) {
DPU_ERROR_ENC(dpu_enc, "failed to init vid enc: %ld\n",
@@ -2333,7 +2334,7 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
break;
}
 
-   ret = dpu_encoder_virt_add_phys_encs(disp_info,
+   ret = dpu_encoder_virt_add_phys_encs(dpu_kms->dev, disp_info,
dpu_enc, _params);
if (ret) {
DPU_ERROR_ENC(dpu_enc, "failed to add phys encs\n");
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 d48558ede488..4fb0d95f3061 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -281,22 +281,24 @@ struct dpu_encoder_wait_info {
  * @p: Pointer to init params structure
  * Return: Error code or newly allocated encoder
  */
-struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
+struct dpu_encoder_phys *dpu_encoder_phys_vid_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
  * dpu_encoder_phys_cmd_init - Construct a new command mode physical encoder
+ * @dev:  Corresponding device for devres management
  * @p: Pointer to init params structure
  * Return: Error code or newly allocated encoder
  */
-struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
+struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
  * dpu_encoder_phys_wb_init - initialize writeback encoder
+ * @dev:  Corresponding device for devres management
  * @init:  Pointer to init info structure with initialization params
  */
-struct dpu_encoder_phys *dpu_encoder_phys_wb_init(
+struct dpu_encoder_phys *dpu_encoder_phys_wb_init(struct drm_device *dev,
struct dpu_enc_phys_init_params *p);
 
 /**
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
index b856c6286c85..2958b64e6e5e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
@@ -13,6 +13,8 @@
 #include "dpu_trace.h"
 #include "disp/msm_disp_snapshot.h"
 
+#include 
+
 #define DPU_DEBUG_CMDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
(e) && (e)->base.parent ? \
(e)->base.parent->base.id : -1, \
@@ -563,14 +565,6 @@ static void dpu_encoder_phys_cmd_disable(struct 
dpu_encoder_phys *phys_enc)
phys_enc->enable_state = DPU_ENC_DISABLED;
 }
 
-static void dpu_encoder_phys_cmd_destroy(struct dpu_encoder_phys *phys_enc)
-{
-  

[PATCH 13/13] drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt

2023-07-07 Thread Dmitry Baryshkov
It is incorrect to use devm-managed memory allocations for DRM data
structures exposed to userspace. They should use drmm_ allocations.
Change struct dpu_encoder allocation to use drmm_encoder_alloc(). This
removes the need to perform any actions on encoder destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 44 -
 1 file changed, 7 insertions(+), 37 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index b42176ce4a3a..fef66c6cb488 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -443,23 +443,6 @@ int dpu_encoder_get_linecount(struct drm_encoder *drm_enc)
return linecount;
 }
 
-static void dpu_encoder_destroy(struct drm_encoder *drm_enc)
-{
-   struct dpu_encoder_virt *dpu_enc = NULL;
-   int i = 0;
-
-   if (!drm_enc) {
-   DPU_ERROR("invalid encoder\n");
-   return;
-   }
-
-   dpu_enc = to_dpu_encoder_virt(drm_enc);
-   DPU_DEBUG_ENC(dpu_enc, "\n");
-
-   drm_encoder_cleanup(drm_enc);
-   mutex_destroy(_enc->enc_lock);
-}
-
 void dpu_encoder_helper_split_config(
struct dpu_encoder_phys *phys_enc,
enum dpu_intf interface)
@@ -2365,7 +2348,6 @@ static const struct drm_encoder_helper_funcs 
dpu_encoder_helper_funcs = {
 };
 
 static const struct drm_encoder_funcs dpu_encoder_funcs = {
-   .destroy = dpu_encoder_destroy,
.late_register = dpu_encoder_late_register,
.early_unregister = dpu_encoder_early_unregister,
 };
@@ -2376,21 +2358,14 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
 {
struct msm_drm_private *priv = dev->dev_private;
struct dpu_kms *dpu_kms = to_dpu_kms(priv->kms);
-   struct drm_encoder *drm_enc = NULL;
-   struct dpu_encoder_virt *dpu_enc = NULL;
+   struct dpu_encoder_virt *dpu_enc;
int ret = 0;
 
-   dpu_enc = devm_kzalloc(dev->dev, sizeof(*dpu_enc), GFP_KERNEL);
+   dpu_enc = drmm_encoder_alloc(dev, struct dpu_encoder_virt, base,
+_encoder_funcs, drm_enc_mode, NULL);
if (!dpu_enc)
return ERR_PTR(-ENOMEM);
 
-   ret = drm_encoder_init(dev, _enc->base, _encoder_funcs,
-  drm_enc_mode, NULL);
-   if (ret) {
-   devm_kfree(dev->dev, dpu_enc);
-   return ERR_PTR(ret);
-   }
-
drm_encoder_helper_add(_enc->base, _encoder_helper_funcs);
 
spin_lock_init(_enc->enc_spinlock);
@@ -2399,8 +2374,10 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
mutex_init(_enc->rc_lock);
 
ret = dpu_encoder_setup_display(dpu_enc, dpu_kms, disp_info);
-   if (ret)
-   goto fail;
+   if (ret) {
+   DPU_ERROR("failed to setup encoder\n");
+   return ERR_PTR(-ENOMEM);
+   }
 
atomic_set(_enc->frame_done_timeout_ms, 0);
timer_setup(_enc->frame_done_timer,
@@ -2426,13 +2403,6 @@ struct drm_encoder *dpu_encoder_init(struct drm_device 
*dev,
DPU_DEBUG_ENC(dpu_enc, "created\n");
 
return _enc->base;
-
-fail:
-   DPU_ERROR("failed to create encoder\n");
-   if (drm_enc)
-   dpu_encoder_destroy(drm_enc);
-
-   return ERR_PTR(ret);
 }
 
 int dpu_encoder_wait_for_event(struct drm_encoder *drm_enc,
-- 
2.39.2



[PATCH 09/13] drm/msm/dpu: use drmm-managed allocation for dpu_plane

2023-07-07 Thread Dmitry Baryshkov
Change struct dpu_plane allocation to use drmm_universal_plane_alloc().
This removes the need to perform any actions on plane destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 44 +--
 1 file changed, 9 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index f114efee1b57..bbf47151adde 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1170,20 +1170,6 @@ static void dpu_plane_atomic_update(struct drm_plane 
*plane,
}
 }
 
-static void dpu_plane_destroy(struct drm_plane *plane)
-{
-   struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
-
-   DPU_DEBUG_PLANE(pdpu, "\n");
-
-   if (pdpu) {
-   /* this will destroy the states as well */
-   drm_plane_cleanup(plane);
-
-   kfree(pdpu);
-   }
-}
-
 static void dpu_plane_destroy_state(struct drm_plane *plane,
struct drm_plane_state *state)
 {
@@ -1353,7 +1339,6 @@ static bool dpu_plane_format_mod_supported(struct 
drm_plane *plane,
 static const struct drm_plane_funcs dpu_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
-   .destroy = dpu_plane_destroy,
.reset = dpu_plane_reset,
.atomic_duplicate_state = dpu_plane_duplicate_state,
.atomic_destroy_state = dpu_plane_destroy_state,
@@ -1383,33 +1368,26 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
uint32_t supported_rotations;
int ret = -EINVAL;
 
-   /* create and zero local structure */
-   pdpu = kzalloc(sizeof(*pdpu), GFP_KERNEL);
-   if (!pdpu) {
-   DPU_ERROR("[%u]failed to allocate local plane struct\n", pipe);
-   ret = -ENOMEM;
-   return ERR_PTR(ret);
-   }
-
-   /* cache local stuff for later */
-   plane = >base;
-   pdpu->pipe = pipe;
-
/* initialize underlying h/w driver */
pipe_hw = dpu_rm_get_sspp(>rm, pipe);
if (!pipe_hw || !pipe_hw->cap || !pipe_hw->cap->sblk) {
DPU_ERROR("[%u]SSPP is invalid\n", pipe);
-   goto clean_plane;
+   return ERR_CAST(pdpu);
}
 
format_list = pipe_hw->cap->sblk->format_list;
num_formats = pipe_hw->cap->sblk->num_formats;
 
-   ret = drm_universal_plane_init(dev, plane, 0xff, _plane_funcs,
+   pdpu = drmm_universal_plane_alloc(dev, struct dpu_plane, base,
+   0xff, _plane_funcs,
format_list, num_formats,
supported_format_modifiers, type, NULL);
-   if (ret)
-   goto clean_plane;
+   if (IS_ERR(pdpu))
+   return ERR_CAST(pdpu);
+
+   /* cache local stuff for later */
+   plane = >base;
+   pdpu->pipe = pipe;
 
pdpu->catalog = kms->catalog;
 
@@ -1439,8 +1417,4 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
pipe, plane->base.id);
return plane;
-
-clean_plane:
-   kfree(pdpu);
-   return ERR_PTR(ret);
 }
-- 
2.39.2



[PATCH 12/13] drm/msm/dpu: drop dpu_encoder_phys_ops::destroy

2023-07-07 Thread Dmitry Baryshkov
Drop the dpu_encoder_phys_ops' destroy() callback. No phys backend
implements it anymore, so it is useless.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 18 --
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  2 --
 2 files changed, 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 7c2cd9ce8acd..b42176ce4a3a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -456,24 +456,6 @@ static void dpu_encoder_destroy(struct drm_encoder 
*drm_enc)
dpu_enc = to_dpu_encoder_virt(drm_enc);
DPU_DEBUG_ENC(dpu_enc, "\n");
 
-   mutex_lock(_enc->enc_lock);
-
-   for (i = 0; i < dpu_enc->num_phys_encs; i++) {
-   struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
-
-   if (phys->ops.destroy) {
-   phys->ops.destroy(phys);
-   --dpu_enc->num_phys_encs;
-   dpu_enc->phys_encs[i] = NULL;
-   }
-   }
-
-   if (dpu_enc->num_phys_encs)
-   DPU_ERROR_ENC(dpu_enc, "expected 0 num_phys_encs not %d\n",
-   dpu_enc->num_phys_encs);
-   dpu_enc->num_phys_encs = 0;
-   mutex_unlock(_enc->enc_lock);
-
drm_encoder_cleanup(drm_enc);
mutex_destroy(_enc->enc_lock);
 }
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 4fb0d95f3061..757ce58f958b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -72,7 +72,6 @@ struct dpu_encoder_phys;
  * @enable:DRM Call. Enable a DRM mode.
  * @disable:   DRM Call. Disable mode.
  * @atomic_check:  DRM Call. Atomic check new DRM state.
- * @destroy:   DRM Call. Destroy and release resources.
  * @control_vblank_irq Register/Deregister for VBLANK IRQ
  * @wait_for_commit_done:  Wait for hardware to have flushed the
  * current pending frames to hardware
@@ -102,7 +101,6 @@ struct dpu_encoder_phys_ops {
int (*atomic_check)(struct dpu_encoder_phys *encoder,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state);
-   void (*destroy)(struct dpu_encoder_phys *encoder);
int (*control_vblank_irq)(struct dpu_encoder_phys *enc, bool enable);
int (*wait_for_commit_done)(struct dpu_encoder_phys *phys_enc);
int (*wait_for_tx_complete)(struct dpu_encoder_phys *phys_enc);
-- 
2.39.2



[PATCH 07/13] drm/msm/dpu: drop unused dpu_plane::lock

2023-07-07 Thread Dmitry Baryshkov
The field dpu_plane::lock was never used for protecting any kind of
data. Drop it now.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 6 --
 1 file changed, 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index c2aaaded07ed..aba5185e1d66 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -78,8 +78,6 @@ static const uint32_t qcom_compressed_supported_formats[] = {
 struct dpu_plane {
struct drm_plane base;
 
-   struct mutex lock;
-
enum dpu_sspp pipe;
 
uint32_t color_fill;
@@ -1186,8 +1184,6 @@ static void dpu_plane_destroy(struct drm_plane *plane)
if (pstate->r_pipe.sspp)
_dpu_plane_set_qos_ctrl(plane, >r_pipe, false);
 
-   mutex_destroy(>lock);
-
/* this will destroy the states as well */
drm_plane_cleanup(plane);
 
@@ -1447,8 +1443,6 @@ struct drm_plane *dpu_plane_init(struct drm_device *dev,
/* success! finalize initialization */
drm_plane_helper_add(plane, _plane_helper_funcs);
 
-   mutex_init(>lock);
-
DPU_DEBUG("%s created for pipe:%u id:%u\n", plane->name,
pipe, plane->base.id);
return plane;
-- 
2.39.2



[PATCH 10/13] drm/msm/dpu: use drmm-managed allocation for dpu_crtc

2023-07-07 Thread Dmitry Baryshkov
Change struct dpu_crtc allocation to use drmm_crtc_alloc_with_planes().
This removes the need to perform any actions on CRTC destruction.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 21 +
 1 file changed, 5 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 214229d11e3e..23a944e15109 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -51,17 +51,6 @@ static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc 
*crtc)
return to_dpu_kms(priv->kms);
 }
 
-static void dpu_crtc_destroy(struct drm_crtc *crtc)
-{
-   struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
-
-   if (!crtc)
-   return;
-
-   drm_crtc_cleanup(crtc);
-   kfree(dpu_crtc);
-}
-
 static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -1433,7 +1422,6 @@ static int dpu_crtc_late_register(struct drm_crtc *crtc)
 
 static const struct drm_crtc_funcs dpu_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
-   .destroy = dpu_crtc_destroy,
.page_flip = drm_atomic_helper_page_flip,
.reset = dpu_crtc_reset,
.atomic_duplicate_state = dpu_crtc_duplicate_state,
@@ -1467,7 +1455,11 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
struct dpu_crtc *dpu_crtc = NULL;
int i, ret;
 
-   dpu_crtc = kzalloc(sizeof(*dpu_crtc), GFP_KERNEL);
+   dpu_crtc = drmm_crtc_alloc_with_planes(dev, struct dpu_crtc, base,
+  plane, cursor,
+  _crtc_funcs,
+  NULL);
+
if (!dpu_crtc)
return ERR_PTR(-ENOMEM);
 
@@ -1489,9 +1481,6 @@ struct drm_crtc *dpu_crtc_init(struct drm_device *dev, 
struct drm_plane *plane,
dpu_crtc_frame_event_work);
}
 
-   drm_crtc_init_with_planes(dev, crtc, plane, cursor, _crtc_funcs,
-   NULL);
-
drm_crtc_helper_add(crtc, _crtc_helper_funcs);
 
if (dpu_kms->catalog->dspp_count)
-- 
2.39.2



[PATCH 05/13] drm/msm/dpu: use devres-managed allocation for MDP TOP

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create MDP TOP structure. This allows us to remove
corresponding kfree and drop dpu_hw_mdp_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c | 17 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h |  8 +---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c|  5 ++---
 3 files changed, 14 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
index cff48763ce25..481b373d9ccb 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c
@@ -2,6 +2,8 @@
 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_catalog.h"
 #include "dpu_hw_top.h"
@@ -268,16 +270,17 @@ static void _setup_mdp_ops(struct dpu_hw_mdp_ops *ops,
ops->intf_audio_select = dpu_hw_intf_audio_select;
 }
 
-struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg,
-   void __iomem *addr,
-   const struct dpu_mdss_cfg *m)
+struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
+ const struct dpu_mdp_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_cfg *m)
 {
struct dpu_hw_mdp *mdp;
 
if (!addr)
return ERR_PTR(-EINVAL);
 
-   mdp = kzalloc(sizeof(*mdp), GFP_KERNEL);
+   mdp = drmm_kzalloc(dev, sizeof(*mdp), GFP_KERNEL);
if (!mdp)
return ERR_PTR(-ENOMEM);
 
@@ -292,9 +295,3 @@ struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct 
dpu_mdp_cfg *cfg,
 
return mdp;
 }
-
-void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp)
-{
-   kfree(mdp);
-}
-
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
index 8b1463d2b2f0..6f3dc98087df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h
@@ -145,13 +145,15 @@ struct dpu_hw_mdp {
 
 /**
  * dpu_hw_mdptop_init - initializes the top driver for the passed config
+ * @dev:  Corresponding device for devres management
  * @cfg:  MDP TOP configuration from catalog
  * @addr: Mapped register io address of MDP
  * @m:Pointer to mdss catalog data
  */
-struct dpu_hw_mdp *dpu_hw_mdptop_init(const struct dpu_mdp_cfg *cfg,
-   void __iomem *addr,
-   const struct dpu_mdss_cfg *m);
+struct dpu_hw_mdp *dpu_hw_mdptop_init(struct drm_device *dev,
+ const struct dpu_mdp_cfg *cfg,
+ void __iomem *addr,
+ const struct dpu_mdss_cfg *m);
 
 void dpu_hw_mdp_destroy(struct dpu_hw_mdp *mdp);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index f7723f89cbbc..48c3f8b6b88f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -822,8 +822,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 
dpu_kms->catalog = NULL;
 
-   if (dpu_kms->hw_mdp)
-   dpu_hw_mdp_destroy(dpu_kms->hw_mdp);
dpu_kms->hw_mdp = NULL;
 }
 
@@ -1051,7 +1049,8 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
dpu_kms->rm_init = true;
 
-   dpu_kms->hw_mdp = dpu_hw_mdptop_init(dpu_kms->catalog->mdp,
+   dpu_kms->hw_mdp = dpu_hw_mdptop_init(dev,
+dpu_kms->catalog->mdp,
 dpu_kms->mmio,
 dpu_kms->catalog);
if (IS_ERR(dpu_kms->hw_mdp)) {
-- 
2.39.2



[PATCH 08/13] drm/msm/dpu: remove QoS teardown on plane destruction

2023-07-07 Thread Dmitry Baryshkov
There is little point in disabling QoS on plane destruction: it happens
during DPU device destruction process, after which there will be no
running planes.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index aba5185e1d66..f114efee1b57 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1173,17 +1173,10 @@ static void dpu_plane_atomic_update(struct drm_plane 
*plane,
 static void dpu_plane_destroy(struct drm_plane *plane)
 {
struct dpu_plane *pdpu = plane ? to_dpu_plane(plane) : NULL;
-   struct dpu_plane_state *pstate;
 
DPU_DEBUG_PLANE(pdpu, "\n");
 
if (pdpu) {
-   pstate = to_dpu_plane_state(plane->state);
-   _dpu_plane_set_qos_ctrl(plane, >pipe, false);
-
-   if (pstate->r_pipe.sspp)
-   _dpu_plane_set_qos_ctrl(plane, >r_pipe, false);
-
/* this will destroy the states as well */
drm_plane_cleanup(plane);
 
-- 
2.39.2



[PATCH 06/13] drm/msm/dpu: use devres-managed allocation for HW blocks

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create HW block structure. This allows us to remove
corresponding kfree and drop all dpu_hw_*_destroy() functions as well as
dpu_rm_destroy(), which becomes empty afterwards.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c|  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c   | 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 13 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h   |  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |  1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +--
 23 files changed, 119 insertions(+), 238 deletions(-)

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 c278fb9d2b5b..d22e3f11ae34 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -4,6 +4,9 @@
  */
 
 #include 
+
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_kms.h"
@@ -674,14 +677,15 @@ static void _setup_ctl_ops(struct dpu_hw_ctl_ops *ops,
ops->set_active_pipes = dpu_hw_ctl_set_fetch_pipe_active;
 };
 
-struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
-   void __iomem *addr,
-   u32 mixer_count,
-   const struct dpu_lm_cfg *mixer)
+struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
+  const struct dpu_ctl_cfg *cfg,
+  void __iomem *addr,
+  u32 mixer_count,
+  const struct dpu_lm_cfg *mixer)
 {
struct dpu_hw_ctl *c;
 
-   c = kzalloc(sizeof(*c), GFP_KERNEL);
+   c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
 
@@ -696,8 +700,3 @@ struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg 
*cfg,
 
return c;
 }
-
-void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx)
-{
-   kfree(ctx);
-}
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 1c242298ff2e..279ebd8dfbff 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -274,20 +274,16 @@ static inline struct dpu_hw_ctl *to_dpu_hw_ctl(struct 
dpu_hw_blk *hw)
 /**
  * dpu_hw_ctl_init() - Initializes the ctl_path hw driver object.
  * Should be called before accessing any ctl_path register.
+ * @dev:  Corresponding device for devres management
  * @cfg:  ctl_path catalog entry for which driver object is required
  * @addr: mapped register io address of MDP
  * @mixer_count: Number of mixers in @mixer
  * @mixer: Pointer to an array of Layer Mixers defined in the catalog
  */
-struct dpu_hw_ctl *dpu_hw_ctl_init(const struct dpu_ctl_cfg *cfg,
-   void __iomem *addr,
-   u32 mixer_count,
-   const struct dpu_lm_cfg *mixer);
-
-/**
- * dpu_hw_ctl_destroy(): Destroys ctl driver context
- * should be called to free the context
- */
-void dpu_hw_ctl_destroy(struct dpu_hw_ctl *ctx);
+struct dpu_hw_ctl *dpu_hw_ctl_init(struct drm_device *dev,
+  const struct dpu_ctl_cfg *cfg,
+  void __iomem *addr,
+  u32 mixer_count,
+  const struct dpu_lm_cfg *mixer);
 
 #endif /*_DPU_HW_CTL_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
index 509dbaa51d87..5e9aad1b2aa2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -3,6 +3,8 @@
  * Copyright (c) 2020-2022, Linaro Limited
  */
 
+#include 
+
 #include 
 
 #include "dpu_kms.h"
@@ -188,12 +190,13 @@ static void _setup_dsc_ops(struct dpu_hw_dsc_ops *ops,
ops->dsc_bind_pingpong_blk = dpu_hw_dsc_bind_pingpong_blk;
 };
 
-struct dpu_hw_dsc *dpu_hw_dsc_init(const struct dpu_dsc_cfg *cfg,
+struct 

[PATCH 04/13] drm/msm/dpu: use devres-managed allocation for VBIF data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create VBIF data structure. This allows us to
remove corresponding kfree and drop dpu_hw_intr_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h |  8 
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 11 +++
 3 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
index a5121a50b2bb..98e34afde2d2 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c
@@ -2,6 +2,8 @@
 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
+#include 
+
 #include "dpu_hwio.h"
 #include "dpu_hw_catalog.h"
 #include "dpu_hw_vbif.h"
@@ -211,12 +213,13 @@ static void _setup_vbif_ops(struct dpu_hw_vbif_ops *ops,
ops->set_write_gather_en = dpu_hw_set_write_gather_en;
 }
 
-struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
-   void __iomem *addr)
+struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
+const struct dpu_vbif_cfg *cfg,
+void __iomem *addr)
 {
struct dpu_hw_vbif *c;
 
-   c = kzalloc(sizeof(*c), GFP_KERNEL);
+   c = drmm_kzalloc(dev, sizeof(*c), GFP_KERNEL);
if (!c)
return ERR_PTR(-ENOMEM);
 
@@ -234,8 +237,3 @@ struct dpu_hw_vbif *dpu_hw_vbif_init(const struct 
dpu_vbif_cfg *cfg,
 
return c;
 }
-
-void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif)
-{
-   kfree(vbif);
-}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
index 7e10d2a172b4..e2b4307500e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h
@@ -108,12 +108,12 @@ struct dpu_hw_vbif {
 /**
  * dpu_hw_vbif_init() - Initializes the VBIF driver for the passed
  * VBIF catalog entry.
+ * @dev:  Corresponding device for devres management
  * @cfg:  VBIF catalog entry for which driver object is required
  * @addr: Mapped register io address of MDSS
  */
-struct dpu_hw_vbif *dpu_hw_vbif_init(const struct dpu_vbif_cfg *cfg,
-   void __iomem *addr);
-
-void dpu_hw_vbif_destroy(struct dpu_hw_vbif *vbif);
+struct dpu_hw_vbif *dpu_hw_vbif_init(struct drm_device *dev,
+const struct dpu_vbif_cfg *cfg,
+void __iomem *addr);
 
 #endif /*_DPU_HW_VBIF_H */
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index ef232dc838c7..f7723f89cbbc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -812,13 +812,8 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
/* safe to call these more than once during shutdown */
_dpu_kms_mmu_destroy(dpu_kms);
 
-   if (dpu_kms->catalog) {
-   for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
-   if (dpu_kms->hw_vbif[i]) {
-   dpu_hw_vbif_destroy(dpu_kms->hw_vbif[i]);
-   dpu_kms->hw_vbif[i] = NULL;
-   }
-   }
+   for (i = 0; i < ARRAY_SIZE(dpu_kms->hw_vbif); i++) {
+   dpu_kms->hw_vbif[i] = NULL;
}
 
if (dpu_kms->rm_init)
@@ -1070,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
struct dpu_hw_vbif *hw;
const struct dpu_vbif_cfg *vbif = _kms->catalog->vbif[i];
 
-   hw = dpu_hw_vbif_init(vbif, dpu_kms->vbif[vbif->id]);
+   hw = dpu_hw_vbif_init(dev, vbif, dpu_kms->vbif[vbif->id]);
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
-- 
2.39.2



[PATCH 03/13] drm/msm/dpu: use devres-managed allocation for interrupts data

2023-07-07 Thread Dmitry Baryshkov
Use devm_kzalloc to create interrupts data structure. This allows us to
remove corresponding kfree and drop dpu_hw_intr_destroy() function.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  4 +---
 3 files changed, 11 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
index 5e2d68ebb113..945f34736206 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c
@@ -6,6 +6,8 @@
 #include 
 #include 
 
+#include 
+
 #include "dpu_core_irq.h"
 #include "dpu_kms.h"
 #include "dpu_hw_interrupts.h"
@@ -441,8 +443,9 @@ static void __intr_offset(const struct dpu_mdss_cfg *m,
hw->blk_addr = addr + m->mdp[0].base;
 }
 
-struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-   const struct dpu_mdss_cfg *m)
+struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
+void __iomem *addr,
+const struct dpu_mdss_cfg *m)
 {
struct dpu_hw_intr *intr;
int nirq = MDP_INTR_MAX * 32;
@@ -450,7 +453,7 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
if (!addr || !m)
return ERR_PTR(-EINVAL);
 
-   intr = kzalloc(struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
+   intr = drmm_kzalloc(dev, struct_size(intr, irq_tbl, nirq), GFP_KERNEL);
if (!intr)
return ERR_PTR(-ENOMEM);
 
@@ -465,11 +468,6 @@ struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
return intr;
 }
 
-void dpu_hw_intr_destroy(struct dpu_hw_intr *intr)
-{
-   kfree(intr);
-}
-
 int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
void (*irq_cb)(void *arg, int irq_idx),
void *irq_arg)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
index 1f2dabc54c22..b0d7bb073203 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h
@@ -70,15 +70,12 @@ struct dpu_hw_intr {
 
 /**
  * dpu_hw_intr_init(): Initializes the interrupts hw object
+ * @dev:  Corresponding device for devres management
  * @addr: mapped register io address of MDP
  * @m:pointer to MDSS catalog data
  */
-struct dpu_hw_intr *dpu_hw_intr_init(void __iomem *addr,
-   const struct dpu_mdss_cfg *m);
+struct dpu_hw_intr *dpu_hw_intr_init(struct drm_device *dev,
+void __iomem *addr,
+const struct dpu_mdss_cfg *m);
 
-/**
- * dpu_hw_intr_destroy(): Cleanup interrutps hw object
- * @intr: pointer to interrupts hw object
- */
-void dpu_hw_intr_destroy(struct dpu_hw_intr *intr);
 #endif
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 85b8c9cc99ef..ef232dc838c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -807,8 +807,6 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
 {
int i;
 
-   if (dpu_kms->hw_intr)
-   dpu_hw_intr_destroy(dpu_kms->hw_intr);
dpu_kms->hw_intr = NULL;
 
/* safe to call these more than once during shutdown */
@@ -1095,7 +1093,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto err_pm_put;
}
 
-   dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
+   dpu_kms->hw_intr = dpu_hw_intr_init(dev, dpu_kms->mmio, 
dpu_kms->catalog);
if (IS_ERR(dpu_kms->hw_intr)) {
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
-- 
2.39.2



[PATCH 01/13] drm/msm/dpu: cleanup dpu_kms_hw_init error path

2023-07-07 Thread Dmitry Baryshkov
It was noticed that dpu_kms_hw_init()'s error path contains several
labels which point to the same code path. Replace all of them with a
single label.

Suggested-by: Konrad Dybcio 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 21 +
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index c11b3ab572ab..e7ac02e92f42 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1037,7 +1037,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (!dpu_kms->catalog) {
DPU_ERROR("device config not known!\n");
rc = -EINVAL;
-   goto power_error;
+   goto err_pm_put;
}
 
/*
@@ -1047,13 +1047,13 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_mmu_init(dpu_kms);
if (rc) {
DPU_ERROR("dpu_kms_mmu_init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
 
rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio);
if (rc) {
DPU_ERROR("rm init failed: %d\n", rc);
-   goto power_error;
+   goto err_pm_put;
}
 
dpu_kms->rm_init = true;
@@ -1065,7 +1065,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_mdp);
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
dpu_kms->hw_mdp = NULL;
-   goto power_error;
+   goto err_pm_put;
}
 
for (i = 0; i < dpu_kms->catalog->vbif_count; i++) {
@@ -1076,7 +1076,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
if (IS_ERR(hw)) {
rc = PTR_ERR(hw);
DPU_ERROR("failed to init vbif %d: %d\n", vbif->id, rc);
-   goto power_error;
+   goto err_pm_put;
}
 
dpu_kms->hw_vbif[vbif->id] = hw;
@@ -1092,7 +1092,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, 
max_core_clk_rate);
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
-   goto perf_err;
+   goto err_pm_put;
}
 
dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
@@ -1100,7 +1100,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
dpu_kms->hw_intr = NULL;
-   goto hw_intr_init_err;
+   goto err_pm_put;
}
 
dev->mode_config.min_width = 0;
@@ -1125,7 +1125,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
rc = _dpu_kms_drm_obj_init(dpu_kms);
if (rc) {
DPU_ERROR("modeset init failed: %d\n", rc);
-   goto drm_obj_init_err;
+   goto err_pm_put;
}
 
dpu_vbif_init_memtypes(dpu_kms);
@@ -1134,10 +1134,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
return 0;
 
-drm_obj_init_err:
-hw_intr_init_err:
-perf_err:
-power_error:
+err_pm_put:
pm_runtime_put_sync(_kms->pdev->dev);
 error:
_dpu_kms_hw_destroy(dpu_kms);
-- 
2.39.2



[PATCH 02/13] drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error handling

2023-07-07 Thread Dmitry Baryshkov
Using IS_ERR_OR_NULL() together with PTR_ERR() is a typical mistake. If
the value is NULL, then the function will return 0 instead of a proper
return code. Replace IS_ERR_OR_NULL() with IS_ERR() in the
dpu_hw_intr_init() error check.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index e7ac02e92f42..85b8c9cc99ef 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1096,7 +1096,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
}
 
dpu_kms->hw_intr = dpu_hw_intr_init(dpu_kms->mmio, dpu_kms->catalog);
-   if (IS_ERR_OR_NULL(dpu_kms->hw_intr)) {
+   if (IS_ERR(dpu_kms->hw_intr)) {
rc = PTR_ERR(dpu_kms->hw_intr);
DPU_ERROR("hw_intr init failed: %d\n", rc);
dpu_kms->hw_intr = NULL;
-- 
2.39.2



[PATCH 00/13] drm/msm/dpu: use managed memory allocations

2023-07-07 Thread Dmitry Baryshkov
In a lots of places in DPU driver memory is allocated by using the
kzalloc and then manually freed using kfree. However thes memory chunks
have a well-defined life cycle. They are either a part of the driver's
runtime and can be devm_kzalloc'ed or are exposed to userspace via the
DRM objects and thus can be drmm_alloc'ed. Implement corresponding
runtime resource manangement for the DPU driver.

Dependencies: [1].

[1] https://patchwork.freedesktop.org/series/118839/

Dmitry Baryshkov (13):
  drm/msm/dpu: cleanup dpu_kms_hw_init error path
  drm/msm/dpu: remove IS_ERR_OR_NULL for dpu_hw_intr_init() error
handling
  drm/msm/dpu: use devres-managed allocation for interrupts data
  drm/msm/dpu: use devres-managed allocation for VBIF data
  drm/msm/dpu: use devres-managed allocation for MDP TOP
  drm/msm/dpu: use devres-managed allocation for HW blocks
  drm/msm/dpu: drop unused dpu_plane::lock
  drm/msm/dpu: remove QoS teardown on plane destruction
  drm/msm/dpu: use drmm-managed allocation for dpu_plane
  drm/msm/dpu: use drmm-managed allocation for dpu_crtc
  drm/msm/dpu: use drmm-managed allocation for dpu_encoder_phys
  drm/msm/dpu: drop dpu_encoder_phys_ops::destroy
  drm/msm/dpu: use drmm-managed allocation for dpu_encoder_virt

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  | 21 ++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 71 +++
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  | 10 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  | 15 +---
 .../drm/msm/disp/dpu1/dpu_encoder_phys_vid.c  | 13 +--
 .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 21 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c| 19 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h| 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 12 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h| 10 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_dsc_1_2.c|  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.c   | 16 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dspp.h   | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 11 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h   | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.h | 12 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.c| 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_merge3d.h| 13 +--
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 14 ++-
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 13 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 15 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h   |  7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.c| 17 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_top.h|  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.c   | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_vbif.h   |  8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 14 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 12 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 51 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |  1 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 57 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 90 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h| 11 +--
 36 files changed, 210 insertions(+), 470 deletions(-)

-- 
2.39.2



Re: [PATCH v3] drm/virtio: conditionally allocate virtio_gpu_fence

2023-07-07 Thread Dmitry Osipenko
On 7/7/23 20:59, Gurchetan Singh wrote:
///
>>> Previously, when VIRTGPU_EXECBUF_RING_IDX flag wasn't specified, the
>>> fence event was created for a default ring_idx=0. Now you changed this
>>> behaviour and event will never be created without
>>> VIRTGPU_EXECBUF_RING_IDX flag being set.
> 
> ring_idx = 0 is fine, but without VIRTGPU_EXECBUF_RING_IDX that means
> the global timeline.
> 
> It's an additional check for where the userspace specifies they want
> to use per-context fencing and polling, but actually uses the global
> timeline.  Userspace never does this since it wouldn't work, so it's a
> bit of a pathological edge case check than any UAPI change.
> 
>>>
>>> Could you please point me at the corresponding userspace code that polls
>>> DRM FD fence event?
> 
> https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools/sommelier/virtualization/virtgpu_channel.cc#216
> 
> Used with the following flow:
> 
> https://crosvm.dev/book/devices/wayland.html
> 
> If you wish to test, please do apply this change:
> 
> https://chromium-review.googlesource.com/c/chromiumos/platform2/+/4605854

Thanks for the links! I tested v2 with sommelier, though wasn't aware
about CL4605854 and alternatives to sommelier

>>> It's unclear whether there is a possible userspace regression here or
>>> not. If there is no regression, then in general such behavioural changes
>>> should be done in a separate commit having detailed description
>>> explaining why behaviour changes.
> 
> Sommelier isn't formally packaged yet in the Linux distro style and it
> always specifies RING_IDX when polling, so no regressions here.  Maybe
> a separate commit is overkill (since the 2nd commit would delete the
> newly added checks), what about just more detail in the commit
> message?

More detail will be fine

>> I see that venus does the polling and ring_idx_mask is a
>> context-specific param, hence it's irrelevant to a generic ctx 0. Still
>> it's now necessary to specify the EXECBUF_RING_IDX flag even if ctx has
>> one ring, which is UAPI change.
> 
> It doesn't seem like venus enables POLL_RINGS_MASK to poll since that
> param is zero?
> 
> https://gitlab.freedesktop.org/mesa/mesa/-/blob/main/src/virtio/vulkan/vn_renderer_virtgpu.c#L617

Indeed, good catch

-- 
Best regards,
Dmitry



[PATCH v3 08/11] drm/msm/dpu: remove unused fields from struct dpu_core_perf

2023-07-07 Thread Dmitry Baryshkov
Remove dpu_core_perf::dev and dpu_core_perf::debugfs_root fields, they
are not used by the code.

Reviewed-by: Konrad Dybcio 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 3 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h | 6 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 2 +-
 3 files changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 8db97583ef18..afd75750380c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -497,15 +497,12 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf)
 
perf->max_core_clk_rate = 0;
perf->core_clk = NULL;
-   perf->dev = NULL;
 }
 
 int dpu_core_perf_init(struct dpu_core_perf *perf,
-   struct drm_device *dev,
const struct dpu_perf_cfg *perf_cfg,
struct clk *core_clk)
 {
-   perf->dev = dev;
perf->perf_cfg = perf_cfg;
perf->core_clk = core_clk;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index f4b84e67138c..e718d523ff30 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -36,8 +36,6 @@ struct dpu_core_perf_tune {
 
 /**
  * struct dpu_core_perf - definition of core performance context
- * @dev: Pointer to drm device
- * @debugfs_root: top level debug folder
  * @perf_cfg: Platform-specific performance configuration
  * @core_clk: Pointer to the core clock
  * @core_clk_rate: current core clock rate
@@ -49,8 +47,6 @@ struct dpu_core_perf_tune {
  * @fix_core_ab_vote: fixed core ab vote in bps used in mode 2
  */
 struct dpu_core_perf {
-   struct drm_device *dev;
-   struct dentry *debugfs_root;
const struct dpu_perf_cfg *perf_cfg;
struct clk *core_clk;
u64 core_clk_rate;
@@ -95,12 +91,10 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf);
 /**
  * dpu_core_perf_init - initialize the given core performance context
  * @perf: Pointer to core performance context
- * @dev: Pointer to drm device
  * @perf_cfg: Pointer to platform performance configuration
  * @core_clk: pointer to core clock
  */
 int dpu_core_perf_init(struct dpu_core_perf *perf,
-   struct drm_device *dev,
const struct dpu_perf_cfg *perf_cfg,
struct clk *core_clk);
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 6e62606e32de..631b6b679bae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1115,7 +1115,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_kms->hw_vbif[vbif->id] = hw;
}
 
-   rc = dpu_core_perf_init(_kms->perf, dev, dpu_kms->catalog->perf,
+   rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf,
msm_clk_bulk_get_clock(dpu_kms->clocks, 
dpu_kms->num_clocks, "core"));
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
-- 
2.39.2



[PATCH v3 09/11] drm/msm/dpu: core_perf: remove extra clk_round_rate() call

2023-07-07 Thread Dmitry Baryshkov
The dev_pm_opp_set_rate() already contains a call for clk_round_rate for
the passed value. Stop calling it manually from
_dpu_core_perf_get_core_clk_rate(). It is slightly incorrect to call it
this way, as we should round the final calculated clock rate rather than
rounding all the intermediate values.

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index afd75750380c..a570810c9254 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -299,8 +299,6 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms 
*kms)
dpu_cstate = to_dpu_crtc_state(crtc->state);
clk_rate = max(dpu_cstate->new_perf.core_clk_rate,
clk_rate);
-   clk_rate = clk_round_rate(kms->perf.core_clk,
-   clk_rate);
}
}
 
-- 
2.39.2



[PATCH v3 11/11] drm/msm/dpu: drop dpu_core_perf_destroy()

2023-07-07 Thread Dmitry Baryshkov
This function does nothing, just clears one struct field. Drop it now.

Acked-by: Konrad Dybcio 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 10 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h |  6 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  1 -
 3 files changed, 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index e9d71c0855df..adb932b0f49c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -486,16 +486,6 @@ int dpu_core_perf_debugfs_init(struct dpu_kms *dpu_kms, 
struct dentry *parent)
 }
 #endif
 
-void dpu_core_perf_destroy(struct dpu_core_perf *perf)
-{
-   if (!perf) {
-   DPU_ERROR("invalid parameters\n");
-   return;
-   }
-
-   perf->max_core_clk_rate = 0;
-}
-
 int dpu_core_perf_init(struct dpu_core_perf *perf,
const struct dpu_perf_cfg *perf_cfg,
unsigned long max_core_clk_rate)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index 8cc55752db5e..4186977390bd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -78,12 +78,6 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
  */
 void dpu_core_perf_crtc_release_bw(struct drm_crtc *crtc);
 
-/**
- * dpu_core_perf_destroy - destroy the given core performance context
- * @perf: Pointer to core performance context
- */
-void dpu_core_perf_destroy(struct dpu_core_perf *perf);
-
 /**
  * dpu_core_perf_init - initialize the given core performance context
  * @perf: Pointer to core performance context
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index f01b2278c01a..44b0daf70c4e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1171,7 +1171,6 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
return 0;
 
 drm_obj_init_err:
-   dpu_core_perf_destroy(_kms->perf);
 hw_intr_init_err:
 perf_err:
 power_error:
-- 
2.39.2



[PATCH v3 10/11] drm/msm/dpu: move max clock decision to dpu_kms.

2023-07-07 Thread Dmitry Baryshkov
dpu_core_perf should not make decisions on the maximum possible core
clock rate. Pass the value from dpu_kms_hw_init().

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 11 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h |  8 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   | 13 +++--
 3 files changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index a570810c9254..e9d71c0855df 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -494,21 +494,14 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf)
}
 
perf->max_core_clk_rate = 0;
-   perf->core_clk = NULL;
 }
 
 int dpu_core_perf_init(struct dpu_core_perf *perf,
const struct dpu_perf_cfg *perf_cfg,
-   struct clk *core_clk)
+   unsigned long max_core_clk_rate)
 {
perf->perf_cfg = perf_cfg;
-   perf->core_clk = core_clk;
-
-   perf->max_core_clk_rate = clk_get_rate(core_clk);
-   if (!perf->max_core_clk_rate) {
-   DPU_DEBUG("optional max core clk rate, use default\n");
-   perf->max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE;
-   }
+   perf->max_core_clk_rate = max_core_clk_rate;
 
return 0;
 }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index e718d523ff30..8cc55752db5e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -12,8 +12,6 @@
 
 #include "dpu_hw_catalog.h"
 
-#defineDPU_PERF_DEFAULT_MAX_CORE_CLK_RATE  41250
-
 /**
  * struct dpu_core_perf_params - definition of performance parameters
  * @max_per_pipe_ib: maximum instantaneous bandwidth request
@@ -37,7 +35,6 @@ struct dpu_core_perf_tune {
 /**
  * struct dpu_core_perf - definition of core performance context
  * @perf_cfg: Platform-specific performance configuration
- * @core_clk: Pointer to the core clock
  * @core_clk_rate: current core clock rate
  * @max_core_clk_rate: maximum allowable core clock rate
  * @perf_tune: debug control for performance tuning
@@ -48,7 +45,6 @@ struct dpu_core_perf_tune {
  */
 struct dpu_core_perf {
const struct dpu_perf_cfg *perf_cfg;
-   struct clk *core_clk;
u64 core_clk_rate;
u64 max_core_clk_rate;
struct dpu_core_perf_tune perf_tune;
@@ -92,11 +88,11 @@ void dpu_core_perf_destroy(struct dpu_core_perf *perf);
  * dpu_core_perf_init - initialize the given core performance context
  * @perf: Pointer to core performance context
  * @perf_cfg: Pointer to platform performance configuration
- * @core_clk: pointer to core clock
+ * @max_core_clk_rate: Maximum core clock rate
  */
 int dpu_core_perf_init(struct dpu_core_perf *perf,
const struct dpu_perf_cfg *perf_cfg,
-   struct clk *core_clk);
+   unsigned long max_core_clk_rate);
 
 struct dpu_kms;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 631b6b679bae..f01b2278c01a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1011,11 +1011,14 @@ unsigned long dpu_kms_get_clk_rate(struct dpu_kms 
*dpu_kms, char *clock_name)
return clk_get_rate(clk);
 }
 
+#defineDPU_PERF_DEFAULT_MAX_CORE_CLK_RATE  41250
+
 static int dpu_kms_hw_init(struct msm_kms *kms)
 {
struct dpu_kms *dpu_kms;
struct drm_device *dev;
int i, rc = -EINVAL;
+   unsigned long max_core_clk_rate;
u32 core_rev;
 
if (!kms) {
@@ -1115,8 +1118,14 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
dpu_kms->hw_vbif[vbif->id] = hw;
}
 
-   rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf,
-   msm_clk_bulk_get_clock(dpu_kms->clocks, 
dpu_kms->num_clocks, "core"));
+   /* TODO: use the same max_freq as in dpu_kms_hw_init */
+   max_core_clk_rate = dpu_kms_get_clk_rate(dpu_kms, "core");
+   if (!max_core_clk_rate) {
+   DPU_DEBUG("max core clk rate not determined, using default\n");
+   max_core_clk_rate = DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE;
+   }
+
+   rc = dpu_core_perf_init(_kms->perf, dpu_kms->catalog->perf, 
max_core_clk_rate);
if (rc) {
DPU_ERROR("failed to init perf %d\n", rc);
goto perf_err;
-- 
2.39.2



[PATCH v3 06/11] drm/msm/dpu: drop the dpu_core_perf_crtc_update()'s stop_req param

2023-07-07 Thread Dmitry Baryshkov
The stop_req is true only in the dpu_crtc_disable() case, when
crtc->enable has already been set to false. This renders the stop_req
argument useless. Remove it completely.

Reviewed-by: Abhinav Kumar 
Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 12 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h |  3 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |  6 +++---
 3 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 87bf4e5cb8e7..df1e47282777 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -315,7 +315,7 @@ static u64 _dpu_core_perf_get_core_clk_rate(struct dpu_kms 
*kms)
 }
 
 int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
-   int params_changed, bool stop_req)
+ int params_changed)
 {
struct dpu_core_perf_params *new, *old;
bool update_bus = false, update_clk = false;
@@ -339,13 +339,13 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
dpu_crtc = to_dpu_crtc(crtc);
dpu_cstate = to_dpu_crtc_state(crtc->state);
 
-   DRM_DEBUG_ATOMIC("crtc:%d stop_req:%d core_clk:%llu\n",
-   crtc->base.id, stop_req, kms->perf.core_clk_rate);
+   DRM_DEBUG_ATOMIC("crtc:%d enabled:%d core_clk:%llu\n",
+   crtc->base.id, crtc->enabled, kms->perf.core_clk_rate);
 
old = _crtc->cur_perf;
new = _cstate->new_perf;
 
-   if (crtc->enabled && !stop_req) {
+   if (crtc->enabled) {
/*
 * cases for bus bandwidth update.
 * 1. new bandwidth vote - "ab or ib vote" is higher
@@ -378,7 +378,7 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
}
 
trace_dpu_perf_crtc_update(crtc->base.id, new->bw_ctl,
-   new->core_clk_rate, stop_req, update_bus, update_clk);
+   new->core_clk_rate, !crtc->enabled, update_bus, update_clk);
 
if (update_bus) {
ret = _dpu_core_perf_crtc_update_bus(kms, crtc);
@@ -398,7 +398,7 @@ int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
 
DRM_DEBUG_ATOMIC("clk:%llu\n", clk_rate);
 
-   trace_dpu_core_perf_update_clk(kms->dev, stop_req, clk_rate);
+   trace_dpu_core_perf_update_clk(kms->dev, !crtc->enabled, 
clk_rate);
 
clk_rate = min(clk_rate, kms->perf.max_core_clk_rate);
ret = dev_pm_opp_set_rate(>pdev->dev, clk_rate);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
index c965dfbc3007..c0097b67f9dd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
@@ -75,11 +75,10 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
  * dpu_core_perf_crtc_update - update performance of the given crtc
  * @crtc: Pointer to crtc
  * @params_changed: true if crtc parameters are modified
- * @stop_req: true if this is a stop request
  * return: zero if success, or error code otherwise
  */
 int dpu_core_perf_crtc_update(struct drm_crtc *crtc,
-   int params_changed, bool stop_req);
+ int params_changed);
 
 /**
  * dpu_core_perf_crtc_release_bw - release bandwidth of the given crtc
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 1edf2b6b0a26..8ce7586e2ddf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -718,7 +718,7 @@ static void dpu_crtc_frame_event_cb(void *data, u32 event)
 void dpu_crtc_complete_commit(struct drm_crtc *crtc)
 {
trace_dpu_crtc_complete_commit(DRMID(crtc));
-   dpu_core_perf_crtc_update(crtc, 0, false);
+   dpu_core_perf_crtc_update(crtc, 0);
_dpu_crtc_complete_flip(crtc);
 }
 
@@ -884,7 +884,7 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
return;
 
/* update performance setting before crtc kickoff */
-   dpu_core_perf_crtc_update(crtc, 1, false);
+   dpu_core_perf_crtc_update(crtc, 1);
 
/*
 * Final plane updates: Give each plane a chance to complete all
@@ -1100,7 +1100,7 @@ static void dpu_crtc_disable(struct drm_crtc *crtc,
atomic_set(_crtc->frame_pending, 0);
}
 
-   dpu_core_perf_crtc_update(crtc, 0, true);
+   dpu_core_perf_crtc_update(crtc, 0);
 
drm_for_each_encoder_mask(encoder, crtc->dev, crtc->state->encoder_mask)
dpu_encoder_register_frame_event_callback(encoder, NULL, NULL);
-- 
2.39.2



[PATCH v3 02/11] drm/msm/dpu: core_perf: extract bandwidth aggregation function

2023-07-07 Thread Dmitry Baryshkov
In preparation to refactoring the dpu_core_perf debugfs interface,
extract the bandwidth aggregation function from
_dpu_core_perf_crtc_update_bus().

Signed-off-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c | 39 +++
 1 file changed, 22 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
index 1d9d83d7b99e..333dcfe57800 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c
@@ -206,33 +206,38 @@ int dpu_core_perf_crtc_check(struct drm_crtc *crtc,
return 0;
 }
 
-static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
-   struct drm_crtc *crtc)
+static void dpu_core_perf_aggregate(struct drm_device *ddev,
+   enum dpu_crtc_client_type curr_client_type,
+   struct dpu_core_perf_params *perf)
 {
-   struct dpu_core_perf_params perf = { 0 };
-   enum dpu_crtc_client_type curr_client_type
-   = dpu_crtc_get_client_type(crtc);
-   struct drm_crtc *tmp_crtc;
struct dpu_crtc_state *dpu_cstate;
-   int i, ret = 0;
-   u64 avg_bw;
+   struct drm_crtc *tmp_crtc;
 
-   drm_for_each_crtc(tmp_crtc, crtc->dev) {
+   drm_for_each_crtc(tmp_crtc, ddev) {
if (tmp_crtc->enabled &&
-   curr_client_type ==
-   dpu_crtc_get_client_type(tmp_crtc)) {
+   curr_client_type == dpu_crtc_get_client_type(tmp_crtc)) {
dpu_cstate = to_dpu_crtc_state(tmp_crtc->state);
 
-   perf.max_per_pipe_ib = max(perf.max_per_pipe_ib,
-   dpu_cstate->new_perf.max_per_pipe_ib);
+   perf->max_per_pipe_ib = max(perf->max_per_pipe_ib,
+   
dpu_cstate->new_perf.max_per_pipe_ib);
 
-   perf.bw_ctl += dpu_cstate->new_perf.bw_ctl;
+   perf->bw_ctl += dpu_cstate->new_perf.bw_ctl;
 
-   DRM_DEBUG_ATOMIC("crtc=%d bw=%llu paths:%d\n",
- tmp_crtc->base.id,
- dpu_cstate->new_perf.bw_ctl, kms->num_paths);
+   DRM_DEBUG_ATOMIC("crtc=%d bw=%llu\n",
+tmp_crtc->base.id,
+dpu_cstate->new_perf.bw_ctl);
}
}
+}
+
+static int _dpu_core_perf_crtc_update_bus(struct dpu_kms *kms,
+   struct drm_crtc *crtc)
+{
+   struct dpu_core_perf_params perf = { 0 };
+   int i, ret = 0;
+   u64 avg_bw;
+
+   dpu_core_perf_aggregate(crtc->dev, dpu_crtc_get_client_type(crtc), 
);
 
if (!kms->num_paths)
return 0;
-- 
2.39.2



  1   2   3   >