Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3376e3e authored by Rob Clark's avatar Rob Clark Committed by Dave Airlie
Browse files

drm/msm: convert to drm_bridge



Drop the msm_connector base class, and special calls to base class
methods from the encoder, and use instead drm_bridge.  This allows for a
cleaner division between the hdmi (and in future dsi) blocks, from the
mdp block.

Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 3b336ec4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ msm-y := \
	adreno/adreno_gpu.o \
	adreno/a3xx_gpu.o \
	hdmi/hdmi.o \
	hdmi/hdmi_bridge.o \
	hdmi/hdmi_connector.o \
	hdmi/hdmi_i2c.o \
	hdmi/hdmi_phy_8960.o \
@@ -17,7 +18,6 @@ msm-y := \
	mdp4/mdp4_irq.o \
	mdp4/mdp4_kms.o \
	mdp4/mdp4_plane.o \
	msm_connector.o \
	msm_drv.o \
	msm_fb.o \
	msm_gem.o \
+43 −6
Original line number Diff line number Diff line
@@ -56,8 +56,9 @@ static irqreturn_t hdmi_irq(int irq, void *dev_id)
	return IRQ_HANDLED;
}

void hdmi_destroy(struct hdmi *hdmi)
void hdmi_destroy(struct kref *kref)
{
	struct hdmi *hdmi = container_of(kref, struct hdmi, refcount);
	struct hdmi_phy *phy = hdmi->phy;

	if (phy)
@@ -70,9 +71,10 @@ void hdmi_destroy(struct hdmi *hdmi)
}

/* initialize connector */
int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,
		struct drm_connector *connector)
int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder)
{
	struct hdmi *hdmi = NULL;
	struct msm_drm_private *priv = dev->dev_private;
	struct platform_device *pdev = hdmi_pdev;
	struct hdmi_platform_config *config;
	int ret;
@@ -85,11 +87,19 @@ int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,

	config = pdev->dev.platform_data;

	hdmi = kzalloc(sizeof(*hdmi), GFP_KERNEL);
	if (!hdmi) {
		ret = -ENOMEM;
		goto fail;
	}

	kref_init(&hdmi->refcount);

	get_device(&pdev->dev);

	hdmi->dev = dev;
	hdmi->pdev = pdev;
	hdmi->connector = connector;
	hdmi->encoder = encoder;

	/* not sure about which phy maps to which msm.. probably I miss some */
	if (config->phy_init)
@@ -152,6 +162,22 @@ int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,
		goto fail;
	}

	hdmi->bridge = hdmi_bridge_init(hdmi);
	if (IS_ERR(hdmi->bridge)) {
		ret = PTR_ERR(hdmi->bridge);
		dev_err(dev->dev, "failed to create HDMI bridge: %d\n", ret);
		hdmi->bridge = NULL;
		goto fail;
	}

	hdmi->connector = hdmi_connector_init(hdmi);
	if (IS_ERR(hdmi->connector)) {
		ret = PTR_ERR(hdmi->connector);
		dev_err(dev->dev, "failed to create HDMI connector: %d\n", ret);
		hdmi->connector = NULL;
		goto fail;
	}

	hdmi->irq = platform_get_irq(pdev, 0);
	if (hdmi->irq < 0) {
		ret = hdmi->irq;
@@ -168,11 +194,22 @@ int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,
		goto fail;
	}

	encoder->bridge = hdmi->bridge;

	priv->bridges[priv->num_bridges++]       = hdmi->bridge;
	priv->connectors[priv->num_connectors++] = hdmi->connector;

	return 0;

fail:
	if (hdmi)
		hdmi_destroy(hdmi);
	if (hdmi) {
		/* bridge/connector are normally destroyed by drm: */
		if (hdmi->bridge)
			hdmi->bridge->funcs->destroy(hdmi->bridge);
		if (hdmi->connector)
			hdmi->connector->funcs->destroy(hdmi->connector);
		hdmi_destroy(&hdmi->refcount);
	}

	return ret;
}
+25 −6
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@
struct hdmi_phy;

struct hdmi {
	struct kref refcount;

	struct drm_device *dev;
	struct platform_device *pdev;

@@ -45,6 +47,10 @@ struct hdmi {
	struct hdmi_phy *phy;
	struct i2c_adapter *i2c;
	struct drm_connector *connector;
	struct drm_bridge *bridge;

	/* the encoder we are hooked to (outside of hdmi block) */
	struct drm_encoder *encoder;

	bool hdmi_mode;               /* are we in hdmi mode? */

@@ -58,9 +64,7 @@ struct hdmi_platform_config {
};

void hdmi_set_mode(struct hdmi *hdmi, bool power_on);
void hdmi_destroy(struct hdmi *hdmi);
int hdmi_init(struct hdmi *hdmi, struct drm_device *dev,
		struct drm_connector *connector);
void hdmi_destroy(struct kref *kref);

static inline void hdmi_write(struct hdmi *hdmi, u32 reg, u32 data)
{
@@ -72,6 +76,17 @@ static inline u32 hdmi_read(struct hdmi *hdmi, u32 reg)
	return msm_readl(hdmi->mmio + reg);
}

static inline struct hdmi * hdmi_reference(struct hdmi *hdmi)
{
	kref_get(&hdmi->refcount);
	return hdmi;
}

static inline void hdmi_unreference(struct hdmi *hdmi)
{
	kref_put(&hdmi->refcount, hdmi_destroy);
}

/*
 * The phy appears to be different, for example between 8960 and 8x60,
 * so split the phy related functions out and load the correct one at
@@ -89,17 +104,21 @@ struct hdmi_phy {
	const struct hdmi_phy_funcs *funcs;
};

/*
 * phy can be different on different generations:
 */
struct hdmi_phy *hdmi_phy_8960_init(struct hdmi *hdmi);
struct hdmi_phy *hdmi_phy_8x60_init(struct hdmi *hdmi);

/*
 * hdmi bridge:
 */

struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi);

/*
 * hdmi connector:
 */

void hdmi_connector_irq(struct drm_connector *connector);
struct drm_connector *hdmi_connector_init(struct hdmi *hdmi);

/*
 * i2c adapter for ddc:
+167 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 Red Hat
 * Author: Rob Clark <robdclark@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "hdmi.h"

struct hdmi_bridge {
	struct drm_bridge base;

	struct hdmi *hdmi;

	unsigned long int pixclock;
};
#define to_hdmi_bridge(x) container_of(x, struct hdmi_bridge, base)

static void hdmi_bridge_destroy(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	hdmi_unreference(hdmi_bridge->hdmi);
	drm_bridge_cleanup(bridge);
	kfree(hdmi_bridge);
}

static void hdmi_bridge_pre_enable(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	struct hdmi_phy *phy = hdmi->phy;

	DBG("power up");
	phy->funcs->powerup(phy, hdmi_bridge->pixclock);
	hdmi_set_mode(hdmi, true);
}

static void hdmi_bridge_enable(struct drm_bridge *bridge)
{
}

static void hdmi_bridge_disable(struct drm_bridge *bridge)
{
}

static void hdmi_bridge_post_disable(struct drm_bridge *bridge)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	struct hdmi_phy *phy = hdmi->phy;

	DBG("power down");
	hdmi_set_mode(hdmi, false);
	phy->funcs->powerdown(phy);
}

static void hdmi_bridge_mode_set(struct drm_bridge *bridge,
		 struct drm_display_mode *mode,
		 struct drm_display_mode *adjusted_mode)
{
	struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge);
	struct hdmi *hdmi = hdmi_bridge->hdmi;
	int hstart, hend, vstart, vend;
	uint32_t frame_ctrl;

	mode = adjusted_mode;

	hdmi_bridge->pixclock = mode->clock * 1000;

	hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1;

	hstart = mode->htotal - mode->hsync_start;
	hend   = mode->htotal - mode->hsync_start + mode->hdisplay;

	vstart = mode->vtotal - mode->vsync_start - 1;
	vend   = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;

	DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
			mode->htotal, mode->vtotal, hstart, hend, vstart, vend);

	hdmi_write(hdmi, REG_HDMI_TOTAL,
			HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
			HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));

	hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
			HDMI_ACTIVE_HSYNC_START(hstart) |
			HDMI_ACTIVE_HSYNC_END(hend));
	hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
			HDMI_ACTIVE_VSYNC_START(vstart) |
			HDMI_ACTIVE_VSYNC_END(vend));

	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
				HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
				HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
				HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
	} else {
		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
				HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
				HDMI_VSYNC_ACTIVE_F2_START(0) |
				HDMI_VSYNC_ACTIVE_F2_END(0));
	}

	frame_ctrl = 0;
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
		frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
		frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
	DBG("frame_ctrl=%08x", frame_ctrl);
	hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);

	// TODO until we have audio, this might be safest:
	if (hdmi->hdmi_mode)
		hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
}

static const struct drm_bridge_funcs hdmi_bridge_funcs = {
		.pre_enable = hdmi_bridge_pre_enable,
		.enable = hdmi_bridge_enable,
		.disable = hdmi_bridge_disable,
		.post_disable = hdmi_bridge_post_disable,
		.mode_set = hdmi_bridge_mode_set,
		.destroy = hdmi_bridge_destroy,
};


/* initialize bridge */
struct drm_bridge *hdmi_bridge_init(struct hdmi *hdmi)
{
	struct drm_bridge *bridge = NULL;
	struct hdmi_bridge *hdmi_bridge;
	int ret;

	hdmi_bridge = kzalloc(sizeof(*hdmi_bridge), GFP_KERNEL);
	if (!hdmi_bridge) {
		ret = -ENOMEM;
		goto fail;
	}

	hdmi_bridge->hdmi = hdmi_reference(hdmi);

	bridge = &hdmi_bridge->base;

	drm_bridge_init(hdmi->dev, bridge, &hdmi_bridge_funcs);

	return bridge;

fail:
	if (bridge)
		hdmi_bridge_destroy(bridge);

	return ERR_PTR(ret);
}
+31 −125
Original line number Diff line number Diff line
@@ -17,14 +17,11 @@

#include <linux/gpio.h>

#include "msm_connector.h"
#include "hdmi.h"

struct hdmi_connector {
	struct msm_connector base;
	struct hdmi hdmi;
	unsigned long int pixclock;
	bool enabled;
	struct drm_connector base;
	struct hdmi *hdmi;
};
#define to_hdmi_connector(x) container_of(x, struct hdmi_connector, base)

@@ -90,8 +87,8 @@ static int gpio_config(struct hdmi *hdmi, bool on)

static int hpd_enable(struct hdmi_connector *hdmi_connector)
{
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct drm_device *dev = hdmi_connector->base.base.dev;
	struct hdmi *hdmi = hdmi_connector->hdmi;
	struct drm_device *dev = hdmi_connector->base.dev;
	struct hdmi_phy *phy = hdmi->phy;
	uint32_t hpd_ctrl;
	int ret;
@@ -158,8 +155,8 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)

static int hdp_disable(struct hdmi_connector *hdmi_connector)
{
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct drm_device *dev = hdmi_connector->base.base.dev;
	struct hdmi *hdmi = hdmi_connector->hdmi;
	struct drm_device *dev = hdmi_connector->base.dev;
	int ret = 0;

	/* Disable HPD interrupt */
@@ -194,9 +191,8 @@ static int hdp_disable(struct hdmi_connector *hdmi_connector)

void hdmi_connector_irq(struct drm_connector *connector)
{
	struct msm_connector *msm_connector = to_msm_connector(connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
	struct hdmi *hdmi = hdmi_connector->hdmi;
	uint32_t hpd_int_status, hpd_int_ctrl;

	/* Process HPD: */
@@ -226,9 +222,8 @@ void hdmi_connector_irq(struct drm_connector *connector)
static enum drm_connector_status hdmi_connector_detect(
		struct drm_connector *connector, bool force)
{
	struct msm_connector *msm_connector = to_msm_connector(connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
	struct hdmi *hdmi = hdmi_connector->hdmi;
	uint32_t hpd_int_status;
	int retry = 20;

@@ -249,24 +244,22 @@ static enum drm_connector_status hdmi_connector_detect(

static void hdmi_connector_destroy(struct drm_connector *connector)
{
	struct msm_connector *msm_connector = to_msm_connector(connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);

	hdp_disable(hdmi_connector);

	drm_sysfs_connector_remove(connector);
	drm_connector_cleanup(connector);

	hdmi_destroy(&hdmi_connector->hdmi);
	hdmi_unreference(hdmi_connector->hdmi);

	kfree(hdmi_connector);
}

static int hdmi_connector_get_modes(struct drm_connector *connector)
{
	struct msm_connector *msm_connector = to_msm_connector(connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
	struct hdmi *hdmi = hdmi_connector->hdmi;
	struct edid *edid;
	uint32_t hdmi_ctrl;
	int ret = 0;
@@ -291,14 +284,14 @@ static int hdmi_connector_get_modes(struct drm_connector *connector)
static int hdmi_connector_mode_valid(struct drm_connector *connector,
				 struct drm_display_mode *mode)
{
	struct msm_connector *msm_connector = to_msm_connector(connector);
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
	struct msm_drm_private *priv = connector->dev->dev_private;
	struct msm_kms *kms = priv->kms;
	long actual, requested;

	requested = 1000 * mode->clock;
	actual = kms->funcs->round_pixclk(kms,
			requested, msm_connector->encoder);
			requested, hdmi_connector->hdmi->encoder);

	DBG("requested=%ld, actual=%ld", requested, actual);

@@ -308,6 +301,13 @@ static int hdmi_connector_mode_valid(struct drm_connector *connector,
	return 0;
}

static struct drm_encoder *
hdmi_connector_best_encoder(struct drm_connector *connector)
{
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(connector);
	return hdmi_connector->hdmi->encoder;
}

static const struct drm_connector_funcs hdmi_connector_funcs = {
	.dpms = drm_helper_connector_dpms,
	.detect = hdmi_connector_detect,
@@ -318,101 +318,11 @@ static const struct drm_connector_funcs hdmi_connector_funcs = {
static const struct drm_connector_helper_funcs hdmi_connector_helper_funcs = {
	.get_modes = hdmi_connector_get_modes,
	.mode_valid = hdmi_connector_mode_valid,
	.best_encoder = msm_connector_attached_encoder,
};

static void hdmi_connector_dpms(struct msm_connector *msm_connector, int mode)
{
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	struct hdmi_phy *phy = hdmi->phy;
	bool enabled = (mode == DRM_MODE_DPMS_ON);

	DBG("mode=%d", mode);

	if (enabled == hdmi_connector->enabled)
		return;

	if (enabled) {
		phy->funcs->powerup(phy, hdmi_connector->pixclock);
		hdmi_set_mode(hdmi, true);
	} else {
		hdmi_set_mode(hdmi, false);
		phy->funcs->powerdown(phy);
	}

	hdmi_connector->enabled = enabled;
}

static void hdmi_connector_mode_set(struct msm_connector *msm_connector,
		struct drm_display_mode *mode)
{
	struct hdmi_connector *hdmi_connector = to_hdmi_connector(msm_connector);
	struct hdmi *hdmi = &hdmi_connector->hdmi;
	int hstart, hend, vstart, vend;
	uint32_t frame_ctrl;

	hdmi_connector->pixclock = mode->clock * 1000;

	hdmi->hdmi_mode = drm_match_cea_mode(mode) > 1;

	hstart = mode->htotal - mode->hsync_start;
	hend   = mode->htotal - mode->hsync_start + mode->hdisplay;

	vstart = mode->vtotal - mode->vsync_start - 1;
	vend   = mode->vtotal - mode->vsync_start + mode->vdisplay - 1;

	DBG("htotal=%d, vtotal=%d, hstart=%d, hend=%d, vstart=%d, vend=%d",
			mode->htotal, mode->vtotal, hstart, hend, vstart, vend);

	hdmi_write(hdmi, REG_HDMI_TOTAL,
			HDMI_TOTAL_H_TOTAL(mode->htotal - 1) |
			HDMI_TOTAL_V_TOTAL(mode->vtotal - 1));

	hdmi_write(hdmi, REG_HDMI_ACTIVE_HSYNC,
			HDMI_ACTIVE_HSYNC_START(hstart) |
			HDMI_ACTIVE_HSYNC_END(hend));
	hdmi_write(hdmi, REG_HDMI_ACTIVE_VSYNC,
			HDMI_ACTIVE_VSYNC_START(vstart) |
			HDMI_ACTIVE_VSYNC_END(vend));

	if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
				HDMI_VSYNC_TOTAL_F2_V_TOTAL(mode->vtotal));
		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
				HDMI_VSYNC_ACTIVE_F2_START(vstart + 1) |
				HDMI_VSYNC_ACTIVE_F2_END(vend + 1));
	} else {
		hdmi_write(hdmi, REG_HDMI_VSYNC_TOTAL_F2,
				HDMI_VSYNC_TOTAL_F2_V_TOTAL(0));
		hdmi_write(hdmi, REG_HDMI_VSYNC_ACTIVE_F2,
				HDMI_VSYNC_ACTIVE_F2_START(0) |
				HDMI_VSYNC_ACTIVE_F2_END(0));
	}

	frame_ctrl = 0;
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
		frame_ctrl |= HDMI_FRAME_CTRL_HSYNC_LOW;
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
		frame_ctrl |= HDMI_FRAME_CTRL_VSYNC_LOW;
	if (mode->flags & DRM_MODE_FLAG_INTERLACE)
		frame_ctrl |= HDMI_FRAME_CTRL_INTERLACED_EN;
	DBG("frame_ctrl=%08x", frame_ctrl);
	hdmi_write(hdmi, REG_HDMI_FRAME_CTRL, frame_ctrl);

	// TODO until we have audio, this might be safest:
	if (hdmi->hdmi_mode)
		hdmi_write(hdmi, REG_HDMI_GC, HDMI_GC_MUTE);
}

static const struct msm_connector_funcs msm_connector_funcs = {
		.dpms = hdmi_connector_dpms,
		.mode_set = hdmi_connector_mode_set,
	.best_encoder = hdmi_connector_best_encoder,
};

/* initialize connector */
struct drm_connector *hdmi_connector_init(struct drm_device *dev,
		struct drm_encoder *encoder)
struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
{
	struct drm_connector *connector = NULL;
	struct hdmi_connector *hdmi_connector;
@@ -424,11 +334,11 @@ struct drm_connector *hdmi_connector_init(struct drm_device *dev,
		goto fail;
	}

	connector = &hdmi_connector->base.base;
	hdmi_connector->hdmi = hdmi_reference(hdmi);

	connector = &hdmi_connector->base;

	msm_connector_init(&hdmi_connector->base,
			&msm_connector_funcs, encoder);
	drm_connector_init(dev, connector, &hdmi_connector_funcs,
	drm_connector_init(hdmi->dev, connector, &hdmi_connector_funcs,
			DRM_MODE_CONNECTOR_HDMIA);
	drm_connector_helper_add(connector, &hdmi_connector_helper_funcs);

@@ -439,17 +349,13 @@ struct drm_connector *hdmi_connector_init(struct drm_device *dev,

	drm_sysfs_connector_add(connector);

	ret = hdmi_init(&hdmi_connector->hdmi, dev, connector);
	if (ret)
		goto fail;

	ret = hpd_enable(hdmi_connector);
	if (ret) {
		dev_err(dev->dev, "failed to enable HPD: %d\n", ret);
		dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret);
		goto fail;
	}

	drm_mode_connector_attach_encoder(connector, encoder);
	drm_mode_connector_attach_encoder(connector, hdmi->encoder);

	return connector;

Loading