Re: [Freedreno] [RFC PATCH 1/2] clk: qcom: implement RCG2 'parked' clock support

2023-10-04 Thread Dmitry Baryshkov

On 04/10/2023 15:52, Bryan O'Donoghue wrote:

On 04/10/2023 13:08, Dmitry Baryshkov wrote:

On Wed, 4 Oct 2023 at 12:27, Bryan O'Donoghue
 wrote:


On 04/10/2023 01:31, Dmitry Baryshkov wrote:

clk_rcg2_shared_ops implements support for the case of the RCG which
must not be completely turned off. However its design has one major
drawback: it doesn't allow us to properly implement the is_enabled
callback, which causes different kinds of misbehaviour from the CCF.

Follow the idea behind clk_regmap_phy_mux_ops and implement the new
clk_rcg2_parked_ops. It also targets the clocks which must not be fully
switched off (and shared most of the implementation with
clk_rcg2_shared_ops). The major difference is that it requires that the
parent map doesn't conain the safe (parked) clock source. Instead if 
the

CFG_REG register points to the safe source, the clock is considered to
be disabled.


Why not have a new bit in .flags ?

Instead of lying about the clock being off, mark the clock as "parked",
or "safe parked" or whatever term we choose for it ?


The main problem with adding flags doesn't fully scale. From the CCF
perspective, what should be the difference between parked and disabled
clocks? How should it treat the parked one?


Exactly the same as a disabled clock, except you get a "parked" instead 
of a "disabled" when looking up its state and you don't have to


-    { .fw_name = "bi_tcxo" },

Also you can then flag for branch2 clocks the same thing - so parking 
would be done at a higher level in the CCF.


Without this removal there is no easy way to identify if the clock is 
parked to XO or if it is reparented to that clock.



--
With best wishes
Dmitry



[Freedreno] [PATCH v5 7/7] drm/msm/dp: move of_dp_aux_populate_bus() to eDP probe()

2023-10-04 Thread Kuogee Hsieh
Currently eDP population is done at msm_dp_modeset_init() which happen
at binding time. Move eDP population to be done at display probe time
so that probe deferral cases can be handled effectively.
wait_for_hpd_asserted callback is added during drm_dp_aux_init()
to ensure eDP's HPD is up before proceeding eDP population.

Changes in v5:
-- inline dp_display_auxbus_population() and delete it

Changes in v4:
-- delete duplicate initialize code to dp_aux before drm_dp_aux_register()
-- delete of_get_child_by_name(dev->of_node, "aux-bus") and inline the function
-- not initialize rc = 0

Changes in v3:
-- add done_probing callback into devm_of_dp_aux_populate_bus()

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_aux.c | 34 -
 drivers/gpu/drm/msm/dp/dp_display.c | 59 +++--
 2 files changed, 51 insertions(+), 42 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 10b6eeb..03f4951 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -479,7 +479,6 @@ void dp_aux_deinit(struct drm_dp_aux *dp_aux)
 
 int dp_aux_register(struct drm_dp_aux *dp_aux)
 {
-   struct dp_aux_private *aux;
int ret;
 
if (!dp_aux) {
@@ -487,12 +486,7 @@ int dp_aux_register(struct drm_dp_aux *dp_aux)
return -EINVAL;
}
 
-   aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
-
-   aux->dp_aux.name = "dpu_dp_aux";
-   aux->dp_aux.dev = aux->dev;
-   aux->dp_aux.transfer = dp_aux_transfer;
-   ret = drm_dp_aux_register(&aux->dp_aux);
+   ret = drm_dp_aux_register(dp_aux);
if (ret) {
DRM_ERROR("%s: failed to register drm aux: %d\n", __func__,
ret);
@@ -507,6 +501,21 @@ void dp_aux_unregister(struct drm_dp_aux *dp_aux)
drm_dp_aux_unregister(dp_aux);
 }
 
+static int dp_wait_hpd_asserted(struct drm_dp_aux *dp_aux,
+unsigned long wait_us)
+{
+   int ret;
+   struct dp_aux_private *aux;
+
+   aux = container_of(dp_aux, struct dp_aux_private, dp_aux);
+
+   pm_runtime_get_sync(aux->dev);
+   ret = dp_catalog_aux_wait_for_hpd_connect_state(aux->catalog);
+   pm_runtime_put_sync(aux->dev);
+
+   return ret;
+}
+
 struct drm_dp_aux *dp_aux_get(struct device *dev, struct dp_catalog *catalog,
  bool is_edp)
 {
@@ -530,6 +539,17 @@ struct drm_dp_aux *dp_aux_get(struct device *dev, struct 
dp_catalog *catalog,
aux->catalog = catalog;
aux->retry_cnt = 0;
 
+   /*
+* Use the drm_dp_aux_init() to use the aux adapter
+* before registering AUX with the DRM device so that
+* msm eDP panel can be detected by generic_dep_panel_probe().
+*/
+   aux->dp_aux.name = "dpu_dp_aux";
+   aux->dp_aux.dev = dev;
+   aux->dp_aux.transfer = dp_aux_transfer;
+   aux->dp_aux.wait_hpd_asserted = dp_wait_hpd_asserted;
+   drm_dp_aux_init(&aux->dp_aux);
+
return &aux->dp_aux;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 79e56d9..df15145 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1207,6 +1207,17 @@ static const struct msm_dp_desc 
*dp_display_get_desc(struct platform_device *pde
return NULL;
 }
 
+static int dp_auxbus_done_probe(struct drm_dp_aux *aux)
+{
+   int rc;
+
+   rc = component_add(aux->dev, &dp_display_comp_ops);
+   if (rc)
+   DRM_ERROR("eDP component add failed, rc=%d\n", rc);
+
+   return rc;
+}
+
 static int dp_display_probe(struct platform_device *pdev)
 {
int rc = 0;
@@ -1272,10 +1283,18 @@ static int dp_display_probe(struct platform_device 
*pdev)
if (rc)
goto err;
 
-   rc = component_add(&pdev->dev, &dp_display_comp_ops);
-   if (rc) {
-   DRM_ERROR("component add failed, rc=%d\n", rc);
-   goto err;
+   if (dp->dp_display.is_edp) {
+   rc = devm_of_dp_aux_populate_bus(dp->aux, dp_auxbus_done_probe);
+   if (rc) {
+   DRM_ERROR("eDP auxbus population failed, rc=%d\n", rc);
+   goto err;
+   }
+   } else {
+   rc = component_add(&pdev->dev, &dp_display_comp_ops);
+   if (rc) {
+   DRM_ERROR("component add failed, rc=%d\n", rc);
+   goto err;
+   }
}
 
return rc;
@@ -1291,7 +1310,6 @@ static int dp_display_remove(struct platform_device *pdev)
 
component_del(&pdev->dev, &dp_display_comp_ops);
dp_display_deinit_sub_modules(dp);
-
platform_set_drvdata(pdev, NULL);
 
return 0;
@@ -1388,29 +1406,8 @@ static int dp_display_get_next_bridge(struct msm_dp *dp)
 {
int rc;
struct dp_display_private *dp_pri

[Freedreno] [PATCH v5 6/7] drm/msm/dp: delete EV_HPD_INIT_SETUP

2023-10-04 Thread Kuogee Hsieh
EV_HPD_INIT_SETUP flag is used to trigger the initialization of external
DP host controller. Since external DP host controller initialization had
been incorporated into pm_runtime_resume(), this flag became obsolete.
msm_dp_irq_postinstall() which triggers EV_HPD_INIT_SETUP event is
obsoleted accordingly.

Changes in v4:
-- reworded commit text
-- drop EV_HPD_INIT_SETUP
-- drop msm_dp_irq_postinstall()

Changes in v3:
-- drop EV_HPD_INIT_SETUP and msm_dp_irq_postinstall()

Signed-off-by: Kuogee Hsieh 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  4 
 drivers/gpu/drm/msm/dp/dp_display.c | 16 
 drivers/gpu/drm/msm/msm_drv.h   |  5 -
 3 files changed, 25 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index aa6ba2c..146f263 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -869,7 +869,6 @@ static int dpu_irq_postinstall(struct msm_kms *kms)
 {
struct msm_drm_private *priv;
struct dpu_kms *dpu_kms = to_dpu_kms(kms);
-   int i;
 
if (!dpu_kms || !dpu_kms->dev)
return -EINVAL;
@@ -878,9 +877,6 @@ static int dpu_irq_postinstall(struct msm_kms *kms)
if (!priv)
return -EINVAL;
 
-   for (i = 0; i < ARRAY_SIZE(priv->dp); i++)
-   msm_dp_irq_postinstall(priv->dp[i]);
-
return 0;
 }
 
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 42efe148b..79e56d9 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -54,7 +54,6 @@ enum {
 enum {
EV_NO_EVENT,
/* hpd events */
-   EV_HPD_INIT_SETUP,
EV_HPD_PLUG_INT,
EV_IRQ_HPD_INT,
EV_HPD_UNPLUG_INT,
@@ -1089,8 +1088,6 @@ static int hpd_event_thread(void *data)
spin_unlock_irqrestore(&dp_priv->event_lock, flag);
 
switch (todo->event_id) {
-   case EV_HPD_INIT_SETUP:
-   break;
case EV_HPD_PLUG_INT:
dp_hpd_plug_handle(dp_priv, todo->data);
break;
@@ -1359,19 +1356,6 @@ void __exit msm_dp_unregister(void)
platform_driver_unregister(&dp_display_driver);
 }
 
-void msm_dp_irq_postinstall(struct msm_dp *dp_display)
-{
-   struct dp_display_private *dp;
-
-   if (!dp_display)
-   return;
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
-
-   if (!dp_display->is_edp)
-   dp_add_event(dp, EV_HPD_INIT_SETUP, 0, 0);
-}
-
 bool msm_dp_wide_bus_available(const struct msm_dp *dp_display)
 {
struct dp_display_private *dp;
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 02fd6c7..30723da 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -384,7 +384,6 @@ int __init msm_dp_register(void);
 void __exit msm_dp_unregister(void);
 int msm_dp_modeset_init(struct msm_dp *dp_display, struct drm_device *dev,
 struct drm_encoder *encoder);
-void msm_dp_irq_postinstall(struct msm_dp *dp_display);
 void msm_dp_snapshot(struct msm_disp_state *disp_state, struct msm_dp 
*dp_display);
 
 void msm_dp_debugfs_init(struct msm_dp *dp_display, struct drm_minor *minor);
@@ -405,10 +404,6 @@ static inline int msm_dp_modeset_init(struct msm_dp 
*dp_display,
return -EINVAL;
 }
 
-static inline void msm_dp_irq_postinstall(struct msm_dp *dp_display)
-{
-}
-
 static inline void msm_dp_snapshot(struct msm_disp_state *disp_state, struct 
msm_dp *dp_display)
 {
 }
-- 
2.7.4



[Freedreno] [PATCH v5 5/7] drm/msm/dp: incorporate pm_runtime framework into DP driver

2023-10-04 Thread Kuogee Hsieh
Currently DP driver is executed independent of PM runtime framework.
This leads msm eDP panel can not being detected by edp_panel driver during
generic_edp_panel_probe() due to AUX DPCD read failed at edp panel driver.
Incorporate PM runtime framework into DP driver so that host controller's
power and clocks are enable/disable through PM runtime mechanism.
Once PM runtime framework is incorporated into DP driver, waking up device
from power up path is not necessary. Hence remove it.

After incorporating pm_runtime framework into eDP/DP driver, dp_pm_suspend()
to handle power off both DP phy and controller during suspend and
dp_pm_resume() to handle power on both DP phy and controller during resume
are not necessary. Therefore both dp_pm_suspend() and dp_pm_resume() are
dropped and replace with dp_pm_runtime_suspend() and dp_pm_runtime_resume()
respectively.

Changes in v5:
-- remove pm_runtime_put_autosuspend feature, use pm_runtime_put_sync() directly
-- squash add pm_runtime_force_suspend()/resume() patch into this patch

Changes in v4:
-- reworded commit text to explain why pm_framework is required for edp panel
-- reworded commit text to explain autosuspend is choiced
-- delete EV_POWER_PM_GET and PM_EV_POWER_PUT from changes #3
-- delete dp_display_pm_get() and dp_display_pm_Put() from changes #3
-- return value from pm_runtime_resume_and_get() directly
-- check return value of devm_pm_runtime_enable()
-- delete pm_runtime_xxx from dp_display_remove()
-- drop dp_display_host_init() from EV_HPD_INIT_SETUP
-- drop both dp_pm_prepare() and dp_pm_compete() from this change
-- delete ST_SUSPENDED state
-- rewording commit text to add more details regrading the purpose
   of this change

Changes in v3:
-- incorporate removing pm_runtime_xx() from dp_pwer.c to this patch
-- use pm_runtime_resume_and_get() instead of pm_runtime_get()
-- error checking pm_runtime_resume_and_get() return value
-- add EV_POWER_PM_GET and PM_EV_POWER_PUT to handle HPD_GPIO case
-- replace dp_pm_suspend() with pm_runtime_force_suspend()
-- replace dp_pm_resume() with pm_runtime_force_resume()

Signed-off-by: Kuogee Hsieh 
Reported-by: kernel test robot 
---
 drivers/gpu/drm/msm/dp/dp_aux.c |   5 ++
 drivers/gpu/drm/msm/dp/dp_display.c | 166 
 drivers/gpu/drm/msm/dp/dp_power.c   |  16 
 drivers/gpu/drm/msm/dp/dp_power.h   |  11 ---
 4 files changed, 59 insertions(+), 139 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 8e3b677..10b6eeb 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -291,6 +291,10 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
return -EINVAL;
}
 
+   ret = pm_runtime_resume_and_get(dp_aux->dev);
+   if (ret)
+   return  ret;
+
mutex_lock(&aux->mutex);
if (!aux->initted) {
ret = -EIO;
@@ -364,6 +368,7 @@ static ssize_t dp_aux_transfer(struct drm_dp_aux *dp_aux,
 
 exit:
mutex_unlock(&aux->mutex);
+   pm_runtime_put_sync(dp_aux->dev);
 
return ret;
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index e4942fc..42efe148b 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -49,7 +49,6 @@ enum {
ST_CONNECTED,
ST_DISCONNECT_PENDING,
ST_DISPLAY_OFF,
-   ST_SUSPENDED,
 };
 
 enum {
@@ -310,15 +309,10 @@ static void dp_display_unbind(struct device *dev, struct 
device *master,
struct dp_display_private *dp = dev_get_dp_display_private(dev);
struct msm_drm_private *priv = dev_get_drvdata(master);
 
-   /* disable all HPD interrupts */
-   if (dp->core_initialized)
-   dp_catalog_hpd_config_intr(dp->catalog, DP_DP_HPD_INT_MASK, 
false);
-
kthread_stop(dp->ev_tsk);
 
of_dp_aux_depopulate_bus(dp->aux);
 
-   dp_power_client_deinit(dp->power);
dp_unregister_audio_driver(dev, dp->audio);
dp_aux_unregister(dp->aux);
dp->drm_dev = NULL;
@@ -559,7 +553,7 @@ static int dp_hpd_plug_handle(struct dp_display_private 
*dp, u32 data)
drm_dbg_dp(dp->drm_dev, "Before, type=%d hpd_state=%d\n",
dp->dp_display.connector_type, state);
 
-   if (state == ST_DISPLAY_OFF || state == ST_SUSPENDED) {
+   if (state == ST_DISPLAY_OFF) {
mutex_unlock(&dp->event_mutex);
return 0;
}
@@ -576,6 +570,14 @@ static int dp_hpd_plug_handle(struct dp_display_private 
*dp, u32 data)
return 0;
}
 
+   if (!dp->dp_display.is_edp) {
+   ret = pm_runtime_resume_and_get(&dp->pdev->dev);
+   if (ret) {
+   DRM_ERROR("failed to pm_runtime_resume\n");
+   return ret;
+   }
+   }
+
ret = dp_display_usbpd_configure_cb(&dp->pdev->dev);
if (ret) { 

[Freedreno] [PATCH v5 3/7] drm/msm/dp: use drm_bridge_hpd_notify() to report HPD status changes

2023-10-04 Thread Kuogee Hsieh
Currently DP driver use drm_helper_hpd_irq_event(), bypassing drm bridge
framework, to report HPD status changes to user space frame work.
Replace it with drm_bridge_hpd_notify() since DP driver is part of drm
bridge.

Signed-off-by: Kuogee Hsieh 
Reviewed-by: Dmitry Baryshkov 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 20 ++--
 1 file changed, 2 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 9e51876..32663ea 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -356,26 +356,10 @@ static bool dp_display_is_sink_count_zero(struct 
dp_display_private *dp)
(dp->link->sink_count == 0);
 }
 
-static void dp_display_send_hpd_event(struct msm_dp *dp_display)
-{
-   struct dp_display_private *dp;
-   struct drm_connector *connector;
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
-
-   connector = dp->dp_display.connector;
-   drm_helper_hpd_irq_event(connector->dev);
-}
-
 static int dp_display_send_hpd_notification(struct dp_display_private *dp,
bool hpd)
 {
-   if ((hpd && dp->dp_display.link_ready) ||
-   (!hpd && !dp->dp_display.link_ready)) {
-   drm_dbg_dp(dp->drm_dev, "HPD already %s\n",
-   (hpd ? "on" : "off"));
-   return 0;
-   }
+   struct drm_bridge *bridge = dp->dp_display.bridge;
 
/* reset video pattern flag on disconnect */
if (!hpd)
@@ -385,7 +369,7 @@ static int dp_display_send_hpd_notification(struct 
dp_display_private *dp,
 
drm_dbg_dp(dp->drm_dev, "type=%d hpd=%d\n",
dp->dp_display.connector_type, hpd);
-   dp_display_send_hpd_event(&dp->dp_display);
+   drm_bridge_hpd_notify(bridge, dp->dp_display.link_ready);
 
return 0;
 }
-- 
2.7.4



[Freedreno] [PATCH v5 4/7] drm/msm/dp: move parser->parse() and dp_power_client_init() to probe

2023-10-04 Thread Kuogee Hsieh
Original both parser->parse() and dp_power_client_init() are done at
dp_display_bind() since eDP population is done at binding time.
In the preparation of having eDP population done at probe() time,
move both function from dp_display_bind() to dp_display_probe().

Changes in v4:
-- explain why parser->parse() and dp_power_client_init() are moved to probe 
time
-- tear down sub modules if failed

Changes in v4:
-- split this patch out of "incorporate pm_runtime framework into DP driver" 
patch

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

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 32663ea..e4942fc 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -276,11 +276,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
dp->dp_display.drm_dev = drm;
priv->dp[dp->id] = &dp->dp_display;
 
-   rc = dp->parser->parse(dp->parser);
-   if (rc) {
-   DRM_ERROR("device tree parsing failed\n");
-   goto end;
-   }
 
 
dp->drm_dev = drm;
@@ -291,11 +286,6 @@ static int dp_display_bind(struct device *dev, struct 
device *master,
goto end;
}
 
-   rc = dp_power_client_init(dp->power);
-   if (rc) {
-   DRM_ERROR("Power client create failed\n");
-   goto end;
-   }
 
rc = dp_register_audio_driver(dev, dp->audio);
if (rc) {
@@ -1250,6 +1240,18 @@ static int dp_display_probe(struct platform_device *pdev)
return -EPROBE_DEFER;
}
 
+   rc = dp->parser->parse(dp->parser);
+   if (rc) {
+   DRM_ERROR("device tree parsing failed\n");
+   goto err;
+   }
+
+   rc = dp_power_client_init(dp->power);
+   if (rc) {
+   DRM_ERROR("Power client create failed\n");
+   goto err;
+   }
+
/* setup event q */
mutex_init(&dp->event_mutex);
init_waitqueue_head(&dp->event_q);
-- 
2.7.4



[Freedreno] [PATCH v5 2/7] drm/msm/dp: rename is_connected with link_ready

2023-10-04 Thread Kuogee Hsieh
The is_connected flag is set to true after DP mainlink successfully
finishes link training to enter into ST_MAINLINK_READY state rather
than being set after the DP dongle is connected. Rename the
is_connected flag with link_ready flag to match the state of DP
driver's state machine.

Changes in v5:
-- reworded commit text according to review comments from change #4

Changes in v4:
-- reworded commit text

Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_display.c | 19 +--
 drivers/gpu/drm/msm/dp/dp_display.h |  2 +-
 drivers/gpu/drm/msm/dp/dp_drm.c | 14 +++---
 3 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 940da48..9e51876 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -367,12 +367,11 @@ static void dp_display_send_hpd_event(struct msm_dp 
*dp_display)
drm_helper_hpd_irq_event(connector->dev);
 }
 
-
 static int dp_display_send_hpd_notification(struct dp_display_private *dp,
bool hpd)
 {
-   if ((hpd && dp->dp_display.is_connected) ||
-   (!hpd && !dp->dp_display.is_connected)) {
+   if ((hpd && dp->dp_display.link_ready) ||
+   (!hpd && !dp->dp_display.link_ready)) {
drm_dbg_dp(dp->drm_dev, "HPD already %s\n",
(hpd ? "on" : "off"));
return 0;
@@ -382,7 +381,7 @@ static int dp_display_send_hpd_notification(struct 
dp_display_private *dp,
if (!hpd)
dp->panel->video_test = false;
 
-   dp->dp_display.is_connected = hpd;
+   dp->dp_display.link_ready = hpd;
 
drm_dbg_dp(dp->drm_dev, "type=%d hpd=%d\n",
dp->dp_display.connector_type, hpd);
@@ -922,7 +921,7 @@ int dp_display_set_plugged_cb(struct msm_dp *dp_display,
 
dp_display->plugged_cb = fn;
dp_display->codec_dev = codec_dev;
-   plugged = dp_display->is_connected;
+   plugged = dp_display->link_ready;
dp_display_handle_plugged_change(dp_display, plugged);
 
return 0;
@@ -1355,16 +1354,16 @@ static int dp_pm_resume(struct device *dev)
 * also only signal audio when disconnected
 */
if (dp->link->sink_count) {
-   dp->dp_display.is_connected = true;
+   dp->dp_display.link_ready = true;
} else {
-   dp->dp_display.is_connected = false;
+   dp->dp_display.link_ready = false;
dp_display_handle_plugged_change(dp_display, false);
}
 
drm_dbg_dp(dp->drm_dev,
"After, type=%d sink=%d conn=%d core_init=%d phy_init=%d 
power=%d\n",
dp->dp_display.connector_type, dp->link->sink_count,
-   dp->dp_display.is_connected, dp->core_initialized,
+   dp->dp_display.link_ready, dp->core_initialized,
dp->phy_initialized, dp_display->power_on);
 
mutex_unlock(&dp->event_mutex);
@@ -1757,8 +1756,8 @@ void dp_bridge_hpd_notify(struct drm_bridge *bridge,
return;
}
 
-   if (!dp_display->is_connected && status == connector_status_connected)
+   if (!dp_display->link_ready && status == connector_status_connected)
dp_add_event(dp, EV_HPD_PLUG_INT, 0, 0);
-   else if (dp_display->is_connected && status == 
connector_status_disconnected)
+   else if (dp_display->link_ready && status == 
connector_status_disconnected)
dp_add_event(dp, EV_HPD_UNPLUG_INT, 0, 0);
 }
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index b3c08de..d65693e 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -16,7 +16,7 @@ struct msm_dp {
struct drm_bridge *bridge;
struct drm_connector *connector;
struct drm_bridge *next_bridge;
-   bool is_connected;
+   bool link_ready;
bool audio_enabled;
bool power_on;
unsigned int connector_type;
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index 785d766..ee945ca 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -24,10 +24,10 @@ static enum drm_connector_status dp_bridge_detect(struct 
drm_bridge *bridge)
 
dp = to_dp_bridge(bridge)->dp_display;
 
-   drm_dbg_dp(dp->drm_dev, "is_connected = %s\n",
-   (dp->is_connected) ? "true" : "false");
+   drm_dbg_dp(dp->drm_dev, "link_ready = %s\n",
+   (dp->link_ready) ? "true" : "false");
 
-   return (dp->is_connected) ? connector_status_connected :
+   return (dp->link_ready) ? connector_status_connected :
connector_status_disconnected;
 }
 
@@ -40,8 +40,8 @@ static int dp_bridge_atomic_check(struct drm_bridge *bridge,
 
dp = t

[Freedreno] [PATCH v5 1/7] drm/msm/dp: tie dp_display_irq_handler() with dp driver

2023-10-04 Thread Kuogee Hsieh
Currently the dp_display_request_irq() is executed at msm_dp_modeset_init()
which ties irq registering to the DPU device's life cycle, while depending on
resources that are released as the DP device is torn down. Move register DP
driver irq handler to dp_display_probe() to have dp_display_irq_handler()
IRQ tied with DP device. In addition, use platform_get_irq() to retrieve irq
number from platform device directly.

Changes in v5:
-- reworded commit text as review comments at change #4
-- tear down component if failed at dp_display_request_irq()

Changes in v4:
-- delete dp->irq check at dp_display_request_irq()

Changes in v3:
-- move calling dp_display_irq_handler() to probe

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

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 76f1395..940da48 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1193,26 +1193,18 @@ static irqreturn_t dp_display_irq_handler(int irq, void 
*dev_id)
return ret;
 }
 
-int dp_display_request_irq(struct msm_dp *dp_display)
+static int dp_display_request_irq(struct dp_display_private *dp)
 {
int rc = 0;
-   struct dp_display_private *dp;
-
-   if (!dp_display) {
-   DRM_ERROR("invalid input\n");
-   return -EINVAL;
-   }
-
-   dp = container_of(dp_display, struct dp_display_private, dp_display);
+   struct device *dev = &dp->pdev->dev;
 
-   dp->irq = irq_of_parse_and_map(dp->pdev->dev.of_node, 0);
+   dp->irq = platform_get_irq(dp->pdev, 0);
if (!dp->irq) {
DRM_ERROR("failed to get irq\n");
return -EINVAL;
}
 
-   rc = devm_request_irq(dp_display->drm_dev->dev, dp->irq,
-   dp_display_irq_handler,
+   rc = devm_request_irq(dev, dp->irq, dp_display_irq_handler,
IRQF_TRIGGER_HIGH, "dp_display_isr", dp);
if (rc < 0) {
DRM_ERROR("failed to request IRQ%u: %d\n",
@@ -1287,13 +1279,21 @@ static int dp_display_probe(struct platform_device 
*pdev)
 
platform_set_drvdata(pdev, &dp->dp_display);
 
+   rc = dp_display_request_irq(dp);
+   if (rc)
+   goto err;
+
rc = component_add(&pdev->dev, &dp_display_comp_ops);
if (rc) {
DRM_ERROR("component add failed, rc=%d\n", rc);
-   dp_display_deinit_sub_modules(dp);
+   goto err;
}
 
return rc;
+
+err:
+   dp_display_deinit_sub_modules(dp);
+   return rc;
 }
 
 static int dp_display_remove(struct platform_device *pdev)
@@ -1549,12 +1549,6 @@ int msm_dp_modeset_init(struct msm_dp *dp_display, 
struct drm_device *dev,
 
dp_priv = container_of(dp_display, struct dp_display_private, 
dp_display);
 
-   ret = dp_display_request_irq(dp_display);
-   if (ret) {
-   DRM_ERROR("request_irq failed, ret=%d\n", ret);
-   return ret;
-   }
-
ret = dp_display_get_next_bridge(dp_display);
if (ret)
return ret;
diff --git a/drivers/gpu/drm/msm/dp/dp_display.h 
b/drivers/gpu/drm/msm/dp/dp_display.h
index 1e9415a..b3c08de 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.h
+++ b/drivers/gpu/drm/msm/dp/dp_display.h
@@ -35,7 +35,6 @@ struct msm_dp {
 int dp_display_set_plugged_cb(struct msm_dp *dp_display,
hdmi_codec_plugged_cb fn, struct device *codec_dev);
 int dp_display_get_modes(struct msm_dp *dp_display);
-int dp_display_request_irq(struct msm_dp *dp_display);
 bool dp_display_check_video_test(struct msm_dp *dp_display);
 int dp_display_get_test_bpp(struct msm_dp *dp_display);
 void dp_display_signal_audio_start(struct msm_dp *dp_display);
-- 
2.7.4



[Freedreno] [PATCH v5 0/7] incorporate pm runtime framework and eDP clean up

2023-10-04 Thread Kuogee Hsieh
The purpose of this patch series is to incorporate pm runtime framework
into MSM eDP/DP driver so that eDP panel can be detected by DRM eDP panel
driver during system probe time. During incorporating procedure, original
customized pm realted fucntions, such as dp_pm_prepare(), dp_pm_suspend(),
dp_pm_resume() and dp_pm_prepare(), are removed and replaced with functions
provided by pm runtiem framework such as pm_runtime_force_suspend() and
pm_runtime_force_resume(). In addition, both eDP aux-bus and irq handler
are bound at system probe time too.

Kuogee Hsieh (7):
  drm/msm/dp: tie dp_display_irq_handler() with dp driver
  drm/msm/dp: rename is_connected with link_ready
  drm/msm/dp: use drm_bridge_hpd_notify() to report HPD status changes
  drm/msm/dp: move parser->parse() and dp_power_client_init() to probe
  drm/msm/dp: incorporate pm_runtime framework into DP driver
  drm/msm/dp: delete EV_HPD_INIT_SETUP
  drm/msm/dp: move of_dp_aux_populate_bus() to eDP probe()

 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |   4 -
 drivers/gpu/drm/msm/dp/dp_aux.c |  39 +++-
 drivers/gpu/drm/msm/dp/dp_display.c | 318 +++-
 drivers/gpu/drm/msm/dp/dp_display.h |   3 +-
 drivers/gpu/drm/msm/dp/dp_drm.c |  14 +-
 drivers/gpu/drm/msm/dp/dp_power.c   |  16 --
 drivers/gpu/drm/msm/dp/dp_power.h   |  11 --
 drivers/gpu/drm/msm/msm_drv.h   |   5 -
 8 files changed, 146 insertions(+), 264 deletions(-)

-- 
2.7.4



Re: [Freedreno] [RFC PATCH 1/2] clk: qcom: implement RCG2 'parked' clock support

2023-10-04 Thread Bryan O'Donoghue

On 04/10/2023 13:08, Dmitry Baryshkov wrote:

On Wed, 4 Oct 2023 at 12:27, Bryan O'Donoghue
 wrote:


On 04/10/2023 01:31, Dmitry Baryshkov wrote:

clk_rcg2_shared_ops implements support for the case of the RCG which
must not be completely turned off. However its design has one major
drawback: it doesn't allow us to properly implement the is_enabled
callback, which causes different kinds of misbehaviour from the CCF.

Follow the idea behind clk_regmap_phy_mux_ops and implement the new
clk_rcg2_parked_ops. It also targets the clocks which must not be fully
switched off (and shared most of the implementation with
clk_rcg2_shared_ops). The major difference is that it requires that the
parent map doesn't conain the safe (parked) clock source. Instead if the
CFG_REG register points to the safe source, the clock is considered to
be disabled.


Why not have a new bit in .flags ?

Instead of lying about the clock being off, mark the clock as "parked",
or "safe parked" or whatever term we choose for it ?


The main problem with adding flags doesn't fully scale. From the CCF
perspective, what should be the difference between parked and disabled
clocks? How should it treat the parked one?


Exactly the same as a disabled clock, except you get a "parked" instead 
of a "disabled" when looking up its state and you don't have to


-   { .fw_name = "bi_tcxo" },

Also you can then flag for branch2 clocks the same thing - so parking 
would be done at a higher level in the CCF.


---
bod


Re: [Freedreno] [RFC PATCH 1/2] clk: qcom: implement RCG2 'parked' clock support

2023-10-04 Thread Dmitry Baryshkov
On Wed, 4 Oct 2023 at 12:27, Bryan O'Donoghue
 wrote:
>
> On 04/10/2023 01:31, Dmitry Baryshkov wrote:
> > clk_rcg2_shared_ops implements support for the case of the RCG which
> > must not be completely turned off. However its design has one major
> > drawback: it doesn't allow us to properly implement the is_enabled
> > callback, which causes different kinds of misbehaviour from the CCF.
> >
> > Follow the idea behind clk_regmap_phy_mux_ops and implement the new
> > clk_rcg2_parked_ops. It also targets the clocks which must not be fully
> > switched off (and shared most of the implementation with
> > clk_rcg2_shared_ops). The major difference is that it requires that the
> > parent map doesn't conain the safe (parked) clock source. Instead if the
> > CFG_REG register points to the safe source, the clock is considered to
> > be disabled.
>
> Why not have a new bit in .flags ?
>
> Instead of lying about the clock being off, mark the clock as "parked",
> or "safe parked" or whatever term we choose for it ?

The main problem with adding flags doesn't fully scale. From the CCF
perspective, what should be the difference between parked and disabled
clocks? How should it treat the parked one?

>From my point of view, the 'parked' clock is as good as 'disabled',
because the end devices do not work with the corresponding clock being
sourced from XO.
We already have a similar implementation for the PCIe PIPE clocks,
which reinterpret physical 'XO' source as a 'disabled' state to
facilitate disabling the clock before turning the genpd off.

>
> I feel 'disabled' should mean disabled and 'enabled' should me enabled
> when I read a value from debugfs and if we are parking a clock it should
> have a clear means of being flagged as a clock that should be parked.
>
> An example. I recently inherited some autogenerated code for camcc on
> sc8280xp.
>
> One of the clocks is marked as CLK_IS_CRITICAL by the autogen code
> meaning "never switch off" but CLK_IS_CRITICAL stops the camcc driver
> from doing runtime pm_ops to power collapse.
>
> The solution I have is to remove CLK_IS_CRITICAL and to hard-code in
> probe() the clock to always on.
>
> But if we had a CLK_DISABLE_SAFE_PARK flag - then not just for rcg but
> for branch clocks we could differentiate away from hard-coded always on
> in probe...
>
> ?
>
> ---
> bod



--
With best wishes
Dmitry


Re: [Freedreno] [PATCH v8 0/5] Add fdinfo support to Panfrost

2023-10-04 Thread Boris Brezillon
On Fri, 29 Sep 2023 19:14:26 +0100
Adrián Larumbe  wrote:

> This patch series adds fdinfo support to the Panfrost DRM driver. It will
> display a series of key:value pairs under /proc/pid/fdinfo/fd for render
> processes that open the Panfrost DRM file.
> 
> The pairs contain basic drm gpu engine and memory region information that
> can either be cat by a privileged user or accessed with IGT's gputop
> utility.
> 
> Changelog:
> 
> v1: 
> https://lore.kernel.org/lkml/bb52b872-e41b-3894-285e-b52cfc849...@arm.com/T/
> 
> v2: https://lore.kernel.org/lkml/20230901084457.5bc1a...@collabora.com/T/
>  - Changed the way gpu cycles and engine time are calculated, using GPU
>registers and taking into account potential resets.
>  - Split render engine values into fragment and vertex/tiler ones.
>  - Added more fine-grained calculation of RSS size for BO's.
>  - Implemente selection of drm-memory region size units.
>  - Removed locking of shrinker's mutex in GEM obj status function.
> 
> v3: 
> https://lore.kernel.org/lkml/20230905184533.959171-1-adrian.laru...@collabora.com/
>  - Changed fdinfo engine names to something more descriptive.;
>  - Mentioned GPU cycle counts aren't an exact measure.
>  - Handled the case when job->priv might be NULL.
>  - Handled 32 bit overflow of cycle register.
>  - Kept fdinfo drm memory stats size unit display within 10k times the
>previous multiplier for more accurate BO size numbers.
>  - Removed special handling of Prime imported BO RSS.
>  - Use rss_size only for heap objects.
>  - Use bo->base.madv instead of specific purgeable flag.
>  - Fixed kernel test robot warnings.
> 
> v4: 
> https://lore.kernel.org/lkml/20230912084044.955864-1-adrian.laru...@collabora.com/
>  - Move cycle counter get and put to panfrost_job_hw_submit and
>panfrost_job_handle_{err,done} for more accuracy.
>  - Make sure cycle counter refs are released in reset path
>  - Drop the model param for toggling cycle counting and do
>leave it down to the debugfs file.
>  - Don't disable cycle counter when togglint debugfs file,
>let refcounting logic handle it instead.
>  - Remove fdinfo data nested structure definion and 'names' field
>  - When incrementing BO RSS size in GPU MMU page fault IRQ handler, assume
>granuality of 2MiB for every successful mapping.
>  - drm-file picks an fdinfo memory object size unit that doesn't lose 
> precision.
> 
> v5: 
> https://lore.kernel.org/lkml/20230914223928.2374933-1-adrian.laru...@collabora.com/
>  - Removed explicit initialisation of atomic variable for profiling mode,
>as it's allocated with kzalloc.
>  - Pass engine utilisation structure to jobs rather than the file context, to 
> avoid
>future misusage of the latter.
>  - Remove double reading of cycle counter register and ktime in job deqeueue 
> function,
>as the scheduler will make sure these values are read over in case of 
> requeuing.
>  - Moved putting of cycle counting refcnt into panfrost job dequeue.
>function to avoid repetition.
> 
> v6: 
> https://lore.kernel.org/lkml/c73ad42b-a8db-23c2-86c7-1a2939dba...@linux.intel.com/T/
>  - Fix wrong swapped-round engine time and cycle values in fdinfo
>drm print statements.
> 
> v7: 
> https://lore.kernel.org/lkml/20230927213133.1651169-6-adrian.laru...@collabora.com/T/
>  - Make sure an object's actual RSS size is added to the overall fdinfo's 
> purgeable
>and active size tally when it's both resident and purgeable or active.
>  - Create a drm/panfrost.rst documentation file with meaning of fdinfo 
> strings.
>  - BUILD_BUG_ON checking the engine name array size for fdinfo.
>  - Added copyright notices for Amazon in Panfrost's new debugfs files.
>  - Discarded fdinfo memory stats unit size selection patch.
> 
> v8:
>  - Style improvements and addressing nitpicks. 
> 
> Adrián Larumbe (5):
>   drm/panfrost: Add cycle count GPU register definitions
>   drm/panfrost: Add fdinfo support GPU load metrics
>   drm/panfrost: Add fdinfo support for memory stats
>   drm/drm_file: Add DRM obj's RSS reporting function for fdinfo
>   drm/panfrost: Implement generic DRM object RSS reporting function

Queued to drm-misc-next.

Thanks!

Boris

> 
>  Documentation/gpu/drm-usage-stats.rst   |  1 +
>  Documentation/gpu/panfrost.rst  | 38 +
>  drivers/gpu/drm/drm_file.c  |  8 +--
>  drivers/gpu/drm/panfrost/Makefile   |  2 +
>  drivers/gpu/drm/panfrost/panfrost_debugfs.c | 21 
>  drivers/gpu/drm/panfrost/panfrost_debugfs.h | 14 +
>  drivers/gpu/drm/panfrost/panfrost_devfreq.c |  8 +++
>  drivers/gpu/drm/panfrost/panfrost_devfreq.h |  3 ++
>  drivers/gpu/drm/panfrost/panfrost_device.c  |  2 +
>  drivers/gpu/drm/panfrost/panfrost_device.h  | 13 +
>  drivers/gpu/drm/panfrost/panfrost_drv.c | 60 -
>  drivers/gpu/drm/panfrost/panfrost_gem.c | 30 +++
>  drivers/gpu/drm/panfrost/panfrost_gem.h |  5 ++
>  drivers/gpu/drm/panfro

Re: [Freedreno] [RFC PATCH 1/2] clk: qcom: implement RCG2 'parked' clock support

2023-10-04 Thread Bryan O'Donoghue

On 04/10/2023 01:31, Dmitry Baryshkov wrote:

clk_rcg2_shared_ops implements support for the case of the RCG which
must not be completely turned off. However its design has one major
drawback: it doesn't allow us to properly implement the is_enabled
callback, which causes different kinds of misbehaviour from the CCF.

Follow the idea behind clk_regmap_phy_mux_ops and implement the new
clk_rcg2_parked_ops. It also targets the clocks which must not be fully
switched off (and shared most of the implementation with
clk_rcg2_shared_ops). The major difference is that it requires that the
parent map doesn't conain the safe (parked) clock source. Instead if the
CFG_REG register points to the safe source, the clock is considered to
be disabled.


Why not have a new bit in .flags ?

Instead of lying about the clock being off, mark the clock as "parked", 
or "safe parked" or whatever term we choose for it ?


I feel 'disabled' should mean disabled and 'enabled' should me enabled 
when I read a value from debugfs and if we are parking a clock it should 
have a clear means of being flagged as a clock that should be parked.


An example. I recently inherited some autogenerated code for camcc on 
sc8280xp.


One of the clocks is marked as CLK_IS_CRITICAL by the autogen code 
meaning "never switch off" but CLK_IS_CRITICAL stops the camcc driver 
from doing runtime pm_ops to power collapse.


The solution I have is to remove CLK_IS_CRITICAL and to hard-code in 
probe() the clock to always on.


But if we had a CLK_DISABLE_SAFE_PARK flag - then not just for rcg but 
for branch clocks we could differentiate away from hard-coded always on 
in probe...


?

---
bod