xf86-video-intel: Branch 'modesetting' - src/i830_driver.c src/i830_sdvo.c src/i830_sdvo_regs.h

Keith Packard keithp at kemper.freedesktop.org
Tue Nov 21 01:19:00 EET 2006


 src/i830_driver.c    |    8 --
 src/i830_sdvo.c      |  148 ++++++++++++++++++++++++++++++++-------------------
 src/i830_sdvo_regs.h |   31 ++++------
 3 files changed, 108 insertions(+), 79 deletions(-)

New commits:
diff-tree d6a0f917e601ea36643c6ad857756e19d24ecd73 (from b945a650e952f98c2d101b71bd3ec0f390478da5)
Author: Keith Packard <keithp at bouzouki.jf.intel.com>
Date:   Mon Nov 20 15:17:32 2006 -0800

    Enable second SDVO channel.
    
    Rework SDVO support so that it can deal with two channels correctly,
    also save/restore all connected output timings.

diff --git a/src/i830_driver.c b/src/i830_driver.c
index aaa2628..5dcd596 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -657,13 +657,7 @@ I830SetupOutputs(ScrnInfoPtr pScrn)
 
    if (IS_I9XX(pI830)) {
       i830_sdvo_init(pScrn, SDVOB);
-
-      /* Don't initialize the second SDVO port for now.  We have issues with
-       * dealing with two ports, where we stomp both SDVO channels' registers
-       * when interacting with each, channel, and commands to one SDVO
-       * device appear to be affecting the other.
-       */
-      /* i830_sdvo_init(pScrn, SDVOC); */
+      i830_sdvo_init(pScrn, SDVOC);
    } else {
       i830_dvo_init(pScrn);
    }
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 8d1f296..fedb8a6 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -59,7 +59,7 @@ struct i830_sdvo_priv {
     int output_device;
 
     /** Active outputs controlled by this SDVO output */
-    struct i830_sdvo_output_flags active_outputs;
+    CARD16 active_outputs;
 
     /**
      * Capabilities of the SDVO device returned by i830_sdvo_get_capabilities()
@@ -72,9 +72,9 @@ struct i830_sdvo_priv {
     /** State for save/restore */
     /** @{ */
     int save_sdvo_mult;
-    struct i830_sdvo_output_flags save_active_outputs;
+    CARD16 save_active_outputs;
     struct i830_sdvo_dtd save_input_dtd_1, save_input_dtd_2;
-    struct i830_sdvo_dtd save_output_dtd;
+    struct i830_sdvo_dtd save_output_dtd[16];
     CARD32 save_SDVOX;
     /** @} */
 };
@@ -155,6 +155,11 @@ const struct _sdvo_cmd_name {
     SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),
 };
 
+static I2CSlaveAddr slaveAddr;
+
+#define SDVO_NAME(dev_priv) ((dev_priv)->output_device == SDVOB ? "SDVO" : "SDVO")
+#define SDVO_PRIV(output)   ((struct i830_sdvo_priv *) (output)->dev_priv)
+
 /**
  * Writes out the data given in args (up to 8 bytes), followed by the opcode.
  */
@@ -162,9 +167,13 @@ static void
 i830_sdvo_write_cmd(I830OutputPtr output, CARD8 cmd, void *args, int args_len)
 {
     int i;
+    struct i830_sdvo_priv *dev_priv = output->dev_priv;
+
+    if (slaveAddr && slaveAddr != dev_priv->d.SlaveAddr)
+	ErrorF ("Mismatch slave addr %x != %x\n", slaveAddr, dev_priv->d.SlaveAddr);
 
     /* Write the SDVO command logging */
-    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "SDVO: W: %02X ", cmd);
+    xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO, "%s: W: %02X ", SDVO_NAME(dev_priv), cmd);
     for (i = 0; i < args_len; i++)
 	LogWrite(1, "%02X ", ((CARD8 *)args)[i]);
     for (; i < 8; i++)
@@ -217,7 +226,7 @@ i830_sdvo_read_response(I830OutputPtr ou
 
     /* Write the SDVO command logging */
     xf86DrvMsg(output->pI2CBus->scrnIndex, X_INFO,
-	       "SDVO: R: ");
+	       "%s: R: ", SDVO_NAME(SDVO_PRIV(output)));
     for (i = 0; i < response_len; i++)
 	LogWrite(1, "%02X ", ((CARD8 *)response)[i]);
     for (; i < 8; i++)
@@ -300,7 +309,7 @@ i830_sdvo_get_trained_inputs(I830OutputP
 
 static Bool
 i830_sdvo_get_active_outputs(I830OutputPtr output,
-			     struct i830_sdvo_output_flags *outputs)
+			     CARD16 *outputs)
 {
     CARD8 status;
 
@@ -312,12 +321,12 @@ i830_sdvo_get_active_outputs(I830OutputP
 
 static Bool
 i830_sdvo_set_active_outputs(I830OutputPtr output,
-			     struct i830_sdvo_output_flags *outputs)
+			     CARD16 outputs)
 {
     CARD8 status;
 
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, outputs,
-			sizeof(*outputs));
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_ACTIVE_OUTPUTS, &outputs,
+			sizeof(outputs));
     status = i830_sdvo_read_response(output, NULL, 0);
 
     return (status == SDVO_CMD_STATUS_SUCCESS);
@@ -348,13 +357,12 @@ i830_sdvo_get_input_pixel_clock_range(I8
 }
 
 static Bool
-i830_sdvo_set_target_output(I830OutputPtr output,
-			    struct i830_sdvo_output_flags *outputs)
+i830_sdvo_set_target_output(I830OutputPtr output, CARD16 outputs)
 {
     CARD8 status;
 
-    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, outputs,
-			sizeof(*outputs));
+    i830_sdvo_write_cmd(output, SDVO_CMD_SET_TARGET_OUTPUT, &outputs,
+			sizeof(outputs));
 
     status = i830_sdvo_read_response(output, NULL, 0);
 
@@ -522,9 +530,9 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     CARD16 h_blank_len, h_sync_len, v_blank_len, v_sync_len;
     CARD16 h_sync_offset, v_sync_offset;
     struct i830_sdvo_dtd output_dtd;
-    struct i830_sdvo_output_flags no_outputs;
+    CARD16 no_outputs;
 
-    memset(&no_outputs, 0, sizeof(no_outputs));
+    no_outputs = 0;
 
     if (!mode)
 	return;
@@ -570,10 +578,10 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
     output_dtd.part2.reserved = 0;
 
     /* Turn off the screens before adjusting timings */
-    i830_sdvo_set_active_outputs(output, &no_outputs);
+    i830_sdvo_set_active_outputs(output, 0);
 
     /* Set the output timing to the screen */
-    i830_sdvo_set_target_output(output, &dev_priv->active_outputs);
+    i830_sdvo_set_target_output(output, dev_priv->active_outputs);
     i830_sdvo_set_output_timing(output, &output_dtd);
 
     /* Set the input timing to the screen. Assume always input 0. */
@@ -609,8 +617,7 @@ i830_sdvo_pre_set_mode(ScrnInfoPtr pScrn
 	break;
     }
 
-    OUTREG(SDVOC, INREG(SDVOC) & ~SDVO_ENABLE);
-    OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
+    OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
 }
 
 static void
@@ -620,7 +627,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
     Bool input1, input2;
-    CARD32 dpll, sdvob, sdvoc;
+    CARD32 dpll, sdvox;
     int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
     int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
     int sdvo_pixel_multiply;
@@ -628,12 +635,18 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     CARD8 status;
 
     /* Set the SDVO control regs. */
-    sdvob = INREG(SDVOB) & SDVOB_PRESERVE_MASK;
-    sdvoc = INREG(SDVOC) & SDVOC_PRESERVE_MASK;
-    sdvob |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
-    sdvoc |= 9 << 19;
+    sdvox = INREG(dev_priv->output_device);
+    switch (dev_priv->output_device) {
+    case SDVOB:
+	sdvox &= SDVOB_PRESERVE_MASK;
+	break;
+    case SDVOC:
+	sdvox &= SDVOC_PRESERVE_MASK;
+	break;
+    }
+    sdvox |= SDVO_ENABLE | (9 << 19) | SDVO_BORDER_ENABLE;
     if (output->pipe == 1)
-	sdvob |= SDVO_PIPE_B_SELECT;
+	sdvox |= SDVO_PIPE_B_SELECT;
 
     dpll = INREG(dpll_reg);
 
@@ -644,13 +657,12 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     } else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
 	dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
     } else {
-	sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
+	sdvox |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
     }
 
     OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);
 
-    OUTREG(SDVOB, sdvob);
-    OUTREG(SDVOC, sdvoc);
+    OUTREG(dev_priv->output_device, sdvox);
 
     for (i = 0; i < 2; i++)
 	i830WaitForVblank(pScrn);
@@ -660,10 +672,11 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScr
     /* Warn if the device reported failure to sync. */
     if (status == SDVO_CMD_STATUS_SUCCESS && !input1) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "First SDVO output reported failure to sync\n");
+		   "First %s output reported failure to sync\n",
+		   SDVO_NAME(dev_priv));
     }
 
-    i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
+    i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
     i830_sdvo_set_target_input(output, TRUE, FALSE);
 }
 
@@ -674,15 +687,11 @@ i830_sdvo_dpms(ScrnInfoPtr pScrn, I830Ou
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
 
     if (mode != DPMSModeOn) {
-	struct i830_sdvo_output_flags no_outputs;
-
-	memset(&no_outputs, 0, sizeof(no_outputs));
-
-	i830_sdvo_set_active_outputs(output, &no_outputs);
-	OUTREG(SDVOB, INREG(SDVOB) & ~SDVO_ENABLE);
+	i830_sdvo_set_active_outputs(output, 0);
+	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) & ~SDVO_ENABLE);
     } else {
-	i830_sdvo_set_active_outputs(output, &dev_priv->active_outputs);
-	OUTREG(SDVOB, INREG(SDVOB) | SDVO_ENABLE);
+	i830_sdvo_set_active_outputs(output, dev_priv->active_outputs);
+	OUTREG(dev_priv->output_device, INREG(dev_priv->output_device) | SDVO_ENABLE);
     }
 }
 
@@ -691,6 +700,7 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    int o;
 
     /* XXX: We should save the in/out mapping. */
 
@@ -707,11 +717,15 @@ i830_sdvo_save(ScrnInfoPtr pScrn, I830Ou
        i830_sdvo_get_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    /* XXX: We should really iterate over the enabled outputs and save each
-     * one's state.
-     */
-    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
-    i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd);
+    for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+    {
+	CARD16  this_output = (1 << o);
+	if (dev_priv->caps.output_flags & this_output)
+	{
+	    i830_sdvo_set_target_output(output, this_output);
+	    i830_sdvo_get_output_timing(output, &dev_priv->save_output_dtd[o]);
+	}
+    }
 
     dev_priv->save_SDVOX = INREG(dev_priv->output_device);
 }
@@ -721,6 +735,7 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
 {
     I830Ptr pI830 = I830PTR(pScrn);
     struct i830_sdvo_priv *dev_priv = output->dev_priv;
+    int o;
 
     if (dev_priv->caps.sdvo_inputs_mask & 0x1) {
        i830_sdvo_set_target_input(output, TRUE, FALSE);
@@ -732,14 +747,20 @@ i830_sdvo_restore(ScrnInfoPtr pScrn, I83
        i830_sdvo_set_input_timing(output, &dev_priv->save_input_dtd_2);
     }
 
-    i830_sdvo_set_target_output(output, &dev_priv->save_active_outputs);
-    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd);
+    for (o = SDVO_OUTPUT_FIRST; o <= SDVO_OUTPUT_LAST; o++)
+    {
+	CARD16  this_output = (1 << o);
+	if (dev_priv->caps.output_flags & this_output)
+	{
+	    i830_sdvo_set_target_output(output, this_output);
+	    i830_sdvo_set_output_timing(output, &dev_priv->save_output_dtd[o]);
+	}
+    }
+    i830_sdvo_set_target_output(output, dev_priv->save_active_outputs);
 
     i830_sdvo_set_clock_rate_mult(output, dev_priv->save_sdvo_mult);
 
     OUTREG(dev_priv->output_device, dev_priv->save_SDVOX);
-
-    i830_sdvo_set_active_outputs(output, &dev_priv->save_active_outputs);
 }
 
 static int
@@ -989,8 +1010,8 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     if (!xf86I2CDevInit(&dev_priv->d)) {
 	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "Failed to initialize SDVO I2C device %s\n",
-		   output_device == SDVOB ? "SDVOB" : "SDVOC");
+		   "Failed to initialize %s I2C device\n",
+		   SDVO_NAME(dev_priv));
 	xf86DestroyI2CBusRec(i2cbus, TRUE, TRUE);
 	xfree(dev_priv);
 	return;
@@ -1043,25 +1064,42 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int ou
 
     i830_sdvo_get_capabilities(output, &dev_priv->caps);
 
+    memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
+    if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0)
+	dev_priv->active_outputs = SDVO_OUTPUT_TMDS0;
+    else if (dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1)
+	dev_priv->active_outputs = SDVO_OUTPUT_TMDS1;
+    else
+    {
+	unsigned char	bytes[2];
+
+	memcpy (bytes, &dev_priv->caps.output_flags, 2);
+	xf86DrvMsg(output->pI2CBus->scrnIndex, X_ERROR,
+		   "%s: No active TMDS outputs (0x%02x%02x)\n",
+		   SDVO_NAME(dev_priv),
+		   bytes[0], bytes[1]);
+    }
+    
+    /* Set the input timing to the screen. Assume always input 0. */
+    i830_sdvo_set_target_input(output, TRUE, FALSE);
+
     i830_sdvo_get_input_pixel_clock_range(output, &dev_priv->pixel_clock_min,
 					  &dev_priv->pixel_clock_max);
 
-    memset(&dev_priv->active_outputs, 0, sizeof(dev_priv->active_outputs));
-    dev_priv->active_outputs.tmds0 = 1;
-
     xf86DrvMsg(pScrn->scrnIndex, X_INFO,
-	       "SDVO device VID/DID: %02X:%02X.%02X, "
+	       "%s device VID/DID: %02X:%02X.%02X, "
 	       "clock range %.1fMHz - %.1fMHz, "
 	       "input 1: %c, input 2: %c, "
 	       "output 1: %c, output 2: %c\n",
+	       SDVO_NAME(dev_priv),
 	       dev_priv->caps.vendor_id, dev_priv->caps.device_id,
 	       dev_priv->caps.device_rev_id,
 	       dev_priv->pixel_clock_min / 1000.0,
 	       dev_priv->pixel_clock_max / 1000.0,
 	       (dev_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N',
 	       (dev_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N',
-	       dev_priv->caps.output_flags.tmds0 ? 'Y' : 'N',
-	       dev_priv->caps.output_flags.tmds1 ? 'Y' : 'N');
+	       dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS0 ? 'Y' : 'N',
+	       dev_priv->caps.output_flags & SDVO_OUTPUT_TMDS1 ? 'Y' : 'N');
 
     pI830->num_outputs++;
 }
diff --git a/src/i830_sdvo_regs.h b/src/i830_sdvo_regs.h
index 98aa7a6..59b2aa8 100644
--- a/src/i830_sdvo_regs.h
+++ b/src/i830_sdvo_regs.h
@@ -29,21 +29,18 @@
  * @file SDVO command definitions and structures.
  */
 
-struct i830_sdvo_output_flags {
-    unsigned int tmds0:1;
-    unsigned int rgb0:1;
-    unsigned int cvbs0:1;
-    unsigned int svid0:1;
-    unsigned int yprpb0:1;
-    unsigned int scart0:1;
-    unsigned int lvds0:1;
-    unsigned int pad0:1;
-    unsigned int tmds1:1;
-    unsigned int pad1:4;
-    unsigned int rgb1:1;
-    unsigned int lvds1:1;
-    unsigned int pad2:1;
-} __attribute__((packed));
+#define SDVO_OUTPUT_FIRST   (0)
+#define SDVO_OUTPUT_TMDS0   (1 << 0)
+#define SDVO_OUTPUT_RGB0    (1 << 1)
+#define SDVO_OUTPUT_CVBS0   (1 << 2)
+#define SDVO_OUTPUT_SVID0   (1 << 3)
+#define SDVO_OUTPUT_YPRPB0  (1 << 4)
+#define SDVO_OUTPUT_SCART0  (1 << 5)
+#define SDVO_OUTPUT_LVDS0   (1 << 6)
+#define SDVO_OUTPUT_TMDS1   (1 << 8)
+#define SDVO_OUTPUT_RGB1    (1 << 13)
+#define SDVO_OUTPUT_LVDS1   (1 << 14)
+#define SDVO_OUTPUT_LAST    (14)
 
 struct i830_sdvo_caps {
     CARD8 vendor_id;
@@ -58,7 +55,7 @@ struct i830_sdvo_caps {
     unsigned int down_scaling:1;
     unsigned int stall_support:1;
     unsigned int pad:1;
-    struct i830_sdvo_output_flags output_flags;
+    CARD16 output_flags;
 } __attribute__((packed));
 
 /** This matches the EDID DTD structure, more or less */
@@ -204,7 +201,7 @@ struct i830_sdvo_get_trained_inputs_resp
 
 #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE		0x0f
 struct i830_sdvo_get_interrupt_event_source_response {
-    struct i830_sdvo_output_flags interrupt_status;
+    CARD16 interrupt_status;
     unsigned int ambient_light_interrupt:1;
     unsigned int pad:7;
 } __attribute__((packed));



More information about the xorg-commit mailing list