drivers/gpu/drm/via/via_hdmi.c |   88 ++++++++++++++++++++++++++---------------
 1 file changed, 57 insertions(+), 31 deletions(-)

New commits:
commit 818b684eee9b17de1f9d0fa494c8cafa35b81fc3
Author: James Simmons <jsimm...@infradead.org>
Date:   Tue Mar 26 20:35:41 2013 -0400

    Add support for a DVI monitor attached to HDMI port

diff --git a/drivers/gpu/drm/via/via_hdmi.c b/drivers/gpu/drm/via/via_hdmi.c
index dffc503..9226068 100644
--- a/drivers/gpu/drm/via/via_hdmi.c
+++ b/drivers/gpu/drm/via/via_hdmi.c
@@ -412,7 +412,6 @@ unsigned int
 via_ddc_read_bytes_by_hdmi(struct drm_via_private *dev_priv, unsigned char 
*block)
 {
        unsigned int status = true, temp = 0, i;
-       unsigned char ckm = 0;
 
        /* Enable DDC */
        VIA_WRITE_MASK(0xC000, 0x00000001, 0x00000001);
@@ -463,13 +462,7 @@ via_ddc_read_bytes_by_hdmi(struct drm_via_private 
*dev_priv, unsigned char *bloc
                VIA_WRITE(0xC0B8, 0x0009);
                via_check_hdmi_i2c_status(dev_priv, 0x0008, true);
                via_check_hdmi_i2c_status(dev_priv, 0x0080, false);
-               if (i == 127) {
-                       *block++ = (0x100 - ckm);
-                       ckm = 0;
-               } else {
-                       *block++ = (unsigned char) ((VIA_READ(0xC0B4) & 
0x0000FF00) >> 8);
-                       ckm += (unsigned char) ((VIA_READ(0xC0B4) & 0x0000FF00) 
>> 8);
-               }
+               *block++ = (unsigned char) ((VIA_READ(0xC0B4) & 0x0000FF00) >> 
8);
                VIA_WRITE(0xC0B8, (VIA_READ(0xC0B8) & ~0x80));
        }
 
@@ -491,8 +484,8 @@ via_hdmi_get_edid(struct drm_connector *connector)
 {
        bool print_bad_edid = !connector->bad_edid_counter || (drm_debug & 
DRM_UT_KMS);
        struct drm_via_private *dev_priv = connector->dev->dev_private;
-       int i, j = 0, valid_extensions = 0;
        struct edid *edid = NULL;
+       int i, j = 0;
        u8 *block;
 
        /* Clear out old EDID block */
@@ -521,6 +514,7 @@ via_hdmi_get_edid(struct drm_connector *connector)
        /* parse the extensions if present */
        if (block[0x7e]) {
                u8 *new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, 
GFP_KERNEL);
+               int valid_extensions = 1;
 
                if (!new)
                        goto out;
@@ -528,7 +522,7 @@ via_hdmi_get_edid(struct drm_connector *connector)
 
                for (j = 1; j <= block[0x7e]; j++) {
                        for (i = 0; i < 4; i++) {
-                               new = block + (valid_extensions + 1) * 
EDID_LENGTH;
+                               new = block + valid_extensions * EDID_LENGTH;
 
                                if (!via_ddc_read_bytes_by_hdmi(dev_priv, new))
                                        goto out;
@@ -547,8 +541,17 @@ via_hdmi_get_edid(struct drm_connector *connector)
                                connector->bad_edid_counter++;
                        }
                }
-       }
 
+               if (valid_extensions != block[0x7e]) {
+                       block[EDID_LENGTH - 1] += block[0x7e] - 
valid_extensions;
+                       block[0x7e] = valid_extensions;
+
+                       new = krealloc(block, valid_extensions * EDID_LENGTH, 
GFP_KERNEL);
+                       if (!new)
+                               goto out;
+                       block = new;
+               }
+       }
        edid = (struct edid *) block;
        drm_mode_connector_update_edid_property(connector, edid);
        return edid;
@@ -570,14 +573,19 @@ via_hdmi_detect(struct drm_connector *connector, bool 
force)
        struct drm_via_private *dev_priv = connector->dev->dev_private;
        enum drm_connector_status ret = connector_status_disconnected;
        u32 mm_c730 = VIA_READ(0xc730) & 0xC0000000;
+       struct edid *edid = NULL;
 
        if (VIA_IRQ_DP_HOT_UNPLUG == mm_c730) {
                drm_mode_connector_update_edid_property(connector, NULL);
                return ret;
        }
 
-       if (via_hdmi_get_edid(connector))
-               ret = connector_status_connected;
+       edid = via_hdmi_get_edid(connector);
+       if (edid) {
+               if ((connector->connector_type != DRM_MODE_CONNECTOR_HDMIA) ^
+                   (drm_detect_hdmi_monitor(edid)))
+                       ret = connector_status_connected;
+       }
        return ret;
 }
 
@@ -651,40 +659,58 @@ static const struct drm_connector_helper_funcs 
via_hdmi_connector_helper_funcs =
 void
 via_hdmi_init(struct drm_device *dev, int diport)
 {
-       struct via_connector *con;
+       struct via_connector *dvi, *hdmi;
        struct via_encoder *enc;
 
-       enc = kzalloc(sizeof(*enc) + sizeof(*con), GFP_KERNEL);
+       enc = kzalloc(sizeof(*enc) + 2 * sizeof(*hdmi), GFP_KERNEL);
        if (!enc) {
                DRM_ERROR("Failed to allocate connector and encoder\n");
                return;
        }
-       con = &enc->cons[0];
+       hdmi = &enc->cons[0];
+       dvi = &enc->cons[1];
+
+       /* Setup the encoders and attach them */
+       drm_encoder_init(dev, &enc->base, &via_hdmi_enc_funcs, 
DRM_MODE_ENCODER_TMDS);
+       drm_encoder_helper_add(&enc->base, &via_hdmi_enc_helper_funcs);
+
+       enc->base.possible_crtcs = BIT(1) | BIT(0);
+       enc->base.possible_clones = 0;
+       enc->diPort = diport;
 
-       /* Piece together our connector */
-       drm_connector_init(dev, &con->base, &via_hdmi_connector_funcs,
+       /* Setup the HDMI connector */
+       drm_connector_init(dev, &hdmi->base, &via_hdmi_connector_funcs,
                                DRM_MODE_CONNECTOR_HDMIA);
-       drm_connector_helper_add(&con->base, &via_hdmi_connector_helper_funcs);
-       drm_sysfs_connector_add(&con->base);
+       drm_connector_helper_add(&hdmi->base, &via_hdmi_connector_helper_funcs);
+       drm_sysfs_connector_add(&hdmi->base);
 
-       con->base.doublescan_allowed = false;
+       hdmi->base.doublescan_allowed = false;
        switch (dev->pdev->device) {
        case PCI_DEVICE_ID_VIA_VT3157:
        case PCI_DEVICE_ID_VIA_VT3353:
-               con->base.interlace_allowed = false;
+               hdmi->base.interlace_allowed = false;
                break;
        default:
-               con->base.interlace_allowed = true;
+               hdmi->base.interlace_allowed = true;
                break;
        }
+       drm_mode_connector_attach_encoder(&hdmi->base, &enc->base);
 
-       /* Setup the encoders and attach them */
-       drm_encoder_init(dev, &enc->base, &via_hdmi_enc_funcs, 
DRM_MODE_ENCODER_TMDS);
-       drm_encoder_helper_add(&enc->base, &via_hdmi_enc_helper_funcs);
-
-       enc->base.possible_crtcs = BIT(1) | BIT(0);
-       enc->base.possible_clones = 0;
-       enc->diPort = diport;
+       /* Setup the DVI connector */
+       drm_connector_init(dev, &dvi->base, &via_hdmi_connector_funcs,
+                               DRM_MODE_CONNECTOR_DVID);
+       drm_connector_helper_add(&dvi->base, &via_hdmi_connector_helper_funcs);
+       drm_sysfs_connector_add(&dvi->base);
 
-       drm_mode_connector_attach_encoder(&con->base, &enc->base);
+       dvi->base.doublescan_allowed = false;
+       switch (dev->pdev->device) {
+       case PCI_DEVICE_ID_VIA_VT3157:
+       case PCI_DEVICE_ID_VIA_VT3353:
+               dvi->base.interlace_allowed = false;
+               break;
+       default:
+               dvi->base.interlace_allowed = true;
+               break;
+       }
+       drm_mode_connector_attach_encoder(&dvi->base, &enc->base);
 }
_______________________________________________
Openchrome-devel mailing list
Openchrome-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/openchrome-devel

Reply via email to