diff options
author | Dave Airlie <airlied@linux.ie> | 2006-03-21 14:19:17 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2006-06-02 10:01:23 +1000 |
commit | 38a403f88d05087de08ad961f0a7a946ab8b3669 (patch) | |
tree | 2022cd9eee53d5918435f4bb91e60c05aae150c2 | |
parent | b9ec6ee94ccee9a5fe69130d34a328752785a805 (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.h | 47 | ||||
-rw-r--r-- | src/i830_driver.c | 188 | ||||
-rw-r--r-- | src/i830_i2c.c | 20 | ||||
-rw-r--r-- | src/i830_modes.c | 3 | ||||
-rw-r--r-- | src/i830_raw.c | 47 |
5 files changed, 185 insertions, 120 deletions
@@ -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) |