drm/msm: convert to drm_bridge
authorRob Clark <robdclark@gmail.com>
Fri, 30 Aug 2013 17:02:15 +0000 (13:02 -0400)
committerDave Airlie <airlied@redhat.com>
Mon, 2 Sep 2013 00:23:35 +0000 (10:23 +1000)
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: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
drivers/gpu/drm/msm/Makefile
drivers/gpu/drm/msm/hdmi/hdmi.c
drivers/gpu/drm/msm/hdmi/hdmi.h
drivers/gpu/drm/msm/hdmi/hdmi_bridge.c [new file with mode: 0644]
drivers/gpu/drm/msm/hdmi/hdmi_connector.c
drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c
drivers/gpu/drm/msm/mdp4/mdp4_kms.c
drivers/gpu/drm/msm/msm_connector.c [deleted file]
drivers/gpu/drm/msm/msm_connector.h [deleted file]
drivers/gpu/drm/msm/msm_drv.h

index 439dfb5..e179148 100644 (file)
@@ -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 \
index 12ecfb9..50d11df 100644 (file)
@@ -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;
 }
index 34703fe..2c2ec56 100644 (file)
@@ -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 (file)
index 0000000..5a8ee34
--- /dev/null
@@ -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);
+}
index 7d63f5f..823eee5 100644 (file)
 
 #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;
 
index 06d49e3..5e0dcae 100644 (file)
@@ -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)
index 960cd89..5db5bba 100644 (file)
@@ -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 (file)
index aeea887..0000000
+++ /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 (file)
index 0b41866..0000000
+++ /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__ */
index 34c36b2..80d7509 100644 (file)
@@ -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);