summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/i830_dvo.c109
1 files changed, 55 insertions, 54 deletions
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 97453ded..283e975b 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -183,37 +183,6 @@ i830_dvo_detect(xf86OutputPtr output)
return intel_output->i2c_drv->vid_rec->detect(dev_priv);
}
-static Bool
-I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus,
- struct _I830DVODriver **retdrv)
-{
- int i;
- void *ret_ptr;
- struct _I830DVODriver *drv;
-
- for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
- drv = &i830_dvo_drivers[i];
- drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
- if (drv->modhandle == NULL)
- continue;
-
- xf86LoaderReqSymLists(drv->symbols, NULL);
-
- ret_ptr = NULL;
- drv->vid_rec = LoaderSymbol(drv->fntablename);
- if (drv->vid_rec != NULL)
- ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
-
- if (ret_ptr != NULL) {
- drv->dev_priv = ret_ptr;
- *retdrv = drv;
- return TRUE;
- }
- xf86UnloadSubModule(drv->modhandle);
- }
- return FALSE;
-}
-
static void
i830_dvo_destroy (xf86OutputPtr output)
{
@@ -245,9 +214,14 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = {
void
i830_dvo_init(ScrnInfoPtr pScrn)
{
- xf86OutputPtr output;
- I830OutputPrivatePtr intel_output;
- int ret;
+ xf86OutputPtr output;
+ I830OutputPrivatePtr intel_output;
+ int ret;
+ int i;
+ void *ret_ptr;
+ struct _I830DVODriver *drv;
+ int gpio_inited = 0;
+ I2CBusPtr pI2CBus = NULL;
output = xf86OutputCreate (pScrn, &i830_dvo_output_funcs,
"TMDS");
@@ -263,14 +237,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
output->driver_private = intel_output;
output->subpixel_order = SubPixelHorizontalRGB;
- /* Set up the I2C and DDC buses */
- ret = I830I2CInit(pScrn, &intel_output->pI2CBus, GPIOE, "DVOI2C_E");
- if (!ret)
- {
- xf86OutputDestroy (output);
- return;
- }
-
+ /* Set up the DDC bus */
ret = I830I2CInit(pScrn, &intel_output->pDDCBus, GPIOD, "DVODDC_D");
if (!ret)
{
@@ -279,17 +246,51 @@ i830_dvo_init(ScrnInfoPtr pScrn)
}
/* Now, try to find a controller */
- ret = I830I2CDetectDVOControllers(pScrn, intel_output->pI2CBus,
- &intel_output->i2c_drv);
- if (ret)
- {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08lX\n",
- intel_output->i2c_drv->modulename,
- intel_output->pI2CBus->DriverPrivate.uval);
- }
- else
- {
- xf86OutputDestroy (output);
- return;
+ for (i = 0; i < I830_NUM_DVO_DRIVERS; i++) {
+ int gpio;
+
+ drv = &i830_dvo_drivers[i];
+ drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
+ if (drv->modhandle == NULL)
+ continue;
+
+ xf86LoaderReqSymLists(drv->symbols, NULL);
+
+ ret_ptr = NULL;
+ drv->vid_rec = LoaderSymbol(drv->fntablename);
+
+ if (drv->type & I830_DVO_CHIP_LVDS)
+ gpio = GPIOB;
+ else
+ gpio = GPIOE;
+
+ /* Set up the I2C bus necessary for the chip we're probing. It appears
+ * that everything is on GPIOE except for panels on i830 laptops, which
+ * are on GPIOB (DVOA).
+ */
+ if (gpio_inited != gpio) {
+ if (pI2CBus != NULL)
+ xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+ if (!I830I2CInit(pScrn, &intel_output->pI2CBus, gpio,
+ gpio == GPIOB ? "DVOI2C_B" : "DVOI2C_E")) {
+ continue;
+ }
+ }
+
+ if (drv->vid_rec != NULL)
+ ret_ptr = drv->vid_rec->init(pI2CBus, drv->address);
+
+ if (ret_ptr != NULL) {
+ drv->dev_priv = ret_ptr;
+ intel_output->i2c_drv = drv;
+ intel_output->pI2CBus = pI2CBus;
+ return;
+ }
+ xf86UnloadSubModule(drv->modhandle);
}
+
+ /* Didn't find a chip, so tear down. */
+ if (pI2CBus != NULL)
+ xf86DestroyI2CBusRec(pI2CBus, TRUE, TRUE);
+ xf86OutputDestroy (output);
}