[Openchrome-devel] drm-openchrome: drivers/gpu/drm
James Simmons
jsimmons at kemper.freedesktop.org
Tue Mar 26 17:35:58 PDT 2013
drivers/gpu/drm/via/via_hdmi.c | 88 ++++++++++++++++++++++++++---------------
1 file changed, 57 insertions(+), 31 deletions(-)
New commits:
commit 818b684eee9b17de1f9d0fa494c8cafa35b81fc3
Author: James Simmons <jsimmons at 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);
}
More information about the Openchrome-devel
mailing list