diff options
author | Rob Clark <robdclark@gmail.com> | 2013-08-30 13:02:15 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2013-09-02 10:23:35 +1000 |
commit | a3376e3ec81c5dd0622cbc187db76d2824d31c1c (patch) | |
tree | 22e4e13c73905a624692cbfd7c7a560d79597b67 /drivers/gpu | |
parent | 3b336ec4c5460833ad7573d0b6e22793f6a389ab (diff) |
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: Rob Clark <robdclark@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/msm/Makefile | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi.h | 31 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 167 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/hdmi/hdmi_connector.c | 156 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_dtv_encoder.c | 12 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/mdp4/mdp4_kms.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_connector.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_connector.h | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/msm/msm_drv.h | 6 |
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); |