Re: [PATCH v7 0/8] Add a panel API to set orientation properly

2022-06-14 Thread Hsin-Yi Wang
On Thu, Jun 9, 2022 at 3:27 PM Hsin-Yi Wang  wrote:
>
> Panels usually call drm_connector_set_panel_orientation(), which is
> later than drm/kms driver calling drm_dev_register(). This leads to a
> WARN()[1].
>
> The orientation property is known earlier. For example, some panels
> parse the property through device tree during probe.
>
> The series add a panel API drm_connector_set_orientation_from_panel()
> for drm/kms drivers. The drivers can call the API to set panel's
> orientation before drm_dev_register().
>
> Panel needs to implement .get_orientation callback to return the property.
>
> [1] 
> https://patchwork.kernel.org/project/linux-mediatek/patch/20220530081910.3947168-2-hsi...@chromium.org/
>
> Hsin-Yi Wang (8):
>   drm/panel: Add an API to allow drm to set orientation from panel
>   drm/panel: boe-tv101wum-nl6: Implement .get_orientation callback
>   drm/panel: panel-edp: Implement .get_orientation callback
>   drm/panel: lvds: Implement .get_orientation callback
>   drm/panel: panel-simple: Implement .get_orientation callback
>   drm/panel: ili9881c: Implement .get_orientation callback
>   drm/panel: elida-kd35t133: Implement .get_orientation callback
>   drm: Config orientation property if panel provides it
>
hi Maintainers,

All the patches are reviewed. If there's no other comments, will this
series be picked? Thanks.

>  drivers/gpu/drm/bridge/panel.c| 34 +++
>  drivers/gpu/drm/drm_bridge_connector.c|  8 -
>  drivers/gpu/drm/drm_connector.c   | 31 +
>  .../gpu/drm/panel/panel-boe-tv101wum-nl6.c| 12 +++
>  drivers/gpu/drm/panel/panel-edp.c | 13 ++-
>  drivers/gpu/drm/panel/panel-elida-kd35t133.c  | 12 +++
>  drivers/gpu/drm/panel/panel-ilitek-ili9881c.c | 12 +++
>  drivers/gpu/drm/panel/panel-lvds.c| 13 +++
>  drivers/gpu/drm/panel/panel-simple.c  | 14 +++-
>  include/drm/drm_bridge.h  | 14 
>  include/drm/drm_connector.h   |  4 +++
>  include/drm/drm_panel.h   |  9 +
>  12 files changed, 173 insertions(+), 3 deletions(-)
>
> --
> 2.36.1.255.ge46751e96f-goog
>


[PATCH] drm/sun4i: Fix crash during suspend after component bind failure

2022-06-14 Thread Samuel Holland
If the component driver fails to bind, or is unbound, the driver data
for the top-level platform device points to a freed drm_device. If the
system is then suspended, the driver passes this dangling pointer to
drm_mode_config_helper_suspend(), which crashes.

Fix this by only setting the driver data while the platform driver holds
a reference to the drm_device.

Fixes: 624b4b48d9d8 ("drm: sun4i: Add support for suspending the display 
driver")
Signed-off-by: Samuel Holland 
---

 drivers/gpu/drm/sun4i/sun4i_drv.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c 
b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 275f7e4a03ae..8841dba989ee 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -73,7 +73,6 @@ static int sun4i_drv_bind(struct device *dev)
goto free_drm;
}
 
-   dev_set_drvdata(dev, drm);
drm->dev_private = drv;
INIT_LIST_HEAD(>frontend_list);
INIT_LIST_HEAD(>engine_list);
@@ -114,6 +113,8 @@ static int sun4i_drv_bind(struct device *dev)
 
drm_fbdev_generic_setup(drm, 32);
 
+   dev_set_drvdata(dev, drm);
+
return 0;
 
 finish_poll:
@@ -130,6 +131,7 @@ static void sun4i_drv_unbind(struct device *dev)
 {
struct drm_device *drm = dev_get_drvdata(dev);
 
+   dev_set_drvdata(dev, NULL);
drm_dev_unregister(drm);
drm_kms_helper_poll_fini(drm);
drm_atomic_helper_shutdown(drm);
-- 
2.35.1



[PATCH v2 6/6] drm/sun4i: sun8i-hdmi-phy: Group PHY ops functions by generation

2022-06-14 Thread Samuel Holland
Now that the PHY ops are separated, sort them topologically, with the
common sun8i_hdmi_phy_set_polarity helper at the top. No function
contents are changed in this commit.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 67 --
 1 file changed, 32 insertions(+), 35 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index f94c1bad..ca53b5e9fffc 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -124,7 +124,19 @@ static const struct dw_hdmi_phy_config 
sun50i_h6_phy_config[] = {
 };
 
 static void sun8i_hdmi_phy_set_polarity(struct sun8i_hdmi_phy *phy,
-   const struct drm_display_mode *mode);
+   const struct drm_display_mode *mode)
+{
+   u32 val = 0;
+
+   if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+   val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC;
+
+   if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+   val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC;
+
+   regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
+  SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
+};
 
 static int sun8i_a83t_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
  const struct drm_display_info *display,
@@ -193,6 +205,25 @@ static int sun8i_a83t_hdmi_phy_config(struct dw_hdmi 
*hdmi, void *data,
return 0;
 }
 
+static void sun8i_a83t_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
+{
+   struct sun8i_hdmi_phy *phy = data;
+
+   dw_hdmi_phy_gen2_txpwron(hdmi, 0);
+   dw_hdmi_phy_gen2_pddq(hdmi, 1);
+
+   regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
+  SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0);
+}
+
+static const struct dw_hdmi_phy_ops sun8i_a83t_hdmi_phy_ops = {
+   .init   = sun8i_a83t_hdmi_phy_config,
+   .disable= sun8i_a83t_hdmi_phy_disable,
+   .read_hpd   = dw_hdmi_phy_read_hpd,
+   .update_hpd = dw_hdmi_phy_update_hpd,
+   .setup_hpd  = dw_hdmi_phy_setup_hpd,
+};
+
 static int sun8i_h3_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
const struct drm_display_info *display,
const struct drm_display_mode *mode)
@@ -348,32 +379,6 @@ static int sun8i_h3_hdmi_phy_config(struct dw_hdmi *hdmi, 
void *data,
return 0;
 }
 
-static void sun8i_hdmi_phy_set_polarity(struct sun8i_hdmi_phy *phy,
-   const struct drm_display_mode *mode)
-{
-   u32 val = 0;
-
-   if (mode->flags & DRM_MODE_FLAG_NHSYNC)
-   val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NHSYNC;
-
-   if (mode->flags & DRM_MODE_FLAG_NVSYNC)
-   val |= SUN8I_HDMI_PHY_DBG_CTRL_POL_NVSYNC;
-
-   regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
-  SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
-};
-
-static void sun8i_a83t_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
-{
-   struct sun8i_hdmi_phy *phy = data;
-
-   dw_hdmi_phy_gen2_txpwron(hdmi, 0);
-   dw_hdmi_phy_gen2_pddq(hdmi, 1);
-
-   regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
-  SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN, 0);
-}
-
 static void sun8i_h3_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
 {
struct sun8i_hdmi_phy *phy = data;
@@ -385,14 +390,6 @@ static void sun8i_h3_hdmi_phy_disable(struct dw_hdmi 
*hdmi, void *data)
regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, 0);
 }
 
-static const struct dw_hdmi_phy_ops sun8i_a83t_hdmi_phy_ops = {
-   .init   = sun8i_a83t_hdmi_phy_config,
-   .disable= sun8i_a83t_hdmi_phy_disable,
-   .read_hpd   = dw_hdmi_phy_read_hpd,
-   .update_hpd = dw_hdmi_phy_update_hpd,
-   .setup_hpd  = dw_hdmi_phy_setup_hpd,
-};
-
 static const struct dw_hdmi_phy_ops sun8i_h3_hdmi_phy_ops = {
.init   = sun8i_h3_hdmi_phy_config,
.disable= sun8i_h3_hdmi_phy_disable,
-- 
2.35.1



[PATCH v2 4/6] drm/sun4i: sun8i-hdmi-phy: Support multiple custom PHY ops

2022-06-14 Thread Samuel Holland
The D1 SoC comes with a new custom HDMI PHY, which does not share any
registers with the existing custom PHY. So it needs a new set of ops.
Instead of providing a flag in the variant structure, provide the ops
themselves.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  2 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 12 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index 0adbfac6eb31..f0b1aaad27d9 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -151,10 +151,10 @@ struct sun8i_hdmi_phy;
 struct sun8i_hdmi_phy_variant {
bool has_phy_clk;
bool has_second_pll;
-   unsigned int is_custom_phy : 1;
const struct dw_hdmi_curr_ctrl *cur_ctr;
const struct dw_hdmi_mpll_config *mpll_cfg;
const struct dw_hdmi_phy_config *phy_cfg;
+   const struct dw_hdmi_phy_ops *phy_ops;
void (*phy_init)(struct sun8i_hdmi_phy *phy);
void (*phy_disable)(struct dw_hdmi *hdmi,
struct sun8i_hdmi_phy *phy);
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 9086ce547fad..e6d25bbe3d2f 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -567,8 +567,8 @@ void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
 {
const struct sun8i_hdmi_phy_variant *variant = phy->variant;
 
-   if (variant->is_custom_phy) {
-   plat_data->phy_ops = _hdmi_phy_ops;
+   if (variant->phy_ops) {
+   plat_data->phy_ops = variant->phy_ops;
plat_data->phy_name = "sun8i_dw_hdmi_phy";
plat_data->phy_data = phy;
} else {
@@ -587,7 +587,7 @@ static const struct regmap_config 
sun8i_hdmi_phy_regmap_config = {
 };
 
 static const struct sun8i_hdmi_phy_variant sun8i_a83t_hdmi_phy = {
-   .is_custom_phy = true,
+   .phy_ops = _hdmi_phy_ops,
.phy_init = _hdmi_phy_init_a83t,
.phy_disable = _hdmi_phy_disable_a83t,
.phy_config = _hdmi_phy_config_a83t,
@@ -595,7 +595,7 @@ static const struct sun8i_hdmi_phy_variant 
sun8i_a83t_hdmi_phy = {
 
 static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = {
.has_phy_clk = true,
-   .is_custom_phy = true,
+   .phy_ops = _hdmi_phy_ops,
.phy_init = _hdmi_phy_init_h3,
.phy_disable = _hdmi_phy_disable_h3,
.phy_config = _hdmi_phy_config_h3,
@@ -604,7 +604,7 @@ static const struct sun8i_hdmi_phy_variant 
sun8i_h3_hdmi_phy = {
 static const struct sun8i_hdmi_phy_variant sun8i_r40_hdmi_phy = {
.has_phy_clk = true,
.has_second_pll = true,
-   .is_custom_phy = true,
+   .phy_ops = _hdmi_phy_ops,
.phy_init = _hdmi_phy_init_h3,
.phy_disable = _hdmi_phy_disable_h3,
.phy_config = _hdmi_phy_config_h3,
@@ -612,7 +612,7 @@ static const struct sun8i_hdmi_phy_variant 
sun8i_r40_hdmi_phy = {
 
 static const struct sun8i_hdmi_phy_variant sun50i_a64_hdmi_phy = {
.has_phy_clk = true,
-   .is_custom_phy = true,
+   .phy_ops = _hdmi_phy_ops,
.phy_init = _hdmi_phy_init_h3,
.phy_disable = _hdmi_phy_disable_h3,
.phy_config = _hdmi_phy_config_h3,
-- 
2.35.1



[PATCH v2 5/6] drm/sun4i: sun8i-hdmi-phy: Separate A83T and H3 PHY ops

2022-06-14 Thread Samuel Holland
Since the driver already needs to support multiple sets of ops, we can
drop the mid-layer used by the A83T and H3 PHYs. They share only a small
amount of code; factor this out as sun8i_hdmi_phy_set_polarity.

For clarity, this commit keeps the existing function order.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  5 --
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 89 +-
 2 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index f0b1aaad27d9..f082b8ecfe2c 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -156,11 +156,6 @@ struct sun8i_hdmi_phy_variant {
const struct dw_hdmi_phy_config *phy_cfg;
const struct dw_hdmi_phy_ops *phy_ops;
void (*phy_init)(struct sun8i_hdmi_phy *phy);
-   void (*phy_disable)(struct dw_hdmi *hdmi,
-   struct sun8i_hdmi_phy *phy);
-   int  (*phy_config)(struct dw_hdmi *hdmi,
-  struct sun8i_hdmi_phy *phy,
-  unsigned int clk_rate);
 };
 
 struct sun8i_hdmi_phy {
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index e6d25bbe3d2f..f94c1bad 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -123,10 +123,18 @@ static const struct dw_hdmi_phy_config 
sun50i_h6_phy_config[] = {
{ ~0UL,  0x, 0x, 0x}
 };
 
-static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi *hdmi,
- struct sun8i_hdmi_phy *phy,
- unsigned int clk_rate)
+static void sun8i_hdmi_phy_set_polarity(struct sun8i_hdmi_phy *phy,
+   const struct drm_display_mode *mode);
+
+static int sun8i_a83t_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
+ const struct drm_display_info *display,
+ const struct drm_display_mode *mode)
 {
+   unsigned int clk_rate = mode->crtc_clock * 1000;
+   struct sun8i_hdmi_phy *phy = data;
+
+   sun8i_hdmi_phy_set_polarity(phy, mode);
+
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_REXT_CTRL_REG,
   SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN,
   SUN8I_HDMI_PHY_REXT_CTRL_REXT_EN);
@@ -185,10 +193,12 @@ static int sun8i_hdmi_phy_config_a83t(struct dw_hdmi 
*hdmi,
return 0;
 }
 
-static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
-   struct sun8i_hdmi_phy *phy,
-   unsigned int clk_rate)
+static int sun8i_h3_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
+   const struct drm_display_info *display,
+   const struct drm_display_mode *mode)
 {
+   unsigned int clk_rate = mode->crtc_clock * 1000;
+   struct sun8i_hdmi_phy *phy = data;
u32 pll_cfg1_init;
u32 pll_cfg2_init;
u32 ana_cfg1_end;
@@ -197,6 +207,11 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
u32 b_offset = 0;
u32 val;
 
+   if (phy->variant->has_phy_clk)
+   clk_set_rate(phy->clk_phy, clk_rate);
+
+   sun8i_hdmi_phy_set_polarity(phy, mode);
+
/* bandwidth / frequency independent settings */
 
pll_cfg1_init = SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN |
@@ -333,11 +348,9 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi *hdmi,
return 0;
 }
 
-static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, void *data,
-const struct drm_display_info *display,
-const struct drm_display_mode *mode)
+static void sun8i_hdmi_phy_set_polarity(struct sun8i_hdmi_phy *phy,
+   const struct drm_display_mode *mode)
 {
-   struct sun8i_hdmi_phy *phy = (struct sun8i_hdmi_phy *)data;
u32 val = 0;
 
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
@@ -348,16 +361,12 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, 
void *data,
 
regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG,
   SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val);
-
-   if (phy->variant->has_phy_clk)
-   clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000);
-
-   return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000);
 };
 
-static void sun8i_hdmi_phy_disable_a83t(struct dw_hdmi *hdmi,
-   struct sun8i_hdmi_phy *phy)
+static void sun8i_a83t_hdmi_phy_disable(struct dw_hdmi *hdmi, void *data)
 {
+   struct sun8i_hdmi_phy *phy = data;
+
dw_hdmi_phy_gen2_txpwron(hdmi, 0);
dw_hdmi_phy_gen2_pddq(hdmi, 1);
 
@@ -365,9 +374,10 @@ static void sun8i_hdmi_phy_disable_a83t(struct 

[PATCH v2 3/6] drm/sun4i: sun8i-hdmi-phy: Used device-managed clocks/resets

2022-06-14 Thread Samuel Holland
Now that the HDMI PHY is using a platform driver, it can use device-
managed resources. Use these, as well as the dev_err_probe helper, to
simplify the probe function and get rid of the remove function.

Signed-off-by: Samuel Holland 
---

Changes in v2:
 - Move error handling inside variant checks in probe function

 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 90 --
 1 file changed, 26 insertions(+), 64 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 10504c2de132..9086ce547fad 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -673,10 +673,8 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct 
device_node *node)
 static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
 {
struct device *dev = >dev;
-   struct device_node *node = dev->of_node;
struct sun8i_hdmi_phy *phy;
void __iomem *regs;
-   int ret;
 
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
@@ -686,88 +684,52 @@ static int sun8i_hdmi_phy_probe(struct platform_device 
*pdev)
phy->dev = dev;
 
regs = devm_platform_ioremap_resource(pdev, 0);
-   if (IS_ERR(regs)) {
-   dev_err(dev, "Couldn't map the HDMI PHY registers\n");
-   return PTR_ERR(regs);
-   }
+   if (IS_ERR(regs))
+   return dev_err_probe(dev, PTR_ERR(regs),
+"Couldn't map the HDMI PHY registers\n");
 
phy->regs = devm_regmap_init_mmio(dev, regs,
  _hdmi_phy_regmap_config);
-   if (IS_ERR(phy->regs)) {
-   dev_err(dev, "Couldn't create the HDMI PHY regmap\n");
-   return PTR_ERR(phy->regs);
-   }
+   if (IS_ERR(phy->regs))
+   return dev_err_probe(dev, PTR_ERR(phy->regs),
+"Couldn't create the HDMI PHY regmap\n");
 
-   phy->clk_bus = of_clk_get_by_name(node, "bus");
-   if (IS_ERR(phy->clk_bus)) {
-   dev_err(dev, "Could not get bus clock\n");
-   return PTR_ERR(phy->clk_bus);
-   }
+   phy->clk_bus = devm_clk_get(dev, "bus");
+   if (IS_ERR(phy->clk_bus))
+   return dev_err_probe(dev, PTR_ERR(phy->clk_bus),
+"Could not get bus clock\n");
 
-   phy->clk_mod = of_clk_get_by_name(node, "mod");
-   if (IS_ERR(phy->clk_mod)) {
-   dev_err(dev, "Could not get mod clock\n");
-   ret = PTR_ERR(phy->clk_mod);
-   goto err_put_clk_bus;
-   }
+   phy->clk_mod = devm_clk_get(dev, "mod");
+   if (IS_ERR(phy->clk_mod))
+   return dev_err_probe(dev, PTR_ERR(phy->clk_mod),
+"Could not get mod clock\n");
 
if (phy->variant->has_phy_clk) {
-   phy->clk_pll0 = of_clk_get_by_name(node, "pll-0");
-   if (IS_ERR(phy->clk_pll0)) {
-   dev_err(dev, "Could not get pll-0 clock\n");
-   ret = PTR_ERR(phy->clk_pll0);
-   goto err_put_clk_mod;
-   }
+   phy->clk_pll0 = devm_clk_get(dev, "pll-0");
+   if (IS_ERR(phy->clk_pll0))
+   return dev_err_probe(dev, PTR_ERR(phy->clk_pll0),
+"Could not get pll-0 clock\n");
 
if (phy->variant->has_second_pll) {
-   phy->clk_pll1 = of_clk_get_by_name(node, "pll-1");
-   if (IS_ERR(phy->clk_pll1)) {
-   dev_err(dev, "Could not get pll-1 clock\n");
-   ret = PTR_ERR(phy->clk_pll1);
-   goto err_put_clk_pll0;
-   }
+   phy->clk_pll1 = devm_clk_get(dev, "pll-1");
+   if (IS_ERR(phy->clk_pll1))
+   return dev_err_probe(dev, 
PTR_ERR(phy->clk_pll1),
+"Could not get pll-1 
clock\n");
}
}
 
-   phy->rst_phy = of_reset_control_get_shared(node, "phy");
-   if (IS_ERR(phy->rst_phy)) {
-   dev_err(dev, "Could not get phy reset control\n");
-   ret = PTR_ERR(phy->rst_phy);
-   goto err_put_clk_pll1;
-   }
+   phy->rst_phy = devm_reset_control_get_shared(dev, "phy");
+   if (IS_ERR(phy->rst_phy))
+   return dev_err_probe(dev, PTR_ERR(phy->rst_phy),
+"Could not get phy reset control\n");
 
platform_set_drvdata(pdev, phy);
 
return 0;
-
-err_put_clk_pll1:
-   clk_put(phy->clk_pll1);
-err_put_clk_pll0:
-   clk_put(phy->clk_pll0);
-err_put_clk_mod:
-   clk_put(phy->clk_mod);
-err_put_clk_bus:
-   clk_put(phy->clk_bus);
-
-   return ret;
-}
-

[PATCH v2 2/6] drm/sun4i: sun8i-hdmi-phy: Use devm_platform_ioremap_resource

2022-06-14 Thread Samuel Holland
The struct resource is not used for anything else, so we can simplify
the code a bit by using the helper function.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 4553e04144fe..10504c2de132 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -675,7 +675,6 @@ static int sun8i_hdmi_phy_probe(struct platform_device 
*pdev)
struct device *dev = >dev;
struct device_node *node = dev->of_node;
struct sun8i_hdmi_phy *phy;
-   struct resource res;
void __iomem *regs;
int ret;
 
@@ -686,13 +685,7 @@ static int sun8i_hdmi_phy_probe(struct platform_device 
*pdev)
phy->variant = of_device_get_match_data(dev);
phy->dev = dev;
 
-   ret = of_address_to_resource(node, 0, );
-   if (ret) {
-   dev_err(dev, "phy: Couldn't get our resources\n");
-   return ret;
-   }
-
-   regs = devm_ioremap_resource(dev, );
+   regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs)) {
dev_err(dev, "Couldn't map the HDMI PHY registers\n");
return PTR_ERR(regs);
-- 
2.35.1



[PATCH v2 1/6] drm/sun4i: sun8i-hdmi-phy: Use of_device_get_match_data

2022-06-14 Thread Samuel Holland
Now that the HDMI PHY is using a platform driver, we can use the usual
helper function for getting the variant structure.

Signed-off-by: Samuel Holland 
---

(no changes since v1)

 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |  2 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 11 ++-
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h 
b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
index bffe1b9cd3dc..0adbfac6eb31 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h
@@ -173,7 +173,7 @@ struct sun8i_hdmi_phy {
unsigned intrcal;
struct regmap   *regs;
struct reset_control*rst_phy;
-   struct sun8i_hdmi_phy_variant   *variant;
+   const struct sun8i_hdmi_phy_variant *variant;
 };
 
 struct sun8i_dw_hdmi_quirks {
diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c 
b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
index 2860e6bff8b7..4553e04144fe 100644
--- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
+++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c
@@ -565,7 +565,7 @@ void sun8i_hdmi_phy_deinit(struct sun8i_hdmi_phy *phy)
 void sun8i_hdmi_phy_set_ops(struct sun8i_hdmi_phy *phy,
struct dw_hdmi_plat_data *plat_data)
 {
-   struct sun8i_hdmi_phy_variant *variant = phy->variant;
+   const struct sun8i_hdmi_phy_variant *variant = phy->variant;
 
if (variant->is_custom_phy) {
plat_data->phy_ops = _hdmi_phy_ops;
@@ -672,7 +672,6 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct 
device_node *node)
 
 static int sun8i_hdmi_phy_probe(struct platform_device *pdev)
 {
-   const struct of_device_id *match;
struct device *dev = >dev;
struct device_node *node = dev->of_node;
struct sun8i_hdmi_phy *phy;
@@ -680,17 +679,11 @@ static int sun8i_hdmi_phy_probe(struct platform_device 
*pdev)
void __iomem *regs;
int ret;
 
-   match = of_match_node(sun8i_hdmi_phy_of_table, node);
-   if (!match) {
-   dev_err(dev, "Incompatible HDMI PHY\n");
-   return -EINVAL;
-   }
-
phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
return -ENOMEM;
 
-   phy->variant = (struct sun8i_hdmi_phy_variant *)match->data;
+   phy->variant = of_device_get_match_data(dev);
phy->dev = dev;
 
ret = of_address_to_resource(node, 0, );
-- 
2.35.1



[PATCH v2 0/6] drm/sun4i: HDMI PHY cleanup/refactoring

2022-06-14 Thread Samuel Holland
This series prepares the sun8i HDMI PHY driver for supporting the new
custom PHY in the Allwinner D1 SoC. No functional change intended here.

This series was tested on D1, H3, and H6.

Changes in v2:
 - Move error handling inside variant checks in probe function

Samuel Holland (6):
  drm/sun4i: sun8i-hdmi-phy: Use of_device_get_match_data
  drm/sun4i: sun8i-hdmi-phy: Use devm_platform_ioremap_resource
  drm/sun4i: sun8i-hdmi-phy: Used device-managed clocks/resets
  drm/sun4i: sun8i-hdmi-phy: Support multiple custom PHY ops
  drm/sun4i: sun8i-hdmi-phy: Separate A83T and H3 PHY ops
  drm/sun4i: sun8i-hdmi-phy: Group PHY ops functions by generation

 drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h  |   9 +-
 drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 242 ++---
 2 files changed, 97 insertions(+), 154 deletions(-)

-- 
2.35.1



RE: [RESEND RFC 06/18] drm/display/dp_mst: Add some missing kdocs for atomic MST structs

2022-06-14 Thread Lin, Wayne
[Public]



> -Original Message-
> From: Lyude Paul 
> Sent: Wednesday, June 8, 2022 3:29 AM
> To: dri-devel@lists.freedesktop.org; nouv...@lists.freedesktop.org; amd-
> g...@lists.freedesktop.org
> Cc: Lin, Wayne ; Ville Syrjälä
> ; Zuo, Jerry ; Jani Nikula
> ; Imre Deak ; Daniel Vetter
> ; Sean Paul ; David Airlie
> ; Daniel Vetter ; Thomas Zimmermann
> ; Deucher, Alexander
> ; Lakha, Bhawanpreet
> ; open list 
> Subject: [RESEND RFC 06/18] drm/display/dp_mst: Add some missing kdocs
> for atomic MST structs
> 
> Since we're about to start adding some stuff here, we may as well fill in any
> missing documentation that we forgot to write.
> 
> Signed-off-by: Lyude Paul 
> Cc: Wayne Lin 
> Cc: Ville Syrjälä 
> Cc: Fangzhi Zuo 
> Cc: Jani Nikula 
> Cc: Imre Deak 
> Cc: Daniel Vetter 
> Cc: Sean Paul 
> ---
>  include/drm/display/drm_dp_mst_helper.h | 24
> 
>  1 file changed, 24 insertions(+)
> 
> diff --git a/include/drm/display/drm_dp_mst_helper.h
> b/include/drm/display/drm_dp_mst_helper.h
> index 8ab4f14f2344..eb0ea578b227 100644
> --- a/include/drm/display/drm_dp_mst_helper.h
> +++ b/include/drm/display/drm_dp_mst_helper.h
> @@ -542,19 +542,43 @@ struct drm_dp_payload {
> 
>  #define to_dp_mst_topology_state(x) container_of(x, struct
> drm_dp_mst_topology_state, base)
> 
> +/**
> + * struct drm_dp_mst_atomic_payload - Atomic state struct for an MST
> +payload
> + *
> + * The primary atomic state structure for a given MST payload. Stores
> +information like current
> + * bandwidth allocation, intended action for this payload, etc.
> + */
>  struct drm_dp_mst_atomic_payload {
> + /** @port: The MST port assigned to this payload */
>   struct drm_dp_mst_port *port;
> + /** @time_slots: The number of timeslots allocated to this payload

Hi Lyude,
Would like to also indicate that the timeslots is allocated from source DP Tx
to immediate downstream DP Rx.

> */
>   int time_slots;
> + /** @pbn: The payload bandwidth for this payload */
>   int pbn;
> + /** @dsc_enabled: Whether or not this payload has DSC enabled */
>   bool dsc_enabled;
> +
> + /** @next: The list node for this payload */
>   struct list_head next;
>  };
> 
> +/**
> + * struct drm_dp_mst_topology_state - DisplayPort MST topology atomic
> +state
> + *
> + * This struct represents the atomic state of the toplevel DisplayPort
> +MST manager  */
>  struct drm_dp_mst_topology_state {
> + /** @base: Base private state for atomic */
>   struct drm_private_state base;
> +
> + /** @payloads: The list of payloads being created/destroyed in this
> +state */
>   struct list_head payloads;
> + /** @mgr: The topology manager */
>   struct drm_dp_mst_topology_mgr *mgr;
> +
> + /** @total_avail_slots: The total number of slots this topology can
> +handle (63 or 64) */
>   u8 total_avail_slots;

I would prefer not using the term "available" which is a bit conflicting with
the idea in the reply of ENUM_PATH_RESOURCES - full PBN & available PBN.
Maybe better to change to use "full_slots"?

Not yet finish all the patches. Will try to go through all the patches recently 
: )

> + /** @start_slot: The first usable time slot in this topology (1 or 0)
> +*/
>   u8 start_slot;
>  };
> 
> --
> 2.35.3

--
Regards,
Wayne Lin


RE: [RESEND RFC 04/18] drm/display/dp_mst: Call them time slots, not VCPI slots

2022-06-14 Thread Lin, Wayne
[Public]

Thank you Lyude for addressing this!

VCPI is also a confusing naming to me at first glance since it stands for 
Virtual Channel Payload Identification which is just an ID number ( we can 
 look up these payload IDs In DPCD 0x2C1 ~0x2FF).

I also look up left VCPI terms in rest of the code. Seems like we still can 
modify 
some parts here? Like:

/**
 * struct drm_dp_vcpi - Virtual Channel Payload Identifier
 * @vcpi: Virtual channel ID.
 * @pbn: Payload Bandwidth Number for this channel
 * @aligned_pbn: PBN aligned with slot size
 * @num_slots: number of slots for this PBN
 */
struct drm_dp_vcpi {
int vcpi;
int pbn;
int aligned_pbn;
int num_slots;
};

Would like to change the structure name to  "struct drm_dp_mst_vcp {}" to 
represent
the virtual channel payload. Not specific to the ID.
Would like to know your thoughts : )

> -Original Message-
> From: Lyude Paul 
> Sent: Wednesday, June 8, 2022 3:29 AM
> To: dri-devel@lists.freedesktop.org; nouv...@lists.freedesktop.org; amd-
> g...@lists.freedesktop.org
> Cc: Lin, Wayne ; Ville Syrjälä
> ; Zuo, Jerry ; Jani Nikula
> ; Imre Deak ; Daniel Vetter
> ; Sean Paul ; Wentland, Harry
> ; Li, Sun peng (Leo) ;
> Siqueira, Rodrigo ; Deucher, Alexander
> ; Koenig, Christian
> ; Pan, Xinhui ; David
> Airlie ; Daniel Vetter ; Jani Nikula
> ; Joonas Lahtinen
> ; Rodrigo Vivi ;
> Tvrtko Ursulin ; Ben Skeggs
> ; Karol Herbst ; Kazlauskas,
> Nicholas ; Li, Roman
> ; Shih, Jude ; Simon Ser
> ; Wu, Hersen ; Thomas
> Zimmermann ; Lakha, Bhawanpreet
> ; José Roberto de Souza
> ; He Ying ; Matt Roper
> ; Sean Paul ; Hans
> Verkuil ; Fernando Ramos ;
> Javier Martinez Canillas ; open list  ker...@vger.kernel.org>; open list:INTEL DRM DRIVERS  g...@lists.freedesktop.org>
> Subject: [RESEND RFC 04/18] drm/display/dp_mst: Call them time slots, not
> VCPI slots
> 
> VCPI is only sort of the correct term here, originally the majority of this 
> code
> simply referred to timeslots vaguely as "slots" - and since I started working
> on it and adding atomic functionality, the name "VCPI slots" has been used to
> represent time slots.
> 
> Now that we actually have consistent access to the DisplayPort spec thanks to
> VESA, I now know this isn't actually the proper term - as the specification
> refers to these as time slots.
> 
> Since we're trying to make this code as easy to figure out as possible, let's
> take this opportunity to correct this nomenclature and call them by their
> proper name - timeslots. Likewise, we rename various functions
> appropriately, along with replacing references in the kernel documentation
> and various debugging messages.
> 
> It's important to note that this patch series leaves the legacy MST code
> untouched for the most part, which is fine since we'll be removing it soon
> anyhow. There should be no functional changes in this series.
> 
> Signed-off-by: Lyude Paul 
> Cc: Wayne Lin 
> Cc: Ville Syrjälä 
> Cc: Fangzhi Zuo 
> Cc: Jani Nikula 
> Cc: Imre Deak 
> Cc: Daniel Vetter 
> Cc: Sean Paul 
> ---
>  .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |   2 +-
>  .../display/amdgpu_dm/amdgpu_dm_mst_types.c   |  28 ++---
>  drivers/gpu/drm/display/drm_dp_mst_topology.c | 106 +-
>  drivers/gpu/drm/i915/display/intel_dp_mst.c   |   5 +-
>  drivers/gpu/drm/nouveau/dispnv50/disp.c   |   4 +-
>  include/drm/display/drm_dp_mst_helper.h   |   6 +-
>  6 files changed, 75 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> index ad4571190a90..f84a4ad736d8 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -7393,7 +7393,7 @@ static int dm_encoder_helper_atomic_check(struct
> drm_encoder *encoder,
>   clock = adjusted_mode->clock;
>   dm_new_connector_state->pbn =
> drm_dp_calc_pbn_mode(clock, bpp, false);
>   }
> - dm_new_connector_state->vcpi_slots =
> drm_dp_atomic_find_vcpi_slots(state,
> + dm_new_connector_state->vcpi_slots =
> +drm_dp_atomic_find_time_slots(state,
> 
> mst_mgr,
> 
> mst_port,
> 
> dm_new_connector_state->pbn, diff --git
> a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> index 9221b6690a4a..e40ff51e7be0 100644
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
> @@ -378,7 +378,7 @@ static int dm_dp_mst_atomic_check(struct
> drm_connector *connector,
>   return 0;
>   }
> 
> - return drm_dp_atomic_release_vcpi_slots(state,
> + return drm_dp_atomic_release_time_slots(state,
>   mst_mgr,
>   mst_port);
>  }
> @@ -689,7 +689,7 @@ static void increase_dsc_bpp(struct
> 

Re: [PATCH v9 05/14] dt-bindings: display: bridge: Add i.MX8qm/qxp display pixel link binding

2022-06-14 Thread Liu Ying
On Tue, 2022-06-14 at 14:11 -0600, Rob Herring wrote:
> On Sat, Jun 11, 2022 at 10:14:12PM +0800, Liu Ying wrote:
> > This patch adds bindings for i.MX8qm/qxp display pixel link.
> > 
> > Signed-off-by: Liu Ying 
> > ---
> > v8->v9:
> > * Add 'fsl,dc-id' and 'fsl,dc-stream-id' properties. (Laurent)
> 
> Why? Isn't the graph sufficient for determining the connections?
> That's 
> what it is for.

'fsl,dc-id' determines the SCU resource IMX_SC_R_DC_{0,1} used by the
pixel link. 'fsl,dc-stream-id' determines the SCU control codes, like
IMX_SC_C_PXL_LINK_MST{1,2}_ADDR.

The pixel combiner stands between the Display Controller(DPU) and the
pixel link. I doubt it'll be good to go through the graph in pixel link
driver to get DPU's output port index to set 'dc-stream-id'. 

The graph doesn't tell 'dc-id' unless DPU's or pixel link's OF alias
ids are used. It looks that people don't like the idea of using the
pixel link's OF alias id in pixel link driver to set 'dc-id'(and 'dc-
stream-id'), just like previous versions do.  

> 
> > * Drop Rob's R-b tag.
> > 
> > v7->v8:
> > * No change.
> > 
> > v6->v7:
> > * No change.
> > 
> > v5->v6:
> > * No change.
> > 
> > v4->v5:
> > * No change.
> > 
> > v3->v4:
> > * No change.
> > 
> > v2->v3:
> > * Add Rob's R-b tag.
> > 
> > v1->v2:
> > * Use graph schema. (Laurent)
> > * Require all four pixel link output ports. (Laurent)
> > * Mention pixel link is accessed via SCU firmware. (Rob)
> > 
> >  .../bridge/fsl,imx8qxp-pixel-link.yaml| 144
> > ++
> >  1 file changed, 144 insertions(+)
> >  create mode 100644
> > Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-
> > link.yaml
> > 
> > diff --git
> > a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-
> > pixel-link.yaml
> > b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-
> > pixel-link.yaml
> > new file mode 100644
> > index ..38ecc7926fad
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-
> > pixel-link.yaml
> > @@ -0,0 +1,144 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: 
> > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fschemas%2Fdisplay%2Fbridge%2Ffsl%2Cimx8qxp-pixel-link.yaml%23data=05%7C01%7Cvictor.liu%40nxp.com%7Cc8ba0853ca6446514fb408da4e421ec0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637908343136669762%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=ZLdEqO84HZMwOIjyo5t%2Fy%2BlcfliLr3J5mV2akOxPU5c%3Dreserved=0
> > +$schema: 
> > https://eur01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fdevicetree.org%2Fmeta-schemas%2Fcore.yaml%23data=05%7C01%7Cvictor.liu%40nxp.com%7Cc8ba0853ca6446514fb408da4e421ec0%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C637908343136669762%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7Csdata=yL5Xi%2BWz4aX3yniTy8Jq0EhB%2FbLz59QOaCQpxP0AmDM%3Dreserved=0
> > +
> > +title: Freescale i.MX8qm/qxp Display Pixel Link
> > +
> > +maintainers:
> > +  - Liu Ying 
> > +
> > +description: |
> > +  The Freescale i.MX8qm/qxp Display Pixel Link(DPL) forms a
> > standard
> > +  asynchronous linkage between pixel sources(display controller or
> > +  camera module) and pixel consumers(imaging or displays).
> > +  It consists of two distinct functions, a pixel transfer function
> > and a
> > +  control interface.  Multiple pixel channels can exist per one
> > control channel.
> > +  This binding documentation is only for pixel links whose pixel
> > sources are
> > +  display controllers.
> > +
> > +  The i.MX8qm/qxp Display Pixel Link is accessed via System
> > Controller Unit(SCU)
> > +  firmware.
> > +
> > +properties:
> > +  compatible:
> > +enum:
> > +  - fsl,imx8qm-dc-pixel-link
> > +  - fsl,imx8qxp-dc-pixel-link
> > +
> > +  fsl,dc-id:
> > +$ref: /schemas/types.yaml#/definitions/uint8
> > +description: |
> > +  u8 value representing the display controller index that the
> > pixel link
> > +  connects to.
> > +
> > +  fsl,dc-stream-id:
> > +$ref: /schemas/types.yaml#/definitions/uint8
> > +description: |
> > +  u8 value representing the display controller stream index
> > that the pixel
> > +  link connects to.
> > +enum: [0, 1]
> > +
> > +  ports:
> > +$ref: /schemas/graph.yaml#/properties/ports
> > +
> > +properties:
> > +  port@0:
> > +$ref: /schemas/graph.yaml#/properties/port
> > +description: The pixel link input port node from upstream
> > video source.
> > +
> > +patternProperties:
> > +  "^port@[1-4]$":
> > +$ref: /schemas/graph.yaml#/properties/port
> > +description: The pixel link output port node to downstream
> > bridge.
> > +
> > +required:
> > +  - port@0
> > +  - port@1
> > +  - port@2
> > +  - port@3
> > +  - port@4
> > +
> > 

Re: [RFC PATCH 3/5] drm/amdgpu: Allow explicit sync for VM ops.

2022-06-14 Thread Bas Nieuwenhuizen
Hi Christian,

Friendly ping on the comments here. Are you okay with me re-spinning
the series with a fixed patch 1 or do we need further discussion on
the approach here?

Thanks,
Bas

On Mon, Jun 6, 2022 at 1:00 PM Bas Nieuwenhuizen
 wrote:
>
> On Mon, Jun 6, 2022 at 12:35 PM Christian König
>  wrote:
> >
> > Am 06.06.22 um 12:30 schrieb Bas Nieuwenhuizen:
> > > On Mon, Jun 6, 2022 at 12:15 PM Christian König
> > >  wrote:
> > >>
> > >>
> > >> Am 03.06.22 um 21:11 schrieb Bas Nieuwenhuizen:
> > >>> On Fri, Jun 3, 2022 at 8:41 PM Christian König 
> > >>>  wrote:
> >  Am 03.06.22 um 19:50 schrieb Bas Nieuwenhuizen:
> > > [SNIP]
> >  Yeah, but that's exactly the bubble we try to avoid. Isn't it?
> > >>> For this series, not really.  To clarify there are two sides for
> > >>> getting GPU bubbles and no overlap:
> > >>>
> > >>> (1) VM operations implicitly wait for earlier CS submissions
> > >>> (2) CS submissions implicitly wait for earlier VM operations
> > >>>
> > >>> Together, these combine to ensure that you get a (potentially small)
> > >>> bubble any time VM work happens.
> > >>>
> > >>> Your series (and further ideas) tackles (2), and is a worthwhile 
> > >>> thing
> > >>> to do. However, while writing the userspace for this I noticed this
> > >>> isn't enough to get rid of all our GPU bubbles. In particular when
> > >>> doing a non-sparse map of a new BO, that tends to need to be waited 
> > >>> on
> > >>> for the next CS anyway for API semantics. Due to VM operations
> > >>> happening on a single timeline that means this high priority map can
> > >>> end up being blocked by earlier sparse maps and hence the bubble in
> > >>> that case still exists.
> > >>>
> > >>> So in this series I try to tackle (1) instead. Since GPU work
> > >>> typically lags behind CPU submissions and VM operations aren't that
> > >>> slow, we can typically execute VM operations early enough that any
> > >>> implicit syncs from (2) are less/no issue.
> > >> Ok, once more since you don't seem to understand what I want to say: 
> > >> It
> > >> isn't possible to fix #1 before you have fixed #2.
> > >>
> > >> The VM unmap operation here is a barrier which divides the CS 
> > >> operations
> > >> in a before and after. This is intentional design.
> > > Why is that barrier needed? The two barriers I got and understood and
> > > I think we can deal with:
> > >
> > > 1) the VM unmap is a barrier between prior CS and later memory free.
> > > 2) The TLB flush need to happen between a VM unmap and later CS.
> > >
> > > But why do we need the VM unmap to be a strict barrier between prior
> > > CS and later CS?
> >  Exactly because of the two reasons you mentioned.
> > >>> This is the part I'm not seeing. I get that removing #2 is a
> > >>> nightmare, which is why I did something that doesn't violate that
> > >>> constraint.
> > >>>
> > >>> Like if an explicit CS that was running before the VM operation  runs
> > >>> till after the VM operation (and hence possibly till after the TLB
> > >>> flush, or otherwise have the TLB flush not apply due to lack of async
> > >>> TLB flush support), that is not an issue. It might see the state from
> > >>> before the unmap, or after the unmap, or some intermediate state and
> > >>> all of those would be okay.
> > >>>
> > >>> We still get the constraint that the TLB flush happens between the VM
> > >>> unmap and later CS and hence the unmap is certainly visible to them.
> > >> So you basically just want to set the sync mode in
> > >> amdgpu_vm_update_range() to AMDGPU_SYNC_EXPLICIT even when it is an 
> > >> unmap?
> > > Yes, with the caveat that I want to do that only for
> > > DMA_RESV_USAGE_BOOKKEEP or higher (i.e. if we submit a CS with
> > > implicit sync we get the old implicit behavior, if we submit a CS with
> > > explicit sync we get the new explicit behavior). The rest of the
> > > series is basically just for enabling explicit sync submissions.
> >
> > That part won't work at all and would cause additional synchronization
> > problems.
> >
> > First of all for implicit synced CS we should use READ, not BOOKKEEP.
> > Because BOOKKEEP would incorrectly be ignored by OpenGL importers. I've
> > fixed that this causes memory corruption, but it is still nice to avoid.
>
> Yes, what I'm saying is that on implicit sync CS submission should add
> READ fences to the dma resv and on explicit sync CS submission should
> add BOOKKEEP fences.
>
> >
> > BOOKKEEP can only be used by VM updates themselves. So that they don't
> > interfere with CS.
>
> That is the point why we would go BOOKKEEP for explicit sync CS
> submissions, no? Explicit submission shouldn't interfere with any
> other CS submissions. That includes being totally ignored by GL
> importers (if we want to have synchronization there between an
> explicit submission and 

[PATCH v2 2/2] drm/i915/gt: Cleanup interface for MCR operations

2022-06-14 Thread Matt Roper
Let's replace the assortment of intel_gt_* and intel_uncore_* functions
that operate on MCR registers with a cleaner set of interfaces:

  * intel_gt_mcr_read -- unicast read from specific instance
  * intel_gt_mcr_read_any[_fw] -- unicast read from any non-terminated
instance
  * intel_gt_mcr_unicast_write -- unicast write to specific instance
  * intel_gt_mcr_multicast_write[_fw] -- multicast write to all instances

We'll also replace the historic "slice" and "subslice" terminology with
"group" and "instance" to match the documentation for more recent
platforms; these days MCR steering applies to more types of replication
than just slice/subslice.

v2:
 - Reference the new kerneldoc from i915.rst.  (Jani)
 - Tweak the wording of the documentation for a couple functions to
   clarify the difference between "_fw" and non-"_fw" forms.

Signed-off-by: Matt Roper 
Acked-by: Jani Nikula 
---
 Documentation/gpu/i915.rst  |  12 +
 drivers/gpu/drm/i915/gem/i915_gem_stolen.c  |   2 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c   |  33 ++-
 drivers/gpu/drm/i915/gt/intel_gt_debugfs.c  |   2 +-
 drivers/gpu/drm/i915/gt/intel_gt_mcr.c  | 239 
 drivers/gpu/drm/i915/gt/intel_gt_mcr.h  |  43 ++--
 drivers/gpu/drm/i915/gt/intel_region_lmem.c |   4 +-
 drivers/gpu/drm/i915/gt/intel_workarounds.c |   8 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c  |   2 +-
 9 files changed, 200 insertions(+), 145 deletions(-)

diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst
index 54060cd6c419..4e59db1cfb00 100644
--- a/Documentation/gpu/i915.rst
+++ b/Documentation/gpu/i915.rst
@@ -246,6 +246,18 @@ Display State Buffer
 .. kernel-doc:: drivers/gpu/drm/i915/display/intel_dsb.c
:internal:
 
+GT Programming
+==
+
+Multicast/Replicated (MCR) Registers
+
+
+.. kernel-doc:: drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+   :doc: GT Multicast/Replicated (MCR) Register Support
+
+.. kernel-doc:: drivers/gpu/drm/i915/gt/intel_gt_mcr.c
+   :internal:
+
 Memory Management and Command Submission
 
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c 
b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index da30503d3ca2..fa54823d1219 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -835,7 +835,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, 
u16 type,
} else {
resource_size_t lmem_range;
 
-   lmem_range = intel_gt_read_register(>gt0, 
XEHPSDV_TILE0_ADDR_RANGE) & 0x;
+   lmem_range = intel_gt_mcr_read_any(>gt0, 
XEHPSDV_TILE0_ADDR_RANGE) & 0x;
lmem_size = lmem_range >> XEHPSDV_TILE_LMEM_RANGE_SHIFT;
lmem_size *= SZ_1G;
}
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index 244af1bdb7db..136cc44c3deb 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -1428,14 +1428,6 @@ void intel_engine_cancel_stop_cs(struct intel_engine_cs 
*engine)
ENGINE_WRITE_FW(engine, RING_MI_MODE, _MASKED_BIT_DISABLE(STOP_RING));
 }
 
-static u32
-read_subslice_reg(const struct intel_engine_cs *engine,
- int slice, int subslice, i915_reg_t reg)
-{
-   return intel_uncore_read_with_mcr_steering(engine->uncore, reg,
-  slice, subslice);
-}
-
 /* NB: please notice the memset */
 void intel_engine_get_instdone(const struct intel_engine_cs *engine,
   struct intel_instdone *instdone)
@@ -1469,28 +1461,33 @@ void intel_engine_get_instdone(const struct 
intel_engine_cs *engine,
if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) {
for_each_instdone_gslice_dss_xehp(i915, sseu, iter, 
slice, subslice) {
instdone->sampler[slice][subslice] =
-   read_subslice_reg(engine, slice, 
subslice,
- 
GEN7_SAMPLER_INSTDONE);
+   intel_gt_mcr_read(engine->gt,
+ GEN7_SAMPLER_INSTDONE,
+ slice, subslice);
instdone->row[slice][subslice] =
-   read_subslice_reg(engine, slice, 
subslice,
- GEN7_ROW_INSTDONE);
+   intel_gt_mcr_read(engine->gt,
+ GEN7_ROW_INSTDONE,
+ slice, subslice);
}
} else {
for_each_instdone_slice_subslice(i915, sseu, slice, 

[PATCH v2 0/2] i915: Extract, polish, and document multicast handling

2022-06-14 Thread Matt Roper
Multicast/replicated (MCR) registers on Intel hardware are a purely
GT-specific concept.  Rather than leaving MCR register handling spread
across several places throughout the driver (intel_uncore.c, intel_gt.c,
etc.) with confusing combinations of handler functions living in
different namespaces, let's consolidate it all into a single place
(intel_gt_mcr.c) and provide a more consistent and clearly-documented
interface for the rest of the driver to access such registers:

 * intel_gt_mcr_read -- unicast read from specific instance
 * intel_gt_mcr_read_any[_fw] -- unicast read from any non-terminated
   instance
 * intel_gt_mcr_unicast_write -- unicast write to specific instance
 * intel_gt_mcr_multicast_write[_fw] -- multicast write to all instances


v2:
 - Reference the new kerneldoc from i915.rst.  (Jani)
 - Tweak the wording of the documentation for a couple functions to
   clarify the difference between "_fw" and non-"_fw" forms.

Matt Roper (2):
  drm/i915/gt: Move multicast register handling to a dedicated file
  drm/i915/gt: Cleanup interface for MCR operations

 Documentation/gpu/i915.rst  |  12 +
 drivers/gpu/drm/i915/Makefile   |   1 +
 drivers/gpu/drm/i915/gem/i915_gem_stolen.c  |   3 +-
 drivers/gpu/drm/i915/gt/intel_engine_cs.c   |  36 +-
 drivers/gpu/drm/i915/gt/intel_gt.c  | 297 +---
 drivers/gpu/drm/i915/gt/intel_gt.h  |  15 -
 drivers/gpu/drm/i915/gt/intel_gt_debugfs.c  |   3 +-
 drivers/gpu/drm/i915/gt/intel_gt_mcr.c  | 497 
 drivers/gpu/drm/i915/gt/intel_gt_mcr.h  |  34 ++
 drivers/gpu/drm/i915/gt/intel_region_lmem.c |   5 +-
 drivers/gpu/drm/i915/gt/intel_workarounds.c |   9 +-
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c  |   3 +-
 drivers/gpu/drm/i915/i915_drv.h |   2 -
 drivers/gpu/drm/i915/intel_uncore.c | 112 -
 drivers/gpu/drm/i915/intel_uncore.h |   8 -
 15 files changed, 577 insertions(+), 460 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_mcr.c
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_mcr.h

-- 
2.35.3



[PATCH v2 1/2] drm/i915/gt: Move multicast register handling to a dedicated file

2022-06-14 Thread Matt Roper
Handling of multicast/replicated registers is spread across intel_gt.c
and intel_uncore.c today.  As multicast handling and the related
steering logic gets more complicated with the addition of new platforms
and new rules it makes sense to centralize it all in one place.

For now the existing functions have been moved to the new .c/.h as-is.
Function renames and updates to operate in a more consistent manner will
be done in subsequent patches.

Signed-off-by: Matt Roper 
Acked-by: Jani Nikula 
---
 drivers/gpu/drm/i915/Makefile   |   1 +
 drivers/gpu/drm/i915/gem/i915_gem_stolen.c  |   1 +
 drivers/gpu/drm/i915/gt/intel_engine_cs.c   |   3 +-
 drivers/gpu/drm/i915/gt/intel_gt.c  | 297 +
 drivers/gpu/drm/i915/gt/intel_gt.h  |  15 -
 drivers/gpu/drm/i915/gt/intel_gt_debugfs.c  |   1 +
 drivers/gpu/drm/i915/gt/intel_gt_mcr.c  | 448 
 drivers/gpu/drm/i915/gt/intel_gt_mcr.h  |  37 ++
 drivers/gpu/drm/i915/gt/intel_region_lmem.c |   1 +
 drivers/gpu/drm/i915/gt/intel_workarounds.c |   1 +
 drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c  |   1 +
 drivers/gpu/drm/i915/i915_drv.h |   2 -
 drivers/gpu/drm/i915/intel_uncore.c | 112 -
 drivers/gpu/drm/i915/intel_uncore.h |   8 -
 14 files changed, 495 insertions(+), 433 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_mcr.c
 create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_mcr.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index d2b18f03a33c..08f5d0d6e83a 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -103,6 +103,7 @@ gt-y += \
gt/intel_gt_debugfs.o \
gt/intel_gt_engines_debugfs.o \
gt/intel_gt_irq.o \
+   gt/intel_gt_mcr.o \
gt/intel_gt_pm.o \
gt/intel_gt_pm_debugfs.o \
gt/intel_gt_pm_irq.o \
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c 
b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
index 47b5e0e342ab..da30503d3ca2 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c
@@ -13,6 +13,7 @@
 #include "gem/i915_gem_lmem.h"
 #include "gem/i915_gem_region.h"
 #include "gt/intel_gt.h"
+#include "gt/intel_gt_mcr.h"
 #include "gt/intel_region_lmem.h"
 #include "i915_drv.h"
 #include "i915_gem_stolen.h"
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c 
b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
index f0acf8518a51..244af1bdb7db 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c
+++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c
@@ -21,8 +21,9 @@
 #include "intel_engine_user.h"
 #include "intel_execlists_submission.h"
 #include "intel_gt.h"
-#include "intel_gt_requests.h"
+#include "intel_gt_mcr.h"
 #include "intel_gt_pm.h"
+#include "intel_gt_requests.h"
 #include "intel_lrc.h"
 #include "intel_lrc_reg.h"
 #include "intel_reset.h"
diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c 
b/drivers/gpu/drm/i915/gt/intel_gt.c
index f33290358c51..be9877c4b496 100644
--- a/drivers/gpu/drm/i915/gt/intel_gt.c
+++ b/drivers/gpu/drm/i915/gt/intel_gt.c
@@ -17,6 +17,7 @@
 #include "intel_gt_clock_utils.h"
 #include "intel_gt_debugfs.h"
 #include "intel_gt_gmch.h"
+#include "intel_gt_mcr.h"
 #include "intel_gt_pm.h"
 #include "intel_gt_regs.h"
 #include "intel_gt_requests.h"
@@ -102,107 +103,13 @@ int intel_gt_assign_ggtt(struct intel_gt *gt)
return gt->ggtt ? 0 : -ENOMEM;
 }
 
-static const char * const intel_steering_types[] = {
-   "L3BANK",
-   "MSLICE",
-   "LNCF",
-   "INSTANCE 0",
-};
-
-static const struct intel_mmio_range icl_l3bank_steering_table[] = {
-   { 0x00B100, 0x00B3FF },
-   {},
-};
-
-static const struct intel_mmio_range xehpsdv_mslice_steering_table[] = {
-   { 0x004000, 0x004AFF },
-   { 0x00C800, 0x00CFFF },
-   { 0x00DD00, 0x00DDFF },
-   { 0x00E900, 0x00 }, /* 0xEA00 - OxEFFF is unused */
-   {},
-};
-
-static const struct intel_mmio_range xehpsdv_lncf_steering_table[] = {
-   { 0x00B000, 0x00B0FF },
-   { 0x00D800, 0x00D8FF },
-   {},
-};
-
-static const struct intel_mmio_range dg2_lncf_steering_table[] = {
-   { 0x00B000, 0x00B0FF },
-   { 0x00D880, 0x00D8FF },
-   {},
-};
-
-/*
- * We have several types of MCR registers on PVC where steering to (0,0)
- * will always provide us with a non-terminated value.  We'll stick them
- * all in the same table for simplicity.
- */
-static const struct intel_mmio_range pvc_instance0_steering_table[] = {
-   { 0x004000, 0x004AFF }, /* HALF-BSLICE */
-   { 0x008800, 0x00887F }, /* CC */
-   { 0x008A80, 0x008AFF }, /* TILEPSMI */
-   { 0x00B000, 0x00B0FF }, /* HALF-BSLICE */
-   { 0x00B100, 0x00B3FF }, /* L3BANK */
-   { 0x00C800, 0x00CFFF }, /* HALF-BSLICE */
-   { 0x00D800, 0x00D8FF }, /* HALF-BSLICE */
-   { 0x00DD00, 0x00DDFF }, /* BSLICE */
-   { 0x00E900, 

[PATCH 2/2] arm64: dts: qcom: sm8250: Enable per-process page tables.

2022-06-14 Thread Emma Anholt
This is an SMMU for the adreno gpu, and adding this compatible lets
the driver use per-fd page tables, which are required for security
between GPU clients.

Signed-off-by: Emma Anholt 
---

Tested with a full deqp-vk run on RB5, which did involve some iommu faults.

 arch/arm64/boot/dts/qcom/sm8250.dtsi | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm64/boot/dts/qcom/sm8250.dtsi 
b/arch/arm64/boot/dts/qcom/sm8250.dtsi
index a92230bec1dd..483c0e0f1d1a 100644
--- a/arch/arm64/boot/dts/qcom/sm8250.dtsi
+++ b/arch/arm64/boot/dts/qcom/sm8250.dtsi
@@ -2513,7 +2513,7 @@ gpucc: clock-controller@3d9 {
};
 
adreno_smmu: iommu@3da {
-   compatible = "qcom,sm8250-smmu-500", "arm,mmu-500";
+   compatible = "qcom,sm8250-smmu-500", "arm,mmu-500", 
"qcom,adreno-smmu";
reg = <0 0x03da 0 0x1>;
#iommu-cells = <2>;
#global-interrupts = <2>;
-- 
2.36.1



[PATCH 1/2] iommu: arm-smmu-impl: Add 8250 display compatible to the client list.

2022-06-14 Thread Emma Anholt
Required for turning on per-process page tables for the GPU.

Signed-off-by: Emma Anholt 
---

 drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
index d8e1ef83c01b..bb9220937068 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
@@ -233,6 +233,7 @@ static const struct of_device_id 
qcom_smmu_client_of_match[] __maybe_unused = {
{ .compatible = "qcom,sc7280-mdss" },
{ .compatible = "qcom,sc7280-mss-pil" },
{ .compatible = "qcom,sc8180x-mdss" },
+   { .compatible = "qcom,sm8250-mdss" },
{ .compatible = "qcom,sdm845-mdss" },
{ .compatible = "qcom,sdm845-mss-pil" },
{ }
-- 
2.36.1



Re: [PATCH v6] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Kuogee Hsieh



On 6/14/2022 2:59 PM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-06-14 14:05:02)

Display resolution change is implemented through drm modeset. Older
modeset (resolution) has to be disabled first before newer modeset
(resolution) can be enabled. Display disable will turn off both
pixel clock and main link clock so that main link have to be
re-trained during display enable to have new video stream flow
again. At current implementation, display enable function manually
kicks up irq_hpd_handle which will read panel link status and start
link training if link status is not in sync state.

However, there is rare case that a particular panel links status keep
staying in sync for some period of time after main link had been shut
down previously at display disabled. In this case, main link retraining
will not be executed by irq_hdp_handle(). Hence video stream of newer
display resolution will fail to be transmitted to panel due to main
link is not in sync between host and panel.

This patch will bypass irq_hpd_hanle() in favor of directly call

s/hanle/handle/


dp_ctrl_on_stream() to always perform link training in regardless of
main link status. So that no unexpected exception resolution change
failure cases will happen. Also this implementation are more efficient
than manual kicking off irq_hpd_handle function.

Changes in v2:
-- set force_link_train flag on DP only (is_edp == false)

Changes in v3:
-- revise commit  text
-- add Fixes tag

Changes in v4:
-- revise commit  text

Changes in v5:
-- fix spelling at commit text

Changes in v6:
-- split dp_ctrl_on_stream() for phy test case
-- revise commit text for modeset

Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by failure of 
link train")
Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_ctrl.c| 31 +++
  drivers/gpu/drm/msm/dp/dp_ctrl.h|  3 ++-
  drivers/gpu/drm/msm/dp/dp_display.c | 13 ++---
  3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index af7a80c..cb9c7af 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1807,7 +1807,27 @@ static int dp_ctrl_link_retrain(struct dp_ctrl_private 
*ctrl)
 return dp_ctrl_setup_main_link(ctrl, _step);
  }

-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
+int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl)
+{
+   int ret = 0;

Drop assignment please.


+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+
+   ret = dp_ctrl_enable_stream_clocks(ctrl);
+   if (ret) {
+   DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
+   return ret;
+   }
+
+   dp_ctrl_send_phy_test_pattern(ctrl);

None of this code needs to be run in the normal display on case?


+
+   return 0;
+}
+
+int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
  {
 int ret = 0;
 bool mainlink_ready = false;
@@ -1843,12 +1863,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
 goto end;
 }

-   if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
-   dp_ctrl_send_phy_test_pattern(ctrl);
-   return 0;
-   }
-
-   if (!dp_ctrl_channel_eq_ok(ctrl))
+   if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))
 dp_ctrl_link_retrain(ctrl);

 /* stop txing train pattern to end link training */
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c388323..b6d25ab 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1688,10 +1689,12 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)

 state =  dp_display->hpd_state;

-   if (state == ST_DISPLAY_OFF)
+   if (state == ST_DISPLAY_OFF) {
 dp_display_host_phy_init(dp_display);
+   force_link_train = true;
+   }

-   dp_display_enable(dp_display, 0);
+   dp_display_enable(dp_display, force_link_train);

Do we need to pass it from here? Why can't dp_display_enable() simply
check for 'state == ST_DISPLAY_OFF' and then force retrain the link?


can we keep this as it is?

it is more readable that we do need force link re-training due to 
ST_DISPLAY_OFF at top level.


Also we only need to do (state == ST_DISPLAY_OFF) checking one time.



Re: [PATCH v6] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Kuogee Hsieh



On 6/14/2022 2:59 PM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-06-14 14:05:02)

Display resolution change is implemented through drm modeset. Older
modeset (resolution) has to be disabled first before newer modeset
(resolution) can be enabled. Display disable will turn off both
pixel clock and main link clock so that main link have to be
re-trained during display enable to have new video stream flow
again. At current implementation, display enable function manually
kicks up irq_hpd_handle which will read panel link status and start
link training if link status is not in sync state.

However, there is rare case that a particular panel links status keep
staying in sync for some period of time after main link had been shut
down previously at display disabled. In this case, main link retraining
will not be executed by irq_hdp_handle(). Hence video stream of newer
display resolution will fail to be transmitted to panel due to main
link is not in sync between host and panel.

This patch will bypass irq_hpd_hanle() in favor of directly call

s/hanle/handle/


dp_ctrl_on_stream() to always perform link training in regardless of
main link status. So that no unexpected exception resolution change
failure cases will happen. Also this implementation are more efficient
than manual kicking off irq_hpd_handle function.

Changes in v2:
-- set force_link_train flag on DP only (is_edp == false)

Changes in v3:
-- revise commit  text
-- add Fixes tag

Changes in v4:
-- revise commit  text

Changes in v5:
-- fix spelling at commit text

Changes in v6:
-- split dp_ctrl_on_stream() for phy test case
-- revise commit text for modeset

Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by failure of 
link train")
Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_ctrl.c| 31 +++
  drivers/gpu/drm/msm/dp/dp_ctrl.h|  3 ++-
  drivers/gpu/drm/msm/dp/dp_display.c | 13 ++---
  3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index af7a80c..cb9c7af 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1807,7 +1807,27 @@ static int dp_ctrl_link_retrain(struct dp_ctrl_private 
*ctrl)
 return dp_ctrl_setup_main_link(ctrl, _step);
  }

-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
+int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl)
+{
+   int ret = 0;

Drop assignment please.


+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+
+   ret = dp_ctrl_enable_stream_clocks(ctrl);
+   if (ret) {
+   DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
+   return ret;
+   }
+
+   dp_ctrl_send_phy_test_pattern(ctrl);

None of this code needs to be run in the normal display on case?


+   ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+
+   ret = dp_ctrl_enable_stream_clocks(ctrl);

These two lines are also used at normal display on case (dp_ctrl_on_stream()).
I have to copy them to here to form a stand alone 
dp_ctrl_on_stream_phy_test_report().


+
+   return 0;
+}
+
+int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
  {
 int ret = 0;
 bool mainlink_ready = false;
@@ -1843,12 +1863,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
 goto end;
 }

-   if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
-   dp_ctrl_send_phy_test_pattern(ctrl);
-   return 0;
-   }
-
-   if (!dp_ctrl_channel_eq_ok(ctrl))
+   if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))
 dp_ctrl_link_retrain(ctrl);

 /* stop txing train pattern to end link training */
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c388323..b6d25ab 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1688,10 +1689,12 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)

 state =  dp_display->hpd_state;

-   if (state == ST_DISPLAY_OFF)
+   if (state == ST_DISPLAY_OFF) {
 dp_display_host_phy_init(dp_display);
+   force_link_train = true;
+   }

-   dp_display_enable(dp_display, 0);
+   dp_display_enable(dp_display, force_link_train);

Do we need to pass it from here? Why can't dp_display_enable() simply
check for 'state == ST_DISPLAY_OFF' and then force retrain the link?


Re: [PATCH v6] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Stephen Boyd
Quoting Kuogee Hsieh (2022-06-14 14:05:02)
> Display resolution change is implemented through drm modeset. Older
> modeset (resolution) has to be disabled first before newer modeset
> (resolution) can be enabled. Display disable will turn off both
> pixel clock and main link clock so that main link have to be
> re-trained during display enable to have new video stream flow
> again. At current implementation, display enable function manually
> kicks up irq_hpd_handle which will read panel link status and start
> link training if link status is not in sync state.
>
> However, there is rare case that a particular panel links status keep
> staying in sync for some period of time after main link had been shut
> down previously at display disabled. In this case, main link retraining
> will not be executed by irq_hdp_handle(). Hence video stream of newer
> display resolution will fail to be transmitted to panel due to main
> link is not in sync between host and panel.
>
> This patch will bypass irq_hpd_hanle() in favor of directly call

s/hanle/handle/

> dp_ctrl_on_stream() to always perform link training in regardless of
> main link status. So that no unexpected exception resolution change
> failure cases will happen. Also this implementation are more efficient
> than manual kicking off irq_hpd_handle function.
>
> Changes in v2:
> -- set force_link_train flag on DP only (is_edp == false)
>
> Changes in v3:
> -- revise commit  text
> -- add Fixes tag
>
> Changes in v4:
> -- revise commit  text
>
> Changes in v5:
> -- fix spelling at commit text
>
> Changes in v6:
> -- split dp_ctrl_on_stream() for phy test case
> -- revise commit text for modeset
>
> Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by 
> failure of link train")
> Signed-off-by: Kuogee Hsieh 
> ---
>  drivers/gpu/drm/msm/dp/dp_ctrl.c| 31 +++
>  drivers/gpu/drm/msm/dp/dp_ctrl.h|  3 ++-
>  drivers/gpu/drm/msm/dp/dp_display.c | 13 ++---
>  3 files changed, 31 insertions(+), 16 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c 
> b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> index af7a80c..cb9c7af 100644
> --- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
> +++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
> @@ -1807,7 +1807,27 @@ static int dp_ctrl_link_retrain(struct dp_ctrl_private 
> *ctrl)
> return dp_ctrl_setup_main_link(ctrl, _step);
>  }
>
> -int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
> +int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl)
> +{
> +   int ret = 0;

Drop assignment please.

> +   struct dp_ctrl_private *ctrl;
> +
> +   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
> +
> +   ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
> +
> +   ret = dp_ctrl_enable_stream_clocks(ctrl);
> +   if (ret) {
> +   DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
> +   return ret;
> +   }
> +
> +   dp_ctrl_send_phy_test_pattern(ctrl);

None of this code needs to be run in the normal display on case?

> +
> +   return 0;
> +}
> +
> +int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
>  {
> int ret = 0;
> bool mainlink_ready = false;
> @@ -1843,12 +1863,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
> goto end;
> }
>
> -   if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
> -   dp_ctrl_send_phy_test_pattern(ctrl);
> -   return 0;
> -   }
> -
> -   if (!dp_ctrl_channel_eq_ok(ctrl))
> +   if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))
> dp_ctrl_link_retrain(ctrl);
>
> /* stop txing train pattern to end link training */
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index c388323..b6d25ab 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -1688,10 +1689,12 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
>
> state =  dp_display->hpd_state;
>
> -   if (state == ST_DISPLAY_OFF)
> +   if (state == ST_DISPLAY_OFF) {
> dp_display_host_phy_init(dp_display);
> +   force_link_train = true;
> +   }
>
> -   dp_display_enable(dp_display, 0);
> +   dp_display_enable(dp_display, force_link_train);

Do we need to pass it from here? Why can't dp_display_enable() simply
check for 'state == ST_DISPLAY_OFF' and then force retrain the link?


Re: [PATCH v3 2/4] drm/panel-edp: Take advantage of wait_hpd_asserted() in struct drm_dp_aux

2022-06-14 Thread Doug Anderson
Hi,

On Thu, Jun 2, 2022 at 8:12 AM Dmitry Baryshkov
 wrote:
>
> On 18/04/2022 20:17, Douglas Anderson wrote:
> > Let's add support for being able to read the HPD pin even if it's
> > hooked directly to the controller. This will allow us to get more
> > accurate delays also lets us take away the waiting in the AUX transfer
> > functions of the eDP controller drivers.
> >
> > Signed-off-by: Douglas Anderson 
>
> Reviewed-by: Dmitry Baryshkov 
>
> > ---
> >
> > (no changes since v2)
> >
> > Changes in v2:
> > - Change is_hpd_asserted() to wait_hpd_asserted()
> >
> >   drivers/gpu/drm/panel/panel-edp.c | 33 +--
> >   1 file changed, 23 insertions(+), 10 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/panel/panel-edp.c 
> > b/drivers/gpu/drm/panel/panel-edp.c
> > index 1732b4f56e38..086e0bf52fb9 100644
> > --- a/drivers/gpu/drm/panel/panel-edp.c
> > +++ b/drivers/gpu/drm/panel/panel-edp.c
> > @@ -417,6 +417,11 @@ static int panel_edp_get_hpd_gpio(struct device *dev, 
> > struct panel_edp *p)
> >   return 0;
> >   }
> >
> > +static bool panel_edp_can_read_hpd(struct panel_edp *p)
> > +{
> > + return !p->no_hpd && (p->hpd_gpio || (p->aux && 
> > p->aux->wait_hpd_asserted));
> > +}
> > +
> >   static int panel_edp_prepare_once(struct panel_edp *p)
> >   {
> >   struct device *dev = p->base.dev;
> > @@ -441,17 +446,21 @@ static int panel_edp_prepare_once(struct panel_edp *p)
> >   if (delay)
> >   msleep(delay);
> >
> > - if (p->hpd_gpio) {
> > + if (panel_edp_can_read_hpd(p)) {
> >   if (p->desc->delay.hpd_absent)
> >   hpd_wait_us = p->desc->delay.hpd_absent * 1000UL;
> >   else
> >   hpd_wait_us = 200;
> >
> > - err = readx_poll_timeout(gpiod_get_value_cansleep, 
> > p->hpd_gpio,
> > -  hpd_asserted, hpd_asserted,
> > -  1000, hpd_wait_us);
> > - if (hpd_asserted < 0)
> > - err = hpd_asserted;
> > + if (p->hpd_gpio) {
> > + err = readx_poll_timeout(gpiod_get_value_cansleep,
> > +  p->hpd_gpio, hpd_asserted,
> > +  hpd_asserted, 1000, 
> > hpd_wait_us);
> > + if (hpd_asserted < 0)
> > + err = hpd_asserted;
> > + } else {
> > + err = p->aux->wait_hpd_asserted(p->aux, hpd_wait_us);
> > + }
>
> I'm close to thinking that this construct deserves a separate helper.

Just to close the loop: I didn't try to create a helper for v5. I'm
not completely convinced that this will be common. I would tend to
expect that having HPD handled by a GPIO is somewhat rare. It's also
fairly rare to have a panel that's not handled by the generic
panel-edp. We ended up with the GPIO on trogdor because of the weird
debouncing on sn85dsi86 and we ended up with one case of not using
edp-panel on trogdor because of the weird power sequencing of the
Samsung OLED panel that's on homestar.

I'd also note that the generic eDP panel has a special case for
"timeout" which we don't have on the Samsung panel to handle at least
one panel I found that sometimes simply didn't come up but then
_would_ come up on a retry...

That doesn't mean we couldn't abstract it out later, of course. ;-)

-Doug


-Doug


[PATCH v4 4/4] drm/bridge: parade-ps8640: Provide wait_hpd_asserted() in struct drm_dp_aux

2022-06-14 Thread Douglas Anderson
This implements the callback added by the patch ("drm/dp: Add
wait_hpd_asserted() callback to struct drm_dp_aux").

With this change and all the two "DP AUX Endpoint" drivers changed to
use wait_hpd_asserted(), we no longer need to have an long delay in
the AUX transfer function. It's up to the panel code to make sure that
the panel is powered now. If someone tried to call the aux transfer
function without making sure the panel is powered we'll just get a
normal transfer failure.

We'll still keep the wait for HPD in the pre_enable() function. Though
it's probably not actually needed there, this driver is used in the
old mode (pre-DP AUX Endpoints) and it may be important for those
cases. If nothing else, it shouldn't cause any big problems.

NOTE: When handling the timeout for HPD we start the timer _after_
we've runtime resumed the device. This is definitely important for the
panel on my homestar which comes up 170 ms after we start timing (the
panel specifies 200 ms max). It's a little unclear how much of this
extra time is due to some internal state machine in the parade
firmware vs. debouncing but it seems to work for the two test cases I
have to do it this way.

Signed-off-by: Douglas Anderson 
Reviewed-by: Dmitry Baryshkov 
---

Changes in v4:
- Add comment that caller powered up the panel.
- Mention in commit message debouncing vs. powering on timing.

Changes in v2:
- Change is_hpd_asserted() to wait_hpd_asserted()

 drivers/gpu/drm/bridge/parade-ps8640.c | 39 +-
 1 file changed, 26 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c 
b/drivers/gpu/drm/bridge/parade-ps8640.c
index ff4227f6d800..e880eee55822 100644
--- a/drivers/gpu/drm/bridge/parade-ps8640.c
+++ b/drivers/gpu/drm/bridge/parade-ps8640.c
@@ -168,23 +168,35 @@ static bool ps8640_of_panel_on_aux_bus(struct device *dev)
return true;
 }
 
-static int ps8640_ensure_hpd(struct ps8640 *ps_bridge)
+static int _ps8640_wait_hpd_asserted(struct ps8640 *ps_bridge, unsigned long 
wait_us)
 {
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
-   struct device *dev = _bridge->page[PAGE2_TOP_CNTL]->dev;
int status;
-   int ret;
 
/*
 * Apparently something about the firmware in the chip signals that
 * HPD goes high by reporting GPIO9 as high (even though HPD isn't
 * actually connected to GPIO9).
 */
-   ret = regmap_read_poll_timeout(map, PAGE2_GPIO_H, status,
-  status & PS_GPIO9, 20 * 1000, 200 * 
1000);
+   return regmap_read_poll_timeout(map, PAGE2_GPIO_H, status,
+   status & PS_GPIO9, wait_us / 10, 
wait_us);
+}
 
-   if (ret < 0)
-   dev_warn(dev, "HPD didn't go high: %d\n", ret);
+static int ps8640_wait_hpd_asserted(struct drm_dp_aux *aux, unsigned long 
wait_us)
+{
+   struct ps8640 *ps_bridge = aux_to_ps8640(aux);
+   struct device *dev = _bridge->page[PAGE0_DP_CNTL]->dev;
+   int ret;
+
+   /*
+* Note that this function is called by code that has already powered
+* the panel. We have to power ourselves up but we don't need to worry
+* about powering the panel.
+*/
+   pm_runtime_get_sync(dev);
+   ret = _ps8640_wait_hpd_asserted(ps_bridge, wait_us);
+   pm_runtime_mark_last_busy(dev);
+   pm_runtime_put_autosuspend(dev);
 
return ret;
 }
@@ -323,9 +335,7 @@ static ssize_t ps8640_aux_transfer(struct drm_dp_aux *aux,
int ret;
 
pm_runtime_get_sync(dev);
-   ret = ps8640_ensure_hpd(ps_bridge);
-   if (!ret)
-   ret = ps8640_aux_transfer_msg(aux, msg);
+   ret = ps8640_aux_transfer_msg(aux, msg);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
 
@@ -369,8 +379,8 @@ static int __maybe_unused ps8640_resume(struct device *dev)
 * Mystery 200 ms delay for the "MCU to be ready". It's unclear if
 * this is truly necessary since the MCU will already signal that
 * things are "good to go" by signaling HPD on "gpio 9". See
-* ps8640_ensure_hpd(). For now we'll keep this mystery delay just in
-* case.
+* _ps8640_wait_hpd_asserted(). For now we'll keep this mystery delay
+* just in case.
 */
msleep(200);
 
@@ -406,7 +416,9 @@ static void ps8640_pre_enable(struct drm_bridge *bridge)
int ret;
 
pm_runtime_get_sync(dev);
-   ps8640_ensure_hpd(ps_bridge);
+   ret = _ps8640_wait_hpd_asserted(ps_bridge, 200 * 1000);
+   if (ret < 0)
+   dev_warn(dev, "HPD didn't go high: %d\n", ret);
 
/*
 * The Manufacturer Command Set (MCS) is a device dependent interface
@@ -682,6 +694,7 @@ static int ps8640_probe(struct i2c_client *client)
ps_bridge->aux.name = "parade-ps8640-aux";
ps_bridge->aux.dev = dev;
ps_bridge->aux.transfer = 

[PATCH v4 3/4] drm/panel: atna33xc20: Take advantage of wait_hpd_asserted() in struct drm_dp_aux

2022-06-14 Thread Douglas Anderson
Let's add support for being able to read the HPD pin even if it's
hooked directly to the controller. This will let us take away the
waiting in the AUX transfer functions of the eDP controller drivers.

Signed-off-by: Douglas Anderson 
---

Changes in v4:
- Reorganized logic as per Dmitry's suggestion.

Changes in v3:
- Don't check "hpd_asserted" boolean when unset.
- Handle errors from gpiod_get_value_cansleep() properly.

Changes in v2:
- Change is_hpd_asserted() to wait_hpd_asserted()

 .../gpu/drm/panel/panel-samsung-atna33xc20.c  | 51 ++-
 1 file changed, 38 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c 
b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
index 3dd10412d147..5a8b978c6415 100644
--- a/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
+++ b/drivers/gpu/drm/panel/panel-samsung-atna33xc20.c
@@ -19,6 +19,10 @@
 #include 
 #include 
 
+/* T3 VCC to HPD high is max 200 ms */
+#define HPD_MAX_MS 200
+#define HPD_MAX_US (HPD_MAX_MS * 1000)
+
 struct atana33xc20_panel {
struct drm_panel base;
bool prepared;
@@ -30,6 +34,7 @@ struct atana33xc20_panel {
 
struct regulator *supply;
struct gpio_desc *el_on3_gpio;
+   struct drm_dp_aux *aux;
 
struct edid *edid;
 
@@ -79,7 +84,7 @@ static int atana33xc20_suspend(struct device *dev)
 static int atana33xc20_resume(struct device *dev)
 {
struct atana33xc20_panel *p = dev_get_drvdata(dev);
-   bool hpd_asserted = false;
+   int hpd_asserted;
int ret;
 
/* T12 (Power off time) is min 500 ms */
@@ -90,23 +95,41 @@ static int atana33xc20_resume(struct device *dev)
return ret;
p->powered_on_time = ktime_get();
 
-   /*
-* Handle HPD. Note: if HPD is hooked up to a dedicated pin on the
-* eDP controller then "no_hpd" will be false _and_ "hpd_gpio" will be
-* NULL. It's up to the controller driver to wait for HPD after
-* preparing the panel in that case.
-*/
if (p->no_hpd) {
-   /* T3 VCC to HPD high is max 200 ms */
-   msleep(200);
-   } else if (p->hpd_gpio) {
+   msleep(HPD_MAX_MS);
+   return 0;
+   }
+
+   if (p->hpd_gpio) {
ret = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio,
 hpd_asserted, hpd_asserted,
-1000, 20);
-   if (!hpd_asserted)
-   dev_warn(dev, "Timeout waiting for HPD\n");
+1000, HPD_MAX_US);
+   if (hpd_asserted < 0)
+   ret = hpd_asserted;
+
+   if (ret)
+   dev_warn(dev, "Error waiting for HPD GPIO: %d\n", ret);
+
+   return ret;
}
 
+   if (p->aux->wait_hpd_asserted) {
+   ret = p->aux->wait_hpd_asserted(p->aux, HPD_MAX_US);
+
+   if (ret)
+   dev_warn(dev, "Controller error waiting for HPD: %d\n", 
ret);
+
+   return ret;
+   }
+
+   /*
+* Note that it's possible that no_hpd is false, hpd_gpio is
+* NULL, and wait_hpd_asserted is NULL. This is because
+* wait_hpd_asserted() is optional even if HPD is hooked up to
+* a dedicated pin on the eDP controller. In this case we just
+* assume that the controller driver will wait for HPD at the
+* right times.
+*/
return 0;
 }
 
@@ -263,6 +286,8 @@ static int atana33xc20_probe(struct dp_aux_ep_device 
*aux_ep)
return -ENOMEM;
dev_set_drvdata(dev, panel);
 
+   panel->aux = aux_ep->aux;
+
panel->supply = devm_regulator_get(dev, "power");
if (IS_ERR(panel->supply))
return dev_err_probe(dev, PTR_ERR(panel->supply),
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v4 2/4] drm/panel-edp: Take advantage of wait_hpd_asserted() in struct drm_dp_aux

2022-06-14 Thread Douglas Anderson
Let's add support for being able to read the HPD pin even if it's
hooked directly to the controller. This will allow us to get more
accurate delays also lets us take away the waiting in the AUX transfer
functions of the eDP controller drivers.

Signed-off-by: Douglas Anderson 
Reviewed-by: Dmitry Baryshkov 
---

(no changes since v2)

Changes in v2:
- Change is_hpd_asserted() to wait_hpd_asserted()

 drivers/gpu/drm/panel/panel-edp.c | 33 +--
 1 file changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/panel/panel-edp.c 
b/drivers/gpu/drm/panel/panel-edp.c
index c96014464355..ce5821132151 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -417,6 +417,11 @@ static int panel_edp_get_hpd_gpio(struct device *dev, 
struct panel_edp *p)
return 0;
 }
 
+static bool panel_edp_can_read_hpd(struct panel_edp *p)
+{
+   return !p->no_hpd && (p->hpd_gpio || (p->aux && 
p->aux->wait_hpd_asserted));
+}
+
 static int panel_edp_prepare_once(struct panel_edp *p)
 {
struct device *dev = p->base.dev;
@@ -441,17 +446,21 @@ static int panel_edp_prepare_once(struct panel_edp *p)
if (delay)
msleep(delay);
 
-   if (p->hpd_gpio) {
+   if (panel_edp_can_read_hpd(p)) {
if (p->desc->delay.hpd_absent)
hpd_wait_us = p->desc->delay.hpd_absent * 1000UL;
else
hpd_wait_us = 200;
 
-   err = readx_poll_timeout(gpiod_get_value_cansleep, p->hpd_gpio,
-hpd_asserted, hpd_asserted,
-1000, hpd_wait_us);
-   if (hpd_asserted < 0)
-   err = hpd_asserted;
+   if (p->hpd_gpio) {
+   err = readx_poll_timeout(gpiod_get_value_cansleep,
+p->hpd_gpio, hpd_asserted,
+hpd_asserted, 1000, 
hpd_wait_us);
+   if (hpd_asserted < 0)
+   err = hpd_asserted;
+   } else {
+   err = p->aux->wait_hpd_asserted(p->aux, hpd_wait_us);
+   }
 
if (err) {
if (err != -ETIMEDOUT)
@@ -532,18 +541,22 @@ static int panel_edp_enable(struct drm_panel *panel)
/*
 * If there is a "prepare_to_enable" delay then that's supposed to be
 * the delay from HPD going high until we can turn the backlight on.
-* However, we can only count this if HPD is handled by the panel
-* driver, not if it goes to a dedicated pin on the controller.
+* However, we can only count this if HPD is readable by the panel
+* driver.
+*
 * If we aren't handling the HPD pin ourselves then the best we
 * can do is assume that HPD went high immediately before we were
-* called (and link training took zero time).
+* called (and link training took zero time). Note that "no-hpd"
+* actually counts as handling HPD ourselves since we're doing the
+* worst case delay (in prepare) ourselves.
 *
 * NOTE: if we ever end up in this "if" statement then we're
 * guaranteed that the panel_edp_wait() call below will do no delay.
 * It already handles that case, though, so we don't need any special
 * code for it.
 */
-   if (p->desc->delay.prepare_to_enable && !p->hpd_gpio && !p->no_hpd)
+   if (p->desc->delay.prepare_to_enable &&
+   !panel_edp_can_read_hpd(p) && !p->no_hpd)
delay = max(delay, p->desc->delay.prepare_to_enable);
 
if (delay)
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v4 0/4] drm/dp: Introduce wait_hpd_asserted() for the DP AUX bus

2022-06-14 Thread Douglas Anderson
This is the 2nd four patches from my RFC series ("drm/dp: Improvements
for DP AUX channel") [1]. I've broken the series in two so we can make
progress on the two halves separately.

v2 of this series changes to add wait_hpd_asserted() instead of
is_hpd_asserted(). This allows us to move the extra delay needed for
ps8640 into the ps8640 driver itself.

The idea for this series came up during the review process of
Sankeerth's series trying to add eDP for Qualcomm SoCs [2].

This _doesn't_ attempt to fix the Analogix driver. If this works out,
ideally someone can post a patch up to do that.

[1] https://lore.kernel.org/r/20220409023628.2104952-1-diand...@chromium.org/
[2] 
https://lore.kernel.org/r/1648656179-10347-2-git-send-email-quic_sbill...@quicinc.com/

Changes in v4:
- Add comment that caller powered up the panel.
- Comments now explain that we may wait longer due to debouncing.
- Mention in commit message debouncing vs. powering on timing.
- Rebased to handle the fact that the stuct moved files.
- Reorganized logic as per Dmitry's suggestion.

Changes in v3:
- Don't check "hpd_asserted" boolean when unset.
- Handle errors from gpiod_get_value_cansleep() properly.

Changes in v2:
- Change is_hpd_asserted() to wait_hpd_asserted()

Douglas Anderson (4):
  drm/dp: Add wait_hpd_asserted() callback to struct drm_dp_aux
  drm/panel-edp: Take advantage of wait_hpd_asserted() in struct
drm_dp_aux
  drm/panel: atna33xc20: Take advantage of wait_hpd_asserted() in struct
drm_dp_aux
  drm/bridge: parade-ps8640: Provide wait_hpd_asserted() in struct
drm_dp_aux

 drivers/gpu/drm/bridge/parade-ps8640.c| 39 +-
 drivers/gpu/drm/panel/panel-edp.c | 33 
 .../gpu/drm/panel/panel-samsung-atna33xc20.c  | 51 ++-
 include/drm/display/drm_dp_helper.h   | 30 +++
 4 files changed, 117 insertions(+), 36 deletions(-)

-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v4 1/4] drm/dp: Add wait_hpd_asserted() callback to struct drm_dp_aux

2022-06-14 Thread Douglas Anderson
Sometimes it's useful for users of the DP AUX bus (like panels) to be
able to poll HPD. Let's add a callback that allows DP AUX busses
drivers to provide this.

Suggested-by: Dmitry Baryshkov 
Signed-off-by: Douglas Anderson 
Reviewed-by: Dmitry Baryshkov 
---

Changes in v4:
- Comments now explain that we may wait longer due to debouncing.
- Rebased to handle the fact that the stuct moved files.

Changes in v2:
- Change is_hpd_asserted() to wait_hpd_asserted()

 include/drm/display/drm_dp_helper.h | 30 +
 1 file changed, 30 insertions(+)

diff --git a/include/drm/display/drm_dp_helper.h 
b/include/drm/display/drm_dp_helper.h
index c5f8f45511ed..db0fe9f8a612 100644
--- a/include/drm/display/drm_dp_helper.h
+++ b/include/drm/display/drm_dp_helper.h
@@ -389,6 +389,36 @@ struct drm_dp_aux {
ssize_t (*transfer)(struct drm_dp_aux *aux,
struct drm_dp_aux_msg *msg);
 
+   /**
+* @wait_hpd_asserted: wait for HPD to be asserted
+*
+* This is mainly useful for eDP panels drivers to wait for an eDP
+* panel to finish powering on. This is an optional function.
+*
+* This function will efficiently wait for the HPD signal to be
+* asserted. The `wait_us` parameter that is passed in says that we
+* know that the HPD signal is expected to be asserted within `wait_us`
+* microseconds. This function could wait for longer than `wait_us` if
+* the logic in the DP controller has a long debouncing time. The
+* important thing is that if this function returns success that the
+* DP controller is ready to send AUX transactions.
+*
+* This function returns 0 if HPD was asserted or -ETIMEDOUT if time
+* expired and HPD wasn't asserted. This function should not print
+* timeout errors to the log.
+*
+* The semantics of this function are designed to match the
+* readx_poll_timeout() function. That means a `wait_us` of 0 means
+* to wait forever. Like readx_poll_timeout(), this function may sleep.
+*
+* NOTE: this function specifically reports the state of the HPD pin
+* that's associated with the DP AUX channel. This is different from
+* the HPD concept in much of the rest of DRM which is more about
+* physical presence of a display. For eDP, for instance, a display is
+* assumed always present even if the HPD pin is deasserted.
+*/
+   int (*wait_hpd_asserted)(struct drm_dp_aux *aux, unsigned long wait_us);
+
/**
 * @i2c_nack_count: Counts I2C NACKs, used for DP validation.
 */
-- 
2.36.1.476.g0c4daa206d-goog



RE: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design document

2022-06-14 Thread Zeng, Oak


Thanks,
Oak

> -Original Message-
> From: dri-devel  On Behalf Of
> Zeng, Oak
> Sent: June 14, 2022 5:13 PM
> To: Vishwanathapura, Niranjana ;
> Landwerlin, Lionel G 
> Cc: Intel GFX ; Wilson, Chris P
> ; Hellstrom, Thomas
> ; Maling list - DRI developers  de...@lists.freedesktop.org>; Vetter, Daniel ;
> Christian König 
> Subject: RE: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design
> document
> 
> 
> 
> Thanks,
> Oak
> 
> > -Original Message-
> > From: Vishwanathapura, Niranjana 
> > Sent: June 14, 2022 1:02 PM
> > To: Landwerlin, Lionel G 
> > Cc: Zeng, Oak ; Intel GFX  > g...@lists.freedesktop.org>; Maling list - DRI developers  > de...@lists.freedesktop.org>; Hellstrom, Thomas
> > ; Wilson, Chris P
> ;
> > Vetter, Daniel ; Christian König
> > 
> > Subject: Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design
> > document
> >
> > On Tue, Jun 14, 2022 at 10:04:00AM +0300, Lionel Landwerlin wrote:
> > >On 13/06/2022 21:02, Niranjana Vishwanathapura wrote:
> > >>On Mon, Jun 13, 2022 at 06:33:07AM -0700, Zeng, Oak wrote:
> > >>>
> > >>>
> > >>>Regards,
> > >>>Oak
> > >>>
> > -Original Message-
> > From: Intel-gfx  On
> > Behalf Of Niranjana
> > Vishwanathapura
> > Sent: June 10, 2022 1:43 PM
> > To: Landwerlin, Lionel G 
> > Cc: Intel GFX ; Maling list -
> > DRI developers  > de...@lists.freedesktop.org>; Hellstrom, Thomas
> > ;
> > Wilson, Chris P ; Vetter, Daniel
> > ; Christian König
> > 
> > Subject: Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND
> > feature design
> > document
> > 
> > On Fri, Jun 10, 2022 at 11:18:14AM +0300, Lionel Landwerlin wrote:
> > >On 10/06/2022 10:54, Niranjana Vishwanathapura wrote:
> > >>On Fri, Jun 10, 2022 at 09:53:24AM +0300, Lionel Landwerlin wrote:
> > >>>On 09/06/2022 22:31, Niranjana Vishwanathapura wrote:
> > On Thu, Jun 09, 2022 at 05:49:09PM +0300, Lionel Landwerlin
> wrote:
> > >  On 09/06/2022 00:55, Jason Ekstrand wrote:
> > >
> > >    On Wed, Jun 8, 2022 at 4:44 PM Niranjana Vishwanathapura
> > >  wrote:
> > >
> > >  On Wed, Jun 08, 2022 at 08:33:25AM +0100, Tvrtko
> > Ursulin wrote:
> > >  >
> > >  >
> > >  >On 07/06/2022 22:32, Niranjana Vishwanathapura wrote:
> > >  >>On Tue, Jun 07, 2022 at 11:18:11AM -0700, Niranjana
> > >Vishwanathapura
> > >  wrote:
> > >  >>>On Tue, Jun 07, 2022 at 12:12:03PM -0500, Jason
> > >Ekstrand wrote:
> > >   On Fri, Jun 3, 2022 at 6:52 PM Niranjana
> > Vishwanathapura
> > >    wrote:
> > >  
> > >     On Fri, Jun 03, 2022 at 10:20:25AM +0300, Lionel
> > >Landwerlin
> > >  wrote:
> > >     >   On 02/06/2022 23:35, Jason Ekstrand wrote:
> > >     >
> > >     > On Thu, Jun 2, 2022 at 3:11 PM Niranjana
> > >Vishwanathapura
> > >     >  wrote:
> > >     >
> > >     >   On Wed, Jun 01, 2022 at 01:28:36PM
> > -0700, Matthew
> > >  Brost wrote:
> > >     >   >On Wed, Jun 01, 2022 at 05:25:49PM
> > +0300, Lionel
> > >  Landwerlin
> > >     wrote:
> > >     > >> On 17/05/2022 21:32, Niranjana
> Vishwanathapura
> > >  wrote:
> > >     > >> > +VM_BIND/UNBIND ioctl will immediately start
> > >     binding/unbinding
> > >     >   the mapping in an
> > >     > >> > +async worker. The binding and
> > >unbinding will
> > >  work like a
> > >     special
> > >     >   GPU engine.
> > >     > >> > +The binding and unbinding operations are
> > >  serialized and
> > >     will
> > >     >   wait on specified
> > >     > >> > +input fences before the operation
> > >and will signal
> > >  the
> > >     output
> > >     >   fences upon the
> > >     > >> > +completion of the operation. Due to
> > >  serialization,
> > >     completion of
> > >     >   an operation
> > >     > >> > +will also indicate that all
> > >previous operations
> > >  are also
> > >     > complete.
> > >     > >>
> > >     > >> I guess we should avoid saying "will
> > >immediately
> > >  start
> > >     > binding/unbinding" if
> > >     > >> there are fences involved.
> > >     > >>
> > >     > >> And the fact 

[PATCH v2 3/3] drm/msm/dpu: Add interface support for CRC debugfs

2022-06-14 Thread Jessica Zhang
Add support for writing CRC values for the interface block to
the debugfs by calling the necessary MISR setup/collect methods.

Changes since V1:
- Set values_cnt to only include phys with backing hw_intf
- Loop over all drm_encs connected to crtc

Signed-off-by: Jessica Zhang 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 49 ++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  3 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 64 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h | 22 +++
 4 files changed, 134 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index 16742a66878e..8c9933b2337f 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -79,6 +79,8 @@ static enum dpu_crtc_crc_source 
dpu_crtc_parse_crc_source(const char *src_name)
if (!strcmp(src_name, "auto") ||
!strcmp(src_name, "lm"))
return DPU_CRTC_CRC_SOURCE_LAYER_MIXER;
+   if (!strcmp(src_name, "intf"))
+   return DPU_CRTC_CRC_SOURCE_INTF;
 
return DPU_CRTC_CRC_SOURCE_INVALID;
 }
@@ -99,8 +101,14 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc,
return -EINVAL;
}
 
-   if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+   if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER) {
*values_cnt = crtc_state->num_mixers;
+   } else if (source == DPU_CRTC_CRC_SOURCE_INTF) {
+   struct drm_encoder *drm_enc;
+
+   drm_for_each_encoder_mask(drm_enc, crtc->dev, 
crtc->state->encoder_mask)
+   *values_cnt += dpu_encoder_get_num_phys(drm_enc);
+   }
 
crtc_state->crcs = kcalloc(*values_cnt, sizeof(crtc_state->crcs), 
GFP_KERNEL);
 
@@ -123,6 +131,14 @@ static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state 
*crtc_state)
}
 }
 
+static void dpu_crtc_setup_encoder_misr(struct drm_crtc *crtc)
+{
+   struct drm_encoder *drm_enc;
+
+   drm_for_each_encoder_mask(drm_enc, crtc->dev, crtc->state->encoder_mask)
+   dpu_encoder_setup_misr(drm_enc);
+}
+
 static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 {
enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
@@ -175,6 +191,8 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
 
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
dpu_crtc_setup_lm_misr(crtc_state);
+   else if (source == DPU_CRTC_CRC_SOURCE_INTF)
+   dpu_crtc_setup_encoder_misr(crtc);
 
 cleanup:
drm_modeset_unlock(>mutex);
@@ -220,11 +238,31 @@ static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, 
struct dpu_crtc_state *crt
drm_crtc_accurate_vblank_count(crtc), crtc_state->crcs);
 }
 
-static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+static int dpu_crtc_get_encoder_crc(struct drm_crtc *crtc)
 {
-   struct dpu_crtc_state *crtc_state;
+   struct drm_encoder *drm_enc;
+   struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
+   int rc, pos = 0;
 
-   crtc_state = to_dpu_crtc_state(crtc->state);
+   drm_for_each_encoder_mask(drm_enc, crtc->dev, 
crtc->state->encoder_mask) {
+   rc = dpu_encoder_get_crc(drm_enc, crtc_state->crcs, pos);
+   if (rc < 0) {
+   if (rc != -ENODATA)
+   DRM_DEBUG_DRIVER("MISR read failed\n");
+
+   return rc;
+   }
+
+   pos += rc;
+   }
+
+   return drm_crtc_add_crc_entry(crtc, true,
+   drm_crtc_accurate_vblank_count(crtc), crtc_state->crcs);
+}
+
+static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+{
+   struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
 
/* Skip first 2 frames in case of "uncooked" CRCs */
if (crtc_state->crc_frame_skip_count < 2) {
@@ -235,6 +273,9 @@ static int dpu_crtc_get_crc(struct drm_crtc *crtc)
if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
return dpu_crtc_get_lm_crc(crtc, crtc_state);
 
+   if (crtc_state->crc_source == DPU_CRTC_CRC_SOURCE_INTF)
+   return dpu_crtc_get_encoder_crc(crtc);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 4bf45e3343ef..5db84ea796db 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -1,5 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2015-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
@@ -73,11 +74,13 @@ struct dpu_crtc_smmu_state_data {
  * enum dpu_crtc_crc_source: CRC source
  * 

[PATCH v2 2/3] drm/msm/dpu: Add MISR register support for interface

2022-06-14 Thread Jessica Zhang
Add support for setting MISR registers within the interface

Changes since V1:
- Replaced dpu_hw_intf collect_misr and setup_misr implementations with
  calls to dpu_hw_utils helper methods

Signed-off-by: Jessica Zhang 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c | 19 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h |  8 +++-
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
index 3f4d2c6e1b45..0157613224fd 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c
@@ -1,5 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
 #include "dpu_hwio.h"
@@ -67,6 +69,9 @@
 #define INTF_CFG2_DATABUS_WIDENBIT(0)
 #define INTF_CFG2_DATA_HCTL_EN BIT(4)
 
+#define INTF_MISR_CTRL 0x180
+#define INTF_MISR_SIGNATURE0x184
+
 static const struct dpu_intf_cfg *_intf_offset(enum dpu_intf intf,
const struct dpu_mdss_cfg *m,
void __iomem *addr,
@@ -319,6 +324,16 @@ static u32 dpu_hw_intf_get_line_count(struct dpu_hw_intf 
*intf)
return DPU_REG_READ(c, INTF_LINE_COUNT);
 }
 
+static void dpu_hw_intf_setup_misr(struct dpu_hw_intf *intf, bool enable, u32 
frame_count)
+{
+   dpu_hw_setup_misr(>hw, enable, frame_count, INTF_MISR_CTRL);
+}
+
+static int dpu_hw_intf_collect_misr(struct dpu_hw_intf *intf, u32 *misr_value)
+{
+   return dpu_hw_collect_misr(>hw, misr_value, INTF_MISR_CTRL, 
INTF_MISR_SIGNATURE);
+}
+
 static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
unsigned long cap)
 {
@@ -329,6 +344,8 @@ static void _setup_intf_ops(struct dpu_hw_intf_ops *ops,
ops->get_line_count = dpu_hw_intf_get_line_count;
if (cap & BIT(DPU_INTF_INPUT_CTRL))
ops->bind_pingpong_blk = dpu_hw_intf_bind_pingpong_blk;
+   ops->setup_misr = dpu_hw_intf_setup_misr;
+   ops->collect_misr = dpu_hw_intf_collect_misr;
 }
 
 struct dpu_hw_intf *dpu_hw_intf_init(enum dpu_intf idx,
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
index 7b2d96ac61e8..8d0e7b509260 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h
@@ -1,5 +1,7 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
-/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+/*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _DPU_HW_INTF_H
@@ -57,6 +59,8 @@ struct intf_status {
  * @ get_line_count: reads current vertical line counter
  * @bind_pingpong_blk: enable/disable the connection with pingpong which will
  * feed pixels to this interface
+ * @setup_misr: enable/disable MISR
+ * @collect_misr: read MISR signature
  */
 struct dpu_hw_intf_ops {
void (*setup_timing_gen)(struct dpu_hw_intf *intf,
@@ -77,6 +81,8 @@ struct dpu_hw_intf_ops {
void (*bind_pingpong_blk)(struct dpu_hw_intf *intf,
bool enable,
const enum dpu_pingpong pp);
+   void (*setup_misr)(struct dpu_hw_intf *intf, bool enable, u32 
frame_count);
+   int (*collect_misr)(struct dpu_hw_intf *intf, u32 *misr_value);
 };
 
 struct dpu_hw_intf {
-- 
2.35.1



[PATCH v2 0/3] Expand CRC to support interface blocks

2022-06-14 Thread Jessica Zhang
Refactor existing CRC code for layer mixer and add CRC support for interface 
blocks

Changes since V1:
- Create helper methods for collect_misr and setup_misr in dpu_hw_util.c
- Move common bitmasks into dpu_hw_util.h
- Update copyrights
- Create a dynamically allocated crcs array in dpu_crtc_state
- Collect CRCs for all drm_encoders connected to the crtc

Jessica Zhang (3):
  drm/msm/dpu: Move LM CRC code into separate method
  drm/msm/dpu: Add MISR register support for interface
  drm/msm/dpu: Add interface support for CRC debugfs

 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 131 +++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|   7 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c |  63 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  22 
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.c |  19 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_intf.h |   8 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c   |  42 +--
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c |  46 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h |  16 +++
 9 files changed, 279 insertions(+), 75 deletions(-)

-- 
2.35.1



[PATCH v2 1/3] drm/msm/dpu: Move LM CRC code into separate method

2022-06-14 Thread Jessica Zhang
Move layer mixer-specific section of dpu_crtc_get_crc() into a separate
helper method. This way, we can make it easier to get CRCs from other HW
blocks by adding other get_crc helper methods.

Changes since V1:
- Moved common bitmasks to dpu_hw_util.h
- Moved common CRC methods to dpu_hw_util.c
- Updated copyrights
- Changed crcs array to a dynamically allocated array and added it as a
  member of crtc_state

Signed-off-by: Jessica Zhang 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 88 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  4 +
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_lm.c   | 42 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.c | 46 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_util.h | 16 
 5 files changed, 124 insertions(+), 72 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index b56f777dbd0e..16742a66878e 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark 
@@ -88,6 +89,11 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc *crtc,
enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
struct dpu_crtc_state *crtc_state = to_dpu_crtc_state(crtc->state);
 
+   if (crtc_state->crcs) {
+   kfree(crtc_state->crcs);
+   crtc_state->crcs = NULL;
+   }
+
if (source < 0) {
DRM_DEBUG_DRIVER("Invalid source %s for CRTC%d\n", src_name, 
crtc->index);
return -EINVAL;
@@ -96,20 +102,37 @@ static int dpu_crtc_verify_crc_source(struct drm_crtc 
*crtc,
if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
*values_cnt = crtc_state->num_mixers;
 
+   crtc_state->crcs = kcalloc(*values_cnt, sizeof(crtc_state->crcs), 
GFP_KERNEL);
+
return 0;
 }
 
+static void dpu_crtc_setup_lm_misr(struct dpu_crtc_state *crtc_state)
+{
+   struct dpu_crtc_mixer *m;
+   int i;
+
+   for (i = 0; i < crtc_state->num_mixers; ++i) {
+   m = _state->mixers[i];
+
+   if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
+   continue;
+
+   /* Calculate MISR over 1 frame */
+   m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
+   }
+}
+
 static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, const char *src_name)
 {
enum dpu_crtc_crc_source source = dpu_crtc_parse_crc_source(src_name);
enum dpu_crtc_crc_source current_source;
struct dpu_crtc_state *crtc_state;
struct drm_device *drm_dev = crtc->dev;
-   struct dpu_crtc_mixer *m;
 
bool was_enabled;
bool enable = false;
-   int i, ret = 0;
+   int ret = 0;
 
if (source < 0) {
DRM_DEBUG_DRIVER("Invalid CRC source %s for CRTC%d\n", 
src_name, crtc->index);
@@ -137,6 +160,10 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
goto cleanup;
 
} else if (was_enabled && !enable) {
+   if (crtc_state->crcs) {
+   kfree(crtc_state->crcs);
+   crtc_state->crcs = NULL;
+   }
drm_crtc_vblank_put(crtc);
}
 
@@ -146,16 +173,8 @@ static int dpu_crtc_set_crc_source(struct drm_crtc *crtc, 
const char *src_name)
 
crtc_state->crc_frame_skip_count = 0;
 
-   for (i = 0; i < crtc_state->num_mixers; ++i) {
-   m = _state->mixers[i];
-
-   if (!m->hw_lm || !m->hw_lm->ops.setup_misr)
-   continue;
-
-   /* Calculate MISR over 1 frame */
-   m->hw_lm->ops.setup_misr(m->hw_lm, true, 1);
-   }
-
+   if (source == DPU_CRTC_CRC_SOURCE_LAYER_MIXER)
+   dpu_crtc_setup_lm_misr(crtc_state);
 
 cleanup:
drm_modeset_unlock(>mutex);
@@ -174,34 +193,21 @@ static u32 dpu_crtc_get_vblank_counter(struct drm_crtc 
*crtc)
return dpu_encoder_get_vsync_count(encoder);
 }
 
-
-static int dpu_crtc_get_crc(struct drm_crtc *crtc)
+static int dpu_crtc_get_lm_crc(struct drm_crtc *crtc, struct dpu_crtc_state 
*crtc_state)
 {
-   struct dpu_crtc_state *crtc_state;
-   struct dpu_crtc_mixer *m;
-   u32 crcs[CRTC_DUAL_MIXERS];
+   struct dpu_crtc_mixer *lm;
 
-   int i = 0;
int rc = 0;
-
-   crtc_state = to_dpu_crtc_state(crtc->state);
-
-   BUILD_BUG_ON(ARRAY_SIZE(crcs) != ARRAY_SIZE(crtc_state->mixers));
-
-   /* Skip first 2 frames in case of "uncooked" CRCs */
-   if (crtc_state->crc_frame_skip_count < 2) {
-   crtc_state->crc_frame_skip_count++;
-   return 0;
-   }
+   int i;
 
for (i = 0; i 

RE: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design document

2022-06-14 Thread Zeng, Oak


Thanks,
Oak

> -Original Message-
> From: Vishwanathapura, Niranjana 
> Sent: June 14, 2022 1:02 PM
> To: Landwerlin, Lionel G 
> Cc: Zeng, Oak ; Intel GFX  g...@lists.freedesktop.org>; Maling list - DRI developers  de...@lists.freedesktop.org>; Hellstrom, Thomas
> ; Wilson, Chris P ;
> Vetter, Daniel ; Christian König
> 
> Subject: Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design
> document
> 
> On Tue, Jun 14, 2022 at 10:04:00AM +0300, Lionel Landwerlin wrote:
> >On 13/06/2022 21:02, Niranjana Vishwanathapura wrote:
> >>On Mon, Jun 13, 2022 at 06:33:07AM -0700, Zeng, Oak wrote:
> >>>
> >>>
> >>>Regards,
> >>>Oak
> >>>
> -Original Message-
> From: Intel-gfx  On
> Behalf Of Niranjana
> Vishwanathapura
> Sent: June 10, 2022 1:43 PM
> To: Landwerlin, Lionel G 
> Cc: Intel GFX ; Maling list -
> DRI developers  de...@lists.freedesktop.org>; Hellstrom, Thomas
> ;
> Wilson, Chris P ; Vetter, Daniel
> ; Christian König
> 
> Subject: Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND
> feature design
> document
> 
> On Fri, Jun 10, 2022 at 11:18:14AM +0300, Lionel Landwerlin wrote:
> >On 10/06/2022 10:54, Niranjana Vishwanathapura wrote:
> >>On Fri, Jun 10, 2022 at 09:53:24AM +0300, Lionel Landwerlin wrote:
> >>>On 09/06/2022 22:31, Niranjana Vishwanathapura wrote:
> On Thu, Jun 09, 2022 at 05:49:09PM +0300, Lionel Landwerlin wrote:
> >  On 09/06/2022 00:55, Jason Ekstrand wrote:
> >
> >    On Wed, Jun 8, 2022 at 4:44 PM Niranjana Vishwanathapura
> >  wrote:
> >
> >  On Wed, Jun 08, 2022 at 08:33:25AM +0100, Tvrtko
> Ursulin wrote:
> >  >
> >  >
> >  >On 07/06/2022 22:32, Niranjana Vishwanathapura wrote:
> >  >>On Tue, Jun 07, 2022 at 11:18:11AM -0700, Niranjana
> >Vishwanathapura
> >  wrote:
> >  >>>On Tue, Jun 07, 2022 at 12:12:03PM -0500, Jason
> >Ekstrand wrote:
> >   On Fri, Jun 3, 2022 at 6:52 PM Niranjana
> Vishwanathapura
> >    wrote:
> >  
> >     On Fri, Jun 03, 2022 at 10:20:25AM +0300, Lionel
> >Landwerlin
> >  wrote:
> >     >   On 02/06/2022 23:35, Jason Ekstrand wrote:
> >     >
> >     > On Thu, Jun 2, 2022 at 3:11 PM Niranjana
> >Vishwanathapura
> >     >  wrote:
> >     >
> >     >   On Wed, Jun 01, 2022 at 01:28:36PM
> -0700, Matthew
> >  Brost wrote:
> >     >   >On Wed, Jun 01, 2022 at 05:25:49PM
> +0300, Lionel
> >  Landwerlin
> >     wrote:
> >     > >> On 17/05/2022 21:32, Niranjana Vishwanathapura
> >  wrote:
> >     > >> > +VM_BIND/UNBIND ioctl will immediately start
> >     binding/unbinding
> >     >   the mapping in an
> >     > >> > +async worker. The binding and
> >unbinding will
> >  work like a
> >     special
> >     >   GPU engine.
> >     > >> > +The binding and unbinding operations are
> >  serialized and
> >     will
> >     >   wait on specified
> >     > >> > +input fences before the operation
> >and will signal
> >  the
> >     output
> >     >   fences upon the
> >     > >> > +completion of the operation. Due to
> >  serialization,
> >     completion of
> >     >   an operation
> >     > >> > +will also indicate that all
> >previous operations
> >  are also
> >     > complete.
> >     > >>
> >     > >> I guess we should avoid saying "will
> >immediately
> >  start
> >     > binding/unbinding" if
> >     > >> there are fences involved.
> >     > >>
> >     > >> And the fact that it's happening in an async
> >  worker seem to
> >     imply
> >     >   it's not
> >     > >> immediate.
> >     > >>
> >     >
> >     >   Ok, will fix.
> >     >   This was added because in earlier design
> >binding was
> >  deferred
> >     until
> >     >   next execbuff.
> >     >   But now it is non-deferred (immediate in
> >that sense).
> >  But yah,
> >     this is
> >     > 

Re: [PATCH] drm/arm/hdlcd: Take over EFI framebuffer properly

2022-06-14 Thread Robin Murphy

On 2022-06-14 14:48, Thomas Zimmermann wrote:

Hi

Am 14.06.22 um 15:04 schrieb Robin Murphy:

The Arm Juno board EDK2 port has provided an EFI GOP display via HDLCD0
for some time now, which works nicely as an early framebuffer. However,
once the HDLCD driver probes and takes over the hardware, it should
take over the logical framebuffer as well, otherwise the now-defunct GOP
device hangs about and virtual console output inevitably disappears into
the wrong place most of the time.

Signed-off-by: Robin Murphy 
---
  drivers/gpu/drm/arm/hdlcd_drv.c | 2 ++
  1 file changed, 2 insertions(+)

diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c 
b/drivers/gpu/drm/arm/hdlcd_drv.c

index af59077a5481..a5d04884658b 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -331,6 +331,8 @@ static int hdlcd_drm_bind(struct device *dev)
  goto err_vblank;
  }
+    drm_fb_helper_remove_conflicting_framebuffers(NULL, "hdlcd", false);
+


In addition to what Javier said, it appears to be too late to call this 
function. If anything her etouches hardware, you might accidentally 
interfere with the EFI-related driver. Rather call it at the top of 
ldlcd_drm_bind().


OK, thanks for the info. I mostly just copied the pattern from the 
simplest-looking other users (sun4i, tegra, vc4) who all seemed to call 
it fairly late, and indeed naively it seemed logical not to do it *too* 
early when there's more chance we might fail to bind and leave the user 
with no framebuffer at all. In particular, waiting until we've bound the 
HDMI encoder seems like a good idea in the case of the Juno board (which 
is the only real HDLCD user), as the I2C bus often gets stuck if the 
System Control Processor is having a bad day. I also don't believe 
there's anything here that would affect efifb more than the fact that 
once the DRM CRTC is alive we simply stop scanning out from the region 
of memory that efifb is managing, but if it's considered good practice 
to do this early then I can certainly make that change too.


Cheers,
Robin.


[PATCH v6] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Kuogee Hsieh
Display resolution change is implemented through drm modeset. Older
modeset (resolution) has to be disabled first before newer modeset
(resolution) can be enabled. Display disable will turn off both
pixel clock and main link clock so that main link have to be
re-trained during display enable to have new video stream flow
again. At current implementation, display enable function manually
kicks up irq_hpd_handle which will read panel link status and start
link training if link status is not in sync state.

However, there is rare case that a particular panel links status keep
staying in sync for some period of time after main link had been shut
down previously at display disabled. In this case, main link retraining
will not be executed by irq_hdp_handle(). Hence video stream of newer
display resolution will fail to be transmitted to panel due to main
link is not in sync between host and panel.

This patch will bypass irq_hpd_hanle() in favor of directly call
dp_ctrl_on_stream() to always perform link training in regardless of
main link status. So that no unexpected exception resolution change
failure cases will happen. Also this implementation are more efficient
than manual kicking off irq_hpd_handle function.

Changes in v2:
-- set force_link_train flag on DP only (is_edp == false)

Changes in v3:
-- revise commit  text
-- add Fixes tag

Changes in v4:
-- revise commit  text

Changes in v5:
-- fix spelling at commit text

Changes in v6:
-- split dp_ctrl_on_stream() for phy test case
-- revise commit text for modeset

Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by 
failure of link train")
Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 31 +++
 drivers/gpu/drm/msm/dp/dp_ctrl.h|  3 ++-
 drivers/gpu/drm/msm/dp/dp_display.c | 13 ++---
 3 files changed, 31 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index af7a80c..cb9c7af 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1551,7 +1551,7 @@ static int dp_ctrl_process_phy_test_request(struct 
dp_ctrl_private *ctrl)
 
ret = dp_ctrl_on_link(>dp_ctrl);
if (!ret)
-   ret = dp_ctrl_on_stream(>dp_ctrl);
+   ret = dp_ctrl_on_stream_phy_test_report(>dp_ctrl);
else
DRM_ERROR("failed to enable DP link controller\n");
 
@@ -1807,7 +1807,27 @@ static int dp_ctrl_link_retrain(struct dp_ctrl_private 
*ctrl)
return dp_ctrl_setup_main_link(ctrl, _step);
 }
 
-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
+int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl)
+{
+   int ret = 0;
+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   ctrl->dp_ctrl.pixel_rate = ctrl->panel->dp_mode.drm_mode.clock;
+
+   ret = dp_ctrl_enable_stream_clocks(ctrl);
+   if (ret) {
+   DRM_ERROR("Failed to start pixel clocks. ret=%d\n", ret);
+   return ret;
+   }
+
+   dp_ctrl_send_phy_test_pattern(ctrl);
+
+   return 0;
+}
+
+int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train)
 {
int ret = 0;
bool mainlink_ready = false;
@@ -1843,12 +1863,7 @@ int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl)
goto end;
}
 
-   if (ctrl->link->sink_request & DP_TEST_LINK_PHY_TEST_PATTERN) {
-   dp_ctrl_send_phy_test_pattern(ctrl);
-   return 0;
-   }
-
-   if (!dp_ctrl_channel_eq_ok(ctrl))
+   if (force_link_train || !dp_ctrl_channel_eq_ok(ctrl))
dp_ctrl_link_retrain(ctrl);
 
/* stop txing train pattern to end link training */
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 0745fde..9a39b00 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -21,7 +21,8 @@ struct dp_ctrl {
 };
 
 int dp_ctrl_on_link(struct dp_ctrl *dp_ctrl);
-int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl);
+int dp_ctrl_on_stream(struct dp_ctrl *dp_ctrl, bool force_link_train);
+int dp_ctrl_on_stream_phy_test_report(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_off_link(struct dp_ctrl *dp_ctrl);
 int dp_ctrl_off(struct dp_ctrl *dp_ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c388323..b6d25ab 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -872,7 +872,7 @@ static int dp_display_enable(struct dp_display_private *dp, 
u32 data)
return 0;
}
 
-   rc = dp_ctrl_on_stream(dp->ctrl);
+   rc = dp_ctrl_on_stream(dp->ctrl, data);
if (!rc)
dp_display->power_on = true;
 
@@ -1654,6 +1654,7 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
int rc = 0;
struct 

Re: [PATCH v3 4/7] dt-bindings: drm/bridge: anx7625: Add mode-switch support

2022-06-14 Thread Krzysztof Kozlowski
On 14/06/2022 12:34, Prashant Malani wrote:
> Analogix 7625 can be used in systems to switch USB Type-C DisplayPort
> alternate mode lane traffic between 2 Type-C ports.
> 
> Update the binding to accommodate this usage by introducing a switch
> property.
> 
> Reviewed-by: Nícolas F. R. A. Prado 
> Tested-by: Nícolas F. R. A. Prado 
> Signed-off-by: Prashant Malani 
> ---
> 
> Changes since v2:
> - Added Reviewed-by and Tested-by tags.
> 
> Changes since v1:
> - Introduced patternProperties for "switch" children (suggested by Krzysztof 
> Kozlowski).
> - Added unevaluatedProperties descriptor (suggested by Krzysztof Kozlowski).
> - Added "address-cells" and "size-cells" properties to "switches".
> 
>  .../display/bridge/analogix,anx7625.yaml  | 63 +++
>  1 file changed, 63 insertions(+)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml 
> b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> index 35a48515836e..cb4a23391244 100644
> --- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> +++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
> @@ -105,6 +105,33 @@ properties:
>- port@0
>- port@1
>  
> +  switches:
> +type: object
> +description: Set of switches controlling DisplayPort traffic on
> +  outgoing RX/TX lanes to Type C ports.
> +unevaluatedProperties: false

This should be additionalProperties:false.

> +
> +properties:
> +  "#address-cells":
> +const: 1
> +
> +  "#size-cells":
> +const: 0
> +
> +patternProperties:
> +  'switch@[01]':

You also need ^ and $. Please use the same quotes as in other places
(here is ' but few lines above ")

> +$ref: /schemas/usb/typec-switch.yaml#

You need unevaluatedProperties:false on this level.

> +
> +properties:
> +  reg:
> +maxItems: 1
> +
> +required:
> +  - reg
> +
> +required:
> +  - switch@0
> +


Best regards,
Krzysztof


Re: [PATCH v5] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Kuogee Hsieh



On 6/14/2022 1:38 AM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-06-13 14:48:37)

During display resolution changes display have to be disabled first
followed by display enabling with new resolution. Display disable
will turn off both pixel clock and main link clock so that main link
have to be re-trained during display enable to have new video stream
flow again. At current implementation, display enable function manually
kicks up irq_hpd_handle which will read panel link status and start link
training if link status is not in sync state. However, there is rare
case that a particular panel links status keep staying in sync for
some period of time after main link had been shut down previously at
display disabled. Main link retraining will not be executed by
irq_hdp_handle() if the link status read from panel shows it is in
sync state. If this was happen, then video stream of newer display
resolution will fail to be transmitted to panel due to main link is
not in sync between host and panel. This patch force main link always
be retrained during display enable procedure to prevent this rare
failed case from happening. Also this implementation are more
efficient than manual kicking off irq_hpd_handle function.

How is resolution change different from disabling and enabling the
display? The commit text talks about resolution changes, but the code
doesn't compare resolutions from before and after to know when to
retrain the link. Can the code be made to actually do what the commit
text says? It would be clearer if the code looked for actual resolution
changes instead of hooking the dp_bridge_enable() function.


Changes in v2:
-- set force_link_train flag on DP only (is_edp == false)

Changes in v3:
-- revise commit  text
-- add Fixes tag

Changes in v4:
-- revise commit  text

Changes in v5:
-- fix spelling at commit text

Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by failure of 
link train")
Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_ctrl.c|  6 +++---
  drivers/gpu/drm/msm/dp/dp_ctrl.h|  2 +-
  drivers/gpu/drm/msm/dp/dp_display.c | 15 ---
  3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index af7a80c..bea93eb 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1551,7 +1551,7 @@ static int dp_ctrl_process_phy_test_request(struct 
dp_ctrl_private *ctrl)

 ret = dp_ctrl_on_link(>dp_ctrl);
 if (!ret)
-   ret = dp_ctrl_on_stream(>dp_ctrl);
+   ret = dp_ctrl_on_stream(>dp_ctrl, false);

Does this even matter if it's true or false? The 'sink_request' has
DP_TEST_LINK_PHY_TEST_PATTERN set from what I can tell, and then
dp_ctrl_on_stream() bails out before calling dp_ctrl_link_retrain()
anyway. It would be nice if we could split dp_ctrl_on_stream() so that
the part after the check for the sink request is a different function
that is called by dp_display.c and then this code can call the 'prepare'
function that does the first part. Then we can ignore the testing path
in the code, and possibly remove the conditional in dp_ctrl_on_stream()?


 else
 DRM_ERROR("failed to enable DP link controller\n");

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c388323..370348d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -872,7 +872,7 @@ static int dp_display_enable(struct dp_display_private *dp, 
u32 data)
 return 0;
 }

-   rc = dp_ctrl_on_stream(dp->ctrl);
+   rc = dp_ctrl_on_stream(dp->ctrl, data);
 if (!rc)
 dp_display->power_on = true;

@@ -1654,6 +1654,7 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
 int rc = 0;
 struct dp_display_private *dp_display;
 u32 state;
+   bool force_link_train = false;

 dp_display = container_of(dp, struct dp_display_private, dp_display);
 if (!dp_display->dp_mode.drm_mode.clock) {
@@ -1688,10 +1689,14 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)

 state =  dp_display->hpd_state;

-   if (state == ST_DISPLAY_OFF)
+   if (state == ST_DISPLAY_OFF) {
 dp_display_host_phy_init(dp_display);

-   dp_display_enable(dp_display, 0);
+   if (!dp->is_edp)

I didn't see any answer to my question about why edp is special on v4.
Can you at least add a comment to the code about why edp doesn't need to
unconditionally retrain, but DP does?


Sorry, missed this one.

This is my mistake, both DP and eDP are same. will remove is_edp flag 
checking.





+   force_link_train = true;
+   }
+
+   dp_display_enable(dp_display, force_link_train);

 rc = dp_display_post_enable(dp);
 if (rc) {


Re: [PATCH v11 01/12] dt-bindings: mediatek,dpi: Add DP_INTF compatible

2022-06-14 Thread Rob Herring
On Mon, Jun 13, 2022 at 02:48:30PM +0800, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann 
> 
> DP_INTF is similar to DPI but does not have the exact same feature set
> or register layouts.
> 
> DP_INTF is the sink of the display pipeline that is connected to the
> DisplayPort controller and encoder unit. It takes the same clocks as
> DPI.
> 
> In this patch, we also do these string replacement:
> - s/mediatek/MediaTek/ in title.
> - s/Mediatek/MediaTek/ in description.
> 
> Signed-off-by: Markus Schneider-Pargmann 
> Signed-off-by: Guillaume Ranquet 
> Signed-off-by: Bo-Chen Chen 
> ---
>  .../bindings/display/mediatek/mediatek,dpi.yaml | 13 -
>  1 file changed, 8 insertions(+), 5 deletions(-)
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml 
> b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> index 77ee1b923991..ca1b48e78581 100644
> --- a/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dpi.yaml
> @@ -4,16 +4,16 @@
>  $id: http://devicetree.org/schemas/display/mediatek/mediatek,dpi.yaml#
>  $schema: http://devicetree.org/meta-schemas/core.yaml#
>  
> -title: mediatek DPI Controller Device Tree Bindings
> +title: MediaTek DPI and DP_INTF Controller
>  
>  maintainers:
>- CK Hu 
>- Jitao shi 
>  
>  description: |
> -  The Mediatek DPI function block is a sink of the display subsystem and
> -  provides 8-bit RGB/YUV444 or 8/10/10-bit YUV422 pixel data on a parallel
> -  output bus.
> +  The MediaTek DPI and DP_INTF function blocks are a sink of the display
> +  subsystem and provides 8-bit RGB/YUV444 or 8/10/10-bit YUV422 pixel data 
> on a
> +  parallel output bus.
>  
>  properties:
>compatible:
> @@ -24,6 +24,7 @@ properties:
>- mediatek,mt8183-dpi
>- mediatek,mt8186-dpi
>- mediatek,mt8192-dpi
> +  - mediatek,mt8195-dp_intf
>  
>reg:
>  maxItems: 1
> @@ -36,12 +37,14 @@ properties:
>- description: Pixel Clock
>- description: Engine Clock
>- description: DPI PLL
> +  - description: Clock gate for PLL
>  
>clock-names:
>  items:
>- const: pixel
>- const: engine
>- const: pll
> +  - const: pll_gate

You just added a new required clock for everyone.

>  
>pinctrl-0: true
>pinctrl-1: true
> @@ -55,7 +58,7 @@ properties:
>  $ref: /schemas/graph.yaml#/properties/port
>  description:
>Output port node. This port should be connected to the input port of an
> -  attached HDMI or LVDS encoder chip.
> +  attached HDMI, LVDS or DisplayPort encoder chip.
>  
>  required:
>- compatible
> -- 
> 2.18.0
> 
> 


Re: [PATCH v11 01/10] dt-bindings: mediatek,dp: Add Display Port binding

2022-06-14 Thread Rob Herring
On Fri, Jun 10, 2022 at 06:55:13PM +0800, Bo-Chen Chen wrote:
> From: Markus Schneider-Pargmann 
> 
> This controller is present on several mediatek hardware. Currently
> mt8195 and mt8395 have this controller without a functional difference,
> so only one compatible field is added.
> 
> The controller can have two forms, as a normal display port and as an
> embedded display port.
> 
> Signed-off-by: Markus Schneider-Pargmann 
> Signed-off-by: Guillaume Ranquet 
> [Bo-Chen: Fix reviewers' comment]
> Signed-off-by: Bo-Chen Chen 
> ---
>  .../display/mediatek/mediatek,dp.yaml | 101 ++
>  1 file changed, 101 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml 
> b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
> new file mode 100644
> index ..10f50a0dcf49
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/mediatek/mediatek,dp.yaml
> @@ -0,0 +1,101 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/mediatek/mediatek,dp.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: MediaTek Display Port Controller
> +
> +maintainers:
> +  - Chun-Kuang Hu 
> +  - Jitao shi 
> +
> +description: |
> +  Device tree bindings for the MediaTek display port and
> +  embedded display port controller present on some MediaTek SoCs.
> +
> +properties:
> +  compatible:
> +enum:
> +  - mediatek,mt8195-dp-tx
> +  - mediatek,mt8195-edp-tx
> +
> +  reg:
> +maxItems: 1
> +
> +  nvmem-cells:
> +maxItems: 1
> +description: efuse data for display port calibration
> +
> +  nvmem-cell-names:
> +const: dp_calibration_data
> +
> +  power-domains:
> +maxItems: 1
> +
> +  interrupts:
> +maxItems: 1
> +
> +  ports:
> +$ref: /schemas/graph.yaml#/properties/ports
> +properties:
> +  port@0:
> +$ref: /schemas/graph.yaml#/properties/port
> +description: Input endpoint of the controller, usually dp_intf
> +
> +  port@1:
> +$ref: /schemas/graph.yaml#/properties/port
> +description: Output endpoint of the controller
> +
> +required:
> +  - port@0
> +  - port@1
> +
> +  max-lanes:
> +maxItems: 1
> +description: maximum number of lanes supported by the hardware.

We already have a 'data-lanes' property defined in 
'video-interfaces.yaml' that can serve this purpose.

> +
> +  max-linkrate:
> +maxItems: 1
> +description: maximum link rate supported by the hardware and unit is MHz.

Then use '-mhz' suffix on the property name. Then you don't need a type 
(or maxItems).


Re: [PATCH v9 05/14] dt-bindings: display: bridge: Add i.MX8qm/qxp display pixel link binding

2022-06-14 Thread Rob Herring
On Sat, Jun 11, 2022 at 10:14:12PM +0800, Liu Ying wrote:
> This patch adds bindings for i.MX8qm/qxp display pixel link.
> 
> Signed-off-by: Liu Ying 
> ---
> v8->v9:
> * Add 'fsl,dc-id' and 'fsl,dc-stream-id' properties. (Laurent)

Why? Isn't the graph sufficient for determining the connections? That's 
what it is for.

> * Drop Rob's R-b tag.
> 
> v7->v8:
> * No change.
> 
> v6->v7:
> * No change.
> 
> v5->v6:
> * No change.
> 
> v4->v5:
> * No change.
> 
> v3->v4:
> * No change.
> 
> v2->v3:
> * Add Rob's R-b tag.
> 
> v1->v2:
> * Use graph schema. (Laurent)
> * Require all four pixel link output ports. (Laurent)
> * Mention pixel link is accessed via SCU firmware. (Rob)
> 
>  .../bridge/fsl,imx8qxp-pixel-link.yaml| 144 ++
>  1 file changed, 144 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml
> 
> diff --git 
> a/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml
>  
> b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml
> new file mode 100644
> index ..38ecc7926fad
> --- /dev/null
> +++ 
> b/Documentation/devicetree/bindings/display/bridge/fsl,imx8qxp-pixel-link.yaml
> @@ -0,0 +1,144 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: 
> http://devicetree.org/schemas/display/bridge/fsl,imx8qxp-pixel-link.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Freescale i.MX8qm/qxp Display Pixel Link
> +
> +maintainers:
> +  - Liu Ying 
> +
> +description: |
> +  The Freescale i.MX8qm/qxp Display Pixel Link(DPL) forms a standard
> +  asynchronous linkage between pixel sources(display controller or
> +  camera module) and pixel consumers(imaging or displays).
> +  It consists of two distinct functions, a pixel transfer function and a
> +  control interface.  Multiple pixel channels can exist per one control 
> channel.
> +  This binding documentation is only for pixel links whose pixel sources are
> +  display controllers.
> +
> +  The i.MX8qm/qxp Display Pixel Link is accessed via System Controller 
> Unit(SCU)
> +  firmware.
> +
> +properties:
> +  compatible:
> +enum:
> +  - fsl,imx8qm-dc-pixel-link
> +  - fsl,imx8qxp-dc-pixel-link
> +
> +  fsl,dc-id:
> +$ref: /schemas/types.yaml#/definitions/uint8
> +description: |
> +  u8 value representing the display controller index that the pixel link
> +  connects to.
> +
> +  fsl,dc-stream-id:
> +$ref: /schemas/types.yaml#/definitions/uint8
> +description: |
> +  u8 value representing the display controller stream index that the 
> pixel
> +  link connects to.
> +enum: [0, 1]
> +
> +  ports:
> +$ref: /schemas/graph.yaml#/properties/ports
> +
> +properties:
> +  port@0:
> +$ref: /schemas/graph.yaml#/properties/port
> +description: The pixel link input port node from upstream video 
> source.
> +
> +patternProperties:
> +  "^port@[1-4]$":
> +$ref: /schemas/graph.yaml#/properties/port
> +description: The pixel link output port node to downstream bridge.
> +
> +required:
> +  - port@0
> +  - port@1
> +  - port@2
> +  - port@3
> +  - port@4
> +
> +allOf:
> +  - if:
> +  properties:
> +compatible:
> +  contains:
> +const: fsl,imx8qxp-dc-pixel-link
> +then:
> +  properties:
> +fsl,dc-id:
> +  const: 0
> +
> +  - if:
> +  properties:
> +compatible:
> +  contains:
> +const: fsl,imx8qm-dc-pixel-link
> +then:
> +  properties:
> +fsl,dc-id:
> +  enum: [0, 1]
> +
> +required:
> +  - compatible
> +  - fsl,dc-id
> +  - fsl,dc-stream-id
> +  - ports
> +
> +additionalProperties: false
> +
> +examples:
> +  - |
> +dc0-pixel-link0 {
> +compatible = "fsl,imx8qxp-dc-pixel-link";
> +fsl,dc-id = /bits/ 8 <0>;
> +fsl,dc-stream-id = /bits/ 8 <0>;
> +
> +ports {
> +#address-cells = <1>;
> +#size-cells = <0>;
> +
> +/* from dc0 pixel combiner channel0 */
> +port@0 {
> +reg = <0>;
> +
> +dc0_pixel_link0_dc0_pixel_combiner_ch0: endpoint {
> +remote-endpoint = 
> <_pixel_combiner_ch0_dc0_pixel_link0>;

Isn't dc0 and link0 here the same information (if you get the port 
number from the remote end).

Rob


Re: [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Dixit, Ashutosh
On Tue, 14 Jun 2022 09:28:14 -0700, Dixit, Ashutosh wrote:
> On Thu, 02 Jun 2022 10:21:19 -0700, Zhanjun Dong wrote:
>
> > @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct 
> > ct_request *req, u32 *status)
> >  #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
> >  #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
> >  #define done \
> > -   (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> > +   (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> > READ_ONCE(req->status)) == \
> >  GUC_HXG_ORIGIN_GUC)
> > err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
> > if (err)
> > err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
> >  #undef done
> > +   if (!intel_guc_ct_enabled(ct))
> > +   err = -ECANCELED;
>
> Also, I really don't like intel_guc_ct_enabled() being called in two
> places. Is there a possibility that intel_guc_ct_enabled() can return false
> in the first place (causing the wait to exit) and then return true in the
> second place (so we don't return -ECANCELED)?
>
> Is it possible to change the status of the request to something else from
> intel_guc_ct_disable() (or wherever ct->enabled is set to false) rather
> than introducing intel_guc_ct_enabled() checks here. Changing the status of
> the request when CT goes down would cause the wait's to exit here. And then
> we can check that special request status signifying CT went down?

I think there are free bits in the request status fields which can be
used. But setting the request status say from intel_guc_ct_enabled() might
not be straightforward since you have to locate waiting requests and also
there may be multiple such requests (waiting in different threads).

Maybe an easier way might be to do something like:

bool foo(ct, req)
{
if (!intel_guc_ct_enabled(ct)) {
req->status = CT_WENT_AWAY;
return true;
}
return false;
}

Now in your patch we can substitute foo() instead of
!intel_guc_ct_enabled(ct) so that we have:

 #define done \
(foo() || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
 GUC_HXG_ORIGIN_GUC)

And then check for req->status == CT_WENT_AWAY (most likely in ct_send()).


[PATCH v3 7/7] drm/bridge: anx7625: Add typec_mux_set callback function

2022-06-14 Thread Prashant Malani
From: Pin-Yen Lin 

Add the callback function when the driver receives state
changes of the Type-C port. The callback function configures the
crosspoint switch of the anx7625 bridge chip, which can change the
output pins of the signals according to the port state.

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Pin-Yen Lin 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Moved num_typec_switches check to beginning of function
- Made dp_connected assignments fit on one line (and removed unnecessary
  parentheses)
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- No changes.

 drivers/gpu/drm/bridge/analogix/anx7625.c | 56 +++
 drivers/gpu/drm/bridge/analogix/anx7625.h | 13 ++
 2 files changed, 69 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index bd21f159b973..5992fc8beeeb 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -2582,9 +2583,64 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static void anx7625_set_crosspoint_switch(struct anx7625_data *ctx,
+ enum typec_orientation orientation)
+{
+   if (orientation == TYPEC_ORIENTATION_NORMAL) {
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX1 | SW_SEL1_DPTX0_RX2);
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX1 | SW_SEL2_DPTX1_TX2);
+   } else if (orientation == TYPEC_ORIENTATION_REVERSE) {
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
+ SW_SEL1_SSRX_RX2 | SW_SEL1_DPTX0_RX1);
+   anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
+ SW_SEL2_SSTX_TX2 | SW_SEL2_DPTX1_TX1);
+   }
+}
+
+static void anx7625_typec_two_ports_update(struct anx7625_data *ctx)
+{
+   if (ctx->typec_ports[0].dp_connected && 
ctx->typec_ports[1].dp_connected)
+   /* Both ports available, do nothing to retain the current one. 
*/
+   return;
+   else if (ctx->typec_ports[0].dp_connected)
+   anx7625_set_crosspoint_switch(ctx, TYPEC_ORIENTATION_NORMAL);
+   else if (ctx->typec_ports[1].dp_connected)
+   anx7625_set_crosspoint_switch(ctx, TYPEC_ORIENTATION_REVERSE);
+}
+
 static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
 struct typec_mux_state *state)
 {
+   struct anx7625_port_data *data = typec_mux_get_drvdata(mux);
+   struct anx7625_data *ctx = data->ctx;
+   struct device *dev = >client->dev;
+   bool new_dp_connected, old_dp_connected;
+
+   if (ctx->num_typec_switches == 1)
+   return 0;
+
+   old_dp_connected = ctx->typec_ports[0].dp_connected || 
ctx->typec_ports[1].dp_connected;
+
+   dev_dbg(dev, "mux_set dp_connected: c0=%d, c1=%d\n",
+   ctx->typec_ports[0].dp_connected, 
ctx->typec_ports[1].dp_connected);
+
+   data->dp_connected = (state->alt && state->alt->svid == 
USB_TYPEC_DP_SID &&
+ state->alt->mode == USB_TYPEC_DP_MODE);
+
+   new_dp_connected = ctx->typec_ports[0].dp_connected || 
ctx->typec_ports[1].dp_connected;
+
+   /* dp on, power on first */
+   if (!old_dp_connected && new_dp_connected)
+   pm_runtime_get_sync(dev);
+
+   anx7625_typec_two_ports_update(ctx);
+
+   /* dp off, power off last */
+   if (old_dp_connected && !new_dp_connected)
+   pm_runtime_put_sync(dev);
+
return 0;
 }
 
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h 
b/drivers/gpu/drm/bridge/analogix/anx7625.h
index 76cfc64f7574..7d6c6fdf9a3a 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -55,6 +55,18 @@
 #define HPD_STATUS_CHANGE 0x80
 #define HPD_STATUS 0x80
 
+#define TCPC_SWITCH_0 0xB4
+#define SW_SEL1_DPTX0_RX2 BIT(0)
+#define SW_SEL1_DPTX0_RX1 BIT(1)
+#define SW_SEL1_SSRX_RX2 BIT(4)
+#define SW_SEL1_SSRX_RX1 BIT(5)
+
+#define TCPC_SWITCH_1 0xB5
+#define SW_SEL2_DPTX1_TX2 BIT(0)
+#define SW_SEL2_DPTX1_TX1 BIT(1)
+#define SW_SEL2_SSTX_TX2 BIT(4)
+#define SW_SEL2_SSTX_TX1 BIT(5)
+
 / END of I2C Address 0x58 /
 
 /***/
@@ -444,6 +456,7 @@ struct anx7625_i2c_client {
 };
 
 struct anx7625_port_data {
+   bool dp_connected;
struct typec_mux_dev *typec_mux;
struct anx7625_data *ctx;
 };
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 6/7] drm/bridge: anx7625: Register Type-C mode switches

2022-06-14 Thread Prashant Malani
When the DT node has "switches" available, register a Type-C mode-switch
for each listed "switch". This allows the driver to receive state
information about what operating mode a Type-C port and its connected
peripherals are in, as well as status information (like VDOs) related to
that state.

The callback function is currently a stub, but subsequent patches will
implement the required functionality.

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Updated dev_info() to dev_warn() print, but added a check to ensure it
  only triggers on non -ENODEV errors.
- Made conflict resolutions resulting from changes introduced in
  Patch v3 5/7 (add ret variable here instead of in Patch v3 5/7).
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- No changes.

 drivers/gpu/drm/bridge/analogix/anx7625.c | 82 +--
 drivers/gpu/drm/bridge/analogix/anx7625.h |  6 ++
 2 files changed, 84 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index e3d4c2738b8c..bd21f159b973 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -15,6 +15,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -2581,10 +2582,61 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
+struct typec_mux_state *state)
+{
+   return 0;
+}
+
+static int anx7625_register_mode_switch(struct device *dev, struct device_node 
*node,
+   struct anx7625_data *ctx)
+{
+   struct anx7625_port_data *port_data;
+   struct typec_mux_desc mux_desc = {};
+   char name[32];
+   u32 port_num;
+   int ret;
+
+   ret = of_property_read_u32(node, "reg", _num);
+   if (ret)
+   return ret;
+
+   if (port_num >= ctx->num_typec_switches) {
+   dev_err(dev, "Invalid port number specified: %d\n", port_num);
+   return -EINVAL;
+   }
+
+   port_data = >typec_ports[port_num];
+   port_data->ctx = ctx;
+   mux_desc.fwnode = >fwnode;
+   mux_desc.drvdata = port_data;
+   snprintf(name, sizeof(name), "%s-%u", node->name, port_num);
+   mux_desc.name = name;
+   mux_desc.set = anx7625_typec_mux_set;
+
+   port_data->typec_mux = typec_mux_register(dev, _desc);
+   if (IS_ERR(port_data->typec_mux)) {
+   ret = PTR_ERR(port_data->typec_mux);
+   dev_err(dev, "Mode switch register for port %d failed: %d", 
port_num, ret);
+   }
+
+   return ret;
+}
+
+static void anx7625_unregister_typec_switches(struct anx7625_data *ctx)
+{
+   int i;
+
+   for (i = 0; i < ctx->num_typec_switches; i++)
+   typec_mux_unregister(ctx->typec_ports[i].typec_mux);
+}
+
 static int anx7625_register_typec_switches(struct device *device, struct 
anx7625_data *ctx)
 {
-   struct device_node *of = of_get_child_by_name(device->of_node, 
"switches");
+   struct device_node *of, *sw;
+   int ret = 0;
 
+   of = of_get_child_by_name(device->of_node, "switches");
if (!of)
return -ENODEV;
 
@@ -2592,7 +2644,27 @@ static int anx7625_register_typec_switches(struct device 
*device, struct anx7625
if (ctx->num_typec_switches <= 0)
return -ENODEV;
 
-   return 0;
+   ctx->typec_ports = devm_kzalloc(device,
+   ctx->num_typec_switches * sizeof(struct 
anx7625_port_data),
+   GFP_KERNEL);
+   if (!ctx->typec_ports)
+   return -ENOMEM;
+
+   /* Register switches for each connector. */
+   for_each_available_child_of_node(of, sw) {
+   if (!of_property_read_bool(sw, "mode-switch"))
+   continue;
+   ret = anx7625_register_mode_switch(device, sw, ctx);
+   if (ret) {
+   dev_err(device, "Failed to register mode switch: %d\n", 
ret);
+   break;
+   }
+   }
+
+   if (ret)
+   anx7625_unregister_typec_switches(ctx);
+
+   return ret;
 }
 
 static int anx7625_i2c_probe(struct i2c_client *client,
@@ -2701,8 +2773,8 @@ static int anx7625_i2c_probe(struct i2c_client *client,
queue_work(platform->workqueue, >work);
 
ret = anx7625_register_typec_switches(dev, platform);
-   if (ret)
-   dev_dbg(dev, "Didn't register Type C switches, err: %d\n", ret);
+   if (ret && ret != -ENODEV)
+   dev_warn(dev, "Didn't register Type C switches, err: %d\n", 
ret);
 
platform->bridge.funcs = _bridge_funcs;
platform->bridge.of_node = client->dev.of_node;
@@ -2757,6 +2829,8 @@ static int 

[PATCH v3 5/7] drm/bridge: anx7625: Register number of Type C switches

2022-06-14 Thread Prashant Malani
Parse the "switches" node, if available, and count and store the number
of Type-C switches within it. Since we currently don't do anything with
this info, no functional changes are expected from this change.

This patch sets a foundation for the actual registering of Type-C
switches with the Type-C connector class framework.

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Move ret variable to Patch v3 6/7..
- Make error print a dev_dbg, since it is noisy.
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- No changes.

 drivers/gpu/drm/bridge/analogix/anx7625.c | 18 ++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  1 +
 2 files changed, 19 insertions(+)

diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
b/drivers/gpu/drm/bridge/analogix/anx7625.c
index 53a5da6c49dd..e3d4c2738b8c 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.c
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
@@ -2581,6 +2581,20 @@ static void anx7625_runtime_disable(void *data)
pm_runtime_disable(data);
 }
 
+static int anx7625_register_typec_switches(struct device *device, struct 
anx7625_data *ctx)
+{
+   struct device_node *of = of_get_child_by_name(device->of_node, 
"switches");
+
+   if (!of)
+   return -ENODEV;
+
+   ctx->num_typec_switches = of_get_child_count(of);
+   if (ctx->num_typec_switches <= 0)
+   return -ENODEV;
+
+   return 0;
+}
+
 static int anx7625_i2c_probe(struct i2c_client *client,
 const struct i2c_device_id *id)
 {
@@ -2686,6 +2700,10 @@ static int anx7625_i2c_probe(struct i2c_client *client,
if (platform->pdata.intp_irq)
queue_work(platform->workqueue, >work);
 
+   ret = anx7625_register_typec_switches(dev, platform);
+   if (ret)
+   dev_dbg(dev, "Didn't register Type C switches, err: %d\n", ret);
+
platform->bridge.funcs = _bridge_funcs;
platform->bridge.of_node = client->dev.of_node;
if (!anx7625_of_panel_on_aux_bus(>dev))
diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.h 
b/drivers/gpu/drm/bridge/analogix/anx7625.h
index e257a84db962..d5cbca708842 100644
--- a/drivers/gpu/drm/bridge/analogix/anx7625.h
+++ b/drivers/gpu/drm/bridge/analogix/anx7625.h
@@ -473,6 +473,7 @@ struct anx7625_data {
struct drm_connector *connector;
struct mipi_dsi_device *dsi;
struct drm_dp_aux aux;
+   int num_typec_switches;
 };
 
 #endif  /* __ANX7625_H__ */
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 4/7] dt-bindings: drm/bridge: anx7625: Add mode-switch support

2022-06-14 Thread Prashant Malani
Analogix 7625 can be used in systems to switch USB Type-C DisplayPort
alternate mode lane traffic between 2 Type-C ports.

Update the binding to accommodate this usage by introducing a switch
property.

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- Introduced patternProperties for "switch" children (suggested by Krzysztof 
Kozlowski).
- Added unevaluatedProperties descriptor (suggested by Krzysztof Kozlowski).
- Added "address-cells" and "size-cells" properties to "switches".

 .../display/bridge/analogix,anx7625.yaml  | 63 +++
 1 file changed, 63 insertions(+)

diff --git 
a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml 
b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
index 35a48515836e..cb4a23391244 100644
--- a/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/analogix,anx7625.yaml
@@ -105,6 +105,33 @@ properties:
   - port@0
   - port@1
 
+  switches:
+type: object
+description: Set of switches controlling DisplayPort traffic on
+  outgoing RX/TX lanes to Type C ports.
+unevaluatedProperties: false
+
+properties:
+  "#address-cells":
+const: 1
+
+  "#size-cells":
+const: 0
+
+patternProperties:
+  'switch@[01]':
+$ref: /schemas/usb/typec-switch.yaml#
+
+properties:
+  reg:
+maxItems: 1
+
+required:
+  - reg
+
+required:
+  - switch@0
+
 required:
   - compatible
   - reg
@@ -167,5 +194,41 @@ examples:
 };
 };
 };
+switches {
+#address-cells = <1>;
+#size-cells = <0>;
+switch@0 {
+compatible = "typec-switch";
+reg = <0>;
+mode-switch;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+anx_typec0: endpoint {
+remote-endpoint = <_port0>;
+};
+};
+};
+};
+switch@1 {
+compatible = "typec-switch";
+reg = <1>;
+mode-switch;
+
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+port@0 {
+reg = <0>;
+anx_typec1: endpoint {
+remote-endpoint = <_port1>;
+};
+};
+};
+};
+};
 };
 };
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 3/7] dt-bindings: usb: Add Type-C switch binding

2022-06-14 Thread Prashant Malani
Introduce a binding which represents a component that can control the
routing of USB Type-C data lines as well as address data line
orientation (based on CC lines' orientation).

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- Removed "items" from compatible.
- Fixed indentation in example.

 .../devicetree/bindings/usb/typec-switch.yaml | 74 +++
 1 file changed, 74 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/usb/typec-switch.yaml

diff --git a/Documentation/devicetree/bindings/usb/typec-switch.yaml 
b/Documentation/devicetree/bindings/usb/typec-switch.yaml
new file mode 100644
index ..78b0190c8543
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/typec-switch.yaml
@@ -0,0 +1,74 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/typec-switch.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: USB Type-C Switch
+
+maintainers:
+  - Prashant Malani 
+
+description:
+  A USB Type-C switch represents a component which routes USB Type-C data
+  lines to various protocol host controllers (e.g USB, VESA DisplayPort,
+  Thunderbolt etc.) depending on which mode the Type-C port, port partner
+  and cable are operating in. It can also modify lane routing based on
+  the orientation of a connected Type-C peripheral.
+
+properties:
+  compatible:
+const: typec-switch
+
+  mode-switch:
+type: boolean
+description: Specify that this switch can handle alternate mode switching.
+
+  orientation-switch:
+type: boolean
+description: Specify that this switch can handle orientation switching.
+
+  ports:
+$ref: /schemas/graph.yaml#/properties/ports
+description: OF graph binding modelling data lines to the Type-C switch.
+
+properties:
+  port@0:
+$ref: /schemas/graph.yaml#/properties/port
+description: Link between the switch and a Type-C connector.
+
+required:
+  - port@0
+
+required:
+  - compatible
+  - ports
+
+anyOf:
+  - required:
+  - mode-switch
+  - required:
+  - orientation-switch
+
+additionalProperties: true
+
+examples:
+  - |
+drm-bridge {
+usb-switch {
+compatible = "typec-switch";
+mode-switch;
+orientation-switch;
+ports {
+#address-cells = <1>;
+#size-cells = <0>;
+
+port@0 {
+reg = <0>;
+anx_ep: endpoint {
+remote-endpoint = <_controller>;
+};
+};
+};
+};
+};
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 2/7] usb: typec: mux: Add CONFIG guards for functions

2022-06-14 Thread Prashant Malani
There are some drivers that can use the Type C mux API, but don't have
to. Introduce CONFIG guards for the mux functions so that drivers can
include the header file and not run into compilation errors on systems
which don't have CONFIG_TYPEC enabled. When CONFIG_TYPEC is not enabled,
the Type C mux functions will be stub versions of the original calls.

Reported-by: kernel test robot 
Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
Signed-off-by: Prashant Malani 
---

Changes since v2:
- Fix up return types for some of the stubs. Remove 1 unnecessary stub
  in the else condition.
- Remove unnecessary IS_MODULE config guard.
- Added Reviewed-by and Tested-by tags.

Changes since v1:
- Added static inline to stub functions.
- Updated function signature of stub functions from "struct typec_mux"
  to "struct typec_mux_dev" in accordance with updates from commit
  713fd49b430c ("usb: typec: mux: Introduce indirection")

 include/linux/usb/typec_mux.h | 44 ++-
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/include/linux/usb/typec_mux.h b/include/linux/usb/typec_mux.h
index ee57781dcf28..9292f0e07846 100644
--- a/include/linux/usb/typec_mux.h
+++ b/include/linux/usb/typec_mux.h
@@ -58,17 +58,13 @@ struct typec_mux_desc {
void *drvdata;
 };
 
+#if IS_ENABLED(CONFIG_TYPEC)
+
 struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle *fwnode,
   const struct typec_altmode_desc *desc);
 void typec_mux_put(struct typec_mux *mux);
 int typec_mux_set(struct typec_mux *mux, struct typec_mux_state *state);
 
-static inline struct typec_mux *
-typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc)
-{
-   return fwnode_typec_mux_get(dev_fwnode(dev), desc);
-}
-
 struct typec_mux_dev *
 typec_mux_register(struct device *parent, const struct typec_mux_desc *desc);
 void typec_mux_unregister(struct typec_mux_dev *mux);
@@ -76,4 +72,40 @@ void typec_mux_unregister(struct typec_mux_dev *mux);
 void typec_mux_set_drvdata(struct typec_mux_dev *mux, void *data);
 void *typec_mux_get_drvdata(struct typec_mux_dev *mux);
 
+#else
+
+static inline struct typec_mux *fwnode_typec_mux_get(struct fwnode_handle 
*fwnode,
+  const struct typec_altmode_desc *desc)
+{
+   return NULL;
+}
+
+static inline void typec_mux_put(struct typec_mux *mux) {}
+
+static inline int typec_mux_set(struct typec_mux *mux, struct typec_mux_state 
*state)
+{
+   return 0;
+}
+
+static inline struct typec_mux_dev *
+typec_mux_register(struct device *parent, const struct typec_mux_desc *desc)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+static inline void typec_mux_unregister(struct typec_mux_dev *mux) {}
+
+static inline void typec_mux_set_drvdata(struct typec_mux_dev *mux, void 
*data) {}
+static inline void *typec_mux_get_drvdata(struct typec_mux_dev *mux)
+{
+   return ERR_PTR(-EOPNOTSUPP);
+}
+
+#endif /* CONFIG_TYPEC */
+
+static inline struct typec_mux *
+typec_mux_get(struct device *dev, const struct typec_altmode_desc *desc)
+{
+   return fwnode_typec_mux_get(dev_fwnode(dev), desc);
+}
+
 #endif /* __USB_TYPEC_MUX */
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 1/7] usb: typec: mux: Allow muxes to specify mode-switch

2022-06-14 Thread Prashant Malani
Loosen the typec_mux_match() requirements so that searches where an
alt mode is not specified, but the target mux device lists the
"mode-switch" property, return a success.

This is helpful in Type C port drivers which would like to get a pointer
to the mux switch associated with a Type C port, but don't want to
specify a particular alt mode.

Signed-off-by: Prashant Malani 
Reviewed-by: Heikki Krogerus 
Reviewed-by: AngeloGioacchino Del Regno 

Reviewed-by: Nícolas F. R. A. Prado 
Tested-by: Nícolas F. R. A. Prado 
---

Changes since v2:
- Included Reviewed-by and Tested-by tags from v2.

Changes since v1:
- No changes.

 drivers/usb/typec/mux.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/typec/mux.c b/drivers/usb/typec/mux.c
index fd55c2c516a5..464330776cd6 100644
--- a/drivers/usb/typec/mux.c
+++ b/drivers/usb/typec/mux.c
@@ -281,9 +281,13 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, 
const char *id,
if (match)
goto find_mux;
 
-   /* Accessory Mode muxes */
if (!desc) {
-   match = fwnode_property_present(fwnode, "accessory");
+   /*
+* Accessory Mode muxes & muxes which explicitly specify
+* the required identifier can avoid SVID matching.
+*/
+   match = fwnode_property_present(fwnode, "accessory") ||
+   fwnode_property_present(fwnode, id);
if (match)
goto find_mux;
return NULL;
-- 
2.36.1.476.g0c4daa206d-goog



[PATCH v3 0/7] usb: typec: Introduce typec-switch binding

2022-06-14 Thread Prashant Malani
This series introduces a binding for Type-C data lane switches. These
control the routing and operating modes of USB Type-C data lanes based
on the PD messaging from the Type-C port driver regarding connected
peripherals.

The first patch introduces a change to the Type-C mux class mode-switch
matching code, while the second adds a config guard to a Type-C header.
The next couple of patches introduce the new "typec-switch" binding as
well as one user of it (the ANX7625 drm bridge).

The remaining patches add functionality to the anx7625 driver to
register the mode-switches, as well as program its crosspoint
switch depending on which Type-C port has a DisplayPort (DP) peripheral
connected to it.

v2: 
https://lore.kernel.org/linux-usb/20220609181106.3695103-1-pmal...@chromium.org/

Changes since v2:
- Addressed review comments in typec_mux.h
- Changed error print to only print when a device is actually listed in
  DT.
- Moved num_typec_switches check to beginning of function.
- Picked up Reviewed-by and Tested-by tags from v2.

Pin-Yen Lin (1):
  drm/bridge: anx7625: Add typec_mux_set callback function

Prashant Malani (6):
  usb: typec: mux: Allow muxes to specify mode-switch
  usb: typec: mux: Add CONFIG guards for functions
  dt-bindings: usb: Add Type-C switch binding
  dt-bindings: drm/bridge: anx7625: Add mode-switch support
  drm/bridge: anx7625: Register number of Type C switches
  drm/bridge: anx7625: Register Type-C mode switches

 .../display/bridge/analogix,anx7625.yaml  |  63 
 .../devicetree/bindings/usb/typec-switch.yaml |  74 +
 drivers/gpu/drm/bridge/analogix/anx7625.c | 148 ++
 drivers/gpu/drm/bridge/analogix/anx7625.h |  20 +++
 drivers/usb/typec/mux.c   |   8 +-
 include/linux/usb/typec_mux.h |  44 +-
 6 files changed, 349 insertions(+), 8 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/usb/typec-switch.yaml

-- 
2.36.1.476.g0c4daa206d-goog



[PATCH 3/3] drm/msm/dpu: remove hard-coded linewidth limit for writeback

2022-06-14 Thread Abhinav Kumar
Remove the hard-coded limit for writeback and lets start using
the one from catalog instead.

Fixes: d7d0e73f7de3 ("introduce the dpu_encoder_phys_* for writeback")
Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
index 59da348ff339..fc1d4fda69b5 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_wb.c
@@ -20,8 +20,6 @@
 #include "dpu_crtc.h"
 #include "disp/msm_disp_snapshot.h"
 
-#define DEFAULT_MAX_WRITEBACK_WIDTH 2048
-
 #define to_dpu_encoder_phys_wb(x) \
container_of(x, struct dpu_encoder_phys_wb, base)
 
@@ -278,9 +276,9 @@ static int dpu_encoder_phys_wb_atomic_check(
DPU_ERROR("invalid fb h=%d, mode h=%d\n", fb->height,
  mode->vdisplay);
return -EINVAL;
-   } else if (fb->width > DEFAULT_MAX_WRITEBACK_WIDTH) {
+   } else if (fb->width > phys_enc->hw_wb->caps->maxlinewidth) {
DPU_ERROR("invalid fb w=%d, maxlinewidth=%u\n",
- fb->width, DEFAULT_MAX_WRITEBACK_WIDTH);
+ fb->width, 
phys_enc->hw_wb->caps->maxlinewidth);
return -EINVAL;
}
 
-- 
2.7.4



[PATCH 2/3] drm/msm/dpu: fix maxlinewidth for writeback block

2022-06-14 Thread Abhinav Kumar
Writeback block for sm8250 was using the default maxlinewidth
of 2048. But this is not right as it supports upto 4096.

This should have no effect on most resolutions as we are
still limiting upto maxlinewidth of SSPP for adding the modes.

Fix the maxlinewidth for writeback block on sm8250.

Fixes: 53324b99bd7b ("add writeback blocks to the sm8250 DPU catalog")
Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
index 400ebceb56bb..dd7537e32f88 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_catalog.c
@@ -1285,7 +1285,7 @@ static const struct dpu_intf_cfg qcm2290_intf[] = {
  * Writeback blocks config
  */
 #define WB_BLK(_name, _id, _base, _features, _clk_ctrl, \
-   __xin_id, vbif_id, _reg, _wb_done_bit) \
+   __xin_id, vbif_id, _reg, _max_linewidth, _wb_done_bit) \
{ \
.name = _name, .id = _id, \
.base = _base, .len = 0x2c8, \
@@ -1295,13 +1295,13 @@ static const struct dpu_intf_cfg qcm2290_intf[] = {
.clk_ctrl = _clk_ctrl, \
.xin_id = __xin_id, \
.vbif_idx = vbif_id, \
-   .maxlinewidth = DEFAULT_DPU_LINE_WIDTH, \
+   .maxlinewidth = _max_linewidth, \
.intr_wb_done = DPU_IRQ_IDX(_reg, _wb_done_bit) \
}
 
 static const struct dpu_wb_cfg sm8250_wb[] = {
WB_BLK("wb_2", WB_2, 0x65000, WB_SM8250_MASK, DPU_CLK_CTRL_WB2, 6,
-   VBIF_RT, MDP_SSPP_TOP0_INTR, 4),
+   VBIF_RT, MDP_SSPP_TOP0_INTR, 4096, 4),
 };
 
 /*
-- 
2.7.4



[PATCH 1/3] drm/msm/dpu: move intf and wb assignment to dpu_encoder_setup_display()

2022-06-14 Thread Abhinav Kumar
intf and wb resources are not dependent on the rm global
state so need not be allocated during dpu_encoder_virt_atomic_mode_set().

Move the allocation of intf and wb resources to dpu_encoder_setup_display()
so that we can utilize the hw caps even during atomic_check() phase.

Since dpu_encoder_setup_display() already has protection against
setting invalid intf_idx and wb_idx, these checks can now
be dropped as well.

Fixes: e02a559a720f ("make changes to dpu_encoder to support virtual encoder")
Signed-off-by: Abhinav Kumar 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 25 +++--
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index 3a462e327e0e..e991d4ba8a40 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1048,24 +1048,6 @@ static void dpu_encoder_virt_atomic_mode_set(struct 
drm_encoder *drm_enc,
phys->hw_pp = dpu_enc->hw_pp[i];
phys->hw_ctl = to_dpu_hw_ctl(hw_ctl[i]);
 
-   if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX)
-   phys->hw_intf = dpu_rm_get_intf(_kms->rm, 
phys->intf_idx);
-
-   if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
-   phys->hw_wb = dpu_rm_get_wb(_kms->rm, phys->wb_idx);
-
-   if (!phys->hw_intf && !phys->hw_wb) {
-   DPU_ERROR_ENC(dpu_enc,
- "no intf or wb block assigned at idx: 
%d\n", i);
-   return;
-   }
-
-   if (phys->hw_intf && phys->hw_wb) {
-   DPU_ERROR_ENC(dpu_enc,
-   "invalid phys both intf and wb block at 
idx: %d\n", i);
-   return;
-   }
-
phys->cached_mode = crtc_state->adjusted_mode;
if (phys->ops.atomic_mode_set)
phys->ops.atomic_mode_set(phys, crtc_state, conn_state);
@@ -2293,7 +2275,14 @@ static int dpu_encoder_setup_display(struct 
dpu_encoder_virt *dpu_enc,
struct dpu_encoder_phys *phys = dpu_enc->phys_encs[i];
atomic_set(>vsync_cnt, 0);
atomic_set(>underrun_cnt, 0);
+
+   if (phys->intf_idx >= INTF_0 && phys->intf_idx < INTF_MAX)
+   phys->hw_intf = dpu_rm_get_intf(_kms->rm, 
phys->intf_idx);
+
+   if (phys->wb_idx >= WB_0 && phys->wb_idx < WB_MAX)
+   phys->hw_wb = dpu_rm_get_wb(_kms->rm, phys->wb_idx);
}
+
mutex_unlock(_enc->enc_lock);
 
return ret;
-- 
2.7.4



Re: [PATCH v2 2/2] drm/virtio: fence created per cursor/plane update

2022-06-14 Thread Dongwon Kim
On Thu, Jun 09, 2022 at 06:24:43AM +0200, Gerd Hoffmann wrote:
> On Fri, Jun 03, 2022 at 02:18:49PM -0700, Dongwon Kim wrote:
> > Having one fence for a vgfb would cause conflict in case there are
> > multiple planes referencing the same vgfb (e.g. Xorg screen covering
> > two displays in extended mode) being flushed simultaneously. So it makes
> > sence to use a separated fence for each plane update to prevent this.
> > 
> > vgfb->fence is not required anymore with the suggested code change so
> > both prepare_fb and cleanup_fb are removed since only fence creation/
> > freeing are done in there.
> 
> The fences are allocated and released in prepare_fb + cleanup_fb for a
> reason: atomic_update must not fail.

In case fence allocation fails, it falls back to non-fence path so it
won't fail for primary-plane-update.

For cursor plane update, it returns if fence is NULL but we could change
it to just proceed and just make it skip waiting like,

if (fence) {
dma_fence_wait(>f, true);
dma_fence_put(>f);
}   

Or maybe I can limit my suggested changes to primary-plane-update only.

What do you think about these?

> 
> I guess virtio-gpu must be fixed to use drm_plane_state->fence
> correctly ...

I was thinking about this too but current functions (e.g.
virtio_gpu_cmd_transfer_to_host_2d) takes "struct virtio_gpu_fence".
Not sure what is the best way to connect drm_plane_state->fence to
virtio_gpu_fence without changing major function interfaces.

> 
> take care,
>   Gerd
> 


[PATCH 3/3] drm/i915: Do not use reserved requests for virtual engines

2022-06-14 Thread Ramalingam C
Do not use reserved requests for virtual engines as this is only
needed for kernel contexts.

Signed-off-by: Ramalingam C 
Suggested-by: Matthew Brost 
---
 drivers/gpu/drm/i915/i915_request.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index c71905d8e154..f0392b053bca 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -135,6 +135,8 @@ static void i915_fence_release(struct dma_fence *fence)
 
/*
 * Keep one request on each engine for reserved use under mempressure
+* do not use with virtual engines as this really is only needed for
+* kernel contexts.
 *
 * We do not hold a reference to the engine here and so have to be
 * very careful in what rq->engine we poke. The virtual engine is
@@ -164,7 +166,8 @@ static void i915_fence_release(struct dma_fence *fence)
 * know that if the rq->execution_mask is a single bit, rq->engine
 * can be a physical engine with the exact corresponding mask.
 */
-   if (is_power_of_2(rq->execution_mask) &&
+   if (!intel_engine_is_virtual(rq->engine) &&
+   is_power_of_2(rq->execution_mask) &&
!cmpxchg(>engine->request_pool, NULL, rq))
return;
 
-- 
2.20.1



[PATCH 2/3] Revert "drm/i915: Hold reference to intel_context over life of i915_request"

2022-06-14 Thread Ramalingam C
From: Niranjana Vishwanathapura 

This reverts commit 1e98d8c52ed5dfbaf273c4423c636525c2ce59e7.

The problem with this patch is that it makes i915_request to hold a
reference to intel_context, which in turn holds a reference on the VM.
This strong back referencing can lead to reference loops which leads
to resource leak.

An example is the upcoming VM_BIND work which requires VM to hold
a reference to some shared VM specific BO. But this BO's dma-resv
fences holds reference to the i915_request thus leading to reference
loop.

Signed-off-by: Niranjana Vishwanathapura 
Signed-off-by: Ramalingam C 
Suggested-by: Matthew Brost 
---
 drivers/gpu/drm/i915/i915_request.c | 55 +
 1 file changed, 32 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index 7f6998bf390c..c71905d8e154 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -134,17 +134,39 @@ static void i915_fence_release(struct dma_fence *fence)
i915_sw_fence_fini(>semaphore);
 
/*
-* Keep one request on each engine for reserved use under mempressure,
-* do not use with virtual engines as this really is only needed for
-* kernel contexts.
+* Keep one request on each engine for reserved use under mempressure
+*
+* We do not hold a reference to the engine here and so have to be
+* very careful in what rq->engine we poke. The virtual engine is
+* referenced via the rq->context and we released that ref during
+* i915_request_retire(), ergo we must not dereference a virtual
+* engine here. Not that we would want to, as the only consumer of
+* the reserved engine->request_pool is the power management parking,
+* which must-not-fail, and that is only run on the physical engines.
+*
+* Since the request must have been executed to be have completed,
+* we know that it will have been processed by the HW and will
+* not be unsubmitted again, so rq->engine and rq->execution_mask
+* at this point is stable. rq->execution_mask will be a single
+* bit if the last and _only_ engine it could execution on was a
+* physical engine, if it's multiple bits then it started on and
+* could still be on a virtual engine. Thus if the mask is not a
+* power-of-two we assume that rq->engine may still be a virtual
+* engine and so a dangling invalid pointer that we cannot dereference
+*
+* For example, consider the flow of a bonded request through a virtual
+* engine. The request is created with a wide engine mask (all engines
+* that we might execute on). On processing the bond, the request mask
+* is reduced to one or more engines. If the request is subsequently
+* bound to a single engine, it will then be constrained to only
+* execute on that engine and never returned to the virtual engine
+* after timeslicing away, see __unwind_incomplete_requests(). Thus we
+* know that if the rq->execution_mask is a single bit, rq->engine
+* can be a physical engine with the exact corresponding mask.
 */
-   if (!intel_engine_is_virtual(rq->engine) &&
-   !cmpxchg(>engine->request_pool, NULL, rq)) {
-   intel_context_put(rq->context);
+   if (is_power_of_2(rq->execution_mask) &&
+   !cmpxchg(>engine->request_pool, NULL, rq))
return;
-   }
-
-   intel_context_put(rq->context);
 
kmem_cache_free(slab_requests, rq);
 }
@@ -921,19 +943,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
}
}
 
-   /*
-* Hold a reference to the intel_context over life of an i915_request.
-* Without this an i915_request can exist after the context has been
-* destroyed (e.g. request retired, context closed, but user space holds
-* a reference to the request from an out fence). In the case of GuC
-* submission + virtual engine, the engine that the request references
-* is also destroyed which can trigger bad pointer dref in fence ops
-* (e.g. i915_fence_get_driver_name). We could likely change these
-* functions to avoid touching the engine but let's just be safe and
-* hold the intel_context reference. In execlist mode the request always
-* eventually points to a physical engine so this isn't an issue.
-*/
-   rq->context = intel_context_get(ce);
+   rq->context = ce;
rq->engine = ce->engine;
rq->ring = ce->ring;
rq->execution_mask = ce->engine->mask;
@@ -1009,7 +1019,6 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
GEM_BUG_ON(!list_empty(>sched.waiters_list));
 
 err_free:
-   intel_context_put(ce);
kmem_cache_free(slab_requests, rq);
 

RE: [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Dong, Zhanjun
Thanks for all comments, I will update code and prepare for next version.

Regards,
Zhanjun

-Original Message-
From: Dixit, Ashutosh  
Sent: June 14, 2022 12:28 PM
To: Dong, Zhanjun 
Cc: intel-...@lists.freedesktop.org; dri-devel@lists.freedesktop.org; Teres 
Alexis, Alan Previn ; Wajdeczko, Michal 

Subject: Re: [PATCH] drm/i915/guc: Check ctx while waiting for response

On Thu, 02 Jun 2022 10:21:19 -0700, Zhanjun Dong wrote:
>

Hi Zhanjun,

> We are seeing error message of "No response for request". Some cases 
> happened while waiting for response and reset/suspend action was 
> triggered. In this case, no response is not an error, active requests will be 
> cancelled.
>
> This patch will handle this condition and change the error message 
> into debug message.

IMO the patch title should be changed: which ctx are we checking while waiting 
for response? Something like "check for ct enabled while waiting for response"?

> @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct 
> ct_request *req, u32 *status)  #define 
> GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10  #define 
> GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000  #define done \
> - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> +READ_ONCE(req->status)) == \
>GUC_HXG_ORIGIN_GUC)
>   err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
>   if (err)
>   err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
>  #undef done
> + if (!intel_guc_ct_enabled(ct))
> + err = -ECANCELED;

Also, I really don't like intel_guc_ct_enabled() being called in two places. Is 
there a possibility that intel_guc_ct_enabled() can return false in the first 
place (causing the wait to exit) and then return true in the second place (so 
we don't return -ECANCELED)?

Is it possible to change the status of the request to something else from
intel_guc_ct_disable() (or wherever ct->enabled is set to false) rather than 
introducing intel_guc_ct_enabled() checks here. Changing the status of the 
request when CT goes down would cause the wait's to exit here. And then we can 
check that special request status signifying CT went down?

Thanks.
--
Ashutosh


[PATCH 1/3] drm/i915: Do not access rq->engine without a reference

2022-06-14 Thread Ramalingam C
From: Niranjana Vishwanathapura 

In i915_fence_get_driver_name(), user may not hold a
reference to rq->engine. Hence do not access it. Instead,
store required device private pointer in 'rq->i915' and use it.

Signed-off-by: Niranjana Vishwanathapura 
Suggested-by: Matthew Brost 
---
 drivers/gpu/drm/i915/i915_request.c | 3 ++-
 drivers/gpu/drm/i915/i915_request.h | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_request.c 
b/drivers/gpu/drm/i915/i915_request.c
index 73d5195146b0..7f6998bf390c 100644
--- a/drivers/gpu/drm/i915/i915_request.c
+++ b/drivers/gpu/drm/i915/i915_request.c
@@ -60,7 +60,7 @@ static struct kmem_cache *slab_execute_cbs;
 
 static const char *i915_fence_get_driver_name(struct dma_fence *fence)
 {
-   return dev_name(to_request(fence)->engine->i915->drm.dev);
+   return dev_name(to_request(fence)->i915->drm.dev);
 }
 
 static const char *i915_fence_get_timeline_name(struct dma_fence *fence)
@@ -937,6 +937,7 @@ __i915_request_create(struct intel_context *ce, gfp_t gfp)
rq->engine = ce->engine;
rq->ring = ce->ring;
rq->execution_mask = ce->engine->mask;
+   rq->i915 = ce->engine->i915;
 
ret = intel_timeline_get_seqno(tl, rq, );
if (ret)
diff --git a/drivers/gpu/drm/i915/i915_request.h 
b/drivers/gpu/drm/i915/i915_request.h
index 28b1f9db5487..47041ec68df8 100644
--- a/drivers/gpu/drm/i915/i915_request.h
+++ b/drivers/gpu/drm/i915/i915_request.h
@@ -196,6 +196,8 @@ struct i915_request {
struct dma_fence fence;
spinlock_t lock;
 
+   struct drm_i915_private *i915;
+
/**
 * Context and ring buffer related to this request
 * Contexts are refcounted, so when this request is associated with a
-- 
2.20.1



[PATCH 0/3] Break VM to rq reference loop

2022-06-14 Thread Ramalingam C
The i915_request holds a reference to intel_context, which in
turn holds a reference on the VM. But the dma-resv update for
VM_BIND feature would require VM hold a reference to the
i915_request through dma-resv fences of VM_PRIVATE objects
(which share a per VM dma-resv object).

Thus, we have a circular reference pattern causing the VM
reference to never reach 0, hence VM is not destroyed.

Break this by reverting the below patch which is making the
i915_request to hold a reference on intel_context.
"drm/i915: Hold reference to intel_context over life of i915_request"

This means we can't access rq->engine in i915_fence_get_driver_name()
as user do not hold a reference on rq->engine here. So, instead
store required device private pointer in 'rq->i915' and use it.

Niranjana Vishwanathapura (2):
  drm/i915: Do not access rq->engine without a reference
  Revert "drm/i915: Hold reference to intel_context over life of
i915_request"

Ramalingam C (1):
  drm/i915: Do not use reserved requests for virtual engines

 drivers/gpu/drm/i915/i915_request.c | 55 ++---
 drivers/gpu/drm/i915/i915_request.h |  2 ++
 2 files changed, 36 insertions(+), 21 deletions(-)

-- 
2.20.1



Re: [PATCH v3 3/3] drm/doc: Add KUnit documentation

2022-06-14 Thread Javier Martinez Canillas
On 6/14/22 20:09, José Expósito wrote:
> Hi Javier,
> 
> On Tue, Jun 14, 2022 at 02:58:29PM +0200, Javier Martinez Canillas wrote:
>> Hello José,
>>
>> On 6/13/22 19:17, José Expósito wrote:
>>
>> [snip]
>>
>>> +KUnit (Kernel unit testing framework) provides a common framework for unit 
>>> tests
>>> +within the Linux kernel.
>>> +
>>
>> I think that it will be useful to have a reference to the KUnit kernel doc 
>> here,
>> something like the following:
>>
>> `KUnit `_ (Kernel Unit...
> 
> There is a link in the next paragraph. Once the documentation is
> generated the path "Documentation/dev-tools/kunit/start.rst" is
> transformed into a link.
>  
Ah, I wasn't aware of that. Thanks!

-- 
Best regards,

Javier Martinez Canillas
Linux Engineering
Red Hat



Re: [PATCH v2 5/7] drm/bridge: anx7625: Register number of Type C switches

2022-06-14 Thread Prashant Malani
On Tue, Jun 14, 2022 at 1:22 AM AngeloGioacchino Del Regno
 wrote:
>
> Il 09/06/22 20:09, Prashant Malani ha scritto:
> > Parse the "switches" node, if available, and count and store the number
> > of Type-C switches within it. Since we currently don't do anything with
> > this info, no functional changes are expected from this change.
> >
> > This patch sets a foundation for the actual registering of Type-C
> > switches with the Type-C connector class framework.
> >
> > Signed-off-by: Prashant Malani 
> > ---
> >
> > Changes since v1:
> > - No changes.
> >
> >   drivers/gpu/drm/bridge/analogix/anx7625.c | 20 
> >   drivers/gpu/drm/bridge/analogix/anx7625.h |  1 +
> >   2 files changed, 21 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> > b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 53a5da6c49dd..07ed44c6b839 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -2581,6 +2581,22 @@ static void anx7625_runtime_disable(void *data)
> >   pm_runtime_disable(data);
> >   }
> >
> > +static int anx7625_register_typec_switches(struct device *device, struct 
> > anx7625_data *ctx)
> > +{
> > + struct device_node *of = NULL;
> > + int ret = 0;
> > +
> > + of = of_get_child_by_name(device->of_node, "switches");
> > + if (!of)
> > + return -ENODEV;
> > +
> > + ctx->num_typec_switches = of_get_child_count(of);
> > + if (ctx->num_typec_switches <= 0)
> > + return -ENODEV;
> > +
> > + return ret;
>
> You aren't using the `ret` variable for anything other than returning zero:
> remove it and simply return 0 here.
The very next patch does use it, but sure I'll remove it from here and
introduce it in v6.
>
> > +}
> > +
> >   static int anx7625_i2c_probe(struct i2c_client *client,
> >const struct i2c_device_id *id)
> >   {
> > @@ -2686,6 +2702,10 @@ static int anx7625_i2c_probe(struct i2c_client 
> > *client,
> >   if (platform->pdata.intp_irq)
> >   queue_work(platform->workqueue, >work);
> >
> > + ret = anx7625_register_typec_switches(dev, platform);
> > + if (ret)
> > + dev_info(dev, "Didn't register Type C switches, err: %d\n", 
> > ret);
>
> Type-C switches are optional for this driver and this will print a sort of 
> error
> on boards that are *not* declaring any switches on purpose (because perhaps 
> they
> don't have any, or for any other reason).
>
> Even though this is a dev_info and not a dev_err, it's still printing an 
> alarming
> (and useless, in the aforementioned case) message.
I'll go ahead and convert this to dev_warn, but only trigger if there
is an error other than ENODEV.

>
> Please fix this.
>
> Regards,
> Angelo
>


Re: [PATCH v3 3/3] drm/doc: Add KUnit documentation

2022-06-14 Thread José Expósito
Hi Javier,

On Tue, Jun 14, 2022 at 02:58:29PM +0200, Javier Martinez Canillas wrote:
> Hello José,
> 
> On 6/13/22 19:17, José Expósito wrote:
> 
> [snip]
> 
> > +KUnit (Kernel unit testing framework) provides a common framework for unit 
> > tests
> > +within the Linux kernel.
> > +
> 
> I think that it will be useful to have a reference to the KUnit kernel doc 
> here,
> something like the following:
> 
> `KUnit `_ (Kernel Unit...

There is a link in the next paragraph. Once the documentation is
generated the path "Documentation/dev-tools/kunit/start.rst" is
transformed into a link.
 
> > +This section covers the specifics for the DRM subsystem. For general 
> > information
> > +about KUnit, please refer to Documentation/dev-tools/kunit/start.rst.
> > +
> > +How to run the tests?
> > +~
> > +
> > +In order to facilitate running the test suite, a configuration file is 
> > present
> > +in ``drivers/gpu/drm/kunit/.kunitconfig``. It can be used by ``kunit.py`` 
> > as
> > +follows:
> > +
> > +.. code-block:: bash
> > +
> > +   $ ./tools/testing/kunit/kunit.py run 
> > --kunitconfig=drivers/gpu/drm/kunit \
> > +   --kconfig_add CONFIG_VIRTIO_UML=y \
> > +   --kconfig_add CONFIG_UML_PCI_OVER_VIRTIO=y
> > +
> > +.. note::
> > +   The configuration included in ``.kunitconfig`` should be as generic as
> > +   possible.
> > +   ``CONFIG_VIRTIO_UML`` and ``CONFIG_UML_PCI_OVER_VIRTIO`` are not
> > +   included in it because they are only required for User Mode Linux.
> > +
> > +
> 
> Maybe also add something like this ?
> 
> For example, the following command can be used to run the test for x86_64:
> 
>   $ ./tools/testing/kunit/kunit.py run 
> --kunitconfig=drivers/gpu/drm/kunit \
>   --arch=x86_64

I didn't want to go into much detail because the KUnit docs are
a very good resource and already explain how to run the tests in your
favorite architecture.

Since running the test on x86_64 should not change the results, I'd
prefer to keep it simple and trust the KUnit docs for the "advanced"
options.
 
> Regardless, the patch looks good to me:
> 
> Reviewed-by: Javier Martinez Canillas 


Thanks a lot for taking the time to review it. I'll add the tag if a v4
is required after chatting with the guys working on the AMDGPU tests.

Jose

> -- 
> Best regards,
> 
> Javier Martinez Canillas
> Linux Engineering
> Red Hat
> 


Re: [PATCH] drm/amd/display: add stub for crtc_debugfs_init()

2022-06-14 Thread Randy Dunlap



On 6/14/22 10:45, Harry Wentland wrote:
> On 2022-06-14 11:57, Randy Dunlap wrote:
>> Fix build error when CONFIG_DEBUG_FS is not enabled by adding a
>> stub function for crtc_debugfs_init().
>>
>> Eliminates this build error:
>>
>> ../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c: In function 
>> ‘amdgpu_dm_crtc_late_register’:
>> ../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:6599:2: 
>> error: implicit declaration of function ‘crtc_debugfs_init’; did you mean 
>> ‘amdgpu_debugfs_init’? [-Werror=implicit-function-declaration]
>>   crtc_debugfs_init(crtc);
>>   ^
>>   amdgpu_debugfs_init
>>
>> Fixes: 86bc22191892 ("drm/amd/display: Support crc on specific region")
> 
> That whole patch and the whole secure display feature depend on debugfs.
> It should never try building without CONFIG_DEBUG_FS.

Hi Harry,
Well, it's clearly possible to have this build error, so something needs
to be fixed somewhere.

> See drivers/gpu/drm/amd/display/Kconfig:
> 
>> config DRM_AMD_SECURE_DISPLAY
>> bool "Enable secure display support"
>> default n
>> depends on DEBUG_FS
>> depends on DRM_AMD_DC_DCN
>> help
>> Choose this option if you want to
>> support secure display
>>
>> This option enables the calculation
>> of crc of specific region via debugfs.
>> Cooperate with specific DMCU FW.
> 
> amdgpu_dm_crtc_late_register is guarded by CONIG_DRM_AMD_SECURE_DISPLAY.
> 
> Harry
> 
>> Signed-off-by: Randy Dunlap 
>> Cc: Wayne Lin 
>> Cc: Alex Deucher 
>> Cc: Christian König 
>> Cc: "Pan, Xinhui" 
>> Cc: amd-...@lists.freedesktop.org
>> Cc: dri-devel@lists.freedesktop.org
>> ---
>>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |2 --
>>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h |6 ++
>>  2 files changed, 6 insertions(+), 2 deletions(-)
>>
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
>> @@ -57,9 +57,7 @@
>>  #include "amdgpu_dm_irq.h"
>>  #include "dm_helpers.h"
>>  #include "amdgpu_dm_mst_types.h"
>> -#if defined(CONFIG_DEBUG_FS)
>>  #include "amdgpu_dm_debugfs.h"
>> -#endif
>>  #include "amdgpu_dm_psr.h"
>>  
>>  #include "ivsrcid/ivsrcid_vislands30.h"
>> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
>> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
>> @@ -31,6 +31,12 @@
>>  
>>  void connector_debugfs_init(struct amdgpu_dm_connector *connector);
>>  void dtn_debugfs_init(struct amdgpu_device *adev);
>> +
>> +#ifdef CONFIG_DEBUG_FS
>>  void crtc_debugfs_init(struct drm_crtc *crtc);
>> +#else
>> +static inline void crtc_debugfs_init(struct drm_crtc *crtc)
>> +{}
>> +#endif
>>  
>>  #endif
> 

thanks.
-- 
~Randy


Re: [PATCH] drm/amd/display: add stub for crtc_debugfs_init()

2022-06-14 Thread Harry Wentland
On 2022-06-14 11:57, Randy Dunlap wrote:
> Fix build error when CONFIG_DEBUG_FS is not enabled by adding a
> stub function for crtc_debugfs_init().
> 
> Eliminates this build error:
> 
> ../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c: In function 
> ‘amdgpu_dm_crtc_late_register’:
> ../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:6599:2: error: 
> implicit declaration of function ‘crtc_debugfs_init’; did you mean 
> ‘amdgpu_debugfs_init’? [-Werror=implicit-function-declaration]
>   crtc_debugfs_init(crtc);
>   ^
>   amdgpu_debugfs_init
> 
> Fixes: 86bc22191892 ("drm/amd/display: Support crc on specific region")

That whole patch and the whole secure display feature depend on debugfs.
It should never try building without CONFIG_DEBUG_FS.

See drivers/gpu/drm/amd/display/Kconfig:

> config DRM_AMD_SECURE_DISPLAY
> bool "Enable secure display support"
> default n
> depends on DEBUG_FS
> depends on DRM_AMD_DC_DCN
> help
> Choose this option if you want to
> support secure display
> 
> This option enables the calculation
> of crc of specific region via debugfs.
> Cooperate with specific DMCU FW.

amdgpu_dm_crtc_late_register is guarded by CONIG_DRM_AMD_SECURE_DISPLAY.

Harry

> Signed-off-by: Randy Dunlap 
> Cc: Wayne Lin 
> Cc: Alex Deucher 
> Cc: Christian König 
> Cc: "Pan, Xinhui" 
> Cc: amd-...@lists.freedesktop.org
> Cc: dri-devel@lists.freedesktop.org
> ---
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |2 --
>  drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h |6 ++
>  2 files changed, 6 insertions(+), 2 deletions(-)
> 
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
> @@ -57,9 +57,7 @@
>  #include "amdgpu_dm_irq.h"
>  #include "dm_helpers.h"
>  #include "amdgpu_dm_mst_types.h"
> -#if defined(CONFIG_DEBUG_FS)
>  #include "amdgpu_dm_debugfs.h"
> -#endif
>  #include "amdgpu_dm_psr.h"
>  
>  #include "ivsrcid/ivsrcid_vislands30.h"
> --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
> +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
> @@ -31,6 +31,12 @@
>  
>  void connector_debugfs_init(struct amdgpu_dm_connector *connector);
>  void dtn_debugfs_init(struct amdgpu_device *adev);
> +
> +#ifdef CONFIG_DEBUG_FS
>  void crtc_debugfs_init(struct drm_crtc *crtc);
> +#else
> +static inline void crtc_debugfs_init(struct drm_crtc *crtc)
> +{}
> +#endif
>  
>  #endif



Re: [PATCH v4, 0/3] add h264 decoder driver for mt8186

2022-06-14 Thread Nicolas Dufresne
Le lundi 13 juin 2022 à 16:10 -0400, Nicolas Dufresne a écrit :
> Le jeudi 12 mai 2022 à 11:46 +0800, Yunfei Dong a écrit :
> > Firstly, add mt8186 compatible and private data, then add document for
> > compatible "mediatek,mt8186-vcodec-dec". For mt8186 is single core
> > architecture, need to add new interface for h264 hardware decoder.
> 
> Would be nice to take the habit of sharing fluster score for this new HW, I
> would expect no less then what the numbers you'd get from running over MT8195 
> or
> 92, remains nice to demonstrate that this was tested and document any oops 
> along
> the way.
> > 
> > Patche 1 add mt8186 compatible and private data.
> > Patche 2 add mt8186 compatible document.
> > Patche 3 add h264 single core driver.
> > ---
> > This patch depends on "support for MT8192 decoder"[1]
> > 
> > [1]  
> > https://patchwork.kernel.org/project/linux-mediatek/cover/20220512021950.29087-1-yunfei.d...@mediatek.com/

I forgot earlier, but I suppose this will also depends on an scp.img firmware ?
If so, any linux-firmware submission to link to ?

> > ---
> > changed with v3:
> > - fix __iomem not reasonable, align share memory to dram.
> > changed with v2:
> > - fix sparse and smatch check fail for patch 3
> > changed with v1:
> > - rebase driver to the latest media_stage.
> > ---
> > Yunfei Dong (3):
> >   dt-bindings: media: mediatek: vcodec: Adds decoder dt-bindings for
> > mt8186
> >   media: mediatek: vcodec: Support MT8186
> >   media: mediatek: vcodec: add h264 decoder driver for mt8186
> > 
> >  .../media/mediatek,vcodec-subdev-decoder.yaml |   4 +-
> >  .../platform/mediatek/vcodec/mtk_vcodec_dec.h |   1 +
> >  .../mediatek/vcodec/mtk_vcodec_dec_drv.c  |   4 +
> >  .../vcodec/mtk_vcodec_dec_stateless.c |  19 ++
> >  .../vcodec/vdec/vdec_h264_req_multi_if.c  | 177 +-
> >  5 files changed, 203 insertions(+), 2 deletions(-)
> > 
> 



Re: [PATCH 31/64] drm/vc4: dsi: Switch to drmm_of_get_bridge

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The current code uses a device-managed function to retrieve the next bridge
> downstream.
>
> However, that means that it will be removed at unbind time, where the DRM
> device is still very much live and might still have some applications that
> still have it open.
>
> Switch to a DRM-managed variant to clean everything up once the DRM device
> has been last closed.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dsi.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index bcaf87b43cbd..10533a2a41b3 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1584,7 +1584,7 @@ static int vc4_dsi_bind(struct device *dev, struct 
> device *master, void *data)
> return ret;
> }
>
> -   dsi->bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +   dsi->bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
> if (IS_ERR(dsi->bridge))
> return PTR_ERR(dsi->bridge);
>
> --
> 2.36.1
>


Re: [PATCH 30/64] drm/vc4: dsi: Switch to DRM-managed encoder initialization

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The current code will call drm_encoder_cleanup() when the device is
> unbound. However, by then, there might still be some references held to
> that encoder, including by the userspace that might still have the DRM
> device open.
>
> Let's switch to a DRM-managed initialization to clean up after ourselves
> only once the DRM device has been last closed.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dsi.c | 6 --
>  1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
> index dbb3f6fb39b4..bcaf87b43cbd 100644
> --- a/drivers/gpu/drm/vc4/vc4_dsi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dsi.c
> @@ -1599,7 +1599,10 @@ static int vc4_dsi_bind(struct device *dev, struct 
> device *master, void *data)
> if (ret)
> return ret;
>
> -   drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DSI);
> +   ret = drmm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_DSI);
> +   if (ret)
> +   return ret;
> +
> drm_encoder_helper_add(encoder, _dsi_encoder_helper_funcs);
>
> ret = drm_bridge_attach(encoder, dsi->bridge, NULL, 0);
> @@ -1632,7 +1635,6 @@ static void vc4_dsi_unbind(struct device *dev, struct 
> device *master,
>  * normally.
>  */
> list_splice_init(>bridge_chain, >bridge_chain);
> -   drm_encoder_cleanup(encoder);
>  }
>
>  static const struct component_ops vc4_dsi_ops = {
> --
> 2.36.1
>


Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND feature design document

2022-06-14 Thread Niranjana Vishwanathapura

On Tue, Jun 14, 2022 at 10:04:00AM +0300, Lionel Landwerlin wrote:

On 13/06/2022 21:02, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 06:33:07AM -0700, Zeng, Oak wrote:



Regards,
Oak


-Original Message-
From: Intel-gfx  On 
Behalf Of Niranjana

Vishwanathapura
Sent: June 10, 2022 1:43 PM
To: Landwerlin, Lionel G 
Cc: Intel GFX ; Maling list - 
DRI developers de...@lists.freedesktop.org>; Hellstrom, Thomas 
;

Wilson, Chris P ; Vetter, Daniel
; Christian König 
Subject: Re: [Intel-gfx] [RFC v3 1/3] drm/doc/rfc: VM_BIND 
feature design

document

On Fri, Jun 10, 2022 at 11:18:14AM +0300, Lionel Landwerlin wrote:

On 10/06/2022 10:54, Niranjana Vishwanathapura wrote:

On Fri, Jun 10, 2022 at 09:53:24AM +0300, Lionel Landwerlin wrote:

On 09/06/2022 22:31, Niranjana Vishwanathapura wrote:

On Thu, Jun 09, 2022 at 05:49:09PM +0300, Lionel Landwerlin wrote:

  On 09/06/2022 00:55, Jason Ekstrand wrote:

    On Wed, Jun 8, 2022 at 4:44 PM Niranjana Vishwanathapura
 wrote:

  On Wed, Jun 08, 2022 at 08:33:25AM +0100, Tvrtko 

Ursulin wrote:

  >
  >
  >On 07/06/2022 22:32, Niranjana Vishwanathapura wrote:
  >>On Tue, Jun 07, 2022 at 11:18:11AM -0700, Niranjana
Vishwanathapura
  wrote:
  >>>On Tue, Jun 07, 2022 at 12:12:03PM -0500, Jason
Ekstrand wrote:
   On Fri, Jun 3, 2022 at 6:52 PM Niranjana 

Vishwanathapura

    wrote:
  
     On Fri, Jun 03, 2022 at 10:20:25AM +0300, Lionel
Landwerlin
  wrote:
     >   On 02/06/2022 23:35, Jason Ekstrand wrote:
     >
     > On Thu, Jun 2, 2022 at 3:11 PM Niranjana
Vishwanathapura
     >  wrote:
     >
     >   On Wed, Jun 01, 2022 at 01:28:36PM 

-0700, Matthew

  Brost wrote:
     >   >On Wed, Jun 01, 2022 at 05:25:49PM 

+0300, Lionel

  Landwerlin
     wrote:
     > >> On 17/05/2022 21:32, Niranjana Vishwanathapura
  wrote:
     > >> > +VM_BIND/UNBIND ioctl will immediately start
     binding/unbinding
     >   the mapping in an
     > >> > +async worker. The binding and
unbinding will
  work like a
     special
     >   GPU engine.
     > >> > +The binding and unbinding operations are
  serialized and
     will
     >   wait on specified
     > >> > +input fences before the operation
and will signal
  the
     output
     >   fences upon the
     > >> > +completion of the operation. Due to
  serialization,
     completion of
     >   an operation
     > >> > +will also indicate that all
previous operations
  are also
     > complete.
     > >>
     > >> I guess we should avoid saying "will
immediately
  start
     > binding/unbinding" if
     > >> there are fences involved.
     > >>
     > >> And the fact that it's happening in an async
  worker seem to
     imply
     >   it's not
     > >> immediate.
     > >>
     >
     >   Ok, will fix.
     >   This was added because in earlier design
binding was
  deferred
     until
     >   next execbuff.
     >   But now it is non-deferred (immediate in
that sense).
  But yah,
     this is
     > confusing
     >   and will fix it.
     >
     > >>
     > >> I have a question on the behavior of the bind
  operation when
     no
     >   input fence
     > >> is provided. Let say I do :
     > >>
     > >> VM_BIND (out_fence=fence1)
     > >>
     > >> VM_BIND (out_fence=fence2)
     > >>
     > >> VM_BIND (out_fence=fence3)
     > >>
     > >>
     > >> In what order are the fences going to
be signaled?
     > >>
     > >> In the order of VM_BIND ioctls? Or out
of order?
     > >>
     > >> Because you wrote "serialized I assume
it's : in
  order
     > >>
     >
     >   Yes, in the order of VM_BIND/UNBIND
ioctls. Note that
  bind and
     unbind
     >   will use
     >   the same queue and hence are ordered.
     >
     > >>
     > >> One thing I didn't realize is that
because we only
  get one
     > "VM_BIND" engine,
     > >> there is a disconnect from the Vulkan
specification.
     > >>
     > >> In Vulkan VM_BIND operations are
serialized but
  per engine.
     > >>
     > >> So you could have something like this :
     > >>
     > >> VM_BIND (engine=rcs0, in_fence=fence1,
  out_fence=fence2)
     > >>
   

Re: [PATCH 13/64] drm/vc4: hvs: Protect device resources after removal

2022-06-14 Thread Dave Stevenson
On Tue, 14 Jun 2022 at 16:11, Dave Stevenson
 wrote:
>
> Hi Maxime
>
> On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
> >
> > Whenever the device and driver are unbound, the main device and all the
> > subdevices will be removed by calling their unbind() method.
> >
> > However, the DRM device itself will only be freed when the last user will
> > have closed it.
> >
> > It means that there is a time window where the device and its resources
> > aren't there anymore, but the userspace can still call into our driver.
> >
> > Fortunately, the DRM framework provides the drm_dev_enter() and
> > drm_dev_exit() functions to make sure our underlying device is still there
> > for the section protected by those calls. Let's add them to the HVS driver.
>
> The framework appears to rely on the remove function calling
> drm_dev_unplug instead of drm_dev_unregister, but I haven't seen a
> patch that makes that change in the vc4 driver.
> Have I missed it, or is there some other route to set the unplugged
> flag that drm_dev_enter/exit are relying on?
>
>   Dave
>
> > Signed-off-by: Maxime Ripard 
> > ---
> >  drivers/gpu/drm/vc4/vc4_drv.h |   1 +
> >  drivers/gpu/drm/vc4/vc4_hvs.c | 106 +++---
> >  2 files changed, 99 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> > index aa4c5910ea05..080deae55f64 100644
> > --- a/drivers/gpu/drm/vc4/vc4_drv.h
> > +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> > @@ -317,6 +317,7 @@ struct vc4_v3d {
> >  };
> >
> >  struct vc4_hvs {
> > +   struct drm_device *dev;
> > struct platform_device *pdev;
> > void __iomem *regs;
> > u32 __iomem *dlist;
> > diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> > index 2a58fc421cf6..483053e7b14f 100644
> > --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> > +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> > @@ -25,6 +25,7 @@
> >  #include 
> >
> >  #include 
> > +#include 
> >  #include 
> >
> >  #include "vc4_drv.h"
> > @@ -66,11 +67,15 @@ static const struct debugfs_reg32 hvs_regs[] = {
> >
> >  void vc4_hvs_dump_state(struct vc4_hvs *hvs)
> >  {
> > +   struct drm_device *drm = hvs->dev;
> > struct drm_printer p = drm_info_printer(>pdev->dev);
> > -   int i;
> > +   int idx, i;
> >
> > drm_print_regset32(, >regset);
> >
> > +   if (!drm_dev_enter(drm, ))
> > +   return;
> > +
> > DRM_INFO("HVS ctx:\n");
> > for (i = 0; i < 64; i += 4) {
> > DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
> > @@ -80,6 +85,8 @@ void vc4_hvs_dump_state(struct vc4_hvs *hvs)
> >  readl((u32 __iomem *)hvs->dlist + i + 2),
> >  readl((u32 __iomem *)hvs->dlist + i + 3));
> > }
> > +
> > +   drm_dev_exit(idx);
> >  }
> >
> >  static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
> > @@ -132,14 +139,18 @@ static int vc4_hvs_upload_linear_kernel(struct 
> > vc4_hvs *hvs,
> > struct drm_mm_node *space,
> > const u32 *kernel)
> >  {
> > -   int ret, i;
> > +   struct drm_device *drm = hvs->dev;
> > +   int idx, ret, i;
> > u32 __iomem *dst_kernel;
> >
> > +   if (!drm_dev_enter(drm, ))
> > +   return -ENODEV;
> > +

vc4_hvs_upload_linear_kernel is only called from vc4_hvs_bind, so
unless bind and unbind calls can be concurrent, then there's no need
for protection here.

> > ret = drm_mm_insert_node(>dlist_mm, space, VC4_KERNEL_DWORDS);
> > if (ret) {
> > DRM_ERROR("Failed to allocate space for filter kernel: 
> > %d\n",
> >   ret);
> > -   return ret;
> > +   goto err_dev_exit;
> > }
> >
> > dst_kernel = hvs->dlist + space->start;
> > @@ -153,16 +164,26 @@ static int vc4_hvs_upload_linear_kernel(struct 
> > vc4_hvs *hvs,
> > }
> > }
> >
> > +   drm_dev_exit(idx);
> > return 0;
> > +
> > +err_dev_exit:
> > +   drm_dev_exit(idx);
> > +   return ret;
> >  }
> >
> >  static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
> >  struct vc4_crtc *vc4_crtc)
> >  {
> > +   struct drm_device *drm = hvs->dev;
> > struct drm_crtc *crtc = _crtc->base;
> > struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> > +   int idx;
> > u32 i;
> >
> > +   if (!drm_dev_enter(drm, ))
> > +   return;
> > +
> > /* The LUT memory is laid out with each HVS channel in order,
> >  * each of which takes 256 writes for R, 256 for G, then 256
> >  * for B.
> > @@ -177,6 +198,8 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
> > HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
> > for (i = 0; i < crtc->gamma_size; i++)
> > 

Re: [PATCH v2 7/7] drm/bridge: anx7625: Add typec_mux_set callback function

2022-06-14 Thread Prashant Malani
On Tue, Jun 14, 2022 at 2:08 AM Pin-yen Lin  wrote:
>
> Hi AngeloGioacchino,
>
>
> On Tue, Jun 14, 2022 at 4:15 PM AngeloGioacchino Del Regno
>  wrote:
> >
> > Il 09/06/22 20:09, Prashant Malani ha scritto:
> > > From: Pin-Yen Lin 
> > >
> > > Add the callback function when the driver receives state
> > > changes of the Type-C port. The callback function configures the
> > > crosspoint switch of the anx7625 bridge chip, which can change the
> > > output pins of the signals according to the port state.
> > >
> > > Signed-off-by: Pin-Yen Lin 
> > > Signed-off-by: Prashant Malani 
> > > ---
> > >
> > > Changes since v2:
> > > - No changes.
> > >
> > >   drivers/gpu/drm/bridge/analogix/anx7625.c | 58 +++
> > >   drivers/gpu/drm/bridge/analogix/anx7625.h | 13 +
> > >   2 files changed, 71 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> > > b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > index d41a21103bd3..2c308d12fab2 100644
> > > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > > @@ -15,6 +15,7 @@
> > >   #include 
> > >   #include 
> > >   #include 
> > > +#include 
> > >   #include 
> > >   #include 
> > >
> > > @@ -2582,9 +2583,66 @@ static void anx7625_runtime_disable(void *data)
> > >   pm_runtime_disable(data);
> > >   }
> > >
> > > +static void anx7625_set_crosspoint_switch(struct anx7625_data *ctx,
> > > +   enum typec_orientation 
> > > orientation)
> > > +{
> > > + if (orientation == TYPEC_ORIENTATION_NORMAL) {
> > > + anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
> > > +   SW_SEL1_SSRX_RX1 | SW_SEL1_DPTX0_RX2);
> > > + anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
> > > +   SW_SEL2_SSTX_TX1 | SW_SEL2_DPTX1_TX2);
> > > + } else if (orientation == TYPEC_ORIENTATION_REVERSE) {
> > > + anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_0,
> > > +   SW_SEL1_SSRX_RX2 | SW_SEL1_DPTX0_RX1);
> > > + anx7625_reg_write(ctx, ctx->i2c.tcpc_client, TCPC_SWITCH_1,
> > > +   SW_SEL2_SSTX_TX2 | SW_SEL2_DPTX1_TX1);
> > > + }
> > > +}
> > > +
> > > +static void anx7625_typec_two_ports_update(struct anx7625_data *ctx)
> > > +{
> > > + if (ctx->typec_ports[0].dp_connected && 
> > > ctx->typec_ports[1].dp_connected)
> > > + /* Both ports available, do nothing to retain the current 
> > > one. */
> > > + return;
> > > + else if (ctx->typec_ports[0].dp_connected)
> > > + anx7625_set_crosspoint_switch(ctx, 
> > > TYPEC_ORIENTATION_NORMAL);
> > > + else if (ctx->typec_ports[1].dp_connected)
> > > + anx7625_set_crosspoint_switch(ctx, 
> > > TYPEC_ORIENTATION_REVERSE);
> > > +}
> > > +
> > >   static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
> > >struct typec_mux_state *state)
> > >   {
> > > + struct anx7625_port_data *data = typec_mux_get_drvdata(mux);
> > > + struct anx7625_data *ctx = data->ctx;
> > > + struct device *dev = >client->dev;
> > > +
> > > + bool old_dp_connected = (ctx->typec_ports[0].dp_connected ||
> > > +  ctx->typec_ports[1].dp_connected);
> >
> > So the old connection state is "either port0 or port1 are currently 
> > connected"...
> >
> > > + bool new_dp_connected;
> > > +
> > > + if (ctx->num_typec_switches == 1)
> > > + return 0;
> > > +
> > > + dev_dbg(dev, "mux_set dp_connected: c0=%d, c1=%d\n",
> > > + ctx->typec_ports[0].dp_connected, 
> > > ctx->typec_ports[1].dp_connected);
> > > +
> > > + data->dp_connected = (state->alt && state->alt->svid == 
> > > USB_TYPEC_DP_SID &&
> > > +   state->alt->mode == USB_TYPEC_DP_MODE);
> > > + > + new_dp_connected = (ctx->typec_ports[0].dp_connected ||
> > > + ctx->typec_ports[1].dp_connected);
> >
> > ...and the new connection state is the same as the old one, because I don't 
> > see
> > anything that could ever modify it in this function's flow, until reaching 
> > this
> > assignment.
>
> The typec mux driver data (`struct anx7625_port_data *data =
> typec_mux_get_drvdata(mux)`) is set to one of the
> `ctx->typec_ports[*]` in `anx7625_register_mode_switch` (see patch 6
> of this series).
>
> So, the `data->dp_connected = ...` assignment may change the new
> connection state.

Angelo, I think your interpretation of this logic is not accurate..
|old_dp_connected| represents *whether* port1 or port0 has a DP
partner connected, not that *either* of them has it.

So, this logic looks OK to me.


>
> Best regards,
> Pin-yen
>
> >
> > > +
> > > + /* dp on, power on first */
> > > + if (!old_dp_connected && new_dp_connected)
> > > + 

Re: [PATCH v2 6/7] drm/bridge: anx7625: Register Type-C mode switches

2022-06-14 Thread Prashant Malani
On Tue, Jun 14, 2022 at 1:18 AM AngeloGioacchino Del Regno
 wrote:
>
> Il 09/06/22 20:09, Prashant Malani ha scritto:
> > When the DT node has "switches" available, register a Type-C mode-switch
> > for each listed "switch". This allows the driver to receive state
> > information about what operating mode a Type-C port and its connected
> > peripherals are in, as well as status information (like VDOs) related to
> > that state.
> >
> > The callback function is currently a stub, but subsequent patches will
> > implement the required functionality.
> >
> > Signed-off-by: Prashant Malani 
> > ---
> >
> > Changes since v2:
> > - No changes.
> >
> >   drivers/gpu/drm/bridge/analogix/anx7625.c | 73 +++
> >   drivers/gpu/drm/bridge/analogix/anx7625.h |  6 ++
> >   2 files changed, 79 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c 
> > b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > index 07ed44c6b839..d41a21103bd3 100644
> > --- a/drivers/gpu/drm/bridge/analogix/anx7625.c
> > +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c
> > @@ -15,6 +15,7 @@
> >   #include 
> >   #include 
> >   #include 
> > +#include 
> >   #include 
> >
> >   #include 
> > @@ -2581,9 +2582,59 @@ static void anx7625_runtime_disable(void *data)
> >   pm_runtime_disable(data);
> >   }
> >
> > +static int anx7625_typec_mux_set(struct typec_mux_dev *mux,
> > +  struct typec_mux_state *state)
> > +{
> > + return 0;
> > +}
> > +
> > +static int anx7625_register_mode_switch(struct device *dev, struct 
> > device_node *node,
> > + struct anx7625_data *ctx)
> > +{
> > + struct anx7625_port_data *port_data;
> > + struct typec_mux_desc mux_desc = {};
> > + char name[32];
> > + u32 port_num;
> > + int ret;
> > +
> > + ret = of_property_read_u32(node, "reg", _num);
> > + if (ret)
> > + return ret;
> > +
> > + if (port_num >= ctx->num_typec_switches) {
> > + dev_err(dev, "Invalid port number specified: %d\n", port_num);
> > + return -EINVAL;
> > + }
> > +
> > + port_data = >typec_ports[port_num];
> > + port_data->ctx = ctx;
> > + mux_desc.fwnode = >fwnode;
> > + mux_desc.drvdata = port_data;
> > + snprintf(name, sizeof(name), "%s-%u", node->name, port_num);
> > + mux_desc.name = name;
> > + mux_desc.set = anx7625_typec_mux_set;
> > +
> > + port_data->typec_mux = typec_mux_register(dev, _desc);
> > + if (IS_ERR(port_data->typec_mux)) {
> > + ret = PTR_ERR(port_data->typec_mux);
> > + dev_err(dev, "Mode switch register for port %d failed: %d", 
> > port_num, ret);
> > + }
>
> Please return 0 at the end of this function.
>
> if (IS_ERR()) {
> ..code..
> return ret;
> }
>
> return 0;
> }

May I ask why? We're not missing any return paths. I would rather we
keep it as is (which has the valid return value).

>
> > +
> > + return ret;
> > +}
> > +
> > +static void anx7625_unregister_typec_switches(struct anx7625_data *ctx)
> > +{
> > + int i;
> > +
> > + for (i = 0; i < ctx->num_typec_switches; i++)
> > + typec_mux_unregister(ctx->typec_ports[i].typec_mux);
> > +}
> > +
> >   static int anx7625_register_typec_switches(struct device *device, struct 
> > anx7625_data *ctx)
> >   {
> >   struct device_node *of = NULL;
> > + struct device_node *sw;
> >   int ret = 0;
> >
> >   of = of_get_child_by_name(device->of_node, "switches");
> > @@ -2594,6 +2645,26 @@ static int anx7625_register_typec_switches(struct 
> > device *device, struct anx7625
> >   if (ctx->num_typec_switches <= 0)
> >   return -ENODEV;
> >
> > + ctx->typec_ports = devm_kzalloc(device,
> > + ctx->num_typec_switches * 
> > sizeof(struct anx7625_port_data),
> > + GFP_KERNEL);
> > + if (!ctx->typec_ports)
> > + return -ENOMEM;
> > +
> > + /* Register switches for each connector. */
> > + for_each_available_child_of_node(of, sw) {
> > + if (!of_property_read_bool(sw, "mode-switch"))
> > + continue;
> > + ret = anx7625_register_mode_switch(device, sw, ctx);
> > + if (ret) {
> > + dev_err(device, "Failed to register mode switch: 
> > %d\n", ret);
> > + break;
> > + }
> > + }
> > +
> > + if (ret)
> > + anx7625_unregister_typec_switches(ctx);
> > +
> >   return ret;
> >   }
> >
> > @@ -2759,6 +2830,8 @@ static int anx7625_i2c_remove(struct i2c_client 
> > *client)
> >
> >   drm_bridge_remove(>bridge);
> >
> > + anx7625_unregister_typec_switches(platform);
> > +
> >   if (platform->pdata.intp_irq)
> >   destroy_workqueue(platform->workqueue);
> >
> > diff --git 

Re: [PATCH 28/64] drm/vc4: dpi: Protect device resources

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Our current code now mixes some resources whose lifetime are tied to the
> device (clocks, IO mappings, etc.) and some that are tied to the DRM device
> (encoder, bridge).
>
> The device one will be freed at unbind time, but the DRM one will only be
> freed when the last user of the DRM device closes its file handle.
>
> So we end up with a time window during which we can call the encoder hooks,
> but we don't have access to the underlying resources and device.
>
> Let's protect all those sections with drm_dev_enter() and drm_dev_exit() so
> that we bail out if we are during that window.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 14 ++
>  1 file changed, 14 insertions(+)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 9950761449cf..ea3d20651f43 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -13,6 +13,7 @@
>
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -111,9 +112,16 @@ static const struct debugfs_reg32 dpi_regs[] = {
>
>  static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
>  {
> +   struct drm_device *dev = encoder->dev;
> struct vc4_dpi *dpi = to_vc4_dpi(encoder);
> +   int idx;
> +
> +   if (!drm_dev_enter(dev, ))
> +   return;
>
> clk_disable_unprepare(dpi->pixel_clock);
> +
> +   drm_dev_exit(idx);
>  }
>
>  static void vc4_dpi_encoder_enable(struct drm_encoder *encoder)
> @@ -124,6 +132,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder 
> *encoder)
> struct drm_connector_list_iter conn_iter;
> struct drm_connector *connector = NULL, *connector_scan;
> u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
> +   int idx;
> int ret;
>
> /* Look up the connector attached to DPI so we can get the
> @@ -184,6 +193,9 @@ static void vc4_dpi_encoder_enable(struct drm_encoder 
> *encoder)
> else if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
> dpi_c |= DPI_VSYNC_DISABLE;
>
> +   if (!drm_dev_enter(dev, ))
> +   return;
> +
> DPI_WRITE(DPI_C, dpi_c);
>
> ret = clk_set_rate(dpi->pixel_clock, mode->clock * 1000);
> @@ -193,6 +205,8 @@ static void vc4_dpi_encoder_enable(struct drm_encoder 
> *encoder)
> ret = clk_prepare_enable(dpi->pixel_clock);
> if (ret)
> DRM_ERROR("Failed to set clock rate: %d\n", ret);
> +
> +   drm_dev_exit(idx);
>  }
>
>  static enum drm_mode_status vc4_dpi_encoder_mode_valid(struct drm_encoder 
> *encoder,
> --
> 2.36.1
>


Re: [PATCH 27/64] drm/vc4: dpi: Switch to drmm_of_get_bridge

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The current code uses a device-managed function to retrieve the next bridge
> downstream.
>
> However, that means that it will be removed at unbind time, where the DRM
> device is still very much live and might still have some applications that
> still have it open.
>
> Switch to a DRM-managed variant to clean everything up once the DRM device
> has been last closed.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 8a50de2c40d9..9950761449cf 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -220,10 +220,11 @@ static const struct of_device_id vc4_dpi_dt_match[] = {
>   */
>  static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
>  {
> +   struct drm_device *drm = dpi->encoder.base.dev;
> struct device *dev = >pdev->dev;
> struct drm_bridge *bridge;
>
> -   bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0);
> +   bridge = drmm_of_get_bridge(drm, dev->of_node, 0, 0);
> if (IS_ERR(bridge)) {
> /* If nothing was connected in the DT, that's not an
>  * error.
> --
> 2.36.1
>


Re: [PATCH 26/64] drm/vc4: dpi: Switch to DRM-managed encoder initialization

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The current code will call drm_encoder_cleanup() when the device is
> unbound. However, by then, there might still be some references held to
> that encoder, including by the userspace that might still have the DRM
> device open.
>
> Let's switch to a DRM-managed initialization to clean up after ourselves
> only once the DRM device has been last closed.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 20 +---
>  1 file changed, 5 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 4e24dbad77f2..8a50de2c40d9 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -296,35 +296,25 @@ static int vc4_dpi_bind(struct device *dev, struct 
> device *master, void *data)
> if (ret)
> return ret;
>
> -   drm_simple_encoder_init(drm, >encoder.base, 
> DRM_MODE_ENCODER_DPI);
> +   ret = drmm_simple_encoder_init(drm, >encoder.base, 
> DRM_MODE_ENCODER_DPI);
> +   if (ret)
> +   return ret;
> +
> drm_encoder_helper_add(>encoder.base, 
> _dpi_encoder_helper_funcs);
>
> ret = vc4_dpi_init_bridge(dpi);
> if (ret)
> -   goto err_destroy_encoder;
> +   return ret;
>
> dev_set_drvdata(dev, dpi);
>
> vc4_debugfs_add_regset32(drm, "dpi_regs", >regset);
>
> return 0;
> -
> -err_destroy_encoder:
> -   drm_encoder_cleanup(>encoder.base);
> -   return ret;
> -}
> -
> -static void vc4_dpi_unbind(struct device *dev, struct device *master,
> -  void *data)
> -{
> -   struct vc4_dpi *dpi = dev_get_drvdata(dev);
> -
> -   drm_encoder_cleanup(>encoder.base);
>  }
>
>  static const struct component_ops vc4_dpi_ops = {
> .bind   = vc4_dpi_bind,
> -   .unbind = vc4_dpi_unbind,
>  };
>
>  static int vc4_dpi_dev_probe(struct platform_device *pdev)
> --
> 2.36.1
>


Re: [PATCH 25/64] drm/vc4: dpi: Add action to disable the clock

2022-06-14 Thread Dave Stevenson
Hi Maxime.

On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Adding a device-managed action will make the error path easier, so let's
> create one to disable our clock.

The DPI block has two clocks (core and pixel), and this is only
affecting one of them (the core clock).
(I'm actually puzzling over what it's wanting to do with the core
clock here as it's only enabling it rather than setting a rate. I
think it may be redundant).

With that text amended:
Reviewed-by: Dave Stevenson 

  Dave

> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 14 +++---
>  1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 5a6cdea7bf7b..4e24dbad77f2 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -237,6 +237,13 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
> return drm_bridge_attach(>encoder.base, bridge, NULL, 0);
>  }
>
> +static void vc4_dpi_disable_clock(void *ptr)
> +{
> +   struct vc4_dpi *dpi = ptr;
> +
> +   clk_disable_unprepare(dpi->core_clock);
> +}
> +
>  static int vc4_dpi_bind(struct device *dev, struct device *master, void 
> *data)
>  {
> struct platform_device *pdev = to_platform_device(dev);
> @@ -285,6 +292,10 @@ static int vc4_dpi_bind(struct device *dev, struct 
> device *master, void *data)
> return ret;
> }
>
> +   ret = devm_add_action_or_reset(dev, vc4_dpi_disable_clock, dpi);
> +   if (ret)
> +   return ret;
> +
> drm_simple_encoder_init(drm, >encoder.base, 
> DRM_MODE_ENCODER_DPI);
> drm_encoder_helper_add(>encoder.base, 
> _dpi_encoder_helper_funcs);
>
> @@ -300,7 +311,6 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
>
>  err_destroy_encoder:
> drm_encoder_cleanup(>encoder.base);
> -   clk_disable_unprepare(dpi->core_clock);
> return ret;
>  }
>
> @@ -310,8 +320,6 @@ static void vc4_dpi_unbind(struct device *dev, struct 
> device *master,
> struct vc4_dpi *dpi = dev_get_drvdata(dev);
>
> drm_encoder_cleanup(>encoder.base);
> -
> -   clk_disable_unprepare(dpi->core_clock);
>  }
>
>  static const struct component_ops vc4_dpi_ops = {
> --
> 2.36.1
>


Re: [Intel-gfx] [PATCH 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-14 Thread Niranjana Vishwanathapura

On Tue, Jun 14, 2022 at 05:07:37PM +0100, Tvrtko Ursulin wrote:


On 14/06/2022 17:02, Tvrtko Ursulin wrote:


On 14/06/2022 16:43, Niranjana Vishwanathapura wrote:

On Tue, Jun 14, 2022 at 08:16:41AM +0100, Tvrtko Ursulin wrote:


On 14/06/2022 00:39, Matthew Brost wrote:

On Mon, Jun 13, 2022 at 07:09:06PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 18:49, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 05:22:02PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 16:05, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 09:24:18AM +0100, Tvrtko Ursulin wrote:


On 10/06/2022 17:14, Niranjana Vishwanathapura wrote:
On Fri, Jun 10, 2022 at 05:48:39PM +0300, Lionel 
Landwerlin wrote:

On 10/06/2022 13:37, Tvrtko Ursulin wrote:


On 10/06/2022 08:07, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

Signed-off-by: Niranjana Vishwanathapura

---
  Documentation/gpu/rfc/i915_vm_bind.h | 490
+++
  1 file changed, 490 insertions(+)
  create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git
a/Documentation/gpu/rfc/i915_vm_bind.h
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..9fc854969cfb
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ * bit[0]: If set, VM_BIND is supported, otherwise not.
+ * bits[8-15]: VM_BIND implementation version.
+ * version 0 will not have VM_BIND/UNBIND
timeline fence array support.
+ */
+#define I915_PARAM_HAS_VM_BIND    57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of 
binding during VM creation.

+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * The older execbuf2 ioctl will not
support VM_BIND mode of operation.
+ * For VM_BIND mode, we have new execbuf3
ioctl which will not accept any
+ * execlist (See struct
drm_i915_gem_execbuffer3 for more details).
+ *
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND    (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they
complete in reasonable amount of time.
+ * Compute on the other hand can be long
running. Hence it is not appropriate
+ * for compute contexts to export request
completion dma-fence to user.
+ * The dma-fence usage will be limited to
in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support 
output fences. Hence,

+ * I915_EXEC_FENCE_SIGNAL (See
_i915_gem_exec_fence.flags) is expected
+ * to be not used. DRM_I915_GEM_WAIT ioctl
call is also not supported for
+ * objects mapped to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND    0x3d
+#define DRM_I915_GEM_VM_UNBIND    0x3e
+#define DRM_I915_GEM_EXECBUFFER3    0x3f
+#define DRM_I915_GEM_WAIT_USER_FENCE    0x40
+
+#define DRM_IOCTL_I915_GEM_VM_BIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_BIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_UNBIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER3
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_EXECBUFFER3, struct
drm_i915_gem_execbuffer3)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_WAIT_USER_FENCE, struct
drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to 
object mapping to bind.

+ *
+ * This structure is passed to VM_BIND
ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the
section of an object that should be bound
+ * in the device page table of the 
specified address space (VM).

+ * The VA range specified must be unique
(ie., not currently bound) and can
+ * be mapped to whole object or a section
of the object (partial binding).
+ * Multiple VA mappings can be created to
the same section of the object
+ * (aliasing).
+ *
+ * The @queue_idx specifies the queue to
use for binding. Same queue can be
+ * used for both VM_BIND and VM_UNBIND
calls. All submitted bind and unbind
+ * operations in a queue are performed in 
the order of submission.

+ *
+ * The @start, @offset and @length should
be 4K page aligned. However the DG2
+ * and XEHPSDV has 64K page size for device
local-memory and has compact page
+ * table. On those platforms, for binding
device local-memory objects, the
+ * @start should be 2M aligned, @offset and
@length should be 64K aligned.
+ * Also, on those platforms, it is not
allowed to bind an device local-memory
+ * object and a system memory object in a
single 2M section of VA range.
+ */
+struct drm_i915_gem_vm_bind {
+    

Re: [PATCH 24/64] drm/vc4: dpi: Remove unnecessary drm_of_panel_bridge_remove call

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Since we have a managed call to create our panel_bridge instance, the call
> to drm_of_panel_bridge_remove() at unbind is both redundant and dangerous
> since it might lead to a use-after-free.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 2 --
>  1 file changed, 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index 658e0aa9e2e1..5a6cdea7bf7b 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -309,8 +309,6 @@ static void vc4_dpi_unbind(struct device *dev, struct 
> device *master,
>  {
> struct vc4_dpi *dpi = dev_get_drvdata(dev);
>
> -   drm_of_panel_bridge_remove(dev->of_node, 0, 0);
> -
> drm_encoder_cleanup(>encoder.base);
>
> clk_disable_unprepare(dpi->core_clock);
> --
> 2.36.1
>


Re: [PATCH] drm/msm/mdp4: Fix refcount leak in mdp4_modeset_init_intf

2022-06-14 Thread Abhinav Kumar




On 6/14/2022 3:09 AM, Dmitry Baryshkov wrote:

On 14/06/2022 13:07, Miaoqian Lin wrote:

Hi, Abhinav

On 2022/6/11 7:20, Abhinav Kumar wrote:



On 6/7/2022 4:08 AM, Miaoqian Lin wrote:

of_graph_get_remote_node() returns remote device node pointer with
refcount incremented, we should use of_node_put() on it
when not need anymore.
Add missing of_node_put() to avoid refcount leak.

Fixes: 86418f90a4c1 ("drm: convert drivers to use 
of_graph_get_remote_node")

Signed-off-by: Miaoqian Lin 
---
   drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c | 2 ++
   1 file changed, 2 insertions(+)



This patch itself looks fine and will cover the cases when there was 
an error and we did not release the refcount.


But, even in the normal cases I am not finding where we are releasing 
the refcount for the panel_node.


I dont see a of_node_put() on mdp4_lcdc_encoder->panel_node.


Thanks for your review.

I don't see it either. It's a bit messy because the reference assigned 
to mdp4_lcdc_encoder->panel_node and mdp4_lvds_connector->panel_node 
both.


I have a plan to rework mdp4 lcdc support once I get my ifc6410 lvds 
cable. Thus I think we can land this patch now and fix the mdp4 
lcdc/lvds code leaking the reference in the due time.




Alright, with that assurance,

Reviewed-by: Abhinav Kumar 

Will pick it up for -fixes.



Am i missing something?

diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c 
b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c

index fb48c8c19ec3..17cb1fc78379 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -216,6 +216,7 @@ static int mdp4_modeset_init_intf(struct 
mdp4_kms *mdp4_kms,

   encoder = mdp4_lcdc_encoder_init(dev, panel_node);
   if (IS_ERR(encoder)) {
   DRM_DEV_ERROR(dev->dev, "failed to construct LCDC 
encoder\n");

+    of_node_put(panel_node);
   return PTR_ERR(encoder);
   }
   @@ -225,6 +226,7 @@ static int mdp4_modeset_init_intf(struct 
mdp4_kms *mdp4_kms,
   connector = mdp4_lvds_connector_init(dev, panel_node, 
encoder);

   if (IS_ERR(connector)) {
   DRM_DEV_ERROR(dev->dev, "failed to initialize LVDS 
connector\n");

+    of_node_put(panel_node);
   return PTR_ERR(connector);
   }





Re: [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Dixit, Ashutosh
On Thu, 02 Jun 2022 10:21:19 -0700, Zhanjun Dong wrote:
>

Hi Zhanjun,

> We are seeing error message of "No response for request". Some cases happened
> while waiting for response and reset/suspend action was triggered. In this
> case, no response is not an error, active requests will be cancelled.
>
> This patch will handle this condition and change the error message into
> debug message.

IMO the patch title should be changed: which ctx are we checking while
waiting for response? Something like "check for ct enabled while waiting
for response"?

> @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct ct_request 
> *req, u32 *status)
>  #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
>  #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
>  #define done \
> - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> READ_ONCE(req->status)) == \
>GUC_HXG_ORIGIN_GUC)
>   err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
>   if (err)
>   err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
>  #undef done
> + if (!intel_guc_ct_enabled(ct))
> + err = -ECANCELED;

Also, I really don't like intel_guc_ct_enabled() being called in two
places. Is there a possibility that intel_guc_ct_enabled() can return false
in the first place (causing the wait to exit) and then return true in the
second place (so we don't return -ECANCELED)?

Is it possible to change the status of the request to something else from
intel_guc_ct_disable() (or wherever ct->enabled is set to false) rather
than introducing intel_guc_ct_enabled() checks here. Changing the status of
the request when CT goes down would cause the wait's to exit here. And then
we can check that special request status signifying CT went down?

Thanks.
--
Ashutosh


Re: [Intel-gfx] [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Jani Nikula
On Thu, 02 Jun 2022, Zhanjun Dong  wrote:
> We are seeing error message of "No response for request". Some cases happened
> while waiting for response and reset/suspend action was triggered. In this
> case, no response is not an error, active requests will be cancelled.
>
> This patch will handle this condition and change the error message into
> debug message.
>
> Signed-off-by: Zhanjun Dong 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index f01325cd1b62..a30a388877e2 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -467,7 +467,7 @@ static int ct_write(struct intel_guc_ct *ct,
>   * * 0 response received (status is valid)
>   * * -ETIMEDOUT no response within hardcoded timeout
>   */
> -static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
> +static int wait_for_ct_request_update(struct ct_request *req, u32 *status, 
> struct intel_guc_ct *ct)
>  {
>   int err;
>  
> @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct ct_request 
> *req, u32 *status)
>  #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
>  #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
>  #define done \
> - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> READ_ONCE(req->status)) == \
>GUC_HXG_ORIGIN_GUC)
>   err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
>   if (err)
>   err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
>  #undef done
> + if (!intel_guc_ct_enabled(ct))
> + err = -ECANCELED;
>  
>   *status = req->status;
>   return err;
> @@ -703,11 +705,15 @@ static int ct_send(struct intel_guc_ct *ct,
>  
>   intel_guc_notify(ct_to_guc(ct));
>  
> - err = wait_for_ct_request_update(, status);
> + err = wait_for_ct_request_update(, status, ct);
>   g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
>   if (unlikely(err)) {
> - CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> -  action[0], request.fence);
> + if (unlikely(err == ECANCELED))

I think you mean -ECANCELED, not ECANCELED.

Please drop the unlikely(). I no longer want to see a single unlikely()
or likely() added anywhere without proper performance
justification. They make the code harder to read, for no real benefit,
and people just cargo cult copy paste them everywhere. Moreover, nested
unlikely/likely is just silly.

> + CT_DEBUG(ct, "Request %#x (fence %u) cancelled as CTB 
> is disabled\n",
> + action[0], request.fence);
> + else
> + CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> + action[0], request.fence);
>   goto unlink;
>   }
>  
> @@ -771,8 +777,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 
> *action, u32 len,
>  
>   ret = ct_send(ct, action, len, response_buf, response_buf_size, 
> );
>   if (unlikely(ret < 0)) {
> - CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n",
> -  action[0], ERR_PTR(ret), status);
> + if (likely(ret != ECANCELED))

Ditto for -ECANCELED and likely().

BR,
Jani.

> + CT_ERROR(ct, "Sending action %#x failed (%pe) 
> status=%#X\n",
> + action[0], ERR_PTR(ret), status);
>   } else if (unlikely(ret)) {
>   CT_DEBUG(ct, "send action %#x returned %d (%#x)\n",
>action[0], ret, ret);

-- 
Jani Nikula, Intel Open Source Graphics Center


Re: [PATCH 23/64] drm/vc4: dpi: Return an error if we can't enable our clock

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> If we fail to enable the DPI clock, we just ignore the error and moves
> forward. Let's return an error instead.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index d1eaafb43bd1..658e0aa9e2e1 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -270,6 +270,7 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
> DRM_ERROR("Failed to get core clock: %d\n", ret);
> return ret;
> }
> +
> dpi->pixel_clock = devm_clk_get(dev, "pixel");
> if (IS_ERR(dpi->pixel_clock)) {
> ret = PTR_ERR(dpi->pixel_clock);
> @@ -279,8 +280,10 @@ static int vc4_dpi_bind(struct device *dev, struct 
> device *master, void *data)
> }
>
> ret = clk_prepare_enable(dpi->core_clock);
> -   if (ret)
> +   if (ret) {
> DRM_ERROR("Failed to turn on core clock: %d\n", ret);
> +   return ret;
> +   }
>
> drm_simple_encoder_init(drm, >encoder.base, 
> DRM_MODE_ENCODER_DPI);
> drm_encoder_helper_add(>encoder.base, 
> _dpi_encoder_helper_funcs);
> --
> 2.36.1
>


Re: [PATCH 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-14 Thread Niranjana Vishwanathapura

On Tue, Jun 14, 2022 at 09:27:05AM +0300, Lionel Landwerlin wrote:

On 10/06/2022 11:53, Matthew Brost wrote:

On Fri, Jun 10, 2022 at 12:07:11AM -0700, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

Signed-off-by: Niranjana Vishwanathapura 
---
 Documentation/gpu/rfc/i915_vm_bind.h | 490 +++
 1 file changed, 490 insertions(+)
 create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git a/Documentation/gpu/rfc/i915_vm_bind.h 
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..9fc854969cfb
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ * bit[0]: If set, VM_BIND is supported, otherwise not.
+ * bits[8-15]: VM_BIND implementation version.
+ * version 0 will not have VM_BIND/UNBIND timeline fence array support.
+ */
+#define I915_PARAM_HAS_VM_BIND 57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM creation.
+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * The older execbuf2 ioctl will not support VM_BIND mode of operation.
+ * For VM_BIND mode, we have new execbuf3 ioctl which will not accept any
+ * execlist (See struct drm_i915_gem_execbuffer3 for more details).
+ *
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND   (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they complete in reasonable amount of time.
+ * Compute on the other hand can be long running. Hence it is not appropriate
+ * for compute contexts to export request completion dma-fence to user.
+ * The dma-fence usage will be limited to in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support output fences. Hence,
+ * I915_EXEC_FENCE_SIGNAL (See _i915_gem_exec_fence.flags) is expected
+ * to be not used. DRM_I915_GEM_WAIT ioctl call is also not supported for
+ * objects mapped to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND   0x3d
+#define DRM_I915_GEM_VM_UNBIND 0x3e
+#define DRM_I915_GEM_EXECBUFFER3   0x3f
+#define DRM_I915_GEM_WAIT_USER_FENCE   0x40
+
+#define DRM_IOCTL_I915_GEM_VM_BIND DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_VM_BIND, struct drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND   DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_VM_UNBIND, struct drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER3 DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_EXECBUFFER3, struct drm_i915_gem_execbuffer3)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + 
DRM_I915_GEM_WAIT_USER_FENCE, struct drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to object mapping to bind.
+ *
+ * This structure is passed to VM_BIND ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the section of an object that should be bound
+ * in the device page table of the specified address space (VM).
+ * The VA range specified must be unique (ie., not currently bound) and can
+ * be mapped to whole object or a section of the object (partial binding).
+ * Multiple VA mappings can be created to the same section of the object
+ * (aliasing).
+ *
+ * The @queue_idx specifies the queue to use for binding. Same queue can be
+ * used for both VM_BIND and VM_UNBIND calls. All submitted bind and unbind
+ * operations in a queue are performed in the order of submission.
+ *
+ * The @start, @offset and @length should be 4K page aligned. However the DG2
+ * and XEHPSDV has 64K page size for device local-memory and has compact page
+ * table. On those platforms, for binding device local-memory objects, the
+ * @start should be 2M aligned, @offset and @length should be 64K aligned.
+ * Also, on those platforms, it is not allowed to bind an device local-memory
+ * object and a system memory object in a single 2M section of VA range.
+ */
+struct drm_i915_gem_vm_bind {
+   /** @vm_id: VM (address space) id to bind */
+   __u32 vm_id;
+
+   /** @queue_idx: Index of queue for binding */
+   __u32 queue_idx;
+
+   /** @rsvd: Reserved, MBZ */
+   __u32 rsvd;
+
+   /** @handle: Object handle */
+   __u32 handle;
+
+   /** @start: Virtual Address start to bind */
+   __u64 start;
+
+   /** @offset: Offset in object to bind */
+   __u64 offset;
+
+   /** @length: Length of mapping to bind */
+   __u64 length;

This probably isn't needed. We are never going to unbind a subset of a
VMA are we? That 

Re: [PATCH 19/64] drm/vc4: crtc: Switch to DRM-managed CRTC initialization

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The current code will call drm_crtc_cleanup() when the device is
> unbound. However, by then, there might still be some references held to
> that CRTC, including by the userspace that might still have the DRM
> device open.
>
> Let's switch to a DRM-managed initialization to clean up after ourselves
> only once the DRM device has been last closed.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 18 +++---
>  drivers/gpu/drm/vc4/vc4_drv.h  |  1 -
>  drivers/gpu/drm/vc4/vc4_txp.c  |  1 -
>  3 files changed, 7 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index c74fa3d07561..24de4706b61a 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -205,11 +205,6 @@ static bool vc4_crtc_get_scanout_position(struct 
> drm_crtc *crtc,
> return ret;
>  }
>
> -void vc4_crtc_destroy(struct drm_crtc *crtc)
> -{
> -   drm_crtc_cleanup(crtc);
> -}
> -
>  static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
>  {
> const struct vc4_crtc_data *crtc_data = 
> vc4_crtc_to_vc4_crtc_data(vc4_crtc);
> @@ -953,7 +948,6 @@ void vc4_crtc_reset(struct drm_crtc *crtc)
>
>  static const struct drm_crtc_funcs vc4_crtc_funcs = {
> .set_config = drm_atomic_helper_set_config,
> -   .destroy = vc4_crtc_destroy,
> .page_flip = vc4_page_flip,
> .set_property = NULL,
> .cursor_set = NULL, /* handled by drm_mode_cursor_universal */
> @@ -1131,6 +1125,7 @@ int vc4_crtc_init(struct drm_device *drm, struct 
> vc4_crtc *vc4_crtc,
> struct drm_crtc *crtc = _crtc->base;
> struct drm_plane *primary_plane;
> unsigned int i;
> +   int ret;
>
> /* For now, we create just the primary and the legacy cursor
>  * planes.  We should be able to stack more planes on easily,
> @@ -1144,10 +1139,13 @@ int vc4_crtc_init(struct drm_device *drm, struct 
> vc4_crtc *vc4_crtc,
> return PTR_ERR(primary_plane);
> }
>
> -   spin_lock_init(_crtc->irq_lock);
> -   drm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
> - crtc_funcs, NULL);
> +   ret = drmm_crtc_init_with_planes(drm, crtc, primary_plane, NULL,
> +crtc_funcs, NULL);
> +   if (ret)
> +   return ret;
> +
> drm_crtc_helper_add(crtc, crtc_helper_funcs);
> +   spin_lock_init(_crtc->irq_lock);

Moving the spin_lock_init appears to be cosmetic and unrelated, but otherwise:

Reviewed-by: Dave Stevenson 

>
> if (!vc4->hvs->hvs5) {
> drm_mode_crtc_set_gamma_size(crtc, 
> ARRAY_SIZE(vc4_crtc->lut_r));
> @@ -1226,8 +1224,6 @@ static void vc4_crtc_unbind(struct device *dev, struct 
> device *master,
> struct platform_device *pdev = to_platform_device(dev);
> struct vc4_crtc *vc4_crtc = dev_get_drvdata(dev);
>
> -   vc4_crtc_destroy(_crtc->base);
> -
> CRTC_WRITE(PV_INTEN, 0);
>
> platform_set_drvdata(pdev, NULL);
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 9a53ace85d95..fff3772be2d4 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -845,7 +845,6 @@ int vc4_crtc_disable_at_boot(struct drm_crtc *crtc);
>  int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
>   const struct drm_crtc_funcs *crtc_funcs,
>   const struct drm_crtc_helper_funcs *crtc_helper_funcs);
> -void vc4_crtc_destroy(struct drm_crtc *crtc);
>  int vc4_page_flip(struct drm_crtc *crtc,
>   struct drm_framebuffer *fb,
>   struct drm_pending_vblank_event *event,
> diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
> index e983ff7c5e13..f306e05ac5b2 100644
> --- a/drivers/gpu/drm/vc4/vc4_txp.c
> +++ b/drivers/gpu/drm/vc4/vc4_txp.c
> @@ -383,7 +383,6 @@ static void vc4_txp_disable_vblank(struct drm_crtc *crtc) 
> {}
>
>  static const struct drm_crtc_funcs vc4_txp_crtc_funcs = {
> .set_config = drm_atomic_helper_set_config,
> -   .destroy= vc4_crtc_destroy,
> .page_flip  = vc4_page_flip,
> .reset  = vc4_crtc_reset,
> .atomic_duplicate_state = vc4_crtc_duplicate_state,
> --
> 2.36.1
>


Re: [PATCH 22/64] drm/vc4: dpi: Switch to drmm_kzalloc

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Our internal structure that stores the DRM entities structure is allocated
> through a device-managed kzalloc.
>
> This means that this will eventually be freed whenever the device is
> removed. In our case, the most like source of removal is that the main
> device is going to be unbound, and component_unbind_all() is being run.
>
> However, it occurs while the DRM device is still registered, which will
> create dangling pointers, eventually resulting in use-after-free.
>
> Switch to a DRM-managed allocation to keep our structure until the DRM
> driver doesn't need it anymore.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index c88e8e397730..d1eaafb43bd1 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -244,9 +244,10 @@ static int vc4_dpi_bind(struct device *dev, struct 
> device *master, void *data)
> struct vc4_dpi *dpi;
> int ret;
>
> -   dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
> +   dpi = drmm_kzalloc(drm, sizeof(*dpi), GFP_KERNEL);
> if (!dpi)
> return -ENOMEM;
> +
> dpi->encoder.type = VC4_ENCODER_TYPE_DPI;
> dpi->pdev = pdev;
> dpi->regs = vc4_ioremap_regs(pdev, 0);
> --
> 2.36.1
>


Re: [Intel-gfx] [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Michal Wajdeczko



On 02.06.2022 19:21, Zhanjun Dong wrote:
> We are seeing error message of "No response for request". Some cases happened
> while waiting for response and reset/suspend action was triggered. In this
> case, no response is not an error, active requests will be cancelled.
> 
> This patch will handle this condition and change the error message into
> debug message.
> 
> Signed-off-by: Zhanjun Dong 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index f01325cd1b62..a30a388877e2 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -467,7 +467,7 @@ static int ct_write(struct intel_guc_ct *ct,
>   * * 0 response received (status is valid)
>   * * -ETIMEDOUT no response within hardcoded timeout
>   */
> -static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
> +static int wait_for_ct_request_update(struct ct_request *req, u32 *status, 
> struct intel_guc_ct *ct)

if you need to add "intel_guc_ct *ct" param then make it the first one

>  {
>   int err;
>  
> @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct ct_request 
> *req, u32 *status)
>  #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
>  #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
>  #define done \
> - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> READ_ONCE(req->status)) == \
>GUC_HXG_ORIGIN_GUC)
>   err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
>   if (err)
>   err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
>  #undef done
> + if (!intel_guc_ct_enabled(ct))
> + err = -ECANCELED;
>  
>   *status = req->status;
>   return err;
> @@ -703,11 +705,15 @@ static int ct_send(struct intel_guc_ct *ct,
>  
>   intel_guc_notify(ct_to_guc(ct));
>  
> - err = wait_for_ct_request_update(, status);
> + err = wait_for_ct_request_update(, status, ct);
>   g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
>   if (unlikely(err)) {
> - CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> -  action[0], request.fence);
> + if (unlikely(err == ECANCELED))

you are looking for -ECANCELED
and I guess you can safely drop "unlikely" hint here

> + CT_DEBUG(ct, "Request %#x (fence %u) cancelled as CTB 
> is disabled\n",
> + action[0], request.fence);
> + else
> + CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> + action[0], request.fence);
>   goto unlink;
>   }
>  
> @@ -771,8 +777,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 
> *action, u32 len,
>  
>   ret = ct_send(ct, action, len, response_buf, response_buf_size, 
> );
>   if (unlikely(ret < 0)) {
> - CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n",
> -  action[0], ERR_PTR(ret), status);
> + if (likely(ret != ECANCELED))

ditto

,Michal

> + CT_ERROR(ct, "Sending action %#x failed (%pe) 
> status=%#X\n",
> + action[0], ERR_PTR(ret), status);
>   } else if (unlikely(ret)) {
>   CT_DEBUG(ct, "send action %#x returned %d (%#x)\n",
>action[0], ret, ret);


Re: [Intel-gfx] [PATCH 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-14 Thread Tvrtko Ursulin



On 14/06/2022 17:02, Tvrtko Ursulin wrote:


On 14/06/2022 16:43, Niranjana Vishwanathapura wrote:

On Tue, Jun 14, 2022 at 08:16:41AM +0100, Tvrtko Ursulin wrote:


On 14/06/2022 00:39, Matthew Brost wrote:

On Mon, Jun 13, 2022 at 07:09:06PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 18:49, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 05:22:02PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 16:05, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 09:24:18AM +0100, Tvrtko Ursulin wrote:


On 10/06/2022 17:14, Niranjana Vishwanathapura wrote:
On Fri, Jun 10, 2022 at 05:48:39PM +0300, Lionel Landwerlin 
wrote:

On 10/06/2022 13:37, Tvrtko Ursulin wrote:


On 10/06/2022 08:07, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

Signed-off-by: Niranjana Vishwanathapura

---
  Documentation/gpu/rfc/i915_vm_bind.h | 490
+++
  1 file changed, 490 insertions(+)
  create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git
a/Documentation/gpu/rfc/i915_vm_bind.h
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..9fc854969cfb
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ * bit[0]: If set, VM_BIND is supported, otherwise not.
+ * bits[8-15]: VM_BIND implementation version.
+ * version 0 will not have VM_BIND/UNBIND
timeline fence array support.
+ */
+#define I915_PARAM_HAS_VM_BIND    57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM 
creation.

+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * The older execbuf2 ioctl will not
support VM_BIND mode of operation.
+ * For VM_BIND mode, we have new execbuf3
ioctl which will not accept any
+ * execlist (See struct
drm_i915_gem_execbuffer3 for more details).
+ *
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND    (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they
complete in reasonable amount of time.
+ * Compute on the other hand can be long
running. Hence it is not appropriate
+ * for compute contexts to export request
completion dma-fence to user.
+ * The dma-fence usage will be limited to
in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support output fences. 
Hence,

+ * I915_EXEC_FENCE_SIGNAL (See
_i915_gem_exec_fence.flags) is expected
+ * to be not used. DRM_I915_GEM_WAIT ioctl
call is also not supported for
+ * objects mapped to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND    0x3d
+#define DRM_I915_GEM_VM_UNBIND    0x3e
+#define DRM_I915_GEM_EXECBUFFER3    0x3f
+#define DRM_I915_GEM_WAIT_USER_FENCE    0x40
+
+#define DRM_IOCTL_I915_GEM_VM_BIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_BIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_UNBIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER3
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_EXECBUFFER3, struct
drm_i915_gem_execbuffer3)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_WAIT_USER_FENCE, struct
drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to object mapping to 
bind.

+ *
+ * This structure is passed to VM_BIND
ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the
section of an object that should be bound
+ * in the device page table of the specified address space 
(VM).

+ * The VA range specified must be unique
(ie., not currently bound) and can
+ * be mapped to whole object or a section
of the object (partial binding).
+ * Multiple VA mappings can be created to
the same section of the object
+ * (aliasing).
+ *
+ * The @queue_idx specifies the queue to
use for binding. Same queue can be
+ * used for both VM_BIND and VM_UNBIND
calls. All submitted bind and unbind
+ * operations in a queue are performed in the order of 
submission.

+ *
+ * The @start, @offset and @length should
be 4K page aligned. However the DG2
+ * and XEHPSDV has 64K page size for device
local-memory and has compact page
+ * table. On those platforms, for binding
device local-memory objects, the
+ * @start should be 2M aligned, @offset and
@length should be 64K aligned.
+ * Also, on those platforms, it is not
allowed to bind an device local-memory
+ * object and a system memory object in a
single 2M section of VA range.
+ */
+struct drm_i915_gem_vm_bind {
+    /** @vm_id: VM (address space) id to bind */
+    __u32 vm_id;
+
+ 

Re: [PATCH 21/64] drm/vc4: dpi: Embed DRM structures into the private structure

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> The VC4 DPI driver private structure contains only a pointer to the
> encoder it implements. This makes the overall structure somewhat
> inconsistent with the rest of the driver, and complicates its
> initialisation without any apparent gain.
>
> Let's embed the drm_encoder structure (through the vc4_encoder one) into
> struct vc4_dpi to fix both issues.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 49 ---
>  1 file changed, 16 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index f2b46c524919..c88e8e397730 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -83,10 +83,10 @@
>
>  /* General DPI hardware state. */
>  struct vc4_dpi {
> +   struct vc4_encoder encoder;
> +
> struct platform_device *pdev;
>
> -   struct drm_encoder *encoder;
> -
> void __iomem *regs;
>
> struct clk *pixel_clock;
> @@ -95,21 +95,15 @@ struct vc4_dpi {
> struct debugfs_regset32 regset;
>  };
>
> +static inline struct vc4_dpi *
> +to_vc4_dpi(struct drm_encoder *encoder)
> +{
> +   return container_of(encoder, struct vc4_dpi, encoder.base);
> +}
> +
>  #define DPI_READ(offset) readl(dpi->regs + (offset))
>  #define DPI_WRITE(offset, val) writel(val, dpi->regs + (offset))
>
> -/* VC4 DPI encoder KMS struct */
> -struct vc4_dpi_encoder {
> -   struct vc4_encoder base;
> -   struct vc4_dpi *dpi;
> -};
> -
> -static inline struct vc4_dpi_encoder *
> -to_vc4_dpi_encoder(struct drm_encoder *encoder)
> -{
> -   return container_of(encoder, struct vc4_dpi_encoder, base.base);
> -}
> -
>  static const struct debugfs_reg32 dpi_regs[] = {
> VC4_REG32(DPI_C),
> VC4_REG32(DPI_ID),
> @@ -117,8 +111,7 @@ static const struct debugfs_reg32 dpi_regs[] = {
>
>  static void vc4_dpi_encoder_disable(struct drm_encoder *encoder)
>  {
> -   struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
> -   struct vc4_dpi *dpi = vc4_encoder->dpi;
> +   struct vc4_dpi *dpi = to_vc4_dpi(encoder);
>
> clk_disable_unprepare(dpi->pixel_clock);
>  }
> @@ -127,8 +120,7 @@ static void vc4_dpi_encoder_enable(struct drm_encoder 
> *encoder)
>  {
> struct drm_device *dev = encoder->dev;
> struct drm_display_mode *mode = >crtc->mode;
> -   struct vc4_dpi_encoder *vc4_encoder = to_vc4_dpi_encoder(encoder);
> -   struct vc4_dpi *dpi = vc4_encoder->dpi;
> +   struct vc4_dpi *dpi = to_vc4_dpi(encoder);
> struct drm_connector_list_iter conn_iter;
> struct drm_connector *connector = NULL, *connector_scan;
> u32 dpi_c = DPI_ENABLE | DPI_OUTPUT_ENABLE_MODE;
> @@ -242,7 +234,7 @@ static int vc4_dpi_init_bridge(struct vc4_dpi *dpi)
> return PTR_ERR(bridge);
> }
>
> -   return drm_bridge_attach(dpi->encoder, bridge, NULL, 0);
> +   return drm_bridge_attach(>encoder.base, bridge, NULL, 0);
>  }
>
>  static int vc4_dpi_bind(struct device *dev, struct device *master, void 
> *data)
> @@ -250,21 +242,12 @@ static int vc4_dpi_bind(struct device *dev, struct 
> device *master, void *data)
> struct platform_device *pdev = to_platform_device(dev);
> struct drm_device *drm = dev_get_drvdata(master);
> struct vc4_dpi *dpi;
> -   struct vc4_dpi_encoder *vc4_dpi_encoder;
> int ret;
>
> dpi = devm_kzalloc(dev, sizeof(*dpi), GFP_KERNEL);
> if (!dpi)
> return -ENOMEM;
> -
> -   vc4_dpi_encoder = devm_kzalloc(dev, sizeof(*vc4_dpi_encoder),
> -  GFP_KERNEL);
> -   if (!vc4_dpi_encoder)
> -   return -ENOMEM;
> -   vc4_dpi_encoder->base.type = VC4_ENCODER_TYPE_DPI;
> -   vc4_dpi_encoder->dpi = dpi;
> -   dpi->encoder = _dpi_encoder->base.base;
> -
> +   dpi->encoder.type = VC4_ENCODER_TYPE_DPI;
> dpi->pdev = pdev;
> dpi->regs = vc4_ioremap_regs(pdev, 0);
> if (IS_ERR(dpi->regs))
> @@ -298,8 +281,8 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
> if (ret)
> DRM_ERROR("Failed to turn on core clock: %d\n", ret);
>
> -   drm_simple_encoder_init(drm, dpi->encoder, DRM_MODE_ENCODER_DPI);
> -   drm_encoder_helper_add(dpi->encoder, _dpi_encoder_helper_funcs);
> +   drm_simple_encoder_init(drm, >encoder.base, 
> DRM_MODE_ENCODER_DPI);
> +   drm_encoder_helper_add(>encoder.base, 
> _dpi_encoder_helper_funcs);
>
> ret = vc4_dpi_init_bridge(dpi);
> if (ret)
> @@ -312,7 +295,7 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
> return 0;
>
>  err_destroy_encoder:
> -   drm_encoder_cleanup(dpi->encoder);
> +   drm_encoder_cleanup(>encoder.base);
> 

Re: [Intel-gfx] [PATCH 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-14 Thread Tvrtko Ursulin



On 14/06/2022 16:43, Niranjana Vishwanathapura wrote:

On Tue, Jun 14, 2022 at 08:16:41AM +0100, Tvrtko Ursulin wrote:


On 14/06/2022 00:39, Matthew Brost wrote:

On Mon, Jun 13, 2022 at 07:09:06PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 18:49, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 05:22:02PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 16:05, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 09:24:18AM +0100, Tvrtko Ursulin wrote:


On 10/06/2022 17:14, Niranjana Vishwanathapura wrote:

On Fri, Jun 10, 2022 at 05:48:39PM +0300, Lionel Landwerlin wrote:

On 10/06/2022 13:37, Tvrtko Ursulin wrote:


On 10/06/2022 08:07, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

Signed-off-by: Niranjana Vishwanathapura

---
  Documentation/gpu/rfc/i915_vm_bind.h | 490
+++
  1 file changed, 490 insertions(+)
  create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git
a/Documentation/gpu/rfc/i915_vm_bind.h
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..9fc854969cfb
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ * bit[0]: If set, VM_BIND is supported, otherwise not.
+ * bits[8-15]: VM_BIND implementation version.
+ * version 0 will not have VM_BIND/UNBIND
timeline fence array support.
+ */
+#define I915_PARAM_HAS_VM_BIND    57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM 
creation.

+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * The older execbuf2 ioctl will not
support VM_BIND mode of operation.
+ * For VM_BIND mode, we have new execbuf3
ioctl which will not accept any
+ * execlist (See struct
drm_i915_gem_execbuffer3 for more details).
+ *
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND    (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they
complete in reasonable amount of time.
+ * Compute on the other hand can be long
running. Hence it is not appropriate
+ * for compute contexts to export request
completion dma-fence to user.
+ * The dma-fence usage will be limited to
in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support output fences. 
Hence,

+ * I915_EXEC_FENCE_SIGNAL (See
_i915_gem_exec_fence.flags) is expected
+ * to be not used. DRM_I915_GEM_WAIT ioctl
call is also not supported for
+ * objects mapped to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND    0x3d
+#define DRM_I915_GEM_VM_UNBIND    0x3e
+#define DRM_I915_GEM_EXECBUFFER3    0x3f
+#define DRM_I915_GEM_WAIT_USER_FENCE    0x40
+
+#define DRM_IOCTL_I915_GEM_VM_BIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_BIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_UNBIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER3
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_EXECBUFFER3, struct
drm_i915_gem_execbuffer3)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_WAIT_USER_FENCE, struct
drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to object mapping to bind.
+ *
+ * This structure is passed to VM_BIND
ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the
section of an object that should be bound
+ * in the device page table of the specified address space 
(VM).

+ * The VA range specified must be unique
(ie., not currently bound) and can
+ * be mapped to whole object or a section
of the object (partial binding).
+ * Multiple VA mappings can be created to
the same section of the object
+ * (aliasing).
+ *
+ * The @queue_idx specifies the queue to
use for binding. Same queue can be
+ * used for both VM_BIND and VM_UNBIND
calls. All submitted bind and unbind
+ * operations in a queue are performed in the order of 
submission.

+ *
+ * The @start, @offset and @length should
be 4K page aligned. However the DG2
+ * and XEHPSDV has 64K page size for device
local-memory and has compact page
+ * table. On those platforms, for binding
device local-memory objects, the
+ * @start should be 2M aligned, @offset and
@length should be 64K aligned.
+ * Also, on those platforms, it is not
allowed to bind an device local-memory
+ * object and a system memory object in a
single 2M section of VA range.
+ */
+struct drm_i915_gem_vm_bind {
+    /** @vm_id: VM (address space) id to bind */
+    __u32 vm_id;
+
+    /** @queue_idx: Index of queue for binding 

Re: [PATCH 20/64] drm/vc4: dpi: Remove vc4_dev dpi pointer

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> There's no user for that pointer so let's just get rid of it.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_dpi.c | 7 ---
>  drivers/gpu/drm/vc4/vc4_drv.h | 1 -
>  2 files changed, 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
> index c180eb60bee8..f2b46c524919 100644
> --- a/drivers/gpu/drm/vc4/vc4_dpi.c
> +++ b/drivers/gpu/drm/vc4/vc4_dpi.c
> @@ -249,7 +249,6 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
>  {
> struct platform_device *pdev = to_platform_device(dev);
> struct drm_device *drm = dev_get_drvdata(master);
> -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> struct vc4_dpi *dpi;
> struct vc4_dpi_encoder *vc4_dpi_encoder;
> int ret;
> @@ -308,8 +307,6 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
>
> dev_set_drvdata(dev, dpi);
>
> -   vc4->dpi = dpi;
> -
> vc4_debugfs_add_regset32(drm, "dpi_regs", >regset);
>
> return 0;
> @@ -323,8 +320,6 @@ static int vc4_dpi_bind(struct device *dev, struct device 
> *master, void *data)
>  static void vc4_dpi_unbind(struct device *dev, struct device *master,
>void *data)
>  {
> -   struct drm_device *drm = dev_get_drvdata(master);
> -   struct vc4_dev *vc4 = to_vc4_dev(drm);
> struct vc4_dpi *dpi = dev_get_drvdata(dev);
>
> drm_of_panel_bridge_remove(dev->of_node, 0, 0);
> @@ -332,8 +327,6 @@ static void vc4_dpi_unbind(struct device *dev, struct 
> device *master,
> drm_encoder_cleanup(dpi->encoder);
>
> clk_disable_unprepare(dpi->core_clock);
> -
> -   vc4->dpi = NULL;
>  }
>
>  static const struct component_ops vc4_dpi_ops = {
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index fff3772be2d4..846f3cda179a 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -79,7 +79,6 @@ struct vc4_dev {
>
> struct vc4_hvs *hvs;
> struct vc4_v3d *v3d;
> -   struct vc4_dpi *dpi;
> struct vc4_vec *vec;
> struct vc4_txp *txp;
>
> --
> 2.36.1
>


Re: [PATCH 17/64] drm/vc4: crtc: Move debugfs_name to crtc_data

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> All the CRTCs, including the TXP, have a debugfs file and name so we can
> consolidate it into vc4_crtc_data.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

I was sort of expecting the vc4_debugfs_add_regset32 call to move to
vc4_crtc_init so that it would be a common call for crtcs and txp, but
that doesn't appear to happen in this set. The debugfs_name for the
txp is therefore actually unused.

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 18 +-
>  drivers/gpu/drm/vc4/vc4_drv.h  |  4 ++--
>  drivers/gpu/drm/vc4/vc4_txp.c  |  1 +
>  3 files changed, 12 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 7163f924b48b..1f7e987e68aa 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -978,10 +978,10 @@ static const struct drm_crtc_helper_funcs 
> vc4_crtc_helper_funcs = {
>
>  static const struct vc4_pv_data bcm2835_pv0_data = {
> .base = {
> +   .debugfs_name = "crtc0_regs",
> .hvs_available_channels = BIT(0),
> .hvs_output = 0,
> },
> -   .debugfs_name = "crtc0_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -992,10 +992,10 @@ static const struct vc4_pv_data bcm2835_pv0_data = {
>
>  static const struct vc4_pv_data bcm2835_pv1_data = {
> .base = {
> +   .debugfs_name = "crtc1_regs",
> .hvs_available_channels = BIT(2),
> .hvs_output = 2,
> },
> -   .debugfs_name = "crtc1_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -1006,10 +1006,10 @@ static const struct vc4_pv_data bcm2835_pv1_data = {
>
>  static const struct vc4_pv_data bcm2835_pv2_data = {
> .base = {
> +   .debugfs_name = "crtc2_regs",
> .hvs_available_channels = BIT(1),
> .hvs_output = 1,
> },
> -   .debugfs_name = "crtc2_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -1020,10 +1020,10 @@ static const struct vc4_pv_data bcm2835_pv2_data = {
>
>  static const struct vc4_pv_data bcm2711_pv0_data = {
> .base = {
> +   .debugfs_name = "crtc0_regs",
> .hvs_available_channels = BIT(0),
> .hvs_output = 0,
> },
> -   .debugfs_name = "crtc0_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -1034,10 +1034,10 @@ static const struct vc4_pv_data bcm2711_pv0_data = {
>
>  static const struct vc4_pv_data bcm2711_pv1_data = {
> .base = {
> +   .debugfs_name = "crtc1_regs",
> .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
> .hvs_output = 3,
> },
> -   .debugfs_name = "crtc1_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -1048,10 +1048,10 @@ static const struct vc4_pv_data bcm2711_pv1_data = {
>
>  static const struct vc4_pv_data bcm2711_pv2_data = {
> .base = {
> +   .debugfs_name = "crtc2_regs",
> .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
> .hvs_output = 4,
> },
> -   .debugfs_name = "crtc2_regs",
> .fifo_depth = 256,
> .pixels_per_clock = 2,
> .encoder_types = {
> @@ -1061,10 +1061,10 @@ static const struct vc4_pv_data bcm2711_pv2_data = {
>
>  static const struct vc4_pv_data bcm2711_pv3_data = {
> .base = {
> +   .debugfs_name = "crtc3_regs",
> .hvs_available_channels = BIT(1),
> .hvs_output = 1,
> },
> -   .debugfs_name = "crtc3_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 1,
> .encoder_types = {
> @@ -1074,10 +1074,10 @@ static const struct vc4_pv_data bcm2711_pv3_data = {
>
>  static const struct vc4_pv_data bcm2711_pv4_data = {
> .base = {
> +   .debugfs_name = "crtc4_regs",
> .hvs_available_channels = BIT(0) | BIT(1) | BIT(2),
> .hvs_output = 5,
> },
> -   .debugfs_name = "crtc4_regs",
> .fifo_depth = 64,
> .pixels_per_clock = 2,
> .encoder_types = {
> @@ -1214,7 +1214,7 @@ static int vc4_crtc_bind(struct device *dev, struct 
> device *master, void *data)
>
> platform_set_drvdata(pdev, vc4_crtc);
>
> -   vc4_debugfs_add_regset32(drm, pv_data->debugfs_name,
> +   vc4_debugfs_add_regset32(drm, pv_data->base.debugfs_name,
>  _crtc->regset);
>
> return 0;
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 5125ca1a8158..9a53ace85d95 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -457,6 

[PATCH] drm/amd/display: add stub for crtc_debugfs_init()

2022-06-14 Thread Randy Dunlap
Fix build error when CONFIG_DEBUG_FS is not enabled by adding a
stub function for crtc_debugfs_init().

Eliminates this build error:

../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c: In function 
‘amdgpu_dm_crtc_late_register’:
../drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm.c:6599:2: error: 
implicit declaration of function ‘crtc_debugfs_init’; did you mean 
‘amdgpu_debugfs_init’? [-Werror=implicit-function-declaration]
  crtc_debugfs_init(crtc);
  ^
  amdgpu_debugfs_init

Fixes: 86bc22191892 ("drm/amd/display: Support crc on specific region")
Signed-off-by: Randy Dunlap 
Cc: Wayne Lin 
Cc: Alex Deucher 
Cc: Christian König 
Cc: "Pan, Xinhui" 
Cc: amd-...@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
---
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c |2 --
 drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h |6 ++
 2 files changed, 6 insertions(+), 2 deletions(-)

--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -57,9 +57,7 @@
 #include "amdgpu_dm_irq.h"
 #include "dm_helpers.h"
 #include "amdgpu_dm_mst_types.h"
-#if defined(CONFIG_DEBUG_FS)
 #include "amdgpu_dm_debugfs.h"
-#endif
 #include "amdgpu_dm_psr.h"
 
 #include "ivsrcid/ivsrcid_vislands30.h"
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.h
@@ -31,6 +31,12 @@
 
 void connector_debugfs_init(struct amdgpu_dm_connector *connector);
 void dtn_debugfs_init(struct amdgpu_device *adev);
+
+#ifdef CONFIG_DEBUG_FS
 void crtc_debugfs_init(struct drm_crtc *crtc);
+#else
+static inline void crtc_debugfs_init(struct drm_crtc *crtc)
+{}
+#endif
 
 #endif


Re: [PATCH] drm/sun4i: dw-hdmi: Fix ddc-en GPIO consumer conflict

2022-06-14 Thread Jernej Škrabec
Dne torek, 14. junij 2022 ob 09:31:00 CEST je Samuel Holland napisal(a):
> commit 6de79dd3a920 ("drm/bridge: display-connector: add ddc-en gpio
> support") added a consumer for this GPIO in the HDMI connector device.
> This new consumer conflicts with the pre-existing GPIO consumer in the
> sun8i HDMI controller driver, which prevents the driver from probing:
> 
>   [4.983358] display-connector connector: GPIO lookup for consumer ddc-
en
>   [4.983364] display-connector connector: using device tree for GPIO 
lookup
>   [4.983392] gpio-226 (ddc-en): gpiod_request: status -16
>   [4.983399] sun8i-dw-hdmi 600.hdmi: Couldn't get ddc-en gpio
>   [4.983618] sun4i-drm display-engine: failed to bind 600.hdmi (ops 
sun8i_dw_hdmi_ops [sun8i_drm_hdmi]): -16
>   [4.984082] sun4i-drm display-engine: Couldn't bind all pipelines 
components
>   [4.984171] sun4i-drm display-engine: adev bind failed: -16
>   [4.984179] sun8i-dw-hdmi: probe of 600.hdmi failed with error -16
> 
> Both drivers have the same behavior: they leave the GPIO active for the
> life of the device. Let's take advantage of the new implementation, and
> drop the now-obsolete code from the HDMI controller driver.
> 
> Fixes: 6de79dd3a920 ("drm/bridge: display-connector: add ddc-en gpio 
support")
> Signed-off-by: Samuel Holland 

Reviewed-by: Jernej Skrabec 

Best regards,
Jernej




Re: [Intel-gfx] [PATCH 3/3] drm/doc/rfc: VM_BIND uapi definition

2022-06-14 Thread Niranjana Vishwanathapura

On Tue, Jun 14, 2022 at 08:16:41AM +0100, Tvrtko Ursulin wrote:


On 14/06/2022 00:39, Matthew Brost wrote:

On Mon, Jun 13, 2022 at 07:09:06PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 18:49, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 05:22:02PM +0100, Tvrtko Ursulin wrote:


On 13/06/2022 16:05, Niranjana Vishwanathapura wrote:

On Mon, Jun 13, 2022 at 09:24:18AM +0100, Tvrtko Ursulin wrote:


On 10/06/2022 17:14, Niranjana Vishwanathapura wrote:

On Fri, Jun 10, 2022 at 05:48:39PM +0300, Lionel Landwerlin wrote:

On 10/06/2022 13:37, Tvrtko Ursulin wrote:


On 10/06/2022 08:07, Niranjana Vishwanathapura wrote:

VM_BIND and related uapi definitions

Signed-off-by: Niranjana Vishwanathapura

---
  Documentation/gpu/rfc/i915_vm_bind.h | 490
+++
  1 file changed, 490 insertions(+)
  create mode 100644 Documentation/gpu/rfc/i915_vm_bind.h

diff --git
a/Documentation/gpu/rfc/i915_vm_bind.h
b/Documentation/gpu/rfc/i915_vm_bind.h
new file mode 100644
index ..9fc854969cfb
--- /dev/null
+++ b/Documentation/gpu/rfc/i915_vm_bind.h
@@ -0,0 +1,490 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2022 Intel Corporation
+ */
+
+/**
+ * DOC: I915_PARAM_HAS_VM_BIND
+ *
+ * VM_BIND feature availability.
+ * See typedef drm_i915_getparam_t param.
+ * bit[0]: If set, VM_BIND is supported, otherwise not.
+ * bits[8-15]: VM_BIND implementation version.
+ * version 0 will not have VM_BIND/UNBIND
timeline fence array support.
+ */
+#define I915_PARAM_HAS_VM_BIND    57
+
+/**
+ * DOC: I915_VM_CREATE_FLAGS_USE_VM_BIND
+ *
+ * Flag to opt-in for VM_BIND mode of binding during VM creation.
+ * See struct drm_i915_gem_vm_control flags.
+ *
+ * The older execbuf2 ioctl will not
support VM_BIND mode of operation.
+ * For VM_BIND mode, we have new execbuf3
ioctl which will not accept any
+ * execlist (See struct
drm_i915_gem_execbuffer3 for more details).
+ *
+ */
+#define I915_VM_CREATE_FLAGS_USE_VM_BIND    (1 << 0)
+
+/**
+ * DOC: I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING
+ *
+ * Flag to declare context as long running.
+ * See struct drm_i915_gem_context_create_ext flags.
+ *
+ * Usage of dma-fence expects that they
complete in reasonable amount of time.
+ * Compute on the other hand can be long
running. Hence it is not appropriate
+ * for compute contexts to export request
completion dma-fence to user.
+ * The dma-fence usage will be limited to
in-kernel consumption only.
+ * Compute contexts need to use user/memory fence.
+ *
+ * So, long running contexts do not support output fences. Hence,
+ * I915_EXEC_FENCE_SIGNAL (See
_i915_gem_exec_fence.flags) is expected
+ * to be not used. DRM_I915_GEM_WAIT ioctl
call is also not supported for
+ * objects mapped to long running contexts.
+ */
+#define I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING   (1u << 2)
+
+/* VM_BIND related ioctls */
+#define DRM_I915_GEM_VM_BIND    0x3d
+#define DRM_I915_GEM_VM_UNBIND    0x3e
+#define DRM_I915_GEM_EXECBUFFER3    0x3f
+#define DRM_I915_GEM_WAIT_USER_FENCE    0x40
+
+#define DRM_IOCTL_I915_GEM_VM_BIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_BIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_VM_UNBIND
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_VM_UNBIND, struct
drm_i915_gem_vm_bind)
+#define DRM_IOCTL_I915_GEM_EXECBUFFER3
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_EXECBUFFER3, struct
drm_i915_gem_execbuffer3)
+#define DRM_IOCTL_I915_GEM_WAIT_USER_FENCE
DRM_IOWR(DRM_COMMAND_BASE +
DRM_I915_GEM_WAIT_USER_FENCE, struct
drm_i915_gem_wait_user_fence)
+
+/**
+ * struct drm_i915_gem_vm_bind - VA to object mapping to bind.
+ *
+ * This structure is passed to VM_BIND
ioctl and specifies the mapping of GPU
+ * virtual address (VA) range to the
section of an object that should be bound
+ * in the device page table of the specified address space (VM).
+ * The VA range specified must be unique
(ie., not currently bound) and can
+ * be mapped to whole object or a section
of the object (partial binding).
+ * Multiple VA mappings can be created to
the same section of the object
+ * (aliasing).
+ *
+ * The @queue_idx specifies the queue to
use for binding. Same queue can be
+ * used for both VM_BIND and VM_UNBIND
calls. All submitted bind and unbind
+ * operations in a queue are performed in the order of submission.
+ *
+ * The @start, @offset and @length should
be 4K page aligned. However the DG2
+ * and XEHPSDV has 64K page size for device
local-memory and has compact page
+ * table. On those platforms, for binding
device local-memory objects, the
+ * @start should be 2M aligned, @offset and
@length should be 64K aligned.
+ * Also, on those platforms, it is not
allowed to bind an device local-memory
+ * object and a system memory object in a
single 2M section of VA range.
+ */
+struct drm_i915_gem_vm_bind {
+    /** @vm_id: VM (address space) id to bind */
+    __u32 vm_id;
+
+    /** @queue_idx: Index of queue for binding */
+    __u32 queue_idx;


I have a question here to which I did 

Re: [PATCH 18/64] drm/vc4: crtc: Switch to drmm_kzalloc

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Our internal structure that stores the DRM entities structure is allocated
> through a device-managed kzalloc.
>
> This means that this will eventually be freed whenever the device is
> removed. In our case, the most like source of removal is that the main
> device is going to be unbound, and component_unbind_all() is being run.
>
> However, it occurs while the DRM device is still registered, which will
> create dangling pointers, eventually resulting in use-after-free.
>
> Switch to a DRM-managed allocation to keep our structure until the DRM
> driver doesn't need it anymore.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 1f7e987e68aa..c74fa3d07561 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -1178,7 +1178,7 @@ static int vc4_crtc_bind(struct device *dev, struct 
> device *master, void *data)
> struct drm_crtc *crtc;
> int ret;
>
> -   vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
> +   vc4_crtc = drmm_kzalloc(drm, sizeof(*vc4_crtc), GFP_KERNEL);
> if (!vc4_crtc)
> return -ENOMEM;
> crtc = _crtc->base;
> --
> 2.36.1
>


Re: [PATCH 16/64] drm/vc4: plane: Switch to drmm_universal_plane_alloc()

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Let's switch to drmm_universal_plane_alloc() for our plane allocation and
> initialisation to make the driver a bit simpler.
>
> Signed-off-by: Maxime Ripard 

Reviewed-by: Dave Stevenson 

> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c  | 12 +---
>  drivers/gpu/drm/vc4/vc4_plane.c | 23 ---
>  2 files changed, 9 insertions(+), 26 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 840a93484bb1..7163f924b48b 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -1176,7 +1176,6 @@ static int vc4_crtc_bind(struct device *dev, struct 
> device *master, void *data)
> const struct vc4_pv_data *pv_data;
> struct vc4_crtc *vc4_crtc;
> struct drm_crtc *crtc;
> -   struct drm_plane *destroy_plane, *temp;
> int ret;
>
> vc4_crtc = devm_kzalloc(dev, sizeof(*vc4_crtc), GFP_KERNEL);
> @@ -1211,7 +1210,7 @@ static int vc4_crtc_bind(struct device *dev, struct 
> device *master, void *data)
>IRQF_SHARED,
>"vc4 crtc", vc4_crtc);
> if (ret)
> -   goto err_destroy_planes;
> +   return ret;
>
> platform_set_drvdata(pdev, vc4_crtc);
>
> @@ -1219,15 +1218,6 @@ static int vc4_crtc_bind(struct device *dev, struct 
> device *master, void *data)
>  _crtc->regset);
>
> return 0;
> -
> -err_destroy_planes:
> -   list_for_each_entry_safe(destroy_plane, temp,
> ->mode_config.plane_list, head) {
> -   if (destroy_plane->possible_crtcs == drm_crtc_mask(crtc))
> -   destroy_plane->funcs->destroy(destroy_plane);
> -   }
> -
> -   return ret;
>  }
>
>  static void vc4_crtc_unbind(struct device *dev, struct device *master,
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index 17dab470ecdf..673c963f5c5a 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -1442,8 +1442,6 @@ static bool vc4_format_mod_supported(struct drm_plane 
> *plane,
>  static const struct drm_plane_funcs vc4_plane_funcs = {
> .update_plane = drm_atomic_helper_update_plane,
> .disable_plane = drm_atomic_helper_disable_plane,
> -   .destroy = drm_plane_cleanup,
> -   .set_property = NULL,
> .reset = vc4_plane_reset,
> .atomic_duplicate_state = vc4_plane_duplicate_state,
> .atomic_destroy_state = vc4_plane_destroy_state,
> @@ -1454,11 +1452,10 @@ struct drm_plane *vc4_plane_init(struct drm_device 
> *dev,
>  enum drm_plane_type type,
>  unsigned int possible_crtcs)
>  {
> -   struct drm_plane *plane = NULL;
> +   struct drm_plane *plane;
> struct vc4_plane *vc4_plane;
> u32 formats[ARRAY_SIZE(hvs_formats)];
> int num_formats = 0;
> -   int ret = 0;
> unsigned i;
> bool hvs5 = of_device_is_compatible(dev->dev->of_node,
> "brcm,bcm2711-vc5");
> @@ -1471,11 +1468,6 @@ struct drm_plane *vc4_plane_init(struct drm_device 
> *dev,
> DRM_FORMAT_MOD_INVALID
> };
>
> -   vc4_plane = devm_kzalloc(dev->dev, sizeof(*vc4_plane),
> -GFP_KERNEL);
> -   if (!vc4_plane)
> -   return ERR_PTR(-ENOMEM);
> -
> for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
> if (!hvs_formats[i].hvs5_only || hvs5) {
> formats[num_formats] = hvs_formats[i].drm;
> @@ -1483,13 +1475,14 @@ struct drm_plane *vc4_plane_init(struct drm_device 
> *dev,
> }
> }
>
> +   vc4_plane = drmm_universal_plane_alloc(dev, struct vc4_plane, base,
> +  possible_crtcs,
> +  _plane_funcs,
> +  formats, num_formats,
> +  modifiers, type, NULL);
> +   if (IS_ERR(vc4_plane))
> +   return ERR_CAST(vc4_plane);
> plane = _plane->base;
> -   ret = drm_universal_plane_init(dev, plane, possible_crtcs,
> -  _plane_funcs,
> -  formats, num_formats,
> -  modifiers, type, NULL);
> -   if (ret)
> -   return ERR_PTR(ret);
>
> drm_plane_helper_add(plane, _plane_helper_funcs);
>
> --
> 2.36.1
>


Re: [PATCH] drm/msm: Make msm_gem_free_object() static

2022-06-14 Thread Dmitry Baryshkov
On Mon, 13 Jun 2022 at 23:49, Rob Clark  wrote:
>
> From: Rob Clark 
>
> Misc small cleanup I noticed.  Not called from another object file since
> 3c9edd9c85f5 ("drm/msm: Introduce GEM object funcs")
>
> Signed-off-by: Rob Clark 

Reviewed-by: Dmitry Baryshkov 

> ---
>  drivers/gpu/drm/msm/msm_gem.c | 2 +-
>  drivers/gpu/drm/msm/msm_gem.h | 1 -
>  2 files changed, 1 insertion(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 35845e273d81..3ef7ada59392 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -1004,7 +1004,7 @@ void msm_gem_describe_objects(struct list_head *list, 
> struct seq_file *m)
>  #endif
>
>  /* don't call directly!  Use drm_gem_object_put() */
> -void msm_gem_free_object(struct drm_gem_object *obj)
> +static void msm_gem_free_object(struct drm_gem_object *obj)
>  {
> struct msm_gem_object *msm_obj = to_msm_bo(obj);
> struct drm_device *dev = obj->dev;
> diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
> index 6b7d5bb3b575..d608339c1643 100644
> --- a/drivers/gpu/drm/msm/msm_gem.h
> +++ b/drivers/gpu/drm/msm/msm_gem.h
> @@ -175,7 +175,6 @@ void msm_gem_active_get(struct drm_gem_object *obj, 
> struct msm_gpu *gpu);
>  void msm_gem_active_put(struct drm_gem_object *obj);
>  int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t 
> *timeout);
>  int msm_gem_cpu_fini(struct drm_gem_object *obj);
> -void msm_gem_free_object(struct drm_gem_object *obj);
>  int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
> uint32_t size, uint32_t flags, uint32_t *handle, char *name);
>  struct drm_gem_object *msm_gem_new(struct drm_device *dev,
> --
> 2.36.1
>


-- 
With best wishes
Dmitry


Re: [Intel-gfx] [PATCH] drm/i915/guc: Check ctx while waiting for response

2022-06-14 Thread Teres Alexis, Alan Previn
Can't see anything wrong with this.
I consider this only a NIT, so feel : not sure if -ECANCELLED is reflective of 
the "ct service being temporarily down"
as opposed to the "requester cancelling". Perhaps a -EPIPE or -EAGAIN (if we 
got this far, we know we are probably mid-
reset) ?? (if not already used elsewhere along this callstack). Else :

Reviewed-by: Alan Previn 

...alan


On Thu, 2022-06-02 at 10:21 -0700, Zhanjun Dong wrote:
> We are seeing error message of "No response for request". Some cases happened
> while waiting for response and reset/suspend action was triggered. In this
> case, no response is not an error, active requests will be cancelled.
> 
> This patch will handle this condition and change the error message into
> debug message.
> 
> Signed-off-by: Zhanjun Dong 
> ---
>  drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 21 ++---
>  1 file changed, 14 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c 
> b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> index f01325cd1b62..a30a388877e2 100644
> --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c
> @@ -467,7 +467,7 @@ static int ct_write(struct intel_guc_ct *ct,
>   * * 0 response received (status is valid)
>   * * -ETIMEDOUT no response within hardcoded timeout
>   */
> -static int wait_for_ct_request_update(struct ct_request *req, u32 *status)
> +static int wait_for_ct_request_update(struct ct_request *req, u32 *status, 
> struct intel_guc_ct *ct)
>  {
>   int err;
>  
> @@ -481,12 +481,14 @@ static int wait_for_ct_request_update(struct ct_request 
> *req, u32 *status)
>  #define GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS 10
>  #define GUC_CTB_RESPONSE_TIMEOUT_LONG_MS 1000
>  #define done \
> - (FIELD_GET(GUC_HXG_MSG_0_ORIGIN, READ_ONCE(req->status)) == \
> + (!intel_guc_ct_enabled(ct) || FIELD_GET(GUC_HXG_MSG_0_ORIGIN, 
> READ_ONCE(req->status)) == \
>GUC_HXG_ORIGIN_GUC)
>   err = wait_for_us(done, GUC_CTB_RESPONSE_TIMEOUT_SHORT_MS);
>   if (err)
>   err = wait_for(done, GUC_CTB_RESPONSE_TIMEOUT_LONG_MS);
>  #undef done
> + if (!intel_guc_ct_enabled(ct))
> + err = -ECANCELED;
>  
>   *status = req->status;
>   return err;
> @@ -703,11 +705,15 @@ static int ct_send(struct intel_guc_ct *ct,
>  
>   intel_guc_notify(ct_to_guc(ct));
>  
> - err = wait_for_ct_request_update(, status);
> + err = wait_for_ct_request_update(, status, ct);
>   g2h_release_space(ct, GUC_CTB_HXG_MSG_MAX_LEN);
>   if (unlikely(err)) {
> - CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> -  action[0], request.fence);
> + if (unlikely(err == ECANCELED))
> + CT_DEBUG(ct, "Request %#x (fence %u) cancelled as CTB 
> is disabled\n",
> + action[0], request.fence);
> + else
> + CT_ERROR(ct, "No response for request %#x (fence %u)\n",
> + action[0], request.fence);
>   goto unlink;
>   }
>  
> @@ -771,8 +777,9 @@ int intel_guc_ct_send(struct intel_guc_ct *ct, const u32 
> *action, u32 len,
>  
>   ret = ct_send(ct, action, len, response_buf, response_buf_size, 
> );
>   if (unlikely(ret < 0)) {
> - CT_ERROR(ct, "Sending action %#x failed (%pe) status=%#X\n",
> -  action[0], ERR_PTR(ret), status);
> + if (likely(ret != ECANCELED))
> + CT_ERROR(ct, "Sending action %#x failed (%pe) 
> status=%#X\n",
> + action[0], ERR_PTR(ret), status);
>   } else if (unlikely(ret)) {
>   CT_DEBUG(ct, "send action %#x returned %d (%#x)\n",
>action[0], ret, ret);
> -- 
> 2.36.0
> 



Re: [PATCH v5] drm/msm/dp: force link training for display resolution change

2022-06-14 Thread Kuogee Hsieh



On 6/14/2022 1:38 AM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2022-06-13 14:48:37)

During display resolution changes display have to be disabled first
followed by display enabling with new resolution. Display disable
will turn off both pixel clock and main link clock so that main link
have to be re-trained during display enable to have new video stream
flow again. At current implementation, display enable function manually
kicks up irq_hpd_handle which will read panel link status and start link
training if link status is not in sync state. However, there is rare
case that a particular panel links status keep staying in sync for
some period of time after main link had been shut down previously at
display disabled. Main link retraining will not be executed by
irq_hdp_handle() if the link status read from panel shows it is in
sync state. If this was happen, then video stream of newer display
resolution will fail to be transmitted to panel due to main link is
not in sync between host and panel. This patch force main link always
be retrained during display enable procedure to prevent this rare
failed case from happening. Also this implementation are more
efficient than manual kicking off irq_hpd_handle function.

How is resolution change different from disabling and enabling the
display? The commit text talks about resolution changes, but the code
doesn't compare resolutions from before and after to know when to
retrain the link. Can the code be made to actually do what the commit
text says? It would be clearer if the code looked for actual resolution
changes instead of hooking the dp_bridge_enable() function.


Resolution changes are implemented through modeset. Therefore you can 
treat resolution changes equal to modeset.


dp_bridge_enable() and dp_bridge_disable() are end of function of 
modeset since DP driver is implemented as DRM bridge.


you have to use modeset to disable previous resolution and modeset to 
enable newer resolution.


Resolution changes is the term from end user point of view. For DP 
driver, we should use modeset.


I will revise the commit text for this.





Changes in v2:
-- set force_link_train flag on DP only (is_edp == false)

Changes in v3:
-- revise commit  text
-- add Fixes tag

Changes in v4:
-- revise commit  text

Changes in v5:
-- fix spelling at commit text

Fixes: 62671d2ef24b ("drm/msm/dp: fixes wrong connection state caused by failure of 
link train")
Signed-off-by: Kuogee Hsieh 
---
  drivers/gpu/drm/msm/dp/dp_ctrl.c|  6 +++---
  drivers/gpu/drm/msm/dp/dp_ctrl.h|  2 +-
  drivers/gpu/drm/msm/dp/dp_display.c | 15 ---
  3 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index af7a80c..bea93eb 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1551,7 +1551,7 @@ static int dp_ctrl_process_phy_test_request(struct 
dp_ctrl_private *ctrl)

 ret = dp_ctrl_on_link(>dp_ctrl);
 if (!ret)
-   ret = dp_ctrl_on_stream(>dp_ctrl);
+   ret = dp_ctrl_on_stream(>dp_ctrl, false);

Does this even matter if it's true or false? The 'sink_request' has
DP_TEST_LINK_PHY_TEST_PATTERN set from what I can tell, and then
dp_ctrl_on_stream() bails out before calling dp_ctrl_link_retrain()
anyway. It would be nice if we could split dp_ctrl_on_stream() so that
the part after the check for the sink request is a different function
that is called by dp_display.c and then this code can call the 'prepare'
function that does the first part. Then we can ignore the testing path
in the code, and possibly remove the conditional in dp_ctrl_on_stream()?


 else
 DRM_ERROR("failed to enable DP link controller\n");

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index c388323..370348d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -872,7 +872,7 @@ static int dp_display_enable(struct dp_display_private *dp, 
u32 data)
 return 0;
 }

-   rc = dp_ctrl_on_stream(dp->ctrl);
+   rc = dp_ctrl_on_stream(dp->ctrl, data);
 if (!rc)
 dp_display->power_on = true;

@@ -1654,6 +1654,7 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)
 int rc = 0;
 struct dp_display_private *dp_display;
 u32 state;
+   bool force_link_train = false;

 dp_display = container_of(dp, struct dp_display_private, dp_display);
 if (!dp_display->dp_mode.drm_mode.clock) {
@@ -1688,10 +1689,14 @@ void dp_bridge_enable(struct drm_bridge *drm_bridge)

 state =  dp_display->hpd_state;

-   if (state == ST_DISPLAY_OFF)
+   if (state == ST_DISPLAY_OFF) {
 dp_display_host_phy_init(dp_display);

-   dp_display_enable(dp_display, 0);
+   if (!dp->is_edp)

I didn't see any answer to my question about why edp is special 

Re: [PATCH 15/64] drm/vc4: plane: Take possible_crtcs as an argument

2022-06-14 Thread Dave Stevenson
On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> vc4_plane_init() currently initialises the plane with no possible CRTCs,
> and will expect the caller to set it up by itself.
>
> Let's change that logic a bit to follow the syntax of
> drm_universal_plane_init() and pass the possible CRTCs bitmask as an
> argument to the function instead.
>
> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_crtc.c  |  2 +-
>  drivers/gpu/drm/vc4/vc4_drv.h   |  3 ++-
>  drivers/gpu/drm/vc4/vc4_plane.c | 15 +++
>  3 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
> index 59b20c8f132b..840a93484bb1 100644
> --- a/drivers/gpu/drm/vc4/vc4_crtc.c
> +++ b/drivers/gpu/drm/vc4/vc4_crtc.c
> @@ -1138,7 +1138,7 @@ int vc4_crtc_init(struct drm_device *drm, struct 
> vc4_crtc *vc4_crtc,
>  * requirement of the plane configuration, and reject ones
>  * that will take too much.
>  */
> -   primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY);
> +   primary_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_PRIMARY, 0);
> if (IS_ERR(primary_plane)) {
> dev_err(drm->dev, "failed to construct primary plane\n");
> return PTR_ERR(primary_plane);
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index 080deae55f64..5125ca1a8158 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -952,7 +952,8 @@ int vc4_kms_load(struct drm_device *dev);
>
>  /* vc4_plane.c */
>  struct drm_plane *vc4_plane_init(struct drm_device *dev,
> -enum drm_plane_type type);
> +enum drm_plane_type type,
> +unsigned int possible_crtcs);

A nit pick.
possible_crtcs in struct drm_plane is a uint32_t , not an unsigned int.
It would never matter on a Pi as unsigned int will never be 16bit, but
avoids the oddity.

Otherwise:
Reviewed-by: Dave Stevenson 

>  int vc4_plane_create_additional_planes(struct drm_device *dev);
>  u32 vc4_plane_write_dlist(struct drm_plane *plane, u32 __iomem *dlist);
>  u32 vc4_plane_dlist_size(const struct drm_plane_state *state);
> diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
> index b3438f4a81ce..17dab470ecdf 100644
> --- a/drivers/gpu/drm/vc4/vc4_plane.c
> +++ b/drivers/gpu/drm/vc4/vc4_plane.c
> @@ -1451,7 +1451,8 @@ static const struct drm_plane_funcs vc4_plane_funcs = {
>  };
>
>  struct drm_plane *vc4_plane_init(struct drm_device *dev,
> -enum drm_plane_type type)
> +enum drm_plane_type type,
> +unsigned int possible_crtcs)
>  {
> struct drm_plane *plane = NULL;
> struct vc4_plane *vc4_plane;
> @@ -1483,7 +1484,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
> }
>
> plane = _plane->base;
> -   ret = drm_universal_plane_init(dev, plane, 0,
> +   ret = drm_universal_plane_init(dev, plane, possible_crtcs,
>_plane_funcs,
>formats, num_formats,
>modifiers, type, NULL);
> @@ -1528,13 +1529,11 @@ int vc4_plane_create_additional_planes(struct 
> drm_device *drm)
>  */
> for (i = 0; i < 16; i++) {
> struct drm_plane *plane =
> -   vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY);
> +   vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
> +  GENMASK(drm->mode_config.num_crtc - 1, 
> 0));
>
> if (IS_ERR(plane))
> continue;
> -
> -   plane->possible_crtcs =
> -   GENMASK(drm->mode_config.num_crtc - 1, 0);
> }
>
> drm_for_each_crtc(crtc, drm) {
> @@ -1542,9 +1541,9 @@ int vc4_plane_create_additional_planes(struct 
> drm_device *drm)
>  * since we overlay planes on the CRTC in the order they were
>  * initialized.
>  */
> -   cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR);
> +   cursor_plane = vc4_plane_init(drm, DRM_PLANE_TYPE_CURSOR,
> + drm_crtc_mask(crtc));
> if (!IS_ERR(cursor_plane)) {
> -   cursor_plane->possible_crtcs = drm_crtc_mask(crtc);
> crtc->cursor = cursor_plane;
> }
> }
> --
> 2.36.1
>


Re: [PATCH 13/64] drm/vc4: hvs: Protect device resources after removal

2022-06-14 Thread Dave Stevenson
Hi Maxime

On Fri, 10 Jun 2022 at 10:30, Maxime Ripard  wrote:
>
> Whenever the device and driver are unbound, the main device and all the
> subdevices will be removed by calling their unbind() method.
>
> However, the DRM device itself will only be freed when the last user will
> have closed it.
>
> It means that there is a time window where the device and its resources
> aren't there anymore, but the userspace can still call into our driver.
>
> Fortunately, the DRM framework provides the drm_dev_enter() and
> drm_dev_exit() functions to make sure our underlying device is still there
> for the section protected by those calls. Let's add them to the HVS driver.

The framework appears to rely on the remove function calling
drm_dev_unplug instead of drm_dev_unregister, but I haven't seen a
patch that makes that change in the vc4 driver.
Have I missed it, or is there some other route to set the unplugged
flag that drm_dev_enter/exit are relying on?

  Dave

> Signed-off-by: Maxime Ripard 
> ---
>  drivers/gpu/drm/vc4/vc4_drv.h |   1 +
>  drivers/gpu/drm/vc4/vc4_hvs.c | 106 +++---
>  2 files changed, 99 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
> index aa4c5910ea05..080deae55f64 100644
> --- a/drivers/gpu/drm/vc4/vc4_drv.h
> +++ b/drivers/gpu/drm/vc4/vc4_drv.h
> @@ -317,6 +317,7 @@ struct vc4_v3d {
>  };
>
>  struct vc4_hvs {
> +   struct drm_device *dev;
> struct platform_device *pdev;
> void __iomem *regs;
> u32 __iomem *dlist;
> diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
> index 2a58fc421cf6..483053e7b14f 100644
> --- a/drivers/gpu/drm/vc4/vc4_hvs.c
> +++ b/drivers/gpu/drm/vc4/vc4_hvs.c
> @@ -25,6 +25,7 @@
>  #include 
>
>  #include 
> +#include 
>  #include 
>
>  #include "vc4_drv.h"
> @@ -66,11 +67,15 @@ static const struct debugfs_reg32 hvs_regs[] = {
>
>  void vc4_hvs_dump_state(struct vc4_hvs *hvs)
>  {
> +   struct drm_device *drm = hvs->dev;
> struct drm_printer p = drm_info_printer(>pdev->dev);
> -   int i;
> +   int idx, i;
>
> drm_print_regset32(, >regset);
>
> +   if (!drm_dev_enter(drm, ))
> +   return;
> +
> DRM_INFO("HVS ctx:\n");
> for (i = 0; i < 64; i += 4) {
> DRM_INFO("0x%08x (%s): 0x%08x 0x%08x 0x%08x 0x%08x\n",
> @@ -80,6 +85,8 @@ void vc4_hvs_dump_state(struct vc4_hvs *hvs)
>  readl((u32 __iomem *)hvs->dlist + i + 2),
>  readl((u32 __iomem *)hvs->dlist + i + 3));
> }
> +
> +   drm_dev_exit(idx);
>  }
>
>  static int vc4_hvs_debugfs_underrun(struct seq_file *m, void *data)
> @@ -132,14 +139,18 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs 
> *hvs,
> struct drm_mm_node *space,
> const u32 *kernel)
>  {
> -   int ret, i;
> +   struct drm_device *drm = hvs->dev;
> +   int idx, ret, i;
> u32 __iomem *dst_kernel;
>
> +   if (!drm_dev_enter(drm, ))
> +   return -ENODEV;
> +
> ret = drm_mm_insert_node(>dlist_mm, space, VC4_KERNEL_DWORDS);
> if (ret) {
> DRM_ERROR("Failed to allocate space for filter kernel: %d\n",
>   ret);
> -   return ret;
> +   goto err_dev_exit;
> }
>
> dst_kernel = hvs->dlist + space->start;
> @@ -153,16 +164,26 @@ static int vc4_hvs_upload_linear_kernel(struct vc4_hvs 
> *hvs,
> }
> }
>
> +   drm_dev_exit(idx);
> return 0;
> +
> +err_dev_exit:
> +   drm_dev_exit(idx);
> +   return ret;
>  }
>
>  static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
>  struct vc4_crtc *vc4_crtc)
>  {
> +   struct drm_device *drm = hvs->dev;
> struct drm_crtc *crtc = _crtc->base;
> struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state);
> +   int idx;
> u32 i;
>
> +   if (!drm_dev_enter(drm, ))
> +   return;
> +
> /* The LUT memory is laid out with each HVS channel in order,
>  * each of which takes 256 writes for R, 256 for G, then 256
>  * for B.
> @@ -177,6 +198,8 @@ static void vc4_hvs_lut_load(struct vc4_hvs *hvs,
> HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_g[i]);
> for (i = 0; i < crtc->gamma_size; i++)
> HVS_WRITE(SCALER_GAMDATA, vc4_crtc->lut_b[i]);
> +
> +   drm_dev_exit(idx);
>  }
>
>  static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
> @@ -198,7 +221,12 @@ static void vc4_hvs_update_gamma_lut(struct vc4_hvs *hvs,
>
>  u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
>  {
> +   struct drm_device *drm = hvs->dev;
> u8 field = 0;
> +   int idx;
> +
> +   if (!drm_dev_enter(drm, ))
> +   return 0;
>
> switch (fifo) {

Re: [Intel-gfx] [PATCH v7] drm/i915/display: disable HPD workers before display driver unregister

2022-06-14 Thread Andrzej Hajda

On 10.06.2022 20:37, Ville Syrjälä wrote:

On Fri, Jun 10, 2022 at 06:00:24PM +0200, Andrzej Hajda wrote:

Handling HPD during driver removal is pointless, and can cause different
use-after-free/concurrency issues:
1. Setup of deferred fbdev after fbdev unregistration.
2. Access to DP-AUX after DP-AUX removal.

Below stacktraces of both cases observed on CI:

[272.634530] general protection fault, probably for non-canonical address 
0x6b6b6b6b6b6b6b6b:  [#1] PREEMPT SMP NOPTI
[272.634536] CPU: 0 PID: 6030 Comm: i915_selftest Tainted: G U
5.18.0-rc5-CI_DRM_11603-g12dccf4f5eef+ #1
[272.634541] Hardware name: Intel Corporation Raptor Lake Client Platform/RPL-S 
ADP-S DDR5 UDIMM CRB, BIOS RPLSFWI1.R00.2397.A01.2109300731 09/30/2021
[272.634545] RIP: 0010:fb_do_apertures_overlap.part.14+0x26/0x60
...
[272.634582] Call Trace:
[272.634583]  
[272.634585]  do_remove_conflicting_framebuffers+0x59/0xa0
[272.634589]  remove_conflicting_framebuffers+0x2d/0xc0
[272.634592]  remove_conflicting_pci_framebuffers+0xc8/0x110
[272.634595]  drm_aperture_remove_conflicting_pci_framebuffers+0x52/0x70
[272.634604]  i915_driver_probe+0x63a/0xdd0 [i915]

[283.405824] cpu_latency_qos_update_request called for unknown object
[283.405866] WARNING: CPU: 2 PID: 240 at kernel/power/qos.c:296 
cpu_latency_qos_update_request+0x2d/0x100
[283.405912] CPU: 2 PID: 240 Comm: kworker/u64:9 Not tainted 
5.18.0-rc6-Patchwork_103738v3-g1672d1c43e43+ #1
[283.405915] Hardware name: Intel Corporation Raptor Lake Client Platform/RPL-S 
ADP-S DDR5 UDIMM CRB, BIOS RPLSFWI1.R00.2397.A01.2109300731 09/30/2021
[283.405916] Workqueue: i915-dp i915_digport_work_func [i915]
[283.406020] RIP: 0010:cpu_latency_qos_update_request+0x2d/0x100
...
[283.406040] Call Trace:
[283.406041]  
[283.406044]  intel_dp_aux_xfer+0x60e/0x8e0 [i915]
[283.406131]  ? finish_swait+0x80/0x80
[283.406139]  intel_dp_aux_transfer+0xc5/0x2b0 [i915]
[283.406218]  drm_dp_dpcd_access+0x79/0x130 [drm_display_helper]
[283.406227]  drm_dp_dpcd_read+0xe2/0xf0 [drm_display_helper]
[283.406233]  intel_dp_hpd_pulse+0x134/0x570 [i915]
[283.406308]  ? __down_killable+0x70/0x140
[283.406313]  i915_digport_work_func+0xba/0x150 [i915]

Signed-off-by: Andrzej Hajda 
---
Hi All,

I am not sure about changes in shutdown path, any comments welcome.
I suspect suspend path have also some common bits, but I am little
bit afraid of touching it.

Changes:
v1 - v6:
 - chasing the bug appearing only on public CI.
v7:
 - shutdown path adjusted (suggested by Jani)

Regards
Andrzej
---
  drivers/gpu/drm/i915/display/intel_display.c | 11 ---
  drivers/gpu/drm/i915/i915_driver.c   |  5 ++---
  2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c 
b/drivers/gpu/drm/i915/display/intel_display.c
index 186b37925d23f2..f9952ee8289fb2 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -10490,13 +10490,6 @@ void intel_modeset_driver_remove_noirq(struct 
drm_i915_private *i915)
 */
intel_hpd_poll_fini(i915);
  
-	/*

-* MST topology needs to be suspended so we don't have any calls to
-* fbdev after it's finalized. MST will be destroyed later as part of
-* drm_mode_config_cleanup()
-*/
-   intel_dp_mst_suspend(i915);
-
/* poll work can call into fbdev, hence clean that up afterwards */
intel_fbdev_fini(i915);
  
@@ -10588,6 +10581,10 @@ void intel_display_driver_unregister(struct drm_i915_private *i915)

if (!HAS_DISPLAY(i915))
return;
  
+	intel_dp_mst_suspend(i915);

+   intel_hpd_cancel_work(i915);
+   drm_kms_helper_poll_disable(>drm);
+
intel_fbdev_unregister(i915);
intel_audio_deinit(i915);
  
diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c

index d26dcca7e654aa..82cdccf072e2bc 100644
--- a/drivers/gpu/drm/i915/i915_driver.c
+++ b/drivers/gpu/drm/i915/i915_driver.c
@@ -1070,15 +1070,14 @@ void i915_driver_shutdown(struct drm_i915_private *i915)
i915_gem_suspend(i915);
  
  	if (HAS_DISPLAY(i915)) {

+   intel_dp_mst_suspend(i915);
+   intel_hpd_cancel_work(i915);
drm_kms_helper_poll_disable(>drm);
  
  		drm_atomic_helper_shutdown(>drm);


You can't suspend MST before this since this is what actually turns the
displays off.

The real chicken and egg sitaation is due to MST sideband depending
on HPD_IRQs to work, but we want to stop the rest of hotplug processing
before we shut down the displays to make sure fbdev/etc. doesn't light
them back up.

If we didn't have MST sidband we could just turn off hotplug interrupts
ahead of time and flush the works, but with MST we need to keep the
interrupts alive. So I suspect we need some kind of flag to indicate
that at least full hotplug handling should not happen even though the
hotplug interrupts are still enabled.




  1   2   >