]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/gpu/drm/nouveau/nouveau_connector.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / gpu / drm / nouveau / nouveau_connector.c
index 52c356e9a3d177b92ed5013e8f55247a56468f5d..390d82c3c4b04a8450c661090e0e680f5154a6ab 100644 (file)
@@ -37,6 +37,8 @@
 #include "nouveau_connector.h"
 #include "nouveau_hw.h"
 
+static void nouveau_connector_hotplug(void *, int);
+
 static struct nouveau_encoder *
 find_encoder_by_type(struct drm_connector *connector, int type)
 {
@@ -94,22 +96,30 @@ nouveau_connector_bpp(struct drm_connector *connector)
 }
 
 static void
-nouveau_connector_destroy(struct drm_connector *drm_connector)
+nouveau_connector_destroy(struct drm_connector *connector)
 {
-       struct nouveau_connector *nv_connector =
-               nouveau_connector(drm_connector);
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct drm_nouveau_private *dev_priv;
+       struct nouveau_gpio_engine *pgpio;
        struct drm_device *dev;
 
        if (!nv_connector)
                return;
 
        dev = nv_connector->base.dev;
+       dev_priv = dev->dev_private;
        NV_DEBUG_KMS(dev, "\n");
 
+       pgpio = &dev_priv->engine.gpio;
+       if (pgpio->irq_unregister) {
+               pgpio->irq_unregister(dev, nv_connector->dcb->gpio_tag,
+                                     nouveau_connector_hotplug, connector);
+       }
+
        kfree(nv_connector->edid);
-       drm_sysfs_connector_remove(drm_connector);
-       drm_connector_cleanup(drm_connector);
-       kfree(drm_connector);
+       drm_sysfs_connector_remove(connector);
+       drm_connector_cleanup(connector);
+       kfree(connector);
 }
 
 static struct nouveau_i2c_chan *
@@ -497,6 +507,7 @@ nouveau_connector_native_mode(struct drm_connector *connector)
        int high_w = 0, high_h = 0, high_v = 0;
 
        list_for_each_entry(mode, &nv_connector->base.probed_modes, head) {
+               mode->vrefresh = drm_mode_vrefresh(mode);
                if (helper->mode_valid(connector, mode) != MODE_OK ||
                    (mode->flags & DRM_MODE_FLAG_INTERLACE))
                        continue;
@@ -760,6 +771,7 @@ nouveau_connector_create(struct drm_device *dev, int index)
 {
        const struct drm_connector_funcs *funcs = &nouveau_connector_funcs;
        struct drm_nouveau_private *dev_priv = dev->dev_private;
+       struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
        struct nouveau_connector *nv_connector = NULL;
        struct dcb_connector_table_entry *dcb = NULL;
        struct drm_connector *connector;
@@ -876,6 +888,11 @@ nouveau_connector_create(struct drm_device *dev, int index)
                break;
        }
 
+       if (pgpio->irq_register) {
+               pgpio->irq_register(dev, nv_connector->dcb->gpio_tag,
+                                   nouveau_connector_hotplug, connector);
+       }
+
        drm_sysfs_connector_add(connector);
        dcb->drm = connector;
        return dcb->drm;
@@ -886,3 +903,29 @@ fail:
        return ERR_PTR(ret);
 
 }
+
+static void
+nouveau_connector_hotplug(void *data, int plugged)
+{
+       struct drm_connector *connector = data;
+       struct drm_device *dev = connector->dev;
+
+       NV_INFO(dev, "%splugged %s\n", plugged ? "" : "un",
+               drm_get_connector_name(connector));
+
+       if (connector->encoder && connector->encoder->crtc &&
+           connector->encoder->crtc->enabled) {
+               struct nouveau_encoder *nv_encoder = nouveau_encoder(connector->encoder);
+               struct drm_encoder_helper_funcs *helper =
+                       connector->encoder->helper_private;
+
+               if (nv_encoder->dcb->type == OUTPUT_DP) {
+                       if (plugged)
+                               helper->dpms(connector->encoder, DRM_MODE_DPMS_ON);
+                       else
+                               helper->dpms(connector->encoder, DRM_MODE_DPMS_OFF);
+               }
+       }
+
+       drm_helper_hpd_irq_event(dev);
+}