File xf86-video-intel-hdmi-audio.diff of Package xorg-x11-driver-video

diff --git a/man/intel.man b/man/intel.man
index 15ab234..31e2b22 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -207,12 +207,6 @@ information.
 Enable XvMC driver. Current support MPEG2 MC on 915/945 and G33 series.
 User should provide absolute path to libIntelXvMC.so in XvMCConfig file.
 Default: Disabled.
-.TP
-.BI "Option \*qForceSDVODetect\*q \*q" boolean \*q
-Instead of depending on SDVO detect status bit to initialize SDVO outputs,
-this option trys to ignore that status bit and try to probe on all SDVO
-ports anyway. Try this if some output is not detected on your ADD2 card.
-Use of this option will slow down your startup time. Default: Disabled.
 
 .SH OUTPUT CONFIGURATION
 On 830M and better chipsets, the driver supports runtime configuration of
diff --git a/src/i810_reg.h b/src/i810_reg.h
index 6458008..95dbf8b 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -1281,6 +1281,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 /** Requird for HDMI operation */
 #define SDVO_NULL_PACKETS_DURING_VSYNC		(1 << 9)
 #define SDVO_BORDER_ENABLE			(1 << 7)
+#define SDVO_AUDIO_ENABLE			(1 << 6)
 /** New with 965, default is to be set */
 #define SDVO_VSYNC_ACTIVE_HIGH			(1 << 4)
 /** New with 965, default is to be set */
diff --git a/src/i830.h b/src/i830.h
index 5e7cbe1..c510eab 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -713,9 +713,6 @@ typedef struct _I830Rec {
    Bool debug_modes;
    unsigned int quirk_flag;
 
-   /* User option to ignore SDVO detect bit status, in case some outputs
-      not detected on SDVO, so let driver try its best. */
-   Bool force_sdvo_detect;
 } I830Rec;
 
 #define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 771a6a0..20aa700 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -313,7 +313,6 @@ typedef enum {
 #ifdef INTEL_XVMC
    OPTION_XVMC,
 #endif
-   OPTION_FORCE_SDVO_DETECT,
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
@@ -340,7 +339,6 @@ static OptionInfoRec I830Options[] = {
 #ifdef INTEL_XVMC
    {OPTION_XVMC,	"XvMC",		OPTV_BOOLEAN,	{0},	TRUE},
 #endif
-   {OPTION_FORCE_SDVO_DETECT, "ForceSDVODetect", OPTV_BOOLEAN,  {0},	FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -913,21 +911,21 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
       i830_lvds_init(pScrn);
 
    if (IS_I9XX(pI830)) {
-      if ((INREG(SDVOB) & SDVO_DETECTED) || pI830->force_sdvo_detect) {
-	 Bool found = i830_sdvo_init(pScrn, SDVOB);
+      Bool found;
+      if ((INREG(SDVOB) & SDVO_DETECTED)) {
+	 found = i830_sdvo_init(pScrn, SDVOB);
 
 	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
 	    i830_hdmi_init(pScrn, SDVOB);
       }
 
-      if ((INREG(SDVOC) & SDVO_DETECTED) || pI830->force_sdvo_detect ||
-	      /* SDVOC detect bit is reserved on 965G/965GM */
-	      (IS_I965G(pI830) && !IS_G4X(pI830))) {
-	 Bool found = i830_sdvo_init(pScrn, SDVOC);
+      if ((INREG(SDVOB) & SDVO_DETECTED))
+	 found = i830_sdvo_init(pScrn, SDVOC);
+
+      if ((INREG(SDVOC) & SDVO_DETECTED) &&
+	    !found && SUPPORTS_INTEGRATED_HDMI(pI830))
+	 i830_hdmi_init(pScrn, SDVOC);
 
-	 if (!found && SUPPORTS_INTEGRATED_HDMI(pI830))
-	    i830_hdmi_init(pScrn, SDVOC);
-      }
    } else {
       i830_dvo_init(pScrn);
    }
@@ -1459,12 +1457,6 @@ I830GetEarlyOptions(ScrnInfoPtr pScrn)
     if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCEENABLEPIPEA, FALSE))
 	pI830->quirk_flag |= QUIRK_PIPEA_FORCE;
 
-    if (xf86ReturnOptValBool(pI830->Options, OPTION_FORCE_SDVO_DETECT, FALSE)) {
-	pI830->force_sdvo_detect = TRUE;
-    } else {
-	pI830->force_sdvo_detect = FALSE;
-    }
-
     return TRUE;
 }
 
diff --git a/src/i830_hdmi.c b/src/i830_hdmi.c
index 44e5c05..76bb8c4 100644
--- a/src/i830_hdmi.c
+++ b/src/i830_hdmi.c
@@ -38,6 +38,8 @@ struct i830_hdmi_priv {
     uint32_t output_reg;
 
     uint32_t save_SDVO;
+
+    Bool has_hdmi_sink;
 };
 
 static int
@@ -78,6 +80,11 @@ i830_hdmi_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 	SDVO_BORDER_ENABLE |
 	SDVO_VSYNC_ACTIVE_HIGH |
 	SDVO_HSYNC_ACTIVE_HIGH;
+
+    if (dev_priv->has_hdmi_sink) {
+	    sdvox |= SDVO_AUDIO_ENABLE;
+	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Audio Enabled\n");
+    }
     if (intel_crtc->pipe == 1)
 	sdvox |= SDVO_PIPE_B_SELECT;
 
@@ -142,6 +149,8 @@ i830_hdmi_detect(xf86OutputPtr output)
     xf86OutputStatus status;
     xf86MonPtr edid_mon;
 
+    dev_priv->has_hdmi_sink = FALSE;
+
     /* For G4X, PEG_BAND_GAP_DATA 3:0 must first be written 0xd.
      * Failure to do so will result in spurious interrupts being
      * generated on the port when a cable is not attached.
@@ -180,6 +189,17 @@ i830_hdmi_detect(xf86OutputPtr output)
     edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
     if (!edid_mon || !DIGITAL(edid_mon->features.input_type))
 	status = XF86OutputStatusDisconnected;
+
+    if (xf86LoaderCheckSymbol("xf86MonitorIsHDMI") &&
+	    xf86MonitorIsHDMI(edid_mon))
+	dev_priv->has_hdmi_sink = TRUE;
+
+    if (pI830->debug_modes)
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+			"%s monitor detected on HDMI-%d\n",
+			dev_priv->has_hdmi_sink ? "HDMI" : "DVI",
+			(dev_priv->output_reg == SDVOB) ? 1 : 2);
+
     xfree(edid_mon);
     return status;
 }
@@ -232,6 +252,7 @@ i830_hdmi_init(ScrnInfoPtr pScrn, int output_reg)
 
     dev_priv = (struct i830_hdmi_priv *)(intel_output + 1);
     dev_priv->output_reg = output_reg;
+    dev_priv->has_hdmi_sink = FALSE;
 
     intel_output->dev_priv = dev_priv;
     intel_output->type = I830_OUTPUT_HDMI;
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 0ceefde..c91196d 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -784,6 +784,24 @@ i830_sdvo_get_supp_encode(xf86OutputPtr output, struct i830_sdvo_encode *encode)
 }
 
 static Bool
+i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
+{
+    I830OutputPrivatePtr    intel_output = output->driver_private;
+    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
+    uint8_t status;
+
+    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
+
+    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0);
+    status = i830_sdvo_read_response(output, &dev_priv->is_hdmi, 1);
+    if (status != SDVO_CMD_STATUS_SUCCESS) {
+	dev_priv->is_hdmi = FALSE;
+	return FALSE;
+    }
+    return TRUE;
+}
+
+static Bool
 i830_sdvo_set_encode(xf86OutputPtr output, uint8_t mode)
 {
     uint8_t status;
@@ -945,7 +963,7 @@ static void i830_sdvo_set_avi_infoframe(xf86OutputPtr output,
 	.len = DIP_LEN_AVI,
     };
 
-    avi_if.u.avi.PR = i830_sdvo_get_pixel_multiplier(mode) - 1;
+//    avi_if.u.avi.PR = i830_sdvo_get_pixel_multiplier(mode) - 1;
     avi_if.checksum = i830_sdvo_calc_hbuf_csum((uint8_t *)&avi_if,
 					4 + avi_if.len);
     i830_sdvo_set_hdmi_buf(output, 1, (uint8_t *)&avi_if, 4 + avi_if.len,
@@ -1017,7 +1035,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
     struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
     xf86CrtcPtr	    crtc = output->crtc;
     I830CrtcPrivatePtr	    intel_crtc = crtc->driver_private;
-    uint32_t sdvox;
+    uint32_t sdvox = 0;
     int sdvo_pixel_multiply;
     struct i830_sdvo_in_out_map in_out;
     struct i830_sdvo_dtd input_dtd;
@@ -1039,8 +1057,10 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 			&in_out, sizeof(in_out));
     status = i830_sdvo_read_response(output, NULL, 0);
 
-    if (dev_priv->is_hdmi)
+    if (dev_priv->is_hdmi) {
 	i830_sdvo_set_avi_infoframe(output, mode);
+	sdvox |= SDVO_AUDIO_ENABLE;
+    }
 
     i830_sdvo_get_dtd_from_mode(&input_dtd, mode);
 
@@ -1088,11 +1108,11 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
 
     /* Set the SDVO control regs. */
     if (IS_I965G(pI830)) {
-	sdvox = SDVO_BORDER_ENABLE |
+	sdvox |= SDVO_BORDER_ENABLE |
 		SDVO_VSYNC_ACTIVE_HIGH |
 		SDVO_HSYNC_ACTIVE_HIGH;
     } else {
-	sdvox = INREG(dev_priv->output_device);
+	sdvox |= INREG(dev_priv->output_device);
 	switch (dev_priv->output_device) {
 	case SDVOB:
 	    sdvox &= SDVOB_PRESERVE_MASK;
@@ -1333,9 +1353,7 @@ i830_sdvo_ddc_i2c_start(I2CBusPtr b, int timeout)
     xf86OutputPtr	    output = b->DriverPrivate.ptr;
     I830OutputPrivatePtr    intel_output = output->driver_private;
     I2CBusPtr		    i2cbus = intel_output->pI2CBus;
-    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
 
-    i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
     return i2cbus->I2CStart(i2cbus, timeout);
 }
 
@@ -1445,6 +1463,34 @@ i830_sdvo_dump(ScrnInfoPtr pScrn)
     }
 }
 
+static void
+i830_sdvo_set_hdmi_encode (xf86OutputPtr output)
+{
+    /* enable hdmi encoding mode if supported */
+    i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
+    i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
+}
+
+/**
+ * Determine if current TMDS encoding is HDMI.
+ * Return TRUE if found HDMI encoding is used, otherwise return FALSE.
+ */
+static Bool
+i830_sdvo_check_hdmi_encode (xf86OutputPtr output)
+{
+    I830OutputPrivatePtr intel_output = output->driver_private;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+    if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
+	    i830_sdvo_get_digital_encoding_mode(output) &&
+	    dev_priv->is_hdmi)
+    {
+	i830_sdvo_set_hdmi_encode(output);
+	return TRUE;
+    } else
+	return FALSE;
+}
+
 /**
  * Asks the SDVO device if any displays are currently connected.
  *
@@ -1479,12 +1525,15 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr output)
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     DisplayModePtr modes = NULL;
     xf86OutputPtr crt;
-    I830OutputPrivatePtr intel_output;
+    I830OutputPrivatePtr intel_output = output->driver_private;
     xf86MonPtr edid_mon = NULL;
+    struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+
+    i830_sdvo_set_control_bus_switch(output, dev_priv->ddc_bus);
 
     modes = i830_ddc_get_modes(output);
     if (modes != NULL)
-	return modes;
+	goto check_hdmi;
 
     /* Mac mini hack.  On this device, I get DDC through the analog, which
      * load-detects as disconnected.  I fail to DDC through the SDVO DDC,
@@ -1504,6 +1553,23 @@ i830_sdvo_get_ddc_modes(xf86OutputPtr output)
 	modes = xf86OutputGetEDIDModes(output);
     }
 
+check_hdmi:
+    /* Check if HDMI encode, setup it and set the flag for HDMI audio */
+    intel_output = output->driver_private;
+    dev_priv = intel_output->dev_priv;
+
+    if (dev_priv->caps.output_flags & (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
+    {
+	if (!i830_sdvo_check_hdmi_encode(output)) {
+	    /* check EDID HDMI info for monitor */
+	    if (output->MonInfo && xf86LoaderCheckSymbol("xf86MonitorIsHDMI")
+		    && xf86MonitorIsHDMI(output->MonInfo)) {
+		dev_priv->is_hdmi = TRUE;
+		i830_sdvo_set_hdmi_encode (output);
+	    } else
+		dev_priv->is_hdmi = FALSE;
+	}
+    }
     return modes;
 }
 
@@ -1729,21 +1795,6 @@ i830_sdvo_select_ddc_bus(struct i830_sdvo_priv *dev_priv)
     dev_priv->ddc_bus = 1 << num_bits;
 }
 
-static Bool
-i830_sdvo_get_digital_encoding_mode(xf86OutputPtr output)
-{
-    I830OutputPrivatePtr    intel_output = output->driver_private;
-    struct i830_sdvo_priv   *dev_priv = intel_output->dev_priv;
-    uint8_t status;
-
-    i830_sdvo_set_target_output(output, dev_priv->controlled_output);
-
-    i830_sdvo_write_cmd(output, SDVO_CMD_GET_ENCODE, NULL, 0);
-    status = i830_sdvo_read_response(output, &dev_priv->is_hdmi, 1);
-    if (status != SDVO_CMD_STATUS_SUCCESS)
-	return FALSE;
-    return TRUE;
-}
 
 Bool
 i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
@@ -1872,14 +1923,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
         output->subpixel_order = SubPixelHorizontalRGB;
 	name_prefix="TMDS";
 
-	if (i830_sdvo_get_supp_encode(output, &dev_priv->encode) &&
-		i830_sdvo_get_digital_encoding_mode(output) &&
-		dev_priv->is_hdmi) {
-	    /* enable hdmi encoding mode if supported */
-	    i830_sdvo_set_encode(output, SDVO_ENCODE_HDMI);
-	    i830_sdvo_set_colorimetry(output, SDVO_COLORIMETRY_RGB256);
+	if (i830_sdvo_check_hdmi_encode (output))
 	    name_prefix = "HDMI";
-	}
     }
     else if (dev_priv->caps.output_flags & SDVO_OUTPUT_SVID0)
     {
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 4d55555..c3929aa 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -210,7 +210,8 @@ struct i830_sdvo_in_out_map {
 struct i830_sdvo_get_interrupt_event_source_response {
     uint16_t interrupt_status;
     unsigned int ambient_light_interrupt:1;
-    unsigned int pad:7;
+    unsigned int hdmi_audio_encrypt_change:1;
+    unsigned int pad:6;
 } __attribute__((packed));
 
 /**
openSUSE Build Service is sponsored by