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));
/**