summaryrefslogtreecommitdiff
path: root/src/i830_sdvo.c
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2007-03-13 16:55:38 -0700
committerEric Anholt <eric@anholt.net>2007-03-13 16:59:38 -0700
commit44708bdd9ebfef0328302c9a964b80deb46e57c6 (patch)
treed0006b7e5938036e4c701ac2ac0579092f809344 /src/i830_sdvo.c
parent5135b3a79f9c30ebce78c84c49846bba83607fed (diff)
Get SDVO DPMS working on the Mac Mini by writing SDVOB and SDVOC together.
Also, add code for setting the encoder power state like the BIOS does, but this doesn't appear to work. We do much more than the BIOS does in powering things down, so perhaps that's interfering somehow.
Diffstat (limited to 'src/i830_sdvo.c')
-rw-r--r--src/i830_sdvo.c81
1 files changed, 70 insertions, 11 deletions
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index cd0b115a..fb6a7c88 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -79,6 +79,25 @@ struct i830_sdvo_priv {
/** @} */
};
+/**
+ * Writes the SDVOB or SDVOC with the given value, but always writes both
+ * SDVOB and SDVOC to work around apparent hardware issues (according to
+ * comments in the BIOS).
+ */
+static void i830_sdvo_write_sdvox(xf86OutputPtr output, CARD32 val)
+{
+ ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
+ I830Ptr pI830 = I830PTR(pScrn);
+
+ if (dev_priv->output_device == SDVOC)
+ OUTREG(SDVOB, INREG(SDVOB));
+ OUTREG(dev_priv->output_device, val);
+ if (dev_priv->output_device == SDVOB)
+ OUTREG(SDVOC, INREG(SDVOC));
+}
+
/** Read a single byte from the given address on the SDVO device. */
static Bool i830_sdvo_read_byte(xf86OutputPtr output, int addr,
unsigned char *ch)
@@ -163,6 +182,9 @@ const static struct _sdvo_cmd_name {
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_POWER_STATES),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ENCODER_POWER_STATE),
+ SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ENCODER_POWER_STATE),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_RESOLUTION_SUPPORT),
SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
};
@@ -346,6 +368,34 @@ i830_sdvo_set_active_outputs(xf86OutputPtr output,
return (status == SDVO_CMD_STATUS_SUCCESS);
}
+static Bool
+i830_sdvo_set_encoder_power_state(xf86OutputPtr output, int mode)
+{
+ CARD8 status;
+ CARD8 state;
+
+ switch (mode) {
+ case DPMSModeOn:
+ state = SDVO_ENCODER_STATE_ON;
+ break;
+ case DPMSModeStandby:
+ state = SDVO_ENCODER_STATE_STANDBY;
+ break;
+ case DPMSModeSuspend:
+ state = SDVO_ENCODER_STATE_SUSPEND;
+ break;
+ case DPMSModeOff:
+ state = SDVO_ENCODER_STATE_OFF;
+ break;
+ }
+
+ i830_sdvo_write_cmd(output, SDVO_CMD_SET_ENCODER_POWER_STATE, &state,
+ sizeof(state));
+ status = i830_sdvo_read_response(output, NULL, 0);
+
+ return (status == SDVO_CMD_STATUS_SUCCESS);
+}
+
/**
* Returns the pixel clock range limits of the current target input in kHz.
*/
@@ -669,7 +719,7 @@ i830_sdvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
}
- OUTREG(dev_priv->output_device, sdvox);
+ i830_sdvo_write_sdvox(output, sdvox);
}
static void
@@ -683,9 +733,16 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode)
if (mode != DPMSModeOn) {
i830_sdvo_set_active_outputs(output, 0);
- temp = INREG(dev_priv->output_device);
- if ((temp & SDVO_ENABLE) != 0)
- OUTREG(dev_priv->output_device, temp & ~SDVO_ENABLE);
+ if (0)
+ i830_sdvo_set_encoder_power_state(output, mode);
+
+ if (mode == DPMSModeOff) {
+ temp = INREG(dev_priv->output_device);
+ if ((temp & SDVO_ENABLE) != 0) {
+ i830_sdvo_write_sdvox(output, temp & ~SDVO_ENABLE);
+ POSTING_READ(dev_priv->output_device);
+ }
+ }
} else {
Bool input1, input2;
int i;
@@ -694,14 +751,15 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode)
temp = INREG(dev_priv->output_device);
if ((temp & SDVO_ENABLE) == 0)
{
- OUTREG(dev_priv->output_device, temp | SDVO_ENABLE);
+ i830_sdvo_write_sdvox(output, temp | SDVO_ENABLE);
POSTING_READ(dev_priv->output_device);
#if 0
- /* Do it again! If we remove this below register write, or the exact
- * same one 2 lines up, the mac mini SDVO output doesn't turn on.
+ /* Do it again! If we remove this below register write, or the
+ * exact same one 2 lines up, the mac mini SDVO output doesn't
+ * turn on.
*/
- OUTREG(dev_priv->output_device,
- INREG(dev_priv->output_device) | SDVO_ENABLE);
+ i830_sdvo_write_sdvox(output, INREG(dev_priv->output_device) |
+ SDVO_ENABLE);
POSTING_READ(dev_priv->output_device);
#endif
}
@@ -717,6 +775,8 @@ i830_sdvo_dpms(xf86OutputPtr output, int mode)
SDVO_NAME(dev_priv));
}
+ if (0)
+ i830_sdvo_set_encoder_power_state(output, mode);
i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
}
}
@@ -764,7 +824,6 @@ i830_sdvo_restore(xf86OutputPtr output)
ScrnInfoPtr pScrn = output->scrn;
I830OutputPrivatePtr intel_output = output->driver_private;
struct i830_sdvo_priv *dev_priv = intel_output->dev_priv;
- I830Ptr pI830 = I830PTR(pScrn);
int o;
int i;
Bool input1, input2;
@@ -794,7 +853,7 @@ i830_sdvo_restore(xf86OutputPtr output)
i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
- OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
+ i830_sdvo_write_sdvox(output, dev_priv->save_SDVOX);
if (dev_priv->save_SDVOX & SDVO_ENABLE)
{