Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions drivers/gpu/drm/bridge/display-connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/workqueue.h>

#include <drm/drm_atomic_helper.h>
#include <drm/drm_bridge.h>
Expand All @@ -25,6 +26,8 @@ struct display_connector {

struct regulator *supply;
struct gpio_desc *ddc_en;

struct work_struct hpd_work;
};

static inline struct display_connector *
Expand Down Expand Up @@ -87,6 +90,34 @@ display_connector_bridge_detect(struct drm_bridge *bridge, struct drm_connector
return display_connector_detect(bridge);
}

static void display_connector_hpd_enable(struct drm_bridge *bridge)
{
struct display_connector *conn = to_display_connector(bridge);

enable_irq(conn->hpd_irq);

if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort)
schedule_work(&conn->hpd_work);
}

static void display_connector_hpd_disable(struct drm_bridge *bridge)
{
struct display_connector *conn = to_display_connector(bridge);

if (conn->bridge.type == DRM_MODE_CONNECTOR_DisplayPort)
cancel_work_sync(&conn->hpd_work);

disable_irq(conn->hpd_irq);
}

static void display_connector_hpd_work(struct work_struct *work)
{
struct display_connector *conn = container_of(work, struct display_connector, hpd_work);
struct drm_bridge *bridge = &conn->bridge;

drm_bridge_hpd_notify(bridge, display_connector_detect(bridge));
}

static const struct drm_edid *display_connector_edid_read(struct drm_bridge *bridge,
struct drm_connector *connector)
{
Expand Down Expand Up @@ -178,6 +209,8 @@ static u32 *display_connector_get_input_bus_fmts(struct drm_bridge *bridge,
static const struct drm_bridge_funcs display_connector_bridge_funcs = {
.attach = display_connector_attach,
.detect = display_connector_bridge_detect,
.hpd_enable = display_connector_hpd_enable,
.hpd_disable = display_connector_hpd_disable,
.edid_read = display_connector_edid_read,
.atomic_get_output_bus_fmts = display_connector_get_output_bus_fmts,
.atomic_get_input_bus_fmts = display_connector_get_input_bus_fmts,
Expand Down Expand Up @@ -307,6 +340,7 @@ static int display_connector_probe(struct platform_device *pdev)
NULL, display_connector_hpd_irq,
IRQF_TRIGGER_RISING |
IRQF_TRIGGER_FALLING |
IRQF_NO_AUTOEN |
IRQF_ONESHOT,
"HPD", conn);
if (ret) {
Expand Down Expand Up @@ -378,6 +412,8 @@ static int display_connector_probe(struct platform_device *pdev)
conn->bridge.ops |= DRM_BRIDGE_OP_DETECT;
if (conn->hpd_irq >= 0)
conn->bridge.ops |= DRM_BRIDGE_OP_HPD;
if (conn->hpd_irq >= 0 && type == DRM_MODE_CONNECTOR_DisplayPort)
INIT_WORK(&conn->hpd_work, display_connector_hpd_work);

dev_dbg(&pdev->dev,
"Found %s display connector '%s' %s DDC bus and %s HPD GPIO (ops 0x%x)\n",
Expand Down