summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/msm/Makefile2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c49
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.h31
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_bridge.c167
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c156
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c12
-rw-r--r--drivers/gpu/drm/msm/mdp4/mdp4_kms.c9
-rw-r--r--drivers/gpu/drm/msm/msm_connector.c34
-rw-r--r--drivers/gpu/drm/msm/msm_connector.h68
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h6
10 files changed, 274 insertions, 260 deletions
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index 439dfb5b417b..e17914889e54 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -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 \
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 12ecfb928f75..50d11df35b21 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -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;
}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h
index 34703fea22ca..2c2ec566394c 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.h
@@ -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:
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
new file mode 100644
index 000000000000..5a8ee3473cf5
--- /dev/null
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c
@@ -0,0 +1,167 @@
+/*
+ * 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);
+}
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index 7d63f5ffa7ba..823eee521a31 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -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 @@ error1:
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 @@ fail:
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 @@ fail:
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;
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
index 06d49e309d34..5e0dcae70ab5 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
@@ -18,7 +18,6 @@
#include <mach/clk.h>
#include "mdp4_kms.h"
-#include "msm_connector.h"
#include "drm_crtc.h"
#include "drm_crtc_helper.h"
@@ -101,7 +100,6 @@ static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
- struct msm_connector *msm_connector = get_connector(encoder);
struct mdp4_kms *mdp4_kms = get_kms(encoder);
bool enabled = (mode == DRM_MODE_DPMS_ON);
@@ -116,9 +114,6 @@ static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
bs_set(mdp4_dtv_encoder, 1);
- if (msm_connector)
- msm_connector->funcs->dpms(msm_connector, mode);
-
DBG("setting src_clk=%lu", pc);
ret = clk_set_rate(mdp4_dtv_encoder->src_clk, pc);
@@ -150,9 +145,6 @@ static void mdp4_dtv_encoder_dpms(struct drm_encoder *encoder, int mode)
clk_disable_unprepare(mdp4_dtv_encoder->hdmi_clk);
clk_disable_unprepare(mdp4_dtv_encoder->mdp_clk);
- if (msm_connector)
- msm_connector->funcs->dpms(msm_connector, mode);
-
bs_set(mdp4_dtv_encoder, 0);
}
@@ -171,7 +163,6 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *adjusted_mode)
{
struct mdp4_dtv_encoder *mdp4_dtv_encoder = to_mdp4_dtv_encoder(encoder);
- struct msm_connector *msm_connector = get_connector(encoder);
struct mdp4_kms *mdp4_kms = get_kms(encoder);
uint32_t dtv_hsync_skew, vsync_period, vsync_len, ctrl_pol;
uint32_t display_v_start, display_v_end;
@@ -230,9 +221,6 @@ static void mdp4_dtv_encoder_mode_set(struct drm_encoder *encoder,
MDP4_DTV_ACTIVE_HCTL_END(0));
mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VSTART, 0);
mdp4_write(mdp4_kms, REG_MDP4_DTV_ACTIVE_VEND, 0);
-
- if (msm_connector)
- msm_connector->funcs->mode_set(msm_connector, mode);
}
static void mdp4_dtv_encoder_prepare(struct drm_encoder *encoder)
diff --git a/drivers/gpu/drm/msm/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp4/mdp4_kms.c
index 960cd894da78..5db5bbaedae2 100644
--- a/drivers/gpu/drm/msm/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp4/mdp4_kms.c
@@ -191,7 +191,6 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_encoder *encoder;
- struct drm_connector *connector;
int ret;
/*
@@ -224,13 +223,11 @@ static int modeset_init(struct mdp4_kms *mdp4_kms)
encoder->possible_crtcs = 0x1; /* DTV can be hooked to DMA_E */
priv->encoders[priv->num_encoders++] = encoder;
- connector = hdmi_connector_init(dev, encoder);
- if (IS_ERR(connector)) {
- dev_err(dev->dev, "failed to construct HDMI connector\n");
- ret = PTR_ERR(connector);
+ ret = hdmi_init(dev, encoder);
+ if (ret) {
+ dev_err(dev->dev, "failed to initialize HDMI\n");
goto fail;
}
- priv->connectors[priv->num_connectors++] = connector;
return 0;
diff --git a/drivers/gpu/drm/msm/msm_connector.c b/drivers/gpu/drm/msm/msm_connector.c
deleted file mode 100644
index aeea8879e36f..000000000000
--- a/drivers/gpu/drm/msm/msm_connector.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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 "msm_drv.h"
-#include "msm_connector.h"
-
-void msm_connector_init(struct msm_connector *connector,
- const struct msm_connector_funcs *funcs,
- struct drm_encoder *encoder)
-{
- connector->funcs = funcs;
- connector->encoder = encoder;
-}
-
-struct drm_encoder *msm_connector_attached_encoder(
- struct drm_connector *connector)
-{
- struct msm_connector *msm_connector = to_msm_connector(connector);
- return msm_connector->encoder;
-}
diff --git a/drivers/gpu/drm/msm/msm_connector.h b/drivers/gpu/drm/msm/msm_connector.h
deleted file mode 100644
index 0b41866adc08..000000000000
--- a/drivers/gpu/drm/msm/msm_connector.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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/>.
- */
-
-#ifndef __MSM_CONNECTOR_H__
-#define __MSM_CONNECTOR_H__
-
-#include "msm_drv.h"
-
-/*
- * Base class for MSM connectors. Typically a connector is a bit more
- * passive. But with the split between (for example) DTV within MDP4,
- * and HDMI encoder, we really need two parts to an encoder. Instead
- * what we do is have the part external to the display controller block
- * in the connector, which is called from the encoder to delegate the
- * appropriate parts of modeset.
- */
-
-struct msm_connector;
-
-struct msm_connector_funcs {
- void (*dpms)(struct msm_connector *connector, int mode);
- void (*mode_set)(struct msm_connector *connector,
- struct drm_display_mode *mode);
-};
-
-struct msm_connector {
- struct drm_connector base;
- struct drm_encoder *encoder;
- const struct msm_connector_funcs *funcs;
-};
-#define to_msm_connector(x) container_of(x, struct msm_connector, base)
-
-void msm_connector_init(struct msm_connector *connector,
- const struct msm_connector_funcs *funcs,
- struct drm_encoder *encoder);
-
-struct drm_encoder *msm_connector_attached_encoder(
- struct drm_connector *connector);
-
-static inline struct msm_connector *get_connector(struct drm_encoder *encoder)
-{
- struct msm_drm_private *priv = encoder->dev->dev_private;
- int i;
-
- for (i = 0; i < priv->num_connectors; i++) {
- struct drm_connector *connector = priv->connectors[i];
- if (msm_connector_attached_encoder(connector) == encoder)
- return to_msm_connector(connector);
- }
-
- return NULL;
-}
-
-#endif /* __MSM_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 34c36b2911d9..80d75094bf0a 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -83,6 +83,9 @@ struct msm_drm_private {
unsigned int num_encoders;
struct drm_encoder *encoders[8];
+ unsigned int num_bridges;
+ struct drm_bridge *bridges[8];
+
unsigned int num_connectors;
struct drm_connector *connectors[8];
};
@@ -170,8 +173,7 @@ struct drm_framebuffer *msm_framebuffer_create(struct drm_device *dev,
struct drm_fb_helper *msm_fbdev_init(struct drm_device *dev);
-struct drm_connector *hdmi_connector_init(struct drm_device *dev,
- struct drm_encoder *encoder);
+int hdmi_init(struct drm_device *dev, struct drm_encoder *encoder);
void __init hdmi_register(void);
void __exit hdmi_unregister(void);