summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2006-03-21 14:19:17 +1100
committerDave Airlie <airlied@linux.ie>2006-06-02 10:01:23 +1000
commit38a403f88d05087de08ad961f0a7a946ab8b3669 (patch)
tree2022cd9eee53d5918435f4bb91e60c05aae150c2
parentb9ec6ee94ccee9a5fe69130d34a328752785a805 (diff)
i830: move to a cleaner output abstraction
still a bit of work to do in linking pipes to outputs
-rw-r--r--src/i830.h47
-rw-r--r--src/i830_driver.c188
-rw-r--r--src/i830_i2c.c20
-rw-r--r--src/i830_modes.c3
-rw-r--r--src/i830_raw.c47
5 files changed, 185 insertions, 120 deletions
diff --git a/src/i830.h b/src/i830.h
index 4ca622c5..c500e4ee 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -219,17 +219,27 @@ typedef struct _I830SaveRec {
/* store information about an Ixxx DVO */
/* The i830->i865 use multiple DVOs with multiple i2cs */
/* the i915, i945 have a single sDVO i2c bus - which is different */
-#define MAX_DVOS 4
+#define MAX_OUTPUTS 6
-#define I830_I2C_BUS_DVO 1
-#define I830_I2C_BUS_SDVO 2
+/* these are outputs from the chip - integrated only
+ external chips are via DVO or SDVO output */
+#define I830_OUTPUT_UNUSED 0
+#define I830_OUTPUT_ANALOG 1
+#define I830_OUTPUT_DVO 2
+#define I830_OUTPUT_SDVO 3
+#define I830_OUTPUT_LVDS 4
+#define I830_OUTPUT_TVOUT 5
#define I830_I2C_CHIP_NONE 0
#define I830_I2C_CHIP_LVDS 1
#define I830_I2C_CHIP_TMDS 2
#define I830_I2C_CHIP_TVOUT 4
-struct _I830RegI2CDriver {
+#define I830_OUTPUT_PIPE_NC 0
+#define I830_OUTPUT_PIPE_A 1
+#define I830_OUTPUT_PIPE_B 2
+
+struct _I830DVODriver {
int type;
char *modulename;
char *fntablename;
@@ -238,24 +248,25 @@ struct _I830RegI2CDriver {
I2CVidOutputRec *vid_rec;
void *devpriv;
pointer modhandle;
-
-};
-
-struct _I830DVORec {
- int bus_type;
- int flags;
- I2CBusPtr pI2CBus;
- I2CBusPtr pDDCBus;
- xf86MonPtr MonInfo;
- struct _I830RegI2CDriver *i2c_drv;
};
-typedef struct _I830SDVORec {
+typedef struct _I830SDVODriver {
int found;
I2CDevRec d;
unsigned char sdvo_regs[20];
} I830SDVORec, *I830SDVOPtr;
+struct _I830OutputRec {
+ int type;
+ int pipe;
+ int flags;
+ xf86MonPtr MonInfo;
+ I2CBusPtr pI2CBus;
+ I2CBusPtr pDDCBus;
+ struct _I830DVODriver *i2c_drv;
+ struct _I830SDVODriver *sdvo_drv;
+};
+
typedef struct _I830Rec {
unsigned char *MMIOBase;
unsigned char *FbBase;
@@ -482,10 +493,10 @@ typedef struct _I830Rec {
int MaxClock;
int ddc2;
- int num_dvos;
+ int num_outputs;
- struct _I830DVORec dvos[MAX_DVOS];
- I830SDVOPtr sdvo;
+ struct _I830OutputRec output[MAX_OUTPUTS];
+ // I830SDVOPtr sdvo;
} I830Rec;
#define I830PTR(p) ((I830Ptr)((p)->driverPrivate))
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 04f3d42b..5ffb7417 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -500,14 +500,16 @@ I830DumpModeDebugInfo(ScrnInfoPtr pScrn)
DR(0x240c);
- if (pI830->sdvo) {
- I830SDVOWriteCommand10(pI830->sdvo);
- I830SDVOWriteCommand18(pI830->sdvo);
- I830SDVOWriteCommand10(pI830->sdvo);
- I830SDVOWriteCommand19(pI830->sdvo);
- I830SDVOWriteCommand10(pI830->sdvo);
+#if 0
+ if (pI830->sdvo && pI830->sdvo->found) {
+ I830SDVOWriteCommand10(pI830->sdvo);
+ I830SDVOWriteCommand18(pI830->sdvo);
+ I830SDVOWriteCommand10(pI830->sdvo);
+ I830SDVOWriteCommand19(pI830->sdvo);
+ I830SDVOWriteCommand10(pI830->sdvo);
}
#endif
+#endif
}
/* XXX Check if this is still needed. */
@@ -1030,15 +1032,19 @@ GetDisplayDevices(ScrnInfoPtr pScrn)
if (pI830->PciInfo->chipType == PCI_CHIP_E7221_G) /* FIXED CONFIG */
return PIPE_CRT;
- if (pI830->dvos[0].MonInfo)
- ret |= PIPE_CRT;
- for (i=1; i<MAX_DVOS; i++)
+
+ for (i=0; i<MAX_OUTPUTS; i++)
{
- if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO)
+ switch (pI830->output[i].type)
{
- if (pI830->dvos[i].MonInfo)
+ case I830_OUTPUT_ANALOG:
+ if (pI830->output[i].MonInfo)
+ ret |= PIPE_CRT;
+ break;
+ case I830_OUTPUT_DVO:
+ if (pI830->output[i].MonInfo)
{
- switch(pI830->dvos[i].i2c_drv->type)
+ switch(pI830->output[i].i2c_drv->type)
{
case I830_I2C_CHIP_LVDS:
ret |= PIPE_LFP;
@@ -1054,6 +1060,15 @@ GetDisplayDevices(ScrnInfoPtr pScrn)
break;
}
}
+ case I830_OUTPUT_SDVO:
+ /* needs more work */
+ break;
+ case I830_OUTPUT_LVDS:
+ ret |= PIPE_LFP;
+ break;
+ case I830_OUTPUT_TVOUT:
+ ret |= PIPE_TV;
+ break;
}
}
@@ -2242,6 +2257,60 @@ I830UseDDC(ScrnInfoPtr pScrn)
return mon_range->max_clock;
}
+void
+I830SetupOutputBusses(ScrnInfoPtr pScrn)
+{
+ I830Ptr pI830 = I830PTR(pScrn);
+ int ret;
+
+ /* everyone has at least a single analog output */
+ pI830->num_outputs = 1;
+ pI830->output[0].type = I830_OUTPUT_ANALOG;
+
+ /* setup the DDC bus for the analog output */
+ I830I2CInit(pScrn, &pI830->output[0].pDDCBus, GPIOA, "CRTDDC_A");
+
+ /* need to add the output busses for each device
+ - this function is very incomplete
+ - i915GM has LVDS and TVOUT for example
+ */
+ switch(pI830->PciInfo->chipType)
+ {
+ case PCI_CHIP_I830_M:
+ case PCI_CHIP_845_G:
+ case PCI_CHIP_I855_GM:
+ case PCI_CHIP_I865_G:
+ /* i865 has a single analog*/
+ pI830->num_outputs = 2;
+ pI830->output[1].type = I830_OUTPUT_DVO;
+ I830I2CInit(pScrn, &pI830->output[1].pDDCBus, GPIOD, "DVODDC_D");
+ I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "DVOI2C_E");
+ break;
+ case PCI_CHIP_I915_G:
+ /* has 2 SDVOs */
+ case PCI_CHIP_E7221_G:
+ case PCI_CHIP_I915_GM:
+ /* has some LVDS + tv-out */
+ case PCI_CHIP_I945_G:
+ /* has 2 SDVOs */
+ case PCI_CHIP_I945_GM:
+ /* be careful there is some hardcoding of SDVO to output 1
+ need to revisit PIPE mappings */
+ pI830->num_outputs = 2;
+ pI830->output[1].type = I830_OUTPUT_SDVO;
+ I830I2CInit(pScrn, &pI830->output[1].pI2CBus, GPIOE, "SDVOCTRL_E");
+
+ pI830->output[1].sdvo_drv = I830SDVOInit(pI830->output[1].pI2CBus);
+ ret = I830I2CDetectSDVOController(pScrn, 1);
+ if (ret == TRUE)
+ {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
+ }
+ break;
+ }
+
+}
+
void
I830PreInitDDC(ScrnInfoPtr pScrn)
{
@@ -2262,44 +2331,7 @@ I830PreInitDDC(ScrnInfoPtr pScrn)
if (xf86LoadSubModule(pScrn, "i2c")) {
xf86LoaderReqSymLists(I810i2cSymbols,NULL);
- pI830->num_dvos = 1;
- pI830->dvos[0].bus_type = I830_I2C_BUS_DVO;
- /* setup the common CRT DVO */
- pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pDDCBus, GPIOA, "DDCGPIOA");
- if (pI830->ddc2 == FALSE)
- return;
- pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[0].pI2CBus, GPIOB, "I2CGPIOB");
- if (pI830->ddc2 == FALSE)
- return;
-
- if (!(IS_I9XX(pI830))) {
- pI830->dvos[1].bus_type = I830_I2C_BUS_DVO;
- pI830->num_dvos = 2;
-
- pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pDDCBus, GPIOD, "DDCGPIOD");
- if (pI830->ddc2 == FALSE)
- return;
- pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "I2CGPIOE");
- if (pI830->ddc2 == FALSE)
- return;
- }
- else {
- pI830->num_dvos = 2;
- pI830->dvos[1].bus_type = I830_I2C_BUS_SDVO;
- /* i915 has sDVO */
- pI830->ddc2 = I830I2CInit(pScrn, &pI830->dvos[1].pI2CBus, GPIOE, "SDVOCTRL");
- if (pI830->ddc2 == FALSE)
- return;
-
- pI830->sdvo=I830SDVOInit(pI830->dvos[1].pI2CBus);
-
- ret = I830I2CDetectSDVOController(pScrn, pI830->dvos[1].pI2CBus);
- if (ret==TRUE)
- {
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found sDVO\n");
- }
-
- }
+ I830SetupOutputBusses(pScrn);
pI830->ddc2 = TRUE;
}
@@ -2315,41 +2347,53 @@ void I830DetectMonitors(ScrnInfoPtr pScrn)
if (!pI830->ddc2)
return;
-
- for (i=0; i<pI830->num_dvos; i++)
- {
-
/* we can't do EDID on sDVO yet */
- if (pI830->dvos[i].bus_type == I830_I2C_BUS_DVO)
+ for (i=0; i<pI830->num_outputs; i++)
+ {
+ switch(pI830->output[i].type)
{
- pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->dvos[i].pDDCBus);
+ case I830_OUTPUT_ANALOG:
+ /* for an analog output just to DDC */
+ pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->output[i].pDDCBus);
+
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC Analog %d, %08X\n", i, pI830->output[i].pDDCBus->DriverPrivate.uval);
+ xf86PrintEDID(pI830->output[i].MonInfo);
+ break;
+ case I830_OUTPUT_DVO:
+ /* check for DDC */
+ pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->output[i].pDDCBus);
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i, pI830->dvos[i].pDDCBus->DriverPrivate.uval);
- xf86PrintEDID(pI830->dvos[i].MonInfo);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC DVO %d, %08X\n", i, pI830->output[i].pDDCBus->DriverPrivate.uval);
+ xf86PrintEDID(pI830->output[i].MonInfo);
/* if we are on an i2C bus > 0 and we see a monitor - try to
find a controller chip */
- if (i > 0 && pI830->dvos[i].MonInfo)
+ if (pI830->output[i].MonInfo)
{
- ret = I830I2CDetectControllers(pScrn, pI830->dvos[i].pI2CBus, &pI830->dvos[i].i2c_drv);
+ ret = I830I2CDetectDVOControllers(pScrn, pI830->output[i].pI2CBus, &pI830->output[i].i2c_drv);
if (ret==TRUE)
{
- xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->dvos[i].i2c_drv->modulename, pI830->dvos[i].pI2CBus->DriverPrivate.uval);
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Found i2c %s on %08X\n", pI830->output[i].i2c_drv->modulename, pI830->output[i].pI2CBus->DriverPrivate.uval);
}
}
- }
- else if (pI830->dvos[i].bus_type == I830_I2C_BUS_SDVO) {
-
- if (pI830->sdvo->found)
+ break;
+ case I830_OUTPUT_SDVO:
+ if (pI830->output[i].sdvo_drv->found)
{
- I830SDVOSetupDDC(pI830->sdvo);
+ I830SDVOSetupDDC(pI830->output[i].sdvo_drv);
- pI830->dvos[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->dvos[i].pI2CBus);
+ pI830->output[i].MonInfo = xf86DoEDID_DDC2(pScrn->scrnIndex, pI830->output[i].pI2CBus);
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "checking DVO %d, %08X\n", i, pI830->dvos[i].pI2CBus->DriverPrivate.uval);
- xf86PrintEDID(pI830->dvos[i].MonInfo);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DDC SDVO %d, %08X\n", i, pI830->output[i].pI2CBus->DriverPrivate.uval);
+ xf86PrintEDID(pI830->output[i].MonInfo);
}
+ break;
+ case I830_OUTPUT_UNUSED:
+ break;
+ default:
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Unknown or unhandled output device at %d\n", i);
+ break;
}
}
@@ -2846,9 +2890,9 @@ I830BIOSPreInit(ScrnInfoPtr pScrn, int flags)
I830DetectMonitors(pScrn);
- for (i=0; i<MAX_DVOS; i++) {
- if (pI830->dvos[i].MonInfo) {
- pScrn->monitor->DDC = pI830->dvos[i].MonInfo;
+ for (i=0; i<MAX_OUTPUTS; i++) {
+ if (pI830->output[i].MonInfo) {
+ pScrn->monitor->DDC = pI830->output[i].MonInfo;
break;
}
}
diff --git a/src/i830_i2c.c b/src/i830_i2c.c
index 3364ef71..8d0e9132 100644
--- a/src/i830_i2c.c
+++ b/src/i830_i2c.c
@@ -56,12 +56,12 @@ static const char *SIL164Symbols[] = {
};
/* driver list */
-struct _I830RegI2CDriver i830_i2c_drivers[] =
+struct _I830DVODriver i830_dvo_drivers[] =
{ I830_I2C_CHIP_TMDS, "sil164", "SIL164VidOutput", (SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL};
-#define I830_NUM_I2C_DRIVERS (sizeof(i830_i2c_drivers)/sizeof(struct _I830RegI2CDriver))
+#define I830_NUM_DVO_DRIVERS (sizeof(i830_dvo_drivers)/sizeof(struct _I830DVODriver))
/* bit locations in the registers */
#define SCL_DIR_MASK 0x0001
@@ -419,16 +419,16 @@ I830I2CInit(ScrnInfoPtr pScrn, I2CBusPtr *bus_ptr, int i2c_reg, char *name)
}
Bool
-I830I2CDetectControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830RegI2CDriver **retdrv)
+I830I2CDetectDVOControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830DVODriver **retdrv)
{
I830Ptr pI830 = I830PTR(pScrn);
int i;
void *ret_ptr;
- struct _I830RegI2CDriver *drv;
+ struct _I830DVODriver *drv;
- for (i=0; i<I830_NUM_I2C_DRIVERS; i++)
+ for (i=0; i<I830_NUM_DVO_DRIVERS; i++)
{
- drv = &i830_i2c_drivers[i];
+ drv = &i830_dvo_drivers[i];
drv->modhandle = xf86LoadSubModule(pScrn, drv->modulename);
if (!drv->modhandle)
@@ -453,13 +453,14 @@ I830I2CDetectControllers(ScrnInfoPtr pScrn, I2CBusPtr pI2CBus, struct _I830RegI2
Bool
-I830I2CDetectSDVOController(ScrnInfoPtr pScrn, I2CBusPtr b)
+I830I2CDetectSDVOController(ScrnInfoPtr pScrn, int output_index)
{
I830Ptr pI830 = I830PTR(pScrn);
I2CDevRec d;
unsigned char ch[64];
int i;
int addr = 0x39 << 1;
+ I2CBusPtr b = pI830->output[output_index].pI2CBus;
/* attempt to talk to an SDVO controller */
d.DevName = "SDVO";
@@ -478,6 +479,9 @@ I830I2CDetectSDVOController(ScrnInfoPtr pScrn, I2CBusPtr b)
return FALSE;
}
}
- pI830->sdvo->found = 1;
+
+ if (pI830->output[output_index].sdvo_drv)
+ pI830->output[output_index].sdvo_drv->found = 1;
+
return TRUE;
}
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 1b089f3d..b9b873d7 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -1106,7 +1106,8 @@ int I830xf86ValidateDDCModes(ScrnInfoPtr pScrn1, char **ppModeName)
pScrn->monitor->Modes->prev = last;
first->prev = temp;
- temp->next = first;
+ if (temp)
+ temp->next = first;
pScrn->monitor->Modes = first;
}
diff --git a/src/i830_raw.c b/src/i830_raw.c
index 8823f4ad..1aa3d95c 100644
--- a/src/i830_raw.c
+++ b/src/i830_raw.c
@@ -134,8 +134,8 @@ i9xx_calc_pll_params(int index, int clock,
CARD32 *retn, CARD32 *retp1, CARD32 *retp2,
CARD32 *retclock)
{
- volatile CARD32 m1, m2, n, p1, p2, n1;
-volatile CARD32 f_vco, p, p_best = 0, m, f_out;
+ CARD32 m1, m2, n, p1, p2, n1;
+ CARD32 f_vco, p, p_best = 0, m, f_out;
CARD32 err_max, err_target, err_best = 10000000;
CARD32 n_best = 0, m_best = 0, f_best, f_err;
CARD32 p_min, p_max, p_inc, div_min, div_max;
@@ -357,7 +357,7 @@ I830RawSetHw(ScrnInfoPtr pScrn, DisplayModePtr pMode)
CARD32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
int index;
int displays = pI830->operatingDevices;
- int ret;
+ int ret, i;
index = IS_I9XX(pI830) ? PLLS_I9xx : PLLS_I8xx;
@@ -459,10 +459,12 @@ I830RawSetHw(ScrnInfoPtr pScrn, DisplayModePtr pMode)
(m2 << FP_M2_DIVISOR_SHIFT);
*fp1 = *fp0;
- if (pI830->sdvo && pI830->sdvo->found)
- *dpll |= DPLL_2X_CLOCK_ENABLE;
- else
- *dpll &= ~DPLL_2X_CLOCK_ENABLE;
+ *dpll &= ~DPLL_2X_CLOCK_ENABLE;
+ for (i=0; i<pI830->num_outputs; i++)
+ {
+ if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+ *dpll |= DPLL_2X_CLOCK_ENABLE;
+ }
/* leave these alone for now */
// hw->dvob &= ~DVO_ENABLE;
@@ -888,6 +890,7 @@ I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
I830Ptr pI830 = I830PTR(pScrn);
Bool didLock = FALSE;
int retry_count = 0;
+ int i;
DPRINTF(PFX, "RawSetMode");
@@ -901,26 +904,28 @@ I830RawSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode)
I830RawSetHw(pScrn, mode);
retry:
- if (pI830->sdvo && pI830->sdvo->found == 1)
+ /* do SDVO setup */
+ for (i = 0; i < pI830->num_outputs; i++)
{
- I830SDVOPreSetMode(pI830->sdvo, mode);
+ if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
+ {
+ I830SDVOPreSetMode(pI830->output[i].sdvo_drv, mode);
+ }
}
- if (0)
- {
- // I830Replay1280x1024_DVI(pScrn, mode);
- }
- else
- ret=I830ProgramModeReg(pScrn, mode);
+ ret=I830ProgramModeReg(pScrn, mode);
- if (pI830->sdvo && pI830->sdvo->found == 1)
+ for (i = 0; i < pI830->num_outputs; i++)
{
- ret = I830SDVOPostSetMode(pI830->sdvo, mode);
- /* if it didn't enable the DFP on the output */
- if (ret==FALSE && (pI830->MonType1 & PIPE_DFP) && retry_count<3)
+ if (pI830->output[i].sdvo_drv && pI830->output[i].sdvo_drv->found)
{
- retry_count++;
- goto retry;
+ ret = I830SDVOPostSetMode(pI830->output[i].sdvo_drv, mode);
+ /* if it didn't enable the DFP on the output */
+ if (ret==FALSE && (pI830->MonType1 & PIPE_DFP) && retry_count<3)
+ {
+ retry_count++;
+ goto retry;
+ }
}
}
if (didLock)