[RFC V2 3/3] drm/bridge: ptn3460: support bridge chaining

Sean Paul seanpaul at chromium.org
Tue May 6 13:05:25 PDT 2014


On Tue, May 6, 2014 at 1:03 PM, Ajay kumar <ajaynumb at gmail.com> wrote:
> Sean,
>
>
> On Tue, May 6, 2014 at 9:24 PM, Sean Paul <seanpaul at chromium.org> wrote:
>> On Mon, May 5, 2014 at 12:52 PM, Ajay Kumar <ajaykumar.rs at samsung.com> wrote:
>>> modify the driver to call the bridge->funcs of the next bridge
>>> in the chain.
>>> We assume that the bridge sitting next to ptn3460 is a bridge-panel.
>>>
>>> Signed-off-by: Ajay Kumar <ajaykumar.rs at samsung.com>
>>> ---
>>>  drivers/gpu/drm/bridge/ptn3460.c | 21 +++++++++++++++++----
>>>  1 file changed, 17 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/drivers/gpu/drm/bridge/ptn3460.c b/drivers/gpu/drm/bridge/ptn3460.c
>>> index b171901..969869a 100644
>>> --- a/drivers/gpu/drm/bridge/ptn3460.c
>>> +++ b/drivers/gpu/drm/bridge/ptn3460.c
>>> @@ -126,6 +126,8 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge)
>>>                 gpio_set_value(ptn_bridge->gpio_rst_n, 1);
>>>         }
>>>
>>> +       if (bridge->next_bridge)
>>> +               bridge->next_bridge->funcs->pre_enable(bridge->next_bridge);
>>>         /*
>>>          * There's a bug in the PTN chip where it falsely asserts hotplug before
>>>          * it is fully functional. We're forced to wait for the maximum start up
>>> @@ -142,6 +144,8 @@ static void ptn3460_pre_enable(struct drm_bridge *bridge)
>>>
>>>  static void ptn3460_enable(struct drm_bridge *bridge)
>>>  {
>>> +       if (bridge->next_bridge)
>>> +               bridge->next_bridge->funcs->enable(bridge->next_bridge);
>>>  }
>>>
>>>  static void ptn3460_disable(struct drm_bridge *bridge)
>>> @@ -153,6 +157,11 @@ static void ptn3460_disable(struct drm_bridge *bridge)
>>>
>>>         ptn_bridge->enabled = false;
>>>
>>> +       if (bridge->next_bridge) {
>>> +               bridge->next_bridge->funcs->disable(bridge->next_bridge);
>>> +               bridge->next_bridge->funcs->post_disable(bridge->next_bridge);
>>
>> Shouldn't post_disable be called from ptn_3460_post_disable, instead of here?
> Umm, right. But no point in delaying ->post_disable of the panel(which
> switches off power to LCD) since
> backlight would be already down in ->disable call itself. So, I
> thought of calling post_disable here itself.
>
>>> +       }
>>> +
>>>         if (gpio_is_valid(ptn_bridge->gpio_rst_n))
>>>                 gpio_set_value(ptn_bridge->gpio_rst_n, 1);
>>>
>>> @@ -197,7 +206,10 @@ int ptn3460_get_modes(struct drm_connector *connector)
>>>                 return drm_add_edid_modes(connector, ptn_bridge->edid);
>>>
>>>         power_off = !ptn_bridge->enabled;
>>> -       ptn3460_pre_enable(ptn_bridge->bridge);
>>> +       if (power_off) {
>>> +               ptn3460_pre_enable(ptn_bridge->bridge);
>>> +               ptn3460_enable(ptn_bridge->bridge);
>>
>> In this case, I don't think we need to power on the entire bridge
>> chain since we're just reading the edid from the bridge chip itself.
>> So I think I'd prefer to break out the power_on/power_off code from
>> the bridge chain such that we can just power up the bridge chip, check
>> the edid and then turn it off.
> Those extra calls were added to make sure that regulator_enable/disable would
> be in sync for the panel. Check the other patch [2/3].

Sure, but we don't need the panel to read the edid. This bridge in
particular provides the edid itself, so in this case, we should leave
the panel off.

Sean


> Another way of doing this is to just check if the bridge is off  and
> switch it on by
> explicitly setting up the gpios here, instead of just calling
> ptn3460_pre_enable.
>
> Ajay
>> In other bridges, where we're actually reading the edid from a
>> downstream source, this decision might be different.
>>
>>
>>
>>> +       }
>>>
>>>         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
>>>         if (!edid) {
>>> @@ -219,8 +231,10 @@ int ptn3460_get_modes(struct drm_connector *connector)
>>>         num_modes = drm_add_edid_modes(connector, ptn_bridge->edid);
>>>
>>>  out:
>>> -       if (power_off)
>>> +       if (power_off) {
>>>                 ptn3460_disable(ptn_bridge->bridge);
>>> +               ptn3460_post_disable(ptn_bridge->bridge);
>>> +       }
>>>
>>>         return num_modes;
>>>  }
>>> @@ -318,14 +332,13 @@ int ptn3460_init(struct drm_device *dev, struct drm_encoder *encoder,
>>>                 goto err;
>>>         }
>>>
>>> -       ret = drm_bridge_init(dev, bridge, &ptn3460_bridge_funcs);
>>> +       ret = drm_bridge_init(dev, bridge, encoder, &ptn3460_bridge_funcs);
>>>         if (ret) {
>>>                 DRM_ERROR("Failed to initialize bridge with drm\n");
>>>                 goto err;
>>>         }
>>>
>>>         bridge->driver_private = ptn_bridge;
>>> -       encoder->bridge = bridge;
>>>
>>>         ret = drm_connector_init(dev, &ptn_bridge->connector,
>>>                         &ptn3460_connector_funcs, DRM_MODE_CONNECTOR_LVDS);
>>> --
>>> 1.8.1.2
>>>


More information about the dri-devel mailing list