Re: [Freedreno] [PATCH v3 6/7] drm/msm/dsi: Add phy configuration for MSM8226

2023-06-07 Thread Jeykumar Sankaran




On 6/1/2023 10:00 AM, Luca Weiss wrote:

MSM8226 uses a modified PLL lock sequence compared to MSM8974, which is
based on the function dsi_pll_enable_seq_m in the msm-3.10 kernel.

Worth noting that the msm-3.10 downstream kernel also will try other
sequences in case this one doesn't work, but during testing it has shown
that the _m sequence succeeds first time also:

   .pll_enable_seqs[0] = dsi_pll_enable_seq_m,
   .pll_enable_seqs[1] = dsi_pll_enable_seq_m,
   .pll_enable_seqs[2] = dsi_pll_enable_seq_d,
   .pll_enable_seqs[3] = dsi_pll_enable_seq_d,
   .pll_enable_seqs[4] = dsi_pll_enable_seq_f1,
   .pll_enable_seqs[5] = dsi_pll_enable_seq_c,
   .pll_enable_seqs[6] = dsi_pll_enable_seq_e,

We may need to expand this in the future.

Signed-off-by: Luca Weiss 
---
  drivers/gpu/drm/msm/dsi/phy/dsi_phy.c  |  2 +
  drivers/gpu/drm/msm/dsi/phy/dsi_phy.h  |  3 +-
  drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c | 97 ++
  3 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
index bb09cbe8ff86..9d5795c58a98 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c
@@ -541,6 +541,8 @@ static const struct of_device_id dsi_phy_dt_match[] = {
  .data = _phy_28nm_hpm_famb_cfgs },
{ .compatible = "qcom,dsi-phy-28nm-lp",
  .data = _phy_28nm_lp_cfgs },
+   { .compatible = "qcom,dsi-phy-28nm-8226",
+ .data = _phy_28nm_8226_cfgs },
  #endif
  #ifdef CONFIG_DRM_MSM_DSI_20NM_PHY
{ .compatible = "qcom,dsi-phy-20nm",
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
index 7137a17ae523..8b640d174785 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.h
@@ -46,8 +46,9 @@ struct msm_dsi_phy_cfg {
  extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_famb_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
-extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8226_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_14nm_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_14nm_660_cfgs;
  extern const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs;
diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c 
b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
index 4c1bf55c5f38..ceec7bb87bf1 100644
--- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
+++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm.c
@@ -37,6 +37,7 @@
  
  /* v2.0.0 28nm LP implementation */

  #define DSI_PHY_28NM_QUIRK_PHY_LP BIT(0)
+#define DSI_PHY_28NM_QUIRK_PHY_8226BIT(1)
  
  #define LPFR_LUT_SIZE			10

  struct lpfr_cfg {
@@ -377,6 +378,74 @@ static int dsi_pll_28nm_vco_prepare_hpm(struct clk_hw *hw)
return ret;
  }
  
+static int dsi_pll_28nm_vco_prepare_8226(struct clk_hw *hw)

+{
+   struct dsi_pll_28nm *pll_28nm = to_pll_28nm(hw);
+   struct device *dev = _28nm->phy->pdev->dev;
+   void __iomem *base = pll_28nm->phy->pll_base;
+   u32 max_reads = 5, timeout_us = 100;
+   bool locked;
+   u32 val;
+   int i;
+
+   DBG("id=%d", pll_28nm->phy->id);
+
+   pll_28nm_software_reset(pll_28nm);
+
+   /*
+* PLL power up sequence.
+* Add necessary delays recommended by hardware.
+*/
+   dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34);
+
+   val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+   dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+   val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+   dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+   val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+   val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+   dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+
+   for (i = 0; i < 7; i++) {
+   /* DSI Uniphy lock detect setting */
+   dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+   dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
+   0x0c, 100);
+   dsi_phy_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+   /* poll for PLL ready status */
+   locked = pll_28nm_poll_for_ready(pll_28nm,
+   max_reads, timeout_us);
+   if (locked)
+   break;
+
+   pll_28nm_software_reset(pll_28nm);
+
+   /*
+* PLL power up sequence.
+* Add necessary delays recommended by hardware.
+*/
+   dsi_phy_write_udelay(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 
0x00, 50);
+

Re: [Freedreno] [PATCH v3 4/7] drm/msm/mdp5: Add MDP5 configuration for MSM8226

2023-06-07 Thread Jeykumar Sankaran




On 6/1/2023 10:00 AM, Luca Weiss wrote:

Add the required config for the v1.1 MDP5 found on MSM8226.

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Luca Weiss 
---
  drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c | 82 
  1 file changed, 82 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c 
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
index 2eec2d78f32a..694d54341337 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cfg.c
@@ -103,6 +103,87 @@ static const struct mdp5_cfg_hw msm8x74v1_config = {
.max_clk = 2,
  };
  
+static const struct mdp5_cfg_hw msm8x26_config = {

+   .name = "msm8x26",
+   .mdp = {
+   .count = 1,
+   .caps = MDP_CAP_SMP |
+   0,
+   },
+   .smp = {
+   .mmb_count = 7,
+   .mmb_size = 4096,
+   .clients = {
+   [SSPP_VIG0] =  1,
+   [SSPP_DMA0] = 4,
+   [SSPP_RGB0] = 7,
+   },
+   },
+   .ctl = {
+   .count = 2,
+   .base = { 0x00500, 0x00600 },
+   .flush_hw_mask = 0x0003,
+   },
+   .pipe_vig = {
+   .count = 1,
+   .base = { 0x01100 },
+   .caps = MDP_PIPE_CAP_HFLIP |
+   MDP_PIPE_CAP_VFLIP |
+   MDP_PIPE_CAP_SCALE |
+   MDP_PIPE_CAP_CSC   |
+   0,
+   },
+   .pipe_rgb = {
+   .count = 1,
+   .base = { 0x01d00 },
+   .caps = MDP_PIPE_CAP_HFLIP |
+   MDP_PIPE_CAP_VFLIP |
+   MDP_PIPE_CAP_SCALE |
+   0,
+   },
+   .pipe_dma = {
+   .count = 1,
+   .base = { 0x02900 },
+   .caps = MDP_PIPE_CAP_HFLIP |
+   MDP_PIPE_CAP_VFLIP |
+   0,
+   },
+   .lm = {
+   .count = 2,
+   .base = { 0x03100, 0x03d00 },
+   .instances = {
+   { .id = 0, .pp = 0, .dspp = 0,
+ .caps = MDP_LM_CAP_DISPLAY, },
+   { .id = 1, .pp = -1, .dspp = -1,
+ .caps = MDP_LM_CAP_WB },
+},
+   .nb_stages = 2,
+   .max_width = 2048,
+   .max_height = 0x,
+   },
+   .dspp = {
+   .count = 1,
+   .base = { 0x04500 },
+   },
+   .pp = {
+   .count = 1,
+   .base = { 0x21a00 },
+   },
+   .intf = {
+   .base = { 0x0, 0x21200 },
+   .connect = {
+   [0] = INTF_DISABLED,
+   [1] = INTF_DSI,
+   },
+   },
+   .perf = {
+   .ab_inefficiency = 100,
+   .ib_inefficiency = 200,
+   .clk_inefficiency = 125
+   },
+   .max_clk = 2,
+};
+
  static const struct mdp5_cfg_hw msm8x74v2_config = {
.name = "msm8x74",
.mdp = {
@@ -1236,6 +1317,7 @@ static const struct mdp5_cfg_hw sdm660_config = {
  
  static const struct mdp5_cfg_handler cfg_handlers_v1[] = {

{ .revision = 0, .config = { .hw = _config } },
+   { .revision = 1, .config = { .hw = _config } },
{ .revision = 2, .config = { .hw = _config } },
{ .revision = 3, .config = { .hw = _config } },
{ .revision = 6, .config = { .hw = _config } },


Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v3 5/7] drm/msm/dsi: Add configuration for MSM8226

2023-06-07 Thread Jeykumar Sankaran




On 6/1/2023 10:00 AM, Luca Weiss wrote:

Add the config for the v1.0.2 DSI found on MSM8226. We can reuse
existing bits from other revisions that are identical for v1.0.2.

Reviewed-by: Dmitry Baryshkov 
Reviewed-by: Konrad Dybcio 
Signed-off-by: Luca Weiss 
---
  drivers/gpu/drm/msm/dsi/dsi_cfg.c | 2 ++
  drivers/gpu/drm/msm/dsi/dsi_cfg.h | 1 +
  2 files changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
index 29ccd755cc2e..8a5fb6df7210 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c
@@ -245,6 +245,8 @@ static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] 
= {
_dsi_cfg, _dsi_v2_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
_apq8084_dsi_cfg, _dsi_6g_host_ops},
+   {MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0_2,
+   _apq8084_dsi_cfg, _dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
_apq8084_dsi_cfg, _dsi_6g_host_ops},
{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1_1,
diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.h 
b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
index 91bdaf50bb1a..43f0dd74edb6 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_cfg.h
+++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.h
@@ -11,6 +11,7 @@
  #define MSM_DSI_VER_MAJOR_V2  0x02
  #define MSM_DSI_VER_MAJOR_6G  0x03
  #define MSM_DSI_6G_VER_MINOR_V1_0 0x1000
+#define MSM_DSI_6G_VER_MINOR_V1_0_20x1002
  #define MSM_DSI_6G_VER_MINOR_V1_1 0x1001
  #define MSM_DSI_6G_VER_MINOR_V1_1_1   0x10010001
  #define MSM_DSI_6G_VER_MINOR_V1_2 0x1002


Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 3/6] drm/msm/dpu: split interrupt address arrays

2023-05-26 Thread Jeykumar Sankaran




On 5/22/2023 2:45 PM, Dmitry Baryshkov wrote:

There is no point in having a single enum (and a single array) for both
DPU < 7.0 and DPU >= 7.0 interrupt registers. Instead define a single
enum and two IRQ address arrays.

Signed-off-by: Dmitry Baryshkov 
---
  .../msm/disp/dpu1/catalog/dpu_7_0_sm8350.h|  1 +
  .../msm/disp/dpu1/catalog/dpu_7_2_sc7280.h|  1 +
  .../msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h  |  1 +
  .../msm/disp/dpu1/catalog/dpu_8_1_sm8450.h|  1 +
  .../msm/disp/dpu1/catalog/dpu_9_0_sm8550.h|  1 +
  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  2 +
  .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.c | 82 +--
  .../gpu/drm/msm/disp/dpu1/dpu_hw_interrupts.h | 28 ---
  8 files changed, 79 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
index 3c1b2c13398d..320cfa4be633 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_0_sm8350.h
@@ -15,6 +15,7 @@ static const struct dpu_caps sm8350_dpu_caps = {
.has_dim_layer = true,
.has_idle_pc = true,
.has_3d_merge = true,
+   .has_7xxx_intr = true,
.max_linewidth = 4096,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
  };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
index 5d894cbb0a62..9306c7a115e9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_7_2_sc7280.h
@@ -13,6 +13,7 @@ static const struct dpu_caps sc7280_dpu_caps = {
.qseed_type = DPU_SSPP_SCALER_QSEED4,
.has_dim_layer = true,
.has_idle_pc = true,
+   .has_7xxx_intr = true,
.max_linewidth = 2400,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
  };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
index c3f1ae000a21..fc1e17c495f0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_0_sc8280xp.h
@@ -15,6 +15,7 @@ static const struct dpu_caps sc8280xp_dpu_caps = {
.has_dim_layer = true,
.has_idle_pc = true,
.has_3d_merge = true,
+   .has_7xxx_intr = true,
.max_linewidth = 5120,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
  };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
index 86c2e68ebd2c..eb72411c16db 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_8_1_sm8450.h
@@ -14,6 +14,7 @@ static const struct dpu_caps sm8450_dpu_caps = {
.has_src_split = true,
.has_dim_layer = true,
.has_idle_pc = true,
+   .has_7xxx_intr = true,
.has_3d_merge = true,
.max_linewidth = 5120,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h 
b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
index 85dc34458b88..8209ca317bdc 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/catalog/dpu_9_0_sm8550.h
@@ -15,6 +15,7 @@ static const struct dpu_caps sm8550_dpu_caps = {
.has_dim_layer = true,
.has_idle_pc = true,
.has_3d_merge = true,
+   .has_7xxx_intr = true,
.max_linewidth = 5120,
.pixel_ram_size = DEFAULT_PIXEL_RAM_SIZE,
  };
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 677048cc3b7d..72530ebb0ae6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -351,6 +351,7 @@ struct dpu_rotation_cfg {
   * @has_dim_layer  dim layer feature status
   * @has_idle_pcindicate if idle power collapse feature is supported
   * @has_3d_merge   indicate if 3D merge is supported
+ * @has_7xxx_intr  indicate that INTF/IRQs use addressing for DPU 7.0 and 
greater


I see the requirement to distinguish feature support based on the DPU 
version in more than one series. Is it a good idea to bring in the DPU 
version info in chipset catalog? This will relieve us from maintaining 
such version flags for individual HW sub-blocks.


Thanks and Regards,
Jeykumar S.


   * @max_linewidth  max linewidth for sspp
   * @pixel_ram_size size of latency hiding and de-tiling buffer in bytes
   * @max_hdeci_exp  max horizontal decimation supported (max is 2^value)
@@ -364,6 +365,7 @@ struct dpu_caps {
bool has_dim_layer;
bool has_idle_pc;
bool has_3d_merge;
+   bool has_7xxx_intr;
/* SSPP limits */
u32 max_linewidth;
u32 pixel_ram_size;
diff --git 

Re: [PATCH v3 1/9] drm/msm/dpu: fix SSPP register definitions

2023-05-25 Thread Jeykumar Sankaran




On 5/18/2023 3:22 PM, Dmitry Baryshkov wrote:

Reorder SSPP register definitions to sort them in the ascending order.
Move register bitfields after the register definitions.

Signed-off-by: Dmitry Baryshkov 
---

Reviewed-by: Jeykumar Sankaran 

  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 64 ++---
  1 file changed, 32 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 6b68ec5c7a5a..08098880b7d5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -26,45 +26,18 @@
  #define SSPP_SRC_FORMAT0x30
  #define SSPP_SRC_UNPACK_PATTERN0x34
  #define SSPP_SRC_OP_MODE   0x38
-
-/* SSPP_MULTIRECT*/
-#define SSPP_SRC_SIZE_REC1 0x16C
-#define SSPP_SRC_XY_REC1   0x168
-#define SSPP_OUT_SIZE_REC1 0x160
-#define SSPP_OUT_XY_REC1   0x164
-#define SSPP_SRC_FORMAT_REC1   0x174
-#define SSPP_SRC_UNPACK_PATTERN_REC1   0x178
-#define SSPP_SRC_OP_MODE_REC1  0x17C
-#define SSPP_MULTIRECT_OPMODE  0x170
-#define SSPP_SRC_CONSTANT_COLOR_REC1   0x180
-#define SSPP_EXCL_REC_SIZE_REC10x184
-#define SSPP_EXCL_REC_XY_REC1  0x188
-
-#define MDSS_MDP_OP_DEINTERLACEBIT(22)
-#define MDSS_MDP_OP_DEINTERLACE_ODDBIT(23)
-#define MDSS_MDP_OP_IGC_ROM_1  BIT(18)
-#define MDSS_MDP_OP_IGC_ROM_0  BIT(17)
-#define MDSS_MDP_OP_IGC_EN BIT(16)
-#define MDSS_MDP_OP_FLIP_UDBIT(14)
-#define MDSS_MDP_OP_FLIP_LRBIT(13)
-#define MDSS_MDP_OP_BWC_EN BIT(0)
-#define MDSS_MDP_OP_PE_OVERRIDEBIT(31)
-#define MDSS_MDP_OP_BWC_LOSSLESS   (0 << 1)
-#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
-#define MDSS_MDP_OP_BWC_Q_MED  (2 << 1)
-
  #define SSPP_SRC_CONSTANT_COLOR0x3c
  #define SSPP_EXCL_REC_CTL  0x40
  #define SSPP_UBWC_STATIC_CTRL  0x44
-#define SSPP_FETCH_CONFIG  0x048
+#define SSPP_FETCH_CONFIG  0x48
  #define SSPP_DANGER_LUT0x60
  #define SSPP_SAFE_LUT  0x64
  #define SSPP_CREQ_LUT  0x68
  #define SSPP_QOS_CTRL  0x6C
-#define SSPP_DECIMATION_CONFIG 0xB4
  #define SSPP_SRC_ADDR_SW_STATUS0x70
  #define SSPP_CREQ_LUT_00x74
  #define SSPP_CREQ_LUT_10x78
+#define SSPP_DECIMATION_CONFIG 0xB4
  #define SSPP_SW_PIX_EXT_C0_LR  0x100
  #define SSPP_SW_PIX_EXT_C0_TB  0x104
  #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS  0x108
@@ -81,11 +54,33 @@
  #define SSPP_TRAFFIC_SHAPER_PREFILL0x150
  #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x154
  #define SSPP_TRAFFIC_SHAPER_REC1   0x158
+#define SSPP_OUT_SIZE_REC1 0x160
+#define SSPP_OUT_XY_REC1   0x164
+#define SSPP_SRC_XY_REC1   0x168
+#define SSPP_SRC_SIZE_REC1 0x16C
+#define SSPP_MULTIRECT_OPMODE  0x170
+#define SSPP_SRC_FORMAT_REC1   0x174
+#define SSPP_SRC_UNPACK_PATTERN_REC1   0x178
+#define SSPP_SRC_OP_MODE_REC1  0x17C
+#define SSPP_SRC_CONSTANT_COLOR_REC1   0x180
+#define SSPP_EXCL_REC_SIZE_REC10x184
+#define SSPP_EXCL_REC_XY_REC1  0x188
  #define SSPP_EXCL_REC_SIZE 0x1B4
  #define SSPP_EXCL_REC_XY   0x1B8
-#define SSPP_VIG_OP_MODE   0x0
-#define SSPP_VIG_CSC_10_OP_MODE0x0
-#define SSPP_TRAFFIC_SHAPER_BPC_MAX0xFF
+
+/* SSPP_SRC_OP_MODE & OP_MODE_REC1 */
+#define MDSS_MDP_OP_DEINTERLACEBIT(22)
+#define MDSS_MDP_OP_DEINTERLACE_ODDBIT(23)
+#define MDSS_MDP_OP_IGC_ROM_1  BIT(18)
+#define MDSS_MDP_OP_IGC_ROM_0  BIT(17)
+#define MDSS_MDP_OP_IGC_EN BIT(16)
+#define MDSS_MDP_OP_FLIP_UDBIT(14)
+#define MDSS_MDP_OP_FLIP_LRBIT(13)
+#define MDSS_MDP_OP_BWC_EN BIT(0)
+#define MDSS_MDP_OP_PE_OVERRIDEBIT(31)
+#define MDSS_MDP_OP_BWC_LOSSLESS   (0 << 1)
+#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
+#define MDSS_MDP_OP_BWC_Q_MED  (2 << 1)
  
  /* SSPP_QOS_CTRL */

  #define SSPP_QOS_CTRL_VBLANK_ENBIT(16)
@@ -96,6 +91,7 @@
  #define SSPP_QOS_CTRL_CREQ_VBLANK_OFF  20
  
  /* DPU_SSPP_SCALER_QSEED2 */

+#define SSPP_VIG_OP_MODE   0x0
  #define SCALE_CONFIG   0x04
  #define COMP0_3_PHASE_STEP_X   0x10
  #define COMP0_3_PHASE_STEP_Y   0x14
@@ -107,6 +103,9 @@
  #define COMP1_2_INIT_PHASE_Y   0x2C
  #define

Re: [Freedreno] [PATCH v2 2/9] drm/msm/dpu: simplify CDP programming

2023-05-06 Thread Jeykumar Sankaran
msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1116,20 +1116,10 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
pipe->sspp->ops.setup_format(pipe, fmt, src_flags);
  
  		if (pipe->sspp->ops.setup_cdp) {

-   struct dpu_hw_cdp_cfg cdp_cfg;
+   const struct dpu_perf_cfg *perf = pdpu->catalog->perf;
  
-			memset(_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));

-
-   cdp_cfg.enable = pdpu->catalog->perf->cdp_cfg
-   [DPU_PERF_CDP_USAGE_RT].rd_enable;
-   cdp_cfg.ubwc_meta_enable =
-   DPU_FORMAT_IS_UBWC(fmt);
-   cdp_cfg.tile_amortize_enable =
-   DPU_FORMAT_IS_UBWC(fmt) ||
-   DPU_FORMAT_IS_TILE(fmt);
-   cdp_cfg.preload_ahead = DPU_SSPP_CDP_PRELOAD_AHEAD_64;
-
-   pipe->sspp->ops.setup_cdp(pipe, _cfg);
+   pipe->sspp->ops.setup_cdp(pipe, fmt,
+ 
perf->cdp_cfg[DPU_PERF_CDP_USAGE_RT].rd_enable);
}
}
  

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 3/9] drm/msm/dpu: fix the condition for (not) applying QoS to CURSOR SSPP

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

The function dpu_plane_sspp_update_pipe() contains code to skip enabling
the QoS and OT limitis for CURSOR pipes. However all DPU since sdm845
repurpose DMA SSPP for the cursor planes because they lack the real
CURSOR SSPP. Fix the condition to actually check that the plane is
CURSOR or not.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 3b210320ea62..b8ed7247a6af 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1126,7 +1126,8 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);
_dpu_plane_set_danger_lut(plane, pipe, fmt);
  
-	if (plane->type != DRM_PLANE_TYPE_CURSOR) {

+   if (pipe->sspp->idx != SSPP_CURSOR0 &&
+   pipe->sspp->idx != SSPP_CURSOR1) {
_dpu_plane_set_qos_ctrl(plane, pipe, true, 
DPU_PLANE_QOS_PANIC_CTRL);
_dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate);
    }

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 8/9] drm/msm/dpu: remove struct dpu_hw_pipe_qos_cfg

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

Now as the struct dpu_hw_pipe_qos_cfg consists of only one bool field,
drop the structure and use corresponding bool directly.

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 10 +++---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h | 13 ++---
  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 11 +++
  3 files changed, 8 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 341e3a8fc927..2533c4629021 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -568,17 +568,13 @@ static void dpu_hw_sspp_setup_creq_lut(struct dpu_hw_sspp 
*ctx,
  }
  
  static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp *ctx,

-   struct dpu_hw_pipe_qos_cfg *cfg)
+  bool danger_safe_en)
  {
-   u32 qos_ctrl = 0;
-
if (!ctx)
return;
  
-	if (cfg->danger_safe_en)

-   qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN;
-
-   DPU_REG_WRITE(>hw, SSPP_QOS_CTRL, qos_ctrl);
+   DPU_REG_WRITE(>hw, SSPP_QOS_CTRL,
+ danger_safe_en ? SSPP_QOS_CTRL_DANGER_SAFE_EN : 0);
  }
  
  static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index aaf6f41d546c..4278c421b6ac 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -163,14 +163,6 @@ struct dpu_sw_pipe_cfg {
struct drm_rect dst_rect;
  };
  
-/**

- * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration
- * @danger_safe_en: enable danger safe generation
- */
-struct dpu_hw_pipe_qos_cfg {
-   bool danger_safe_en;
-};
-
  /**
   * struct dpu_hw_pipe_ts_cfg - traffic shaper configuration
   * @size: size to prefill in bytes, or zero to disable
@@ -285,11 +277,10 @@ struct dpu_hw_sspp_ops {
/**
 * setup_qos_ctrl - setup QoS control
 * @ctx: Pointer to pipe context
-* @cfg: Pointer to pipe QoS configuration
-*
+* @danger_safe_en: flags controlling enabling of danger/safe QoS/LUT
 */
void (*setup_qos_ctrl)(struct dpu_hw_sspp *ctx,
-   struct dpu_hw_pipe_qos_cfg *cfg);
+  bool danger_safe_en);
  
  	/**

 * setup_histogram - setup histograms
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index d1443c4b2915..c8837d0aa0c3 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -343,22 +343,17 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane 
*plane,
bool enable)
  {
struct dpu_plane *pdpu = to_dpu_plane(plane);
-   struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
-
-   memset(_qos_cfg, 0, sizeof(pipe_qos_cfg));
-
-   pipe_qos_cfg.danger_safe_en = enable;
  
  	if (!pdpu->is_rt_pipe)

-   pipe_qos_cfg.danger_safe_en = false;
+   enable = false;
  
  	DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n",

pdpu->pipe - SSPP_VIG0,
-   pipe_qos_cfg.danger_safe_en,
+   enable,
pdpu->is_rt_pipe);
  
  	pipe->sspp->ops.setup_qos_ctrl(pipe->sspp,

-   _qos_cfg);
+  enable);
  }
  
  /**

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 5/9] drm/msm/dpu: drop DPU_PLANE_QOS_VBLANK_CTRL

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

Drop support for DPU_PLANE_QOS_VBLANK_CTRL flag. It is not used both
in upstream driver and in vendor SDE driver.

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h |  4 
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c|  8 
  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c  | 10 --
  3 files changed, 22 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index b2831b45ac64..d47e7061a36b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -371,8 +371,6 @@ struct dpu_caps {
  /**
   * struct dpu_sspp_sub_blks : SSPP sub-blocks
   * common: Pointer to common configurations shared by sub blocks
- * @creq_vblank: creq priority during vertical blanking
- * @danger_vblank: danger priority during vertical blanking
   * @maxdwnscale: max downscale ratio supported(without DECIMATION)
   * @maxupscale:  maxupscale ratio supported
   * @smart_dma_priority: hw priority of rect1 of multirect pipe
@@ -387,8 +385,6 @@ struct dpu_caps {
   * @dpu_rotation_cfg: inline rotation configuration
   */
  struct dpu_sspp_sub_blks {
-   u32 creq_vblank;
-   u32 danger_vblank;
u32 maxdwnscale;
u32 maxupscale;
u32 smart_dma_priority;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 731199030336..b198def5534b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -697,14 +697,6 @@ int _dpu_hw_sspp_init_debugfs(struct dpu_hw_sspp *hw_pipe, 
struct dpu_kms *kms,
0400,
debugfs_root,
(u32 *) >clk_ctrl);
-   debugfs_create_x32("creq_vblank",
-   0600,
-   debugfs_root,
-   (u32 *) >creq_vblank);
-   debugfs_create_x32("danger_vblank",
-   0600,
-   debugfs_root,
-   (u32 *) >danger_vblank);
  
  	return 0;

  }
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 586f089756fa..3cb891917b65 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -73,13 +73,11 @@ static const uint32_t qcom_compressed_supported_formats[] = 
{
  /**
   * enum dpu_plane_qos - Different qos configurations for each pipe
   *
- * @DPU_PLANE_QOS_VBLANK_CTRL: Setup VBLANK qos for the pipe.
   * @DPU_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
   *this configuration is mutually exclusive from VBLANK_CTRL.
   * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
   */
  enum dpu_plane_qos {
-   DPU_PLANE_QOS_VBLANK_CTRL = BIT(0),
DPU_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
DPU_PLANE_QOS_PANIC_CTRL = BIT(2),
  };
@@ -361,15 +359,7 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane 
*plane,
  
  	memset(_qos_cfg, 0, sizeof(pipe_qos_cfg));
  
-	if (flags & DPU_PLANE_QOS_VBLANK_CTRL) {

-   pipe_qos_cfg.creq_vblank = pipe->sspp->cap->sblk->creq_vblank;
-   pipe_qos_cfg.danger_vblank =
-   pipe->sspp->cap->sblk->danger_vblank;
-   pipe_qos_cfg.vblank_en = enable;
-   }
-
if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) {
-   /* this feature overrules previous VBLANK_CTRL */
pipe_qos_cfg.vblank_en = false;
pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
}

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 1/9] drm/msm/dpu: fix SSPP register definitions

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

Reorder SSPP register definitions to sort them in the ascending order.
Move register bitfields after the register definitions.

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 66 +++--
  1 file changed, 34 insertions(+), 32 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 6b68ec5c7a5a..1bf717290dab 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -26,45 +26,18 @@
  #define SSPP_SRC_FORMAT0x30
  #define SSPP_SRC_UNPACK_PATTERN0x34
  #define SSPP_SRC_OP_MODE   0x38
-
-/* SSPP_MULTIRECT*/
-#define SSPP_SRC_SIZE_REC1 0x16C
-#define SSPP_SRC_XY_REC1   0x168
-#define SSPP_OUT_SIZE_REC1 0x160
-#define SSPP_OUT_XY_REC1   0x164
-#define SSPP_SRC_FORMAT_REC1   0x174
-#define SSPP_SRC_UNPACK_PATTERN_REC1   0x178
-#define SSPP_SRC_OP_MODE_REC1  0x17C
-#define SSPP_MULTIRECT_OPMODE  0x170
-#define SSPP_SRC_CONSTANT_COLOR_REC1   0x180
-#define SSPP_EXCL_REC_SIZE_REC10x184
-#define SSPP_EXCL_REC_XY_REC1  0x188
-
-#define MDSS_MDP_OP_DEINTERLACEBIT(22)
-#define MDSS_MDP_OP_DEINTERLACE_ODDBIT(23)
-#define MDSS_MDP_OP_IGC_ROM_1  BIT(18)
-#define MDSS_MDP_OP_IGC_ROM_0  BIT(17)
-#define MDSS_MDP_OP_IGC_EN BIT(16)
-#define MDSS_MDP_OP_FLIP_UDBIT(14)
-#define MDSS_MDP_OP_FLIP_LRBIT(13)
-#define MDSS_MDP_OP_BWC_EN BIT(0)
-#define MDSS_MDP_OP_PE_OVERRIDEBIT(31)
-#define MDSS_MDP_OP_BWC_LOSSLESS   (0 << 1)
-#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
-#define MDSS_MDP_OP_BWC_Q_MED  (2 << 1)
-
  #define SSPP_SRC_CONSTANT_COLOR0x3c
  #define SSPP_EXCL_REC_CTL  0x40
  #define SSPP_UBWC_STATIC_CTRL  0x44
-#define SSPP_FETCH_CONFIG  0x048
+#define SSPP_FETCH_CONFIG  0x48
  #define SSPP_DANGER_LUT0x60
  #define SSPP_SAFE_LUT  0x64
  #define SSPP_CREQ_LUT  0x68
  #define SSPP_QOS_CTRL  0x6C
-#define SSPP_DECIMATION_CONFIG 0xB4
  #define SSPP_SRC_ADDR_SW_STATUS0x70
  #define SSPP_CREQ_LUT_00x74
  #define SSPP_CREQ_LUT_10x78
+#define SSPP_DECIMATION_CONFIG 0xB4
  #define SSPP_SW_PIX_EXT_C0_LR  0x100
  #define SSPP_SW_PIX_EXT_C0_TB  0x104
  #define SSPP_SW_PIX_EXT_C0_REQ_PIXELS  0x108
@@ -81,11 +54,33 @@
  #define SSPP_TRAFFIC_SHAPER_PREFILL0x150
  #define SSPP_TRAFFIC_SHAPER_REC1_PREFILL   0x154
  #define SSPP_TRAFFIC_SHAPER_REC1   0x158
+#define SSPP_OUT_SIZE_REC1 0x160
+#define SSPP_OUT_XY_REC1   0x164
+#define SSPP_SRC_XY_REC1   0x168
+#define SSPP_SRC_SIZE_REC1 0x16C
+#define SSPP_MULTIRECT_OPMODE  0x170
+#define SSPP_SRC_FORMAT_REC1   0x174
+#define SSPP_SRC_UNPACK_PATTERN_REC1   0x178
+#define SSPP_SRC_OP_MODE_REC1  0x17C
+#define SSPP_SRC_CONSTANT_COLOR_REC1   0x180
+#define SSPP_EXCL_REC_SIZE_REC10x184
+#define SSPP_EXCL_REC_XY_REC1  0x188
  #define SSPP_EXCL_REC_SIZE 0x1B4
  #define SSPP_EXCL_REC_XY   0x1B8
-#define SSPP_VIG_OP_MODE   0x0
-#define SSPP_VIG_CSC_10_OP_MODE0x0
-#define SSPP_TRAFFIC_SHAPER_BPC_MAX0xFF
+
+/* SSPP_SRC_OP_MODE & OP_MODE_REC1 */
+#define MDSS_MDP_OP_DEINTERLACEBIT(22)
+#define MDSS_MDP_OP_DEINTERLACE_ODDBIT(23)
+#define MDSS_MDP_OP_IGC_ROM_1  BIT(18)
+#define MDSS_MDP_OP_IGC_ROM_0  BIT(17)
+#define MDSS_MDP_OP_IGC_EN BIT(16)
+#define MDSS_MDP_OP_FLIP_UDBIT(14)
+#define MDSS_MDP_OP_FLIP_LRBIT(13)
+#define MDSS_MDP_OP_BWC_EN BIT(0)
+#define MDSS_MDP_OP_PE_OVERRIDEBIT(31)
+#define MDSS_MDP_OP_BWC_LOSSLESS   (0 << 1)
+#define MDSS_MDP_OP_BWC_Q_HIGH (1 << 1)
+#define MDSS_MDP_OP_BWC_Q_MED  (2 << 1)
  
  /* SSPP_QOS_CTRL */

  #define SSPP_QOS_CTRL_VBLANK_ENBIT(16)
@@ -96,6 +91,7 @@
  #define SSPP_QOS_CTRL_CREQ_VBLANK_OFF  20
  
  /* DPU_SSPP_SCALER_QSEED2 */

+#define SSPP_VIG_OP_MODE   0x0
  #define SCALE_CONFIG   0x04
  #define COMP0_3_PHASE_STEP_X   0x10
  #define COMP0_3_PHASE_STEP_Y   0x14
@@ -107,6 +103,12 @@
  #define COMP1_2_INIT_PHASE_Y   0x2C
  #define VIG_0_QSEED2_SHARP 0x30
  
+/* DPU_SSPP_CSC_10BIT space */

+#define 

Re: [Freedreno] [PATCH v2 9/9] drm/msm/dpu: use common helper for WB and SSPP QoS setup

2023-05-06 Thread Jeykumar Sankaran
rf_set_qos_luts(pipe->sspp->idx - SSPP_VIG0,

(fmt) ? fmt->base.pixel_format : 0,
-   pdpu->is_rt_pipe, total_fl, qos_lut, lut_usage);
+   pdpu->is_rt_pipe, total_fl, cfg.creq_lut, lut_usage);
  
  	DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s rt:%d fl:%u lut:0x%llx\n",

pdpu->pipe - SSPP_VIG0,
fmt ? (char *)>base.pixel_format : NULL,
-   pdpu->is_rt_pipe, total_fl, qos_lut);
-
-   pipe->sspp->ops.setup_creq_lut(pipe->sspp, qos_lut);
-}
-
-/**
- * _dpu_plane_set_danger_lut - set danger/safe LUT of the given plane
- * @plane: Pointer to drm plane
- * @pipe:  Pointer to software pipe
- * @fmt:   Pointer to source buffer format
- */
-static void _dpu_plane_set_danger_lut(struct drm_plane *plane,
-   struct dpu_sw_pipe *pipe,
-   const struct dpu_format *fmt)
-{
-   struct dpu_plane *pdpu = to_dpu_plane(plane);
-   u32 danger_lut, safe_lut;
-
-   if (!pdpu->is_rt_pipe) {
-   danger_lut = pdpu->catalog->perf->danger_lut_tbl
-   [DPU_QOS_LUT_USAGE_NRT];
-   safe_lut = pdpu->catalog->perf->safe_lut_tbl
-   [DPU_QOS_LUT_USAGE_NRT];
-   } else {
-   if (fmt && DPU_FORMAT_IS_LINEAR(fmt)) {
-   danger_lut = pdpu->catalog->perf->danger_lut_tbl
-   [DPU_QOS_LUT_USAGE_LINEAR];
-   safe_lut = pdpu->catalog->perf->safe_lut_tbl
-   [DPU_QOS_LUT_USAGE_LINEAR];
-   } else {
-   danger_lut = pdpu->catalog->perf->danger_lut_tbl
-   [DPU_QOS_LUT_USAGE_MACROTILE];
-   safe_lut = pdpu->catalog->perf->safe_lut_tbl
-   [DPU_QOS_LUT_USAGE_MACROTILE];
-   }
-   }
+   pdpu->is_rt_pipe, total_fl, cfg.creq_lut);
  
  	trace_dpu_perf_set_danger_luts(pdpu->pipe - SSPP_VIG0,

(fmt) ? fmt->base.pixel_format : 0,
(fmt) ? fmt->fetch_mode : 0,
-   danger_lut,
-   safe_lut);
+   cfg.danger_lut,
+   cfg.safe_lut);
  
  	DPU_DEBUG_PLANE(pdpu, "pnum:%d fmt: %4.4s mode:%d luts[0x%x, 0x%x]\n",

pdpu->pipe - SSPP_VIG0,
fmt ? (char *)>base.pixel_format : NULL,
fmt ? fmt->fetch_mode : -1,
-   danger_lut,
-   safe_lut);
+   cfg.danger_lut,
+   cfg.safe_lut);
  
-	pipe->sspp->ops.setup_danger_safe_lut(pipe->sspp,

-   danger_lut, safe_lut);
+   pipe->sspp->ops.setup_qos_lut(pipe->sspp, );
  }
  
  /**

@@ -336,7 +316,6 @@ static void _dpu_plane_set_danger_lut(struct drm_plane 
*plane,
   * @plane:Pointer to drm plane
   * @pipe: Pointer to software pipe
   * @enable:   true to enable QoS control
- * @flags: QoS control mode (enum dpu_plane_qos)
   */
  static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
@@ -1086,10 +1065,6 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
    }
  
  	_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);

-   _dpu_plane_set_danger_lut(plane, pipe, fmt);
-   _dpu_plane_set_qos_ctrl(plane, pipe,
-   pipe->sspp->idx != SSPP_CURSOR0 &&
-   pipe->sspp->idx != SSPP_CURSOR1);
  
  	if (pipe->sspp->idx != SSPP_CURSOR0 &&

pipe->sspp->idx != SSPP_CURSOR1)

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 7/9] drm/msm/dpu: drop DPU_PLANE_QOS_PANIC_CTRL

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

This flag is always passed to _dpu_plane_set_qos_ctrl(), so drop it and
remove corresponding conditions from the mentioned function.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 0ed350776775..d1443c4b2915 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -70,15 +70,6 @@ static const uint32_t qcom_compressed_supported_formats[] = {
DRM_FORMAT_P010,
  };
  
-/**

- * enum dpu_plane_qos - Different qos configurations for each pipe
- *
- * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
- */
-enum dpu_plane_qos {
-   DPU_PLANE_QOS_PANIC_CTRL = BIT(2),
-};
-
  /*
   * struct dpu_plane - local dpu plane structure
   * @aspace: address space pointer
@@ -349,15 +340,14 @@ static void _dpu_plane_set_danger_lut(struct drm_plane 
*plane,
   */
  static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
struct dpu_sw_pipe *pipe,
-   bool enable, u32 flags)
+   bool enable)
  {
struct dpu_plane *pdpu = to_dpu_plane(plane);
struct dpu_hw_pipe_qos_cfg pipe_qos_cfg;
  
  	memset(_qos_cfg, 0, sizeof(pipe_qos_cfg));
  
-	if (flags & DPU_PLANE_QOS_PANIC_CTRL)

-   pipe_qos_cfg.danger_safe_en = enable;
+   pipe_qos_cfg.danger_safe_en = enable;
  
  	if (!pdpu->is_rt_pipe)

pipe_qos_cfg.danger_safe_en = false;
@@ -1058,7 +1048,7 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
  
  	/* override for color fill */

if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
-   _dpu_plane_set_qos_ctrl(plane, pipe, false, 
DPU_PLANE_QOS_PANIC_CTRL);
+   _dpu_plane_set_qos_ctrl(plane, pipe, false);
  
  		/* skip remaining processing on color fill */

return;
@@ -1104,8 +1094,7 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
_dpu_plane_set_danger_lut(plane, pipe, fmt);
_dpu_plane_set_qos_ctrl(plane, pipe,
pipe->sspp->idx != SSPP_CURSOR0 &&
-   pipe->sspp->idx != SSPP_CURSOR1,
-   DPU_PLANE_QOS_PANIC_CTRL);
+   pipe->sspp->idx != SSPP_CURSOR1);
  
  	if (pipe->sspp->idx != SSPP_CURSOR0 &&

pipe->sspp->idx != SSPP_CURSOR1)
@@ -1224,10 +1213,10 @@ static void dpu_plane_destroy(struct drm_plane *plane)
  
  	if (pdpu) {

pstate = to_dpu_plane_state(plane->state);
-   _dpu_plane_set_qos_ctrl(plane, >pipe, false, 
DPU_PLANE_QOS_PANIC_CTRL);
+   _dpu_plane_set_qos_ctrl(plane, >pipe, false);
  
  		if (pstate->r_pipe.sspp)

-   _dpu_plane_set_qos_ctrl(plane, >r_pipe, false, 
DPU_PLANE_QOS_PANIC_CTRL);
+   _dpu_plane_set_qos_ctrl(plane, >r_pipe, false);
  
  		mutex_destroy(>lock);
  
@@ -1384,9 +1373,9 @@ void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)

return;
  
  	pm_runtime_get_sync(_kms->pdev->dev);

-   _dpu_plane_set_qos_ctrl(plane, >pipe, enable, 
DPU_PLANE_QOS_PANIC_CTRL);
+   _dpu_plane_set_qos_ctrl(plane, >pipe, enable);
if (pstate->r_pipe.sspp)
-   _dpu_plane_set_qos_ctrl(plane, >r_pipe, enable, 
DPU_PLANE_QOS_PANIC_CTRL);
+   _dpu_plane_set_qos_ctrl(plane, >r_pipe, enable);
pm_runtime_put_sync(_kms->pdev->dev);
  }
  #endif

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 6/9] drm/msm/dpu: simplify qos_ctrl handling

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

After removal of DPU_PLANE_QOS_VBLANK_CTRL, several fields of struct
dpu_hw_pipe_qos_cfg are fixed to false/0. Drop them from the structure
(and drop the corresponding code from the functions).

The DPU_PLANE_QOS_VBLANK_AMORTIZE flag is also removed, since it is now
a NOP.

Signed-off-by: Dmitry Baryshkov 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c | 10 --
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h |  6 --
  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c   | 17 ++---
  3 files changed, 2 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index b198def5534b..341e3a8fc927 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -575,16 +575,6 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp 
*ctx,
if (!ctx)
return;
  
-	if (cfg->vblank_en) {

-   qos_ctrl |= ((cfg->creq_vblank &
-   SSPP_QOS_CTRL_CREQ_VBLANK_MASK) <<
-   SSPP_QOS_CTRL_CREQ_VBLANK_OFF);
-   qos_ctrl |= ((cfg->danger_vblank &
-   SSPP_QOS_CTRL_DANGER_VBLANK_MASK) <<
-   SSPP_QOS_CTRL_DANGER_VBLANK_OFF);
-   qos_ctrl |= SSPP_QOS_CTRL_VBLANK_EN;
-   }
-
if (cfg->danger_safe_en)
qos_ctrl |= SSPP_QOS_CTRL_DANGER_SAFE_EN;
  
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h

index 86bf4b2cda77..aaf6f41d546c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -165,15 +165,9 @@ struct dpu_sw_pipe_cfg {
  
  /**

   * struct dpu_hw_pipe_qos_cfg : Source pipe QoS configuration
- * @creq_vblank: creq value generated to vbif during vertical blanking
- * @danger_vblank: danger value generated during vertical blanking
- * @vblank_en: enable creq_vblank and danger_vblank during vblank
   * @danger_safe_en: enable danger safe generation
   */
  struct dpu_hw_pipe_qos_cfg {
-   u32 creq_vblank;
-   u32 danger_vblank;
-   bool vblank_en;
bool danger_safe_en;
  };
  
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c

index 3cb891917b65..0ed350776775 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -73,12 +73,9 @@ static const uint32_t qcom_compressed_supported_formats[] = {
  /**
   * enum dpu_plane_qos - Different qos configurations for each pipe
   *
- * @DPU_PLANE_QOS_VBLANK_AMORTIZE: Enables Amortization within pipe.
- * this configuration is mutually exclusive from VBLANK_CTRL.
   * @DPU_PLANE_QOS_PANIC_CTRL: Setup panic for the pipe.
   */
  enum dpu_plane_qos {
-   DPU_PLANE_QOS_VBLANK_AMORTIZE = BIT(1),
DPU_PLANE_QOS_PANIC_CTRL = BIT(2),
  };
  
@@ -359,25 +356,15 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
  
  	memset(_qos_cfg, 0, sizeof(pipe_qos_cfg));
  
-	if (flags & DPU_PLANE_QOS_VBLANK_AMORTIZE) {

-   pipe_qos_cfg.vblank_en = false;
-   pipe_qos_cfg.creq_vblank = 0; /* clear vblank bits */
-   }
-
if (flags & DPU_PLANE_QOS_PANIC_CTRL)
pipe_qos_cfg.danger_safe_en = enable;
  
-	if (!pdpu->is_rt_pipe) {

-   pipe_qos_cfg.vblank_en = false;
+   if (!pdpu->is_rt_pipe)
pipe_qos_cfg.danger_safe_en = false;
-   }
  
-	DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d vb:%d pri[0x%x, 0x%x] is_rt:%d\n",

+   DPU_DEBUG_PLANE(pdpu, "pnum:%d ds:%d is_rt:%d\n",
pdpu->pipe - SSPP_VIG0,
pipe_qos_cfg.danger_safe_en,
-   pipe_qos_cfg.vblank_en,
-   pipe_qos_cfg.creq_vblank,
-   pipe_qos_cfg.danger_vblank,
pdpu->is_rt_pipe);
  
  	pipe->sspp->ops.setup_qos_ctrl(pipe->sspp,

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH v2 4/9] drm/msm/dpu: rearrange QoS setting code

2023-05-06 Thread Jeykumar Sankaran




On 5/2/2023 8:05 AM, Dmitry Baryshkov wrote:

Slightly rearrainge code in dpu_plane_sspp_update_pipe() to group
QoS/LUT related functions.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index b8ed7247a6af..586f089756fa 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1079,10 +1079,10 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
pipe->sspp->ops.setup_sourceaddress(pipe, layout);
}
  
-	_dpu_plane_set_qos_ctrl(plane, pipe, false, DPU_PLANE_QOS_PANIC_CTRL);

-
/* override for color fill */
if (pdpu->color_fill & DPU_PLANE_COLOR_FILL_FLAG) {
+   _dpu_plane_set_qos_ctrl(plane, pipe, false, 
DPU_PLANE_QOS_PANIC_CTRL);
+
/* skip remaining processing on color fill */
return;
}
@@ -1125,12 +1125,14 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
  
  	_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);

_dpu_plane_set_danger_lut(plane, pipe, fmt);
+   _dpu_plane_set_qos_ctrl(plane, pipe,
+   pipe->sspp->idx != SSPP_CURSOR0 &&
+   pipe->sspp->idx != SSPP_CURSOR1,
+   DPU_PLANE_QOS_PANIC_CTRL);
  
  	if (pipe->sspp->idx != SSPP_CURSOR0 &&

-   pipe->sspp->idx != SSPP_CURSOR1) {
-   _dpu_plane_set_qos_ctrl(plane, pipe, true, 
DPU_PLANE_QOS_PANIC_CTRL);
+   pipe->sspp->idx != SSPP_CURSOR1)
_dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate);
-   }
  
  	if (pstate->needs_qos_remap)

    _dpu_plane_set_qos_remap(plane, pipe);

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH 2/9] drm/msm/dpu: simplify CDP programming

2023-05-02 Thread Jeykumar Sankaran




On 4/30/2023 1:57 PM, Dmitry Baryshkov wrote:

Get rid of intermediatory configuration structure and defines. Pass the
format and the enablement bit directly to the new helper. The
WB_CDP_CNTL register ignores BIT(2), so we can write it for both SSPP
and WB CDP settings.

Signed-off-by: Dmitry Baryshkov 
---
  .../drm/msm/disp/dpu1/dpu_encoder_phys_wb.c   | 19 -
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 17 ---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h   | 14 -
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c   | 21 +++
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h   | 19 +++--
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.c | 19 -
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_wb.h | 11 ++
  drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 20 --
  8 files changed, 46 insertions(+), 94 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index bac4aa807b4b..120141f1e5c5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -140,7 +140,6 @@ static void dpu_encoder_phys_wb_setup_fb(struct 
dpu_encoder_phys *phys_enc,
struct dpu_encoder_phys_wb *wb_enc = to_dpu_encoder_phys_wb(phys_enc);
struct dpu_hw_wb *hw_wb;
struct dpu_hw_wb_cfg *wb_cfg;
-   struct dpu_hw_cdp_cfg cdp_cfg;
  
  	if (!phys_enc || !phys_enc->dpu_kms || !phys_enc->dpu_kms->catalog) {

DPU_ERROR("invalid encoder\n");
@@ -162,20 +161,10 @@ static void dpu_encoder_phys_wb_setup_fb(struct 
dpu_encoder_phys *phys_enc,
if (hw_wb->ops.setup_outformat)
hw_wb->ops.setup_outformat(hw_wb, wb_cfg);
  
-	if (hw_wb->ops.setup_cdp) {

-   memset(_cfg, 0, sizeof(struct dpu_hw_cdp_cfg));
-
-   cdp_cfg.enable = phys_enc->dpu_kms->catalog->perf->cdp_cfg
-   [DPU_PERF_CDP_USAGE_NRT].wr_enable;
-   cdp_cfg.ubwc_meta_enable =
-   DPU_FORMAT_IS_UBWC(wb_cfg->dest.format);
-   cdp_cfg.tile_amortize_enable =
-   DPU_FORMAT_IS_UBWC(wb_cfg->dest.format) ||
-   DPU_FORMAT_IS_TILE(wb_cfg->dest.format);
-   cdp_cfg.preload_ahead = DPU_WB_CDP_PRELOAD_AHEAD_64;
-
-   hw_wb->ops.setup_cdp(hw_wb, _cfg);
-   }
+   if (hw_wb->ops.setup_cdp)
+   hw_wb->ops.setup_cdp(hw_wb, wb_cfg->dest.format,
+phys_enc->dpu_kms->catalog->perf->cdp_cfg
+[DPU_PERF_CDP_USAGE_NRT].wr_enable);

Too many indirections. Consider adding a temp variable.
  
  	if (hw_wb->ops.setup_outaddress)

hw_wb->ops.setup_outaddress(hw_wb, wb_cfg);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 1bf717290dab..731199030336 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -592,13 +592,13 @@ static void dpu_hw_sspp_setup_qos_ctrl(struct dpu_hw_sspp 
*ctx,
  }
  
  static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,

-   struct dpu_hw_cdp_cfg *cfg)
+ const struct dpu_format *fmt,
+ bool enable)
  {
struct dpu_hw_sspp *ctx = pipe->sspp;
-   u32 cdp_cntl = 0;
u32 cdp_cntl_offset = 0;
  
-	if (!ctx || !cfg)

+   if (!ctx)
return;
  
  	if (pipe->multirect_index == DPU_SSPP_RECT_SOLO ||

@@ -607,16 +607,7 @@ static void dpu_hw_sspp_setup_cdp(struct dpu_sw_pipe *pipe,
else
cdp_cntl_offset = SSPP_CDP_CNTL_REC1;
  
-	if (cfg->enable)

-   cdp_cntl |= BIT(0);
-   if (cfg->ubwc_meta_enable)
-   cdp_cntl |= BIT(1);
-   if (cfg->tile_amortize_enable)
-   cdp_cntl |= BIT(2);
-   if (cfg->preload_ahead == DPU_SSPP_CDP_PRELOAD_AHEAD_64)
-   cdp_cntl |= BIT(3);
-
-   DPU_REG_WRITE(>hw, cdp_cntl_offset, cdp_cntl);
+   dpu_setup_cdp(>hw, cdp_cntl_offset, fmt, enable);
  }
  
  static void _setup_layer_ops(struct dpu_hw_sspp *c,

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
index 7a8d11ba618d..86bf4b2cda77 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.h
@@ -177,14 +177,6 @@ struct dpu_hw_pipe_qos_cfg {
bool danger_safe_en;
  };
  
-/**

- * enum CDP preload ahead address size
- */
-enum {
-   DPU_SSPP_CDP_PRELOAD_AHEAD_32,
-   DPU_SSPP_CDP_PRELOAD_AHEAD_64
-};
-
  /**
   * struct dpu_hw_pipe_ts_cfg - traffic shaper configuration
   * @size: size to prefill in bytes, or zero to disable
@@ -331,10 +323,12 @@ struct dpu_hw_sspp_ops {
/**
 * 

Re: [Freedreno] [PATCH 3/9] drm/msm/dpu: fix the condition for (not) applying QoS to CURSOR SSPP

2023-05-02 Thread Jeykumar Sankaran




On 4/30/2023 1:57 PM, Dmitry Baryshkov wrote:

The function dpu_plane_sspp_update_pipe() contains code to skip enabling
the QoS and OT limitis for CURSOR pipes. However all DPU since sdm845
repurpose DMA SSPP for the cursor planes because they lack the real
CURSOR SSPP. Fix the condition to actually check that the plane is
CURSOR or not.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index 43d9fbc0c687..36f6eb71fef8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -1124,7 +1124,8 @@ static void dpu_plane_sspp_update_pipe(struct drm_plane 
*plane,
_dpu_plane_set_qos_lut(plane, pipe, fmt, pipe_cfg);
_dpu_plane_set_danger_lut(plane, pipe, fmt);
  
-	if (plane->type != DRM_PLANE_TYPE_CURSOR) {

+   if (pipe->sspp->idx == SSPP_CURSOR0 ||
+   pipe->sspp->idx == SSPP_CURSOR1) {
Isn't this differ from the current sequence: The existing sequence 
programs QOS for all the non-cursor SSPP's. This patch programs QOS only 
for CURSOR SSPP's.


If DMA SSPP's are used for cursor planes, we should ideally remove this 
check.


Jeykumar S.

_dpu_plane_set_qos_ctrl(plane, pipe, true, 
DPU_PLANE_QOS_PANIC_CTRL);
_dpu_plane_set_ot_limit(plane, pipe, pipe_cfg, frame_rate);
}


Re: [Freedreno] [PATCH 3/3] drm/msm/dpu: access CSC/CSC10 registers directly

2023-04-27 Thread Jeykumar Sankaran




On 4/21/2023 5:08 PM, Dmitry Baryshkov wrote:

Stop using _sspp_subblk_offset() to get offset of the csc_blk. Inline
this function and use ctx->cap->sblk->csc_blk.base directly.

As this was the last user, drop _sspp_subblk_offset() too.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index 22c59f2250be..f4698e28e197 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -136,30 +136,6 @@
  #define TS_CLK1920
  
  
-static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx,

-   int s_id,
-   u32 *idx)
-{
-   int rc = 0;
-   const struct dpu_sspp_sub_blks *sblk;
-
-   if (!ctx || !ctx->cap || !ctx->cap->sblk)
-   return -EINVAL;
-
-   sblk = ctx->cap->sblk;
-
-   switch (s_id) {
-   case DPU_SSPP_CSC:
-   case DPU_SSPP_CSC_10BIT:
-   *idx = sblk->csc_blk.base;
-   break;
-   default:
-   rc = -EINVAL;
-   }
-
-   return rc;
-}
-
  static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe *pipe)
  {
struct dpu_hw_sspp *ctx = pipe->sspp;
@@ -210,19 +186,16 @@ static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,
  static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
  {
-   u32 idx;
+   const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
u32 opmode;
  
-	if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC_10BIT, ))

-   return;
-
-   opmode = DPU_REG_READ(>hw, SSPP_VIG_CSC_10_OP_MODE + idx);
+   opmode = DPU_REG_READ(>hw, sblk->csc_blk.base + 
SSPP_VIG_CSC_10_OP_MODE);
if (en)
opmode |= mask;
else
opmode &= ~mask;
  
-	DPU_REG_WRITE(>hw, SSPP_VIG_CSC_10_OP_MODE + idx, opmode);

+   DPU_REG_WRITE(>hw, sblk->csc_blk.base + SSPP_VIG_CSC_10_OP_MODE, 
opmode);
  }
  
  /*

@@ -530,18 +503,20 @@ static void dpu_hw_sspp_setup_sourceaddress(struct 
dpu_sw_pipe *pipe,
  static void dpu_hw_sspp_setup_csc(struct dpu_hw_sspp *ctx,
const struct dpu_csc_cfg *data)
  {
-   u32 idx;
+   u32 offset;
bool csc10 = false;
  
-	if (_sspp_subblk_offset(ctx, DPU_SSPP_CSC, ) || !data)

+   if (!ctx || !data)
return;
  
+	offset = ctx->cap->sblk->csc_blk.base;

+
if (test_bit(DPU_SSPP_CSC_10BIT, >cap->features)) {
-   idx += CSC_10BIT_OFFSET;
+   offset += CSC_10BIT_OFFSET;
csc10 = true;
}
  
-	dpu_hw_csc_setup(>hw, idx, data, csc10);

+   dpu_hw_csc_setup(>hw, offset, data, csc10);
  }
  
  static void dpu_hw_sspp_setup_solidfill(struct dpu_sw_pipe *pipe, u32 color)


Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH 2/3] drm/msm/dpu: access QSEED registers directly

2023-04-27 Thread Jeykumar Sankaran




On 4/21/2023 5:08 PM, Dmitry Baryshkov wrote:

Stop using _sspp_subblk_offset() to get offset of the scaler_blk. Inline
this function and use ctx->cap->sblk->scaler_blk.base directly.

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index fce135f010d4..22c59f2250be 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -149,11 +149,6 @@ static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx,
sblk = ctx->cap->sblk;
  
  	switch (s_id) {

-   case DPU_SSPP_SCALER_QSEED2:
-   case DPU_SSPP_SCALER_QSEED3:
-   case DPU_SSPP_SCALER_RGB:
-   *idx = sblk->scaler_blk.base;
-   break;
case DPU_SSPP_CSC:
case DPU_SSPP_CSC_10BIT:
*idx = sblk->csc_blk.base;
@@ -195,22 +190,21 @@ static void dpu_hw_sspp_setup_multirect(struct 
dpu_sw_pipe *pipe)
  static void _sspp_setup_opmode(struct dpu_hw_sspp *ctx,
u32 mask, u8 en)
  {
-   u32 idx;
+   const struct dpu_sspp_sub_blks *sblk = ctx->cap->sblk;
u32 opmode;
  
  	if (!test_bit(DPU_SSPP_SCALER_QSEED2, >cap->features) ||

-   _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED2, ) ||
!test_bit(DPU_SSPP_CSC, >cap->features))
return;
  
-	opmode = DPU_REG_READ(>hw, SSPP_VIG_OP_MODE + idx);

+   opmode = DPU_REG_READ(>hw, sblk->scaler_blk.base + 
SSPP_VIG_OP_MODE);
  
  	if (en)

opmode |= mask;
else
opmode &= ~mask;
  
-	DPU_REG_WRITE(>hw, SSPP_VIG_OP_MODE + idx, opmode);

+   DPU_REG_WRITE(>hw, sblk->scaler_blk.base + SSPP_VIG_OP_MODE, 
opmode);
  }
  
  static void _sspp_setup_csc10_opmode(struct dpu_hw_sspp *ctx,

@@ -416,25 +410,22 @@ static void _dpu_hw_sspp_setup_scaler3(struct dpu_hw_sspp 
*ctx,
struct dpu_hw_scaler3_cfg *scaler3_cfg,
const struct dpu_format *format)
  {
-   u32 idx;
-
-   if (_sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, )
-   || !scaler3_cfg)
+   if (!ctx || !scaler3_cfg)
return;
  
-	dpu_hw_setup_scaler3(>hw, scaler3_cfg, idx,

+   dpu_hw_setup_scaler3(>hw, scaler3_cfg,
+   ctx->cap->sblk->scaler_blk.base,
ctx->cap->sblk->scaler_blk.version,
format);
  }
  
  static u32 _dpu_hw_sspp_get_scaler3_ver(struct dpu_hw_sspp *ctx)

  {
-   u32 idx;
-
-   if (!ctx || _sspp_subblk_offset(ctx, DPU_SSPP_SCALER_QSEED3, ))
+   if (!ctx)
return 0;
  
-	return dpu_hw_get_scaler3_ver(>hw, idx);

+   return dpu_hw_get_scaler3_ver(>hw,
+     ctx->cap->sblk->scaler_blk.base);
  }
  
  /*

Reviewed-by: Jeykumar Sankaran 


Re: [Freedreno] [PATCH 1/3] drm/msm/dpu: drop SSPP's SRC subblock

2023-04-27 Thread Jeykumar Sankaran




On 4/21/2023 5:08 PM, Dmitry Baryshkov wrote:

The src_blk declares a lame copy of main SSPP register space. It's
offset is always 0. It's length has been fixed to 0x150, while SSPP's
length is now correct. Drop the src_blk and access SSPP registers
without additional subblock lookup.

Signed-off-by: Dmitry Baryshkov 
---
  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|   8 --
  .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  10 --
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c   | 114 --
  3 files changed, 48 insertions(+), 84 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 03f162af1a50..24bf1ae75dbf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -252,8 +252,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
-   .src_blk = {.name = STRCAT("sspp_src_", num), \
-   .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
If you are removing the sub block for the source registers and planning 
to use the SSPP's base address, you might as well remove the macro 
DPU_SSPP_SRC and its usage in setup_layer_ops etc. It doesnt make sense 
to check explicity.



Jeykumar S.

.scaler_blk = {.name = STRCAT("sspp_scaler", num), \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -272,8 +270,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = MAX_DOWNSCALE_RATIO, \
.maxupscale = MAX_UPSCALE_RATIO, \
.smart_dma_priority = sdma_pri, \
-   .src_blk = {.name = STRCAT("sspp_src_", num), \
-   .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.scaler_blk = {.name = STRCAT("sspp_scaler", num), \
.id = qseed_ver, \
.base = 0xa00, .len = 0xa0,}, \
@@ -292,8 +288,6 @@ static const uint32_t wb2_formats[] = {
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
.smart_dma_priority = sdma_pri, \
-   .src_blk = {.name = STRCAT("sspp_src_", num), \
-   .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.format_list = plane_formats, \
.num_formats = ARRAY_SIZE(plane_formats), \
.virt_format_list = plane_formats, \
@@ -375,8 +369,6 @@ static const struct dpu_sspp_sub_blks sm8550_dma_sblk_5 = 
_DMA_SBLK("13", 6);
.maxdwnscale = SSPP_UNITY_SCALE, \
.maxupscale = SSPP_UNITY_SCALE, \
.smart_dma_priority = sdma_pri, \
-   .src_blk = {.name = STRCAT("sspp_src_", num), \
-   .id = DPU_SSPP_SRC, .base = 0x00, .len = 0x150,}, \
.format_list = plane_formats_yuv, \
.num_formats = ARRAY_SIZE(plane_formats_yuv), \
.virt_format_list = plane_formats, \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
index 71584cd56fd7..3c7585c91bc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -278,14 +278,6 @@ enum {
u32 base; \
u32 len
  
-/**

- * struct dpu_src_blk: SSPP part of the source pipes
- * @info:   HW register and features supported by this sub-blk
- */
-struct dpu_src_blk {
-   DPU_HW_SUBBLK_INFO;
-};
-
  /**
   * struct dpu_scaler_blk: Scaler information
   * @info:   HW register and features supported by this sub-blk
@@ -392,7 +384,6 @@ struct dpu_caps {
   * @smart_dma_priority: hw priority of rect1 of multirect pipe
   * @max_per_pipe_bw: maximum allowable bandwidth of this pipe in kBps
   * @qseed_ver: qseed version
- * @src_blk:
   * @scaler_blk:
   * @csc_blk:
   * @hsic:
@@ -413,7 +404,6 @@ struct dpu_sspp_sub_blks {
u32 smart_dma_priority;
u32 max_per_pipe_bw;
u32 qseed_ver;
-   struct dpu_src_blk src_blk;
struct dpu_scaler_blk scaler_blk;
struct dpu_pp_blk csc_blk;
struct dpu_pp_blk hsic_blk;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
index cf70a9bd1034..fce135f010d4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_sspp.c
@@ -149,9 +149,6 @@ static int _sspp_subblk_offset(struct dpu_hw_sspp *ctx,
sblk = ctx->cap->sblk;
  
  	switch (s_id) {

-   case DPU_SSPP_SRC:
-   *idx = sblk->src_blk.base;
-   break;
case DPU_SSPP_SCALER_QSEED2:
case DPU_SSPP_SCALER_QSEED3:
case DPU_SSPP_SCALER_RGB:
@@ -172,9 +169,8 @@ static void dpu_hw_sspp_setup_multirect(struct dpu_sw_pipe 
*pipe)
  {
struct dpu_hw_sspp *ctx = pipe->sspp;
u32 mode_mask;
-   u32 idx;
  
-	if (_sspp_subblk_offset(ctx, DPU_SSPP_SRC, ))

+   if (!ctx)
return;
  
  	if (pipe->multirect_index == 

Re: [Freedreno] [PATCH 02/11] drm/msm/dpu: use the actual lm maximum width instead of a hardcoded value

2023-04-21 Thread Jeykumar Sankaran




On 4/19/2023 3:23 PM, Dmitry Baryshkov wrote:

On 19/04/2023 17:41, Arnaud Vrac wrote:

This avoids using two LMs instead of one when the display width is lower
than the maximum supported value. For example on MSM8996/MSM8998, the
actual maxwidth is 2560, so we would use two LMs for 1280x720 or
1920x1080 resolutions, while one is enough.

Signed-off-by: Arnaud Vrac 


While this looks correct (and following what we have in 4.4), later 
vendor kernels specify the topology explicitly. Probably we should check 
this with the hw guys, because it might be the following case: even 
though a single LM can supply the mode, it will spend more power 
compared to two LMs.



Yes. 2 LM split will allow the HW to run in lower mdp core clock. Can 
you maintain the split_threshold in the hw catalog until per mode 
topology is available?


Jeykumar S

---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 10 +-
  1 file changed, 5 insertions(+), 5 deletions(-)

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

index 1dc5dbe585723..dd2914726c4f6 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -53,8 +53,6 @@
  #define IDLE_SHORT_TIMEOUT    1
-#define MAX_HDISPLAY_SPLIT 1080
-
  /* timeout in frames waiting for frame done */
  #define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
@@ -568,10 +566,12 @@ static struct msm_display_topology 
dpu_encoder_get_topology(

   */
  if (intf_count == 2)
  topology.num_lm = 2;
-    else if (!dpu_kms->catalog->caps->has_3d_merge)
-    topology.num_lm = 1;
+    else if (dpu_kms->catalog->caps->has_3d_merge &&
+ dpu_kms->catalog->mixer_count > 0 &&
+ mode->hdisplay > dpu_kms->catalog->mixer[0].sblk->maxwidth)
+    topology.num_lm = 2;
  else
-    topology.num_lm = (mode->hdisplay > MAX_HDISPLAY_SPLIT) ? 2 : 1;
+    topology.num_lm = 1;
  if (crtc_state->ctm)
  topology.num_dspp = topology.num_lm;





Re: [Freedreno] [PATCH 03/11] drm/msm/dpu: use hsync/vsync polarity set by the encoder

2023-04-21 Thread Jeykumar Sankaran




On 4/19/2023 7:41 AM, Arnaud Vrac wrote:

Do not override the hsync/vsync polarity passed by the encoder when
setting up intf timings. The same logic was used in both the encoder and
intf code to set the DP and DSI polarities, so those interfaces are not
impacted. However for HDMI, the polarities were overriden to static
values based on the vertical resolution, instead of using the actual
mode polarities.

Any idea why vres based static polarity override was in place? Hope you 
had tested HDMI resolutions with yres > and < than 720.


Jeykumar S.


Signed-off-by: Arnaud Vrac 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 16 +++-
  1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 84ee2efa9c664..9f05417eb1213 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -104,7 +104,7 @@ static void dpu_hw_intf_setup_timing_engine(struct 
dpu_hw_intf *ctx,
u32 active_h_start, active_h_end;
u32 active_v_start, active_v_end;
u32 active_hctl, display_hctl, hsync_ctl;
-   u32 polarity_ctl, den_polarity, hsync_polarity, vsync_polarity;
+   u32 polarity_ctl, den_polarity;
u32 panel_format;
u32 intf_cfg, intf_cfg2 = 0;
u32 display_data_hctl = 0, active_data_hctl = 0;
@@ -191,19 +191,9 @@ static void dpu_hw_intf_setup_timing_engine(struct 
dpu_hw_intf *ctx,
}
  
  	den_polarity = 0;

-   if (ctx->cap->type == INTF_HDMI) {
-   hsync_polarity = p->yres >= 720 ? 0 : 1;
-   vsync_polarity = p->yres >= 720 ? 0 : 1;
-   } else if (ctx->cap->type == INTF_DP) {
-   hsync_polarity = p->hsync_polarity;
-   vsync_polarity = p->vsync_polarity;
-   } else {
-   hsync_polarity = 0;
-   vsync_polarity = 0;
-   }
polarity_ctl = (den_polarity << 2) | /*  DEN Polarity  */
-   (vsync_polarity << 1) | /* VSYNC Polarity */
-   (hsync_polarity << 0);  /* HSYNC Polarity */
+   (p->vsync_polarity << 1) | /* VSYNC Polarity */
+   (p->hsync_polarity << 0);  /* HSYNC Polarity */
  
  	if (!DPU_FORMAT_IS_YUV(fmt))

panel_format = (fmt->bits[C0_G_Y] |



Re: [Freedreno] [PATCH 0/5] MDSS reg bus interconnect

2023-04-20 Thread Jeykumar Sankaran




On 4/17/2023 8:30 AM, Konrad Dybcio wrote:

Apart from the already handled data bus (MAS_MDP_Pn<->DDR), there's
another path that needs to be handled to ensure MDSS functions properly,
namely the "reg bus", a.k.a the CPU-MDSS interconnect.

Gating that path may have a variety of effects.. from none to otherwise
inexplicable DSI timeouts..
Current DPU driver already votes on the "reg bus" indirectly through the 
display AHB clock handle[< DISP_CC_MDSS_AHB_CLK>] in DTSI. Can 
you provide more details on the issues that warrants this patch series?


Thanks
Jeykumar S


This series tries to address the lack of that.

Example path:

interconnects = < MASTER_AMPSS_M0 0 _noc SLAVE_DISPLAY_CFG 0>;

Signed-off-by: Konrad Dybcio 
---
Konrad Dybcio (5):
   dt-bindings: display/msm: Add reg bus interconnect
   drm/msm/dpu1: Rename path references to mdp_path
   drm/msm/mdss: Rename path references to mdp_path
   drm/msm/mdss: Handle the reg bus ICC path
   drm/msm/dpu1: Handle the reg bus ICC path

  .../bindings/display/msm/mdss-common.yaml  |  1 +
  drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.c  | 10 +++
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c| 34 -
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h|  5 ++--
  drivers/gpu/drm/msm/msm_mdss.c | 35 ++
  5 files changed, 57 insertions(+), 28 deletions(-)
---
base-commit: d3f2cd24819158bb70701c3549e586f9df9cee67
change-id: 20230417-topic-dpu_regbus-abc94a770952

Best regards,


Re: [Freedreno] [PATCH 1/5] dt-bindings: display/msm: Add reg bus interconnect

2023-04-20 Thread Jeykumar Sankaran
Resending the question as the previous one was sent only to the 
freedreno list. Apologies for spamming!


On 4/17/2023 8:30 AM, Konrad Dybcio wrote:

Apart from the already handled data bus (MAS_MDP_Pn<->DDR), there's
another path that needs to be handled to ensure MDSS functions properly,
namely the "reg bus", a.k.a the CPU-MDSS interconnect.

Gating that path may have a variety of effects.. from none to otherwise
inexplicable DSI timeouts..

Describe it in bindings to allow for use in device trees.

Signed-off-by: Konrad Dybcio 
---
  Documentation/devicetree/bindings/display/msm/mdss-common.yaml | 1 +
  1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/display/msm/mdss-common.yaml 
b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml
index ccd7d6417523..9eb5b6d3e0b9 100644
--- a/Documentation/devicetree/bindings/display/msm/mdss-common.yaml
+++ b/Documentation/devicetree/bindings/display/msm/mdss-common.yaml
@@ -72,6 +72,7 @@ properties:
  items:
- const: mdp0-mem
- const: mdp1-mem
+  - const: cpu-cfg
  

If posted already, please point to the DTSI patch for this ICC path.

resets:
  items:



Re: [Freedreno] [PATCH 5/5] drm/msm/dpu1: Handle the reg bus ICC path

2023-04-20 Thread Jeykumar Sankaran




On 4/19/2023 12:48 PM, Konrad Dybcio wrote:



On 19.04.2023 21:06, Jeykumar Sankaran wrote:



On 4/17/2023 8:30 AM, Konrad Dybcio wrote:

Apart from the already handled data bus (MAS_MDP_Pn<->DDR), there's
another path that needs to be handled to ensure MDSS functions properly,
namely the "reg bus", a.k.a the CPU-MDSS interconnect.

Gating that path may have a variety of effects.. from none to otherwise
inexplicable DSI timeouts..

On the DPU side, we need to keep the bus alive. The vendor driver
kickstarts it to max (300Mbps) throughput on first commit, but in
exchange for some battery life in rare DPU-enabled-panel-disabled
usecases, we can request it at DPU init and gate it at suspend.

Signed-off-by: Konrad Dybcio 
---
   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 22 --
   drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
   2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index dd6c1c40ab9e..d1f77faebbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -384,15 +384,17 @@ static int dpu_kms_global_obj_init(struct dpu_kms 
*dpu_kms)
   return 0;
   }
   -static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms)
+static int dpu_kms_parse_icc_paths(struct dpu_kms *dpu_kms)
   {
   struct icc_path *path0;
   struct icc_path *path1;
+    struct icc_path *reg_bus_path;
   struct drm_device *dev = dpu_kms->dev;
   struct device *dpu_dev = dev->dev;
     path0 = msm_icc_get(dpu_dev, "mdp0-mem");
   path1 = msm_icc_get(dpu_dev, "mdp1-mem");
+    reg_bus_path = msm_icc_get(dpu_dev, "cpu-cfg");
     if (IS_ERR_OR_NULL(path0))
   return PTR_ERR_OR_ZERO(path0);
@@ -404,6 +406,10 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms 
*dpu_kms)
   dpu_kms->mdp_path[1] = path1;
   dpu_kms->num_mdp_paths++;
   }
+
+    if (!IS_ERR_OR_NULL(reg_bus_path))
+    dpu_kms->reg_bus_path = reg_bus_path;
+
   return 0;
   }
   @@ -1039,7 +1045,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
   DPU_DEBUG("REG_DMA is not defined");
   }
   -    dpu_kms_parse_data_bus_icc_path(dpu_kms);
+    dpu_kms_parse_icc_paths(dpu_kms);
     rc = pm_runtime_resume_and_get(_kms->pdev->dev);
   if (rc < 0)
@@ -1241,6 +1247,9 @@ static int __maybe_unused dpu_runtime_suspend(struct 
device *dev)
   for (i = 0; i < dpu_kms->num_mdp_paths; i++)
   icc_set_bw(dpu_kms->mdp_path[i], 0, 0);
   +    if (dpu_kms->reg_bus_path)
+    icc_set_bw(dpu_kms->reg_bus_path, 0, 0);
+
   return 0;
   }
   @@ -1261,6 +1270,15 @@ static int __maybe_unused dpu_runtime_resume(struct 
device *dev)
   return rc;
   }
   +    /*
+ * The vendor driver supports setting 76.8 / 150 / 300 Mbps on this

How do you arrive at these distint BW values? Are they provided by the ICC fwk 
for the given path?

They're hardcoded in the SDE driver.

Konrad
These bandwidths are derived from the scaling frequencies of all the 
buses participating in the icc-path. So they cannot be constants. 
Ideally they should be read from the hw catalog data of the respective 
platform.


Jeykumar S.

+ * path, but it seems to go for the highest level when display output
+ * is enabled and zero otherwise. For simplicity, we can assume that
+ * DPU being enabled and running implies that.
+ */
+    if (dpu_kms->reg_bus_path)
+    icc_set_bw(dpu_kms->reg_bus_path, 0, MBps_to_icc(300));
+
   dpu_vbif_init_memtypes(dpu_kms);
     drm_for_each_encoder(encoder, ddev)
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index d5d9bec90705..c332381d58c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -111,6 +111,7 @@ struct dpu_kms {
   atomic_t bandwidth_ref;
   struct icc_path *mdp_path[2];
   u32 num_mdp_paths;
+    struct icc_path *reg_bus_path;
   };
     struct vsync_info {



Re: [Freedreno] [PATCH 5/5] drm/msm/dpu1: Handle the reg bus ICC path

2023-04-20 Thread Jeykumar Sankaran




On 4/17/2023 8:30 AM, Konrad Dybcio wrote:

Apart from the already handled data bus (MAS_MDP_Pn<->DDR), there's
another path that needs to be handled to ensure MDSS functions properly,
namely the "reg bus", a.k.a the CPU-MDSS interconnect.

Gating that path may have a variety of effects.. from none to otherwise
inexplicable DSI timeouts..

On the DPU side, we need to keep the bus alive. The vendor driver
kickstarts it to max (300Mbps) throughput on first commit, but in
exchange for some battery life in rare DPU-enabled-panel-disabled
usecases, we can request it at DPU init and gate it at suspend.

Signed-off-by: Konrad Dybcio 
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 22 --
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
  2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index dd6c1c40ab9e..d1f77faebbc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -384,15 +384,17 @@ static int dpu_kms_global_obj_init(struct dpu_kms 
*dpu_kms)
return 0;
  }
  
-static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms *dpu_kms)

+static int dpu_kms_parse_icc_paths(struct dpu_kms *dpu_kms)
  {
struct icc_path *path0;
struct icc_path *path1;
+   struct icc_path *reg_bus_path;
struct drm_device *dev = dpu_kms->dev;
struct device *dpu_dev = dev->dev;
  
  	path0 = msm_icc_get(dpu_dev, "mdp0-mem");

path1 = msm_icc_get(dpu_dev, "mdp1-mem");
+   reg_bus_path = msm_icc_get(dpu_dev, "cpu-cfg");
  
  	if (IS_ERR_OR_NULL(path0))

return PTR_ERR_OR_ZERO(path0);
@@ -404,6 +406,10 @@ static int dpu_kms_parse_data_bus_icc_path(struct dpu_kms 
*dpu_kms)
dpu_kms->mdp_path[1] = path1;
dpu_kms->num_mdp_paths++;
}
+
+   if (!IS_ERR_OR_NULL(reg_bus_path))
+   dpu_kms->reg_bus_path = reg_bus_path;
+
return 0;
  }
  
@@ -1039,7 +1045,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)

DPU_DEBUG("REG_DMA is not defined");
}
  
-	dpu_kms_parse_data_bus_icc_path(dpu_kms);

+   dpu_kms_parse_icc_paths(dpu_kms);
  
  	rc = pm_runtime_resume_and_get(_kms->pdev->dev);

if (rc < 0)
@@ -1241,6 +1247,9 @@ static int __maybe_unused dpu_runtime_suspend(struct 
device *dev)
for (i = 0; i < dpu_kms->num_mdp_paths; i++)
icc_set_bw(dpu_kms->mdp_path[i], 0, 0);
  
+	if (dpu_kms->reg_bus_path)

+   icc_set_bw(dpu_kms->reg_bus_path, 0, 0);
+
return 0;
  }
  
@@ -1261,6 +1270,15 @@ static int __maybe_unused dpu_runtime_resume(struct device *dev)

return rc;
}
  
+	/*

+* The vendor driver supports setting 76.8 / 150 / 300 Mbps on this
How do you arrive at these distint BW values? Are they provided by the 
ICC fwk for the given path?

+* path, but it seems to go for the highest level when display output
+* is enabled and zero otherwise. For simplicity, we can assume that
+* DPU being enabled and running implies that.
+*/
+   if (dpu_kms->reg_bus_path)
+   icc_set_bw(dpu_kms->reg_bus_path, 0, MBps_to_icc(300));
+
dpu_vbif_init_memtypes(dpu_kms);
  
  	drm_for_each_encoder(encoder, ddev)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index d5d9bec90705..c332381d58c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -111,6 +111,7 @@ struct dpu_kms {
atomic_t bandwidth_ref;
struct icc_path *mdp_path[2];
u32 num_mdp_paths;
+   struct icc_path *reg_bus_path;
  };
  
  struct vsync_info {




[PATCH] drm/connector: notify userspace on hotplug after register complete

2020-06-02 Thread Jeykumar Sankaran
drm connector notifies userspace on hotplug event prematurely before
late_register and mode_object register completes. This leads to a race
between userspace and kernel on updating the IDR list. So, move the
notification to end of connector register.

Signed-off-by: Jeykumar Sankaran 
Signed-off-by: Steve Cohen 
---
 drivers/gpu/drm/drm_connector.c | 5 +
 drivers/gpu/drm/drm_sysfs.c | 3 ---
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index b1099e1..d877ddc 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -523,6 +524,10 @@ int drm_connector_register(struct drm_connector *connector)
drm_mode_object_register(connector->dev, >base);
 
connector->registration_state = DRM_CONNECTOR_REGISTERED;
+
+   /* Let userspace know we have a new connector */
+   drm_sysfs_hotplug_event(connector->dev);
+
goto unlock;
 
 err_debugfs:
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 939f003..f0336c8 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -291,9 +291,6 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
return PTR_ERR(connector->kdev);
}
 
-   /* Let userspace know we have a new connector */
-   drm_sysfs_hotplug_event(dev);
-
if (connector->ddc)
return sysfs_create_link(>kdev->kobj,
 >ddc->dev.kobj, "ddc");
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH] drm/meson: fix max mode_config height/width

2019-10-11 Thread Jeykumar Sankaran

On 2019-10-09 03:47, Daniel Vetter wrote:

On Tue, Sep 24, 2019 at 10:28:48AM -0700, Jeykumar Sankaran wrote:

Reviving this thread from the context of the below conversion:



https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332881
@baylibre.com/T/#u


On 2018-10-05 01:19, Neil Armstrong wrote:
> On 05/10/2018 09:58, Daniel Vetter wrote:
> > On Fri, Oct 5, 2018 at 9:39 AM Neil Armstrong
> >  wrote:
> > >
>
> [...]
>
> > > OK, won't this be enough ?
> > > --- a/include/drm/drm_mode_config.h
> > > +++ b/include/drm/drm_mode_config.h
> > > @@ -333,6 +333,8 @@ struct drm_mode_config_funcs {
> > >   * @min_height: minimum fb pixel height on this device
> > >   * @max_width: maximum fb pixel width on this device
> > >   * @max_height: maximum fb pixel height on this device
> > > + * @max_fb_width: maximum fb buffer width if differs from

max_width

> > > + * @max_fb_height: maximum fb buffer height if differs from
> > > max_height
> > >   * @funcs: core driver provided mode setting functions
> > >   * @fb_base: base address of the framebuffer
> > >   * @poll_enabled: track polling support for this device
> > > @@ -508,6 +510,7 @@ struct drm_mode_config {
> > >
> > > int min_width, min_height;
> > > int max_width, max_height;
> > > +   int max_fb_width, max_fb_height;
> > > const struct drm_mode_config_funcs *funcs;
> > > resource_size_t fb_base;
> > >
> > > --- a/drivers/gpu/drm/drm_framebuffer.c
> > > +++ b/drivers/gpu/drm/drm_framebuffer.c
> > > @@ -283,14 +283,20 @@ drm_internal_framebuffer_create(struct
> > > drm_device *dev,
> > > return ERR_PTR(-EINVAL);
> > > }
> > >
> > > -   if ((config->min_width > r->width) || (r->width >
> > > config->max_width)) {
> > > +   if ((config->min_width > r->width) ||
> > > +   (!config->max_fb_width && r->width >
> > > config->max_width) ||
> > > +   (config->max_fb_width && r->width >
> > > config->max_fb_width)) {
> > > DRM_DEBUG_KMS("bad framebuffer width %d, should
> > > be >= %d && <= %d\n",
> > > - r->width, config->min_width,
> > > config->max_width);
> > > + r->width, config->min_width,
> > > config->max_fb_width ?
> > > + config->max_fb_width :

config->max_width);

> > > return ERR_PTR(-EINVAL);
> > > }
> > > -   if ((config->min_height > r->height) || (r->height >
> > > config->max_height)) {
> > > +   if ((config->min_height > r->height) ||
> > > +   (!config->max_fb_height && r->height >
> > > config->max_height) ||
> > > +   (config->max_fb_height && r->height >
> > > config->max_fb_height)) {
> > > DRM_DEBUG_KMS("bad framebuffer height %d, should
> > > be >= %d && <= %d\n",
> > > - r->height, config->min_height,
> > > config->max_height);
> > > + r->height, config->min_height,
> > > config->max_fb_height ?
> > > + config->max_fb_height :
> > > config->max_height);
> > > return ERR_PTR(-EINVAL);
> > > }
> > >
> > > and in the driver :
> > >
> > > +   drm->mode_config.max_width = 4096;
> > > +   drm->mode_config.max_height = 3840;
> > > +   drm->mode_config.max_fb_width = 16384;
> > > +   drm->mode_config.max_fb_height = 8192;
> > >
> > > With this I leave the mode filtering intact.
> >
> > Not enough. See
> >

https://dri.freedesktop.org/docs/drm/gpu/drm-kms-helpers.html#c.drm_connec
tor_helper_funcs

> > and scroll down to mode_valid. You need to filter modes both in the
> > detect paths, and the atomic_check paths.
> >
> > Detect is explicitly filtered out, but atomic_check was only
> > implicitly filtered, through the max fb size checks. Ok, you could
> > light up a mode that's bigger than max fb, but in practice, no
> > userspace ever did that.

Daniel, MSM and few other vendor hardware have upscale blocks where 
the

driver can expose fb 

Re: [PATCH] drm: add fb max width/height fields to drm_mode_config

2019-10-01 Thread Jeykumar Sankaran

On 2019-09-30 03:39, Ville Syrjälä wrote:

On Fri, Sep 27, 2019 at 06:28:51PM -0700, Jeykumar Sankaran wrote:

The mode_config max width/height values determine the maximum
resolution the pixel reader can handle.


Not according to the docs I "fixed" a while ago.


But the same values are
used to restrict the size of the framebuffer creation. Hardware's
with scaling blocks can operate on framebuffers larger/smaller than
that of the pixel reader resolutions by scaling them down/up before
rendering.

This changes adds a separate framebuffer max width/height fields
in drm_mode_config to allow vendors to set if they are different
than that of the default max resolution values.


If you're going to change the meaning of the old values you need
to fix the drivers too.

Personally I don't see too much point in this since you most likely
want to validate all the other timings as well, and so likely need
some kind of mode_valid implementation anyway. Hence to validate
modes there's not much benefit of having global min/max values.


https://patchwork.kernel.org/patch/10467155/

I believe you are referring to this patch.

I am primarily interested in the scaling scenario mentioned here. MSM
and a few other hardware have scaling block that are used both ways:

1) Where FB limits are larger than the display limits. Scalar blocks are 
used to

   downscale the framebuffers and render within display limits.

In this scenario, with your patch, are you suggesting the drivers 
maintain the
display limits locally and use those values in fill_modes() / 
mode_valid() to filter

out invalid modes explicitly instead of mode_config.max_width/height?

2) Where FB limits are smaller than display limits. Enforced for 
performance reasons on low tier hardware.
It reduces the fetch bandwidth and uses post blending scalar block to 
scale up the pixel stream

to match the display resolution.

Any suggestions on how this topology can be handled with a single set of 
max/min values?


Thanks and Regards,
Jeykumar S.


Vendors setting these fields should fix their mode_set paths too
by filtering and validating the modes against the appropriate max
fields in their mode_valid() implementations.

Signed-off-by: Neil Armstrong 
Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/drm_framebuffer.c | 15 +++
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_framebuffer.c

b/drivers/gpu/drm/drm_framebuffer.c

index 5756431..2083168 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -300,14 +300,21 @@ struct drm_framebuffer *
return ERR_PTR(-EINVAL);
}

-   if ((config->min_width > r->width) || (r->width >

config->max_width)) {

+   if ((config->min_width > r->width) ||
+   (!config->max_fb_width && r->width > config->max_width) ||
+   (config->max_fb_width && r->width > config->max_fb_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d

&& <= %d\n",

- r->width, config->min_width, config->max_width);
+   r->width, config->min_width, config->max_fb_width

?

+   config->max_fb_width : config->max_width);
return ERR_PTR(-EINVAL);
}
-   if ((config->min_height > r->height) || (r->height >

config->max_height)) {

+
+   if ((config->min_height > r->height) ||
+   (!config->max_fb_height && r->height > config->max_height) ||
+   (config->max_fb_height && r->height > config->max_fb_height))

{

DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d

&& <= %d\n",

- r->height, config->min_height,

config->max_height);

+   r->height, config->min_height,

config->max_fb_width ?

+   config->max_fb_height : config->max_height);
return ERR_PTR(-EINVAL);
}

diff --git a/include/drm/drm_mode_config.h

b/include/drm/drm_mode_config.h

index 3bcbe30..c6394ed 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -339,6 +339,8 @@ struct drm_mode_config_funcs {
  * @min_height: minimum fb pixel height on this device
  * @max_width: maximum fb pixel width on this device
  * @max_height: maximum fb pixel height on this device
+ * @max_fb_width: maximum fb buffer width if differs from max_width
+ * @max_fb_height: maximum fb buffer height if differs from  
max_height

  * @funcs: core driver provided mode setting functions
  * @fb_base: base address of the framebuffer
  * @poll_enabled: track polling support for this device
@@ -523,6 +525,7 @@ struct drm_mode_config {

   

[PATCH] drm: add fb max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
The mode_config max width/height values determine the maximum
resolution the pixel reader can handle. But the same values are
used to restrict the size of the framebuffer creation. Hardware's
with scaling blocks can operate on framebuffers larger/smaller than
that of the pixel reader resolutions by scaling them down/up before
rendering.

This changes adds a separate framebuffer max width/height fields
in drm_mode_config to allow vendors to set if they are different
than that of the default max resolution values.

Vendors setting these fields should fix their mode_set paths too
by filtering and validating the modes against the appropriate max
fields in their mode_valid() implementations.

Signed-off-by: Neil Armstrong 
Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/drm_framebuffer.c | 15 +++
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 5756431..2083168 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -300,14 +300,21 @@ struct drm_framebuffer *
return ERR_PTR(-EINVAL);
}
 
-   if ((config->min_width > r->width) || (r->width > config->max_width)) {
+   if ((config->min_width > r->width) ||
+   (!config->max_fb_width && r->width > config->max_width) ||
+   (config->max_fb_width && r->width > config->max_fb_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= 
%d\n",
- r->width, config->min_width, config->max_width);
+   r->width, config->min_width, config->max_fb_width ?
+   config->max_fb_width : config->max_width);
return ERR_PTR(-EINVAL);
}
-   if ((config->min_height > r->height) || (r->height > 
config->max_height)) {
+
+   if ((config->min_height > r->height) ||
+   (!config->max_fb_height && r->height > config->max_height) ||
+   (config->max_fb_height && r->height > config->max_fb_height)) {
DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= 
%d\n",
- r->height, config->min_height, config->max_height);
+   r->height, config->min_height, config->max_fb_width ?
+   config->max_fb_height : config->max_height);
return ERR_PTR(-EINVAL);
}
 
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 3bcbe30..c6394ed 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -339,6 +339,8 @@ struct drm_mode_config_funcs {
  * @min_height: minimum fb pixel height on this device
  * @max_width: maximum fb pixel width on this device
  * @max_height: maximum fb pixel height on this device
+ * @max_fb_width: maximum fb buffer width if differs from max_width
+ * @max_fb_height: maximum fb buffer height if differs from  max_height
  * @funcs: core driver provided mode setting functions
  * @fb_base: base address of the framebuffer
  * @poll_enabled: track polling support for this device
@@ -523,6 +525,7 @@ struct drm_mode_config {
 
int min_width, min_height;
int max_width, max_height;
+   int max_fb_width, max_fb_height;
const struct drm_mode_config_funcs *funcs;
resource_size_t fb_base;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] Add framebuffer max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
Below two discussion threads will provide the context behind this patch.

https://www.spinics.net/lists/dri-devel/msg229070.html
https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332...@baylibre.com/T/

Seperating out the core framework patch from vendor implementation.

Jeykumar Sankaran (1):
  drm: add fb max width/height fields to drm_mode_config

 drivers/gpu/drm/drm_framebuffer.c | 17 +
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 16 insertions(+), 4 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] Add framebuffer max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
Below two discussion threads will provide the context behind this patch.

https://www.spinics.net/lists/dri-devel/msg229070.html
https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332...@baylibre.com/T/

Seperating out the core framework patch from vendor implementation.

Jeykumar Sankaran (1):
  drm: add fb max width/height fields to drm_mode_config

 drivers/gpu/drm/drm_framebuffer.c | 17 +
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 16 insertions(+), 4 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] drm: add fb max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
The mode_config max width/height values determine the maximum
resolution the pixel reader can handle. But the same values are
used to restrict the size of the framebuffer creation. Hardware's
with scaling blocks can operate on framebuffers larger/smaller than
that of the pixel reader resolutions by scaling them down/up before
rendering.

This changes adds a separate framebuffer max width/height fields
in drm_mode_config to allow vendors to set if they are different
than that of the default max resolution values.

Vendors setting these fields should fix their mode_set paths too
by filtering and validating the modes against the appropriate max
fields in their mode_valid() implementations.

Signed-off-by: Neil Armstrong 
Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/drm_framebuffer.c | 15 +++
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_framebuffer.c 
b/drivers/gpu/drm/drm_framebuffer.c
index 5756431..2083168 100644
--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -300,14 +300,21 @@ struct drm_framebuffer *
return ERR_PTR(-EINVAL);
}
 
-   if ((config->min_width > r->width) || (r->width > config->max_width)) {
+   if ((config->min_width > r->width) ||
+   (!config->max_fb_width && r->width > config->max_width) ||
+   (config->max_fb_width && r->width > config->max_fb_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= %d && <= 
%d\n",
- r->width, config->min_width, config->max_width);
+   r->width, config->min_width, config->max_fb_width ?
+   config->max_fb_width : config->max_width);
return ERR_PTR(-EINVAL);
}
-   if ((config->min_height > r->height) || (r->height > 
config->max_height)) {
+
+   if ((config->min_height > r->height) ||
+   (!config->max_fb_height && r->height > config->max_height) ||
+   (config->max_fb_height && r->height > config->max_fb_height)) {
DRM_DEBUG_KMS("bad framebuffer height %d, should be >= %d && <= 
%d\n",
- r->height, config->min_height, config->max_height);
+   r->height, config->min_height, config->max_fb_width ?
+   config->max_fb_height : config->max_height);
return ERR_PTR(-EINVAL);
}
 
diff --git a/include/drm/drm_mode_config.h b/include/drm/drm_mode_config.h
index 3bcbe30..c6394ed 100644
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -339,6 +339,8 @@ struct drm_mode_config_funcs {
  * @min_height: minimum fb pixel height on this device
  * @max_width: maximum fb pixel width on this device
  * @max_height: maximum fb pixel height on this device
+ * @max_fb_width: maximum fb buffer width if differs from max_width
+ * @max_fb_height: maximum fb buffer height if differs from  max_height
  * @funcs: core driver provided mode setting functions
  * @fb_base: base address of the framebuffer
  * @poll_enabled: track polling support for this device
@@ -523,6 +525,7 @@ struct drm_mode_config {
 
int min_width, min_height;
int max_width, max_height;
+   int max_fb_width, max_fb_height;
const struct drm_mode_config_funcs *funcs;
resource_size_t fb_base;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project



[PATCH] Add framebuffer max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
Below two discussion threads will provide the context behind this patch.

https://www.spinics.net/lists/dri-devel/msg229070.html
https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332...@baylibre.com/T/

Seperating out the core framework patch from vendor implementation.

Jeykumar Sankaran (1):
  drm: add fb max width/height fields to drm_mode_config

 drivers/gpu/drm/drm_framebuffer.c | 17 +
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 16 insertions(+), 4 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH] Add framebuffer max width/height fields to drm_mode_config

2019-09-27 Thread Jeykumar Sankaran
Below two discussion threads will provide the context behind this patch.

https://www.spinics.net/lists/dri-devel/msg229070.html
https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332...@baylibre.com/T/

Seperating out the core framework patch from vendor implementation.

Jeykumar Sankaran (1):
  drm: add fb max width/height fields to drm_mode_config

 drivers/gpu/drm/drm_framebuffer.c | 17 +
 include/drm/drm_mode_config.h |  3 +++
 2 files changed, 16 insertions(+), 4 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [PATCH] drm/meson: fix max mode_config height/width

2019-09-24 Thread Jeykumar Sankaran

Reviving this thread from the context of the below conversion:

https://lore.kernel.org/linux-arm-msm/db26145b-3f64-a334-f698-76f972332...@baylibre.com/T/#u

On 2018-10-05 01:19, Neil Armstrong wrote:

On 05/10/2018 09:58, Daniel Vetter wrote:
On Fri, Oct 5, 2018 at 9:39 AM Neil Armstrong 
 wrote:




[...]


OK, won't this be enough ?
--- a/include/drm/drm_mode_config.h
+++ b/include/drm/drm_mode_config.h
@@ -333,6 +333,8 @@ struct drm_mode_config_funcs {
  * @min_height: minimum fb pixel height on this device
  * @max_width: maximum fb pixel width on this device
  * @max_height: maximum fb pixel height on this device
+ * @max_fb_width: maximum fb buffer width if differs from max_width
+ * @max_fb_height: maximum fb buffer height if differs from 
max_height

  * @funcs: core driver provided mode setting functions
  * @fb_base: base address of the framebuffer
  * @poll_enabled: track polling support for this device
@@ -508,6 +510,7 @@ struct drm_mode_config {

int min_width, min_height;
int max_width, max_height;
+   int max_fb_width, max_fb_height;
const struct drm_mode_config_funcs *funcs;
resource_size_t fb_base;

--- a/drivers/gpu/drm/drm_framebuffer.c
+++ b/drivers/gpu/drm/drm_framebuffer.c
@@ -283,14 +283,20 @@ drm_internal_framebuffer_create(struct 
drm_device *dev,

return ERR_PTR(-EINVAL);
}

-   if ((config->min_width > r->width) || (r->width > 
config->max_width)) {

+   if ((config->min_width > r->width) ||
+   (!config->max_fb_width && r->width > config->max_width) 
||
+   (config->max_fb_width && r->width > 
config->max_fb_width)) {
DRM_DEBUG_KMS("bad framebuffer width %d, should be >= 
%d && <= %d\n",
- r->width, config->min_width, 
config->max_width);
+ r->width, config->min_width, 
config->max_fb_width ?

+ config->max_fb_width : config->max_width);
return ERR_PTR(-EINVAL);
}
-   if ((config->min_height > r->height) || (r->height > 
config->max_height)) {

+   if ((config->min_height > r->height) ||
+   (!config->max_fb_height && r->height > 
config->max_height) ||
+   (config->max_fb_height && r->height > 
config->max_fb_height)) {
DRM_DEBUG_KMS("bad framebuffer height %d, should be 
>= %d && <= %d\n",
- r->height, config->min_height, 
config->max_height);
+ r->height, config->min_height, 
config->max_fb_height ?
+ config->max_fb_height : 
config->max_height);

return ERR_PTR(-EINVAL);
}

and in the driver :

+   drm->mode_config.max_width = 4096;
+   drm->mode_config.max_height = 3840;
+   drm->mode_config.max_fb_width = 16384;
+   drm->mode_config.max_fb_height = 8192;

With this I leave the mode filtering intact.


Not enough. See
https://dri.freedesktop.org/docs/drm/gpu/drm-kms-helpers.html#c.drm_connector_helper_funcs
and scroll down to mode_valid. You need to filter modes both in the
detect paths, and the atomic_check paths.

Detect is explicitly filtered out, but atomic_check was only
implicitly filtered, through the max fb size checks. Ok, you could
light up a mode that's bigger than max fb, but in practice, no
userspace ever did that.


Daniel, MSM and few other vendor hardware have upscale blocks where the 
driver can expose fb sizes smaller than
the mode resolution and use h/w upscaling to fill the screen. This would 
optimize the fetch bandwidth.


But with your code we're missing crucial

validation now, and userspace could fall over that. What I think we
need is to add mode filter against mode_config.max_width/height in
drm_atomic_helper_check_modeset(). Probably best to stuff that into
the mode_valid() function.


Agreed! Since the above patch from Niel is taking care of cases where 
max/min fb values
are not set, by checking against the original max/min values, can we 
separate out this
core change from the driver level mode_valid changes? If Niel couldn't 
find the time, I can

repost the above change.

Thanks and Regards,
Jeykumar S.


Ok I understood now, thanks for pointer, I'll try to add this.

Neil



Cheers, Daniel


Neil



-Daniel



Neil



Bunch of igt to make sure we're not missing anything would be 
sweet on
top, e.g. e.g. trying to set a mode over the limit and making sure 
it

fails.

Cheers, Daniel


---
 drivers/gpu/drm/meson/meson_drv.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/meson/meson_drv.c 
b/drivers/gpu/drm/meson/meson_drv.c

index d344312..2e29968 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -243,8 +243,8 @@ static int meson_drv_bind_master(struct 
device *dev, bool has_components)

 goto free_drm;

 drm_mode_config_init(drm);
-drm->mode_config.max_width = 3840;
-drm->mode_config.max_height 

Re: [RFC] Expanding drm_mode_modeinfo flags

2019-07-28 Thread Jeykumar Sankaran

On 2019-07-24 07:48, Sean Paul wrote:

On Mon, Jul 22, 2019 at 04:50:43PM -0700, Jeykumar Sankaran wrote:

On 2019-07-19 07:29, Sean Paul wrote:
> On Fri, Jul 19, 2019 at 05:15:28PM +0300, Ville Syrjälä wrote:
> > On Fri, Jul 19, 2019 at 09:55:58AM -0400, Sean Paul wrote:
> > > On Fri, Jul 19, 2019 at 11:05:53AM +0200, Daniel Vetter wrote:
> > > > On Thu, Jul 18, 2019 at 11:18:42AM -0700, Jeykumar Sankaran

wrote:

> > > > > On 2019-07-16 02:07, Daniel Vetter wrote:
> > > > > > On Thu, Jul 11, 2019 at 11:46:44AM -0700, Jeykumar Sankaran

wrote:

>
> /snip
>
> > > > > > >   drm: add mode flags in uapi for seamless mode switch
> > > > > >
> > > > > > I think the uapi is the trivial part here, the real deal is

how

> > > > > > userspace
> > > > > > uses this. Can you pls post the patches for your compositor?
> > > > > >
> > > > > > Also note that we already allow userspace to tell the kernel

whether

> > > > > > flickering is ok or not for a modeset. msm driver could use

that to at

> > > > > > least tell userspace whether a modeset change is possible.

So you can

> > > > > > already implement glitch-free modeset changes for at least

video mode.

> > > > > > -Daniel
> > > > >
> > > > > I believe you are referring to the below tv property of the

connector.

> > > > >
> > > > > /**
> > > > >  * @tv_flicker_reduction_property: Optional TV property to

control the

> > > > >  * flicker reduction mode.
> > > > >  */
> > > > > struct drm_property *tv_flicker_reduction_property;
> > > >
> > > > Not even close :-)
> > > >
> > > > I mean the DRM_MODE_ATOMIC_ALLOW_MODESET flag for the atomic

ioctl. This

> > > > is not a property of a mode, this is a property of a

_transition_ between

> > > > configurations. Some transitions can be done flicker free,

others can't.

> > >
> > > Agree that an atomic flag on a commit is the way to accomplish

this. It's pretty

> > > similar to the psr transitions, where we want to reuse most of the

atomic

> > > circuitry, but in a specialized way. We'd also have to be careful

to only

> > > involve the drm objects which are seamless modeset aware (you

could imagine

> > > a bridge chain where the bridges downstream of the first bridge

don't care).

> > >
> > > >
> > > > There's then still the question of how to pick video vs command

mode, but

> > > > imo better to start with implementing the transition behaviour

correctly

> > > > first.
> > >
> > > Connector property? Possibly a terrible idea, but I wonder if we

could [re]use

> > > the vrr properties for command mode. The docs state that the

driver has the

> > > option of putting upper and lower bounds on the refresh rate.
> >
> > Not really sure why this needs new props and whatnot. This is kinda
> > what
> > the i915 "fastset" stuff already does:
> > 1. userspace asks for something to be changed via atomic
> > 2. driver calculates whether a modeset is actually required
> > 3. atomic validates need_modeset() vs. DRM_MODE_ATOMIC_ALLOW_MODESET
> > 4. if (need_modeset) heavyweight_commit() else lightweight_commit()
> >
> > Ie. why should userspace really care about anything except the
> > "flickers are OK" vs. "flickers not wanted" thing?
>
> Agree, I don't think the seamless modeset (ie: changing resolution
> without
> flicker) needs a property. Just need to test the commit without
> ALLOW_MODESET
> and commit it if the test passes.
>

Agreed that a TEST_ONLY commit without ALLOW_MODESET flag can be used 
to

check
whether the modeset can be done seamless. But since there are no error

code

returns,
the client cannot distinguish the test_only commit failures from other
invalid config failures.

Also, note that when the client sees two 1080p modes (vid/cmd) and it 
is

interested only
to do *only* seamless switches, without any additional flag it cannot
distinguish between
these two 1080p modes. The client has to invoke two test_only commits

with

these
modes to identify the seamless one. Is that a preferred approach?


Hi Jey!
Yeah, pretty much. Stepping back a bit though, why is the kernel 
exposing

2
1080p modes in the first place? If you just expose one mode and then 
use a

property to enter "low-latency operation" (or overloading vrr for cmd
mode), you
shouldn't need to do the mode

Re: [RFC] Expanding drm_mode_modeinfo flags

2019-07-22 Thread Jeykumar Sankaran

On 2019-07-19 07:29, Sean Paul wrote:

On Fri, Jul 19, 2019 at 05:15:28PM +0300, Ville Syrjälä wrote:

On Fri, Jul 19, 2019 at 09:55:58AM -0400, Sean Paul wrote:
> On Fri, Jul 19, 2019 at 11:05:53AM +0200, Daniel Vetter wrote:
> > On Thu, Jul 18, 2019 at 11:18:42AM -0700, Jeykumar Sankaran wrote:
> > > On 2019-07-16 02:07, Daniel Vetter wrote:
> > > > On Thu, Jul 11, 2019 at 11:46:44AM -0700, Jeykumar Sankaran wrote:


/snip


> > > > >   drm: add mode flags in uapi for seamless mode switch
> > > >
> > > > I think the uapi is the trivial part here, the real deal is how
> > > > userspace
> > > > uses this. Can you pls post the patches for your compositor?
> > > >
> > > > Also note that we already allow userspace to tell the kernel whether
> > > > flickering is ok or not for a modeset. msm driver could use that to at
> > > > least tell userspace whether a modeset change is possible. So you can
> > > > already implement glitch-free modeset changes for at least video mode.
> > > > -Daniel
> > >
> > > I believe you are referring to the below tv property of the connector.
> > >
> > > /**
> > >  * @tv_flicker_reduction_property: Optional TV property to control the
> > >  * flicker reduction mode.
> > >  */
> > > struct drm_property *tv_flicker_reduction_property;
> >
> > Not even close :-)
> >
> > I mean the DRM_MODE_ATOMIC_ALLOW_MODESET flag for the atomic ioctl. This
> > is not a property of a mode, this is a property of a _transition_ between
> > configurations. Some transitions can be done flicker free, others can't.
>
> Agree that an atomic flag on a commit is the way to accomplish this. It's 
pretty
> similar to the psr transitions, where we want to reuse most of the atomic
> circuitry, but in a specialized way. We'd also have to be careful to only
> involve the drm objects which are seamless modeset aware (you could imagine
> a bridge chain where the bridges downstream of the first bridge don't care).
>
> >
> > There's then still the question of how to pick video vs command mode, but
> > imo better to start with implementing the transition behaviour correctly
> > first.
>
> Connector property? Possibly a terrible idea, but I wonder if we could [re]use
> the vrr properties for command mode. The docs state that the driver has the
> option of putting upper and lower bounds on the refresh rate.

Not really sure why this needs new props and whatnot. This is kinda 
what

the i915 "fastset" stuff already does:
1. userspace asks for something to be changed via atomic
2. driver calculates whether a modeset is actually required
3. atomic validates need_modeset() vs. DRM_MODE_ATOMIC_ALLOW_MODESET
4. if (need_modeset) heavyweight_commit() else lightweight_commit()

Ie. why should userspace really care about anything except the
"flickers are OK" vs. "flickers not wanted" thing?


Agree, I don't think the seamless modeset (ie: changing resolution 
without
flicker) needs a property. Just need to test the commit without 
ALLOW_MODESET

and commit it if the test passes.



Agreed that a TEST_ONLY commit without ALLOW_MODESET flag can be used to 
check
whether the modeset can be done seamless. But since there are no error 
code returns,
the client cannot distinguish the test_only commit failures from other 
invalid config failures.


Also, note that when the client sees two 1080p modes (vid/cmd) and it is 
interested only
to do *only* seamless switches, without any additional flag it cannot 
distinguish between
these two 1080p modes. The client has to invoke two test_only commits 
with these

modes to identify the seamless one. Is that a preferred approach?

Intel's "fastset" calculates the need for modeset internally based on 
the

configuration and chooses the best commit path. But the requirement here
is to expose the information up-front since the use case cannot afford
to fall back to the normal modeset when it has requested for a seamless 
one.




Also what's the benefit of using video mode if your panel supportes
command mode? Can you turn off the memory in the panel and actually
save power that way? And if there is a benefit can't the driver just
automagically switch between the two based on how often things are
getting updated? That would match how eDP PSR already works.


I'm guessing video mode might have some latency benefits over command 
mode?


Sean


Yes. Pretty much those are reasons we need to switch to video mode. But 
instead
of making the decision internal to the driver based on the frequency of 
frame updates,
we have proprietary use cases where the client has to trigger the switch 
explicitly.
So we are trying to find ways to represent the same resolution in both 
video/cmd modes.


Thanks and Regards,
Jeykumar S.





--
Ville Syrjälä
Intel


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [RFC] Expanding drm_mode_modeinfo flags

2019-07-18 Thread Jeykumar Sankaran

On 2019-07-16 02:07, Daniel Vetter wrote:

On Thu, Jul 11, 2019 at 11:46:44AM -0700, Jeykumar Sankaran wrote:

Hello All,
drm_mode_modeinfo::flags is a 32 bit field currently used to
describe the properties of a connector mode. I see the least order

22 bits

are already in use. Posting this RFC to discuss on any potential

plans to

expand the bit range support of this field for growing mode

properties and

ways to handle one such property needed by the msm dpu driver.

msm drivers support panels which can dynamically switch between
video(active) and command(smart) modes. Within video mode, they 
also

support
switching between resolutions seamlessly i.e. glitch free 
resolution

switch.

But they cannot do a seamless switch from a resolutions from video

to

command or vice versa. Clients need to be aware for these

capablities before

they switch between the resolutions. Since these capabilities are

identified
per drm_mode, we are considering the below two approaches to 
handle

this

use case.

Option 1:
Attached patch adds flag values to associate a drm_mode to

video/command

mode and to indicate its capability to do a seamless switch.

Option 2:
drm_mode_modeinfo can expose a new "private_flags" field to handle

vendor

specific mode flags. Besides the above mentioned use case, we are

also

expoloring methods to handle some of our display port resolution

switch use

cases where the DP ports can be operated in a tiled/detiled modes.

This
approach will provide a standard channel for drm driver vendors 
for

their

growing need for drm_mode specific capabilities.

Please provide your inputs on the options or any upstream friendly
recommendation to handle such custom use cases.

Thanks and Regards,
Jeykumar S.

Jeykumar Sankaran (1):
  drm: add mode flags in uapi for seamless mode switch


I think the uapi is the trivial part here, the real deal is how 
userspace

uses this. Can you pls post the patches for your compositor?

Also note that we already allow userspace to tell the kernel whether
flickering is ok or not for a modeset. msm driver could use that to at
least tell userspace whether a modeset change is possible. So you can
already implement glitch-free modeset changes for at least video mode.
-Daniel


I believe you are referring to the below tv property of the connector.

/**
 * @tv_flicker_reduction_property: Optional TV property to control the
 * flicker reduction mode.
 */
struct drm_property *tv_flicker_reduction_property;

Sure. We can use this to indicate whether the connector representing the 
panel
can support the dynamic glitch-free switch. But when the panel supports 
both
video and command mode resolutions and such glitch-free switch is 
possible only between
video mode resolutions, we need per resolution(drm_mode_modeinfo) 
information

to identify the resolutions enumerated for video mode.

Below is an example of the compositor utility function which can use the 
tv_flicker_property

and the proposed modeinfo flags to identify glitch-free switches.

 bool is_seamless_switch_supported(struct drm_mode_modeinfo src_mode, 
struct
 drm_mode_modeinfo *dst_mode, bool 
flicker_reduction_supported)

 {
 if (!flicker_reduction_supported) {
 printf("flicker reduction prop not set for the 
connector\n");

 return false;
 }

 /*
  * Seamless switch(if supported) is possible only between video 
mode

  * resolutions
  */
 if (src_mode->flags & DRM_MODE_FLAG_VIDEO_MODE &&
 dst_mode->flags & DRM_MODE_FLAG_VIDEO_MODE)
 return true;
 else
 return false;

 }


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[RFC PATCH] drm: add mode flags in uapi for seamless mode switch

2019-07-11 Thread Jeykumar Sankaran
Add drm mode flag values to expose mode capabilities to
perform dynamic seamless mode switch. This change also
exposes the backing panel type associated with a mode
for panels which can dynamically switch between video
and command display modes.

Signed-off-by: Jeykumar Sankaran 
---
 include/uapi/drm/drm_mode.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5ab331e..b76f1bf 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -124,6 +124,11 @@
 #define  DRM_MODE_FLAG_PIC_AR_256_135 \
(DRM_MODE_PICTURE_ASPECT_256_135<<19)
 
+#define DRM_MODE_FLAG_SEAMLESS_SWITCH (1<<23)
+
+#define DRM_MODE_FLAG_VIDEO_MODE   (1<<24)
+#define DRM_MODE_FLAG_COMMAND_MODE (1<<25)
+
 #define  DRM_MODE_FLAG_ALL (DRM_MODE_FLAG_PHSYNC | \
 DRM_MODE_FLAG_NHSYNC | \
 DRM_MODE_FLAG_PVSYNC | \
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[RFC] Expanding drm_mode_modeinfo flags

2019-07-11 Thread Jeykumar Sankaran
Hello All, 
drm_mode_modeinfo::flags is a 32 bit field currently used to
describe the properties of a connector mode. I see the least order 22 bits
are already in use. Posting this RFC to discuss on any potential plans to 
expand the bit range support of this field for growing mode properties and 
ways to handle one such property needed by the msm dpu driver.

msm drivers support panels which can dynamically switch between
video(active) and command(smart) modes. Within video mode, they also support
switching between resolutions seamlessly i.e. glitch free resolution switch.
But they cannot do a seamless switch from a resolutions from video to
command or vice versa. Clients need to be aware for these capablities before
they switch between the resolutions. Since these capabilities are identified
per drm_mode, we are considering the below two approaches to handle this
use case.

Option 1:
Attached patch adds flag values to associate a drm_mode to video/command
mode and to indicate its capability to do a seamless switch.

Option 2:
drm_mode_modeinfo can expose a new "private_flags" field to handle vendor
specific mode flags. Besides the above mentioned use case, we are also
expoloring methods to handle some of our display port resolution switch use
cases where the DP ports can be operated in a tiled/detiled modes. This 
approach will provide a standard channel for drm driver vendors for their 
growing need for drm_mode specific capabilities.

Please provide your inputs on the options or any upstream friendly
recommendation to handle such custom use cases.

Thanks and Regards,
Jeykumar S.

Jeykumar Sankaran (1):
  drm: add mode flags in uapi for seamless mode switch

 include/uapi/drm/drm_mode.h | 5 +
 1 file changed, 5 insertions(+)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: drm/msm/dpu: Correct dpu encoder spinlock initialization

2019-07-02 Thread Jeykumar Sankaran

On 2019-07-02 11:21, Jeykumar Sankaran wrote:

On 2019-07-01 03:29, d...@codeaurora.org wrote:

On 2019-06-26 03:10, Jeykumar Sankaran wrote:

On 2019-06-24 22:44, d...@codeaurora.org wrote:

On 2019-06-25 03:56, Jeykumar Sankaran wrote:

On 2019-06-23 23:27, Shubhashree Dhar wrote:

dpu encoder spinlock should be initialized during dpu encoder
init instead of dpu encoder setup which is part of commit.
There are chances that vblank control uses the uninitialized
spinlock if not initialized during encoder init.

Not much can be done if someone is performing a vblank operation
before encoder_setup is done.
Can you point to the path where this lock is acquired before
the encoder_setup?

Thanks
Jeykumar S.




When running some dp usecase, we are hitting this callstack.

Process kworker/u16:8 (pid: 215, stack limit = 0xdf9dd930)
Call trace:
 spin_dump+0x84/0x8c
 spin_dump+0x0/0x8c
 do_raw_spin_lock+0x80/0xb0
 _raw_spin_lock_irqsave+0x34/0x44
 dpu_encoder_toggle_vblank_for_crtc+0x8c/0xe8
 dpu_crtc_vblank+0x168/0x1a0
 dpu_kms_enable_vblank+0[   11.648998]  vblank_ctrl_worker+0x3c/0x60
 process_one_work+0x16c/0x2d8
 worker_thread+0x1d8/0x2b0
 kthread+0x124/0x134

Looks like vblank is getting enabled earlier causing this issue and 
we

are using the spinlock without initializing it.

Thanks,
Shubhashree

DP calls into set_encoder_mode during hotplug before even notifying 
the

u/s. Can you trace out the original caller of this stack?

Even though the patch is harmless, I am not entirely convinced to 
move this

initialization. Any call which acquires the lock before encoder_setup
will be a no-op since there will not be any physical encoder to work 
with.


Thanks and Regards,
Jeykumar S.


Change-Id: I5a18b95fa47397c834a266b22abf33a517b03a4e
Signed-off-by: Shubhashree Dhar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5f085b5..22938c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2195,8 +2195,6 @@ int dpu_encoder_setup(struct drm_device 
*dev, struct

drm_encoder *enc,
if (ret)
goto fail;

-   spin_lock_init(_enc->enc_spinlock);
-
atomic_set(_enc->frame_done_timeout, 0);
timer_setup(_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
@@ -2250,6 +2248,7 @@ struct drm_encoder *dpu_encoder_init(struct
drm_device *dev,

 	drm_encoder_helper_add(_enc->base, 
_encoder_helper_funcs);


+   spin_lock_init(_enc->enc_spinlock);
dpu_enc->enabled = false;

return _enc->base;


In dpu_crtc_vblank(), we are looping through all the encoders in the
present mode_config:
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/disp/dpu
1/dpu_crtc.c#L1082
and hence calling dpu_encoder_toggle_vblank_for_crtc() for all the
encoders. But in dpu_encoder_toggle_vblank_for_crtc(), after acquiring
the spinlock, we will do a early return for
the encoders which are not currently assigned to our crtc:
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/disp/dpu
1/dpu_encoder.c#L1318.
Since the encoder_setup for the secondary encoder(dp encoder in this
case) is not called until dp hotplug, we are hitting kernel panic
while acquiring the lock.

This is the sequence in which the events are expected to happen:

1) DP connector is instantiated with an inactive state
2) Hot plug on DP
3) DP connector is activated
4) User space attaches a CRTC to the activated connector
5) CRTC is enabled
6) CRTC_VBLANK_ON is called
7) dpu_crtc_vblank is called.

So can you help tracing out why dpu_crtc_vblank is called when the 
connector

is not activated yet (no hotplug)?


Overlooked the loop which iterates through *all* the encoders 
irrespective of their

activated status.

Reviewed-by: Jeykumar Sankaran 

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: drm/msm/dpu: Correct dpu encoder spinlock initialization

2019-07-02 Thread Jeykumar Sankaran

On 2019-07-01 03:29, d...@codeaurora.org wrote:

On 2019-06-26 03:10, Jeykumar Sankaran wrote:

On 2019-06-24 22:44, d...@codeaurora.org wrote:

On 2019-06-25 03:56, Jeykumar Sankaran wrote:

On 2019-06-23 23:27, Shubhashree Dhar wrote:

dpu encoder spinlock should be initialized during dpu encoder
init instead of dpu encoder setup which is part of commit.
There are chances that vblank control uses the uninitialized
spinlock if not initialized during encoder init.

Not much can be done if someone is performing a vblank operation
before encoder_setup is done.
Can you point to the path where this lock is acquired before
the encoder_setup?

Thanks
Jeykumar S.




When running some dp usecase, we are hitting this callstack.

Process kworker/u16:8 (pid: 215, stack limit = 0xdf9dd930)
Call trace:
 spin_dump+0x84/0x8c
 spin_dump+0x0/0x8c
 do_raw_spin_lock+0x80/0xb0
 _raw_spin_lock_irqsave+0x34/0x44
 dpu_encoder_toggle_vblank_for_crtc+0x8c/0xe8
 dpu_crtc_vblank+0x168/0x1a0
 dpu_kms_enable_vblank+0[   11.648998]  vblank_ctrl_worker+0x3c/0x60
 process_one_work+0x16c/0x2d8
 worker_thread+0x1d8/0x2b0
 kthread+0x124/0x134

Looks like vblank is getting enabled earlier causing this issue and 
we

are using the spinlock without initializing it.

Thanks,
Shubhashree

DP calls into set_encoder_mode during hotplug before even notifying 
the

u/s. Can you trace out the original caller of this stack?

Even though the patch is harmless, I am not entirely convinced to move 
this

initialization. Any call which acquires the lock before encoder_setup
will be a no-op since there will not be any physical encoder to work 
with.


Thanks and Regards,
Jeykumar S.


Change-Id: I5a18b95fa47397c834a266b22abf33a517b03a4e
Signed-off-by: Shubhashree Dhar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5f085b5..22938c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2195,8 +2195,6 @@ int dpu_encoder_setup(struct drm_device *dev, 
struct

drm_encoder *enc,
if (ret)
goto fail;

-   spin_lock_init(_enc->enc_spinlock);
-
atomic_set(_enc->frame_done_timeout, 0);
timer_setup(_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
@@ -2250,6 +2248,7 @@ struct drm_encoder *dpu_encoder_init(struct
drm_device *dev,

 	drm_encoder_helper_add(_enc->base, 
_encoder_helper_funcs);


+   spin_lock_init(_enc->enc_spinlock);
dpu_enc->enabled = false;

return _enc->base;


In dpu_crtc_vblank(), we are looping through all the encoders in the
present mode_config:
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/disp/dpu
1/dpu_crtc.c#L1082
and hence calling dpu_encoder_toggle_vblank_for_crtc() for all the
encoders. But in dpu_encoder_toggle_vblank_for_crtc(), after acquiring
the spinlock, we will do a early return for
the encoders which are not currently assigned to our crtc:
https://github.com/torvalds/linux/blob/master/drivers/gpu/drm/msm/disp/dpu
1/dpu_encoder.c#L1318.
Since the encoder_setup for the secondary encoder(dp encoder in this
case) is not called until dp hotplug, we are hitting kernel panic
while acquiring the lock.

This is the sequence in which the events are expected to happen:

1) DP connector is instantiated with an inactive state
2) Hot plug on DP
3) DP connector is activated
4) User space attaches a CRTC to the activated connector
5) CRTC is enabled
6) CRTC_VBLANK_ON is called
7) dpu_crtc_vblank is called.

So can you help tracing out why dpu_crtc_vblank is called when the 
connector

is not activated yet (no hotplug)?

--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: drm/msm/dpu: Correct dpu encoder spinlock initialization

2019-06-25 Thread Jeykumar Sankaran

On 2019-06-24 22:44, d...@codeaurora.org wrote:

On 2019-06-25 03:56, Jeykumar Sankaran wrote:

On 2019-06-23 23:27, Shubhashree Dhar wrote:

dpu encoder spinlock should be initialized during dpu encoder
init instead of dpu encoder setup which is part of commit.
There are chances that vblank control uses the uninitialized
spinlock if not initialized during encoder init.

Not much can be done if someone is performing a vblank operation
before encoder_setup is done.
Can you point to the path where this lock is acquired before
the encoder_setup?

Thanks
Jeykumar S.




When running some dp usecase, we are hitting this callstack.

Process kworker/u16:8 (pid: 215, stack limit = 0xdf9dd930)
Call trace:
 spin_dump+0x84/0x8c
 spin_dump+0x0/0x8c
 do_raw_spin_lock+0x80/0xb0
 _raw_spin_lock_irqsave+0x34/0x44
 dpu_encoder_toggle_vblank_for_crtc+0x8c/0xe8
 dpu_crtc_vblank+0x168/0x1a0
 dpu_kms_enable_vblank+0[   11.648998]  vblank_ctrl_worker+0x3c/0x60
 process_one_work+0x16c/0x2d8
 worker_thread+0x1d8/0x2b0
 kthread+0x124/0x134

Looks like vblank is getting enabled earlier causing this issue and we
are using the spinlock without initializing it.

Thanks,
Shubhashree


DP calls into set_encoder_mode during hotplug before even notifying the
u/s. Can you trace out the original caller of this stack?

Even though the patch is harmless, I am not entirely convinced to move 
this

initialization. Any call which acquires the lock before encoder_setup
will be a no-op since there will not be any physical encoder to work 
with.


Thanks and Regards,
Jeykumar S.


Change-Id: I5a18b95fa47397c834a266b22abf33a517b03a4e
Signed-off-by: Shubhashree Dhar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5f085b5..22938c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2195,8 +2195,6 @@ int dpu_encoder_setup(struct drm_device *dev, 
struct

drm_encoder *enc,
if (ret)
goto fail;

-   spin_lock_init(_enc->enc_spinlock);
-
atomic_set(_enc->frame_done_timeout, 0);
timer_setup(_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
@@ -2250,6 +2248,7 @@ struct drm_encoder *dpu_encoder_init(struct
drm_device *dev,

drm_encoder_helper_add(_enc->base, _encoder_helper_funcs);

+   spin_lock_init(_enc->enc_spinlock);
dpu_enc->enabled = false;

return _enc->base;


--
Jeykumar S


Re: drm/msm/dpu: Correct dpu encoder spinlock initialization

2019-06-24 Thread Jeykumar Sankaran

On 2019-06-23 23:27, Shubhashree Dhar wrote:

dpu encoder spinlock should be initialized during dpu encoder
init instead of dpu encoder setup which is part of commit.
There are chances that vblank control uses the uninitialized
spinlock if not initialized during encoder init.

Not much can be done if someone is performing a vblank operation
before encoder_setup is done.
Can you point to the path where this lock is acquired before
the encoder_setup?

Thanks
Jeykumar S.


Change-Id: I5a18b95fa47397c834a266b22abf33a517b03a4e
Signed-off-by: Shubhashree Dhar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 5f085b5..22938c7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2195,8 +2195,6 @@ int dpu_encoder_setup(struct drm_device *dev, 
struct

drm_encoder *enc,
if (ret)
goto fail;

-   spin_lock_init(_enc->enc_spinlock);
-
atomic_set(_enc->frame_done_timeout, 0);
timer_setup(_enc->frame_done_timer,
dpu_encoder_frame_done_timeout, 0);
@@ -2250,6 +2248,7 @@ struct drm_encoder *dpu_encoder_init(struct
drm_device *dev,

drm_encoder_helper_add(_enc->base, _encoder_helper_funcs);

+   spin_lock_init(_enc->enc_spinlock);
dpu_enc->enabled = false;

return _enc->base;


--
Jeykumar S


Re: [PATCH v2 4/7] drm/msm/dpu: dont use encoder->crtc in atomic path

2019-03-06 Thread Jeykumar Sankaran

On 2019-03-04 10:09, Sean Paul wrote:

On Wed, Feb 13, 2019 at 05:19:13PM -0800, Jeykumar Sankaran wrote:

encoder->crtc is not really meaningful for atomic path. Use
crtc->encoder_mask to identify the crtc attached with
an encoder.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

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

b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index 45617b9..0a19124 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -961,6 +961,7 @@ static void dpu_encoder_virt_mode_set(struct

drm_encoder *drm_enc,

struct dpu_kms *dpu_kms;
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
+   struct drm_crtc *drm_crtc;
struct dpu_rm_hw_iter pp_iter, ctl_iter;
struct msm_display_topology topology;
struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
@@ -992,10 +993,14 @@ static void dpu_encoder_virt_mode_set(struct

drm_encoder *drm_enc,

return;
}

+   drm_for_each_crtc(drm_crtc, drm_enc->dev)
+   if (drm_crtc->state->encoder_mask &

drm_encoder_mask(drm_enc))

+   break;


You should check whether you actually found the crtc, or are just using
the last
one in the list.

I see you have pulled in the this entire series on msm-next. If it is 
the right
thing to do, I can address this comment in a separate patch on top 
instead of

posting v2.

Thanks
Jeykumar S.

Sean


+
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);

/* Reserve dynamic resources now. Indicating non-AtomicTest phase

*/

-   ret = dpu_rm_reserve(_kms->rm, drm_enc, drm_enc->crtc->state,
+   ret = dpu_rm_reserve(_kms->rm, drm_enc, drm_crtc->state,
 topology, false);
if (ret) {
DPU_ERROR_ENC(dpu_enc,
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

a Linux Foundation Collaborative Project



--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

Re: [Freedreno] [PATCH v2 1/4] drm/msm/dpu: add atomic private object to dpu crtc

2019-03-05 Thread Jeykumar Sankaran

On 2019-03-04 13:32, Sean Paul wrote:

On Wed, Feb 13, 2019 at 05:52:19PM -0800, Jeykumar Sankaran wrote:

Subclass drm private object state for DPU for handling driver
specific data. Adds atomic private object to dpu crtc to
track hw resources per display. Provide helper function to
retrieve DPU private data from current atomic state before
atomic swap.

changes in v2:
- private objects are maintained in dpu_crtc as
  the resources are tracked per display


Seems like you could just store it in crtc_state if it's per-crtc?


If you mean - "no need for priv object, maintain in crtc state", that
was the original v1 implementation. But you proposed to have them
tracked in a private object since I had to use crtc_state for tracking
interfaces too which were mapped in encoders.

It made sense as the private objects not bounded to any DRM object
domain and is the best candidate to track per display assignments.
So v2 implementation moved all the RM assignment to private objects 
state

and provided an interface for CRTC and Encoder to query its domain
specific hw blocks.

v1: https://patchwork.freedesktop.org/patch/255452/

Thanks and Regards,
Jeykumar S.



Sean



Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h |  3 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  | 64

+++-

 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h  | 15 
 3 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h

b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h

index e59d62b..be07554 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -141,6 +141,7 @@ struct dpu_crtc_frame_event {
  * @frame_pending : Whether or not an update is pending
  * @frame_events  : static allocation of in-flight frame events
  * @frame_event_list : available frame event list
+ * @priv_obj : private state object to track hw resources
  * @spin_lock : spin lock for frame event, transaction status,

etc...

  * @frame_done_comp: for frame_event_done synchronization
  * @event_thread  : Pointer to event handler thread
@@ -176,6 +177,8 @@ struct dpu_crtc {
spinlock_t spin_lock;
struct completion frame_done_comp;

+   struct drm_private_obj priv_obj;
+
/* for handling internal event thread */
spinlock_t event_lock;

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

b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 885bf88..1677862 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -459,6 +459,49 @@ static int _dpu_kms_setup_displays(struct

drm_device *dev,

return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
 }

+struct dpu_private_state *dpu_get_private_state(struct 
drm_atomic_state

*state,

+   struct dpu_crtc *crtc)
+{
+   struct drm_private_state *priv_state;
+
+   priv_state = drm_atomic_get_private_obj_state(state,

>priv_obj);

+   if (IS_ERR(priv_state))
+   return ERR_PTR(-ENOMEM);
+
+   return container_of(priv_state, struct dpu_private_state, base);
+}
+
+static struct drm_private_state *
+dpu_private_obj_duplicate_state(struct drm_private_obj *obj)
+{
+   struct dpu_private_state *dpu_priv_state;
+
+   dpu_priv_state = kmemdup(obj->state, sizeof(*dpu_priv_state),
+GFP_KERNEL);
+   if (!dpu_priv_state)
+   return NULL;
+
+   __drm_atomic_helper_private_obj_duplicate_state(obj,
+

_priv_state->base);

+
+   return _priv_state->base;
+}
+
+static void dpu_private_obj_destroy_state(struct drm_private_obj 
*obj,

+ struct drm_private_state *state)
+{
+   struct dpu_private_state *dpu_priv_state = container_of(state,
+ struct

dpu_private_state,

+ base);
+
+   kfree(dpu_priv_state);
+}
+
+static const struct drm_private_state_funcs priv_obj_funcs = {
+   .atomic_duplicate_state = dpu_private_obj_duplicate_state,
+   .atomic_destroy_state = dpu_private_obj_destroy_state,
+};
+
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
 {
struct msm_drm_private *priv;
@@ -476,8 +519,12 @@ static void _dpu_kms_drm_obj_destroy(struct 
dpu_kms

*dpu_kms)

}
priv = dpu_kms->dev->dev_private;

-   for (i = 0; i < priv->num_crtcs; i++)
+   for (i = 0; i < priv->num_crtcs; i++) {
+   struct dpu_crtc *dpu_crtc = to_dpu_crtc(priv->crtcs[i]);
+
+   drm_atomic_private_obj_fini(_crtc->priv_obj);
priv->crtcs[i]->funcs->destroy(priv->crtcs[i]);
+   }
priv->num_crtcs = 0;

for (i = 0; i < priv->num_planes; i++)
@@ -499,6 +546,7 @@ static int _dpu_k

[PATCH v2 4/4] drm/msm/dpu: remove mode_set_complete

2019-02-13 Thread Jeykumar Sankaran
This flag was introduced as a fix to notify modeset complete
when hw reservations were happening in both atomic_check
and atomic_commit paths. Now that we are reserving only in
atomic_check, we can get rid of this flag.

changes in v2:
- none

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 86c025b..beb9f86 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -170,7 +170,6 @@ enum dpu_enc_rc_states {
  * clks and resources after IDLE_TIMEOUT time.
  * @vsync_event_work:  worker to handle vsync event for autorefresh
  * @topology:   topology of the display
- * @mode_set_complete:  flag to indicate modeset completion
  * @idle_timeout:  idle timeout duration in milliseconds
  */
 struct dpu_encoder_virt {
@@ -208,7 +207,6 @@ struct dpu_encoder_virt {
struct delayed_work delayed_off_work;
struct kthread_work vsync_event_work;
struct msm_display_topology topology;
-   bool mode_set_complete;
 
u32 idle_timeout;
 };
@@ -604,12 +602,7 @@ static int dpu_encoder_virt_atomic_check(
}
}
 
-   /*
-* Avoid reserving resources when mode set is pending. Topology
-* info may not be available to complete reservation.
-*/
-   if (!ret && drm_atomic_crtc_needs_modeset(crtc_state)
-   && dpu_enc->mode_set_complete) {
+   if (!ret && drm_atomic_crtc_needs_modeset(crtc_state)) {
struct msm_display_topology topology;
struct dpu_private_state *dpu_priv_state;
 
@@ -619,7 +612,6 @@ static int dpu_encoder_virt_atomic_check(
 
ret = dpu_rm_reserve(_kms->rm, drm_enc,
 _priv_state->base, topology, false);
-   dpu_enc->mode_set_complete = false;
}
 
if (!ret)
@@ -1039,8 +1031,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
if (phys->ops.mode_set)
phys->ops.mode_set(phys, mode, adj_mode);
}
-
-   dpu_enc->mode_set_complete = true;
 }
 
 static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 2/4] drm/msm/dpu: track HW resources using private object state

2019-02-13 Thread Jeykumar Sankaran
DPU maintained reservation lists to cache assigned
HW blocks for the display and a retrieval mechanism for
the individual DRM components to query their respective
HW blocks.

This patch uses the sub-classed private object state to store
and track HW blocks assigned for different components
of the display pipeline. It helps the driver:
- to get rid of unwanted store and retrieval RM API's
- to preserve HW resources assigned in atomic_check
  through atomic swap/duplicate.

Resources are reserved only when drm_atomic_crtc_needs_modeset
is set to TRUE and are released in atomic disable path.

With TEST_ONLY atomic commit path, reserved resources
are released back to RM pool in private_obj_destroy_state
call.

changes in v2 (comments from Sean Paul):
- Track resources in private object state instead
  of crtc state.
- Avoid duplicate tracking of hw_ctls in crtc
- No explicit count for hw_ctl as they match
  with hw_intf count

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|   7 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 157 
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |   9 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  17 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 131 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |   8 +-
 6 files changed, 185 insertions(+), 144 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index be07554..cec0674 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -202,8 +202,6 @@ struct dpu_crtc {
  * @new_perf: new performance state being requested
  * @num_mixers: Number of mixers in use
  * @mixers: List of active mixers
- * @num_ctls  : Number of ctl paths in use
- * @hw_ctls   : List of active ctl paths
  */
 struct dpu_crtc_state {
struct drm_crtc_state base;
@@ -217,11 +215,8 @@ struct dpu_crtc_state {
struct dpu_core_perf_params new_perf;
 
/* HW Resources reserved for the crtc */
-   u32 num_mixers;
+   int num_mixers;
struct dpu_crtc_mixer mixers[CRTC_DUAL_MIXERS];
-
-   u32 num_ctls;
-   struct dpu_hw_ctl *hw_ctls[CRTC_DUAL_MIXERS];
 };
 
 #define to_dpu_crtc_state(x) \
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 98ea478..bd646c5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -559,7 +559,6 @@ static int dpu_encoder_virt_atomic_check(
struct dpu_kms *dpu_kms;
const struct drm_display_mode *mode;
struct drm_display_mode *adj_mode;
-   struct msm_display_topology topology;
int i = 0;
int ret = 0;
 
@@ -605,20 +604,24 @@ static int dpu_encoder_virt_atomic_check(
}
}
 
-   topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
+   /*
+* Reserve dynamic resources now. Indicating AtomicTest phase
+*
+* Avoid reserving resources when mode set is pending. Topology
+* info may not be available to complete reservation.
+*/
+   if (!ret && drm_atomic_crtc_needs_modeset(crtc_state)
+   && dpu_enc->mode_set_complete) {
+   struct msm_display_topology topology;
+   struct dpu_private_state *dpu_priv_state;
 
-   /* Reserve dynamic resources now. Indicating AtomicTest phase */
-   if (!ret) {
-   /*
-* Avoid reserving resources when mode set is pending. Topology
-* info may not be available to complete reservation.
-*/
-   if (drm_atomic_crtc_needs_modeset(crtc_state)
-   && dpu_enc->mode_set_complete) {
-   ret = dpu_rm_reserve(_kms->rm, drm_enc, crtc_state,
-topology, true);
-   dpu_enc->mode_set_complete = false;
-   }
+   topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
+   dpu_priv_state = dpu_get_private_state(crtc_state->state,
+  to_dpu_crtc(crtc_state->crtc));
+
+   ret = dpu_rm_reserve(_kms->rm, drm_enc,
+_priv_state->base, topology, true);
+   dpu_enc->mode_set_complete = false;
}
 
if (!ret)
@@ -962,12 +965,10 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
struct drm_crtc *drm_crtc;
-   struct dpu_crtc_state *cstate;
-   struct dpu_rm_hw_iter hw_iter;
+   struct dpu_crtc_state *dpu_cstate;
struct msm_d

[PATCH v2 3/4] drm/msm/dpu: remove reserve in encoder mode_set

2019-02-13 Thread Jeykumar Sankaran
Now that we have dpu private state tracking the reserved
HW resources, we have access to them after atomic swap.
So avoid reserving the resources in mode_set.

changes in v2:
- removal applied on private object based reservation

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 18 ++
 1 file changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index bd646c5..86c025b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -605,8 +605,6 @@ static int dpu_encoder_virt_atomic_check(
}
 
/*
-* Reserve dynamic resources now. Indicating AtomicTest phase
-*
 * Avoid reserving resources when mode set is pending. Topology
 * info may not be available to complete reservation.
 */
@@ -620,7 +618,7 @@ static int dpu_encoder_virt_atomic_check(
   to_dpu_crtc(crtc_state->crtc));
 
ret = dpu_rm_reserve(_kms->rm, drm_enc,
-_priv_state->base, topology, true);
+_priv_state->base, topology, false);
dpu_enc->mode_set_complete = false;
}
 
@@ -966,10 +964,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct drm_connector *conn = NULL, *conn_iter;
struct drm_crtc *drm_crtc;
struct dpu_crtc_state *dpu_cstate;
-   struct msm_display_topology topology;
struct dpu_crtc *dpu_crtc;
struct dpu_private_state *dpu_private_state;
-   int i, j, ret;
+   int i, j;
 
if (!drm_enc) {
DPU_ERROR("invalid encoder\n");
@@ -1001,18 +998,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
if (drm_crtc->state->encoder_mask & drm_encoder_mask(drm_enc))
break;
 
-   topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
dpu_crtc = to_dpu_crtc(drm_crtc);
-
-   /* Reserve dynamic resources now. Indicating non-AtomicTest phase */
-   ret = dpu_rm_reserve(_kms->rm, drm_enc, dpu_crtc->priv_obj.state,
-topology, false);
-   if (ret) {
-   DPU_ERROR_ENC(dpu_enc,
-"failed to reserve hw resources, %d\n", ret);
-   return;
-   }
-
dpu_cstate = to_dpu_crtc_state(drm_crtc->state);
dpu_private_state = container_of(dpu_crtc->priv_obj.state,
 struct dpu_private_state, base);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 0/4] reserve RM resources in private obj state

2019-02-13 Thread Jeykumar Sankaran
v2 patches for [1]. 

changes in v2:
- Reserve and track hw resources allocated per
  display in subclassed drm private object states. 
- Private objects are created per CRTC.

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

Follow up series will be submitted to clean up RM iterator
API's.

Thanks and Regards,
Jeykumar S.

Jeykumar Sankaran (4):
  drm/msm/dpu: add atomic private object to dpu crtc
  drm/msm/dpu: track HW resources using private object state
  drm/msm/dpu: remove reserve in encoder mode_set
  drm/msm/dpu: remove mode_set_complete

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  10 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 163 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  73 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  32 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 131 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |   8 +-
 6 files changed, 257 insertions(+), 160 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 1/4] drm/msm/dpu: add atomic private object to dpu crtc

2019-02-13 Thread Jeykumar Sankaran
Subclass drm private object state for DPU for handling driver
specific data. Adds atomic private object to dpu crtc to
track hw resources per display. Provide helper function to
retrieve DPU private data from current atomic state before
atomic swap.

changes in v2:
- private objects are maintained in dpu_crtc as
  the resources are tracked per display

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h |  3 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c  | 64 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h  | 15 
 3 files changed, 81 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index e59d62b..be07554 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -141,6 +141,7 @@ struct dpu_crtc_frame_event {
  * @frame_pending : Whether or not an update is pending
  * @frame_events  : static allocation of in-flight frame events
  * @frame_event_list : available frame event list
+ * @priv_obj : private state object to track hw resources
  * @spin_lock : spin lock for frame event, transaction status, etc...
  * @frame_done_comp: for frame_event_done synchronization
  * @event_thread  : Pointer to event handler thread
@@ -176,6 +177,8 @@ struct dpu_crtc {
spinlock_t spin_lock;
struct completion frame_done_comp;
 
+   struct drm_private_obj priv_obj;
+
/* for handling internal event thread */
spinlock_t event_lock;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 885bf88..1677862 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -459,6 +459,49 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
 }
 
+struct dpu_private_state *dpu_get_private_state(struct drm_atomic_state *state,
+   struct dpu_crtc *crtc)
+{
+   struct drm_private_state *priv_state;
+
+   priv_state = drm_atomic_get_private_obj_state(state, >priv_obj);
+   if (IS_ERR(priv_state))
+   return ERR_PTR(-ENOMEM);
+
+   return container_of(priv_state, struct dpu_private_state, base);
+}
+
+static struct drm_private_state *
+dpu_private_obj_duplicate_state(struct drm_private_obj *obj)
+{
+   struct dpu_private_state *dpu_priv_state;
+
+   dpu_priv_state = kmemdup(obj->state, sizeof(*dpu_priv_state),
+GFP_KERNEL);
+   if (!dpu_priv_state)
+   return NULL;
+
+   __drm_atomic_helper_private_obj_duplicate_state(obj,
+   _priv_state->base);
+
+   return _priv_state->base;
+}
+
+static void dpu_private_obj_destroy_state(struct drm_private_obj *obj,
+ struct drm_private_state *state)
+{
+   struct dpu_private_state *dpu_priv_state = container_of(state,
+ struct dpu_private_state,
+ base);
+
+   kfree(dpu_priv_state);
+}
+
+static const struct drm_private_state_funcs priv_obj_funcs = {
+   .atomic_duplicate_state = dpu_private_obj_duplicate_state,
+   .atomic_destroy_state = dpu_private_obj_destroy_state,
+};
+
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
 {
struct msm_drm_private *priv;
@@ -476,8 +519,12 @@ static void _dpu_kms_drm_obj_destroy(struct dpu_kms 
*dpu_kms)
}
priv = dpu_kms->dev->dev_private;
 
-   for (i = 0; i < priv->num_crtcs; i++)
+   for (i = 0; i < priv->num_crtcs; i++) {
+   struct dpu_crtc *dpu_crtc = to_dpu_crtc(priv->crtcs[i]);
+
+   drm_atomic_private_obj_fini(_crtc->priv_obj);
priv->crtcs[i]->funcs->destroy(priv->crtcs[i]);
+   }
priv->num_crtcs = 0;
 
for (i = 0; i < priv->num_planes; i++)
@@ -499,6 +546,7 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
struct drm_plane *primary_planes[MAX_PLANES], *plane;
struct drm_plane *cursor_planes[MAX_PLANES] = { NULL };
struct drm_crtc *crtc;
+   struct dpu_private_state *dpu_priv_state;
 
struct msm_drm_private *priv;
struct dpu_mdss_cfg *catalog;
@@ -560,11 +608,25 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
 
/* Create one CRTC per encoder */
for (i = 0; i < max_crtc_count; i++) {
+   struct dpu_crtc *dpu_crtc;
+
crtc = dpu_crtc_init(dev, primary_planes[i], cursor_planes[i]);
if (IS_ERR(crtc)) {
ret = PTR_ERR(crtc);
goto fail;
}
+
+   dpu_crtc = to_d

Re: [PATCH v2 0/7] move dpu resource parsing to encoder modeset

2019-02-13 Thread Jeykumar Sankaran

On 2019-02-13 17:19, Jeykumar Sankaran wrote:

Fixing some of the low hanging fruits by moving the hw resource
parsing and assignment to encoder modeset. This series
prepares DPU resource management to switch to state based
resource tracking which is implemented in the next incoming
changes.



Below changes are introduced in the series. V2 label is to indicate
its relation to the RM resource series posted quite a while back:
https://patchwork.freedesktop.org/series/50722/


Thanks.

Jeykumar Sankaran (7):
  drm/msm/dpu: move hw_inf encoder baseclass
  drm/msm/dpu: remove phys_vid subclass
  drm/msm/dpu: release resources on modeset failure
  drm/msm/dpu: dont use encoder->crtc in atomic path
  drm/msm/dpu: map mixer/ctl hw blocks in encoder modeset
  drm/msm/dpu: assign intf to encoder in mode_set
  drm/msm/dpu: check split role for single flush

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  64 +---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c|  73 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  15 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   | 177
++---
 4 files changed, 118 insertions(+), 211 deletions(-)


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 6/7] drm/msm/dpu: assign intf to encoder in mode_set

2019-02-13 Thread Jeykumar Sankaran
Iterate and assign HW intf block to physical encoders
in encoder modeset. Moving all the HW block assignments
to encoder modeset to allow easy switching to state
based resource management.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c| 22 +++-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   | 24 --
 2 files changed, 21 insertions(+), 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index f648e7f..98ea478 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -968,7 +968,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL };
int num_lm = 0, num_ctl = 0;
-   int i = 0, ret;
+   int i, j, ret;
 
if (!drm_enc) {
DPU_ERROR("invalid encoder\n");
@@ -1065,6 +1065,26 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
phys->hw_pp = dpu_enc->hw_pp[i];
phys->hw_ctl = hw_ctl[i];
 
+   dpu_rm_init_hw_iter(_iter, drm_enc->base.id,
+   DPU_HW_BLK_INTF);
+   for (j = 0; j < MAX_CHANNELS_PER_ENC; j++) {
+   struct dpu_hw_intf *hw_intf;
+
+   if (!dpu_rm_get_hw(_kms->rm, _iter))
+   break;
+
+   hw_intf = (struct dpu_hw_intf *)hw_iter.hw;
+   if (hw_intf->idx == phys->intf_idx)
+   phys->hw_intf = hw_intf;
+   }
+
+   if (!phys->hw_intf) {
+   DPU_ERROR_ENC(dpu_enc,
+ "no intf block assigned at idx: 
%d\n",
+ i);
+   goto error;
+   }
+
phys->connector = conn->state->connector;
if (phys->ops.mode_set)
phys->ops.mode_set(phys, mode, adj_mode);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index ce65521..02362c5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -449,35 +449,11 @@ static int dpu_encoder_phys_vid_control_vblank_irq(
 
 static void dpu_encoder_phys_vid_enable(struct dpu_encoder_phys *phys_enc)
 {
-   struct msm_drm_private *priv;
-   struct dpu_rm_hw_iter iter;
struct dpu_hw_ctl *ctl;
u32 flush_mask = 0;
 
-   if (!phys_enc || !phys_enc->parent || !phys_enc->parent->dev ||
-   !phys_enc->parent->dev->dev_private) {
-   DPU_ERROR("invalid encoder/device\n");
-   return;
-   }
-   priv = phys_enc->parent->dev->dev_private;
-
ctl = phys_enc->hw_ctl;
 
-   dpu_rm_init_hw_iter(, phys_enc->parent->base.id, DPU_HW_BLK_INTF);
-   while (dpu_rm_get_hw(_enc->dpu_kms->rm, )) {
-   struct dpu_hw_intf *hw_intf = (struct dpu_hw_intf *)iter.hw;
-
-   if (hw_intf->idx == phys_enc->intf_idx) {
-   phys_enc->hw_intf = hw_intf;
-   break;
-   }
-   }
-
-   if (!phys_enc->hw_intf) {
-   DPU_ERROR("hw_intf not assigned\n");
-   return;
-   }
-
DPU_DEBUG_VIDENC(phys_enc, "\n");
 
if (WARN_ON(!phys_enc->hw_intf->ops.enable_timing))
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 5/7] drm/msm/dpu: map mixer/ctl hw blocks in encoder modeset

2019-02-13 Thread Jeykumar Sankaran
After resource allocation, iterate and populate mixer/ctl
hw blocks in encoder modeset thereby centralizing all
the resource mapping to the CRTC. This change is made
for easy switching to state based allocation using
private objects later in this series.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 64 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 37 +
 2 files changed, 31 insertions(+), 70 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 4e4b648..6d30ba9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -425,65 +425,6 @@ void dpu_crtc_complete_commit(struct drm_crtc *crtc,
trace_dpu_crtc_complete_commit(DRMID(crtc));
 }
 
-static void _dpu_crtc_setup_mixer_for_encoder(
-   struct drm_crtc *crtc,
-   struct drm_encoder *enc)
-{
-   struct dpu_crtc_state *cstate = to_dpu_crtc_state(crtc->state);
-   struct dpu_kms *dpu_kms = _dpu_crtc_get_kms(crtc);
-   struct dpu_rm *rm = _kms->rm;
-   struct dpu_crtc_mixer *mixer;
-   struct dpu_hw_ctl *last_valid_ctl = NULL;
-   int i;
-   struct dpu_rm_hw_iter lm_iter, ctl_iter;
-
-   dpu_rm_init_hw_iter(_iter, enc->base.id, DPU_HW_BLK_LM);
-   dpu_rm_init_hw_iter(_iter, enc->base.id, DPU_HW_BLK_CTL);
-
-   /* Set up all the mixers and ctls reserved by this encoder */
-   for (i = cstate->num_mixers; i < ARRAY_SIZE(cstate->mixers); i++) {
-   mixer = >mixers[i];
-
-   if (!dpu_rm_get_hw(rm, _iter))
-   break;
-   mixer->hw_lm = (struct dpu_hw_mixer *)lm_iter.hw;
-
-   /* CTL may be <= LMs, if <, multiple LMs controlled by 1 CTL */
-   if (!dpu_rm_get_hw(rm, _iter)) {
-   DPU_DEBUG("no ctl assigned to lm %d, using previous\n",
-   mixer->hw_lm->idx - LM_0);
-   mixer->lm_ctl = last_valid_ctl;
-   } else {
-   mixer->lm_ctl = (struct dpu_hw_ctl *)ctl_iter.hw;
-   last_valid_ctl = mixer->lm_ctl;
-   }
-
-   /* Shouldn't happen, mixers are always >= ctls */
-   if (!mixer->lm_ctl) {
-   DPU_ERROR("no valid ctls found for lm %d\n",
-   mixer->hw_lm->idx - LM_0);
-   return;
-   }
-
-   cstate->num_mixers++;
-   DPU_DEBUG("setup mixer %d: lm %d\n",
-   i, mixer->hw_lm->idx - LM_0);
-   DPU_DEBUG("setup mixer %d: ctl %d\n",
-   i, mixer->lm_ctl->idx - CTL_0);
-   }
-}
-
-static void _dpu_crtc_setup_mixers(struct drm_crtc *crtc)
-{
-   struct drm_encoder *enc;
-
-   WARN_ON(!drm_modeset_is_locked(>mutex));
-
-   /* Check for mixers on all encoders attached to this crtc */
-   drm_for_each_encoder_mask(enc, crtc->dev, crtc->state->encoder_mask)
-   _dpu_crtc_setup_mixer_for_encoder(crtc, enc);
-}
-
 static void _dpu_crtc_setup_lm_bounds(struct drm_crtc *crtc,
struct drm_crtc_state *state)
 {
@@ -533,10 +474,7 @@ static void dpu_crtc_atomic_begin(struct drm_crtc *crtc,
dev = crtc->dev;
smmu_state = _crtc->smmu_state;
 
-   if (!cstate->num_mixers) {
-   _dpu_crtc_setup_mixers(crtc);
-   _dpu_crtc_setup_lm_bounds(crtc, crtc->state);
-   }
+   _dpu_crtc_setup_lm_bounds(crtc, crtc->state);
 
if (dpu_crtc->event) {
WARN_ON(dpu_crtc->event);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0a19124..f648e7f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -962,9 +962,12 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
struct drm_crtc *drm_crtc;
-   struct dpu_rm_hw_iter pp_iter, ctl_iter;
+   struct dpu_crtc_state *cstate;
+   struct dpu_rm_hw_iter hw_iter;
struct msm_display_topology topology;
struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
+   struct dpu_hw_mixer *hw_lm[MAX_CHANNELS_PER_ENC] = { NULL };
+   int num_lm = 0, num_ctl = 0;
int i = 0, ret;
 
if (!drm_enc) {
@@ -1008,21 +1011,41 @@ static void dpu_encoder_virt_mode_set(struct 
drm_encoder *drm_enc,
return;
}
 
-   dpu_rm_init_hw_iter(_iter, drm_enc->base.id, DPU_HW_BLK_PINGPONG);
+   dpu_rm_in

[PATCH v2 2/7] drm/msm/dpu: remove phys_vid subclass

2019-02-13 Thread Jeykumar Sankaran
Not holding any video encoder specific data. Get rid of it.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 11 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 18 --
 2 files changed, 4 insertions(+), 25 deletions(-)

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 acd5956..9b1efd9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -254,17 +254,6 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
 }
 
 /**
- * struct dpu_encoder_phys_vid - sub-class of dpu_encoder_phys to handle video
- * mode specific operations
- * @base:  Baseclass physical encoder structure
- * @timing_params: Current timing parameter
- */
-struct dpu_encoder_phys_vid {
-   struct dpu_encoder_phys base;
-   struct intf_timing_params timing_params;
-};
-
-/**
  * struct dpu_encoder_phys_cmd - sub-class of dpu_encoder_phys to handle 
command
  * mode specific operations
  * @base:  Baseclass physical encoder structure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index e326395..ce65521 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -240,7 +240,6 @@ static bool dpu_encoder_phys_vid_mode_fixup(
 static void dpu_encoder_phys_vid_setup_timing_engine(
struct dpu_encoder_phys *phys_enc)
 {
-   struct dpu_encoder_phys_vid *vid_enc;
struct drm_display_mode mode;
struct intf_timing_params timing_params = { 0 };
const struct dpu_format *fmt = NULL;
@@ -254,7 +253,6 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
}
 
mode = phys_enc->cached_mode;
-   vid_enc = to_dpu_encoder_phys_vid(phys_enc);
if (!phys_enc->hw_intf->ops.setup_timing_gen) {
DPU_ERROR("timing engine setup is not supported\n");
return;
@@ -293,8 +291,6 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
 
programmable_fetch_config(phys_enc, _params);
-
-   vid_enc->timing_params = timing_params;
 }
 
 static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
@@ -515,16 +511,13 @@ static void dpu_encoder_phys_vid_enable(struct 
dpu_encoder_phys *phys_enc)
 
 static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc)
 {
-   struct dpu_encoder_phys_vid *vid_enc;
-
if (!phys_enc) {
DPU_ERROR("invalid encoder\n");
return;
}
 
-   vid_enc = to_dpu_encoder_phys_vid(phys_enc);
DPU_DEBUG_VIDENC(phys_enc, "\n");
-   kfree(vid_enc);
+   kfree(phys_enc);
 }
 
 static void dpu_encoder_phys_vid_get_hw_resources(
@@ -747,7 +740,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
struct dpu_enc_phys_init_params *p)
 {
struct dpu_encoder_phys *phys_enc = NULL;
-   struct dpu_encoder_phys_vid *vid_enc = NULL;
struct dpu_encoder_irq *irq;
int i, ret = 0;
 
@@ -756,14 +748,12 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
goto fail;
}
 
-   vid_enc = kzalloc(sizeof(*vid_enc), GFP_KERNEL);
-   if (!vid_enc) {
+   phys_enc = kzalloc(sizeof(*phys_enc), GFP_KERNEL);
+   if (!phys_enc) {
ret = -ENOMEM;
goto fail;
}
 
-   phys_enc = _enc->base;
-
phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
phys_enc->intf_idx = p->intf_idx;
 
@@ -807,7 +797,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
 
 fail:
DPU_ERROR("failed to create encoder\n");
-   if (vid_enc)
+   if (phys_enc)
dpu_encoder_phys_vid_destroy(phys_enc);
 
return ERR_PTR(ret);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 0/7] move dpu resource parsing to encoder modeset

2019-02-13 Thread Jeykumar Sankaran
Fixing some of the low hanging fruits by moving the hw resource
parsing and assignment to encoder modeset. This series 
prepares DPU resource management to switch to state based
resource tracking which is implemented in the next incoming
changes.

Thanks.

Jeykumar Sankaran (7):
  drm/msm/dpu: move hw_inf encoder baseclass
  drm/msm/dpu: remove phys_vid subclass
  drm/msm/dpu: release resources on modeset failure
  drm/msm/dpu: dont use encoder->crtc in atomic path
  drm/msm/dpu: map mixer/ctl hw blocks in encoder modeset
  drm/msm/dpu: assign intf to encoder in mode_set
  drm/msm/dpu: check split role for single flush

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c   |  64 +---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c|  73 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |  15 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   | 177 ++---
 4 files changed, 118 insertions(+), 211 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 4/7] drm/msm/dpu: dont use encoder->crtc in atomic path

2019-02-13 Thread Jeykumar Sankaran
encoder->crtc is not really meaningful for atomic path. Use
crtc->encoder_mask to identify the crtc attached with
an encoder.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 45617b9..0a19124 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -961,6 +961,7 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_kms *dpu_kms;
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
+   struct drm_crtc *drm_crtc;
struct dpu_rm_hw_iter pp_iter, ctl_iter;
struct msm_display_topology topology;
struct dpu_hw_ctl *hw_ctl[MAX_CHANNELS_PER_ENC] = { NULL };
@@ -992,10 +993,14 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
return;
}
 
+   drm_for_each_crtc(drm_crtc, drm_enc->dev)
+   if (drm_crtc->state->encoder_mask & drm_encoder_mask(drm_enc))
+   break;
+
topology = dpu_encoder_get_topology(dpu_enc, dpu_kms, adj_mode);
 
/* Reserve dynamic resources now. Indicating non-AtomicTest phase */
-   ret = dpu_rm_reserve(_kms->rm, drm_enc, drm_enc->crtc->state,
+   ret = dpu_rm_reserve(_kms->rm, drm_enc, drm_crtc->state,
 topology, false);
if (ret) {
DPU_ERROR_ENC(dpu_enc,
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 1/7] drm/msm/dpu: move hw_inf encoder baseclass

2019-02-13 Thread Jeykumar Sankaran
Both video and command physical encoders will have
a hw interface assigned to it. So there is really no
need to track the hw block in specific encoder subclass.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |   4 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   | 125 +
 2 files changed, 52 insertions(+), 77 deletions(-)

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 44e6f8b6..acd5956 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -201,6 +201,7 @@ struct dpu_encoder_irq {
  * @hw_mdptop: Hardware interface to the top registers
  * @hw_ctl:Hardware interface to the ctl registers
  * @hw_pp: Hardware interface to the ping pong registers
+ * @hw_intf:   Hardware interface to the intf registers
  * @dpu_kms:   Pointer to the dpu_kms top level
  * @cached_mode:   DRM mode cached at mode_set time, acted on in enable
  * @enabled:   Whether the encoder has enabled and running a mode
@@ -229,6 +230,7 @@ struct dpu_encoder_phys {
struct dpu_hw_mdp *hw_mdptop;
struct dpu_hw_ctl *hw_ctl;
struct dpu_hw_pingpong *hw_pp;
+   struct dpu_hw_intf *hw_intf;
struct dpu_kms *dpu_kms;
struct drm_display_mode cached_mode;
enum dpu_enc_split_role split_role;
@@ -255,12 +257,10 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
  * struct dpu_encoder_phys_vid - sub-class of dpu_encoder_phys to handle video
  * mode specific operations
  * @base:  Baseclass physical encoder structure
- * @hw_intf:   Hardware interface to the intf registers
  * @timing_params: Current timing parameter
  */
 struct dpu_encoder_phys_vid {
struct dpu_encoder_phys base;
-   struct dpu_hw_intf *hw_intf;
struct intf_timing_params timing_params;
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index acdab5b0..e326395 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -18,14 +18,14 @@
 #include "dpu_trace.h"
 
 #define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
-   (e) && (e)->base.parent ? \
-   (e)->base.parent->base.id : -1, \
+   (e) && (e)->parent ? \
+   (e)->parent->base.id : -1, \
(e) && (e)->hw_intf ? \
(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
 
 #define DPU_ERROR_VIDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \
-   (e) && (e)->base.parent ? \
-   (e)->base.parent->base.id : -1, \
+   (e) && (e)->parent ? \
+   (e)->parent->base.id : -1, \
(e) && (e)->hw_intf ? \
(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
 
@@ -44,7 +44,7 @@ static bool dpu_encoder_phys_vid_is_master(
 }
 
 static void drm_mode_to_intf_timing_params(
-   const struct dpu_encoder_phys_vid *vid_enc,
+   const struct dpu_encoder_phys *phys_enc,
const struct drm_display_mode *mode,
struct intf_timing_params *timing)
 {
@@ -92,7 +92,7 @@ static void drm_mode_to_intf_timing_params(
timing->hsync_skew = mode->hskew;
 
/* DSI controller cannot handle active-low sync signals. */
-   if (vid_enc->hw_intf->cap->type == INTF_DSI) {
+   if (phys_enc->hw_intf->cap->type == INTF_DSI) {
timing->hsync_polarity = 0;
timing->vsync_polarity = 0;
}
@@ -143,11 +143,11 @@ static u32 get_vertical_total(const struct 
intf_timing_params *timing)
  * lines based on the chip worst case latencies.
  */
 static u32 programmable_fetch_get_num_lines(
-   struct dpu_encoder_phys_vid *vid_enc,
+   struct dpu_encoder_phys *phys_enc,
const struct intf_timing_params *timing)
 {
u32 worst_case_needed_lines =
-   vid_enc->hw_intf->cap->prog_fetch_lines_worst_case;
+   phys_enc->hw_intf->cap->prog_fetch_lines_worst_case;
u32 start_of_frame_lines =
timing->v_back_porch + timing->vsync_pulse_width;
u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
@@ -155,26 +155,26 @@ static u32 programmable_fetch_get_num_lines(
 
/* Fetch must be outside active lines, otherwise undefined. */
if (start_of_frame_lines >= worst_case_needed_lines) {
-   DPU_DEBUG_VIDENC(vid_enc,
+   DPU_DEBUG_VIDENC(phys_enc,
"prog fetch

[PATCH v2 7/7] drm/msm/dpu: check split role for single flush

2019-02-13 Thread Jeykumar Sankaran
Removing unwanted access of crtc_state for finding this information.
Use split role information to know whether we have slave ctl.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 14 +-
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index 02362c5..3fc3cc0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -347,22 +347,10 @@ static void dpu_encoder_phys_vid_underrun_irq(void *arg, 
int irq_idx)
phys_enc);
 }
 
-static bool _dpu_encoder_phys_is_dual_ctl(struct dpu_encoder_phys *phys_enc)
-{
-   struct dpu_crtc_state *dpu_cstate;
-
-   if (!phys_enc)
-   return false;
-
-   dpu_cstate = to_dpu_crtc_state(phys_enc->parent->crtc->state);
-
-   return dpu_cstate->num_ctls > 1;
-}
-
 static bool dpu_encoder_phys_vid_needs_single_flush(
struct dpu_encoder_phys *phys_enc)
 {
-   return (phys_enc && _dpu_encoder_phys_is_dual_ctl(phys_enc));
+   return phys_enc->split_role != ENC_ROLE_SOLO;
 }
 
 static void _dpu_encoder_phys_vid_setup_irq_hw_idx(
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH v2 3/7] drm/msm/dpu: release resources on modeset failure

2019-02-13 Thread Jeykumar Sankaran
release resources allocated in mode_set if any of
the hw check fails. Most of these checks are not
necessary and they will be removed in the follow up
patches with state based resource allocations.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 941ac25..45617b9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1025,13 +1025,13 @@ static void dpu_encoder_virt_mode_set(struct 
drm_encoder *drm_enc,
if (!dpu_enc->hw_pp[i]) {
DPU_ERROR_ENC(dpu_enc, "no pp block assigned"
 "at idx: %d\n", i);
-   return;
+   goto error;
}
 
if (!hw_ctl[i]) {
DPU_ERROR_ENC(dpu_enc, "no ctl block assigned"
 "at idx: %d\n", i);
-   return;
+   goto error;
}
 
phys->hw_pp = dpu_enc->hw_pp[i];
@@ -1044,6 +1044,9 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
}
 
dpu_enc->mode_set_complete = true;
+
+error:
+   dpu_rm_release(_kms->rm, drm_enc);
 }
 
 static void _dpu_encoder_virt_enable_helper(struct drm_encoder *drm_enc)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

[PATCH 1/2] drm/msm/dpu: move hw_inf encoder baseclass

2019-02-06 Thread Jeykumar Sankaran
Both video and command physical encoders will have
a hw interface assigned to it. So there is really no
need to track the hw block in specific encoder subclass.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h   |   4 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c   | 125 +
 2 files changed, 52 insertions(+), 77 deletions(-)

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 44e6f8b6..acd5956 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -201,6 +201,7 @@ struct dpu_encoder_irq {
  * @hw_mdptop: Hardware interface to the top registers
  * @hw_ctl:Hardware interface to the ctl registers
  * @hw_pp: Hardware interface to the ping pong registers
+ * @hw_intf:   Hardware interface to the intf registers
  * @dpu_kms:   Pointer to the dpu_kms top level
  * @cached_mode:   DRM mode cached at mode_set time, acted on in enable
  * @enabled:   Whether the encoder has enabled and running a mode
@@ -229,6 +230,7 @@ struct dpu_encoder_phys {
struct dpu_hw_mdp *hw_mdptop;
struct dpu_hw_ctl *hw_ctl;
struct dpu_hw_pingpong *hw_pp;
+   struct dpu_hw_intf *hw_intf;
struct dpu_kms *dpu_kms;
struct drm_display_mode cached_mode;
enum dpu_enc_split_role split_role;
@@ -255,12 +257,10 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
  * struct dpu_encoder_phys_vid - sub-class of dpu_encoder_phys to handle video
  * mode specific operations
  * @base:  Baseclass physical encoder structure
- * @hw_intf:   Hardware interface to the intf registers
  * @timing_params: Current timing parameter
  */
 struct dpu_encoder_phys_vid {
struct dpu_encoder_phys base;
-   struct dpu_hw_intf *hw_intf;
struct intf_timing_params timing_params;
 };
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index acdab5b0..e326395 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -18,14 +18,14 @@
 #include "dpu_trace.h"
 
 #define DPU_DEBUG_VIDENC(e, fmt, ...) DPU_DEBUG("enc%d intf%d " fmt, \
-   (e) && (e)->base.parent ? \
-   (e)->base.parent->base.id : -1, \
+   (e) && (e)->parent ? \
+   (e)->parent->base.id : -1, \
(e) && (e)->hw_intf ? \
(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
 
 #define DPU_ERROR_VIDENC(e, fmt, ...) DPU_ERROR("enc%d intf%d " fmt, \
-   (e) && (e)->base.parent ? \
-   (e)->base.parent->base.id : -1, \
+   (e) && (e)->parent ? \
+   (e)->parent->base.id : -1, \
(e) && (e)->hw_intf ? \
(e)->hw_intf->idx - INTF_0 : -1, ##__VA_ARGS__)
 
@@ -44,7 +44,7 @@ static bool dpu_encoder_phys_vid_is_master(
 }
 
 static void drm_mode_to_intf_timing_params(
-   const struct dpu_encoder_phys_vid *vid_enc,
+   const struct dpu_encoder_phys *phys_enc,
const struct drm_display_mode *mode,
struct intf_timing_params *timing)
 {
@@ -92,7 +92,7 @@ static void drm_mode_to_intf_timing_params(
timing->hsync_skew = mode->hskew;
 
/* DSI controller cannot handle active-low sync signals. */
-   if (vid_enc->hw_intf->cap->type == INTF_DSI) {
+   if (phys_enc->hw_intf->cap->type == INTF_DSI) {
timing->hsync_polarity = 0;
timing->vsync_polarity = 0;
}
@@ -143,11 +143,11 @@ static u32 get_vertical_total(const struct 
intf_timing_params *timing)
  * lines based on the chip worst case latencies.
  */
 static u32 programmable_fetch_get_num_lines(
-   struct dpu_encoder_phys_vid *vid_enc,
+   struct dpu_encoder_phys *phys_enc,
const struct intf_timing_params *timing)
 {
u32 worst_case_needed_lines =
-   vid_enc->hw_intf->cap->prog_fetch_lines_worst_case;
+   phys_enc->hw_intf->cap->prog_fetch_lines_worst_case;
u32 start_of_frame_lines =
timing->v_back_porch + timing->vsync_pulse_width;
u32 needed_vfp_lines = worst_case_needed_lines - start_of_frame_lines;
@@ -155,26 +155,26 @@ static u32 programmable_fetch_get_num_lines(
 
/* Fetch must be outside active lines, otherwise undefined. */
if (start_of_frame_lines >= worst_case_needed_lines) {
-   DPU_DEBUG_VIDENC(vid_enc,
+   DPU_DEBUG_VIDENC(phys_enc,
"prog fetch

[PATCH 2/2] drm/msm/dpu: remove phys_vid subclass

2019-02-06 Thread Jeykumar Sankaran
Not holding any video encoder specific data. Get rid of it.

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 11 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c | 18 --
 2 files changed, 4 insertions(+), 25 deletions(-)

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 acd5956..9b1efd9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -254,17 +254,6 @@ static inline int dpu_encoder_phys_inc_pending(struct 
dpu_encoder_phys *phys)
 }
 
 /**
- * struct dpu_encoder_phys_vid - sub-class of dpu_encoder_phys to handle video
- * mode specific operations
- * @base:  Baseclass physical encoder structure
- * @timing_params: Current timing parameter
- */
-struct dpu_encoder_phys_vid {
-   struct dpu_encoder_phys base;
-   struct intf_timing_params timing_params;
-};
-
-/**
  * struct dpu_encoder_phys_cmd - sub-class of dpu_encoder_phys to handle 
command
  * mode specific operations
  * @base:  Baseclass physical encoder structure
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
index e326395..ce65521 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
@@ -240,7 +240,6 @@ static bool dpu_encoder_phys_vid_mode_fixup(
 static void dpu_encoder_phys_vid_setup_timing_engine(
struct dpu_encoder_phys *phys_enc)
 {
-   struct dpu_encoder_phys_vid *vid_enc;
struct drm_display_mode mode;
struct intf_timing_params timing_params = { 0 };
const struct dpu_format *fmt = NULL;
@@ -254,7 +253,6 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
}
 
mode = phys_enc->cached_mode;
-   vid_enc = to_dpu_encoder_phys_vid(phys_enc);
if (!phys_enc->hw_intf->ops.setup_timing_gen) {
DPU_ERROR("timing engine setup is not supported\n");
return;
@@ -293,8 +291,6 @@ static void dpu_encoder_phys_vid_setup_timing_engine(
spin_unlock_irqrestore(phys_enc->enc_spinlock, lock_flags);
 
programmable_fetch_config(phys_enc, _params);
-
-   vid_enc->timing_params = timing_params;
 }
 
 static void dpu_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
@@ -515,16 +511,13 @@ static void dpu_encoder_phys_vid_enable(struct 
dpu_encoder_phys *phys_enc)
 
 static void dpu_encoder_phys_vid_destroy(struct dpu_encoder_phys *phys_enc)
 {
-   struct dpu_encoder_phys_vid *vid_enc;
-
if (!phys_enc) {
DPU_ERROR("invalid encoder\n");
return;
}
 
-   vid_enc = to_dpu_encoder_phys_vid(phys_enc);
DPU_DEBUG_VIDENC(phys_enc, "\n");
-   kfree(vid_enc);
+   kfree(phys_enc);
 }
 
 static void dpu_encoder_phys_vid_get_hw_resources(
@@ -747,7 +740,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
struct dpu_enc_phys_init_params *p)
 {
struct dpu_encoder_phys *phys_enc = NULL;
-   struct dpu_encoder_phys_vid *vid_enc = NULL;
struct dpu_encoder_irq *irq;
int i, ret = 0;
 
@@ -756,14 +748,12 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
goto fail;
}
 
-   vid_enc = kzalloc(sizeof(*vid_enc), GFP_KERNEL);
-   if (!vid_enc) {
+   phys_enc = kzalloc(sizeof(*phys_enc), GFP_KERNEL);
+   if (!phys_enc) {
ret = -ENOMEM;
goto fail;
}
 
-   phys_enc = _enc->base;
-
phys_enc->hw_mdptop = p->dpu_kms->hw_mdp;
phys_enc->intf_idx = p->intf_idx;
 
@@ -807,7 +797,7 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
 
 fail:
DPU_ERROR("failed to create encoder\n");
-   if (vid_enc)
+   if (phys_enc)
dpu_encoder_phys_vid_destroy(phys_enc);
 
return ERR_PTR(ret);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 4/4] drm/msm: dpu: Don't queue the frame_done watchdog for cursor

2019-02-06 Thread Jeykumar Sankaran

On 2019-01-28 12:42, Sean Paul wrote:

From: Sean Paul 

In the case of an async/cursor update, we don't wait for the frame_done
event, which means handle_frame_done is never called, and the 
frame_done
watchdog isn't canceled. Currently, this results in a frame_done 
timeout

every time the cursor moves without a synchronous frame following it up
before the timeout expires. Since we don't wait for frame_done, and
don't handle it, we shouldn't modify the watchdog.

Signed-off-by: Sean Paul 
---


Reviewed-by: Jeykumar Sankaran 


 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 51e46b206c73e..05145cf9fb408 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1794,7 +1794,6 @@ void dpu_encoder_kickoff(struct drm_encoder 
*drm_enc,

bool async)
 {
struct dpu_encoder_virt *dpu_enc;
struct dpu_encoder_phys *phys;
-   unsigned long timeout_ms;
ktime_t wakeup_time;
unsigned int i;

@@ -1807,12 +1806,20 @@ void dpu_encoder_kickoff(struct drm_encoder
*drm_enc, bool async)

trace_dpu_enc_kickoff(DRMID(drm_enc));

-   timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 /
-   drm_mode_vrefresh(_enc->crtc->state->adjusted_mode);
+   /*
+* Asynchronous frames don't handle FRAME_DONE events. As such, they
+* shouldn't enable the frame_done watchdog since it will always time
+* out.
+*/
+   if (!async) {
+   unsigned long timeout_ms;
+   timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 /
+   drm_mode_vrefresh(_enc->crtc->state->adjusted_mode);

-   atomic_set(_enc->frame_done_timeout_ms, timeout_ms);
-   mod_timer(_enc->frame_done_timer,
- jiffies + msecs_to_jiffies(timeout_ms));
+   atomic_set(_enc->frame_done_timeout_ms, timeout_ms);
+   mod_timer(_enc->frame_done_timer,
+ jiffies + msecs_to_jiffies(timeout_ms));
+   }

/* All phys encs are ready to go, trigger the kickoff */
_dpu_encoder_kickoff_phys(dpu_enc, async);


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 3/4] drm/msm: dpu: Untangle frame_done timeout units

2019-02-06 Thread Jeykumar Sankaran

On 2019-01-28 12:42, Sean Paul wrote:

From: Sean Paul 

There exists a bunch of confusion as to what the actual units of
frame_done is:

- The definition states it's in # of frames
- CRTC treats it like it's ms
- frame_done_timeout comment thinks it's Hz, but it stores ms
- frame_done timer is setup such that it _should_ be in frames, but the
  timeout is super long

So this patch tries to interpret what the driver really wants. I've
de-centralized the #define since the consumers are expecting different
units.

For crtc, we just use 60ms since that's what it was doing before.
Perhaps we could get fancy and scale with vrefresh, but that's for
another time.

For encoder, fix the comments and rename frame_done_timeout so it's
obvious what the units are. In practice, frame_done_timeout is really
just checked against 0 || !0, which I guess is why the units being 
wrong
didn't matter. I've also dropped the timeout from the previous 60 
frames

to 5. That seems like more than enough time to give up on a frame, and
my guess is that no one intended for the timeout to _actually_ be 60
frames.

Signed-off-by: Sean Paul 


Reviewed-by: Jeykumar Sankaran 


---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c|  5 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 19 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  3 ---
 3 files changed, 15 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 4e4b64821c9e8..b0b394af2a7ef 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -46,6 +46,9 @@
 #define LEFT_MIXER 0
 #define RIGHT_MIXER 1

+/* timeout in ms waiting for frame done */
+#define DPU_CRTC_FRAME_DONE_TIMEOUT_MS 60
+
 static struct dpu_kms *_dpu_crtc_get_kms(struct drm_crtc *crtc)
 {
struct msm_drm_private *priv = crtc->dev->dev_private;
@@ -683,7 +686,7 @@ static int _dpu_crtc_wait_for_frame_done(struct 
drm_crtc

*crtc)

DPU_ATRACE_BEGIN("frame done completion wait");
ret = wait_for_completion_timeout(_crtc->frame_done_comp,
-   msecs_to_jiffies(DPU_FRAME_DONE_TIMEOUT));
+   msecs_to_jiffies(DPU_CRTC_FRAME_DONE_TIMEOUT_MS));
if (!ret) {
DRM_ERROR("frame done wait timed out, ret:%d\n", ret);
rc = -ETIMEDOUT;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 83a4c47dbed2d..51e46b206c73e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -69,6 +69,9 @@

 #define MAX_VDISPLAY_SPLIT 1080

+/* timeout in frames waiting for frame done */
+#define DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES 5
+
 /**
  * enum dpu_enc_rc_events - events for resource control state machine
  * @DPU_ENC_RC_EVENT_KICKOFF:
@@ -158,7 +161,7 @@ enum dpu_enc_rc_states {
  * Bit0 = phys_encs[0] etc.
  * @crtc_frame_event_cb:   callback handler for frame event
  * @crtc_frame_event_cb_data:  callback handler private data
- * @frame_done_timeout:frame done timeout in Hz
+ * @frame_done_timeout_ms: frame done timeout in ms
  * @frame_done_timer:  watchdog timer for frame done event
  * @vsync_event_timer: vsync timer
  * @disp_info: local copy of msm_display_info struct
@@ -196,7 +199,7 @@ struct dpu_encoder_virt {
void (*crtc_frame_event_cb)(void *, u32 event);
void *crtc_frame_event_cb_data;

-   atomic_t frame_done_timeout;
+   atomic_t frame_done_timeout_ms;
struct timer_list frame_done_timer;
struct timer_list vsync_event_timer;

@@ -1184,7 +1187,7 @@ static void dpu_encoder_virt_disable(struct
drm_encoder *drm_enc)
}

 	/* after phys waits for frame-done, should be no more frames pending 
*/

-   if (atomic_xchg(_enc->frame_done_timeout, 0)) {
+   if (atomic_xchg(_enc->frame_done_timeout_ms, 0)) {
DPU_ERROR("enc%d timeout pending\n", drm_enc->base.id);
del_timer_sync(_enc->frame_done_timer);
}
@@ -1341,7 +1344,7 @@ static void dpu_encoder_frame_done_callback(
}

if (!dpu_enc->frame_busy_mask[0]) {
-   atomic_set(_enc->frame_done_timeout, 0);
+   atomic_set(_enc->frame_done_timeout_ms, 0);
del_timer(_enc->frame_done_timer);

dpu_encoder_resource_control(drm_enc,
@@ -1804,10 +1807,10 @@ void dpu_encoder_kickoff(struct drm_encoder
*drm_enc, bool async)

trace_dpu_enc_kickoff(DRMID(drm_enc));

-   timeout_ms = DPU_FRAME_DONE_TIMEOUT * 1000 /
+   timeout_ms = DPU_ENCODER_FRAME_DONE_TIMEOUT_FRAMES * 1000 /
drm_mode_vrefresh(_enc->crtc->state->adjusted_mode);

-   atomic_set(_enc->fram

Re: [PATCH 2/4] drm/msm: dpu: Simplify frame_done watchdog timeout calculation

2019-02-06 Thread Jeykumar Sankaran

On 2019-01-28 12:42, Sean Paul wrote:

From: Sean Paul 

Instead of setting the timeout and then immediately reading it back
(along with the hand-rolled msecs_to_jiffies calculation), just
calculate it once and set it in both places at the same time.

Signed-off-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 12 +++-
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index dd71cb6ba4f5c..83a4c47dbed2d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1791,6 +1791,7 @@ void dpu_encoder_kickoff(struct drm_encoder 
*drm_enc,

bool async)
 {
struct dpu_encoder_virt *dpu_enc;
struct dpu_encoder_phys *phys;
+   unsigned long timeout_ms;
ktime_t wakeup_time;
unsigned int i;

@@ -1803,11 +1804,12 @@ void dpu_encoder_kickoff(struct drm_encoder
*drm_enc, bool async)

trace_dpu_enc_kickoff(DRMID(drm_enc));

-   atomic_set(_enc->frame_done_timeout,
-   DPU_FRAME_DONE_TIMEOUT * 1000 /
-   
drm_mode_vrefresh(_enc->crtc->state->adjusted_mode));
-   mod_timer(_enc->frame_done_timer, jiffies +
-   ((atomic_read(_enc->frame_done_timeout) * HZ) / 1000));
+   timeout_ms = DPU_FRAME_DONE_TIMEOUT * 1000 /
+   drm_mode_vrefresh(_enc->crtc->state->adjusted_mode);


For future cleanup: Is drm_enc->crtc a valid usage here?


+
+   atomic_set(_enc->frame_done_timeout, timeout_ms);
+   mod_timer(_enc->frame_done_timer,
+ jiffies + msecs_to_jiffies(timeout_ms));

/* All phys encs are ready to go, trigger the kickoff */
_dpu_encoder_kickoff_phys(dpu_enc, async);


Reviewed-by: Jeykumar Sankaran 
--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [PATCH 1/4] drm/msm: Use drm_mode_vrefresh instead of mode->vrefresh

2019-02-06 Thread Jeykumar Sankaran

On 2019-01-28 12:42, Sean Paul wrote:

From: Sean Paul 

Use the drm_mode_vrefresh helper where we need refresh rate in case
vrefresh is empty.

Signed-off-by: Sean Paul 


Reviewed-by: Jeykumar Sankaran 


---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c  | 6 +++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c | 5 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c| 2 +-
 drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c | 4 ++--
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 941ac25d2a023..dd71cb6ba4f5c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -522,8 +522,8 @@ static void _dpu_encoder_adjust_mode(struct
drm_connector *connector,

list_for_each_entry(cur_mode, >modes, head) {
if (cur_mode->vdisplay == adj_mode->vdisplay &&
-   cur_mode->hdisplay == adj_mode->hdisplay &&
-   cur_mode->vrefresh == adj_mode->vrefresh) {
+   cur_mode->hdisplay == adj_mode->hdisplay &&
+   drm_mode_vrefresh(cur_mode) == drm_mode_vrefresh(adj_mode)) 
{
adj_mode->private = cur_mode->private;
adj_mode->private_flags |= cur_mode->private_flags;
}
@@ -1805,7 +1805,7 @@ void dpu_encoder_kickoff(struct drm_encoder 
*drm_enc,

bool async)

atomic_set(_enc->frame_done_timeout,
DPU_FRAME_DONE_TIMEOUT * 1000 /
-   drm_enc->crtc->state->adjusted_mode.vrefresh);
+   
drm_mode_vrefresh(_enc->crtc->state->adjusted_mode));
mod_timer(_enc->frame_done_timer, jiffies +
((atomic_read(_enc->frame_done_timeout) * HZ) / 1000));

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 99ab5ca9bed3b..f21163313d635 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
@@ -404,7 +404,8 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
return;
}

-   tc_cfg.vsync_count = vsync_hz / (mode->vtotal * mode->vrefresh);
+   tc_cfg.vsync_count = vsync_hz /
+   (mode->vtotal * drm_mode_vrefresh(mode));

/* enable external TE after kickoff to avoid premature autorefresh */
tc_cfg.hw_vsync_mode = 0;
@@ -424,7 +425,7 @@ static void dpu_encoder_phys_cmd_tearcheck_config(
DPU_DEBUG_CMDENC(cmd_enc,
"tc %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
phys_enc->hw_pp->idx - PINGPONG_0, vsync_hz,
-   mode->vtotal, mode->vrefresh);
+   mode->vtotal, drm_mode_vrefresh(mode));
DPU_DEBUG_CMDENC(cmd_enc,
"tc %d enable %u start_pos %u rd_ptr_irq %u\n",
phys_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
index b01183b309b9e..da1f727d74957 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c
@@ -387,7 +387,7 @@ static void _dpu_plane_set_ot_limit(struct 
drm_plane

*plane,
ot_params.width = drm_rect_width(>pipe_cfg.src_rect);
ot_params.height = drm_rect_height(>pipe_cfg.src_rect);
ot_params.is_wfd = !pdpu->is_rt_pipe;
-   ot_params.frame_rate = crtc->mode.vrefresh;
+   ot_params.frame_rate = drm_mode_vrefresh(>mode);
ot_params.vbif_idx = VBIF_RT;
ot_params.clk_ctrl = pdpu->pipe_hw->cap->clk_ctrl;
ot_params.rd = true;
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
index c1962f29ec7d6..6341ac010f7de 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_cmd_encoder.c
@@ -59,10 +59,10 @@ static int pingpong_tearcheck_setup(struct 
drm_encoder

*encoder,
return -EINVAL;
}

-   total_lines_x100 = mode->vtotal * mode->vrefresh;
+   total_lines_x100 = mode->vtotal * drm_mode_vrefresh(mode);
if (!total_lines_x100) {
DRM_DEV_ERROR(dev, "%s: vtotal(%d) or vrefresh(%d) is 0\n",
-   __func__, mode->vtotal, mode->vrefresh);
+ __func__, mode->vtotal, drm_mode_vrefresh(mode));
return -EINVAL;
}


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 1/3] drm/msm/dpu: fix documentation for intf_type

2018-12-17 Thread Jeykumar Sankaran
Fix intf_type description in msm_disp_info to show that
it represents drm encoder mode of the display.

changes in v3:
- introduced in the series
changes in v4:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 9cd6a96..4725d52 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -126,7 +126,7 @@ struct msm_display_topology {
 
 /**
  * struct msm_display_info - defines display properties
- * @intf_type:  DRM_MODE_CONNECTOR_ display type
+ * @intf_type:  DRM_MODE_ENCODER_ type
  * @capabilities:   Bitmask of display flags
  * @num_of_h_tiles: Number of horizontal tiles in case of split interface
  * @h_tile_instance:Controller instance used per tile. Number of elements 
is
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 3/3] drm/msm/dpu: add display port support in DPU

2018-12-17 Thread Jeykumar Sankaran
Add display port support in DPU by creating hooks
for DP encoder enumeration and encoder mode
initialization.

This change is based on the SDM845 Display port
driver changes[1].

changes in v2:
- rebase on [2] (Sean Paul)
- remove unwanted error checks and
  switch cases (Jordan Crouse)
changes in v3:
- add dp support after fixing
  the current code base for error logging (Sean Paul)
changes in v4:
-  avoid duplicate returns (Jordan Crouse)
-  get rid of duplicate error logs (Jordan Crouse)

[1] https://lwn.net/Articles/768265/
[2] https://lkml.org/lkml/2018/11/17/87

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Jordan Crouse 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  8 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 58 +
 2 files changed, 54 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0dda4a6..371d17d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2031,7 +2031,7 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
 {
int ret = 0;
int i = 0;
-   enum dpu_intf_type intf_type;
+   enum dpu_intf_type intf_type = INTF_NONE;
struct dpu_enc_phys_init_params phys_params;
 
if (!dpu_enc || !dpu_kms) {
@@ -2054,9 +2054,9 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
case DRM_MODE_ENCODER_DSI:
intf_type = INTF_DSI;
break;
-   default:
-   DPU_ERROR_ENC(dpu_enc, "unsupported display interface type\n");
-   return -EINVAL;
+   case DRM_MODE_ENCODER_TMDS:
+   intf_type = INTF_DP;
+   break;
}
 
WARN_ON(disp_info->num_of_h_tiles < 1);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 885bf88..62b400c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -439,6 +439,31 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
return rc;
 }
 
+static int _dpu_kms_initialize_displayport(struct drm_device *dev,
+   struct msm_drm_private *priv,
+   struct dpu_kms *dpu_kms)
+{
+   struct drm_encoder *encoder = NULL;
+   int rc;
+
+   if (!priv->dp)
+   return 0;
+
+   encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS);
+   if (IS_ERR(encoder)) {
+   DPU_ERROR("encoder init failed for dsi display\n");
+   return PTR_ERR(encoder);
+   }
+
+   rc = msm_dp_modeset_init(priv->dp, dev, encoder);
+   if (rc) {
+   DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
+   drm_encoder_cleanup(encoder);
+   }
+
+   return rc;
+}
+
 /**
  * _dpu_kms_setup_displays - create encoders, bridges and connectors
  *   for underlying displays
@@ -451,12 +476,22 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
+   int rc;
+
+   rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   if (rc)
+   goto fail;
+
+   rc = _dpu_kms_initialize_displayport(dev, priv, dpu_kms);
+   if (rc)
+   goto fail;
+
/**
 * Extend this function to initialize other
 * types of displays
 */
-
-   return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+fail:
+   return rc;
 }
 
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -669,13 +704,20 @@ static void _dpu_kms_set_encoder_mode(struct msm_kms *kms,
info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;
 
-   /* TODO: No support for DSI swap */
-   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (priv->dsi[i]) {
-   info.h_tile_instance[info.num_of_h_tiles] = i;
-   info.num_of_h_tiles++;
+   switch (info.intf_type) {
+   case DRM_MODE_ENCODER_DSI:
+   /* TODO: No support for DSI swap */
+   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
+   if (priv->dsi[i]) {
+   info.h_tile_instance[info.num_of_h_tiles] = i;
+   info.num_of_h_tiles++;
+   }
}
-   }
+   break;
+   case DRM_MODE_ENCODER_TMDS:
+   info.num_of_h_tiles = 1;
+   break;
+   };
 
rc = dpu_encoder_setup(encoder->dev, encoder, );
if (rc)
-- 
The Qualcomm Innova

[PATCH v4 2/3] drm/msm/dpu: handle failures while initializing displays

2018-12-17 Thread Jeykumar Sankaran
Bail out KMS hw init on display initialization failures with
proper error logging.

changes in v3:
- introduced in the series
changes in v4:
- avoid duplicate return on errors (Sean Paul)
- avoid spamming errors on failures (Jordon Crouse)

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 31 ++-
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index d39b745..885bf88 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -405,35 +405,38 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms 
*kms,
}
 }
 
-static void _dpu_kms_initialize_dsi(struct drm_device *dev,
+static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
struct drm_encoder *encoder = NULL;
-   int i, rc;
+   int i, rc = 0;
+
+   if (!(priv->dsi[0] || priv->dsi[1]))
+   return rc;
 
/*TODO: Support two independent DSI connectors */
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
-   if (IS_ERR_OR_NULL(encoder)) {
+   if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
-   return;
+   return PTR_ERR(encoder);
}
 
priv->encoders[priv->num_encoders++] = encoder;
 
for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (!priv->dsi[i]) {
-   DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
-   return;
-   }
+   if (!priv->dsi[i])
+   continue;
 
rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
i, rc);
-   continue;
+   break;
}
}
+
+   return rc;
 }
 
 /**
@@ -444,16 +447,16 @@ static void _dpu_kms_initialize_dsi(struct drm_device 
*dev,
  * @dpu_kms:Pointer to dpu kms structure
  * Returns: Zero on success
  */
-static void _dpu_kms_setup_displays(struct drm_device *dev,
+static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
-   _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
-
/**
 * Extend this function to initialize other
 * types of displays
 */
+
+   return _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
 }
 
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -516,7 +519,9 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
 * Create encoder and query display drivers to create
 * bridges and connectors
 */
-   _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   if (ret)
+   goto fail;
 
max_crtc_count = min(catalog->mixer_count, priv->num_encoders);
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [PATCH v3 2/3] drm/msm/dpu: handle failures while initializing displays

2018-12-17 Thread Jeykumar Sankaran

On 2018-12-14 07:22, Sean Paul wrote:

On Thu, Dec 13, 2018 at 10:51:03AM -0800, Jeykumar Sankaran wrote:

Bail out KMS hw init on display initialization failures with
proper error logging.

changes in v3:
- introduced in the series

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 39

+++--

 1 file changed, 27 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 685686e..39c8549 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -405,33 +405,36 @@ static void dpu_kms_wait_for_commit_done(struct

msm_kms *kms,

}
 }

-static void _dpu_kms_initialize_dsi(struct drm_device *dev,
+static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
struct drm_encoder *encoder = NULL;
-   int i, rc;
+   int i, rc = 0;
+
+   if (!(priv->dsi[0] || priv->dsi[1]))


It'd be nice to not have to support both blocks if only one is hooked 
up.

Perhaps move the TODO below above this check.


+   return rc;

/*TODO: Support two independent DSI connectors */
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
-   if (IS_ERR_OR_NULL(encoder)) {
+   if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
-   return;
+   return PTR_ERR(encoder);
}

for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (!priv->dsi[i]) {
-   DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
-   return;
-   }
+   if (!priv->dsi[i])


I don't think this is possible given the check at the beginning of the
function


The check at the beginning returns only if BOTH the dsi blocks are NULL.
In case of full hd panel, only one of the dsi block will be active. The
above check is needed to return on the inactive dsi.

Thanks,
Jeykumar S.

+   continue;

rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc =

%d\n",

i, rc);
-   continue;
+   return rc;
}
}
+
+   return rc;


nit: You can keep rc uninitialized above and just return 0 here.


 }

 /**
@@ -442,16 +445,24 @@ static void _dpu_kms_initialize_dsi(struct

drm_device *dev,

  * @dpu_kms:Pointer to dpu kms structure
  * Returns: Zero on success
  */
-static void _dpu_kms_setup_displays(struct drm_device *dev,
+static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
-   _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   int rc = 0;


nit: No need to initialize to 0


+
+   rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   if (rc) {
+   DPU_ERROR("failed to initialize dsi, rc = %d\n", rc);
+   return rc;
+   }

/**
 * Extend this function to initialize other
 * types of displays
 */
+
+   return rc;
 }

 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -517,7 +528,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms

*dpu_kms)

 * Create encoder and query display drivers to create
 * bridges and connectors
 */
-   _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   if (ret) {
+   DPU_ERROR("failed to setup display, rc = %d\n", ret);
+   goto fail;
+   }

max_crtc_count = min(catalog->mixer_count,
 (u32)dev->mode_config.num_encoder);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

a Linux Foundation Collaborative Project

___
Freedreno mailing list
freedr...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [PATCH v3 2/3] drm/msm/dpu: handle failures while initializing displays

2018-12-17 Thread Jeykumar Sankaran

On 2018-12-14 07:22, Sean Paul wrote:

On Thu, Dec 13, 2018 at 10:51:03AM -0800, Jeykumar Sankaran wrote:

Bail out KMS hw init on display initialization failures with
proper error logging.

changes in v3:
- introduced in the series

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 39

+++--

 1 file changed, 27 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 685686e..39c8549 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -405,33 +405,36 @@ static void dpu_kms_wait_for_commit_done(struct

msm_kms *kms,

}
 }

-static void _dpu_kms_initialize_dsi(struct drm_device *dev,
+static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
struct drm_encoder *encoder = NULL;
-   int i, rc;
+   int i, rc = 0;
+
+   if (!(priv->dsi[0] || priv->dsi[1]))


It'd be nice to not have to support both blocks if only one is hooked 
up.

Perhaps move the TODO below above this check.

For dual DSI panels (e.g: MTP panels), both of these blocks will be 
populated.
TODO comment below is to convey that the support for two independent 
single DSI

panels is not yet available in DPU.

Thanks and Regards,
Jeykumar S.

+   return rc;

/*TODO: Support two independent DSI connectors */
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
-   if (IS_ERR_OR_NULL(encoder)) {
+   if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
-   return;
+   return PTR_ERR(encoder);
}

for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (!priv->dsi[i]) {
-   DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
-   return;
-   }
+   if (!priv->dsi[i])


I don't think this is possible given the check at the beginning of the
function


+   continue;

rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc =

%d\n",

i, rc);
-   continue;
+   return rc;
}
}
+
+   return rc;


nit: You can keep rc uninitialized above and just return 0 here.


 }

 /**
@@ -442,16 +445,24 @@ static void _dpu_kms_initialize_dsi(struct

drm_device *dev,

  * @dpu_kms:Pointer to dpu kms structure
  * Returns: Zero on success
  */
-static void _dpu_kms_setup_displays(struct drm_device *dev,
+static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
-   _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   int rc = 0;


nit: No need to initialize to 0


+
+   rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   if (rc) {
+   DPU_ERROR("failed to initialize dsi, rc = %d\n", rc);
+   return rc;
+   }

/**
 * Extend this function to initialize other
 * types of displays
 */
+
+   return rc;
 }

 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -517,7 +528,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms

*dpu_kms)

 * Create encoder and query display drivers to create
 * bridges and connectors
 */
-   _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   if (ret) {
+   DPU_ERROR("failed to setup display, rc = %d\n", ret);
+   goto fail;
+   }

max_crtc_count = min(catalog->mixer_count,
 (u32)dev->mode_config.num_encoder);
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora

Forum,

a Linux Foundation Collaborative Project

___
Freedreno mailing list
freedr...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [DPU PATCH v2] drm/msm/dpu: Change RGB565 and BGR565 format map.

2018-12-17 Thread Jeykumar Sankaran

On 2018-12-14 11:46, Tanmay Shah wrote:

Red and Blue colors will be interchanged on display with
current format maps for RGB565 and BGR565.

Change both format maps to display correct colors.


You can drop "DPU PATCH" prefix in the patches.
Can you also provide history on what has changed since v1.

Thanks,
Jeykumar S.

Signed-off-by: Tanmay Shah 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
index d53abc8ce670..f59fe1a9f4b9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_formats.c
@@ -263,13 +263,13 @@ static const struct dpu_format dpu_format_map[] = 
{


INTERLEAVED_RGB_FMT(RGB565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-   C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
+   C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
false, 2, 0,
DPU_FETCH_LINEAR, 1),

INTERLEAVED_RGB_FMT(BGR565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
-   C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
+   C1_B_Cb, C0_G_Y, C2_R_Cr, 0, 3,
false, 2, 0,
DPU_FETCH_LINEAR, 1),


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 4/5] drm/msm: clean up display thread

2018-12-14 Thread Jeykumar Sankaran
Since there are no clients using these threads,
cleaning it up.

changes in v2:
- switch all the dependent clients to use system wq
  before removing the disp_threads (Sean Paul)
changes in v3:
- none
changes in v4:
- none
changes in v5:
- Rebase on latest tip with [1] (Sean Paul)

[1] https://patchwork.freedesktop.org/patch/255105/

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 43 ++-
 drivers/gpu/drm/msm/msm_drv.h |  1 -
 2 files changed, 2 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c61ce06..f7cb2c7 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -287,13 +287,8 @@ static int msm_drm_uninit(struct device *dev)
kfree(vbl_ev);
}
 
-   /* clean up display commit/event worker threads */
+   /* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
-   if (priv->disp_thread[i].thread) {
-   kthread_destroy_worker(>disp_thread[i].worker);
-   priv->disp_thread[i].thread = NULL;
-   }
-
if (priv->event_thread[i].thread) {
kthread_destroy_worker(>event_thread[i].worker);
priv->event_thread[i].thread = NULL;
@@ -551,26 +546,6 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
 */
param.sched_priority = 16;
for (i = 0; i < priv->num_crtcs; i++) {
-
-   /* initialize display thread */
-   priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
-   kthread_init_worker(>disp_thread[i].worker);
-   priv->disp_thread[i].dev = ddev;
-   priv->disp_thread[i].thread =
-   kthread_run(kthread_worker_fn,
-   >disp_thread[i].worker,
-   "crtc_commit:%d", priv->disp_thread[i].crtc_id);
-   ret = sched_setscheduler(priv->disp_thread[i].thread,
-   SCHED_FIFO, );
-   if (ret)
-   pr_warn("display thread priority update failed: %d\n",
-   ret);
-
-   if (IS_ERR(priv->disp_thread[i].thread)) {
-   DRM_DEV_ERROR(dev, "failed to create crtc_commit 
kthread\n");
-   priv->disp_thread[i].thread = NULL;
-   }
-
/* initialize event thread */
priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
kthread_init_worker(>event_thread[i].worker);
@@ -580,13 +555,6 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
>event_thread[i].worker,
"crtc_event:%d", priv->event_thread[i].crtc_id);
 
-   /**
-* event thread should also run at same priority as disp_thread
-* because it is handling frame_done events. A lower priority
-* event thread and higher priority disp_thread can causes
-* frame_pending counters beyond 2. This can lead to commit
-* failure at crtc commit level.
-*/
ret = sched_setscheduler(priv->event_thread[i].thread,
SCHED_FIFO, );
if (ret)
@@ -598,16 +566,9 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
priv->event_thread[i].thread = NULL;
}
 
-   if ((!priv->disp_thread[i].thread) ||
-   !priv->event_thread[i].thread) {
+   if (!priv->event_thread[i].thread) {
/* clean up previously created threads if any */
for ( ; i >= 0; i--) {
-   if (priv->disp_thread[i].thread) {
-   kthread_stop(
-   priv->disp_thread[i].thread);
-   priv->disp_thread[i].thread = NULL;
-   }
-
if (priv->event_thread[i].thread) {
kthread_stop(
priv->event_thread[i].thread);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 8fad151..2a30fc4 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -199,7 +199,6 @@ struct msm_drm_private {
unsigned int num_crtcs;
struct drm_crt

[PATCH v5 5/5] drm/msm: subclass work object for vblank events

2018-12-14 Thread Jeykumar Sankaran
msm maintains a separate structure to define vblank
work definitions and a list to track events submitted
to the workqueue. We can avoid this redundant list
and its protection mechanism, if we subclass the
work object to encapsulate vblank event parameters.

changes in v2:
- subclass optimization on system wq (Sean Paul)
changes in v3:
- none
changes in v4:
- move flush_workqueue before irq uninstall
changes in v5:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 71 ++-
 drivers/gpu/drm/msm/msm_drv.h |  7 -
 2 files changed, 22 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index f7cb2c7..f9ad362 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -207,61 +207,44 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }
 
-struct vblank_event {
-   struct list_head node;
+struct msm_vblank_work {
+   struct work_struct work;
int crtc_id;
bool enable;
+   struct msm_drm_private *priv;
 };
 
 static void vblank_ctrl_worker(struct work_struct *work)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
-   struct msm_vblank_ctrl, work);
-   struct msm_drm_private *priv = container_of(vbl_ctrl,
-   struct msm_drm_private, vblank_ctrl);
+   struct msm_vblank_work *vbl_work = container_of(work,
+   struct msm_vblank_work, work);
+   struct msm_drm_private *priv = vbl_work->priv;
struct msm_kms *kms = priv->kms;
-   struct vblank_event *vbl_ev, *tmp;
-   unsigned long flags;
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
-   list_del(_ev->node);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
-
-   if (vbl_ev->enable)
-   kms->funcs->enable_vblank(kms,
-   priv->crtcs[vbl_ev->crtc_id]);
-   else
-   kms->funcs->disable_vblank(kms,
-   priv->crtcs[vbl_ev->crtc_id]);
-
-   kfree(vbl_ev);
 
-   spin_lock_irqsave(_ctrl->lock, flags);
-   }
+   if (vbl_work->enable)
+   kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
+   else
+   kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
 
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   kfree(vbl_work);
 }
 
 static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev;
-   unsigned long flags;
+   struct msm_vblank_work *vbl_work;
 
-   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
-   if (!vbl_ev)
+   vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC);
+   if (!vbl_work)
return -ENOMEM;
 
-   vbl_ev->crtc_id = crtc_id;
-   vbl_ev->enable = enable;
+   INIT_WORK(_work->work, vblank_ctrl_worker);
 
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_add_tail(_ev->node, _ctrl->event_list);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   vbl_work->crtc_id = crtc_id;
+   vbl_work->enable = enable;
+   vbl_work->priv = priv;
 
-   queue_work(priv->wq, _ctrl->work);
+   queue_work(priv->wq, _work->work);
 
return 0;
 }
@@ -273,19 +256,15 @@ static int msm_drm_uninit(struct device *dev)
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_mdss *mdss = priv->mdss;
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev, *tmp;
int i;
 
/* We must cancel and cleanup any pending vblank enable/disable
 * work before drm_irq_uninstall() to avoid work re-enabling an
 * irq after uninstall has disabled it.
 */
-   flush_work(_ctrl->work);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
-   list_del(_ev->node);
-   kfree(vbl_ev);
-   }
+
+   flush_workqueue(priv->wq);
+   destroy_workqueue(priv->wq);
 
/* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
@@ -315,9 +294,6 @@ static int msm_drm_uninit(struct device *dev)
drm_irq_uninstall(ddev);
pm_runtime_put_sync(dev);
 
-   flush_workqueue(priv->wq);
-   destroy_workqueue(priv->wq);
-
if (kms &a

[PATCH v5 3/5] drm/msm/dpu: use msm wq for idle power collapse

2018-12-14 Thread Jeykumar Sankaran
msm is using msm wq for dispatching commit and vblank
events. Switch idle power collapse feature also to use
msm wq to handle delayed work handlers so that
msm can get rid of redundant display threads.

changes in v2:
- patch introduced in v2
changes in v3:
- none
changes in v4:
- use msm wq for delayed works
changes in v5:
- none

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 0dda4a6..941ac25 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -205,7 +205,7 @@ struct dpu_encoder_virt {
bool idle_pc_supported;
struct mutex rc_lock;
enum dpu_enc_rc_states rc_state;
-   struct kthread_delayed_work delayed_off_work;
+   struct delayed_work delayed_off_work;
struct kthread_work vsync_event_work;
struct msm_display_topology topology;
bool mode_set_complete;
@@ -744,7 +744,6 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
 {
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
-   struct msm_drm_thread *disp_thread;
bool is_vid_mode = false;
 
if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private ||
@@ -757,12 +756,6 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
is_vid_mode = dpu_enc->disp_info.capabilities &
MSM_DISPLAY_CAP_VID_MODE;
 
-   if (drm_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) {
-   DPU_ERROR("invalid crtc index\n");
-   return -EINVAL;
-   }
-   disp_thread = >disp_thread[drm_enc->crtc->index];
-
/*
 * when idle_pc is not supported, process only KICKOFF, STOP and MODESET
 * events and return early for other events (ie wb display).
@@ -779,8 +772,7 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
switch (sw_event) {
case DPU_ENC_RC_EVENT_KICKOFF:
/* cancel delayed off work, if any */
-   if (kthread_cancel_delayed_work_sync(
-   _enc->delayed_off_work))
+   if (cancel_delayed_work_sync(_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
 
@@ -839,10 +831,8 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
return 0;
}
 
-   kthread_queue_delayed_work(
-   _thread->worker,
-   _enc->delayed_off_work,
-   msecs_to_jiffies(dpu_enc->idle_timeout));
+   queue_delayed_work(priv->wq, _enc->delayed_off_work,
+  msecs_to_jiffies(dpu_enc->idle_timeout));
 
trace_dpu_enc_rc(DRMID(drm_enc), sw_event,
 dpu_enc->idle_pc_supported, dpu_enc->rc_state,
@@ -851,8 +841,7 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
 
case DPU_ENC_RC_EVENT_PRE_STOP:
/* cancel delayed off work, if any */
-   if (kthread_cancel_delayed_work_sync(
-   _enc->delayed_off_work))
+   if (cancel_delayed_work_sync(_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
 
@@ -1370,7 +1359,7 @@ static void dpu_encoder_frame_done_callback(
}
 }
 
-static void dpu_encoder_off_work(struct kthread_work *work)
+static void dpu_encoder_off_work(struct work_struct *work)
 {
struct dpu_encoder_virt *dpu_enc = container_of(work,
struct dpu_encoder_virt, delayed_off_work.work);
@@ -2195,7 +2184,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct 
drm_encoder *enc,
 
 
mutex_init(_enc->rc_lock);
-   kthread_init_delayed_work(_enc->delayed_off_work,
+   INIT_DELAYED_WORK(_enc->delayed_off_work,
dpu_encoder_off_work);
dpu_enc->idle_timeout = IDLE_TIMEOUT;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 2/5] drm/msm/dpu: use msm wq for vblank events

2018-12-14 Thread Jeykumar Sankaran
DPU was using one thread per display to dispatch async commits and
vblank requests. Since clean up already happened in msm to use the
common thread for all the display commits, display threads are only
used to cater vblank requests. Since a single thread is sufficient
to do the job without any performance hits, use msm workqueue
to queue requests. A separate patch is submitted later in this
series to remove the display threads altogether.

changes in v2:
- switch to system wq before removing disp threads (Sean Paul)
changes in v3:
- none
changes in v4:
- use msm wq for vblank events
changes in v5:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 9 -
 drivers/gpu/drm/msm/msm_drv.h | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 78d5b1c..c61ce06 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -213,7 +213,7 @@ struct vblank_event {
bool enable;
 };
 
-static void vblank_ctrl_worker(struct kthread_work *work)
+static void vblank_ctrl_worker(struct work_struct *work)
 {
struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
struct msm_vblank_ctrl, work);
@@ -261,8 +261,7 @@ static int vblank_ctrl_queue_work(struct msm_drm_private 
*priv,
list_add_tail(_ev->node, _ctrl->event_list);
spin_unlock_irqrestore(_ctrl->lock, flags);
 
-   kthread_queue_work(>disp_thread[crtc_id].worker,
-   _ctrl->work);
+   queue_work(priv->wq, _ctrl->work);
 
return 0;
 }
@@ -282,7 +281,7 @@ static int msm_drm_uninit(struct device *dev)
 * work before drm_irq_uninstall() to avoid work re-enabling an
 * irq after uninstall has disabled it.
 */
-   kthread_flush_work(_ctrl->work);
+   flush_work(_ctrl->work);
list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
list_del(_ev->node);
kfree(vbl_ev);
@@ -489,7 +488,7 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
 
INIT_LIST_HEAD(>inactive_list);
INIT_LIST_HEAD(>vblank_ctrl.event_list);
-   kthread_init_work(>vblank_ctrl.work, vblank_ctrl_worker);
+   INIT_WORK(>vblank_ctrl.work, vblank_ctrl_worker);
spin_lock_init(>vblank_ctrl.lock);
 
drm_mode_config_init(ddev);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 9cd6a96..8fad151 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -78,7 +78,7 @@ enum msm_mdp_plane_property {
 };
 
 struct msm_vblank_ctrl {
-   struct kthread_work work;
+   struct work_struct work;
struct list_head event_list;
spinlock_t lock;
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 1/5] drm/msm/dpu: use kthread_destroy_worker to release msm workers

2018-12-14 Thread Jeykumar Sankaran
use kthread_destroy_worker to destroy workers and
release their associated kthreads.

changes in v3:
- introduced in the series
changes in v4:
- none
changes in v5:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 6265be8..78d5b1c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -291,14 +291,12 @@ static int msm_drm_uninit(struct device *dev)
/* clean up display commit/event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
if (priv->disp_thread[i].thread) {
-   kthread_flush_worker(>disp_thread[i].worker);
-   kthread_stop(priv->disp_thread[i].thread);
+   kthread_destroy_worker(>disp_thread[i].worker);
priv->disp_thread[i].thread = NULL;
}
 
if (priv->event_thread[i].thread) {
-   kthread_flush_worker(>event_thread[i].worker);
-   kthread_stop(priv->event_thread[i].thread);
+   kthread_destroy_worker(>event_thread[i].worker);
priv->event_thread[i].thread = NULL;
}
}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 3/3] drm/msm/dpu: add display port support in DPU

2018-12-13 Thread Jeykumar Sankaran
Add display port support in DPU by creating hooks
for DP encoder enumeration and encoder mode
initialization.

This change is based on the SDM845 Display port
driver changes[1].

changes in v2:
- rebase on [2] (Sean Paul)
- remove unwanted error checks and
  switch cases (Jordan Crouse)
changes in v3:
- add dp support after fixing
  the current code base for error logging (Sean Paul)

[1] https://lwn.net/Articles/768265/
[2] https://lkml.org/lkml/2018/11/17/87

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  8 ++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 51 +
 2 files changed, 49 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 36158b7..b79fd9d 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2029,7 +2029,7 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
 {
int ret = 0;
int i = 0;
-   enum dpu_intf_type intf_type;
+   enum dpu_intf_type intf_type = INTF_NONE;
struct dpu_enc_phys_init_params phys_params;
 
if (!dpu_enc || !dpu_kms) {
@@ -2052,9 +2052,9 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
case DRM_MODE_ENCODER_DSI:
intf_type = INTF_DSI;
break;
-   default:
-   DPU_ERROR_ENC(dpu_enc, "unsupported display interface type\n");
-   return -EINVAL;
+   case DRM_MODE_ENCODER_TMDS:
+   intf_type = INTF_DP;
+   break;
}
 
WARN_ON(disp_info->num_of_h_tiles < 1);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 39c8549..ba3e75c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -437,6 +437,32 @@ static int _dpu_kms_initialize_dsi(struct drm_device *dev,
return rc;
 }
 
+static int _dpu_kms_initialize_displayport(struct drm_device *dev,
+   struct msm_drm_private *priv,
+   struct dpu_kms *dpu_kms)
+{
+   struct drm_encoder *encoder = NULL;
+   int rc = 0;
+
+   if (!priv->dp)
+   return rc;
+
+   encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS);
+   if (IS_ERR(encoder)) {
+   DPU_ERROR("encoder init failed for dsi display\n");
+   return PTR_ERR(encoder);
+   }
+
+   rc = msm_dp_modeset_init(priv->dp, dev, encoder);
+   if (rc) {
+   DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
+   drm_encoder_cleanup(encoder);
+   return rc;
+   }
+
+   return rc;
+}
+
 /**
  * _dpu_kms_setup_displays - create encoders, bridges and connectors
  *   for underlying displays
@@ -457,6 +483,12 @@ static int _dpu_kms_setup_displays(struct drm_device *dev,
return rc;
}
 
+   rc = _dpu_kms_initialize_displayport(dev, priv, dpu_kms);
+   if (rc) {
+   DPU_ERROR("failed to initialize display port, rc = %d\n", rc);
+   return rc;
+   }
+
/**
 * Extend this function to initialize other
 * types of displays
@@ -675,13 +707,20 @@ static void _dpu_kms_set_encoder_mode(struct msm_kms *kms,
info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;
 
-   /* TODO: No support for DSI swap */
-   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (priv->dsi[i]) {
-   info.h_tile_instance[info.num_of_h_tiles] = i;
-   info.num_of_h_tiles++;
+   switch (info.intf_type) {
+   case DRM_MODE_ENCODER_DSI:
+   /* TODO: No support for DSI swap */
+   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
+   if (priv->dsi[i]) {
+   info.h_tile_instance[info.num_of_h_tiles] = i;
+   info.num_of_h_tiles++;
+   }
}
-   }
+   break;
+   case DRM_MODE_ENCODER_TMDS:
+   info.num_of_h_tiles = 1;
+   break;
+   };
 
rc = dpu_encoder_setup(encoder->dev, encoder, );
if (rc)
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 2/3] drm/msm/dpu: handle failures while initializing displays

2018-12-13 Thread Jeykumar Sankaran
Bail out KMS hw init on display initialization failures with
proper error logging.

changes in v3:
- introduced in the series

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 39 +++--
 1 file changed, 27 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 685686e..39c8549 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -405,33 +405,36 @@ static void dpu_kms_wait_for_commit_done(struct msm_kms 
*kms,
}
 }
 
-static void _dpu_kms_initialize_dsi(struct drm_device *dev,
+static int _dpu_kms_initialize_dsi(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
struct drm_encoder *encoder = NULL;
-   int i, rc;
+   int i, rc = 0;
+
+   if (!(priv->dsi[0] || priv->dsi[1]))
+   return rc;
 
/*TODO: Support two independent DSI connectors */
encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_DSI);
-   if (IS_ERR_OR_NULL(encoder)) {
+   if (IS_ERR(encoder)) {
DPU_ERROR("encoder init failed for dsi display\n");
-   return;
+   return PTR_ERR(encoder);
}
 
for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (!priv->dsi[i]) {
-   DPU_DEBUG("invalid msm_dsi for ctrl %d\n", i);
-   return;
-   }
+   if (!priv->dsi[i])
+   continue;
 
rc = msm_dsi_modeset_init(priv->dsi[i], dev, encoder);
if (rc) {
DPU_ERROR("modeset_init failed for dsi[%d], rc = %d\n",
i, rc);
-   continue;
+   return rc;
}
}
+
+   return rc;
 }
 
 /**
@@ -442,16 +445,24 @@ static void _dpu_kms_initialize_dsi(struct drm_device 
*dev,
  * @dpu_kms:Pointer to dpu kms structure
  * Returns: Zero on success
  */
-static void _dpu_kms_setup_displays(struct drm_device *dev,
+static int _dpu_kms_setup_displays(struct drm_device *dev,
struct msm_drm_private *priv,
struct dpu_kms *dpu_kms)
 {
-   _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   int rc = 0;
+
+   rc = _dpu_kms_initialize_dsi(dev, priv, dpu_kms);
+   if (rc) {
+   DPU_ERROR("failed to initialize dsi, rc = %d\n", rc);
+   return rc;
+   }
 
/**
 * Extend this function to initialize other
 * types of displays
 */
+
+   return rc;
 }
 
 static void _dpu_kms_drm_obj_destroy(struct dpu_kms *dpu_kms)
@@ -517,7 +528,11 @@ static int _dpu_kms_drm_obj_init(struct dpu_kms *dpu_kms)
 * Create encoder and query display drivers to create
 * bridges and connectors
 */
-   _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   ret = _dpu_kms_setup_displays(dev, priv, dpu_kms);
+   if (ret) {
+   DPU_ERROR("failed to setup display, rc = %d\n", ret);
+   goto fail;
+   }
 
max_crtc_count = min(catalog->mixer_count,
 (u32)dev->mode_config.num_encoder);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v3 1/3] drm/msm/dpu: fix documentation for intf_type

2018-12-13 Thread Jeykumar Sankaran
Fix intf_type description in msm_disp_info to show that
it represents drm encoder mode of the display.

changes in v3:
- introduced in the series

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 60a7da0..4b0ae70 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -119,7 +119,7 @@ struct msm_display_topology {
 
 /**
  * struct msm_display_info - defines display properties
- * @intf_type:  DRM_MODE_CONNECTOR_ display type
+ * @intf_type:  DRM_MODE_ENCODER_ type
  * @capabilities:   Bitmask of display flags
  * @num_of_h_tiles: Number of horizontal tiles in case of split interface
  * @h_tile_instance:Controller instance used per tile. Number of elements 
is
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 2/6] drm/msm/dpu: remove dev from RM

2018-12-07 Thread Jeykumar Sankaran
Not used. Remove from RM.

changes in v2:
- none

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 3 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 7 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  | 6 +-
 3 files changed, 4 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 4d67b3c..1ecd04a 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -877,8 +877,7 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
goto power_error;
}
 
-   rc = dpu_rm_init(_kms->rm, dpu_kms->catalog, dpu_kms->mmio,
-   dpu_kms->dev);
+   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;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 36a929b..5ce89b9 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -224,13 +224,12 @@ static int _dpu_rm_hw_blk_create(
 
 int dpu_rm_init(struct dpu_rm *rm,
struct dpu_mdss_cfg *cat,
-   void __iomem *mmio,
-   struct drm_device *dev)
+   void __iomem *mmio)
 {
int rc, i;
enum dpu_hw_blk_type type;
 
-   if (!rm || !cat || !mmio || !dev) {
+   if (!rm || !cat || !mmio) {
DPU_ERROR("invalid kms\n");
return -EINVAL;
}
@@ -243,8 +242,6 @@ int dpu_rm_init(struct dpu_rm *rm,
for (type = 0; type < DPU_HW_BLK_MAX; type++)
INIT_LIST_HEAD(>hw_blks[type]);
 
-   rm->dev = dev;
-
/* Some of the sub-blocks require an mdptop to be created */
rm->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, mmio, cat);
if (IS_ERR_OR_NULL(rm->hw_mdp)) {
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 0dd3c21..f41fd19 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -22,7 +22,6 @@
 
 /**
  * struct dpu_rm - DPU dynamic hardware resource manager
- * @dev: device handle for event logging purposes
  * @hw_blks: array of lists of hardware resources present in the system, one
  * list per type of hardware block
  * @hw_mdp: hardware object for mdp_top
@@ -30,7 +29,6 @@
  * @rm_lock: resource manager mutex
  */
 struct dpu_rm {
-   struct drm_device *dev;
struct list_head hw_blks[DPU_HW_BLK_MAX];
struct dpu_hw_mdp *hw_mdp;
uint32_t lm_max_width;
@@ -63,13 +61,11 @@ struct dpu_rm_hw_iter {
  * @rm: DPU Resource Manager handle
  * @cat: Pointer to hardware catalog
  * @mmio: mapped register io address of MDP
- * @dev: device handle for event logging purposes
  * @Return: 0 on Success otherwise -ERROR
  */
 int dpu_rm_init(struct dpu_rm *rm,
struct dpu_mdss_cfg *cat,
-   void __iomem *mmio,
-   struct drm_device *dev);
+   void __iomem *mmio);
 
 /**
  * dpu_rm_destroy - Free all memory allocated by dpu_rm_init
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 3/6] drm/msm/dpu: clean up dpu_rm_check_property_topctl declaration

2018-12-07 Thread Jeykumar Sankaran
Definition was removed already. Clean up header declaration.

changes in v2:
- none

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h | 8 
 1 file changed, 8 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index f41fd19..eb6a6ac 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -136,12 +136,4 @@ void dpu_rm_init_hw_iter(
  * @Return: true on match found, false on no match found
  */
 bool dpu_rm_get_hw(struct dpu_rm *rm, struct dpu_rm_hw_iter *iter);
-
-/**
- * dpu_rm_check_property_topctl - validate property bitmask before it is set
- * @val: user's proposed topology control bitmask
- * @Return: 0 on success or error
- */
-int dpu_rm_check_property_topctl(uint64_t val);
-
 #endif /* __DPU_RM_H__ */
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 6/6] drm/msm/dpu: maintain hw_mdp in kms

2018-12-07 Thread Jeykumar Sankaran
hw_mdp block is common for displays. No need
to reserve per display.

changes in v2:
- use IS_ERR for error checking (Jordan Crouse)

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 11 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 20 
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  | 10 --
 3 files changed, 7 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 1ecd04a..f489526 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -627,6 +627,10 @@ static void _dpu_kms_hw_destroy(struct dpu_kms *dpu_kms)
devm_iounmap(_kms->pdev->dev, dpu_kms->vbif[VBIF_RT]);
dpu_kms->vbif[VBIF_RT] = NULL;
 
+   if (dpu_kms->hw_mdp)
+   dpu_hw_mdp_destroy(dpu_kms->hw_mdp);
+   dpu_kms->hw_mdp = NULL;
+
if (dpu_kms->mmio)
devm_iounmap(_kms->pdev->dev, dpu_kms->mmio);
dpu_kms->mmio = NULL;
@@ -885,11 +889,10 @@ static int dpu_kms_hw_init(struct msm_kms *kms)
 
dpu_kms->rm_init = true;
 
-   dpu_kms->hw_mdp = dpu_rm_get_mdp(_kms->rm);
-   if (IS_ERR_OR_NULL(dpu_kms->hw_mdp)) {
+   dpu_kms->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, dpu_kms->mmio,
+dpu_kms->catalog);
+   if (IS_ERR(dpu_kms->hw_mdp)) {
rc = PTR_ERR(dpu_kms->hw_mdp);
-   if (!dpu_kms->hw_mdp)
-   rc = -EINVAL;
DPU_ERROR("failed to get hw_mdp: %d\n", rc);
dpu_kms->hw_mdp = NULL;
goto power_error;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index e7fc9a4..037d9f4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -49,11 +49,6 @@ struct dpu_rm_hw_blk {
struct dpu_hw_blk *hw;
 };
 
-struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm)
-{
-   return rm->hw_mdp;
-}
-
 void dpu_rm_init_hw_iter(
struct dpu_rm_hw_iter *iter,
uint32_t enc_id,
@@ -148,9 +143,6 @@ int dpu_rm_destroy(struct dpu_rm *rm)
}
}
 
-   dpu_hw_mdp_destroy(rm->hw_mdp);
-   rm->hw_mdp = NULL;
-
mutex_destroy(>rm_lock);
 
return 0;
@@ -165,11 +157,8 @@ static int _dpu_rm_hw_blk_create(
void *hw_catalog_info)
 {
struct dpu_rm_hw_blk *blk;
-   struct dpu_hw_mdp *hw_mdp;
void *hw;
 
-   hw_mdp = rm->hw_mdp;
-
switch (type) {
case DPU_HW_BLK_LM:
hw = dpu_hw_lm_init(id, mmio, cat);
@@ -233,15 +222,6 @@ int dpu_rm_init(struct dpu_rm *rm,
for (type = 0; type < DPU_HW_BLK_MAX; type++)
INIT_LIST_HEAD(>hw_blks[type]);
 
-   /* Some of the sub-blocks require an mdptop to be created */
-   rm->hw_mdp = dpu_hw_mdptop_init(MDP_TOP, mmio, cat);
-   if (IS_ERR_OR_NULL(rm->hw_mdp)) {
-   rc = PTR_ERR(rm->hw_mdp);
-   rm->hw_mdp = NULL;
-   DPU_ERROR("failed: mdp hw not available\n");
-   goto fail;
-   }
-
/* Interrogate HW catalog and create tracking items for hw blocks */
for (i = 0; i < cat->mixer_count; i++) {
struct dpu_lm_cfg *lm = >mixer[i];
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index eb6a6ac..381611f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
@@ -24,13 +24,11 @@
  * struct dpu_rm - DPU dynamic hardware resource manager
  * @hw_blks: array of lists of hardware resources present in the system, one
  * list per type of hardware block
- * @hw_mdp: hardware object for mdp_top
  * @lm_max_width: cached layer mixer maximum width
  * @rm_lock: resource manager mutex
  */
 struct dpu_rm {
struct list_head hw_blks[DPU_HW_BLK_MAX];
-   struct dpu_hw_mdp *hw_mdp;
uint32_t lm_max_width;
struct mutex rm_lock;
 };
@@ -104,14 +102,6 @@ int dpu_rm_reserve(struct dpu_rm *rm,
 void dpu_rm_release(struct dpu_rm *rm, struct drm_encoder *enc);
 
 /**
- * dpu_rm_get_mdp - Retrieve HW block for MDP TOP.
- * This is never reserved, and is usable by any display.
- * @rm: DPU Resource Manager handle
- * @Return: Pointer to hw block or NULL
- */
-struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm);
-
-/**
  * dpu_rm_init_hw_iter - setup given iterator for new iteration over hw list
  * using dpu_rm_get_hw
  * @iter: iter object to initialize
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 4/6] drm/msm/dpu: remove encoder from crtc mixer struct

2018-12-07 Thread Jeykumar Sankaran
Not actively used. Clean up the crtc mixer struct.

changes in v2:
- none

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c | 2 --
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h | 2 --
 2 files changed, 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 9be7c35..d6e6925 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -465,8 +465,6 @@ static void _dpu_crtc_setup_mixer_for_encoder(
return;
}
 
-   mixer->encoder = enc;
-
cstate->num_mixers++;
DPU_DEBUG("setup mixer %d: lm %d\n",
i, mixer->hw_lm->idx - LM_0);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index dbfb38a..e59d62b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -84,14 +84,12 @@ struct dpu_crtc_smmu_state_data {
  * struct dpu_crtc_mixer: stores the map for each virtual pipeline in the CRTC
  * @hw_lm: LM HW Driver context
  * @lm_ctl:CTL Path HW driver context
- * @encoder:   Encoder attached to this lm & ctl
  * @mixer_op_mode: mixer blending operation mode
  * @flush_mask:mixer flush mask for ctl, mixer and pipe
  */
 struct dpu_crtc_mixer {
struct dpu_hw_mixer *hw_lm;
struct dpu_hw_ctl *lm_ctl;
-   struct drm_encoder *encoder;
u32 mixer_op_mode;
u32 flush_mask;
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v2 1/6] drm/msm/dpu: avoid tracking reservations in RM

2018-12-07 Thread Jeykumar Sankaran
RM was equipped with reservation tracking structure RSVP
to cache HW reservation of displays for certain clients
where atomic_checks (atomic commit with TEST_ONLY) for all
the displays are called before their respective atomic_commits.
Since DPU doesn't support the sequence anymore, clean up
the support from RM. Replace rsvp with the corresponding
encoder id to tag the HW blocks reserved. It prepares DPU
to get rid of RM altogether and track reservations using
private states.

changes in v2:
- none

Signed-off-by: Jeykumar Sankaran 
Reviewed-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c | 284 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h |   4 -
 2 files changed, 43 insertions(+), 245 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index bdb1177..36a929b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -21,8 +21,8 @@
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
-#define RESERVED_BY_OTHER(h, r) \
-   ((h)->rsvp && ((h)->rsvp->enc_id != (r)->enc_id))
+#define RESERVED_BY_OTHER(h, r)  \
+   ((h)->enc_id && (h)->enc_id != r)
 
 /**
  * struct dpu_rm_requirements - Reservation requirements parameter bundle
@@ -34,85 +34,23 @@ struct dpu_rm_requirements {
struct dpu_encoder_hw_resources hw_res;
 };
 
-/**
- * struct dpu_rm_rsvp - Use Case Reservation tagging structure
- * Used to tag HW blocks as reserved by a CRTC->Encoder->Connector chain
- * By using as a tag, rather than lists of pointers to HW blocks used
- * we can avoid some list management since we don't know how many blocks
- * of each type a given use case may require.
- * @list:  List head for list of all reservations
- * @seq:   Global RSVP sequence number for debugging, especially for
- * differentiating differenct allocations for same encoder.
- * @enc_id:Reservations are tracked by Encoder DRM object ID.
- * CRTCs may be connected to multiple Encoders.
- * An encoder or connector id identifies the display path.
- */
-struct dpu_rm_rsvp {
-   struct list_head list;
-   uint32_t seq;
-   uint32_t enc_id;
-};
 
 /**
  * struct dpu_rm_hw_blk - hardware block tracking list member
  * @list:  List head for list of all hardware blocks tracking items
- * @rsvp:  Pointer to use case reservation if reserved by a client
- * @rsvp_nxt:  Temporary pointer used during reservation to the incoming
- * request. Will be swapped into rsvp if proposal is accepted
  * @type:  Type of hardware block this structure tracks
  * @id:Hardware ID number, within it's own space, ie. LM_X
- * @catalog:   Pointer to the hardware catalog entry for this block
+ * @enc_id:Encoder id to which this blk is binded
  * @hw:Pointer to the hardware register access object for this 
block
  */
 struct dpu_rm_hw_blk {
struct list_head list;
-   struct dpu_rm_rsvp *rsvp;
-   struct dpu_rm_rsvp *rsvp_nxt;
enum dpu_hw_blk_type type;
uint32_t id;
+   uint32_t enc_id;
struct dpu_hw_blk *hw;
 };
 
-/**
- * dpu_rm_dbg_rsvp_stage - enum of steps in making reservation for event 
logging
- */
-enum dpu_rm_dbg_rsvp_stage {
-   DPU_RM_STAGE_BEGIN,
-   DPU_RM_STAGE_AFTER_CLEAR,
-   DPU_RM_STAGE_AFTER_RSVPNEXT,
-   DPU_RM_STAGE_FINAL
-};
-
-static void _dpu_rm_print_rsvps(
-   struct dpu_rm *rm,
-   enum dpu_rm_dbg_rsvp_stage stage)
-{
-   struct dpu_rm_rsvp *rsvp;
-   struct dpu_rm_hw_blk *blk;
-   enum dpu_hw_blk_type type;
-
-   DPU_DEBUG("%d\n", stage);
-
-   list_for_each_entry(rsvp, >rsvps, list) {
-   DRM_DEBUG_KMS("%d rsvp[s%ue%u]\n", stage, rsvp->seq,
- rsvp->enc_id);
-   }
-
-   for (type = 0; type < DPU_HW_BLK_MAX; type++) {
-   list_for_each_entry(blk, >hw_blks[type], list) {
-   if (!blk->rsvp && !blk->rsvp_nxt)
-   continue;
-
-   DRM_DEBUG_KMS("%d rsvp[s%ue%u->s%ue%u] %d %d\n", stage,
-   (blk->rsvp) ? blk->rsvp->seq : 0,
-   (blk->rsvp) ? blk->rsvp->enc_id : 0,
-   (blk->rsvp_nxt) ? blk->rsvp_nxt->seq : 0,
-   (blk->rsvp_nxt) ? blk->rsvp_nxt->enc_id : 0,
-   blk->type, blk->id);
-   }
-   }
-}
-
 struct dpu_hw_mdp *dpu_rm_get_mdp(struct dpu_rm *rm)
 {
return rm->hw_mdp;
@@ -148,15 +86,13 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, 
struct dpu_rm_hw_iter *i)
i->blk = list_prepare_entry(i->

[PATCH v2 5/6] drm/msm/dpu: clean up redundant hw type

2018-12-07 Thread Jeykumar Sankaran
struct dpu_hw_blk has hw block type info. Remove duplicate
type tracking in struct dpu_rm_hw_blk.

changes in v2:
- remove redundant type in trace api's (Sean Paul)

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 22 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h | 28 +++-
 2 files changed, 16 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index 5ce89b9..e7fc9a4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -38,14 +38,12 @@ struct dpu_rm_requirements {
 /**
  * struct dpu_rm_hw_blk - hardware block tracking list member
  * @list:  List head for list of all hardware blocks tracking items
- * @type:  Type of hardware block this structure tracks
  * @id:Hardware ID number, within it's own space, ie. LM_X
  * @enc_id:Encoder id to which this blk is binded
  * @hw:Pointer to the hardware register access object for this 
block
  */
 struct dpu_rm_hw_blk {
struct list_head list;
-   enum dpu_hw_blk_type type;
uint32_t id;
uint32_t enc_id;
struct dpu_hw_blk *hw;
@@ -86,12 +84,6 @@ static bool _dpu_rm_get_hw_locked(struct dpu_rm *rm, struct 
dpu_rm_hw_iter *i)
i->blk = list_prepare_entry(i->blk, blk_list, list);
 
list_for_each_entry_continue(i->blk, blk_list, list) {
-   if (i->blk->type != i->type) {
-   DPU_ERROR("found incorrect block type %d on %d list\n",
-   i->blk->type, i->type);
-   return false;
-   }
-
if (i->enc_id == i->blk->enc_id) {
i->hw = i->blk->hw;
DPU_DEBUG("found type %d id %d for enc %d\n",
@@ -151,7 +143,7 @@ int dpu_rm_destroy(struct dpu_rm *rm)
list_for_each_entry_safe(hw_cur, hw_nxt, >hw_blks[type],
list) {
list_del(_cur->list);
-   _dpu_rm_hw_destroy(hw_cur->type, hw_cur->hw);
+   _dpu_rm_hw_destroy(type, hw_cur->hw);
kfree(hw_cur);
}
}
@@ -213,7 +205,6 @@ static int _dpu_rm_hw_blk_create(
return -ENOMEM;
}
 
-   blk->type = type;
blk->id = id;
blk->hw = hw;
blk->enc_id = 0;
@@ -458,8 +449,7 @@ static int _dpu_rm_reserve_lms(struct dpu_rm *rm, uint32_t 
enc_id,
lm[i]->enc_id = enc_id;
pp[i]->enc_id = enc_id;
 
-   trace_dpu_rm_reserve_lms(lm[i]->id, lm[i]->type, enc_id,
-pp[i]->id);
+   trace_dpu_rm_reserve_lms(lm[i]->id, enc_id, pp[i]->id);
}
 
return rc;
@@ -510,8 +500,7 @@ static int _dpu_rm_reserve_ctls(
 
for (i = 0; i < ARRAY_SIZE(ctls) && i < num_ctls; i++) {
ctls[i]->enc_id = enc_id;
-   trace_dpu_rm_reserve_ctls(ctls[i]->id, ctls[i]->type,
- enc_id);
+   trace_dpu_rm_reserve_ctls(ctls[i]->id, enc_id);
}
 
return 0;
@@ -538,8 +527,7 @@ static int _dpu_rm_reserve_intf(
}
 
iter.blk->enc_id = enc_id;
-   trace_dpu_rm_reserve_intf(iter.blk->id, iter.blk->type,
- enc_id);
+   trace_dpu_rm_reserve_intf(iter.blk->id, enc_id);
break;
}
 
@@ -628,7 +616,7 @@ static void _dpu_rm_release_reservation(struct dpu_rm *rm, 
uint32_t enc_id)
if (blk->enc_id == enc_id) {
blk->enc_id = 0;
DPU_DEBUG("rel enc %d %d %d\n", enc_id,
- blk->type, blk->id);
+ type, blk->id);
}
}
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
index c78b521..8bb4609 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h
@@ -831,48 +831,42 @@
 );
 
 DECLARE_EVENT_CLASS(dpu_rm_iter_template,
-   TP_PROTO(uint32_t id, enum dpu_hw_blk_type type, uint32_t enc_id),
-   TP_ARGS(id, type, enc_id),
+   TP_PROTO(uint32_t id, uint32_t enc_id),
+   TP_ARGS(id, enc_id),
TP_STRUCT__entry(
__field(uint32_t,   id  )
-   __field(enum dpu_hw_blk_type,   type)
__field(uint32_t,   enc_id  )
),
TP_fast_assign(
 

[PATCH v2 0/6] DPU resource manager cleanup

2018-12-07 Thread Jeykumar Sankaran
First set of clean up patches for DPU resource manager. 
Removes/realigns some of the redudant RM interfaces.
Eventual plan is to migrate resource maintenence using
private state objects.

Thanks and Regards,
Jeykumar S

Jeykumar Sankaran (6):
  drm/msm/dpu: avoid tracking reservations in RM
  drm/msm/dpu: remove dev from RM
  drm/msm/dpu: clean up dpu_rm_check_property_topctl declaration
  drm/msm/dpu: remove encoder from crtc mixer struct
  drm/msm/dpu: clean up redundant hw type
  drm/msm/dpu: maintain hw_mdp in kms

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c  |   2 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h  |   2 -
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c   |  14 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c| 325 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|  28 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_trace.h |  28 +--
 6 files changed, 66 insertions(+), 333 deletions(-)

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [PATCH v2 5/5] drm/msm: subclass work object for vblank events

2018-12-07 Thread Jeykumar Sankaran

On 2018-12-07 09:22, Sean Paul wrote:

On Mon, Dec 03, 2018 at 12:27:42PM -0800, Jeykumar Sankaran wrote:

On 2018-12-03 06:21, Sean Paul wrote:
> On Fri, Nov 30, 2018 at 04:21:15PM -0800, Jeykumar Sankaran wrote:
> > On 2018-11-30 12:07, Sean Paul wrote:
> > > On Fri, Nov 30, 2018 at 11:45:55AM -0800, Jeykumar Sankaran wrote:
> > > > On 2018-11-29 14:15, Sean Paul wrote:
> > > > > On Tue, Nov 20, 2018 at 02:04:14PM -0800, Jeykumar Sankaran

wrote:

> > > > > > On 2018-11-07 07:55, Sean Paul wrote:
> > > > > > > On Tue, Nov 06, 2018 at 02:36:30PM -0800, Jeykumar

Sankaran

> wrote:
> > > > > > > > msm maintains a separate structure to define vblank
> > > > > > > > work definitions and a list to track events submitted
> > > > > > > > to the workqueue. We can avoid this redundant list
> > > > > > > > and its protection mechanism, if we subclass the
> > > > > > > > work object to encapsulate vblank event parameters.
> > > > > > > >
> > > > > > > > changes in v2:
> > > > > > > > - subclass optimization on system wq (Sean Paul)
> > > > > > >
> > > > > > > I wouldn't do it like this, tbh. One problem is that

you've

> lost
> > > your
> > > > > > > flush() on
> > > > > > > unbind, so there's no way to know if you have workers in

the

> wild
> > > > > > > waiting
> > > > > > > to
> > > > > > > enable/disable vblank.
> > > > > > >
> > > > > > > Another issues is that AFAICT, we don't need a queue of
> > > > > > > enables/disables,
> > > > > > > but
> > > > > > > rather just the last requested state (ie: should we be on

or

> off).
> > > So
> > > > > > > things
> > > > > > > don't need to be this complicated (and we're possibly
> thrashing
> > > vblank
> > > > > > > on/off
> > > > > > > for no reason).
> > > > > > >
> > > > > > > I'm still of the mind that you should just make this
> synchronous
> > > and
> > > > > be
> > > > > > > done
> > > > > > > with the threads (especially since we're still
> > > uncovering/introducing
> > > > > > > races!).
> > > > > > >
> > > > > > While scoping out the effort to make vblank events

synchronous,

> I
> > > > > > found
> > > > > > that the spinlock locking order of vblank request sequence

and

> > > vblank
> > > > > > callback
> > > > > > sequences are the opposite.
> > > > > >
> > > > > > In DPU, drm_vblank_enable acquires vblank_time_lock before
> > > registering
> > > > > > the crtc to encoder which happens after acquiring
> encoder_spinlock.
> > > > > > But
> > > > > > the vblank_callback acquires encoder_spinlock before

accessing

> the
> > > > > > registered
> > > > > > crtc and calling into drm_vblank_handler which tries to

acquire

> > > > > > vblank_time_lock.
> > > > > > Acquiring both vblank_time_lock and encoder_spinlock in the

same

> > > > > > thread
> > > > > > is leading to deadlock.
> > > > >
> > > > > Hmm, I'm not sure I follow. Are you seeing issues where irq
> overlaps
> > > > > with
> > > > > enable/disable? I hacked in sync vblank enable/disable quickly

to

> see
> > > if
> > > > > I
> > > > > could
> > > > > reproduce what you're seeing, but things seemed well behaved.
> > > > >
> > > >
> > > > The race is between drm_vblank_get/put and vblank_handler

contexts.

> > > >
> > > > When made synchronous:
> > > >
> > > > while calling drm_vblank_get, the callstack looks like below:
> > > > drm_vblank_get -> drm_vblank_enable (acquires vblank_time_lock)

->

> > > > __enable_vblank -> dpu_crtc_vblank ->
> > > > dpu_encoder_toggle_vblank_for_crtc
> > > > (tries to acquire enc_spinlock)
> > > >
> > > > In vblank handler, the call stack will b

[PATCH v4 5/5] drm/msm: subclass work object for vblank events

2018-12-06 Thread Jeykumar Sankaran
msm maintains a separate structure to define vblank
work definitions and a list to track events submitted
to the workqueue. We can avoid this redundant list
and its protection mechanism, if we subclass the
work object to encapsulate vblank event parameters.

changes in v2:
- subclass optimization on system wq (Sean Paul)
changes in v3:
- none
changes in v4:
- move flush_workqueue before irq uninstall

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 71 ++-
 drivers/gpu/drm/msm/msm_drv.h |  7 -
 2 files changed, 22 insertions(+), 56 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 1e9fec1..5f61fc4 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -206,61 +206,44 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }
 
-struct vblank_event {
-   struct list_head node;
+struct msm_vblank_work {
+   struct work_struct work;
int crtc_id;
bool enable;
+   struct msm_drm_private *priv;
 };
 
 static void vblank_ctrl_worker(struct work_struct *work)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
-   struct msm_vblank_ctrl, work);
-   struct msm_drm_private *priv = container_of(vbl_ctrl,
-   struct msm_drm_private, vblank_ctrl);
+   struct msm_vblank_work *vbl_work = container_of(work,
+   struct msm_vblank_work, work);
+   struct msm_drm_private *priv = vbl_work->priv;
struct msm_kms *kms = priv->kms;
-   struct vblank_event *vbl_ev, *tmp;
-   unsigned long flags;
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
-   list_del(_ev->node);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
-
-   if (vbl_ev->enable)
-   kms->funcs->enable_vblank(kms,
-   priv->crtcs[vbl_ev->crtc_id]);
-   else
-   kms->funcs->disable_vblank(kms,
-   priv->crtcs[vbl_ev->crtc_id]);
-
-   kfree(vbl_ev);
 
-   spin_lock_irqsave(_ctrl->lock, flags);
-   }
+   if (vbl_work->enable)
+   kms->funcs->enable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
+   else
+   kms->funcs->disable_vblank(kms, priv->crtcs[vbl_work->crtc_id]);
 
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   kfree(vbl_work);
 }
 
 static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev;
-   unsigned long flags;
+   struct msm_vblank_work *vbl_work;
 
-   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
-   if (!vbl_ev)
+   vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC);
+   if (!vbl_work)
return -ENOMEM;
 
-   vbl_ev->crtc_id = crtc_id;
-   vbl_ev->enable = enable;
+   INIT_WORK(_work->work, vblank_ctrl_worker);
 
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_add_tail(_ev->node, _ctrl->event_list);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   vbl_work->crtc_id = crtc_id;
+   vbl_work->enable = enable;
+   vbl_work->priv = priv;
 
-   queue_work(priv->wq, _ctrl->work);
+   queue_work(priv->wq, _work->work);
 
return 0;
 }
@@ -272,19 +255,15 @@ static int msm_drm_uninit(struct device *dev)
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_mdss *mdss = priv->mdss;
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev, *tmp;
int i;
 
/* We must cancel and cleanup any pending vblank enable/disable
 * work before drm_irq_uninstall() to avoid work re-enabling an
 * irq after uninstall has disabled it.
 */
-   flush_work(_ctrl->work);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
-   list_del(_ev->node);
-   kfree(vbl_ev);
-   }
+
+   flush_workqueue(priv->wq);
+   destroy_workqueue(priv->wq);
 
/* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
@@ -313,9 +292,6 @@ static int msm_drm_uninit(struct device *dev)
drm_irq_uninstall(ddev);
pm_runtime_put_sync(dev);
 
-   flush_workqueue(priv->wq);
-   destroy_workqueue(priv->wq);
-
if (kms && kms->funcs)
   

[PATCH v4 3/5] drm/msm/dpu: use msm wq for idle power collapse

2018-12-06 Thread Jeykumar Sankaran
msm is using msm wq for dispatching commit and vblank
events. Switch idle power collapse feature also to use
msm wq to handle delayed work handlers so that
msm can get rid of redundant display threads.

changes in v2:
- patch introduced in v2
changes in v3:
- none
changes in v4:
- use msm wq for delayed works

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

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 36158b7..3d1e1e4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -205,7 +205,7 @@ struct dpu_encoder_virt {
bool idle_pc_supported;
struct mutex rc_lock;
enum dpu_enc_rc_states rc_state;
-   struct kthread_delayed_work delayed_off_work;
+   struct delayed_work delayed_off_work;
struct kthread_work vsync_event_work;
struct msm_display_topology topology;
bool mode_set_complete;
@@ -742,7 +742,6 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
 {
struct dpu_encoder_virt *dpu_enc;
struct msm_drm_private *priv;
-   struct msm_drm_thread *disp_thread;
bool is_vid_mode = false;
 
if (!drm_enc || !drm_enc->dev || !drm_enc->dev->dev_private ||
@@ -755,12 +754,6 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
is_vid_mode = dpu_enc->disp_info.capabilities &
MSM_DISPLAY_CAP_VID_MODE;
 
-   if (drm_enc->crtc->index >= ARRAY_SIZE(priv->disp_thread)) {
-   DPU_ERROR("invalid crtc index\n");
-   return -EINVAL;
-   }
-   disp_thread = >disp_thread[drm_enc->crtc->index];
-
/*
 * when idle_pc is not supported, process only KICKOFF, STOP and MODESET
 * events and return early for other events (ie wb display).
@@ -777,8 +770,7 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
switch (sw_event) {
case DPU_ENC_RC_EVENT_KICKOFF:
/* cancel delayed off work, if any */
-   if (kthread_cancel_delayed_work_sync(
-   _enc->delayed_off_work))
+   if (cancel_delayed_work_sync(_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
 
@@ -837,10 +829,8 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
return 0;
}
 
-   kthread_queue_delayed_work(
-   _thread->worker,
-   _enc->delayed_off_work,
-   msecs_to_jiffies(dpu_enc->idle_timeout));
+   queue_delayed_work(priv->wq, _enc->delayed_off_work,
+  msecs_to_jiffies(dpu_enc->idle_timeout));
 
trace_dpu_enc_rc(DRMID(drm_enc), sw_event,
 dpu_enc->idle_pc_supported, dpu_enc->rc_state,
@@ -849,8 +839,7 @@ static int dpu_encoder_resource_control(struct drm_encoder 
*drm_enc,
 
case DPU_ENC_RC_EVENT_PRE_STOP:
/* cancel delayed off work, if any */
-   if (kthread_cancel_delayed_work_sync(
-   _enc->delayed_off_work))
+   if (cancel_delayed_work_sync(_enc->delayed_off_work))
DPU_DEBUG_ENC(dpu_enc, "sw_event:%d, work cancelled\n",
sw_event);
 
@@ -1368,7 +1357,7 @@ static void dpu_encoder_frame_done_callback(
}
 }
 
-static void dpu_encoder_off_work(struct kthread_work *work)
+static void dpu_encoder_off_work(struct work_struct *work)
 {
struct dpu_encoder_virt *dpu_enc = container_of(work,
struct dpu_encoder_virt, delayed_off_work.work);
@@ -2193,7 +2182,7 @@ int dpu_encoder_setup(struct drm_device *dev, struct 
drm_encoder *enc,
 
 
mutex_init(_enc->rc_lock);
-   kthread_init_delayed_work(_enc->delayed_off_work,
+   INIT_DELAYED_WORK(_enc->delayed_off_work,
dpu_encoder_off_work);
dpu_enc->idle_timeout = IDLE_TIMEOUT;
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 1/5] drm/msm/dpu: use kthread_destroy_worker to release msm workers

2018-12-06 Thread Jeykumar Sankaran
use kthread_destroy_worker to destroy workers and
release their associated kthreads.

changes in v3:
- introduced in the series
changes in v4:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 7d168cf..956f0599 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -290,14 +290,12 @@ static int msm_drm_uninit(struct device *dev)
/* clean up display commit/event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
if (priv->disp_thread[i].thread) {
-   kthread_flush_worker(>disp_thread[i].worker);
-   kthread_stop(priv->disp_thread[i].thread);
+   kthread_destroy_worker(>disp_thread[i].worker);
priv->disp_thread[i].thread = NULL;
}
 
if (priv->event_thread[i].thread) {
-   kthread_flush_worker(>event_thread[i].worker);
-   kthread_stop(priv->event_thread[i].thread);
+   kthread_destroy_worker(>event_thread[i].worker);
priv->event_thread[i].thread = NULL;
}
}
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 4/5] drm/msm: clean up display thread

2018-12-06 Thread Jeykumar Sankaran
Since there are no clients using these threads,
cleaning it up.

changes in v2:
- switch all the dependent clients to use system wq
  before removing the disp_threads (Sean Paul)
changes in v3:
- none
changes in v4:
- none

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 35 +--
 drivers/gpu/drm/msm/msm_drv.h |  1 -
 2 files changed, 1 insertion(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 37740b8..1e9fec1 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -286,13 +286,8 @@ static int msm_drm_uninit(struct device *dev)
kfree(vbl_ev);
}
 
-   /* clean up display commit/event worker threads */
+   /* clean up event worker threads */
for (i = 0; i < priv->num_crtcs; i++) {
-   if (priv->disp_thread[i].thread) {
-   kthread_destroy_worker(>disp_thread[i].worker);
-   priv->disp_thread[i].thread = NULL;
-   }
-
if (priv->event_thread[i].thread) {
kthread_destroy_worker(>event_thread[i].worker);
priv->event_thread[i].thread = NULL;
@@ -545,27 +540,6 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
 */
param.sched_priority = 16;
for (i = 0; i < priv->num_crtcs; i++) {
-
-   /* initialize display thread */
-   priv->disp_thread[i].crtc_id = priv->crtcs[i]->base.id;
-   kthread_init_worker(>disp_thread[i].worker);
-   priv->disp_thread[i].dev = ddev;
-   priv->disp_thread[i].thread =
-   kthread_run(kthread_worker_fn,
-   >disp_thread[i].worker,
-   "crtc_commit:%d", priv->disp_thread[i].crtc_id);
-   if (IS_ERR(priv->disp_thread[i].thread)) {
-   DRM_DEV_ERROR(dev, "failed to create crtc_commit 
kthread\n");
-   priv->disp_thread[i].thread = NULL;
-   goto err_msm_uninit;
-   }
-
-   ret = sched_setscheduler(priv->disp_thread[i].thread,
-SCHED_FIFO, );
-   if (ret)
-   dev_warn(dev, "disp_thread set priority failed: %d\n",
-ret);
-
/* initialize event thread */
priv->event_thread[i].crtc_id = priv->crtcs[i]->base.id;
kthread_init_worker(>event_thread[i].worker);
@@ -580,13 +554,6 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
goto err_msm_uninit;
}
 
-   /**
-* event thread should also run at same priority as disp_thread
-* because it is handling frame_done events. A lower priority
-* event thread and higher priority disp_thread can causes
-* frame_pending counters beyond 2. This can lead to commit
-* failure at crtc commit level.
-*/
ret = sched_setscheduler(priv->event_thread[i].thread,
 SCHED_FIFO, );
if (ret)
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 0298fa7..0307543 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -197,7 +197,6 @@ struct msm_drm_private {
unsigned int num_crtcs;
struct drm_crtc *crtcs[MAX_CRTCS];
 
-   struct msm_drm_thread disp_thread[MAX_CRTCS];
struct msm_drm_thread event_thread[MAX_CRTCS];
 
unsigned int num_encoders;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v4 2/5] drm/msm/dpu: use msm wq for vblank events

2018-12-06 Thread Jeykumar Sankaran
DPU was using one thread per display to dispatch async commits and
vblank requests. Since clean up already happened in msm to use the
common thread for all the display commits, display threads are only
used to cater vblank requests. Since a single thread is sufficient
to do the job without any performance hits, use msm workqueue
to queue requests. A separate patch is submitted later in this
series to remove the display threads altogether.

changes in v2:
- switch to system wq before removing disp threads (Sean Paul)
changes in v3:
- none
changes in v4:
- use msm wq for vblank events

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 9 -
 drivers/gpu/drm/msm/msm_drv.h | 2 +-
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 956f0599..37740b8 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -212,7 +212,7 @@ struct vblank_event {
bool enable;
 };
 
-static void vblank_ctrl_worker(struct kthread_work *work)
+static void vblank_ctrl_worker(struct work_struct *work)
 {
struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
struct msm_vblank_ctrl, work);
@@ -260,8 +260,7 @@ static int vblank_ctrl_queue_work(struct msm_drm_private 
*priv,
list_add_tail(_ev->node, _ctrl->event_list);
spin_unlock_irqrestore(_ctrl->lock, flags);
 
-   kthread_queue_work(>disp_thread[crtc_id].worker,
-   _ctrl->work);
+   queue_work(priv->wq, _ctrl->work);
 
return 0;
 }
@@ -281,7 +280,7 @@ static int msm_drm_uninit(struct device *dev)
 * work before drm_irq_uninstall() to avoid work re-enabling an
 * irq after uninstall has disabled it.
 */
-   kthread_flush_work(_ctrl->work);
+   flush_work(_ctrl->work);
list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node) {
list_del(_ev->node);
kfree(vbl_ev);
@@ -479,7 +478,7 @@ static int msm_drm_init(struct device *dev, struct 
drm_driver *drv)
 
INIT_LIST_HEAD(>inactive_list);
INIT_LIST_HEAD(>vblank_ctrl.event_list);
-   kthread_init_work(>vblank_ctrl.work, vblank_ctrl_worker);
+   INIT_WORK(>vblank_ctrl.work, vblank_ctrl_worker);
spin_lock_init(>vblank_ctrl.lock);
 
drm_mode_config_init(ddev);
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 71a03ce..0298fa7 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -78,7 +78,7 @@ enum msm_mdp_plane_property {
 };
 
 struct msm_vblank_ctrl {
-   struct kthread_work work;
+   struct work_struct work;
struct list_head event_list;
spinlock_t lock;
 };
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project

___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


Re: [Freedreno] [PATCH v2 5/5] drm/msm: subclass work object for vblank events

2018-12-06 Thread Jeykumar Sankaran

On 2018-12-06 10:56, Jeykumar Sankaran wrote:

On 2018-11-07 07:55, Sean Paul wrote:

On Tue, Nov 06, 2018 at 02:36:30PM -0800, Jeykumar Sankaran wrote:

msm maintains a separate structure to define vblank
work definitions and a list to track events submitted
to the workqueue. We can avoid this redundant list
and its protection mechanism, if we subclass the
work object to encapsulate vblank event parameters.

changes in v2:
- subclass optimization on system wq (Sean Paul)


I wouldn't do it like this, tbh. One problem is that you've lost your
flush() on
unbind, so there's no way to know if you have workers in the wild 
waiting

to
enable/disable vblank.


I believe I didnt respond to this quesition of yours. This patch is
removing the flush on the work. But flush_workqueue before destroying 
the WQ

will make sure all the queued work jobs are run to completion.

To honor the comment, I will fix the patch to move the flush/destroy
wq before the
irq_unininstall.


Above is possible if we use priv->wq for vblank requests. Posted v4 with
the above fixes.

Thanks,
Jeykumar S.


Another issues is that AFAICT, we don't need a queue of 
enables/disables,

but
rather just the last requested state (ie: should we be on or off). So
things
don't need to be this complicated (and we're possibly thrashing vblank
on/off
for no reason).

I'm still of the mind that you should just make this synchronous and 
be

done
with the threads (especially since we're still uncovering/introducing
races!).

Sean



Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 67

+--

 drivers/gpu/drm/msm/msm_drv.h |  7 -
 2 files changed, 20 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c

b/drivers/gpu/drm/msm/msm_drv.c

index 6d6c73b..8da5be2 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -203,61 +203,44 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }

-struct vblank_event {
-   struct list_head node;
+struct msm_vblank_work {
+   struct work_struct work;
int crtc_id;
bool enable;
+   struct msm_drm_private *priv;
 };

 static void vblank_ctrl_worker(struct work_struct *work)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
-   struct msm_vblank_ctrl,

work);

-   struct msm_drm_private *priv = container_of(vbl_ctrl,
-   struct msm_drm_private,

vblank_ctrl);

+   struct msm_vblank_work *vbl_work = container_of(work,
+   struct msm_vblank_work,

work);

+   struct msm_drm_private *priv = vbl_work->priv;
struct msm_kms *kms = priv->kms;
-   struct vblank_event *vbl_ev, *tmp;
-   unsigned long flags;
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node)

{

-   list_del(_ev->node);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
-
-   if (vbl_ev->enable)
-   kms->funcs->enable_vblank(kms,
-

priv->crtcs[vbl_ev->crtc_id]);

-   else
-   kms->funcs->disable_vblank(kms,
-

priv->crtcs[vbl_ev->crtc_id]);


-   kfree(vbl_ev);
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   }
+   if (vbl_work->enable)
+   kms->funcs->enable_vblank(kms,

priv->crtcs[vbl_work->crtc_id]);

+   else
+   kms->funcs->disable_vblank(kms,

priv->crtcs[vbl_work->crtc_id]);


-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   kfree(vbl_work);
 }

 static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev;
-   unsigned long flags;
+   struct msm_vblank_work *vbl_work;

-   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
-   if (!vbl_ev)
+   vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC);
+   if (!vbl_work)
return -ENOMEM;

-   vbl_ev->crtc_id = crtc_id;
-   vbl_ev->enable = enable;
+   INIT_WORK(_work->work, vblank_ctrl_worker);

-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_add_tail(_ev->node, _ctrl->event_list);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   vbl_work->crtc_id = crtc_id;
+   vbl_work->enable = enable;
+   vbl_work->priv = priv;

-   schedule_work(_ctrl->work);
+   schedule_work(_work->work);

return 0;
 }
@@ -269,14 +252,13 @@ static int msm_drm_uninit(struct device *dev)
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_mdss *mdss =

Re: [Freedreno] [PATCH v2 5/5] drm/msm: subclass work object for vblank events

2018-12-06 Thread Jeykumar Sankaran

On 2018-11-07 07:55, Sean Paul wrote:

On Tue, Nov 06, 2018 at 02:36:30PM -0800, Jeykumar Sankaran wrote:

msm maintains a separate structure to define vblank
work definitions and a list to track events submitted
to the workqueue. We can avoid this redundant list
and its protection mechanism, if we subclass the
work object to encapsulate vblank event parameters.

changes in v2:
- subclass optimization on system wq (Sean Paul)


I wouldn't do it like this, tbh. One problem is that you've lost your
flush() on
unbind, so there's no way to know if you have workers in the wild 
waiting

to
enable/disable vblank.


I believe I didnt respond to this quesition of yours. This patch is
removing the flush on the work. But flush_workqueue before destroying 
the WQ

will make sure all the queued work jobs are run to completion.

To honor the comment, I will fix the patch to move the flush/destroy wq 
before the

irq_unininstall.

Thanks,
Jeykumar S.

Another issues is that AFAICT, we don't need a queue of 
enables/disables,

but
rather just the last requested state (ie: should we be on or off). So
things
don't need to be this complicated (and we're possibly thrashing vblank
on/off
for no reason).

I'm still of the mind that you should just make this synchronous and be
done
with the threads (especially since we're still uncovering/introducing
races!).

Sean



Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/msm_drv.c | 67

+--

 drivers/gpu/drm/msm/msm_drv.h |  7 -
 2 files changed, 20 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/msm/msm_drv.c

b/drivers/gpu/drm/msm/msm_drv.c

index 6d6c73b..8da5be2 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -203,61 +203,44 @@ u32 msm_readl(const void __iomem *addr)
return val;
 }

-struct vblank_event {
-   struct list_head node;
+struct msm_vblank_work {
+   struct work_struct work;
int crtc_id;
bool enable;
+   struct msm_drm_private *priv;
 };

 static void vblank_ctrl_worker(struct work_struct *work)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = container_of(work,
-   struct msm_vblank_ctrl,

work);

-   struct msm_drm_private *priv = container_of(vbl_ctrl,
-   struct msm_drm_private,

vblank_ctrl);

+   struct msm_vblank_work *vbl_work = container_of(work,
+   struct msm_vblank_work,

work);

+   struct msm_drm_private *priv = vbl_work->priv;
struct msm_kms *kms = priv->kms;
-   struct vblank_event *vbl_ev, *tmp;
-   unsigned long flags;
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_for_each_entry_safe(vbl_ev, tmp, _ctrl->event_list, node)

{

-   list_del(_ev->node);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
-
-   if (vbl_ev->enable)
-   kms->funcs->enable_vblank(kms,
-

priv->crtcs[vbl_ev->crtc_id]);

-   else
-   kms->funcs->disable_vblank(kms,
-

priv->crtcs[vbl_ev->crtc_id]);


-   kfree(vbl_ev);
-
-   spin_lock_irqsave(_ctrl->lock, flags);
-   }
+   if (vbl_work->enable)
+   kms->funcs->enable_vblank(kms,

priv->crtcs[vbl_work->crtc_id]);

+   else
+   kms->funcs->disable_vblank(kms,

priv->crtcs[vbl_work->crtc_id]);


-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   kfree(vbl_work);
 }

 static int vblank_ctrl_queue_work(struct msm_drm_private *priv,
int crtc_id, bool enable)
 {
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev;
-   unsigned long flags;
+   struct msm_vblank_work *vbl_work;

-   vbl_ev = kzalloc(sizeof(*vbl_ev), GFP_ATOMIC);
-   if (!vbl_ev)
+   vbl_work = kzalloc(sizeof(*vbl_work), GFP_ATOMIC);
+   if (!vbl_work)
return -ENOMEM;

-   vbl_ev->crtc_id = crtc_id;
-   vbl_ev->enable = enable;
+   INIT_WORK(_work->work, vblank_ctrl_worker);

-   spin_lock_irqsave(_ctrl->lock, flags);
-   list_add_tail(_ev->node, _ctrl->event_list);
-   spin_unlock_irqrestore(_ctrl->lock, flags);
+   vbl_work->crtc_id = crtc_id;
+   vbl_work->enable = enable;
+   vbl_work->priv = priv;

-   schedule_work(_ctrl->work);
+   schedule_work(_work->work);

return 0;
 }
@@ -269,14 +252,13 @@ static int msm_drm_uninit(struct device *dev)
struct msm_drm_private *priv = ddev->dev_private;
struct msm_kms *kms = priv->kms;
struct msm_mdss *mdss = priv->mdss;
-   struct msm_vblank_ctrl *vbl_ctrl = >vblank_ctrl;
-   struct vblank_event *vbl_ev, *tmp;
int i;

/* 

[PATCH v6] arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file

2018-12-04 Thread Jeykumar Sankaran
DPU is short for the Display Processing Unit. It is the display
controller on Qualcomm SDM845 chips.

This change adds MDSS and DSI nodes to enable display on the
target device.

Changes in v2:
 - Beefed up commit message
 - Use SoC specific compatibles for mdss and dpu (Rob H)
 - Use assigned-clocks to set initial clock frequency(Rob H)
Changes in v3:
 - added IOMMU node
 - Fix device naming (remove _phys)
 - Use correct IRQ_TYPE in interrupt specifiers
Changes in v4:
 - move mdss node to preserve the unit address sort order
 - remove _clk suffix from dsi clocks
 (both the comments are from Doug Anderson)
Changes in v5:
- Keep the device status "disabled" by default (Bjorn Andersson)
- Use MDSS_GDSC macro (Jordan)
- Fix phy-names (Jordan)
- List reg ranges in numerical order (Jordan)
Changes in v6:
- Separating this patch out of the series
- fix phy-names

Signed-off-by: Jeykumar Sankaran 
Signed-off-by: Sean Paul 
---
 arch/arm64/boot/dts/qcom/sdm845.dtsi | 203 +++
 1 file changed, 203 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi 
b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 1419b00..fa7023e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1256,6 +1256,209 @@
};
};
 
+   mdss: mdss@ae0 {
+   compatible = "qcom,sdm845-mdss";
+   reg = <0xae0 0x1000>;
+   reg-names = "mdss";
+
+   power-domains = < MDSS_GDSC>;
+
+   clocks = < GCC_DISP_AHB_CLK>,
+< GCC_DISP_AXI_CLK>,
+< DISP_CC_MDSS_MDP_CLK>;
+   clock-names = "iface", "bus", "core";
+
+   assigned-clocks = < DISP_CC_MDSS_MDP_CLK>;
+   assigned-clock-rates = <3>;
+
+   interrupts = ;
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   iommus = <_smmu 0x880 0x8>,
+<_smmu 0xc80 0x8>;
+
+   status = "disabled";
+
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   mdss_mdp: mdp@ae01000 {
+   compatible = "qcom,sdm845-dpu";
+   reg = <0x0ae01000 0x8f000>,
+ <0x0aeb 0x2008>;
+   reg-names = "mdp", "vbif";
+
+   clocks = < DISP_CC_MDSS_AHB_CLK>,
+< DISP_CC_MDSS_AXI_CLK>,
+< DISP_CC_MDSS_MDP_CLK>,
+< DISP_CC_MDSS_VSYNC_CLK>;
+   clock-names = "iface", "bus", "core", "vsync";
+
+   assigned-clocks = < 
DISP_CC_MDSS_MDP_CLK>,
+ < 
DISP_CC_MDSS_VSYNC_CLK>;
+   assigned-clock-rates = <3>,
+  <1920>;
+
+   interrupt-parent = <>;
+   interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+   status = "disabled";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+   dpu_intf1_out: endpoint {
+   remote-endpoint = 
<_in>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+   dpu_intf2_out: endpoint {
+   remote-endpoint = 
<_in>;
+   };
+   };
+   };
+   };
+
+   dsi0: dsi@ae94000 {
+   compatible =

Re: [Freedreno] [PATCH v2] drm/msm/dpu: add display port support in DPU

2018-12-04 Thread Jeykumar Sankaran

On 2018-12-03 06:47, Sean Paul wrote:

On Tue, Nov 27, 2018 at 02:28:30PM -0800, Jeykumar Sankaran wrote:

Add display port support in DPU by creating hooks
for DP encoder enumeration and encoder mode
initialization.

This change is based on the SDM845 Display port
driver changes[1].

changes in v2:
- rebase on [2] (Sean Paul)
- remove unwanted error checks and
  switch cases (Jordan Crouse)

[1] https://lwn.net/Articles/768265/
[2] https://lkml.org/lkml/2018/11/17/87

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  8 ++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 47

+

 2 files changed, 45 insertions(+), 10 deletions(-)

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

b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index d3f4501..1f6b4b1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2015,7 +2015,7 @@ static int dpu_encoder_setup_display(struct

dpu_encoder_virt *dpu_enc,

 {
int ret = 0;
int i = 0;
-   enum dpu_intf_type intf_type;
+   enum dpu_intf_type intf_type = INTF_NONE;


dpu_intf_type seems unnecessary, you could just use the 
DRM_MODE_ENCODER_*

value
directly?

enum dpu_intf_type enumerates HW interface types the SOC has. Below 
switch

case maps the DRM_MODE_ENCODER_* to HW dpu_intf_type it should reserve.
Note that DRM_MODE_ENCODER_* and dpu_intf_type are not mapped 1-to-1.
e.g. DRM_MODE_ENCODER_TMDS can be mapped to HDMI or DisplayPort.

Thanks,
Jeykumar S.


struct dpu_enc_phys_init_params phys_params;

if (!dpu_enc || !dpu_kms) {
@@ -2038,9 +2038,9 @@ static int dpu_encoder_setup_display(struct

dpu_encoder_virt *dpu_enc,

case DRM_MODE_ENCODER_DSI:
intf_type = INTF_DSI;
break;
-   default:
-   DPU_ERROR_ENC(dpu_enc, "unsupported display interface

type\n");

-   return -EINVAL;
+   case DRM_MODE_ENCODER_TMDS:
+   intf_type = INTF_DP;
+   break;
}

WARN_ON(disp_info->num_of_h_tiles < 1);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 985c855..7d931ae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -473,6 +473,32 @@ static void _dpu_kms_initialize_dsi(struct

drm_device *dev,

}
 }

+static void _dpu_kms_initialize_displayport(struct drm_device *dev,
+   struct msm_drm_private *priv,
+   struct dpu_kms *dpu_kms)
+{
+   struct drm_encoder *encoder = NULL;
+   int rc;
+
+   if (!priv->dp)
+   return;
+
+   encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS);
+   if (IS_ERR(encoder)) {
+   DPU_ERROR("encoder init failed for dsi display\n");
+   return;
+   }
+
+   rc = msm_dp_modeset_init(priv->dp, dev, encoder);
+   if (rc) {
+   DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
+   drm_encoder_cleanup(encoder);
+   return;
+   }
+
+   priv->encoders[priv->num_encoders++] = encoder;


No need to keep track of drm resources at the driver level, the core 
will

do
this for you. So can you please add a patch preceding this one to 
remove

the
priv->encoders/crtc/planes/connectors arrays?


+}
+
 /**
  * _dpu_kms_setup_displays - create encoders, bridges and connectors
  *   for underlying displays
@@ -487,6 +513,8 @@ static void _dpu_kms_setup_displays(struct

drm_device *dev,

Why are these functions voids? Seems like there are plenty of places 
for

them to
fail :)

Let's add a patch to the beginning of this series to properly handle
failures in
setup_displays and initialize_dsi


 {
_dpu_kms_initialize_dsi(dev, priv, dpu_kms);

+   _dpu_kms_initialize_displayport(dev, priv, dpu_kms);
+
/**
 * Extend this function to initialize other
 * types of displays
@@ -723,13 +751,20 @@ static void _dpu_kms_set_encoder_mode(struct

msm_kms *kms,

info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;

-   /* TODO: No support for DSI swap */
-   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (priv->dsi[i]) {
-   info.h_tile_instance[info.num_of_h_tiles] = i;
-   info.num_of_h_tiles++;
+   switch (info.intf_type) {
+   case DRM_MODE_ENCODER_DSI:
+   /* TODO: No support for DSI swap */
+   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
+   if (priv->dsi[i]) {
+   info.h_tile_instance[info.num_o

Re: [Freedreno] [PATCH v2] drm/msm/dpu: add display port support in DPU

2018-12-03 Thread Jeykumar Sankaran

On 2018-12-03 06:47, Sean Paul wrote:

On Tue, Nov 27, 2018 at 02:28:30PM -0800, Jeykumar Sankaran wrote:

Add display port support in DPU by creating hooks
for DP encoder enumeration and encoder mode
initialization.

This change is based on the SDM845 Display port
driver changes[1].

changes in v2:
- rebase on [2] (Sean Paul)
- remove unwanted error checks and
  switch cases (Jordan Crouse)

[1] https://lwn.net/Articles/768265/
[2] https://lkml.org/lkml/2018/11/17/87

Signed-off-by: Jeykumar Sankaran 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  8 ++---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c | 47

+

 2 files changed, 45 insertions(+), 10 deletions(-)

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

b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c

index d3f4501..1f6b4b1 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -2015,7 +2015,7 @@ static int dpu_encoder_setup_display(struct

dpu_encoder_virt *dpu_enc,

 {
int ret = 0;
int i = 0;
-   enum dpu_intf_type intf_type;
+   enum dpu_intf_type intf_type = INTF_NONE;


dpu_intf_type seems unnecessary, you could just use the 
DRM_MODE_ENCODER_*

value
directly?


struct dpu_enc_phys_init_params phys_params;

if (!dpu_enc || !dpu_kms) {
@@ -2038,9 +2038,9 @@ static int dpu_encoder_setup_display(struct

dpu_encoder_virt *dpu_enc,

case DRM_MODE_ENCODER_DSI:
intf_type = INTF_DSI;
break;
-   default:
-   DPU_ERROR_ENC(dpu_enc, "unsupported display interface

type\n");

-   return -EINVAL;
+   case DRM_MODE_ENCODER_TMDS:
+   intf_type = INTF_DP;
+   break;
}

WARN_ON(disp_info->num_of_h_tiles < 1);
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 985c855..7d931ae 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -473,6 +473,32 @@ static void _dpu_kms_initialize_dsi(struct

drm_device *dev,

}
 }

+static void _dpu_kms_initialize_displayport(struct drm_device *dev,
+   struct msm_drm_private *priv,
+   struct dpu_kms *dpu_kms)
+{
+   struct drm_encoder *encoder = NULL;
+   int rc;
+
+   if (!priv->dp)
+   return;
+
+   encoder = dpu_encoder_init(dev, DRM_MODE_ENCODER_TMDS);
+   if (IS_ERR(encoder)) {
+   DPU_ERROR("encoder init failed for dsi display\n");
+   return;
+   }
+
+   rc = msm_dp_modeset_init(priv->dp, dev, encoder);
+   if (rc) {
+   DPU_ERROR("modeset_init failed for DP, rc = %d\n", rc);
+   drm_encoder_cleanup(encoder);
+   return;
+   }
+
+   priv->encoders[priv->num_encoders++] = encoder;


No need to keep track of drm resources at the driver level, the core 
will

do
this for you. So can you please add a patch preceding this one to 
remove

the
priv->encoders/crtc/planes/connectors arrays?

priv arrays for tracking drm components and priv->num_** counters are 
introduced

by mdp4/5. DPU just adapted the implementation.

De-coupling DPU from these arrays is much easier than fixing them in 
mdp4/5. I see

mdp5 is using it to track the max resources and also in ./msm_fbdev.c.

Thanks and Regards,
Jeykumar S.

+}
+
 /**
  * _dpu_kms_setup_displays - create encoders, bridges and connectors
  *   for underlying displays
@@ -487,6 +513,8 @@ static void _dpu_kms_setup_displays(struct

drm_device *dev,

Why are these functions voids? Seems like there are plenty of places 
for

them to
fail :)

Let's add a patch to the beginning of this series to properly handle
failures in
setup_displays and initialize_dsi


 {
_dpu_kms_initialize_dsi(dev, priv, dpu_kms);

+   _dpu_kms_initialize_displayport(dev, priv, dpu_kms);
+
/**
 * Extend this function to initialize other
 * types of displays
@@ -723,13 +751,20 @@ static void _dpu_kms_set_encoder_mode(struct

msm_kms *kms,

info.capabilities = cmd_mode ? MSM_DISPLAY_CAP_CMD_MODE :
MSM_DISPLAY_CAP_VID_MODE;

-   /* TODO: No support for DSI swap */
-   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
-   if (priv->dsi[i]) {
-   info.h_tile_instance[info.num_of_h_tiles] = i;
-   info.num_of_h_tiles++;
+   switch (info.intf_type) {
+   case DRM_MODE_ENCODER_DSI:
+   /* TODO: No support for DSI swap */
+   for (i = 0; i < ARRAY_SIZE(priv->dsi); i++) {
+   if (priv->dsi[i]) {
+   info.h_tile_instance[info.nu

Re: [PATCH v5 1/3] arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file

2018-12-03 Thread Jeykumar Sankaran

On 2018-12-03 16:57, Doug Anderson wrote:

Hi,

On Mon, Dec 3, 2018 at 2:27 PM Jeykumar Sankaran 


wrote:

+   dsi0: dsi@ae94000 {
+   compatible = "qcom,mdss-dsi-ctrl";
+   reg = <0xae94000 0x400>;
+   reg-names = "dsi_ctrl";
+
+   interrupt-parent = <>;
+   interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+
+   clocks = < 
DISP_CC_MDSS_BYTE0_CLK>,

+<
DISP_CC_MDSS_BYTE0_INTF_CLK>,
+< 
DISP_CC_MDSS_PCLK0_CLK>,
+< 
DISP_CC_MDSS_ESC0_CLK>,
+< 
DISP_CC_MDSS_AHB_CLK>,
+< 
DISP_CC_MDSS_AXI_CLK>;

+   clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+   phys = <_phy>;
+   phy-names = "dsi0";


I'm pretty sure that this should just be "dsi" and the one below in
dsi1 should also be called "dsi".  +Jordan should confirm.


Makes sense. I can fix that!



+   dsi1: dsi@ae96000 {
+   compatible = "qcom,mdss-dsi-ctrl";
+   reg = <0xae96000 0x400>;
+   reg-names = "dsi_ctrl";
+
+   interrupt-parent = <>;
+   interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
+
+   clocks = < 
DISP_CC_MDSS_BYTE1_CLK>,

+<
DISP_CC_MDSS_BYTE1_INTF_CLK>,
+< 
DISP_CC_MDSS_PCLK1_CLK>,
+< 
DISP_CC_MDSS_ESC1_CLK>,
+< 
DISP_CC_MDSS_AHB_CLK>,
+< 
DISP_CC_MDSS_AXI_CLK>;

+   clock-names = "byte",
+ "byte_intf",
+ "pixel",
+ "core",
+ "iface",
+ "bus";
+
+   phys = <_phy>;
+   phy-names = "dsi1";
+
+   status = "disabled";


This "disabled" is causing me problems.  I don't actually need "dsi1"
but if I don't enable "dsi1" then my display doesn't come up.  :(  I
ran out of time to debug but I wonder if this is this the standard
thing where DRM needs to wait for all the components to probe until it
can finish?  If nobody on this list just knows I'll dig tomorrow and
confirm that my memory isn't faulty and see what we've done about this
in the past.


https://patchwork.kernel.org/patch/10467895/

Can you try out with this change (reviewed but not merged yet). It 
validates

the nodes before adding to the DSI list.



One last note: it's pretty weird that you sent out only 1/3 and not
2/3 and 3/3.  If you're not ready to send out MTP stuff yet then you
should send out v6 as just a singleton patch.
Yes. I was trying to separate this one out as an independent change. 
Sandeep

is working on the comments on removing the pinctrl nodes and updated
mtp nodes. He should be posting 2/3 and 3/3 in the next couple of days.

Thanks,
Jeykumar S.




-Doug


--
Jeykumar S
___
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel


[PATCH v5 1/3] arm64: dts: qcom: sdm845: Add dpu to sdm845 dts file

2018-12-03 Thread Jeykumar Sankaran
DPU is short for the Display Processing Unit. It is the display
controller on Qualcomm SDM845 chips.

This change adds MDSS and DSI nodes to enable display on the
target device.

Changes in v2:
 - Beefed up commit message
 - Use SoC specific compatibles for mdss and dpu (Rob H)
 - Use assigned-clocks to set initial clock frequency(Rob H)
Changes in v3:
 - added IOMMU node
 - Fix device naming (remove _phys)
 - Use correct IRQ_TYPE in interrupt specifiers
Changes in v4:
 - move mdss node to preserve the unit address sort order
 - remove _clk suffix from dsi clocks
 (both the comments are from Doug Anderson)
Changes in v5:
- Keep the device status "disabled" by default (Bjorn Andersson)
- Use MDSS_GDSC macro (Jordan)
- Fix phy-names (Jordan)
- List reg ranges in numerical order (Jordan)

Signed-off-by: Jeykumar Sankaran 
Signed-off-by: Sean Paul 
---
 arch/arm64/boot/dts/qcom/sdm845.dtsi | 203 +++
 1 file changed, 203 insertions(+)

diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi 
b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 1419b00..a16f1fe 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -1256,6 +1256,209 @@
};
};
 
+   mdss: mdss@ae0 {
+   compatible = "qcom,sdm845-mdss";
+   reg = <0xae0 0x1000>;
+   reg-names = "mdss";
+
+   power-domains = < MDSS_GDSC>;
+
+   clocks = < GCC_DISP_AHB_CLK>,
+< GCC_DISP_AXI_CLK>,
+< DISP_CC_MDSS_MDP_CLK>;
+   clock-names = "iface", "bus", "core";
+
+   assigned-clocks = < DISP_CC_MDSS_MDP_CLK>;
+   assigned-clock-rates = <3>;
+
+   interrupts = ;
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   iommus = <_smmu 0x880 0x8>,
+<_smmu 0xc80 0x8>;
+
+   status = "disabled";
+
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges;
+
+   mdss_mdp: mdp@ae01000 {
+   compatible = "qcom,sdm845-dpu";
+   reg = <0x0ae01000 0x8f000>,
+ <0x0aeb 0x2008>;
+   reg-names = "mdp", "vbif";
+
+   clocks = < DISP_CC_MDSS_AHB_CLK>,
+< DISP_CC_MDSS_AXI_CLK>,
+< DISP_CC_MDSS_MDP_CLK>,
+< DISP_CC_MDSS_VSYNC_CLK>;
+   clock-names = "iface", "bus", "core", "vsync";
+
+   assigned-clocks = < 
DISP_CC_MDSS_MDP_CLK>,
+ < 
DISP_CC_MDSS_VSYNC_CLK>;
+   assigned-clock-rates = <3>,
+  <1920>;
+
+   interrupt-parent = <>;
+   interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+   status = "disabled";
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   port@0 {
+   reg = <0>;
+   dpu_intf1_out: endpoint {
+   remote-endpoint = 
<_in>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+   dpu_intf2_out: endpoint {
+   remote-endpoint = 
<_in>;
+   };
+   };
+   };
+   };
+
+   dsi0: dsi@ae94000 {
+   compatible = "qcom,mdss-dsi-ctrl";
+   reg = <0xae94000 0x400>;
+   reg-names = &

  1   2   3   4   >