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

2021-12-21 Thread Kuogee Hsieh



On 12/14/2021 5:50 PM, Stephen Boyd wrote:

Quoting Kuogee Hsieh (2021-12-09 13:35:07)

diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
b/drivers/gpu/drm/msm/dp/dp_display.c
index 0766752..cfbc5e4 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -83,6 +83,7 @@ struct dp_display_private {

 /* state variables */
 bool core_initialized;
+   bool phy_initialized;
 bool hpd_irq_on;
 bool audio_supported;

@@ -371,21 +372,46 @@ static int dp_display_process_hpd_high(struct 
dp_display_private *dp)
 return rc;
  }

-static void dp_display_host_init(struct dp_display_private *dp, int reset)
+static void dp_display_host_phy_init(struct dp_display_private *dp)
  {
-   bool flip = false;
+   DRM_DEBUG_DP("core_init=%d phy_init=%d\n",
+   dp->core_initialized, dp->phy_initialized);

+   if (!dp->phy_initialized) {

Is this check only here because we don't know when this function is
getting called? I see in the DP case we get here from
dp_display_usbpd_configure_cb() but in the eDP case we get here from
dp_display_host_init() and presumably again from
dp_display_usbpd_configure_cb() called by dp_hpd_plug_handle().

If at all possible, I'd prefer to not have another tracking variable and
call dp_display_host_phy_init() from the same place regardless of DP or
eDP. Doing that would make it symmetric, per the commit text.


Agree, but  dp->phy_initialized variable used to track some other 
conditions.


For example, phy required to be re inited if dpcd read failed due to 
cable unplugged.


other dpcd read failed will not required to re inited.

Therefore I think dp->phy_initialized variable is still required.


+   dp_ctrl_phy_init(dp->ctrl);
+   dp->phy_initialized = true;
+   }
+}
+
+static void dp_display_host_phy_exit(struct dp_display_private *dp)
+{
+   DRM_DEBUG_DP("core_init=%d phy_init=%d\n",
+   dp->core_initialized, dp->phy_initialized);
+
+   if (dp->phy_initialized) {
+   dp_ctrl_phy_exit(dp->ctrl);
+   dp->phy_initialized = false;
+   }
+}
+
+static void dp_display_host_init(struct dp_display_private *dp)
+{
 DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized);
 if (dp->core_initialized) {
 DRM_DEBUG_DP("DP core already initialized\n");
 return;
 }

-   if (dp->usbpd->orientation == ORIENTATION_CC2)
-   flip = true;
+   dp_power_init(dp->power, false);
+   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
+
+   /*
+* eDP is the embedded primary display and has its own phy
+* initialize phy immediately

Can we get some more details here? Why is it better to initialize the
phy here vs. when HPD goes high on the panel? The comment says what the
code is doing but it isn't telling us why that's OK.


Will do.




+*/
+   if (dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP)
+   dp_display_host_phy_init(dp);

-   dp_power_init(dp->power, flip);
-   dp_ctrl_host_init(dp->ctrl, flip, reset);
 dp_aux_init(dp->aux);
 dp->core_initialized = true;
  }


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

2021-12-14 Thread Stephen Boyd
Quoting Kuogee Hsieh (2021-12-09 13:35:07)
> diff --git a/drivers/gpu/drm/msm/dp/dp_display.c 
> b/drivers/gpu/drm/msm/dp/dp_display.c
> index 0766752..cfbc5e4 100644
> --- a/drivers/gpu/drm/msm/dp/dp_display.c
> +++ b/drivers/gpu/drm/msm/dp/dp_display.c
> @@ -83,6 +83,7 @@ struct dp_display_private {
>
> /* state variables */
> bool core_initialized;
> +   bool phy_initialized;
> bool hpd_irq_on;
> bool audio_supported;
>
> @@ -371,21 +372,46 @@ static int dp_display_process_hpd_high(struct 
> dp_display_private *dp)
> return rc;
>  }
>
> -static void dp_display_host_init(struct dp_display_private *dp, int reset)
> +static void dp_display_host_phy_init(struct dp_display_private *dp)
>  {
> -   bool flip = false;
> +   DRM_DEBUG_DP("core_init=%d phy_init=%d\n",
> +   dp->core_initialized, dp->phy_initialized);
>
> +   if (!dp->phy_initialized) {

Is this check only here because we don't know when this function is
getting called? I see in the DP case we get here from
dp_display_usbpd_configure_cb() but in the eDP case we get here from
dp_display_host_init() and presumably again from
dp_display_usbpd_configure_cb() called by dp_hpd_plug_handle().

If at all possible, I'd prefer to not have another tracking variable and
call dp_display_host_phy_init() from the same place regardless of DP or
eDP. Doing that would make it symmetric, per the commit text.

> +   dp_ctrl_phy_init(dp->ctrl);
> +   dp->phy_initialized = true;
> +   }
> +}
> +
> +static void dp_display_host_phy_exit(struct dp_display_private *dp)
> +{
> +   DRM_DEBUG_DP("core_init=%d phy_init=%d\n",
> +   dp->core_initialized, dp->phy_initialized);
> +
> +   if (dp->phy_initialized) {
> +   dp_ctrl_phy_exit(dp->ctrl);
> +   dp->phy_initialized = false;
> +   }
> +}
> +
> +static void dp_display_host_init(struct dp_display_private *dp)
> +{
> DRM_DEBUG_DP("core_initialized=%d\n", dp->core_initialized);
> if (dp->core_initialized) {
> DRM_DEBUG_DP("DP core already initialized\n");
> return;
> }
>
> -   if (dp->usbpd->orientation == ORIENTATION_CC2)
> -   flip = true;
> +   dp_power_init(dp->power, false);
> +   dp_ctrl_reset_irq_ctrl(dp->ctrl, true);
> +
> +   /*
> +* eDP is the embedded primary display and has its own phy
> +* initialize phy immediately

Can we get some more details here? Why is it better to initialize the
phy here vs. when HPD goes high on the panel? The comment says what the
code is doing but it isn't telling us why that's OK.

> +*/
> +   if (dp->dp_display.connector_type == DRM_MODE_CONNECTOR_eDP)
> +   dp_display_host_phy_init(dp);
>
> -   dp_power_init(dp->power, flip);
> -   dp_ctrl_host_init(dp->ctrl, flip, reset);
> dp_aux_init(dp->aux);
> dp->core_initialized = true;
>  }


[PATCH v7 2/2] drm/msm/dp: do not initialize phy until plugin interrupt received

2021-12-09 Thread Kuogee Hsieh
Current DP drivers have regulators, clocks, irq and phy are grouped
together within a function and executed not in a symmetric manner.
This increase difficulty of code maintenance and limited code scalability.
This patch divides the driver life cycle of operation into four states,
resume (including booting up), dongle plugin, dongle unplugged and suspend.
Regulators, core clocks and irq are grouped together and enabled at resume
(or booting up) so that the DP controller is armed and ready to receive HPD
plugin interrupts. HPD plugin interrupt is generated when a dongle plugs
into DUT (device under test). Once HPD plugin interrupt is received, DP
controller will initialize phy so that dpcd read/write will function and
following link training can be proceeded successfully. DP phy will be
disabled after main link is teared down at end of unplugged HPD interrupt
handle triggered by dongle unplugged out of DUT. Finally regulators, code
clocks and irq are disabled at corresponding suspension.

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

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

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

Changes in V5:
-- rebase on top of msm-next branch

Changes in V6:
-- delete flip variable

Changes in V7:
-- dp_ctrl_irq_enable/disabe() merged into dp_ctrl_reset_irq_ctrl()

Fixes: 8ede2ecc3e5e ("drm/msm/dp: Add DP compliance tests on Snapdragon 
Chipsets")
Signed-off-by: Kuogee Hsieh 
---
 drivers/gpu/drm/msm/dp/dp_ctrl.c| 77 --
 drivers/gpu/drm/msm/dp/dp_ctrl.h|  8 ++--
 drivers/gpu/drm/msm/dp/dp_display.c | 84 ++---
 3 files changed, 92 insertions(+), 77 deletions(-)

diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index c724cb0..39558a2 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -1365,60 +1365,44 @@ static int dp_ctrl_enable_stream_clocks(struct 
dp_ctrl_private *ctrl)
return ret;
 }
 
-int dp_ctrl_host_init(struct dp_ctrl *dp_ctrl, bool flip, bool reset)
+void dp_ctrl_reset_irq_ctrl(struct dp_ctrl *dp_ctrl, bool enable)
+{
+   struct dp_ctrl_private *ctrl;
+
+   ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+   dp_catalog_ctrl_reset(ctrl->catalog);
+
+   if (enable)
+   dp_catalog_ctrl_enable_irq(ctrl->catalog, enable);
+}
+
+void dp_ctrl_phy_init(struct dp_ctrl *dp_ctrl)
 {
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;
 
-   if (!dp_ctrl) {
-   DRM_ERROR("Invalid input data\n");
-   return -EINVAL;
-   }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;
 
-   ctrl->dp_ctrl.orientation = flip;
-
-   if (reset)
-   dp_catalog_ctrl_reset(ctrl->catalog);
-
-   DRM_DEBUG_DP("flip=%d\n", flip);
dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_init(phy);
-   dp_catalog_ctrl_enable_irq(ctrl->catalog, true);
-
-   return 0;
 }
 
-/**
- * dp_ctrl_host_deinit() - Uninitialize DP controller
- * @dp_ctrl: Display Port Driver data
- *
- * Perform required steps to uninitialize DP controller
- * and its resources.
- */
-void dp_ctrl_host_deinit(struct dp_ctrl *dp_ctrl)
+void dp_ctrl_phy_exit(struct dp_ctrl *dp_ctrl)
 {
struct dp_ctrl_private *ctrl;
struct dp_io *dp_io;
struct phy *phy;
 
-   if (!dp_ctrl) {
-   DRM_ERROR("Invalid input data\n");
-   return;
-   }
-
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
dp_io = &ctrl->parser->io;
phy = dp_io->phy;
 
-   dp_catalog_ctrl_enable_irq(ctrl->catalog, false);
+   dp_catalog_ctrl_phy_reset(ctrl->catalog);
phy_exit(phy);
-
-   DRM_DEBUG_DP("Host deinitialized successfully\n");
 }
 
 static bool dp_ctrl_use_fixed_nvid(struct dp_ctrl_private *ctrl)
@@ -1893,8 +1877,14 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
return ret;
}
 
+   DRM_DEBUG_DP("Before, phy=%x init_count=%d power_on=%d\n",
+   (u32)(uintptr_t)phy, phy->init_count, phy->power_count);
+
phy_power_off(phy);
 
+   DRM_DEBUG_DP("After, phy=%x init_count=%d power_on=%d\n",
+   (u32)(uintptr_t)phy, phy->init_count, phy->power_count);
+
/* aux channel down, reinit phy */
phy_exit(phy);
phy_init(phy);
@@ -1903,23 +1893,6 @@ int dp_ctrl_off_link_stream(struct dp_ctrl *dp_ctrl)
return ret;
 }
 
-void dp_ctrl_off_phy(struct dp_ctrl *dp_ctrl)
-{
-   struct dp_ctrl_private *ctrl;
-   struct dp_io *dp_io;
-   s