[Freedreno] [PATCH v1 1/3] dt-bindings: phy: Add eDP PHY compatible for sc7280

2021-11-15 Thread Sankeerth Billakanti
Add compatible string for the supported eDP PHY on sc7280 platform.

Signed-off-by: Sankeerth Billakanti 
---
 Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml 
b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
index 9076e19..a5850ff 100644
--- a/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml
@@ -16,7 +16,9 @@ description:
 
 properties:
   compatible:
-const: qcom,sc8180x-edp-phy
+enum:
+  - qcom,sc7280-edp-phy
+  - qcom,sc8180x-edp-phy
 
   reg:
 items:
-- 
2.7.4



[Freedreno] [PATCH v1 3/3] phy: qcom: Program SSC only if supported by sink

2021-11-15 Thread Sankeerth Billakanti
Some legacy eDP sinks may not support SSC. The support for SSC is
indicated through an opts flag from the controller driver. This
change will enable SSC only if the sink supports it.

Signed-off-by: Sankeerth Billakanti 
---
 drivers/phy/qualcomm/phy-qcom-edp.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c 
b/drivers/phy/qualcomm/phy-qcom-edp.c
index 6d9404d..06ba609 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -335,9 +335,11 @@ static int qcom_edp_phy_power_on(struct phy *phy)
writel(0x00, edp->tx0 + TXn_LANE_MODE_1);
writel(0x00, edp->tx1 + TXn_LANE_MODE_1);
 
-   ret = qcom_edp_configure_ssc(edp);
-   if (ret)
-   return ret;
+   if (edp->dp_opts.ssc) {
+   ret = qcom_edp_configure_ssc(edp);
+   if (ret)
+   return ret;
+   }
 
ret = qcom_edp_configure_pll(edp);
if (ret)
-- 
2.7.4



[Freedreno] [PATCH v1 2/3] phy: qcom: Add support for eDP PHY on sc7280

2021-11-15 Thread Sankeerth Billakanti
The sc7280 platform supports native eDP controller and PHY.
This change will add support for the eDP PHY on sc7280.

Signed-off-by: Sankeerth Billakanti 
---
 drivers/phy/qualcomm/phy-qcom-edp.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/phy/qualcomm/phy-qcom-edp.c 
b/drivers/phy/qualcomm/phy-qcom-edp.c
index 17d5653..6d9404d 100644
--- a/drivers/phy/qualcomm/phy-qcom-edp.c
+++ b/drivers/phy/qualcomm/phy-qcom-edp.c
@@ -654,6 +654,7 @@ static int qcom_edp_phy_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id qcom_edp_phy_match_table[] = {
+   { .compatible = "qcom,sc7280-edp-phy" },
{ .compatible = "qcom,sc8180x-edp-phy" },
{ }
 };
-- 
2.7.4



[Freedreno] [PATCH v1 0/3] Add support for eDP PHY on SC7280 platform

2021-11-15 Thread Sankeerth Billakanti
This series adds support for the eDP PHY on Qualcomm SC7280 platform.
The changes are dependent on v4 of the new eDP PHY driver introduced by Bjorn:
https://patchwork.kernel.org/project/linux-arm-msm/list/?series=575135

Sankeerth Billakanti (3):
  dt-bindings: phy: Add eDP PHY compatible for sc7280
  phy: qcom: Add support for eDP PHY on sc7280
  phy: qcom: Program SSC only if supported by sink

 Documentation/devicetree/bindings/phy/qcom,edp-phy.yaml | 4 +++-
 drivers/phy/qualcomm/phy-qcom-edp.c | 9 ++---
 2 files changed, 9 insertions(+), 4 deletions(-)

-- 
2.7.4



[Freedreno] [PATCH v3 13/13] drm/msm/dsi: Pass DSC params to drm_panel

2021-11-15 Thread Vinod Koul
When DSC is enabled, we need to pass the DSC parameters to panel driver
as well, so add a dsc parameter in panel and set it when DSC is enabled

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 16 +++-
 include/drm/drm_panel.h|  7 +++
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 2c14c36f0b3d..3d5773fcf496 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2159,11 +2159,25 @@ int msm_dsi_host_modeset_init(struct mipi_dsi_host 
*host,
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
struct msm_drm_private *priv;
+   struct drm_panel *panel;
int ret;
 
msm_host->dev = dev;
+   panel = msm_dsi_host_get_panel(&msm_host->base);
priv = dev->dev_private;
-   priv->dsc = msm_host->dsc;
+
+   if (panel && panel->dsc) {
+   struct msm_display_dsc_config *dsc = priv->dsc;
+
+   if (!dsc) {
+   dsc = kzalloc(sizeof(*dsc), GFP_KERNEL);
+   if (!dsc)
+   return -ENOMEM;
+   dsc->drm = panel->dsc;
+   priv->dsc = dsc;
+   msm_host->dsc = dsc;
+   }
+   }
 
ret = cfg_hnd->ops->tx_buf_alloc(msm_host, SZ_4K);
if (ret) {
diff --git a/include/drm/drm_panel.h b/include/drm/drm_panel.h
index 4602f833eb51..eb8ae9bf32ed 100644
--- a/include/drm/drm_panel.h
+++ b/include/drm/drm_panel.h
@@ -171,6 +171,13 @@ struct drm_panel {
 * Panel entry in registry.
 */
struct list_head list;
+
+   /**
+* @dsc:
+*
+* Panel DSC pps payload to be sent
+*/
+   struct drm_dsc_config *dsc;
 };
 
 void drm_panel_init(struct drm_panel *panel, struct device *dev,
-- 
2.31.1



[Freedreno] [PATCH v3 12/13] drm/msm/dsi: Add support for DSC configuration

2021-11-15 Thread Vinod Koul
When DSC is enabled, we need to configure DSI registers accordingly and
configure the respective stream compression registers.

Add support to calculate the register setting based on DSC params and
timing information and configure these registers.

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.xml.h  |  10 +++
 drivers/gpu/drm/msm/dsi/dsi_host.c | 113 -
 2 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h 
b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 49b551ad1bff..c1c85df58c4b 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -706,4 +706,14 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 #define REG_DSI_CPHY_MODE_CTRL 0x02d4
 
 
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL0x029c
+
+#define REG_DSI_VIDEO_COMPRESSION_MODE_CTRL2   0x02a0
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL  0x02a4
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL2 0x02a8
+
+#define REG_DSI_COMMAND_COMPRESSION_MODE_CTRL3 0x02ac
+
 #endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 31d385d8d834..2c14c36f0b3d 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -908,6 +908,20 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, 
bool enable,
dsi_write(msm_host, REG_DSI_CPHY_MODE_CTRL, BIT(0));
 }
 
+static int dsi_dsc_update_pic_dim(struct msm_display_dsc_config *dsc,
+ int pic_width, int pic_height)
+{
+   if (!dsc || !pic_width || !pic_height) {
+   pr_err("DSI: invalid input: pic_width: %d pic_height: %d\n", 
pic_width, pic_height);
+   return -EINVAL;
+   }
+
+   dsc->drm->pic_width = pic_width;
+   dsc->drm->pic_height = pic_height;
+
+   return 0;
+}
+
 static void dsi_timing_setup(struct msm_dsi_host *msm_host, bool is_bonded_dsi)
 {
struct drm_display_mode *mode = msm_host->mode;
@@ -940,7 +954,68 @@ static void dsi_timing_setup(struct msm_dsi_host 
*msm_host, bool is_bonded_dsi)
hdisplay /= 2;
}
 
+   if (msm_host->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+
+   /* update dsc params with timing params */
+   dsi_dsc_update_pic_dim(dsc, mode->hdisplay, mode->vdisplay);
+   DBG("Mode Width- %d x Height %d\n", dsc->drm->pic_width, 
dsc->drm->pic_height);
+
+   /* we do the calculations for dsc parameters here so that
+* panel can use these parameters
+*/
+   dsi_populate_dsc_params(dsc);
+
+   /* Divide the display by 3 but keep back/font porch and
+* pulse width same
+*/
+   h_total -= hdisplay;
+   hdisplay /= 3;
+   h_total += hdisplay;
+   ha_end = ha_start + hdisplay;
+   }
+
if (msm_host->mode_flags & MIPI_DSI_MODE_VIDEO) {
+   if (msm_host->dsc) {
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   u32 reg, intf_width, slice_per_intf;
+   u32 total_bytes_per_intf;
+
+   /* first calculate dsc parameters and then program
+* compress mode registers
+*/
+   intf_width = hdisplay;
+   slice_per_intf = DIV_ROUND_UP(intf_width, 
dsc->drm->slice_width);
+
+   dsc->drm->slice_count = 1;
+   dsc->bytes_in_slice = 
DIV_ROUND_UP(dsc->drm->slice_width * 8, 8);
+   total_bytes_per_intf = dsc->bytes_in_slice * 
slice_per_intf;
+
+   dsc->eol_byte_num = total_bytes_per_intf % 3;
+   dsc->pclk_per_line =  
DIV_ROUND_UP(total_bytes_per_intf, 3);
+   dsc->bytes_per_pkt = dsc->bytes_in_slice * 
dsc->drm->slice_count;
+   dsc->pkt_per_line = slice_per_intf / 
dsc->drm->slice_count;
+
+   reg = dsc->bytes_per_pkt << 16;
+   reg |= (0x0b << 8);/* dtype of compressed image */
+
+   /* pkt_per_line:
+* 0 == 1 pkt
+* 1 == 2 pkt
+* 2 == 4 pkt
+* 3 pkt is not supported
+* above translates to ffs() - 1
+*/
+   reg |= (ffs(dsc->pkt_per_line) - 1) << 6;
+
+   dsc->eol_byte_num = total_bytes_per_intf % 3;
+   reg |= dsc->eol_byte_num << 4;
+   reg |= 1;
+
+   dsi_write(msm_host,
+   

[Freedreno] [PATCH v3 11/13] drm/msm/dsi: add mode valid callback for dsi_mgr

2021-11-15 Thread Vinod Koul
Add a mode valid callback for dsi_mgr for checking mode being valid in
case of DSC. For DSC the height and width needs to be multiple of slice,
so we check that here

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi.h |  2 ++
 drivers/gpu/drm/msm/dsi/dsi_host.c| 26 ++
 drivers/gpu/drm/msm/dsi/dsi_manager.c | 12 
 3 files changed, 40 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 569c8ff062ba..e7affab2fc1e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -115,6 +115,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host,
 int msm_dsi_host_power_off(struct mipi_dsi_host *host);
 int msm_dsi_host_set_display_mode(struct mipi_dsi_host *host,
  const struct drm_display_mode *mode);
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode 
*mode);
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host);
 unsigned long msm_dsi_host_get_mode_flags(struct mipi_dsi_host *host);
 struct drm_bridge *msm_dsi_host_get_bridge(struct mipi_dsi_host *host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 30c1e299aa52..31d385d8d834 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -2588,6 +2588,32 @@ int msm_dsi_host_set_display_mode(struct mipi_dsi_host 
*host,
return 0;
 }
 
+enum drm_mode_status msm_dsi_host_check_dsc(struct mipi_dsi_host *host,
+   const struct drm_display_mode *mode)
+{
+   struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+   struct msm_display_dsc_config *dsc = msm_host->dsc;
+   int pic_width = mode->hdisplay;
+   int pic_height = mode->vdisplay;
+
+   if (!msm_host->dsc)
+   return MODE_OK;
+
+   if (pic_width % dsc->drm->slice_width) {
+   pr_err("DSI: pic_width %d has to be multiple of slice %d\n",
+  pic_width, dsc->drm->slice_width);
+   return MODE_H_ILLEGAL;
+   }
+
+   if (pic_height % dsc->drm->slice_height) {
+   pr_err("DSI: pic_height %d has to be multiple of slice %d\n",
+  pic_height, dsc->drm->slice_height);
+   return MODE_V_ILLEGAL;
+   }
+
+   return MODE_OK;
+}
+
 struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host)
 {
return of_drm_find_panel(to_msm_dsi_host(host)->device_node);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c 
b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 20c4d650fd80..0ad8a53aaa0e 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -579,6 +579,17 @@ static void dsi_mgr_bridge_mode_set(struct drm_bridge 
*bridge,
msm_dsi_host_set_display_mode(other_dsi->host, adjusted_mode);
 }
 
+static enum drm_mode_status dsi_mgr_bridge_mode_valid(struct drm_bridge 
*bridge,
+ const struct 
drm_display_info *info,
+ const struct 
drm_display_mode *mode)
+{
+   int id = dsi_mgr_bridge_get_id(bridge);
+   struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+   struct mipi_dsi_host *host = msm_dsi->host;
+
+   return msm_dsi_host_check_dsc(host, mode);
+}
+
 static const struct drm_connector_funcs dsi_mgr_connector_funcs = {
.detect = dsi_mgr_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes,
@@ -600,6 +611,7 @@ static const struct drm_bridge_funcs dsi_mgr_bridge_funcs = 
{
.disable = dsi_mgr_bridge_disable,
.post_disable = dsi_mgr_bridge_post_disable,
.mode_set = dsi_mgr_bridge_mode_set,
+   .mode_valid = dsi_mgr_bridge_mode_valid,
 };
 
 /* initialize connector when we're connected to a drm_panel */
-- 
2.31.1



[Freedreno] [PATCH v3 10/13] drm/msm/disp/dpu1: Add DSC support in RM

2021-11-15 Thread Vinod Koul
This add the bits in RM to enable the DSC blocks

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h |  1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c  | 66 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h  |  1 +
 3 files changed, 68 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
index 775bcbda860f..fd6672efb096 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h
@@ -146,6 +146,7 @@ struct dpu_global_state {
uint32_t ctl_to_enc_id[CTL_MAX - CTL_0];
uint32_t intf_to_enc_id[INTF_MAX - INTF_0];
uint32_t dspp_to_enc_id[DSPP_MAX - DSPP_0];
+   uint32_t dsc_to_enc_id[DSC_MAX - DSC_0];
 };
 
 struct dpu_global_state
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
index f9c83d6e427a..c9d0fc765aaf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c
@@ -11,6 +11,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_dspp.h"
 #include "dpu_hw_merge3d.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_encoder.h"
 #include "dpu_trace.h"
 
@@ -75,6 +76,14 @@ int dpu_rm_destroy(struct dpu_rm *rm)
dpu_hw_intf_destroy(hw);
}
}
+   for (i = 0; i < ARRAY_SIZE(rm->dsc_blks); i++) {
+   struct dpu_hw_dsc *hw;
+
+   if (rm->dsc_blks[i]) {
+   hw = to_dpu_hw_dsc(rm->dsc_blks[i]);
+   dpu_hw_dsc_destroy(hw);
+   }
+   }
 
return 0;
 }
@@ -221,6 +230,19 @@ int dpu_rm_init(struct dpu_rm *rm,
rm->dspp_blks[dspp->id - DSPP_0] = &hw->base;
}
 
+   for (i = 0; i < cat->dsc_count; i++) {
+   struct dpu_hw_dsc *hw;
+   const struct dpu_dsc_cfg *dsc = &cat->dsc[i];
+
+   hw = dpu_hw_dsc_init(dsc->id, mmio, cat);
+   if (IS_ERR_OR_NULL(hw)) {
+   rc = PTR_ERR(hw);
+   DPU_ERROR("failed dsc object creation: err %d\n", rc);
+   goto fail;
+   }
+   rm->dsc_blks[dsc->id - DSC_0] = &hw->base;
+   }
+
return 0;
 
 fail:
@@ -476,6 +498,7 @@ static int _dpu_rm_reserve_intf(
}
 
global_state->intf_to_enc_id[idx] = enc_id;
+
return 0;
 }
 
@@ -500,6 +523,38 @@ static int _dpu_rm_reserve_intf_related_hw(
return ret;
 }
 
+static int _dpu_rm_reserve_dsc(struct dpu_rm *rm,
+  struct dpu_global_state *global_state,
+  struct drm_encoder *enc,
+  const struct msm_display_topology *top)
+{
+   struct msm_drm_private *priv;
+   int num_dsc = top->num_dsc;
+   int i;
+
+   priv = enc->dev->dev_private;
+
+   if (!priv)
+   return -EIO;
+
+   /* check if DSC is supported */
+   if (!priv->dsc)
+   return 0;
+
+   /* check if DSC required are allocated or not */
+   for (i = 0; i < num_dsc; i++) {
+   if (global_state->dsc_to_enc_id[i]) {
+   DPU_ERROR("DSC %d is already allocated\n", i);
+   return -EIO;
+   }
+   }
+
+   for (i = 0; i < num_dsc; i++)
+   global_state->dsc_to_enc_id[i] = enc->base.id;
+
+   return 0;
+}
+
 static int _dpu_rm_make_reservation(
struct dpu_rm *rm,
struct dpu_global_state *global_state,
@@ -526,6 +581,10 @@ static int _dpu_rm_make_reservation(
if (ret)
return ret;
 
+   ret  = _dpu_rm_reserve_dsc(rm, global_state, enc, &reqs->topology);
+   if (ret)
+   return ret;
+
return ret;
 }
 
@@ -567,6 +626,8 @@ void dpu_rm_release(struct dpu_global_state *global_state,
ARRAY_SIZE(global_state->ctl_to_enc_id), enc->base.id);
_dpu_rm_clear_mapping(global_state->intf_to_enc_id,
ARRAY_SIZE(global_state->intf_to_enc_id), enc->base.id);
+   _dpu_rm_clear_mapping(global_state->dsc_to_enc_id,
+   ARRAY_SIZE(global_state->dsc_to_enc_id), enc->base.id);
 }
 
 int dpu_rm_reserve(
@@ -640,6 +701,11 @@ int dpu_rm_get_assigned_resources(struct dpu_rm *rm,
hw_to_enc_id = global_state->dspp_to_enc_id;
max_blks = ARRAY_SIZE(rm->dspp_blks);
break;
+   case DPU_HW_BLK_DSC:
+   hw_blks = rm->dsc_blks;
+   hw_to_enc_id = global_state->dsc_to_enc_id;
+   max_blks = ARRAY_SIZE(rm->dsc_blks);
+   break;
default:
DPU_ERROR("blk type %d not managed by rm\n", type);
return 0;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
index 1f12c8d5b8aa..278d2a510b80 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h
+++ b/drivers/gpu/drm/ms

[Freedreno] [PATCH v3 09/13] drm/msm/disp/dpu1: Add support for DSC in topology

2021-11-15 Thread Vinod Koul
For DSC to work we typically need a 2,2,1 configuration. This should
suffice for resolutions up to 4k. For more resolutions like 8k this won't
work.

Also, it is better to use 2 LMs and DSC instances as half width results
in lesser power consumption as compared to single LM, DSC at full width.

The panel has been tested only with 2,2,1 configuration, so for
now we blindly create 2,2,1 topology when DSC is enabled

Co-developed-by: Abhinav Kumar 
Signed-off-by: Abhinav Kumar 
Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 18 ++
 drivers/gpu/drm/msm/msm_drv.h   |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index f2ff8a504918..12f58de88ac7 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -533,6 +533,8 @@ static struct msm_display_topology dpu_encoder_get_topology(
struct drm_display_mode *mode)
 {
struct msm_display_topology topology = {0};
+   struct drm_encoder *drm_enc;
+   struct msm_drm_private *priv;
int i, intf_count = 0;
 
for (i = 0; i < MAX_PHYS_ENCODERS_PER_VIRTUAL; i++)
@@ -567,8 +569,24 @@ static struct msm_display_topology 
dpu_encoder_get_topology(
topology.num_enc = 0;
topology.num_intf = intf_count;
 
+   drm_enc = &dpu_enc->base;
+   priv = drm_enc->dev->dev_private;
+   if (priv && priv->dsc) {
+   /* In case of Display Stream Compression DSC, we would use
+* 2 encoders, 2 line mixers and 1 interface
+* this is power optimal and can drive up to (including) 4k
+* screens
+*/
+   topology.num_enc = 2;
+   topology.num_dsc = 2;
+   topology.num_intf = 1;
+   topology.num_lm = 2;
+   priv->dsc->dsc_mask = BIT(0) | BIT(1);
+   }
+
return topology;
 }
+
 static int dpu_encoder_virt_atomic_check(
struct drm_encoder *drm_enc,
struct drm_crtc_state *crtc_state,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index c4a588ad226e..d6b25d77700e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -103,12 +103,14 @@ enum msm_event_wait {
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
  * @num_dspp: number of dspp blocks used
+ * @num_dsc:  number of Display Stream Compression (DSC) blocks used
  */
 struct msm_display_topology {
u32 num_lm;
u32 num_enc;
u32 num_intf;
u32 num_dspp;
+   u32 num_dsc;
 };
 
 /**
-- 
2.31.1



[Freedreno] [PATCH v3 08/13] drm/msm: Add missing structure documentation

2021-11-15 Thread Vinod Koul
Somehow documentation for dspp was missed, so add that

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/msm_drv.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index de7cb65bfc52..c4a588ad226e 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -102,6 +102,7 @@ enum msm_event_wait {
  * @num_lm:   number of layer mixers used
  * @num_enc:  number of compression encoder blocks used
  * @num_intf: number of interfaces the panel is mounted on
+ * @num_dspp: number of dspp blocks used
  */
 struct msm_display_topology {
u32 num_lm;
-- 
2.31.1



[Freedreno] [PATCH v3 07/13] drm/msm/disp/dpu1: Add support for DSC in encoder

2021-11-15 Thread Vinod Koul
We need to configure the encoder for DSC configuration and calculate DSC
parameters for the given timing so this patch adds that support by
adding dpu_encoder_prep_dsc() which is invoked when DSC is enabled.

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 140 +++-
 1 file changed, 139 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 e7ee4cfb8461..f2ff8a504918 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -21,6 +21,7 @@
 #include "dpu_hw_intf.h"
 #include "dpu_hw_ctl.h"
 #include "dpu_hw_dspp.h"
+#include "dpu_hw_dsc.h"
 #include "dpu_formats.h"
 #include "dpu_encoder_phys.h"
 #include "dpu_crtc.h"
@@ -136,6 +137,7 @@ enum dpu_enc_rc_states {
  * @cur_slave: As above but for the slave encoder.
  * @hw_pp: Handle to the pingpong blocks used for the display. No.
  * pingpong blocks can be different than num_phys_encs.
+ * @hw_dsc:Handle to the DSC blocks used for the display.
  * @intfs_swapped: Whether or not the phys_enc interfaces have been swapped
  * for partial update right-only cases, such as pingpong
  * split where virtual pingpong does not generate IRQs
@@ -182,6 +184,7 @@ struct dpu_encoder_virt {
struct dpu_encoder_phys *cur_master;
struct dpu_encoder_phys *cur_slave;
struct dpu_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
+   struct dpu_hw_dsc *hw_dsc[MAX_CHANNELS_PER_ENC];
 
bool intfs_swapped;
 
@@ -972,7 +975,8 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
struct dpu_hw_blk *hw_ctl[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_lm[MAX_CHANNELS_PER_ENC];
struct dpu_hw_blk *hw_dspp[MAX_CHANNELS_PER_ENC] = { NULL };
-   int num_lm, num_ctl, num_pp;
+   struct dpu_hw_blk *hw_dsc[MAX_CHANNELS_PER_ENC];
+   int num_lm, num_ctl, num_pp, num_dsc;
int i, j;
 
if (!drm_enc) {
@@ -1030,6 +1034,14 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
dpu_enc->hw_pp[i] = i < num_pp ? to_dpu_hw_pingpong(hw_pp[i])
: NULL;
 
+   if (priv->dsc) {
+   num_dsc = dpu_rm_get_assigned_resources(&dpu_kms->rm, 
global_state,
+   drm_enc->base.id, 
DPU_HW_BLK_DSC,
+   hw_dsc, 
ARRAY_SIZE(hw_dsc));
+   for (i = 0; i < MAX_CHANNELS_PER_ENC; i++)
+   dpu_enc->hw_dsc[i] = i < num_dsc ? 
to_dpu_hw_dsc(hw_dsc[i]) : NULL;
+   }
+
cstate = to_dpu_crtc_state(drm_crtc->state);
 
for (i = 0; i < num_lm; i++) {
@@ -1772,10 +1784,132 @@ static void 
dpu_encoder_vsync_event_work_handler(struct kthread_work *work)
nsecs_to_jiffies(ktime_to_ns(wakeup_time)));
 }
 
+static void
+dpu_encoder_dsc_pclk_param_calc(struct msm_display_dsc_config *dsc, u32 width)
+{
+   int slice_count, slice_per_intf;
+   int bytes_in_slice, total_bytes_per_intf;
+
+   if (!dsc || !dsc->drm->slice_width || !dsc->drm->slice_count) {
+   DPU_ERROR("Invalid DSC/slices\n");
+   return;
+   }
+
+   slice_count = dsc->drm->slice_count;
+   slice_per_intf = DIV_ROUND_UP(width, dsc->drm->slice_width);
+
+   /*
+* If slice_count is greater than slice_per_intf then default to 1.
+* This can happen during partial update.
+*/
+   if (slice_count > slice_per_intf)
+   slice_count = 1;
+
+   bytes_in_slice = DIV_ROUND_UP(dsc->drm->slice_width *
+ dsc->drm->bits_per_pixel, 8);
+   total_bytes_per_intf = bytes_in_slice * slice_per_intf;
+
+   dsc->eol_byte_num = total_bytes_per_intf % 3;
+   dsc->pclk_per_line =  DIV_ROUND_UP(total_bytes_per_intf, 3);
+   dsc->bytes_in_slice = bytes_in_slice;
+   dsc->bytes_per_pkt = bytes_in_slice * slice_count;
+   dsc->pkt_per_line = slice_per_intf / slice_count;
+}
+
+static void
+dpu_encoder_dsc_initial_line_calc(struct msm_display_dsc_config *dsc,
+ u32 enc_ip_width)
+{
+   int ssm_delay, total_pixels, soft_slice_per_enc;
+
+   soft_slice_per_enc = enc_ip_width / dsc->drm->slice_width;
+
+   /*
+* minimum number of initial line pixels is a sum of:
+* 1. sub-stream multiplexer delay (83 groups for 8bpc,
+*91 for 10 bpc) * 3
+* 2. for two soft slice cases, add extra sub-stream multiplexer * 3
+* 3. the initial xmit delay
+* 4. total pipeline delay through the "lock step" of encoder (47)
+* 5. 6 additional pixels as the output of the rate buffer is
+*48 bits wide
+*/
+   ssm_delay = ((dsc

[Freedreno] [PATCH v3 06/13] drm/msm/disp/dpu1: Add DSC support in hw_ctl

2021-11-15 Thread Vinod Koul
Later gens of hardware have DSC bits moved to hw_ctl, so configure these
bits so that DSC would work there as well

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 36831457a91b..66b0c44118d8 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -25,6 +25,8 @@
 #define   CTL_MERGE_3D_ACTIVE   0x0E4
 #define   CTL_INTF_ACTIVE   0x0F4
 #define   CTL_MERGE_3D_FLUSH0x100
+#define   CTL_DSC_ACTIVE0x0E8
+#define   CTL_DSC_FLUSH0x104
 #define   CTL_INTF_FLUSH0x110
 #define   CTL_INTF_MASTER   0x134
 #define   CTL_FETCH_PIPE_ACTIVE 0x0FC
@@ -34,6 +36,7 @@
 
 #define DPU_REG_RESET_TIMEOUT_US2000
 #define  MERGE_3D_IDX   23
+#define  DSC_IDX22
 #define  INTF_IDX   31
 #define CTL_INVALID_BIT 0x
 
@@ -120,7 +123,6 @@ static u32 dpu_hw_ctl_get_pending_flush(struct dpu_hw_ctl 
*ctx)
 
 static inline void dpu_hw_ctl_trigger_flush_v1(struct dpu_hw_ctl *ctx)
 {
-
if (ctx->pending_flush_mask & BIT(MERGE_3D_IDX))
DPU_REG_WRITE(&ctx->hw, CTL_MERGE_3D_FLUSH,
ctx->pending_merge_3d_flush_mask);
@@ -498,6 +500,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
u32 intf_active = 0;
u32 mode_sel = 0;
 
+   if (cfg->dsc)
+   DPU_REG_WRITE(&ctx->hw, CTL_DSC_FLUSH, cfg->dsc);
+
if (cfg->intf_mode_sel == DPU_CTL_MODE_SEL_CMD)
mode_sel |= BIT(17);
 
@@ -509,6 +514,10 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx,
if (cfg->merge_3d)
DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE,
  BIT(cfg->merge_3d - MERGE_3D_0));
+   if (cfg->dsc) {
+   DPU_REG_WRITE(&ctx->hw, CTL_FLUSH, cfg->dsc);
+   DPU_REG_WRITE(c, CTL_DSC_ACTIVE, cfg->dsc);
+   }
 }
 
 static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
-- 
2.31.1



[Freedreno] [PATCH v3 05/13] drm/msm/disp/dpu1: Don't use DSC with mode_3d

2021-11-15 Thread Vinod Koul
We cannot enable mode_3d when we are using the DSC. So pass
configuration to detect DSC is enabled and not enable mode_3d
when we are using DSC

We add a helper dpu_encoder_helper_get_dsc() to detect dsc
enabled and pass this to .setup_intf_cfg()

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h | 11 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c |  2 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c   |  3 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h   |  2 ++
 4 files changed, 17 insertions(+), 1 deletion(-)

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 e7270eb6b84b..efb85d595598 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
@@ -332,6 +332,17 @@ static inline enum dpu_3d_blend_mode 
dpu_encoder_helper_get_3d_blend_mode(
return BLEND_3D_NONE;
 }
 
+static inline bool dpu_encoder_helper_get_dsc(struct dpu_encoder_phys 
*phys_enc)
+{
+   struct drm_encoder *drm_enc = phys_enc->parent;
+   struct msm_drm_private *priv = drm_enc->dev->dev_private;
+
+   if (priv->dsc)
+   return priv->dsc->dsc_mask;
+
+   return 0;
+}
+
 /**
  * dpu_encoder_helper_split_config - split display configuration helper 
function
  * This helper function may be used by physical encoders to configure
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 34a6940d12c5..f3f00f4d0193 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
@@ -70,6 +70,8 @@ static void _dpu_encoder_phys_cmd_update_intf_cfg(
intf_cfg.intf_mode_sel = DPU_CTL_MODE_SEL_CMD;
intf_cfg.stream_sel = cmd_enc->stream_sel;
intf_cfg.mode_3d = dpu_encoder_helper_get_3d_blend_mode(phys_enc);
+   intf_cfg.dsc = dpu_encoder_helper_get_dsc(phys_enc);
+
ctl->ops.setup_intf_cfg(ctl, &intf_cfg);
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
index 64740ddb983e..36831457a91b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
@@ -519,7 +519,8 @@ static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx,
 
intf_cfg |= (cfg->intf & 0xF) << 4;
 
-   if (cfg->mode_3d) {
+   /* In DSC we can't set merge, so check for dsc too */
+   if (cfg->mode_3d && !cfg->dsc) {
intf_cfg |= BIT(19);
intf_cfg |= (cfg->mode_3d - 0x1) << 20;
}
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
index 806c171e5df2..9847c9c46d6f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h
@@ -40,6 +40,7 @@ struct dpu_hw_stage_cfg {
  * @merge_3d:  3d merge block used
  * @intf_mode_sel: Interface mode, cmd / vid
  * @stream_sel:Stream selection for multi-stream interfaces
+ * @dsc:   DSC BIT masks
  */
 struct dpu_hw_intf_cfg {
enum dpu_intf intf;
@@ -47,6 +48,7 @@ struct dpu_hw_intf_cfg {
enum dpu_merge_3d merge_3d;
enum dpu_ctl_mode_sel intf_mode_sel;
int stream_sel;
+   unsigned int dsc;
 };
 
 /**
-- 
2.31.1



[Freedreno] [PATCH v3 04/13] drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog

2021-11-15 Thread Vinod Koul
This adds SDM845 DSC blocks into hw_catalog

Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c| 20 +++
 1 file changed, 20 insertions(+)

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 ce6f32a919e5..c773bbe57b6b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -821,6 +821,24 @@ static const struct dpu_pingpong_cfg sc7280_pp[] = {
PP_BLK("pingpong_2", PINGPONG_2, 0x6b000, 0, sc7280_pp_sblk, -1, -1),
PP_BLK("pingpong_3", PINGPONG_3, 0x6c000, 0, sc7280_pp_sblk, -1, -1),
 };
+
+/*
+ * DSC sub blocks config
+ */
+#define DSC_BLK(_name, _id, _base) \
+   {\
+   .name = _name, .id = _id, \
+   .base = _base, .len = 0x140, \
+   .features = 0, \
+   }
+
+static struct dpu_dsc_cfg sdm845_dsc[] = {
+   DSC_BLK("dsc_0", DSC_0, 0x8),
+   DSC_BLK("dsc_1", DSC_1, 0x80400),
+   DSC_BLK("dsc_2", DSC_2, 0x80800),
+   DSC_BLK("dsc_3", DSC_3, 0x80c00),
+};
+
 /*
  * INTF sub blocks config
  */
@@ -1124,6 +1142,8 @@ static void sdm845_cfg_init(struct dpu_mdss_cfg *dpu_cfg)
.mixer = sdm845_lm,
.pingpong_count = ARRAY_SIZE(sdm845_pp),
.pingpong = sdm845_pp,
+   .dsc_count = ARRAY_SIZE(sdm845_dsc),
+   .dsc = sdm845_dsc,
.intf_count = ARRAY_SIZE(sdm845_intf),
.intf = sdm845_intf,
.vbif_count = ARRAY_SIZE(sdm845_vbif),
-- 
2.31.1



[Freedreno] [PATCH v3 03/13] drm/msm/disp/dpu1: Add support for DSC in pingpong block

2021-11-15 Thread Vinod Koul
In SDM845, DSC can be enabled by writing to pingpong block registers, so
add support for DSC in hw_pp

Reviewed-by: Abhinav Kumar 
Reviewed-by: Dmitry Baryshkov 
Signed-off-by: Vinod Koul 
---
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   | 32 +++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   | 14 
 2 files changed, 46 insertions(+)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
index 55766c97c4c8..47c6ab6caf95 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c
@@ -28,6 +28,9 @@
 #define PP_FBC_MODE 0x034
 #define PP_FBC_BUDGET_CTL   0x038
 #define PP_FBC_LOSSY_MODE   0x03C
+#define PP_DSC_MODE 0x0a0
+#define PP_DCE_DATA_IN_SWAP 0x0ac
+#define PP_DCE_DATA_OUT_SWAP0x0c8
 
 #define PP_DITHER_EN   0x000
 #define PP_DITHER_BITDEPTH 0x004
@@ -245,6 +248,32 @@ static u32 dpu_hw_pp_get_line_count(struct dpu_hw_pingpong 
*pp)
return line;
 }
 
+static int dpu_hw_pp_dsc_enable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 1);
+   return 0;
+}
+
+static void dpu_hw_pp_dsc_disable(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *c = &pp->hw;
+
+   DPU_REG_WRITE(c, PP_DSC_MODE, 0);
+}
+
+static int dpu_hw_pp_setup_dsc(struct dpu_hw_pingpong *pp)
+{
+   struct dpu_hw_blk_reg_map *pp_c = &pp->hw;
+   int data;
+
+   data = DPU_REG_READ(pp_c, PP_DCE_DATA_OUT_SWAP);
+   data |= BIT(18); /* endian flip */
+   DPU_REG_WRITE(pp_c, PP_DCE_DATA_OUT_SWAP, data);
+   return 0;
+}
+
 static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
unsigned long features)
 {
@@ -256,6 +285,9 @@ static void _setup_pingpong_ops(struct dpu_hw_pingpong *c,
c->ops.get_autorefresh = dpu_hw_pp_get_autorefresh_config;
c->ops.poll_timeout_wr_ptr = dpu_hw_pp_poll_timeout_wr_ptr;
c->ops.get_line_count = dpu_hw_pp_get_line_count;
+   c->ops.setup_dsc = dpu_hw_pp_setup_dsc;
+   c->ops.enable_dsc = dpu_hw_pp_dsc_enable;
+   c->ops.disable_dsc = dpu_hw_pp_dsc_disable;
 
if (test_bit(DPU_PINGPONG_DITHER, &features))
c->ops.setup_dither = dpu_hw_pp_setup_dither;
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
index 89d08a715c16..12758468d9ca 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h
@@ -124,6 +124,20 @@ struct dpu_hw_pingpong_ops {
 */
void (*setup_dither)(struct dpu_hw_pingpong *pp,
struct dpu_hw_dither_cfg *cfg);
+   /**
+* Enable DSC
+*/
+   int (*enable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Disable DSC
+*/
+   void (*disable_dsc)(struct dpu_hw_pingpong *pp);
+
+   /**
+* Setup DSC
+*/
+   int (*setup_dsc)(struct dpu_hw_pingpong *pp);
 };
 
 struct dpu_hw_merge_3d;
-- 
2.31.1



[Freedreno] [PATCH v3 02/13] drm/msm/disp/dpu1: Add support for DSC

2021-11-15 Thread Vinod Koul
Display Stream Compression (DSC) is one of the hw blocks in dpu, so add
support by adding hw blocks for DSC

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/Makefile  |   1 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +++
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 ++
 5 files changed, 314 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 40577f8856d8..7d7058f1f5c1 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -59,6 +59,7 @@ msm-y := \
disp/dpu1/dpu_formats.o \
disp/dpu1/dpu_hw_catalog.o \
disp/dpu1/dpu_hw_ctl.o \
+   disp/dpu1/dpu_hw_dsc.o \
disp/dpu1/dpu_hw_interrupts.o \
disp/dpu1/dpu_hw_intf.o \
disp/dpu1/dpu_hw_lm.o \
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 4ade44bbd37e..65f43fadcda0 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h
@@ -553,6 +553,16 @@ struct dpu_merge_3d_cfg  {
const struct dpu_merge_3d_sub_blks *sblk;
 };
 
+/**
+ * struct dpu_dsc_cfg - information of DSC blocks
+ * @id enum identifying this block
+ * @base   register offset of this block
+ * @features   bit mask identifying sub-blocks/features
+ */
+struct dpu_dsc_cfg {
+   DPU_HW_BLK_INFO;
+};
+
 /**
  * struct dpu_intf_cfg - information of timing engine blocks
  * @id enum identifying this block
@@ -749,6 +759,9 @@ struct dpu_mdss_cfg {
u32 merge_3d_count;
const struct dpu_merge_3d_cfg *merge_3d;
 
+   u32 dsc_count;
+   struct dpu_dsc_cfg *dsc;
+
u32 intf_count;
const struct dpu_intf_cfg *intf;
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
new file mode 100644
index ..449d6f1dad28
--- /dev/null
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
@@ -0,0 +1,210 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2020-2021, Linaro Limited
+ */
+
+#include "dpu_kms.h"
+#include "dpu_hw_catalog.h"
+#include "dpu_hwio.h"
+#include "dpu_hw_mdss.h"
+#include "dpu_hw_dsc.h"
+
+#define DSC_COMMON_MODE0x000
+#define DSC_ENC 0X004
+#define DSC_PICTURE 0x008
+#define DSC_SLICE   0x00C
+#define DSC_CHUNK_SIZE  0x010
+#define DSC_DELAY   0x014
+#define DSC_SCALE_INITIAL   0x018
+#define DSC_SCALE_DEC_INTERVAL  0x01C
+#define DSC_SCALE_INC_INTERVAL  0x020
+#define DSC_FIRST_LINE_BPG_OFFSET   0x024
+#define DSC_BPG_OFFSET  0x028
+#define DSC_DSC_OFFSET  0x02C
+#define DSC_FLATNESS0x030
+#define DSC_RC_MODEL_SIZE   0x034
+#define DSC_RC  0x038
+#define DSC_RC_BUF_THRESH   0x03C
+#define DSC_RANGE_MIN_QP0x074
+#define DSC_RANGE_MAX_QP0x0B0
+#define DSC_RANGE_BPG_OFFSET0x0EC
+
+static void dpu_hw_dsc_disable(struct dpu_hw_dsc *dsc)
+{
+   struct dpu_hw_blk_reg_map *c = &dsc->hw;
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, 0);
+}
+
+static void dpu_hw_dsc_config(struct dpu_hw_dsc *hw_dsc,
+ struct msm_display_dsc_config *dsc, u32 mode)
+{
+   struct dpu_hw_blk_reg_map *c = &hw_dsc->hw;
+   u32 data, lsb, bpp;
+   u32 initial_lines = dsc->initial_lines;
+   bool is_cmd_mode = !(mode & DSC_MODE_VIDEO);
+
+   DPU_REG_WRITE(c, DSC_COMMON_MODE, mode);
+
+   if (is_cmd_mode)
+   initial_lines += 1;
+
+   data = (initial_lines << 20);
+   data |= ((dsc->slice_last_group_size - 1) << 18);
+   /* bpp is 6.4 format, 4 LSBs bits are for fractional part */
+   data |= dsc->drm->bits_per_pixel << 12;
+   lsb = dsc->drm->bits_per_pixel % 4;
+   bpp = dsc->drm->bits_per_pixel / 4;
+   bpp *= 4;
+   bpp <<= 4;
+   bpp |= lsb;
+
+   data |= bpp << 8;
+   data |= (dsc->drm->block_pred_enable << 7);
+   data |= (dsc->drm->line_buf_depth << 3);
+   data |= (dsc->drm->simple_422 << 2);
+   data |= (dsc->drm->convert_rgb << 1);
+   data |= dsc->drm->bits_per_component;
+
+   DPU_REG_WRITE(c, DSC_ENC, data);
+
+   data = dsc->drm->pic_width << 16;
+   data |= dsc->drm->pic_height;
+   DPU_REG_WRITE(c, DSC_PICTURE, data);
+
+   data = dsc->drm->slice_width << 16;
+   data |= dsc->drm->slice_height;
+   DPU_REG_WRITE(c, DSC_SLICE, data);
+
+   data = dsc->drm->slice_chunk_size << 16;

[Freedreno] [PATCH v3 01/13] drm/msm/dsi: add support for dsc data

2021-11-15 Thread Vinod Koul
Display Stream Compression (DSC) parameters need to be calculated. Add
helpers and struct msm_display_dsc_config in msm_drv for this
msm_display_dsc_config uses drm_dsc_config for DSC parameters.

Signed-off-by: Vinod Koul 
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 132 +
 drivers/gpu/drm/msm/msm_drv.h  |  20 +
 2 files changed, 152 insertions(+)

diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c 
b/drivers/gpu/drm/msm/dsi/dsi_host.c
index f69a125f9559..30c1e299aa52 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -31,6 +31,8 @@
 
 #define DSI_RESET_TOGGLE_DELAY_MS 20
 
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc);
+
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
u32 ver;
@@ -157,6 +159,7 @@ struct msm_dsi_host {
struct regmap *sfpb;
 
struct drm_display_mode *mode;
+   struct msm_display_dsc_config *dsc;
 
/* connected device info */
struct device_node *device_node;
@@ -1710,6 +1713,135 @@ static int dsi_host_parse_lane_data(struct msm_dsi_host 
*msm_host,
return -EINVAL;
 }
 
+static u32 dsi_dsc_rc_buf_thresh[DSC_NUM_BUF_RANGES - 1] = {
+   0x0e, 0x1c, 0x2a, 0x38, 0x46, 0x54, 0x62,
+   0x69, 0x70, 0x77, 0x79, 0x7b, 0x7d, 0x7e
+};
+
+/* only 8bpc, 8bpp added */
+static char min_qp[DSC_NUM_BUF_RANGES] = {
+   0, 0, 1, 1, 3, 3, 3, 3, 3, 3, 5, 5, 5, 7, 13
+};
+
+static char max_qp[DSC_NUM_BUF_RANGES] = {
+   4, 4, 5, 6, 7, 7, 7, 8, 9, 10, 11, 12, 13, 13, 15
+};
+
+static char bpg_offset[DSC_NUM_BUF_RANGES] = {
+   2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12
+};
+
+static int dsi_populate_dsc_params(struct msm_display_dsc_config *dsc)
+{
+   int mux_words_size;
+   int groups_per_line, groups_total;
+   int min_rate_buffer_size;
+   int hrd_delay;
+   int pre_num_extra_mux_bits, num_extra_mux_bits;
+   int slice_bits;
+   int target_bpp_x16;
+   int data;
+   int final_value, final_scale;
+   int i;
+
+   dsc->drm->rc_model_size = 8192;
+   dsc->drm->first_line_bpg_offset = 12;
+   dsc->drm->rc_edge_factor = 6;
+   dsc->drm->rc_tgt_offset_high = 3;
+   dsc->drm->rc_tgt_offset_low = 3;
+   dsc->drm->simple_422 = 0;
+   dsc->drm->convert_rgb = 1;
+   dsc->drm->vbr_enable = 0;
+
+   /* handle only bpp = bpc = 8 */
+   for (i = 0; i < DSC_NUM_BUF_RANGES - 1 ; i++)
+   dsc->drm->rc_buf_thresh[i] = dsi_dsc_rc_buf_thresh[i];
+
+   for (i = 0; i < DSC_NUM_BUF_RANGES; i++) {
+   dsc->drm->rc_range_params[i].range_min_qp = min_qp[i];
+   dsc->drm->rc_range_params[i].range_max_qp = max_qp[i];
+   dsc->drm->rc_range_params[i].range_bpg_offset = bpg_offset[i];
+   }
+
+   dsc->drm->initial_offset = 6144; /* Not bpp 12 */
+   if (dsc->drm->bits_per_pixel != 8)
+   dsc->drm->initial_offset = 2048;/* bpp = 12 */
+
+   mux_words_size = 48;/* bpc == 8/10 */
+   if (dsc->drm->bits_per_component == 12)
+   mux_words_size = 64;
+
+   dsc->drm->initial_xmit_delay = 512;
+   dsc->drm->initial_scale_value = 32;
+   dsc->drm->first_line_bpg_offset = 12;
+   dsc->drm->line_buf_depth = dsc->drm->bits_per_component + 1;
+
+   /* bpc 8 */
+   dsc->drm->flatness_min_qp = 3;
+   dsc->drm->flatness_max_qp = 12;
+   dsc->det_thresh_flatness = 7 + 2 * (dsc->drm->bits_per_component - 8);
+   dsc->drm->rc_quant_incr_limit0 = 11;
+   dsc->drm->rc_quant_incr_limit1 = 11;
+   dsc->drm->mux_word_size = DSC_MUX_WORD_SIZE_8_10_BPC;
+
+   /* FIXME: need to call drm_dsc_compute_rc_parameters() so that rest of
+* params are calculated
+*/
+   dsc->slice_last_group_size = 3 - (dsc->drm->slice_width % 3);
+   groups_per_line = DIV_ROUND_UP(dsc->drm->slice_width, 3);
+   dsc->drm->slice_chunk_size = dsc->drm->slice_width * 
dsc->drm->bits_per_pixel / 8;
+   if ((dsc->drm->slice_width * dsc->drm->bits_per_pixel) % 8)
+   dsc->drm->slice_chunk_size++;
+
+   /* rbs-min */
+   min_rate_buffer_size =  dsc->drm->rc_model_size - 
dsc->drm->initial_offset +
+   dsc->drm->initial_xmit_delay * 
dsc->drm->bits_per_pixel +
+   groups_per_line * 
dsc->drm->first_line_bpg_offset;
+
+   hrd_delay = DIV_ROUND_UP(min_rate_buffer_size, 
dsc->drm->bits_per_pixel);
+
+   dsc->drm->initial_dec_delay = hrd_delay - dsc->drm->initial_xmit_delay;
+
+   dsc->drm->initial_scale_value = 8 * dsc->drm->rc_model_size /
+  (dsc->drm->rc_model_size - 
dsc->drm->initial_offset);
+
+   slice_bits = 8 * dsc->drm->slice_chunk_size * dsc->drm->slice_height;
+
+   groups_total = groups_per_line * dsc->drm->slice_height;
+
+   data = dsc->drm->first_line_bpg_offset * 2

[Freedreno] [PATCH v3 00/13] drm/msm: Add Display Stream Compression Support

2021-11-15 Thread Vinod Koul
Display Stream Compression (DSC) compresses the display stream in host which
is later decoded by panel. This series enables this for Qualcomm msm driver.
This was tested on Google Pixel3 phone which use LGE SW43408 panel.
 
The changes include DSC data and hardware block enabling for DPU1 then
support in encoder. We also add support in DSI and introduce required
topology changes.
 
In order for panel to set the DSC parameters we add dsc in drm_panel and set
it from the msm driver.

We still have dsc as a globabl entity. I think while doing DP + DSC we
should be able to update it, right now comprehending the requirements are
bit difficult.
 
Complete changes which enable this for Pixel3 along with panel driver (not
part of this series) and DT changes can be found at:
git.linaro.org/people/vinod.koul/kernel.git pixel/dsc_v3
 
Comments welcome!

Changes since v2:
 - Fix comments by Dimitry except the dsc being global.
 - Move RM patch later for dependency on topology now
 - Add patch for mode valid callback for dsi_mgr
 - Add missing structure documentation patch
 - Fix errors in mode_3d changes
 - Rebase on v5.16-rc1 and test

Changes since v1:
 - Fix various issues spotted by kbuildbot
 - Rebase to v5.15-rc3
 - Remove unused fields and duplicate defines
 - Enable DSC blocks only when DSC is enabled
 - remove sdm845 feature mask, use 0
 - Check for DSC in hw_ctl

Changes since RFC:
 - Drop the DT binding patch as we derive the configuration from panel
 - Drop the drm api patch as we no longer need it (use pps drm api)
 - Fix comments raised by Dimitry
 - Add dsc parameters calculation from downstream

Vinod Koul (13):
  drm/msm/dsi: add support for dsc data
  drm/msm/disp/dpu1: Add support for DSC
  drm/msm/disp/dpu1: Add support for DSC in pingpong block
  drm/msm/disp/dpu1: Add DSC for SDM845 to hw_catalog
  drm/msm/disp/dpu1: Don't use DSC with mode_3d
  drm/msm/disp/dpu1: Add DSC support in hw_ctl
  drm/msm/disp/dpu1: Add support for DSC in encoder
  drm/msm: Add missing structure documentation
  drm/msm/disp/dpu1: Add support for DSC in topology
  drm/msm/disp/dpu1: Add DSC support in RM
  drm/msm/dsi: add mode valid callback for dsi_mgr
  drm/msm/dsi: Add support for DSC configuration
  drm/msm/dsi: Pass DSC params to drm_panel

 drivers/gpu/drm/msm/Makefile  |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c   | 158 +-
 .../gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h  |  11 +
 .../drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c  |   2 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c|  20 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_catalog.h|  13 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c|  14 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.h|   2 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c| 210 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h|  77 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_mdss.h   |  13 +
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.c   |  32 ++
 .../gpu/drm/msm/disp/dpu1/dpu_hw_pingpong.h   |  14 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h   |   1 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.c|  66 
 drivers/gpu/drm/msm/disp/dpu1/dpu_rm.h|   1 +
 drivers/gpu/drm/msm/dsi/dsi.h |   2 +
 drivers/gpu/drm/msm/dsi/dsi.xml.h |  10 +
 drivers/gpu/drm/msm/dsi/dsi_host.c| 285 +-
 drivers/gpu/drm/msm/dsi/dsi_manager.c |  12 +
 drivers/gpu/drm/msm/msm_drv.h |  23 ++
 include/drm/drm_panel.h   |   7 +
 22 files changed, 970 insertions(+), 4 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.c
 create mode 100644 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_dsc.h

-- 
2.31.1



Re: [Freedreno] [PATCH 2/2] drm/msm: Restore error return on invalid fence

2021-11-15 Thread Akhil P Oommen

On 11/15/2021 10:26 PM, Rob Clark wrote:

On Mon, Nov 15, 2021 at 6:43 AM Akhil P Oommen  wrote:


On 11/12/2021 12:54 AM, Rob Clark wrote:

From: Rob Clark 

When converting to use an idr to map userspace fence seqno values back
to a dma_fence, we lost the error return when userspace passes seqno
that is larger than the last submitted fence.  Restore this check.

Reported-by: Akhil P Oommen 
Fixes: a61acbbe9cf8 ("drm/msm: Track "seqno" fences by idr")
Signed-off-by: Rob Clark 
---
Note: I will rebase "drm/msm: Handle fence rollover" on top of this,
to simplify backporting this patch to stable kernels

   drivers/gpu/drm/msm/msm_drv.c| 6 ++
   drivers/gpu/drm/msm/msm_gem_submit.c | 1 +
   drivers/gpu/drm/msm/msm_gpu.h| 3 +++
   3 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index cb14d997c174..56500eb5219e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -967,6 +967,12 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, 
uint32_t fence_id,
   struct dma_fence *fence;
   int ret;

+ if (fence_id > queue->last_fence) {


But fence_id can wrap around and then this check won't be valid.


that is correct, but see my note about rebasing "drm/msm: Handle fence
rollover" on top of this patch, so this patch could be more easily
cherry-picked to stable/lts branches

BR,
-R


Missed that. Thanks.

Reviewed-by: Akhil P Oommen 

-Akhil.



-Akhil.


+ DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n",
+   fence_id, queue->last_fence);
+ return -EINVAL;
+ }
+
   /*
* Map submitqueue scoped "seqno" (which is actually an idr key)
* back to underlying dma-fence
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c 
b/drivers/gpu/drm/msm/msm_gem_submit.c
index 151d19e4453c..a38f23be497d 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -911,6 +911,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
   drm_sched_entity_push_job(&submit->base, queue->entity);

   args->fence = submit->fence_id;
+ queue->last_fence = submit->fence_id;

   msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
   msm_process_post_deps(post_deps, args->nr_out_syncobjs,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index bd4e0024033e..e73a5bb03544 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -376,6 +376,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu 
*gpu, int prio,
* @ring_nr:   the ringbuffer used by this submitqueue, which is determined
* by the submitqueue's priority
* @faults:the number of GPU hangs associated with this submitqueue
+ * @last_fence: the sequence number of the last allocated fence (for error
+ * checking)
* @ctx:   the per-drm_file context associated with the submitqueue (ie.
* which set of pgtables do submits jobs associated with the
* submitqueue use)
@@ -391,6 +393,7 @@ struct msm_gpu_submitqueue {
   u32 flags;
   u32 ring_nr;
   int faults;
+ uint32_t last_fence;
   struct msm_file_private *ctx;
   struct list_head node;
   struct idr fence_idr;







Re: [Freedreno] [PATCH igt v3 2/4] lib/igt_debugfs: Add helper for detecting debugfs files

2021-11-15 Thread Petri Latvala
On Mon, Nov 15, 2021 at 04:30:40PM -0800, Rob Clark wrote:
> From: Rob Clark 
> 
> Add a helper that can be used with, for ex, igt_require() so that tests
> can be skipped if the kernel is too old.
> 
> Signed-off-by: Rob Clark 

Reviewed-by: Petri Latvala 

> ---
>  lib/igt_debugfs.c | 21 +
>  lib/igt_debugfs.h |  1 +
>  2 files changed, 22 insertions(+)
> 
> diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
> index dd6f2995..7211c410 100644
> --- a/lib/igt_debugfs.c
> +++ b/lib/igt_debugfs.c
> @@ -307,6 +307,27 @@ int igt_debugfs_open(int device, const char *filename, 
> int mode)
>   return ret;
>  }
>  
> +/**
> + * igt_debugfs_exists:
> + * @device: the drm device file fd
> + * @filename: file name
> + * @mode: mode bits as used by open()
> + *
> + * Test that the specified debugfs file exists and can be opened with the
> + * requested mode.
> + */
> +bool igt_debugfs_exists(int device, const char *filename, int mode)
> +{
> + int fd = igt_debugfs_open(device, filename, mode);
> +
> + if (fd >= 0) {
> + close(fd);
> + return true;
> + }
> +
> + return false;
> +}
> +
>  /**
>   * igt_debugfs_simple_read:
>   * @filename: file name
> diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
> index b4867681..37e85067 100644
> --- a/lib/igt_debugfs.h
> +++ b/lib/igt_debugfs.h
> @@ -39,6 +39,7 @@ int igt_debugfs_connector_dir(int device, char *conn_name, 
> int mode);
>  int igt_debugfs_pipe_dir(int device, int pipe, int mode);
>  
>  int igt_debugfs_open(int fd, const char *filename, int mode);
> +bool igt_debugfs_exists(int fd, const char *filename, int mode);
>  void __igt_debugfs_read(int fd, const char *filename, char *buf, int size);
>  void __igt_debugfs_write(int fd, const char *filename, const char *buf, int 
> size);
>  int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int 
> size);
> -- 
> 2.33.1
> 


Re: [Freedreno] [PATCH linux-next] drm/msm/dp: remove unneeded variable

2021-11-15 Thread Stephen Boyd
Quoting cgel@gmail.com (2021-11-10 04:05:12)
> From: Changcheng Deng 
>
> Fix the following coccicheck review:
> ./drivers/gpu/drm/msm/dp/dp_debug.c: Unneeded variable
>
> Remove unneeded variable used to store return value.
>
> Reported-by: Zeal Robot 
> Signed-off-by: Changcheng Deng 
> ---
>  drivers/gpu/drm/msm/dp/dp_debug.c | 3 +--
>  1 file changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c 
> b/drivers/gpu/drm/msm/dp/dp_debug.c
> index 2f6247e80e9d..c5c75273d1e5 100644
> --- a/drivers/gpu/drm/msm/dp/dp_debug.c
> +++ b/drivers/gpu/drm/msm/dp/dp_debug.c
> @@ -365,7 +365,6 @@ static const struct file_operations test_active_fops = {
>
>  static int dp_debug_init(struct dp_debug *dp_debug, struct drm_minor *minor)

Would be nice to make it void as well and then cleanup the caller. Can
you do that too?

>  {
> -   int rc = 0;
> struct dp_debug_private *debug = container_of(dp_debug,
> struct dp_debug_private, dp_debug);
>


Re: [Freedreno] [PATCH] drm/msm: Fix mmap to include VM_IO and VM_DONTDUMP

2021-11-15 Thread Stephen Boyd
Quoting Douglas Anderson (2021-11-10 11:33:42)
> In commit 510410bfc034 ("drm/msm: Implement mmap as GEM object
> function") we switched to a new/cleaner method of doing things. That's
> good, but we missed a little bit.
>
> Before that commit, we used to _first_ run through the
> drm_gem_mmap_obj() case where `obj->funcs->mmap()` was NULL. That meant
> that we ran:
>
>   vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP;
>   vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
>   vma->vm_page_prot = pgprot_decrypted(vma->vm_page_prot);
>
> ...and _then_ we modified those mappings with our own. Now that
> `obj->funcs->mmap()` is no longer NULL we don't run the default
> code. It looks like the fact that the vm_flags got VM_IO / VM_DONTDUMP
> was important because we're now getting crashes on Chromebooks that
> use ARC++ while logging out. Specifically a crash that looks like this
> (this is on a 5.10 kernel w/ relevant backports but also seen on a
> 5.15 kernel):
>
>   Unable to handle kernel paging request at virtual address ffc00800
>   Mem abort info:
> ESR = 0x9606
> EC = 0x25: DABT (current EL), IL = 32 bits
> SET = 0, FnV = 0
> EA = 0, S1PTW = 0
>   Data abort info:
> ISV = 0, ISS = 0x0006
> CM = 0, WnR = 0
>   swapper pgtable: 4k pages, 39-bit VAs, pgdp=8293d000
>   [ffc00800] pgd=0001002b3003, p4d=0001002b3003,
>  pud=0001002b3003, pmd=
>   Internal error: Oops: 9606 [#1] PREEMPT SMP
>   [...]
>   CPU: 7 PID: 15734 Comm: crash_dump64 Tainted: G W 5.10.67 #1 [...]
>   Hardware name: Qualcomm Technologies, Inc. sc7280 IDP SKU2 platform (DT)
>   pstate: 8049 (Nzcv daif +PAN -UAO -TCO BTYPE=--)
>   pc : __arch_copy_to_user+0xc0/0x30c
>   lr : copyout+0xac/0x14c
>   [...]
>   Call trace:
>__arch_copy_to_user+0xc0/0x30c
>copy_page_to_iter+0x1a0/0x294
>process_vm_rw_core+0x240/0x408
>process_vm_rw+0x110/0x16c
>__arm64_sys_process_vm_readv+0x30/0x3c
>el0_svc_common+0xf8/0x250
>do_el0_svc+0x30/0x80
>el0_svc+0x10/0x1c
>el0_sync_handler+0x78/0x108
>el0_sync+0x184/0x1c0
>   Code: f8408423 f80008c3 910020c6 36100082 (b8404423)
>
> Let's add the two flags back in.
>
> While we're at it, the fact that we aren't running the default means
> that we _don't_ need to clear out VM_PFNMAP, so remove that and save
> an instruction.
>
> NOTE: it was confirmed that VM_IO was the important flag to fix the
> problem I was seeing, but adding back VM_DONTDUMP seems like a sane
> thing to do so I'm doing that too.
>
> Fixes: 510410bfc034 ("drm/msm: Implement mmap as GEM object function")
> Reported-by: Stephen Boyd 
> Signed-off-by: Douglas Anderson 
> ---

Reviewed-by: Stephen Boyd 
Tested-by: Stephen Boyd 


[Freedreno] [PATCH igt v3 4/4] msm: Add recovery tests

2021-11-15 Thread Rob Clark
From: Rob Clark 

Add tests to exercise:

1. sw hangcheck timeout
2. gpu fault (hang) recovery
3. iova fault recovery

Signed-off-by: Rob Clark 
---
 lib/igt_msm.h|   3 +
 tests/meson.build|   1 +
 tests/msm_recovery.c | 174 +++
 3 files changed, 178 insertions(+)
 create mode 100644 tests/msm_recovery.c

diff --git a/lib/igt_msm.h b/lib/igt_msm.h
index 1a66c806..421d23ed 100644
--- a/lib/igt_msm.h
+++ b/lib/igt_msm.h
@@ -97,6 +97,9 @@ enum adreno_pm4_packet_type {
 
 enum adreno_pm4_type3_packets {
CP_NOP = 16,
+   CP_WAIT_MEM_GTE = 20,
+   CP_WAIT_REG_MEM = 60,
+   CP_MEM_WRITE = 61,
 };
 
 static inline unsigned
diff --git a/tests/meson.build b/tests/meson.build
index 0af3e03a..166e3494 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -60,6 +60,7 @@ test_progs = [
'kms_vrr',
'kms_writeback',
'meta_test',
+   'msm_recovery',
'msm_submit',
'panfrost_get_param',
'panfrost_gem_new',
diff --git a/tests/msm_recovery.c b/tests/msm_recovery.c
new file mode 100644
index ..890c543a
--- /dev/null
+++ b/tests/msm_recovery.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright © 2021 Google, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include 
+#include 
+
+#include "igt.h"
+#include "igt_msm.h"
+
+static struct msm_device *dev;
+static struct msm_bo *scratch_bo;
+static uint32_t *scratch;
+
+/*
+ * Helpers for cmdstream packet building:
+ */
+
+static void
+wait_mem_gte(struct msm_cmd *cmd, uint32_t offset_dwords, uint32_t ref)
+{
+   msm_cmd_pkt7(cmd, CP_WAIT_MEM_GTE, 4);
+   msm_cmd_emit(cmd, 0);  /* RESERVED */
+   msm_cmd_bo  (cmd, scratch_bo, offset_dwords * 4);  /* POLL_ADDR_LO/HI */
+   msm_cmd_emit(cmd, ref);/* REF */
+}
+
+static void
+mem_write(struct msm_cmd *cmd, uint32_t offset_dwords, uint32_t val)
+{
+   msm_cmd_pkt7(cmd, CP_MEM_WRITE, 3);
+   msm_cmd_bo  (cmd, scratch_bo, offset_dwords * 4);  /* ADDR_LO/HI */
+   msm_cmd_emit(cmd, val);/* VAL */
+}
+
+/*
+ * Helper to wait on a fence-fd:
+ */
+static void
+wait_and_close(int fence_fd)
+{
+   poll(&(struct pollfd){fence_fd, POLLIN}, 1, -1);
+   close(fence_fd);
+}
+
+/*
+ * Helper for hang tests.  Emits multiple submits, with one in the middle
+ * that triggers a fault, and confirms that the submits before and after
+ * the faulting one execute properly, ie. that the driver properly manages
+ * to recover and re-queue the submits after the faulting submit;
+ */
+static void
+do_hang_test(struct msm_pipe *pipe)
+{
+   struct msm_cmd *cmds[16];
+   int fence_fds[ARRAY_SIZE(cmds)];
+
+   memset(scratch, 0, 0x1000);
+
+   for (unsigned i = 0; i < ARRAY_SIZE(cmds); i++) {
+   struct msm_cmd *cmd = igt_msm_cmd_new(pipe, 0x1000);
+
+   cmds[i] = cmd;
+
+   /*
+* Emit a packet to wait for scratch[0] to be >= 1
+*
+* This lets us force the GPU to wait until all the cmdstream is
+* queued up.
+*/
+   wait_mem_gte(cmd, 0, 1);
+
+   if (i == 10) {
+   msm_cmd_emit(cmd, 0xdeaddead);
+   }
+
+   /* Emit a packet to write scratch[1+i] = 2+i: */
+   mem_write(cmd, 1+i, 2+i);
+   }
+
+   for (unsigned i = 0; i < ARRAY_SIZE(cmds); i++) {
+   fence_fds[i] = igt_msm_cmd_submit(cmds[i]);
+   }
+
+   usleep(1);
+
+   /* Let the WAIT_MEM_GTE complete: */
+   scratch[0] = 1;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(cmds); i++) {
+   wait_and_close(fence_fds[i]);
+   igt_msm_cmd_free(cmds[i]);
+   if (i == 10)
+   continue;
+   igt_assert_

[Freedreno] [PATCH igt v3 3/4] msm: Add helper for cmdstream building and submission

2021-11-15 Thread Rob Clark
From: Rob Clark 

A pretty minimal subset compared to what a full gallium driver would
need, but OTOH for igt tests we should only need to emit fairly basic
command stream.

Signed-off-by: Rob Clark 
---
 lib/igt_msm.c | 102 ++
 lib/igt_msm.h |  48 
 2 files changed, 150 insertions(+)

diff --git a/lib/igt_msm.c b/lib/igt_msm.c
index b9534164..e9cf588f 100644
--- a/lib/igt_msm.c
+++ b/lib/igt_msm.c
@@ -91,6 +91,19 @@ igt_msm_dev_close(struct msm_device *dev)
free(dev);
 }
 
+static uint64_t
+get_iova(struct msm_bo *bo)
+{
+   struct drm_msm_gem_info req = {
+   .handle = bo->handle,
+   .info = MSM_INFO_GET_IOVA,
+   };
+
+   do_ioctl(bo->dev->fd, DRM_IOCTL_MSM_GEM_INFO, &req);
+
+   return req.value;
+}
+
 /**
  * igt_msm_bo_new:
  * @dev: the device to allocate the BO from
@@ -115,6 +128,7 @@ igt_msm_bo_new(struct msm_device *dev, size_t size, 
uint32_t flags)
do_ioctl(dev->fd, DRM_IOCTL_MSM_GEM_NEW, &req);
 
bo->handle = req.handle;
+   bo->iova = get_iova(bo);
 
return bo;
 }
@@ -209,3 +223,91 @@ igt_msm_pipe_close(struct msm_pipe *pipe)
do_ioctl(pipe->dev->fd, DRM_IOCTL_MSM_SUBMITQUEUE_CLOSE, 
&pipe->submitqueue_id);
free(pipe);
 }
+
+/**
+ * igt_msm_cmd_new:
+ * @pipe: the submitqueue to submit cmdstream against
+ * @size: the size of requested cmdstream buffer
+ */
+struct msm_cmd *
+igt_msm_cmd_new(struct msm_pipe *pipe, size_t size)
+{
+   struct msm_cmd *cmd = calloc(1, sizeof(*cmd));
+
+   cmd->pipe = pipe;
+   cmd->cmdstream_bo = igt_msm_bo_new(pipe->dev, size, MSM_BO_WC);
+   cmd->cur = igt_msm_bo_map(cmd->cmdstream_bo);
+
+   __igt_msm_append_bo(cmd, cmd->cmdstream_bo);
+
+   return cmd;
+}
+
+static uint32_t
+cmdstream_size(struct msm_cmd *cmd)
+{
+   uint8_t *start = igt_msm_bo_map(cmd->cmdstream_bo);
+   return (uint8_t *)cmd->cur - start;
+}
+
+/**
+ * igt_msm_cmd_submit:
+ * @cmd: the command stream object to submit
+ *
+ * Returns dma-fence fd
+ */
+int
+igt_msm_cmd_submit(struct msm_cmd *cmd)
+{
+   struct drm_msm_gem_submit_bo bos[cmd->nr_bos];
+   struct drm_msm_gem_submit_cmd cmds[] = {
+   [0] = {
+   .type   = MSM_SUBMIT_CMD_BUF,
+   .submit_idx = 0,
+   .size   = cmdstream_size(cmd),
+   },
+   };
+   struct drm_msm_gem_submit req = {
+   .flags   = cmd->pipe->pipe | MSM_SUBMIT_FENCE_FD_OUT,
+   .queueid = cmd->pipe->submitqueue_id,
+   .nr_cmds = ARRAY_SIZE(cmds),
+   .cmds= VOID2U64(cmds),
+   .nr_bos  = ARRAY_SIZE(bos),
+   .bos = VOID2U64(bos),
+   };
+
+   for (unsigned i = 0; i < cmd->nr_bos; i++) {
+   bos[i] = (struct drm_msm_gem_submit_bo) {
+   .handle  = cmd->bos[i]->handle,
+   .flags   = MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE,
+   };
+   }
+
+   do_ioctl(cmd->pipe->dev->fd, DRM_IOCTL_MSM_GEM_SUBMIT, &req);
+
+   return req.fence_fd;
+}
+
+void
+__igt_msm_append_bo(struct msm_cmd *cmd, struct msm_bo *bo)
+{
+   for (unsigned i = 0; i < cmd->nr_bos; i++)
+   if (cmd->bos[i] == bo)
+   return;
+
+   assert((cmd->nr_bos + 1) < ARRAY_SIZE(cmd->bos));
+   cmd->bos[cmd->nr_bos++] = bo;
+}
+
+/**
+ * igt_msm_cmd_free:
+ * @cmd: the command stream object to free
+ *
+ * Free a command stream object
+ */
+void
+igt_msm_cmd_free(struct msm_cmd *cmd)
+{
+   igt_msm_bo_free(cmd->cmdstream_bo);
+   free(cmd);
+}
diff --git a/lib/igt_msm.h b/lib/igt_msm.h
index 99a099c1..1a66c806 100644
--- a/lib/igt_msm.h
+++ b/lib/igt_msm.h
@@ -24,6 +24,8 @@
 #ifndef IGT_MSM_H
 #define IGT_MSM_H
 
+#include "ioctl_wrappers.h"
+
 #include "msm_drm.h"
 
 /**
@@ -47,6 +49,7 @@ void igt_msm_dev_close(struct msm_device *dev);
  * @handle: the BO's GEM handle
  * @size: the BO's size
  * @map: the BO's memory mapping (if mapped)
+ * @iova: the BO's GPU address
  *
  * Helper wrapper for a GEM buffer object.
  */
@@ -55,6 +58,7 @@ struct msm_bo {
int handle;
uint32_t size;
void *map;
+   uint64_t iova;
 };
 
 struct msm_bo *igt_msm_bo_new(struct msm_device *dev, size_t size, uint32_t 
flags);
@@ -136,6 +140,50 @@ pm4_pkt7_hdr(uint8_t opcode, uint16_t cnt)
((pm4_odd_parity_bit(opcode) << 23));
 }
 
+/**
+ * msm_cmd:
+ * @pipe: the submitqueue to submit cmdstream against
+ * @cmdstream_bo: the backing cmdstream buffer object
+ * @cur: pointer to current position in cmdstream
+ *
+ * Helper for building cmdstream and cmdstream submission
+ */
+struct msm_cmd {
+   struct msm_pipe *pipe;
+   struct msm_bo *cmdstream_bo;
+   uint32_t *cur;
+   uint32_t nr_bos;
+ 

[Freedreno] [PATCH igt v3 2/4] lib/igt_debugfs: Add helper for detecting debugfs files

2021-11-15 Thread Rob Clark
From: Rob Clark 

Add a helper that can be used with, for ex, igt_require() so that tests
can be skipped if the kernel is too old.

Signed-off-by: Rob Clark 
---
 lib/igt_debugfs.c | 21 +
 lib/igt_debugfs.h |  1 +
 2 files changed, 22 insertions(+)

diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index dd6f2995..7211c410 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -307,6 +307,27 @@ int igt_debugfs_open(int device, const char *filename, int 
mode)
return ret;
 }
 
+/**
+ * igt_debugfs_exists:
+ * @device: the drm device file fd
+ * @filename: file name
+ * @mode: mode bits as used by open()
+ *
+ * Test that the specified debugfs file exists and can be opened with the
+ * requested mode.
+ */
+bool igt_debugfs_exists(int device, const char *filename, int mode)
+{
+   int fd = igt_debugfs_open(device, filename, mode);
+
+   if (fd >= 0) {
+   close(fd);
+   return true;
+   }
+
+   return false;
+}
+
 /**
  * igt_debugfs_simple_read:
  * @filename: file name
diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
index b4867681..37e85067 100644
--- a/lib/igt_debugfs.h
+++ b/lib/igt_debugfs.h
@@ -39,6 +39,7 @@ int igt_debugfs_connector_dir(int device, char *conn_name, 
int mode);
 int igt_debugfs_pipe_dir(int device, int pipe, int mode);
 
 int igt_debugfs_open(int fd, const char *filename, int mode);
+bool igt_debugfs_exists(int fd, const char *filename, int mode);
 void __igt_debugfs_read(int fd, const char *filename, char *buf, int size);
 void __igt_debugfs_write(int fd, const char *filename, const char *buf, int 
size);
 int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int 
size);
-- 
2.33.1



[Freedreno] [PATCH igt v3 0/4] msm: Add tests for gpu fault handling

2021-11-15 Thread Rob Clark
From: Rob Clark 

The first patch adds a easy way to write debugfs files (needed to
disable hw fault detection, so we can test the sw timeout fallback).
The second adds some helpers for cmdstream building.  And the third
adds the new tests.

v2: Fix headerdoc comments in first patch
v3: Add helper to detect debugfs files and updated last patch
to skip the one sub-test that depends on new debugfs when
running on older kernels

Rob Clark (4):
  lib/igt_debugfs: Add helper for writing debugfs files
  lib/igt_debugfs: Add helper for detecting debugfs files
  msm: Add helper for cmdstream building and submission
  msm: Add recovery tests

 lib/igt_debugfs.c|  38 ++
 lib/igt_debugfs.h|  14 
 lib/igt_msm.c| 102 +
 lib/igt_msm.h|  51 +
 tests/meson.build|   1 +
 tests/msm_recovery.c | 174 +++
 6 files changed, 380 insertions(+)
 create mode 100644 tests/msm_recovery.c

-- 
2.33.1



[Freedreno] [PATCH igt v3 1/4] lib/igt_debugfs: Add helper for writing debugfs files

2021-11-15 Thread Rob Clark
From: Rob Clark 

Signed-off-by: Rob Clark 
Reviewed-by: Petri Latvala 
---
 lib/igt_debugfs.c | 17 +
 lib/igt_debugfs.h | 13 +
 2 files changed, 30 insertions(+)

diff --git a/lib/igt_debugfs.c b/lib/igt_debugfs.c
index a5bb95ca..dd6f2995 100644
--- a/lib/igt_debugfs.c
+++ b/lib/igt_debugfs.c
@@ -351,6 +351,23 @@ void __igt_debugfs_read(int fd, const char *filename, char 
*buf, int size)
close(dir);
 }
 
+/**
+ * __igt_debugfs_write:
+ * @fd: the drm device file fd
+ * @filename: file name
+ * @buf: buffer to be written to the debugfs file
+ * @size: size of the buffer
+ *
+ * This function opens the debugfs file, writes it, then closes the file.
+ */
+void __igt_debugfs_write(int fd, const char *filename, const char *buf, int 
size)
+{
+   int dir = igt_debugfs_dir(fd);
+
+   igt_sysfs_write(dir, filename, buf, size);
+   close(dir);
+}
+
 /**
  * igt_debugfs_search:
  * @filename: file name
diff --git a/lib/igt_debugfs.h b/lib/igt_debugfs.h
index d43ba6c6..b4867681 100644
--- a/lib/igt_debugfs.h
+++ b/lib/igt_debugfs.h
@@ -40,6 +40,7 @@ int igt_debugfs_pipe_dir(int device, int pipe, int mode);
 
 int igt_debugfs_open(int fd, const char *filename, int mode);
 void __igt_debugfs_read(int fd, const char *filename, char *buf, int size);
+void __igt_debugfs_write(int fd, const char *filename, const char *buf, int 
size);
 int igt_debugfs_simple_read(int dir, const char *filename, char *buf, int 
size);
 bool igt_debugfs_search(int fd, const char *filename, const char *substring);
 
@@ -54,6 +55,18 @@ bool igt_debugfs_search(int fd, const char *filename, const 
char *substring);
 #define igt_debugfs_read(fd, filename, buf) \
__igt_debugfs_read(fd, (filename), (buf), sizeof(buf))
 
+/**
+ * igt_debugfs_write:
+ * @fd: the drm device file fd
+ * @filename: name of the debugfs file
+ * @buf: buffer to be written to the debugfs file
+ *
+ * This is just a convenience wrapper for __igt_debugfs_write. See its
+ * documentation.
+ */
+#define igt_debugfs_write(fd, filename, buf) \
+   __igt_debugfs_write(fd, (filename), (buf), sizeof(buf))
+
 /*
  * Pipe CRC
  */
-- 
2.33.1



Re: [Freedreno] [PATCH v3] arm64: dts: qcom: sc7280: Add Display Port node

2021-11-15 Thread Stephen Boyd
Quoting Kuogee Hsieh (2021-11-02 16:44:33)
> From: Kuogee Hsieh 
>
> Signed-off-by: Kuogee Hsieh 
> ---

What tree is this based on? I don't see edp_phy upstream for sc7280

Otherwise, looks good to me.

Reviewed-by: Stephen Boyd 


Re: [Freedreno] [PATCH v4] drm/msm/dp: do not initialize phy until plugin interrupt received

2021-11-15 Thread khsieh

On 2021-11-09 13:38, Kuogee Hsieh wrote:

From: Kuogee Hsieh 

Current DP drivers have regulators, clocks, irq and phy are grouped
together within a function and executed not in a symmetric manner.
This increase difficulty of code maintenance and limited code 
scalability.

This patch divided the driver life cycle of operation into four states,
resume (including booting up), dongle plugin, dongle unplugged and 
suspend.
Regulators, core clocks and irq are grouped together and enabled at 
resume
(or booting up) so that the DP controller is armed and ready to receive 
HPD
plugin interrupts. HPD plugin interrupt is generated when a dongle 
plugs

into DUT (device under test). Once HPD plugin interrupt is received, DP
controller will initialize phy so that dpcd read/write will function 
and

following link training can be proceeded successfully. DP phy will be
disabled after main link is teared down at end of unplugged HPD 
interrupt
handle triggered by dongle unplugged out of DUT. Finally regulators, 
code

clocks and irq are disabled at corresponding suspension.

Changes in V2:
-- removed unnecessary dp_ctrl NULL check
-- removed unnecessary phy init_count and power_count DRM_DEBUG_DP logs
-- remove flip parameter out of dp_ctrl_irq_enable()
-- add fixes tag

Changes in V3:
-- call dp_display_host_phy_init() instead of dp_ctrl_phy_init() at
dp_display_host_init() for eDP

Changes in V4:
-- rewording commit text to match this commit changes

Fixes: e91e3065a806 ("drm/msm/dp: Add DP compliance tests on
Snapdragon Chipsets")

Signed-off-by: Kuogee Hsieh 
---


any more comments?

 drivers/gpu/drm/msm/dp/dp_ctrl.c| 87 
-

 drivers/gpu/drm/msm/dp/dp_ctrl.h|  9 ++--
 drivers/gpu/drm/msm/dp/dp_display.c | 83 
++-

 3 files changed, 105 insertions(+), 74 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
b/drivers/gpu/drm/msm/dp/dp_ctrl.c

index 7ec155d..4788e8c 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1364,60 +1364,54 @@ static int dp_ctrl_enable_stream_clocks(struct
dp_ctrl_private *ctrl)
return ret;
 }

-int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
+void dp_ctrl_irq_enable(struct dp_ctrl *dp_ctrl)
+{
+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   dp_catalog_ctrl_reset(ctrl->catalog);
+
+   dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
+}
+
+void dp_ctrl_irq_disable(struct dp_ctrl *dp_ctrl)
+{
+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   dp_catalog_ctrl_reset(ctrl->catalog);
+
+   dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
+}
+
+void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl)
 {
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;

-   if (!dp_ctrl) {
-   DRM_ERROR("Invalid input data\n");
-   return -EINVAL;
-   }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;

-   ctrl->dp_ctrl.orientation = flip;
-
-   if (reset)
-   dp_catalog_ctrl_reset(ctrl->catalog);
-
-   DRM_DEBUG_DP("flip=%d\n", flip);
dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
-   dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
-
-   return 0;
 }

-/**
- * dp_ctrl_host_deinit() - Uninitialize DP controller
- * @dp_ctrl: Display Port Driver data
- *
- * Perform required steps to uninitialize DP controller
- * and its resources.
- */
-void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
+void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl)
 {
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;

-   if (!dp_ctrl) {
-   DRM_ERROR("Invalid input data\n");
-   return;
-   }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;

-   dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
+   dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_exit(phy);
-
-   DRM_DEBUG_DP("Host deinitialized successfully\n");
 }

 static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
@@ -1895,8 +1889,14 @@ int dp_ctrl_off_link_stream(struct dp_ctrl 
*dp_ctrl)

return ret;
}

+   DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n",
+   (u32)(uintptr_t)phy, phy->init_count, phy->power_count);
+
phy_power_off(phy);

+   DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n",
+   (u32)(uintptr_t)phy, phy->init_count, phy->power_count);
+
/* aux channel down, reinit phy */
phy_exit(phy);
phy_init(phy);
@@ -1905,23 +1905,6 @@ int dp_ctrl_off_link_stream(struct dp_ctrl 
*dp_ctr

[Freedreno] [PATCH v4.5 12/14] dt-bindings: msm/dp: Add bindings for HDCP registers

2021-11-15 Thread Sean Paul
From: Sean Paul 

This patch adds the bindings for the MSM DisplayPort HDCP registers
which are required to write the HDCP key into the display controller as
well as the registers to enable HDCP authentication/key
exchange/encryption.

We'll use a new compatible string for this since the fields are optional.

Cc: Rob Herring 
Cc: Stephen Boyd 
Signed-off-by: Sean Paul 
Link: 
https://patchwork.freedesktop.org/patch/msgid/20210913175747.47456-13-s...@poorly.run
 #v1
Link: 
https://patchwork.freedesktop.org/patch/msgid/20210915203834.1439-13-s...@poorly.run
 #v2
Link: 
https://patchwork.freedesktop.org/patch/msgid/20211001151145.55916-13-s...@poorly.run
 #v3
Link: 
https://patchwork.freedesktop.org/patch/msgid/20211105030434.2828845-13-s...@poorly.run
 #v4

Changes in v2:
-Drop register range names (Stephen)
-Fix yaml errors (Rob)
Changes in v3:
-Add new compatible string for dp-hdcp
-Add descriptions to reg
-Add minItems/maxItems to reg
-Make reg depend on the new hdcp compatible string
Changes in v4:
-Rebase on Bjorn's multi-dp patchset
Changes in v4.5:
-Remove maxItems from reg (Rob)
-Remove leading zeros in example (Rob)
---
 .../devicetree/bindings/display/msm/dp-controller.yaml | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml 
b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
index b36d74c1da7c..aff7d45ba6ed 100644
--- a/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
+++ b/Documentation/devicetree/bindings/display/msm/dp-controller.yaml
@@ -21,12 +21,15 @@ properties:
   - qcom,sc8180x-edp
 
   reg:
+minItems: 5
 items:
   - description: ahb register block
   - description: aux register block
   - description: link register block
   - description: p0 register block
   - description: p1 register block
+  - description: (Optional) Registers for HDCP device key injection
+  - description: (Optional) Registers for HDCP TrustZone interaction
 
   interrupts:
 maxItems: 1
@@ -111,7 +114,9 @@ examples:
   <0xae90200 0x200>,
   <0xae90400 0xc00>,
   <0xae91000 0x400>,
-  <0xae91400 0x400>;
+  <0xae91400 0x400>,
+  <0xaed1000 0x174>,
+  <0xaee1000 0x2c>;
 interrupt-parent = <&mdss>;
 interrupts = <12>;
 clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
-- 
Sean Paul, Software Engineer, Google / Chromium OS



[Freedreno] [PATCH] drm/msm/adreno: Name the shadow buffer

2021-11-15 Thread Rob Clark
From: Rob Clark 

This was the one GPU related kernel buffer which was not given a debug
name.  Let's fix that.

Signed-off-by: Rob Clark 
---
 drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 2 ++
 drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 2 ++
 2 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
index ec8e043c9d38..a95977e8ad98 100644
--- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
@@ -925,6 +925,8 @@ static int a5xx_hw_init(struct msm_gpu *gpu)
 
if (IS_ERR(a5xx_gpu->shadow))
return PTR_ERR(a5xx_gpu->shadow);
+
+   msm_gem_object_set_name(a5xx_gpu->shadow_bo, "shadow");
}
 
gpu_write64(gpu, REG_A5XX_CP_RB_RPTR_ADDR,
diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
index dcde5eff931d..c6e7e7ca0482 100644
--- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
@@ -1068,6 +1068,8 @@ static int hw_init(struct msm_gpu *gpu)
 
if (IS_ERR(a6xx_gpu->shadow))
return PTR_ERR(a6xx_gpu->shadow);
+
+   msm_gem_object_set_name(a6xx_gpu->shadow_bo, "shadow");
}
 
gpu_write64(gpu, REG_A6XX_CP_RB_RPTR_ADDR_LO,
-- 
2.33.1



[Freedreno] [PATCH v3] drm/msm/dp: employ bridge mechanism for display enable and disable

2021-11-15 Thread Kuogee Hsieh
Currently the msm_dp_*** functions implement the same sequence which would
happen when drm_bridge is used. hence get rid of this intermediate layer
and align with the drm_bridge usage to avoid customized implementation.

Signed-off-by: Kuogee Hsieh 

Changes in v2:
-- revise commit text
-- rename dp_bridge to msm_dp_bridge
-- delete empty functions

Changes in 3:
-- replace kzalloc() with devm_kzalloc()
-- replace __dp_display_enable() with dp_display_enable()
-- replace __dp_display_disable() with dp_display_disable()
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  7 +++
 drivers/gpu/drm/msm/dp/dp_display.c |  4 +-
 drivers/gpu/drm/msm/dp/dp_display.h |  1 +
 drivers/gpu/drm/msm/dp/dp_drm.c | 91 +
 drivers/gpu/drm/msm/msm_drv.h   | 16 +++--
 6 files changed, 113 insertions(+), 27 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 31050aa..c4e08c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1003,9 +1003,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
 
trace_dpu_enc_mode_set(DRMID(drm_enc));
 
-   if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS)
-   msm_dp_display_mode_set(dpu_enc->dp, drm_enc, mode, adj_mode);
-
list_for_each_entry(conn_iter, connector_list, head)
if (conn_iter->encoder == drm_enc)
conn = conn_iter;
@@ -1181,14 +1178,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
 
_dpu_encoder_virt_enable_helper(drm_enc);
 
-   if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {
-   ret = msm_dp_display_enable(dpu_enc->dp, drm_enc);
-   if (ret) {
-   DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n",
-   ret);
-   goto out;
-   }
-   }
dpu_enc->enabled = true;
 
 out:
@@ -1214,11 +1203,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder 
*drm_enc)
/* wait for idle */
dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
 
-   if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {
-   if (msm_dp_display_pre_disable(dpu_enc->dp, drm_enc))
-   DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n");
-   }
-
dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP);
 
for (i = 0; i < dpu_enc->num_phys_encs; i++) {
@@ -1243,11 +1227,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder 
*drm_enc)
 
DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
 
-   if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {
-   if (msm_dp_display_disable(dpu_enc->dp, drm_enc))
-   DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n");
-   }
-
mutex_unlock(&dpu_enc->enc_lock);
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index 27d98b5..d16337f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -557,6 +557,13 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
  encoder->base.id, rc);
return rc;
}
+
+   rc = msm_dp_bridge_init(priv->dp[i], dev, encoder);
+   if (rc) {
+   DPU_ERROR("failed to setup DPU bridge %d: rc:%d\n",
+   encoder->base.id, rc);
+   return rc;
+   }
}
 
return rc;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 2f113ff..51770a4 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1674,8 +1674,8 @@ int msm_dp_display_disable(struct msm_dp *dp, struct 
drm_encoder *encoder)
 }
 
 void msm_dp_display_mode_set(struct msm_dp *dp, struct drm_encoder *encoder,
-   struct drm_display_mode *mode,
-   struct drm_display_mode *adjusted_mode)
+   const struct drm_display_mode *mode,
+   const struct drm_display_mode *adjusted_mode)
 {
struct dp_display_private *dp_display;
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 76f45f9..2237e80 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -13,6 +13,7 @@
 struct msm_dp {
struct drm_device *drm_dev;
struct device *codec_dev;
+   struct drm_bridge *bridge;
struct drm_connector *connector;
struct drm_encoder *encoder;
struct drm_panel *drm_panel;
diff --git a/

[Freedreno] [PATCH 5.15 261/917] drm/msm: prevent NULL dereference in msm_gpu_crashstate_capture()

2021-11-15 Thread Greg Kroah-Hartman
From: Tim Gardner 

[ Upstream commit b220c154832c5cd0df34cbcbcc19d7135c16e823 ]

Coverity complains of a possible NULL dereference:

CID 120718 (#1 of 1): Dereference null return value (NULL_RETURNS)
23. dereference: Dereferencing a pointer that might be NULL state->bos when
calling msm_gpu_crashstate_get_bo. [show details]
301msm_gpu_crashstate_get_bo(state, submit->bos[i].obj,
302submit->bos[i].iova, submit->bos[i].flags);

Fix this by employing the same state->bos NULL check as is used in the next
for loop.

Cc: Rob Clark 
Cc: Sean Paul 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: linux-arm-...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: freedreno@lists.freedesktop.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Tim Gardner 
Reviewed-by: Dmitry Baryshkov 
Link: https://lore.kernel.org/r/20210929162554.14295-1-tim.gard...@canonical.com
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Rob Clark 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_gpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 8a3a592da3a4d..2c46cd968ac4c 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -296,7 +296,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
state->bos = kcalloc(nr,
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
 
-   for (i = 0; i < submit->nr_bos; i++) {
+   for (i = 0; state->bos && i < submit->nr_bos; i++) {
if (should_dump(submit, i)) {
msm_gpu_crashstate_get_bo(state, 
submit->bos[i].obj,
submit->bos[i].iova, 
submit->bos[i].flags);
-- 
2.33.0





Re: [Freedreno] [PATCH v2] drm/msm/dp: employ bridge mechanism for display enable and disable

2021-11-15 Thread Kuogee Hsieh



On 11/6/2021 9:25 AM, Bjorn Andersson wrote:

On Fri 05 Nov 16:22 CDT 2021, Kuogee Hsieh wrote:


Currently the msm_dp_*** functions implement the same sequence which would
happen when drm_bridge is used. hence get rid of this intermediate layer
and align with the drm_bridge usage to avoid customized implementation.

Signed-off-by: Kuogee Hsieh 

Changes in v2:
-- revise commit text
-- rename dp_bridge to msm_dp_bridge
-- delete empty functions
---
  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ---
  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  7 +++
  drivers/gpu/drm/msm/dp/dp_display.c | 18 +++---
  drivers/gpu/drm/msm/dp/dp_display.h |  1 +
  drivers/gpu/drm/msm/dp/dp_drm.c | 91 +
  drivers/gpu/drm/msm/msm_drv.h   | 16 +++--
  6 files changed, 120 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 31050aa..c4e08c4 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1003,9 +1003,6 @@ static void dpu_encoder_virt_mode_set(struct drm_encoder 
*drm_enc,
  
  	trace_dpu_enc_mode_set(DRMID(drm_enc));
  
-	if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS)

-   msm_dp_display_mode_set(dpu_enc->dp, drm_enc, mode, adj_mode);
-
list_for_each_entry(conn_iter, connector_list, head)
if (conn_iter->encoder == drm_enc)
conn = conn_iter;
@@ -1181,14 +1178,6 @@ static void dpu_encoder_virt_enable(struct drm_encoder 
*drm_enc)
  
  	_dpu_encoder_virt_enable_helper(drm_enc);
  
-	if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {

-   ret = msm_dp_display_enable(dpu_enc->dp, drm_enc);
-   if (ret) {
-   DPU_ERROR_ENC(dpu_enc, "dp display enable failed: %d\n",
-   ret);
-   goto out;
-   }
-   }
dpu_enc->enabled = true;
  
  out:

@@ -1214,11 +1203,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder 
*drm_enc)
/* wait for idle */
dpu_encoder_wait_for_event(drm_enc, MSM_ENC_TX_COMPLETE);
  
-	if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {

-   if (msm_dp_display_pre_disable(dpu_enc->dp, drm_enc))
-   DPU_ERROR_ENC(dpu_enc, "dp display push idle failed\n");
-   }
-
dpu_encoder_resource_control(drm_enc, DPU_ENC_RC_EVENT_PRE_STOP);
  
  	for (i = 0; i < dpu_enc->num_phys_encs; i++) {

@@ -1243,11 +1227,6 @@ static void dpu_encoder_virt_disable(struct drm_encoder 
*drm_enc)
  
  	DPU_DEBUG_ENC(dpu_enc, "encoder disabled\n");
  
-	if (drm_enc->encoder_type == DRM_MODE_ENCODER_TMDS) {

-   if (msm_dp_display_disable(dpu_enc->dp, drm_enc))
-   DPU_ERROR_ENC(dpu_enc, "dp display disable failed\n");
-   }
-
mutex_unlock(&dpu_enc->enc_lock);
  }
  
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c

index 27d98b5..d16337f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -557,6 +557,13 @@ static int _dpu_kms_initialize_displayport(struct 
drm_device *dev,
  encoder->base.id, rc);
return rc;
}
+
+   rc = msm_dp_bridge_init(priv->dp[i], dev, encoder);
+   if (rc) {
+   DPU_ERROR("failed to setup DPU bridge %d: rc:%d\n",
+   encoder->base.id, rc);
+   return rc;
+   }
}
  
  	return rc;

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index e41dd40..e9ea6ed 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -569,8 +569,8 @@ static int dp_hpd_plug_handle(struct dp_display_private 
*dp, u32 data)
return 0;
  };
  
-static int dp_display_enable(struct dp_display_private *dp, u32 data);

-static int dp_display_disable(struct dp_display_private *dp, u32 data);
+static int __dp_display_enable(struct dp_display_private *dp, u32 data);
+static int __dp_display_disable(struct dp_display_private *dp, u32 data);

Can you please help me understand why you're changing the name of these
functions?

  
  static int dp_connect_pending_timeout(struct dp_display_private *dp, u32 data)

  {
@@ -855,7 +855,7 @@ static int dp_display_prepare(struct msm_dp *dp_display)
return 0;
  }
  
-static int dp_display_enable(struct dp_display_private *dp, u32 data)

+static int __dp_display_enable(struct dp_display_private *dp, u32 data)
  {
int rc = 0;
  
@@ -898,7 +898,7 @@ static int dp_display_post_enable(struct msm_dp *dp_display)

return 0;
  }
  
-static int dp_display_disable(struct dp_display_private *dp, u32 data)

+static int __dp_display_disable(st

[Freedreno] [PATCH 5.14 280/849] drm/msm: prevent NULL dereference in msm_gpu_crashstate_capture()

2021-11-15 Thread Greg Kroah-Hartman
From: Tim Gardner 

[ Upstream commit b220c154832c5cd0df34cbcbcc19d7135c16e823 ]

Coverity complains of a possible NULL dereference:

CID 120718 (#1 of 1): Dereference null return value (NULL_RETURNS)
23. dereference: Dereferencing a pointer that might be NULL state->bos when
calling msm_gpu_crashstate_get_bo. [show details]
301msm_gpu_crashstate_get_bo(state, submit->bos[i].obj,
302submit->bos[i].iova, submit->bos[i].flags);

Fix this by employing the same state->bos NULL check as is used in the next
for loop.

Cc: Rob Clark 
Cc: Sean Paul 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: linux-arm-...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: freedreno@lists.freedesktop.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Tim Gardner 
Reviewed-by: Dmitry Baryshkov 
Link: https://lore.kernel.org/r/20210929162554.14295-1-tim.gard...@canonical.com
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Rob Clark 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_gpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 0ebf7bc6ad097..8236989828ba3 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -404,7 +404,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
state->bos = kcalloc(nr,
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
 
-   for (i = 0; i < submit->nr_bos; i++) {
+   for (i = 0; state->bos && i < submit->nr_bos; i++) {
if (should_dump(submit, i)) {
msm_gpu_crashstate_get_bo(state, 
submit->bos[i].obj,
submit->bos[i].iova, 
submit->bos[i].flags);
-- 
2.33.0





[Freedreno] [PATCH 5.10 218/575] drm/msm: prevent NULL dereference in msm_gpu_crashstate_capture()

2021-11-15 Thread Greg Kroah-Hartman
From: Tim Gardner 

[ Upstream commit b220c154832c5cd0df34cbcbcc19d7135c16e823 ]

Coverity complains of a possible NULL dereference:

CID 120718 (#1 of 1): Dereference null return value (NULL_RETURNS)
23. dereference: Dereferencing a pointer that might be NULL state->bos when
calling msm_gpu_crashstate_get_bo. [show details]
301msm_gpu_crashstate_get_bo(state, submit->bos[i].obj,
302submit->bos[i].iova, submit->bos[i].flags);

Fix this by employing the same state->bos NULL check as is used in the next
for loop.

Cc: Rob Clark 
Cc: Sean Paul 
Cc: David Airlie 
Cc: Daniel Vetter 
Cc: linux-arm-...@vger.kernel.org
Cc: dri-de...@lists.freedesktop.org
Cc: freedreno@lists.freedesktop.org
Cc: linux-ker...@vger.kernel.org
Signed-off-by: Tim Gardner 
Reviewed-by: Dmitry Baryshkov 
Link: https://lore.kernel.org/r/20210929162554.14295-1-tim.gard...@canonical.com
Signed-off-by: Dmitry Baryshkov 
Signed-off-by: Rob Clark 
Signed-off-by: Sasha Levin 
---
 drivers/gpu/drm/msm/msm_gpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 55d16489d0f3f..90c26da109026 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -376,7 +376,7 @@ static void msm_gpu_crashstate_capture(struct msm_gpu *gpu,
state->bos = kcalloc(nr,
sizeof(struct msm_gpu_state_bo), GFP_KERNEL);
 
-   for (i = 0; i < submit->nr_bos; i++) {
+   for (i = 0; state->bos && i < submit->nr_bos; i++) {
if (should_dump(submit, i)) {
msm_gpu_crashstate_get_bo(state, 
submit->bos[i].obj,
submit->bos[i].iova, 
submit->bos[i].flags);
-- 
2.33.0





Re: [Freedreno] [PATCH 2/2] drm/msm: Restore error return on invalid fence

2021-11-15 Thread Rob Clark
On Mon, Nov 15, 2021 at 6:43 AM Akhil P Oommen  wrote:
>
> On 11/12/2021 12:54 AM, Rob Clark wrote:
> > From: Rob Clark 
> >
> > When converting to use an idr to map userspace fence seqno values back
> > to a dma_fence, we lost the error return when userspace passes seqno
> > that is larger than the last submitted fence.  Restore this check.
> >
> > Reported-by: Akhil P Oommen 
> > Fixes: a61acbbe9cf8 ("drm/msm: Track "seqno" fences by idr")
> > Signed-off-by: Rob Clark 
> > ---
> > Note: I will rebase "drm/msm: Handle fence rollover" on top of this,
> > to simplify backporting this patch to stable kernels
> >
> >   drivers/gpu/drm/msm/msm_drv.c| 6 ++
> >   drivers/gpu/drm/msm/msm_gem_submit.c | 1 +
> >   drivers/gpu/drm/msm/msm_gpu.h| 3 +++
> >   3 files changed, 10 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> > index cb14d997c174..56500eb5219e 100644
> > --- a/drivers/gpu/drm/msm/msm_drv.c
> > +++ b/drivers/gpu/drm/msm/msm_drv.c
> > @@ -967,6 +967,12 @@ static int wait_fence(struct msm_gpu_submitqueue 
> > *queue, uint32_t fence_id,
> >   struct dma_fence *fence;
> >   int ret;
> >
> > + if (fence_id > queue->last_fence) {
>
> But fence_id can wrap around and then this check won't be valid.

that is correct, but see my note about rebasing "drm/msm: Handle fence
rollover" on top of this patch, so this patch could be more easily
cherry-picked to stable/lts branches

BR,
-R

> -Akhil.
>
> > + DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of 
> > %u)\n",
> > +   fence_id, queue->last_fence);
> > + return -EINVAL;
> > + }
> > +
> >   /*
> >* Map submitqueue scoped "seqno" (which is actually an idr key)
> >* back to underlying dma-fence
> > diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c 
> > b/drivers/gpu/drm/msm/msm_gem_submit.c
> > index 151d19e4453c..a38f23be497d 100644
> > --- a/drivers/gpu/drm/msm/msm_gem_submit.c
> > +++ b/drivers/gpu/drm/msm/msm_gem_submit.c
> > @@ -911,6 +911,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void 
> > *data,
> >   drm_sched_entity_push_job(&submit->base, queue->entity);
> >
> >   args->fence = submit->fence_id;
> > + queue->last_fence = submit->fence_id;
> >
> >   msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);
> >   msm_process_post_deps(post_deps, args->nr_out_syncobjs,
> > diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> > index bd4e0024033e..e73a5bb03544 100644
> > --- a/drivers/gpu/drm/msm/msm_gpu.h
> > +++ b/drivers/gpu/drm/msm/msm_gpu.h
> > @@ -376,6 +376,8 @@ static inline int msm_gpu_convert_priority(struct 
> > msm_gpu *gpu, int prio,
> >* @ring_nr:   the ringbuffer used by this submitqueue, which is 
> > determined
> >* by the submitqueue's priority
> >* @faults:the number of GPU hangs associated with this submitqueue
> > + * @last_fence: the sequence number of the last allocated fence (for error
> > + * checking)
> >* @ctx:   the per-drm_file context associated with the submitqueue 
> > (ie.
> >* which set of pgtables do submits jobs associated with the
> >* submitqueue use)
> > @@ -391,6 +393,7 @@ struct msm_gpu_submitqueue {
> >   u32 flags;
> >   u32 ring_nr;
> >   int faults;
> > + uint32_t last_fence;
> >   struct msm_file_private *ctx;
> >   struct list_head node;
> >   struct idr fence_idr;
> >
>


Re: [Freedreno] [PATCH v3] arm64: dts: qcom: sc7280: Add Display Port node

2021-11-15 Thread khsieh

On 2021-11-02 16:44, Kuogee Hsieh wrote:

From: Kuogee Hsieh 

Signed-off-by: Kuogee Hsieh 
---


Anyone has comments on this patch?



Changes in v2:
-- move fixes of dp_phy reg property to other patch

Changes in v3:
-- delete "qcom,sc7180-dp" from msm_dp node

 arch/arm64/boot/dts/qcom/sc7280.dtsi | 89 
+++-

 1 file changed, 87 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/boot/dts/qcom/sc7280.dtsi
b/arch/arm64/boot/dts/qcom/sc7280.dtsi
index fb2f1506..4414abc 100644
--- a/arch/arm64/boot/dts/qcom/sc7280.dtsi
+++ b/arch/arm64/boot/dts/qcom/sc7280.dtsi
@@ -2709,8 +2709,8 @@
 <&gcc GCC_DISP_GPLL0_CLK_SRC>,
 <&dsi_phy 0>,
 <&dsi_phy 1>,
-<0>,
-<0>,
+<&dp_phy 0>,
+<&dp_phy 1>,
 <&edp_phy 0>,
 <&edp_phy 1>;
clock-names = "bi_tcxo",
@@ -2807,6 +2807,13 @@
remote-endpoint = 
<&edp_in>;
};
};
+
+   port@2 {
+reg = <2>;
+dpu_intf0_out: 
endpoint {

+
remote-endpoint = <&dp_in>;
+};
+};
};

mdp_opp_table: opp-table {
@@ -3018,6 +3025,78 @@

status = "disabled";
};
+
+   msm_dp: displayport-controller@ae9 {
+   status = "disabled";
+   compatible = "qcom,sc7280-dp";
+
+   reg = <0 0x0ae9 0 0x1400>;
+
+   interrupt-parent = <&mdss>;
+   interrupts = <12>;
+
+   clocks = <&dispcc DISP_CC_MDSS_AHB_CLK>,
+<&dispcc DISP_CC_MDSS_DP_AUX_CLK>,
+<&dispcc DISP_CC_MDSS_DP_LINK_CLK>,
+<&dispcc 
DISP_CC_MDSS_DP_LINK_INTF_CLK>,
+<&dispcc DISP_CC_MDSS_DP_PIXEL_CLK>;
+   clock-names =   "core_iface",
+   "core_aux",
+   "ctrl_link",
+   "ctrl_link_iface",
+   "stream_pixel";
+   #clock-cells = <1>;
+   assigned-clocks = <&dispcc 
DISP_CC_MDSS_DP_LINK_CLK_SRC>,
+ <&dispcc 
DISP_CC_MDSS_DP_PIXEL_CLK_SRC>;
+   assigned-clock-parents = <&dp_phy 0>, <&dp_phy 
1>;
+   phys = <&dp_phy>;
+   phy-names = "dp";
+
+   operating-points-v2 = <&dp_opp_table>;
+   power-domains = <&rpmhpd SC7280_CX>;
+
+   #sound-dai-cells = <0>;
+
+   ports {
+   #address-cells = <1>;
+   #size-cells = <0>;
+   port@0 {
+   reg = <0>;
+   dp_in: endpoint {
+   remote-endpoint = 
<&dpu_intf0_out>;
+   };
+   };
+
+   port@1 {
+   reg = <1>;
+   dp_out: endpoint { };
+   };
+   };
+
+   dp_opp_table: opp-table {
+   compatible = "operating-points-v2";
+
+   opp-16000 {
+   opp-hz = /bits/ 64 <16000>;
+   required-opps = 
<&rpmhpd_opp_low_svs>;
+   };
+
+   opp-27000 {
+   opp-hz = /bits/ 64 <27000>;
+   required-opps = 
<&rpmhpd_opp_svs>;
+   };
+
+   opp-540

Re: [Freedreno] [PATCH 2/2] drm/msm: Restore error return on invalid fence

2021-11-15 Thread Akhil P Oommen

On 11/12/2021 12:54 AM, Rob Clark wrote:

From: Rob Clark 

When converting to use an idr to map userspace fence seqno values back
to a dma_fence, we lost the error return when userspace passes seqno
that is larger than the last submitted fence.  Restore this check.

Reported-by: Akhil P Oommen 
Fixes: a61acbbe9cf8 ("drm/msm: Track "seqno" fences by idr")
Signed-off-by: Rob Clark 
---
Note: I will rebase "drm/msm: Handle fence rollover" on top of this,
to simplify backporting this patch to stable kernels

  drivers/gpu/drm/msm/msm_drv.c| 6 ++
  drivers/gpu/drm/msm/msm_gem_submit.c | 1 +
  drivers/gpu/drm/msm/msm_gpu.h| 3 +++
  3 files changed, 10 insertions(+)

diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index cb14d997c174..56500eb5219e 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -967,6 +967,12 @@ static int wait_fence(struct msm_gpu_submitqueue *queue, 
uint32_t fence_id,
struct dma_fence *fence;
int ret;
  
+	if (fence_id > queue->last_fence) {


But fence_id can wrap around and then this check won't be valid.

-Akhil.


+   DRM_ERROR_RATELIMITED("waiting on invalid fence: %u (of %u)\n",
+ fence_id, queue->last_fence);
+   return -EINVAL;
+   }
+
/*
 * Map submitqueue scoped "seqno" (which is actually an idr key)
 * back to underlying dma-fence
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c 
b/drivers/gpu/drm/msm/msm_gem_submit.c
index 151d19e4453c..a38f23be497d 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -911,6 +911,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
drm_sched_entity_push_job(&submit->base, queue->entity);
  
  	args->fence = submit->fence_id;

+   queue->last_fence = submit->fence_id;
  
  	msm_reset_syncobjs(syncobjs_to_reset, args->nr_in_syncobjs);

msm_process_post_deps(post_deps, args->nr_out_syncobjs,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index bd4e0024033e..e73a5bb03544 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -376,6 +376,8 @@ static inline int msm_gpu_convert_priority(struct msm_gpu 
*gpu, int prio,
   * @ring_nr:   the ringbuffer used by this submitqueue, which is determined
   * by the submitqueue's priority
   * @faults:the number of GPU hangs associated with this submitqueue
+ * @last_fence: the sequence number of the last allocated fence (for error
+ * checking)
   * @ctx:   the per-drm_file context associated with the submitqueue (ie.
   * which set of pgtables do submits jobs associated with the
   * submitqueue use)
@@ -391,6 +393,7 @@ struct msm_gpu_submitqueue {
u32 flags;
u32 ring_nr;
int faults;
+   uint32_t last_fence;
struct msm_file_private *ctx;
struct list_head node;
struct idr fence_idr;