From 780c7e34b795122b843c2d92ffb422a35058f63b Mon Sep 17 00:00:00 2001
From: Zhenyu Wang <zhenyu.z.wang@intel.com>
Date: Fri, 5 Dec 2008 14:05:19 +0800
Subject: [PATCH] SDVO: use attached display flags for output setup

SDVO encoder will return all supported display types in
capability flag, which can't be used to determine what current
display type is, and possible to cause conflict.

This one trys to use GET_ATTACHED_DISPLAYS command
to setup output according with current config.
---
 src/i830_sdvo.c |   57 +++++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 45 insertions(+), 12 deletions(-)

diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 256d16d..f22c12c 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -1450,6 +1450,16 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
     }
 }
 
+static uint8_t
+i830_sdvo_get_attached_display (xf86OutputPtr output, uint16_t* response)
+{
+    uint8_t status;
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
+    status = i830_sdvo_read_response(output, response, 2);
+    return status;
+}
+
 /**
  * Asks the SDVO device if any displays are currently connected.
  *
@@ -1462,16 +1472,15 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
 static xf86OutputStatus
 i830_sdvo_detect(xf86OutputPtr output)
 {
-    uint8_t response[2];
+    uint16_t response;
     uint8_t status;
 
-    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ATTACHED_DISPLAYS, NULL, 0);
-    status = i830_sdvo_read_response(output, &response, 2);
+    status = i830_sdvo_get_attached_display(output, &response);
 
     if (status != SDVO_CMD_STATUS_SUCCESS)
 	return XF86OutputStatusUnknown;
 
-    if (response[0] != 0 || response[1] != 0)
+    if (response != 0)
 	return XF86OutputStatusConnected;
     else
 	return XF86OutputStatusDisconnected;
@@ -1753,6 +1762,7 @@ i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
 Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 {
+    I830Ptr		    pI830 = I830PTR(pScrn);
     xf86OutputPtr	    output;
     I830OutputPrivatePtr    intel_output;
     struct i830_sdvo_priv   *dev_priv;
@@ -1762,6 +1772,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     char		    name[60];
     char		    *name_prefix;
     char		    *name_suffix;
+    uint8_t		    status;
+    uint16_t		    attached;
 
     output = xf86OutputCreate (pScrn, &i830_sdvo_output_funcs,NULL);
     if (!output)
@@ -1866,11 +1878,32 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
     intel_output->pDDCBus = ddcbus;
     intel_output->dev_priv = dev_priv;
 
-    i830_sdvo_get_capabilities(output, &dev_priv->caps);
+    if (i830_sdvo_get_capabilities(output, &dev_priv->caps) == FALSE ||
+	    dev_priv->caps.output_flags == 0)
+    {
+	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
+		"SDVO can't get encoder capability\n");
+	xf86OutputDestroy (output);
+	return FALSE;
+    }
+
+    status = i830_sdvo_get_attached_display (output, &attached);
+    if (status != SDVO_CMD_STATUS_SUCCESS) {
+	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
+		"SDVO can't get attached displays\n");
+	xf86OutputDestroy (output);
+	return FALSE;
+    } else {
+	if (pI830->debug_modes)
+	    xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_INFO,
+		    "SDVO%c attached display 0x%x\n",
+		    output_device == SDVOB ? 'B' : 'C',
+		    attached);
+    }
 
-    if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+    if (attached & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
     {
-	if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+	if (attached & SDVO_OUTPUT_TMDS0)
 	    dev_priv->controlled_output = SDVO_OUTPUT_TMDS0;
 	else
 	    dev_priv->controlled_output = SDVO_OUTPUT_TMDS1;
@@ -1886,7 +1919,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	    name_prefix = "HDMI";
 	}
     }
-    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
+    else if (attached & SDVO_OUTPUT_SVID0)
     {
 	dev_priv->controlled_output = SDVO_OUTPUT_SVID0;
         output->subpixel_order = SubPixelHorizontalRGB; /* XXX */
@@ -1894,13 +1927,13 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	dev_priv->is_tv = TRUE;
 	intel_output->needs_tv_clock = TRUE;
     }
-    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB0)
+    else if (attached & SDVO_OUTPUT_RGB0)
     {
 	dev_priv->controlled_output = SDVO_OUTPUT_RGB0;
         output->subpixel_order = SubPixelHorizontalRGB;
 	name_prefix="VGA";
     }
-    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_RGB1)
+    else if (attached & SDVO_OUTPUT_RGB1)
     {
 	dev_priv->controlled_output = SDVO_OUTPUT_RGB1;
         output->subpixel_order = SubPixelHorizontalRGB;
@@ -1911,7 +1944,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	unsigned char	bytes[2];
 
 	dev_priv->controlled_output = 0;
-	memcpy (bytes, &dev_priv->caps.output_flags, 2);
+	memcpy (bytes, &attached, 2);
 	xf86DrvMsg(intel_output->pI2CBus->scrnIndex, X_WARNING,
 		   "%s: Unknown SDVO output type (0x%02x%02x)\n",
 		   SDVO_NAME(dev_priv),
@@ -1950,7 +1983,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
 	       dev_priv->caps.sdvo_input_count >= 2 ? "s" : "");
 
 #define REPORT_OUTPUT_FLAG(flag, name) do {				\
-    if (dev_priv->caps.output_flags & flag) {				\
+    if (attached & flag) {				\
 	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s: %s output reported\n", \
 		   SDVO_NAME(dev_priv), name);				\
     }									\
-- 
1.5.6.5