diff mbox series

[RFC,v2,1/5] drm/msm/dp: fix panel bridge attachment

Message ID 20220211224006.1797846-2-dmitry.baryshkov@linaro.org
State Accepted
Commit 4d793a02c4967ab14d4ae5e86a51ee02ed78921a
Headers show
Series Simplify and correct msm/dp bridge implementation | expand

Commit Message

Dmitry Baryshkov Feb. 11, 2022, 10:40 p.m. UTC
In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
enable and disable") the DP driver received a drm_bridge instance, which
is always attached to the encoder as a root bridge. However it conflicts
with the panel_bridge support for eDP panels. The panel bridge attaches
to the encoder before the "dp" bridge has a chace to do so. Change
panel_bridge attachment to come after dp_bridge attachment.

Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable")
Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
---
 drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

Comments

Kuogee Hsieh Feb. 18, 2022, 9:14 p.m. UTC | #1
On 2/11/2022 2:40 PM, Dmitry Baryshkov wrote:
> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> enable and disable") the DP driver received a drm_bridge instance, which
> is always attached to the encoder as a root bridge. However it conflicts
> with the panel_bridge support for eDP panels. The panel bridge attaches
> to the encoder before the "dp" bridge has a chace to do so. Change
> panel_bridge attachment to come after dp_bridge attachment.
>
> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable")
> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Tested-by: Kuogee Hsieh <quic_khsieh@quicinc.com>
> ---
>   drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
>   1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
> index d4d360d19eba..26ef41a4c1b6 100644
> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
> @@ -169,16 +169,6 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
>   
>   	drm_connector_attach_encoder(connector, dp_display->encoder);
>   
> -	if (dp_display->panel_bridge) {
> -		ret = drm_bridge_attach(dp_display->encoder,
> -					dp_display->panel_bridge, NULL,
> -					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -		if (ret < 0) {
> -			DRM_ERROR("failed to attach panel bridge: %d\n", ret);
> -			return ERR_PTR(ret);
> -		}
> -	}
> -
>   	return connector;
>   }
>   
> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi
>   		return ERR_PTR(rc);
>   	}
>   
> +	if (dp_display->panel_bridge) {
> +		rc = drm_bridge_attach(dp_display->encoder,
> +					dp_display->panel_bridge, bridge,
> +					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +		if (rc < 0) {
> +			DRM_ERROR("failed to attach panel bridge: %d\n", rc);
> +			drm_bridge_remove(bridge);
> +			return ERR_PTR(rc);
> +		}
> +	}
> +
>   	return bridge;
>   }
Stephen Boyd Feb. 18, 2022, 11:56 p.m. UTC | #2
Quoting Dmitry Baryshkov (2022-02-11 14:40:02)
> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> enable and disable") the DP driver received a drm_bridge instance, which
> is always attached to the encoder as a root bridge. However it conflicts
> with the panel_bridge support for eDP panels. The panel bridge attaches
> to the encoder before the "dp" bridge has a chace to do so. Change

s/chace/chance/

> panel_bridge attachment to come after dp_bridge attachment.

s/panel_bridge/panel bridge/ possibly? And maybe clarify that dp_bridge
is the "DP driver's drm_bridge instance created in
msm_dp_bridge_init()"?

My understanding is that we want to pass the bridge created in
msm_dp_bridge_init() as the 'previous' bridge so that it attaches the
panel bridge to the output of the DP bridge that's attached to the
encoder.

>
> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable")
> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> ---

Reviewed-by: Stephen Boyd <swboyd@chromium.org>

>  drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
>  1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
> index d4d360d19eba..26ef41a4c1b6 100644
> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
> @@ -169,16 +169,6 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
>
>         drm_connector_attach_encoder(connector, dp_display->encoder);
>
> -       if (dp_display->panel_bridge) {
> -               ret = drm_bridge_attach(dp_display->encoder,
> -                                       dp_display->panel_bridge, NULL,
> -                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> -               if (ret < 0) {
> -                       DRM_ERROR("failed to attach panel bridge: %d\n", ret);
> -                       return ERR_PTR(ret);
> -               }
> -       }
> -
>         return connector;
>  }
>
> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi
>                 return ERR_PTR(rc);
>         }
>
> +       if (dp_display->panel_bridge) {
> +               rc = drm_bridge_attach(dp_display->encoder,
> +                                       dp_display->panel_bridge, bridge,
> +                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> +               if (rc < 0) {
> +                       DRM_ERROR("failed to attach panel bridge: %d\n", rc);
> +                       drm_bridge_remove(bridge);
> +                       return ERR_PTR(rc);
> +               }
> +       }
> +
>         return bridge;

Not a problem with this patch, but what is this pointer used for? I see
it's assigned to priv->bridges and num_bridges is incremented but nobody
seems to look at that.
Dmitry Baryshkov Feb. 19, 2022, 2:26 a.m. UTC | #3
On 19/02/2022 02:56, Stephen Boyd wrote:
> Quoting Dmitry Baryshkov (2022-02-11 14:40:02)
>> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
>> enable and disable") the DP driver received a drm_bridge instance, which
>> is always attached to the encoder as a root bridge. However it conflicts
>> with the panel_bridge support for eDP panels. The panel bridge attaches
>> to the encoder before the "dp" bridge has a chace to do so. Change
> 
> s/chace/chance/
> 
>> panel_bridge attachment to come after dp_bridge attachment.
> 
> s/panel_bridge/panel bridge/ possibly? And maybe clarify that dp_bridge
> is the "DP driver's drm_bridge instance created in
> msm_dp_bridge_init()"?
> 
> My understanding is that we want to pass the bridge created in
> msm_dp_bridge_init() as the 'previous' bridge so that it attaches the
> panel bridge to the output of the DP bridge that's attached to the
> encoder.

Thanks! I'll update the commit log when pushing the patches.

> 
>>
>> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display enable and disable")
>> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>> ---
> 
> Reviewed-by: Stephen Boyd <swboyd@chromium.org>
> 
>>   drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
>>   1 file changed, 11 insertions(+), 10 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
>> index d4d360d19eba..26ef41a4c1b6 100644
>> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
>> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
>> @@ -169,16 +169,6 @@ struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
>>
>>          drm_connector_attach_encoder(connector, dp_display->encoder);
>>
>> -       if (dp_display->panel_bridge) {
>> -               ret = drm_bridge_attach(dp_display->encoder,
>> -                                       dp_display->panel_bridge, NULL,
>> -                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>> -               if (ret < 0) {
>> -                       DRM_ERROR("failed to attach panel bridge: %d\n", ret);
>> -                       return ERR_PTR(ret);
>> -               }
>> -       }
>> -
>>          return connector;
>>   }
>>
>> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi
>>                  return ERR_PTR(rc);
>>          }
>>
>> +       if (dp_display->panel_bridge) {
>> +               rc = drm_bridge_attach(dp_display->encoder,
>> +                                       dp_display->panel_bridge, bridge,
>> +                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>> +               if (rc < 0) {
>> +                       DRM_ERROR("failed to attach panel bridge: %d\n", rc);
>> +                       drm_bridge_remove(bridge);
>> +                       return ERR_PTR(rc);
>> +               }
>> +       }
>> +
>>          return bridge;
> 
> Not a problem with this patch, but what is this pointer used for? I see
> it's assigned to priv->bridges and num_bridges is incremented but nobody
> seems to look at that.


That's on my todo list. to remove connectors array and to destroy 
created bridges during drm device destruction.
Abhinav Kumar Feb. 25, 2022, 2:01 a.m. UTC | #4
On 2/24/2022 12:41 PM, Dmitry Baryshkov wrote:
> On Thu, 24 Feb 2022 at 21:25, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>>
>>
>>
>> On 2/18/2022 6:26 PM, Dmitry Baryshkov wrote:
>>> On 19/02/2022 02:56, Stephen Boyd wrote:
>>>> Quoting Dmitry Baryshkov (2022-02-11 14:40:02)
>>>>> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
>>>>> enable and disable") the DP driver received a drm_bridge instance, which
>>>>> is always attached to the encoder as a root bridge. However it conflicts
>>>>> with the panel_bridge support for eDP panels. The panel bridge attaches
>>>>> to the encoder before the "dp" bridge has a chace to do so. Change
>>>>
>>>> s/chace/chance/
>>>>
>>>>> panel_bridge attachment to come after dp_bridge attachment.
>>>>
>>>> s/panel_bridge/panel bridge/ possibly? And maybe clarify that dp_bridge
>>>> is the "DP driver's drm_bridge instance created in
>>>> msm_dp_bridge_init()"?
>>>>
>>>> My understanding is that we want to pass the bridge created in
>>>> msm_dp_bridge_init() as the 'previous' bridge so that it attaches the
>>>> panel bridge to the output of the DP bridge that's attached to the
>>>> encoder.
>>>
>>> Thanks! I'll update the commit log when pushing the patches.
>>
>> Please correct if i am missing something here.
>>
>> You are right that the eDP panel's panel bridge attaches to the encoder
>> in dp_drm_connector_init() which happens before msm_dp_bridge_init() and
>> hence it will attach directly to the encoder.
>>
>> But we are talking about different encoders here. DP's dp_display has a
>> different encoder compared to the EDP's dp_display.
> 
> The encoders are different. However both encoders use the same
> codepath, which includes dp_bridge. It controls dp_display by calling
> msm_dp_display_foo() functions.
> 
>> So DP's bridge will still be attached to its encoder's root.
> 
> There is one dp_bridge per each encoder. Consider sc8180x which has 3
> DP controllers (and thus 3 dp_bridges).
> 

Sorry, but I still didnt follow this.

So for eDP, dp_drm_connector_init() will attach the panel_bridge
and then msm_dp_bridge_init() will add a drm_bridge.

And yes in that case, the drm_bridge will be after the panel_bridge

But since panel_bridge is at the root for eDP it should be okay.

Your commit text was mentioning about DP.

For DP, for each controller in the catalog, we will call modeset_init() 
which should skip this part for DP

   if (dp_display->panel_bridge) {
         ret = drm_bridge_attach(dp_display->encoder,
                     dp_display->panel_bridge, NULL,
                     DRM_BRIDGE_ATTACH_NO_CONNECTOR);
         if (ret < 0) {
             DRM_ERROR("failed to attach panel bridge: %d\n", ret);
             return ERR_PTR(ret);
         }
     }

Followed by calling msm_dp_bridge_init() which will actually attach the 
bridge:

drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);

Now, even for 3 DP controllers, this shall be true as there will be 3 
separate encoders and 3 dp_displays and hence 3 drm_bridges.

What am i missing here?

>>
>> So what are we achieving with this change?
>>
>>>
>>>>
>>>>>
>>>>> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
>>>>> enable and disable")
>>>>> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
>>>>> ---
>>>>
>>>> Reviewed-by: Stephen Boyd <swboyd@chromium.org>
>>>>
>>>>>    drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
>>>>>    1 file changed, 11 insertions(+), 10 deletions(-)
>>>>>
>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c
>>>>> b/drivers/gpu/drm/msm/dp/dp_drm.c
>>>>> index d4d360d19eba..26ef41a4c1b6 100644
>>>>> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
>>>>> @@ -169,16 +169,6 @@ struct drm_connector
>>>>> *dp_drm_connector_init(struct msm_dp *dp_display)
>>>>>
>>>>>           drm_connector_attach_encoder(connector, dp_display->encoder);
>>>>>
>>>>> -       if (dp_display->panel_bridge) {
>>>>> -               ret = drm_bridge_attach(dp_display->encoder,
>>>>> -                                       dp_display->panel_bridge, NULL,
>>>>> -                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>>>> -               if (ret < 0) {
>>>>> -                       DRM_ERROR("failed to attach panel bridge:
>>>>> %d\n", ret);
>>>>> -                       return ERR_PTR(ret);
>>>>> -               }
>>>>> -       }
>>>>> -
>>>>>           return connector;
>>>>>    }
>>>>>
>>>>> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct
>>>>> msm_dp *dp_display, struct drm_devi
>>>>>                   return ERR_PTR(rc);
>>>>>           }
>>>>>
>>>>> +       if (dp_display->panel_bridge) {
>>>>> +               rc = drm_bridge_attach(dp_display->encoder,
>>>>> +                                       dp_display->panel_bridge,
>>>>> bridge,
>>>>> +                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
>>>>> +               if (rc < 0) {
>>>>> +                       DRM_ERROR("failed to attach panel bridge:
>>>>> %d\n", rc);
>>>>> +                       drm_bridge_remove(bridge);
>>>>> +                       return ERR_PTR(rc);
>>>>> +               }
>>>>> +       }
>>>>> +
>>>>>           return bridge;
>>>>
>>>> Not a problem with this patch, but what is this pointer used for? I see
>>>> it's assigned to priv->bridges and num_bridges is incremented but nobody
>>>> seems to look at that.
>>>
>>>
>>> That's on my todo list. to remove connectors array and to destroy
>>> created bridges during drm device destruction.
>>>
> 
> 
>
Dmitry Baryshkov Feb. 25, 2022, 9:04 a.m. UTC | #5
On Fri, 25 Feb 2022 at 07:45, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 2/24/2022 8:22 PM, Dmitry Baryshkov wrote:
> > On Fri, 25 Feb 2022 at 05:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 2/24/2022 12:41 PM, Dmitry Baryshkov wrote:
> >>> On Thu, 24 Feb 2022 at 21:25, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 2/18/2022 6:26 PM, Dmitry Baryshkov wrote:
> >>>>> On 19/02/2022 02:56, Stephen Boyd wrote:
> >>>>>> Quoting Dmitry Baryshkov (2022-02-11 14:40:02)
> >>>>>>> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> >>>>>>> enable and disable") the DP driver received a drm_bridge instance, which
> >>>>>>> is always attached to the encoder as a root bridge. However it conflicts
> >>>>>>> with the panel_bridge support for eDP panels. The panel bridge attaches
> >>>>>>> to the encoder before the "dp" bridge has a chace to do so. Change
> >>>>>>
> >>>>>> s/chace/chance/
> >>>>>>
> >>>>>>> panel_bridge attachment to come after dp_bridge attachment.
> >>>>>>
> >>>>>> s/panel_bridge/panel bridge/ possibly? And maybe clarify that dp_bridge
> >>>>>> is the "DP driver's drm_bridge instance created in
> >>>>>> msm_dp_bridge_init()"?
> >>>>>>
> >>>>>> My understanding is that we want to pass the bridge created in
> >>>>>> msm_dp_bridge_init() as the 'previous' bridge so that it attaches the
> >>>>>> panel bridge to the output of the DP bridge that's attached to the
> >>>>>> encoder.
> >>>>>
> >>>>> Thanks! I'll update the commit log when pushing the patches.
> >>>>
> >>>> Please correct if i am missing something here.
> >>>>
> >>>> You are right that the eDP panel's panel bridge attaches to the encoder
> >>>> in dp_drm_connector_init() which happens before msm_dp_bridge_init() and
> >>>> hence it will attach directly to the encoder.
> >>>>
> >>>> But we are talking about different encoders here. DP's dp_display has a
> >>>> different encoder compared to the EDP's dp_display.
> >>>
> >>> The encoders are different. However both encoders use the same
> >>> codepath, which includes dp_bridge. It controls dp_display by calling
> >>> msm_dp_display_foo() functions.
> >>>
> >
> >>>> So DP's bridge will still be attached to its encoder's root.
> >>>
> >>> There is one dp_bridge per each encoder. Consider sc8180x which has 3
> >>> DP controllers (and thus 3 dp_bridges).
> >>>
> >>
> >> Sorry, but I still didnt follow this.
> >>
> >> So for eDP, dp_drm_connector_init() will attach the panel_bridge
> >> and then msm_dp_bridge_init() will add a drm_bridge.
> >>
> >> And yes in that case, the drm_bridge will be after the panel_bridge
> >>
> >> But since panel_bridge is at the root for eDP it should be okay.
> >
> > No. It is not.
> > For both DP and eDP the chain should be:
> > dpu_encoder -> dp_bridge -> external (panel) bridge, optional for DP
> > -> [other bridges] -> connector
> >
> > Otherwise drm_bridge_chain_foo() functions would be called in the
> > incorrect order.
>
> Agreed. For drm_bridge_chain_foo() ordering to be correct, for eDP chain
> the order should be what you mentioned and panel_bridge should be at the
> end ( should be the last one ).
>
> For the above reason,
>
> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
>
> I still didnt understand what gets affected by this for the
> msm_dp_display_foo() functions you mentioned earlier and wanted to get
> some clarity on that.

They should be called at the correct time.

> >
> > Thus the dp_bridge should be attached directly to the encoder
> > (drm_encoder) and panel_bridge should use dp_bridge as the 'previous'
> > bridge.
> >
>
> Agreed.
>
> > For example, for the DP port one can use a display-connector (which
> > actually implements drm_bridge) as an external bridge to provide hpd
> > or dp power GPIOs.
> >
> > Note, that the current dp_connector breaks layering. It makes calls
> > directly into dp_display, not allowing external bridge (and other
> > bridges) to override get_modes/mode_valid and other callbacks.
> > Thus one of the next patches in series (the one that Kuogee had issues
> > with) tries to replace the chain with the following one:
> > dpu_encoder -> dp_bridge -> external (panel) bridge -> [other bridges]
> > -> drm_bridge_connector.
> >
> >>
>
> So originally the plan was always that the DP connector layer intercepts
> the call because panel-eDP file did not support reading of the EDID ( we
> have not provided the aux bus ). So it was intended that we did not want
> to goto the eDP panel to get the modes. Not an error but something which
> we wanted to cleanup later when we moved to panel-eDP completely.

panel_edp_get_modes() correctly handles this case and returns modes
specified in the panel description. So the code should work even with
panel-eDP and w/o the AUX bus.

>
> Till then we wanted the dp_connector to read the EDID and get the modes.
>
> So this was actually intended to happen till the point where we moved to
> panel-eDP to get the modes.
>
> Hence what you have mentioned in your cover letter is right that the
> chain was broken but there was no loss of functionality due to that today.
>
> Now that these changes are made, we can still goto panel-eDP file for
> the modes because of the below change from Sankeerth where the mode is
> hard-coded:
>
> https://patchwork.freedesktop.org/patch/473431/
>
> With this change cherry-picked it should work for kuogee. We will
> re-test that with this change.

I suppose he had both of the changes in the tree. Otherwise the
panel_edp_get_modes() wouldn't be called.

> >> Your commit text was mentioning about DP.
> >>
> >> For DP, for each controller in the catalog, we will call modeset_init()
> >> which should skip this part for DP
> >>
> >>     if (dp_display->panel_bridge) {
> >>           ret = drm_bridge_attach(dp_display->encoder,
> >>                       dp_display->panel_bridge, NULL,
> >
> > as you see, NULL is incorrect. It should be a pointer to dp_bridge instead
> >
> >>                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>           if (ret < 0) {
> >>               DRM_ERROR("failed to attach panel bridge: %d\n", ret);
> >>               return ERR_PTR(ret);
> >>           }
> >>       }
> >>
> >> Followed by calling msm_dp_bridge_init() which will actually attach the
> >> bridge:
> >>
> >> drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >
> > And this bridge should be attached before the external bridge.
> >
> >>
> >> Now, even for 3 DP controllers, this shall be true as there will be 3
> >> separate encoders and 3 dp_displays and hence 3 drm_bridges.
> >>
> >> What am i missing here?
> >>
> >>>>
> >>>> So what are we achieving with this change?
> >>>>
> >>>>>
> >>>>>>
> >>>>>>>
> >>>>>>> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> >>>>>>> enable and disable")
> >>>>>>> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
> >>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >>>>>>> ---
> >>>>>>
> >>>>>> Reviewed-by: Stephen Boyd <swboyd@chromium.org>
> >>>>>>
> >>>>>>>     drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
> >>>>>>>     1 file changed, 11 insertions(+), 10 deletions(-)
> >>>>>>>
> >>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>> b/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>> index d4d360d19eba..26ef41a4c1b6 100644
> >>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>> @@ -169,16 +169,6 @@ struct drm_connector
> >>>>>>> *dp_drm_connector_init(struct msm_dp *dp_display)
> >>>>>>>
> >>>>>>>            drm_connector_attach_encoder(connector, dp_display->encoder);
> >>>>>>>
> >>>>>>> -       if (dp_display->panel_bridge) {
> >>>>>>> -               ret = drm_bridge_attach(dp_display->encoder,
> >>>>>>> -                                       dp_display->panel_bridge, NULL,
> >>>>>>> -                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>>>> -               if (ret < 0) {
> >>>>>>> -                       DRM_ERROR("failed to attach panel bridge:
> >>>>>>> %d\n", ret);
> >>>>>>> -                       return ERR_PTR(ret);
> >>>>>>> -               }
> >>>>>>> -       }
> >>>>>>> -
> >>>>>>>            return connector;
> >>>>>>>     }
> >>>>>>>
> >>>>>>> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct
> >>>>>>> msm_dp *dp_display, struct drm_devi
> >>>>>>>                    return ERR_PTR(rc);
> >>>>>>>            }
> >>>>>>>
> >>>>>>> +       if (dp_display->panel_bridge) {
> >>>>>>> +               rc = drm_bridge_attach(dp_display->encoder,
> >>>>>>> +                                       dp_display->panel_bridge,
> >>>>>>> bridge,
> >>>>>>> +                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>>>> +               if (rc < 0) {
> >>>>>>> +                       DRM_ERROR("failed to attach panel bridge:
> >>>>>>> %d\n", rc);
> >>>>>>> +                       drm_bridge_remove(bridge);
> >>>>>>> +                       return ERR_PTR(rc);
> >>>>>>> +               }
> >>>>>>> +       }
> >>>>>>> +
> >>>>>>>            return bridge;
> >>>>>>
> >>>>>> Not a problem with this patch, but what is this pointer used for? I see
> >>>>>> it's assigned to priv->bridges and num_bridges is incremented but nobody
> >>>>>> seems to look at that.
> >>>>>
> >>>>>
> >>>>> That's on my todo list. to remove connectors array and to destroy
> >>>>> created bridges during drm device destruction.
> >>>>>
> >>>
> >>>
> >>>
> >
> >
> >
Dmitry Baryshkov Feb. 25, 2022, 5:25 p.m. UTC | #6
On Fri, 25 Feb 2022 at 20:11, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
>
>
>
> On 2/25/2022 1:04 AM, Dmitry Baryshkov wrote:
> > On Fri, 25 Feb 2022 at 07:45, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>
> >>
> >>
> >> On 2/24/2022 8:22 PM, Dmitry Baryshkov wrote:
> >>> On Fri, 25 Feb 2022 at 05:01, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>
> >>>>
> >>>>
> >>>> On 2/24/2022 12:41 PM, Dmitry Baryshkov wrote:
> >>>>> On Thu, 24 Feb 2022 at 21:25, Abhinav Kumar <quic_abhinavk@quicinc.com> wrote:
> >>>>>>
> >>>>>>
> >>>>>>
> >>>>>> On 2/18/2022 6:26 PM, Dmitry Baryshkov wrote:
> >>>>>>> On 19/02/2022 02:56, Stephen Boyd wrote:
> >>>>>>>> Quoting Dmitry Baryshkov (2022-02-11 14:40:02)
> >>>>>>>>> In commit 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> >>>>>>>>> enable and disable") the DP driver received a drm_bridge instance, which
> >>>>>>>>> is always attached to the encoder as a root bridge. However it conflicts
> >>>>>>>>> with the panel_bridge support for eDP panels. The panel bridge attaches
> >>>>>>>>> to the encoder before the "dp" bridge has a chace to do so. Change
> >>>>>>>>
> >>>>>>>> s/chace/chance/
> >>>>>>>>
> >>>>>>>>> panel_bridge attachment to come after dp_bridge attachment.
> >>>>>>>>
> >>>>>>>> s/panel_bridge/panel bridge/ possibly? And maybe clarify that dp_bridge
> >>>>>>>> is the "DP driver's drm_bridge instance created in
> >>>>>>>> msm_dp_bridge_init()"?
> >>>>>>>>
> >>>>>>>> My understanding is that we want to pass the bridge created in
> >>>>>>>> msm_dp_bridge_init() as the 'previous' bridge so that it attaches the
> >>>>>>>> panel bridge to the output of the DP bridge that's attached to the
> >>>>>>>> encoder.
> >>>>>>>
> >>>>>>> Thanks! I'll update the commit log when pushing the patches.
> >>>>>>
> >>>>>> Please correct if i am missing something here.
> >>>>>>
> >>>>>> You are right that the eDP panel's panel bridge attaches to the encoder
> >>>>>> in dp_drm_connector_init() which happens before msm_dp_bridge_init() and
> >>>>>> hence it will attach directly to the encoder.
> >>>>>>
> >>>>>> But we are talking about different encoders here. DP's dp_display has a
> >>>>>> different encoder compared to the EDP's dp_display.
> >>>>>
> >>>>> The encoders are different. However both encoders use the same
> >>>>> codepath, which includes dp_bridge. It controls dp_display by calling
> >>>>> msm_dp_display_foo() functions.
> >>>>>
> >>>
> >>>>>> So DP's bridge will still be attached to its encoder's root.
> >>>>>
> >>>>> There is one dp_bridge per each encoder. Consider sc8180x which has 3
> >>>>> DP controllers (and thus 3 dp_bridges).
> >>>>>
> >>>>
> >>>> Sorry, but I still didnt follow this.
> >>>>
> >>>> So for eDP, dp_drm_connector_init() will attach the panel_bridge
> >>>> and then msm_dp_bridge_init() will add a drm_bridge.
> >>>>
> >>>> And yes in that case, the drm_bridge will be after the panel_bridge
> >>>>
> >>>> But since panel_bridge is at the root for eDP it should be okay.
> >>>
> >>> No. It is not.
> >>> For both DP and eDP the chain should be:
> >>> dpu_encoder -> dp_bridge -> external (panel) bridge, optional for DP
> >>> -> [other bridges] -> connector
> >>>
> >>> Otherwise drm_bridge_chain_foo() functions would be called in the
> >>> incorrect order.
> >>
> >> Agreed. For drm_bridge_chain_foo() ordering to be correct, for eDP chain
> >> the order should be what you mentioned and panel_bridge should be at the
> >> end ( should be the last one ).
> >>
> >> For the above reason,
> >>
> >> Reviewed-by: Abhinav Kumar <quic_abhinavk@quicinc.com>
> >>
> >> I still didnt understand what gets affected by this for the
> >> msm_dp_display_foo() functions you mentioned earlier and wanted to get
> >> some clarity on that.
> >
> > They should be called at the correct time.
> >
> >>>
> >>> Thus the dp_bridge should be attached directly to the encoder
> >>> (drm_encoder) and panel_bridge should use dp_bridge as the 'previous'
> >>> bridge.
> >>>
> >>
> >> Agreed.
> >>
> >>> For example, for the DP port one can use a display-connector (which
> >>> actually implements drm_bridge) as an external bridge to provide hpd
> >>> or dp power GPIOs.
> >>>
> >>> Note, that the current dp_connector breaks layering. It makes calls
> >>> directly into dp_display, not allowing external bridge (and other
> >>> bridges) to override get_modes/mode_valid and other callbacks.
> >>> Thus one of the next patches in series (the one that Kuogee had issues
> >>> with) tries to replace the chain with the following one:
> >>> dpu_encoder -> dp_bridge -> external (panel) bridge -> [other bridges]
> >>> -> drm_bridge_connector.
> >>>
> >>>>
> >>
> >> So originally the plan was always that the DP connector layer intercepts
> >> the call because panel-eDP file did not support reading of the EDID ( we
> >> have not provided the aux bus ). So it was intended that we did not want
> >> to goto the eDP panel to get the modes. Not an error but something which
> >> we wanted to cleanup later when we moved to panel-eDP completely.
> >
> > panel_edp_get_modes() correctly handles this case and returns modes
> > specified in the panel description. So the code should work even with
> > panel-eDP and w/o the AUX bus.
> >
>
> If hard-coded modes are not present, it will fail in below case:
>
>      /*
>       * Add hard-coded panel modes. Don't call this if there are no timings
>       * and no modes (the generic edp-panel case) because it will clobber
>       * the display_info that was already set by drm_add_edid_modes().
>       */
>      if (p->desc->num_timings || p->desc->num_modes)
>          num += panel_edp_get_non_edid_modes(p, connector);
>      else if (!num)
>          dev_warn(p->base.dev, "No display modes\n");
>
> Thats exactly the error he was seeing.

Ah, so he had neither timings nor modes. The rest of the panels does.

>
> >>
> >> Till then we wanted the dp_connector to read the EDID and get the modes.
> >>
> >> So this was actually intended to happen till the point where we moved to
> >> panel-eDP to get the modes.
> >>
> >> Hence what you have mentioned in your cover letter is right that the
> >> chain was broken but there was no loss of functionality due to that today.
> >>
> >> Now that these changes are made, we can still goto panel-eDP file for
> >> the modes because of the below change from Sankeerth where the mode is
> >> hard-coded:
> >>
> >> https://patchwork.freedesktop.org/patch/473431/
> >>
> >> With this change cherry-picked it should work for kuogee. We will
> >> re-test that with this change.
> >
> > I suppose he had both of the changes in the tree. Otherwise the
> > panel_edp_get_modes() wouldn't be called.
>
> No he did not.
>
> That brings up another point.
>
> Even Bjorn was relying on the DP connector's get_modes() for his eDP
> panel if I am not mistaken.
>
> Unless he makes an equivalent change for his panel OR supports reading
> EDID in panel-edp, then he will hit the same error.
>
> Given that your changes were only compile tested, lets wait for both
> Kuogee and Bjorn to validate their resp setups.

Sure, anyway I think it's too late to bring in this patch during this cycle.

>
> >
> >>>> Your commit text was mentioning about DP.
> >>>>
> >>>> For DP, for each controller in the catalog, we will call modeset_init()
> >>>> which should skip this part for DP
> >>>>
> >>>>      if (dp_display->panel_bridge) {
> >>>>            ret = drm_bridge_attach(dp_display->encoder,
> >>>>                        dp_display->panel_bridge, NULL,
> >>>
> >>> as you see, NULL is incorrect. It should be a pointer to dp_bridge instead
> >>>
> >>>>                        DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>            if (ret < 0) {
> >>>>                DRM_ERROR("failed to attach panel bridge: %d\n", ret);
> >>>>                return ERR_PTR(ret);
> >>>>            }
> >>>>        }
> >>>>
> >>>> Followed by calling msm_dp_bridge_init() which will actually attach the
> >>>> bridge:
> >>>>
> >>>> drm_bridge_attach(encoder, bridge, NULL, DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>
> >>> And this bridge should be attached before the external bridge.
> >>>
> >>>>
> >>>> Now, even for 3 DP controllers, this shall be true as there will be 3
> >>>> separate encoders and 3 dp_displays and hence 3 drm_bridges.
> >>>>
> >>>> What am i missing here?
> >>>>
> >>>>>>
> >>>>>> So what are we achieving with this change?
> >>>>>>
> >>>>>>>
> >>>>>>>>
> >>>>>>>>>
> >>>>>>>>> Fixes: 8a3b4c17f863 ("drm/msm/dp: employ bridge mechanism for display
> >>>>>>>>> enable and disable")
> >>>>>>>>> Cc: Kuogee Hsieh <quic_khsieh@quicinc.com>
> >>>>>>>>> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> >>>>>>>>> ---
> >>>>>>>>
> >>>>>>>> Reviewed-by: Stephen Boyd <swboyd@chromium.org>
> >>>>>>>>
> >>>>>>>>>      drivers/gpu/drm/msm/dp/dp_drm.c | 21 +++++++++++----------
> >>>>>>>>>      1 file changed, 11 insertions(+), 10 deletions(-)
> >>>>>>>>>
> >>>>>>>>> diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>>>> b/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>>>> index d4d360d19eba..26ef41a4c1b6 100644
> >>>>>>>>> --- a/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>>>> +++ b/drivers/gpu/drm/msm/dp/dp_drm.c
> >>>>>>>>> @@ -169,16 +169,6 @@ struct drm_connector
> >>>>>>>>> *dp_drm_connector_init(struct msm_dp *dp_display)
> >>>>>>>>>
> >>>>>>>>>             drm_connector_attach_encoder(connector, dp_display->encoder);
> >>>>>>>>>
> >>>>>>>>> -       if (dp_display->panel_bridge) {
> >>>>>>>>> -               ret = drm_bridge_attach(dp_display->encoder,
> >>>>>>>>> -                                       dp_display->panel_bridge, NULL,
> >>>>>>>>> -                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>>>>>> -               if (ret < 0) {
> >>>>>>>>> -                       DRM_ERROR("failed to attach panel bridge:
> >>>>>>>>> %d\n", ret);
> >>>>>>>>> -                       return ERR_PTR(ret);
> >>>>>>>>> -               }
> >>>>>>>>> -       }
> >>>>>>>>> -
> >>>>>>>>>             return connector;
> >>>>>>>>>      }
> >>>>>>>>>
> >>>>>>>>> @@ -246,5 +236,16 @@ struct drm_bridge *msm_dp_bridge_init(struct
> >>>>>>>>> msm_dp *dp_display, struct drm_devi
> >>>>>>>>>                     return ERR_PTR(rc);
> >>>>>>>>>             }
> >>>>>>>>>
> >>>>>>>>> +       if (dp_display->panel_bridge) {
> >>>>>>>>> +               rc = drm_bridge_attach(dp_display->encoder,
> >>>>>>>>> +                                       dp_display->panel_bridge,
> >>>>>>>>> bridge,
> >>>>>>>>> +                                       DRM_BRIDGE_ATTACH_NO_CONNECTOR);
> >>>>>>>>> +               if (rc < 0) {
> >>>>>>>>> +                       DRM_ERROR("failed to attach panel bridge:
> >>>>>>>>> %d\n", rc);
> >>>>>>>>> +                       drm_bridge_remove(bridge);
> >>>>>>>>> +                       return ERR_PTR(rc);
> >>>>>>>>> +               }
> >>>>>>>>> +       }
> >>>>>>>>> +
> >>>>>>>>>             return bridge;
> >>>>>>>>
> >>>>>>>> Not a problem with this patch, but what is this pointer used for? I see
> >>>>>>>> it's assigned to priv->bridges and num_bridges is incremented but nobody
> >>>>>>>> seems to look at that.
> >>>>>>>
> >>>>>>>
> >>>>>>> That's on my todo list. to remove connectors array and to destroy
> >>>>>>> created bridges during drm device destruction.
> >>>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>
> >>>
> >>>
> >
> >
> >
diff mbox series

Patch

diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index d4d360d19eba..26ef41a4c1b6 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -169,16 +169,6 @@  struct drm_connector *dp_drm_connector_init(struct msm_dp *dp_display)
 
 	drm_connector_attach_encoder(connector, dp_display->encoder);
 
-	if (dp_display->panel_bridge) {
-		ret = drm_bridge_attach(dp_display->encoder,
-					dp_display->panel_bridge, NULL,
-					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
-		if (ret < 0) {
-			DRM_ERROR("failed to attach panel bridge: %d\n", ret);
-			return ERR_PTR(ret);
-		}
-	}
-
 	return connector;
 }
 
@@ -246,5 +236,16 @@  struct drm_bridge *msm_dp_bridge_init(struct msm_dp *dp_display, struct drm_devi
 		return ERR_PTR(rc);
 	}
 
+	if (dp_display->panel_bridge) {
+		rc = drm_bridge_attach(dp_display->encoder,
+					dp_display->panel_bridge, bridge,
+					DRM_BRIDGE_ATTACH_NO_CONNECTOR);
+		if (rc < 0) {
+			DRM_ERROR("failed to attach panel bridge: %d\n", rc);
+			drm_bridge_remove(bridge);
+			return ERR_PTR(rc);
+		}
+	}
+
 	return bridge;
 }