summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2006-12-21 16:21:28 -0800
committerEric Anholt <eric@anholt.net>2006-12-28 11:41:46 -0800
commitb928cef9cd5b3f88dc0880f406300d246a59e0fe (patch)
tree9e296cc289cf62715bb16a359a5b9d1d41e9bca4
parentc87462ded20904dbc6c6cbdb9547523b75fe5471 (diff)
Move dvo driver detection into i830_dvo_init(), and use GPIOB for LVDS drivers.
The documentation states that GPIOB is (generally) used for devices on DVOA on the motherboard, which appears to be the case on the laptop we have with LVDS on the motherboard. This patch is probably not entirely accurate, as there was apparently an LVDS DVO card sold that could be put in desktop machines, which would likely be on GPIOE like other ADD cards. Given that we couldn't find one of these cards for purchase, I'm not worrying about it.
-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);
}