summaryrefslogtreecommitdiff
path: root/src/i830_dvo.c
diff options
context:
space:
mode:
authorKeith Packard <keithp@dulcimer.keithp.com>2007-05-16 14:02:00 -0700
committerKeith Packard <keithp@dulcimer.keithp.com>2007-05-16 14:02:00 -0700
commitc0daa0a982e7074af4b50653b4a45b0a6352b43d (patch)
tree784a6d552d5ff6e957d5a5fefac99f206f654c46 /src/i830_dvo.c
parentb28817a87a1608e849e4a9a736dda43533a84b0c (diff)
Change DVO module interface to pass more state across. Fix IVCH display.
The DVO module interface reflected most of the xf86Output API to the underlying functions; finish that work given the changes that have since occurred in the xf86Output API. Move the LVDS-specific code into the IVCH module and make that work on the Thinkpad X30 (an i830-based laptop). Panel scaling does not work yet.
Diffstat (limited to 'src/i830_dvo.c')
-rw-r--r--src/i830_dvo.c121
1 files changed, 69 insertions, 52 deletions
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index 129651c9..b69105e9 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -60,11 +60,11 @@ static const char *ch7017_symbols[] = {
/* driver list */
struct _I830DVODriver i830_dvo_drivers[] =
{
- {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput",
+ {I830_DVO_CHIP_TMDS, "sil164", "SIL164VidOutput", DVOC,
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
- {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput",
+ {I830_DVO_CHIP_TMDS | I830_DVO_CHIP_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
- {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
+ {I830_DVO_CHIP_LVDS, "ivch", "ivch_methods", DVOA,
0x04, ivch_symbols, NULL, NULL, NULL},
/*
{I830_DVO_CHIP_LVDS, "ivch", "ivch_methods",
@@ -88,20 +88,18 @@ i830_dvo_dpms(xf86OutputPtr output, int mode)
ScrnInfoPtr pScrn = output->scrn;
I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
- void * dev_priv = intel_output->i2c_drv->dev_priv;
- unsigned int dvo_reg;
-
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS)
- dvo_reg = DVOA;
- else
- dvo_reg = DVOC;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ void * dev_priv = drv->dev_priv;
+ unsigned int dvo_reg = drv->dvo_reg;
if (mode == DPMSModeOn) {
OUTREG(dvo_reg, INREG(dvo_reg) | DVO_ENABLE);
+ POSTING_READ(dvo_reg);
(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
} else {
(*intel_output->i2c_drv->vid_rec->dpms)(dev_priv, mode);
OUTREG(dvo_reg, INREG(dvo_reg) & ~DVO_ENABLE);
+ POSTING_READ(dvo_reg);
}
}
@@ -131,18 +129,18 @@ i830_dvo_restore(xf86OutputPtr output)
I830OutputPrivatePtr intel_output = output->driver_private;
void * dev_priv = intel_output->i2c_drv->dev_priv;
+ (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
+
OUTREG(DVOA, pI830->saveDVOA);
OUTREG(DVOB, pI830->saveDVOB);
OUTREG(DVOC, pI830->saveDVOC);
-
- (*intel_output->i2c_drv->vid_rec->restore)(dev_priv);
}
static int
i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
- void *dev_priv = intel_output->i2c_drv->dev_priv;
+ void *dev_priv = intel_output->i2c_drv->dev_priv;
if (pMode->Flags & V_DBLSCAN)
return MODE_NO_DBLESCAN;
@@ -156,8 +154,11 @@ static Bool
i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
- /* XXX: Hook this up to a DVO driver function */
+ I830OutputPrivatePtr intel_output = output->driver_private;
+ if (intel_output->i2c_drv->vid_rec->mode_fixup)
+ return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
+ mode, adjusted_mode);
return TRUE;
}
@@ -170,21 +171,26 @@ i830_dvo_mode_set(xf86OutputPtr output, DisplayModePtr mode,
xf86CrtcPtr crtc = output->crtc;
I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
I830OutputPrivatePtr intel_output = output->driver_private;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
int pipe = intel_crtc->pipe;
CARD32 dvo;
- unsigned int dvo_reg, dvo_srcdim_reg;
+ unsigned int dvo_reg = drv->dvo_reg, dvo_srcdim_reg;
int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS) {
- dvo_reg = DVOA;
+ switch (dvo_reg) {
+ case DVOA:
dvo_srcdim_reg = DVOA_SRCDIM;
- } else {
- dvo_reg = DVOC;
+ break;
+ case DVOB:
+ dvo_srcdim_reg = DVOB_SRCDIM;
+ break;
+ case DVOC:
dvo_srcdim_reg = DVOC_SRCDIM;
+ break;
}
intel_output->i2c_drv->vid_rec->mode_set(intel_output->i2c_drv->dev_priv,
- mode);
+ mode, adjusted_mode);
/* Save the data order, since I don't know what it should be set to. */
dvo = INREG(dvo_reg) & (DVO_PRESERVE_MASK | DVO_DATA_ORDER_GBRG);
@@ -227,8 +233,6 @@ i830_dvo_detect(xf86OutputPtr output)
static DisplayModePtr
i830_dvo_get_modes(xf86OutputPtr output)
{
- ScrnInfoPtr pScrn = output->scrn;
- I830Ptr pI830 = I830PTR(pScrn);
I830OutputPrivatePtr intel_output = output->driver_private;
DisplayModePtr modes;
@@ -241,11 +245,11 @@ i830_dvo_get_modes(xf86OutputPtr output)
if (modes != NULL)
return modes;
- if (intel_output->i2c_drv->type & I830_DVO_CHIP_LVDS &&
- pI830->panel_fixed_mode != NULL)
+ if (intel_output->i2c_drv->vid_rec->get_modes)
{
- xf86PrintModeline(pScrn->scrnIndex, pI830->panel_fixed_mode);
- return xf86DuplicateMode(pI830->panel_fixed_mode);
+ modes = intel_output->i2c_drv->vid_rec->get_modes (intel_output->i2c_drv->dev_priv);
+ if (modes != NULL)
+ return modes;
}
return NULL;
@@ -258,11 +262,12 @@ i830_dvo_destroy (xf86OutputPtr output)
if (intel_output)
{
+ if (intel_output->i2c_drv->vid_rec->destroy)
+ intel_output->i2c_drv->vid_rec->destroy (intel_output->i2c_drv->dev_priv);
if (intel_output->pI2CBus)
xf86DestroyI2CBusRec (intel_output->pI2CBus, TRUE, TRUE);
if (intel_output->pDDCBus)
xf86DestroyI2CBusRec (intel_output->pDDCBus, TRUE, TRUE);
- /* XXX sub module cleanup? */
xfree (intel_output);
}
}
@@ -287,35 +292,49 @@ static const xf86OutputFuncsRec i830_dvo_output_funcs = {
* Other chips with DVO LVDS will need to extend this to deal with the LVDS
* chip being on DVOB/C and having multiple pipes.
*/
-static void
-i830_dvo_get_panel_timings(xf86OutputPtr output)
+DisplayModePtr
+i830_dvo_get_current_mode (xf86OutputPtr output)
{
ScrnInfoPtr pScrn = output->scrn;
+ I830OutputPrivatePtr intel_output = output->driver_private;
I830Ptr pI830 = I830PTR(pScrn);
- CARD32 dvoa = INREG(DVOA);
-
- if (!IS_I830(pI830))
- return;
+ struct _I830DVODriver *drv = intel_output->i2c_drv;
+ unsigned int dvo_reg = drv->dvo_reg;
+ CARD32 dvo = INREG(dvo_reg);
+ DisplayModePtr mode = NULL;
- assert(pI830->fixed_panel_mode == NULL);
-
- /* If the DVOA port is active, that'll be the LVDS, so we can pull out
+ /* If the DVO port is active, that'll be the LVDS, so we can pull out
* its timings to get how the BIOS set up the panel.
*/
- if (dvoa & DVO_ENABLE) {
- xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int pipe = (dvoa & DVO_PIPE_B_SELECT) ? 1 : 0;
- xf86CrtcPtr crtc = xf86_config->crtc[pipe];
-
- pI830->panel_fixed_mode = i830_crtc_mode_get(pScrn, crtc);
- if (pI830->panel_fixed_mode != NULL)
- pI830->panel_fixed_mode->type |= M_T_PREFERRED;
-
- if (dvoa & DVO_HSYNC_ACTIVE_HIGH)
- pI830->panel_fixed_mode->Flags |= V_PHSYNC;
- if (dvoa & DVO_VSYNC_ACTIVE_HIGH)
- pI830->panel_fixed_mode->Flags |= V_PVSYNC;
+ if (dvo & DVO_ENABLE)
+ {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int pipe = (dvo & DVO_PIPE_B_SELECT) ? 1 : 0;
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+ I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
+ if (intel_crtc->pipe == pipe)
+ {
+ mode = i830_crtc_mode_get(pScrn, crtc);
+
+ if (mode)
+ {
+ mode->type |= M_T_PREFERRED;
+
+ if (dvo & DVO_HSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PHSYNC;
+ if (dvo & DVO_VSYNC_ACTIVE_HIGH)
+ mode->Flags |= V_PVSYNC;
+ }
+ break;
+ }
+ }
}
+ return mode;
}
void
@@ -394,9 +413,6 @@ i830_dvo_init(ScrnInfoPtr pScrn)
return;
}
- if (drv->type & I830_DVO_CHIP_LVDS)
- i830_dvo_get_panel_timings(output);
-
output->driver_private = intel_output;
output->subpixel_order = SubPixelHorizontalRGB;
output->interlaceAllowed = FALSE;
@@ -405,6 +421,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
drv->dev_priv = ret_ptr;
intel_output->i2c_drv = drv;
intel_output->pI2CBus = pI2CBus;
+ drv->vid_rec->setup (drv->dev_priv, output);
return;
}
xf86UnloadSubModule(drv->modhandle);