Move the ivch's fixed panel mode support to i830_dvo.c for other LVDS drivers.

This also results in removal of the setup hook, which was being called
unconditionally and breaking non-ivch dvo drivers.
This commit is contained in:
Eric Anholt 2007-06-22 16:29:21 -07:00
parent ec236c76b9
commit f8d7cbc6e1
4 changed files with 73 additions and 96 deletions

View File

@ -30,12 +30,6 @@ typedef struct _I830I2CVidOutputRec {
* Returns NULL if the device does not exist.
*/
void *(*init)(I2CBusPtr b, I2CSlaveAddr addr);
/**
* Setup the device for use, after the relevant output has been created
*/
Bool
(*setup) (I2CDevPtr d, xf86OutputPtr output);
/**
* Called to allow the output a chance to create properties after the

View File

@ -209,6 +209,8 @@ struct _I830DVODriver {
I830I2CVidOutputRec *vid_rec;
void *dev_priv;
pointer modhandle;
DisplayModePtr panel_fixed_mode;
Bool panel_wants_dither;
};
extern const char *i830_output_type_names[];

View File

@ -60,20 +60,30 @@ static const char *ch7017_symbols[] = {
/* driver list */
struct _I830DVODriver i830_dvo_drivers[] =
{
{I830_OUTPUT_DVO_TMDS, "sil164", "SIL164VidOutput", DVOC,
(SIL164_ADDR_1<<1), SIL164Symbols, NULL , NULL, NULL},
{I830_OUTPUT_DVO_TMDS | I830_OUTPUT_DVO_TVOUT, "ch7xxx", "CH7xxxVidOutput", DVOC,
(CH7xxx_ADDR_1<<1), CH7xxxSymbols, NULL , NULL, NULL},
{I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods", DVOA,
0x04, ivch_symbols, NULL, NULL, NULL},
/*
{I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
0x44, ivch_symbols, NULL, NULL, NULL},
{I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
0x84, ivch_symbols, NULL, NULL, NULL},
{I830_OUTPUT_DVO_LVDS, "ivch", "ivch_methods",
0xc4, ivch_symbols, NULL, NULL, NULL},
*/
{
.type = I830_OUTPUT_DVO_TMDS,
.modulename = "sil164",
.fntablename = "SIL164VidOutput",
.dvo_reg = DVOC,
.address = (SIL164_ADDR_1<<1),
.symbols = SIL164Symbols
},
{
.type = I830_OUTPUT_DVO_TMDS,
.modulename = "ch7xxx",
.fntablename = "CH7xxxVidOutput",
.dvo_reg = DVOC,
.address = (CH7xxx_ADDR_1<<1),
.symbols = CH7xxxSymbols
},
{
.type = I830_OUTPUT_DVO_LVDS,
.modulename = "ivch",
.fntablename = "ivch_methods",
.dvo_reg = DVOA,
.address = 0x04, /* Might also be 0x44, 0x84, 0xc4 */
.symbols = ivch_symbols
},
/*
{ I830_OUTPUT_DVO_LVDS, "ch7017", "ch7017_methods",
0xea, ch7017_symbols, NULL, NULL, NULL }
@ -140,6 +150,7 @@ static int
i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
struct _I830DVODriver *drv = intel_output->i2c_drv;
void *dev_priv = intel_output->i2c_drv->dev_priv;
if (pMode->Flags & V_DBLSCAN)
@ -147,6 +158,13 @@ i830_dvo_mode_valid(xf86OutputPtr output, DisplayModePtr pMode)
/* XXX: Validate clock range */
if (drv->panel_fixed_mode) {
if (pMode->HDisplay > drv->panel_fixed_mode->HDisplay)
return MODE_PANEL;
if (pMode->VDisplay > drv->panel_fixed_mode->VDisplay)
return MODE_PANEL;
}
return intel_output->i2c_drv->vid_rec->mode_valid(dev_priv, pMode);
}
@ -155,6 +173,25 @@ i830_dvo_mode_fixup(xf86OutputPtr output, DisplayModePtr mode,
DisplayModePtr adjusted_mode)
{
I830OutputPrivatePtr intel_output = output->driver_private;
struct _I830DVODriver *drv = intel_output->i2c_drv;
/* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode,
* with the panel scaling set up to source from the H/VDisplay
* of the original mode.
*/
if (drv->panel_fixed_mode != NULL) {
adjusted_mode->HDisplay = drv->panel_fixed_mode->HDisplay;
adjusted_mode->HSyncStart = drv->panel_fixed_mode->HSyncStart;
adjusted_mode->HSyncEnd = drv->panel_fixed_mode->HSyncEnd;
adjusted_mode->HTotal = drv->panel_fixed_mode->HTotal;
adjusted_mode->VDisplay = drv->panel_fixed_mode->VDisplay;
adjusted_mode->VSyncStart = drv->panel_fixed_mode->VSyncStart;
adjusted_mode->VSyncEnd = drv->panel_fixed_mode->VSyncEnd;
adjusted_mode->VTotal = drv->panel_fixed_mode->VTotal;
adjusted_mode->Clock = drv->panel_fixed_mode->Clock;
xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
}
if (intel_output->i2c_drv->vid_rec->mode_fixup)
return intel_output->i2c_drv->vid_rec->mode_fixup (intel_output->i2c_drv->dev_priv,
@ -235,6 +272,7 @@ static DisplayModePtr
i830_dvo_get_modes(xf86OutputPtr output)
{
I830OutputPrivatePtr intel_output = output->driver_private;
struct _I830DVODriver *drv = intel_output->i2c_drv;
DisplayModePtr modes;
/* We should probably have an i2c driver get_modes function for those
@ -253,6 +291,9 @@ i830_dvo_get_modes(xf86OutputPtr output)
return modes;
}
if (drv->panel_fixed_mode != NULL)
return xf86DuplicateMode(drv->panel_fixed_mode);
return NULL;
}
@ -436,7 +477,19 @@ 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);
if (intel_output->type == I830_OUTPUT_DVO_LVDS) {
/* For our LVDS chipsets, we should hopefully be able to
* dig the fixed panel mode out of the BIOS data. However,
* it's in a different format from the BIOS data on chipsets
* with integrated LVDS (stored in AIM headers, liekly),
* so for now, just get the current mode being output through
* DVO.
*/
drv->panel_fixed_mode = i830_dvo_get_current_mode(output);
drv->panel_wants_dither = TRUE;
}
return;
}
xf86UnloadSubModule(drv->modhandle);

View File

@ -49,9 +49,6 @@ struct ivch_priv {
xf86OutputPtr output;
DisplayModePtr panel_fixed_mode;
Bool panel_wants_dither;
CARD16 width;
CARD16 height;
@ -189,6 +186,9 @@ ivch_init(I2CBusPtr b, I2CSlaveAddr addr)
goto out;
}
ivch_read(priv, VR20, &priv->width);
ivch_read(priv, VR21, &priv->height);
return priv;
out:
@ -196,60 +196,18 @@ out:
return NULL;
}
/** Gets the panel mode */
static Bool
ivch_setup (I2CDevPtr d, xf86OutputPtr output)
{
struct ivch_priv *priv = d->DriverPrivate.ptr;
priv->output = output;
ivch_read (priv, VR20, &priv->width);
ivch_read (priv, VR21, &priv->height);
priv->panel_fixed_mode = i830_bios_get_panel_mode (output->scrn, &priv->panel_wants_dither);
if (!priv->panel_fixed_mode)
{
priv->panel_fixed_mode = i830_dvo_get_current_mode (output);
priv->panel_wants_dither = TRUE;
}
return TRUE;
}
static xf86OutputStatus
ivch_detect(I2CDevPtr d)
{
return XF86OutputStatusConnected;
}
static DisplayModePtr
ivch_get_modes (I2CDevPtr d)
{
struct ivch_priv *priv = d->DriverPrivate.ptr;
if (priv->panel_fixed_mode)
return xf86DuplicateMode (priv->panel_fixed_mode);
return NULL;
}
static ModeStatus
ivch_mode_valid(I2CDevPtr d, DisplayModePtr mode)
{
struct ivch_priv *priv = d->DriverPrivate.ptr;
DisplayModePtr panel_fixed_mode = priv->panel_fixed_mode;
if (mode->Clock > 112000)
return MODE_CLOCK_HIGH;
if (panel_fixed_mode)
{
if (mode->HDisplay > panel_fixed_mode->HDisplay)
return MODE_PANEL;
if (mode->VDisplay > panel_fixed_mode->VDisplay)
return MODE_PANEL;
}
return MODE_OK;
}
@ -291,33 +249,6 @@ ivch_dpms(I2CDevPtr d, int mode)
usleep (16 * 1000);
}
static Bool
ivch_mode_fixup(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
struct ivch_priv *priv = d->DriverPrivate.ptr;
DisplayModePtr panel_fixed_mode = priv->panel_fixed_mode;
/* If we have timings from the BIOS for the panel, put them in
* to the adjusted mode. The CRTC will be set up for this mode,
* with the panel scaling set up to source from the H/VDisplay
* of the original mode.
*/
if (panel_fixed_mode != NULL) {
adjusted_mode->HDisplay = panel_fixed_mode->HDisplay;
adjusted_mode->HSyncStart = panel_fixed_mode->HSyncStart;
adjusted_mode->HSyncEnd = panel_fixed_mode->HSyncEnd;
adjusted_mode->HTotal = panel_fixed_mode->HTotal;
adjusted_mode->VDisplay = panel_fixed_mode->VDisplay;
adjusted_mode->VSyncStart = panel_fixed_mode->VSyncStart;
adjusted_mode->VSyncEnd = panel_fixed_mode->VSyncEnd;
adjusted_mode->VTotal = panel_fixed_mode->VTotal;
adjusted_mode->Clock = panel_fixed_mode->Clock;
xf86SetModeCrtc(adjusted_mode, INTERLACE_HALVE_V);
}
return TRUE;
}
static void
ivch_mode_set(I2CDevPtr d, DisplayModePtr mode, DisplayModePtr adjusted_mode)
{
@ -420,14 +351,11 @@ ivch_restore(I2CDevPtr d)
I830I2CVidOutputRec ivch_methods = {
.init = ivch_init,
.setup = ivch_setup,
.dpms = ivch_dpms,
.save = ivch_save,
.restore = ivch_restore,
.mode_valid = ivch_mode_valid,
.mode_fixup = ivch_mode_fixup,
.mode_set = ivch_mode_set,
.detect = ivch_detect,
.get_modes = ivch_get_modes,
.dump_regs = ivch_dump_regs,
};