Skip to content

Commit

Permalink
drm/bridge: parade-ps8640: Populate devices on aux-bus
Browse files Browse the repository at this point in the history
Conventionally, panel is listed under the root of the device tree.
When userland asks for display mode, ps8640 bridge is responsible
for returning EDID when ps8640_bridge_get_edid() is called.

Now enable a new option of listing panel under "aux-bus" of ps8640
bridge node in the device tree. In this case, panel driver can retrieve
EDID by triggering AUX transactions, without ps8640_bridge_get_edid()
calls at all.

To prevent the "old" and "new" options from interfering with each
other's logic flow, disable DRM_BRIDGE_OP_EDID when the new option
is taken.

Signed-off-by: Philip Chen <philipchen@chromium.org>
Reviewed-by: Stephen Boyd <swboyd@chromium.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20211028105754.v5.2.I09899dea340f11feab97d719cb4b62bef3179e4b@changeid
  • Loading branch information
Philip Chen authored and Douglas Anderson committed Nov 11, 2021
1 parent 826cff3 commit e9d9f95
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 12 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/bridge/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ config DRM_PARADE_PS8622
config DRM_PARADE_PS8640
tristate "Parade PS8640 MIPI DSI to eDP Converter"
depends on OF
select DRM_DP_AUX_BUS
select DRM_KMS_HELPER
select DRM_MIPI_DSI
select DRM_PANEL
Expand Down
51 changes: 39 additions & 12 deletions drivers/gpu/drm/bridge/parade-ps8640.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/regulator/consumer.h>

#include <drm/drm_bridge.h>
#include <drm/drm_dp_aux_bus.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_mipi_dsi.h>
#include <drm/drm_of.h>
Expand Down Expand Up @@ -149,6 +150,23 @@ static inline struct ps8640 *aux_to_ps8640(struct drm_dp_aux *aux)
return container_of(aux, struct ps8640, aux);
}

static bool ps8640_of_panel_on_aux_bus(struct device *dev)
{
struct device_node *bus, *panel;

bus = of_get_child_by_name(dev->of_node, "aux-bus");
if (!bus)
return false;

panel = of_get_child_by_name(bus, "panel");
of_node_put(bus);
if (!panel)
return false;
of_node_put(panel);

return true;
}

static int ps8640_ensure_hpd(struct ps8640 *ps_bridge)
{
struct regmap *map = ps_bridge->regmap[PAGE2_TOP_CNTL];
Expand Down Expand Up @@ -555,17 +573,6 @@ static int ps8640_probe(struct i2c_client *client)
if (!ps_bridge)
return -ENOMEM;

/* port@1 is ps8640 output port */
ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
if (ret < 0)
return ret;
if (!panel)
return -ENODEV;

ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
if (IS_ERR(ps_bridge->panel_bridge))
return PTR_ERR(ps_bridge->panel_bridge);

ps_bridge->supplies[0].supply = "vdd33";
ps_bridge->supplies[1].supply = "vdd12";
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies),
Expand All @@ -588,9 +595,16 @@ static int ps8640_probe(struct i2c_client *client)

ps_bridge->bridge.funcs = &ps8640_bridge_funcs;
ps_bridge->bridge.of_node = dev->of_node;
ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID;
ps_bridge->bridge.type = DRM_MODE_CONNECTOR_eDP;

/*
* In the device tree, if panel is listed under aux-bus of the bridge
* node, panel driver should be able to retrieve EDID by itself using
* aux-bus. So let's not set DRM_BRIDGE_OP_EDID here.
*/
if (!ps8640_of_panel_on_aux_bus(&client->dev))
ps_bridge->bridge.ops = DRM_BRIDGE_OP_EDID;

ps_bridge->page[PAGE0_DP_CNTL] = client;

ps_bridge->regmap[PAGE0_DP_CNTL] = devm_regmap_init_i2c(client, ps8640_regmap_config);
Expand Down Expand Up @@ -633,6 +647,19 @@ static int ps8640_probe(struct i2c_client *client)
if (ret)
return ret;

devm_of_dp_aux_populate_ep_devices(&ps_bridge->aux);

/* port@1 is ps8640 output port */
ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL);
if (ret < 0)
return ret;
if (!panel)
return -ENODEV;

ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel);
if (IS_ERR(ps_bridge->panel_bridge))
return PTR_ERR(ps_bridge->panel_bridge);

drm_bridge_add(&ps_bridge->bridge);

ret = ps8640_bridge_host_attach(dev, ps_bridge);
Expand Down

0 comments on commit e9d9f95

Please sign in to comment.