Give each output a get_modes function and expose those modes through RandR.
The get_modes should return the probed modes only. The driver should then append to the list (for example, compatible modes listed in other outputs, or standard VESA modes) to create the list to expose through RandR. That isn't done yet.
This commit is contained in:
parent
cc3728be24
commit
7195dfabd5
15
src/i830.h
15
src/i830.h
|
|
@ -269,6 +269,20 @@ struct _I830OutputRec {
|
|||
*/
|
||||
enum detect_status (*detect)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* Query the device for the modes it provides.
|
||||
*
|
||||
* \return singly-linked list of modes or NULL if no modes found.
|
||||
*/
|
||||
DisplayModePtr (*get_modes)(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/**
|
||||
* List of available modes on this output.
|
||||
*
|
||||
* This should be the list from get_modes(), plus perhaps additional
|
||||
* compatible modes added later.
|
||||
*/
|
||||
DisplayModePtr probed_modes;
|
||||
xf86MonPtr MonInfo;
|
||||
I2CBusPtr pI2CBus;
|
||||
I2CBusPtr pDDCBus;
|
||||
|
|
@ -680,6 +694,7 @@ DisplayModePtr i830GetGTF(int h_pixels, int v_lines, float freq,
|
|||
|
||||
/* i830_modes.c */
|
||||
int I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time);
|
||||
DisplayModePtr i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output);
|
||||
|
||||
/* i830_randr.c */
|
||||
Bool I830RandRCreateScreenResources (ScreenPtr pScreen);
|
||||
|
|
|
|||
|
|
@ -286,6 +286,7 @@ i830_crt_init(ScrnInfoPtr pScrn)
|
|||
pI830->output[pI830->num_outputs].pre_set_mode = i830_crt_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_crt_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_crt_detect;
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
|
||||
|
||||
/* Set up the DDC bus. */
|
||||
I830I2CInit(pScrn, &pI830->output[pI830->num_outputs].pDDCBus,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,7 @@ i830_dvo_init(ScrnInfoPtr pScrn)
|
|||
pI830->output[i].pre_set_mode = i830_dvo_pre_set_mode;
|
||||
pI830->output[i].post_set_mode = i830_dvo_post_set_mode;
|
||||
pI830->output[i].detect = i830_dvo_detect;
|
||||
pI830->output[i].get_modes = i830_ddc_get_modes;
|
||||
|
||||
/* Set up the I2C and DDC buses */
|
||||
ret = I830I2CInit(pScrn, &pI830->output[i].pI2CBus, GPIOE, "DVOI2C_E");
|
||||
|
|
|
|||
|
|
@ -235,6 +235,11 @@ i830_lvds_init(ScrnInfoPtr pScrn)
|
|||
pI830->output[pI830->num_outputs].pre_set_mode = i830_lvds_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_lvds_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_lvds_detect;
|
||||
/* This will usually return NULL on laptop panels, which is no good.
|
||||
* We need to construct a mode from the fixed panel info, and return a copy
|
||||
* of that when DDC is unavailable.
|
||||
*/
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_ddc_get_modes;
|
||||
|
||||
/* Set up the LVDS DDC channel. Most panels won't support it, but it can
|
||||
* be useful if available.
|
||||
|
|
|
|||
|
|
@ -933,11 +933,22 @@ int
|
|||
I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
|
||||
{
|
||||
I830Ptr pI830 = I830PTR(pScrn);
|
||||
int pipe;
|
||||
int pipe, i;
|
||||
DisplayModePtr saved_mode, last;
|
||||
Bool pipes_reconfigured = FALSE;
|
||||
int originalVirtualX, originalVirtualY;
|
||||
|
||||
/* Re-probe the list of modes for each output. */
|
||||
for (i = 0; i < pI830->num_outputs; i++) {
|
||||
while (pI830->output[i].probed_modes != NULL) {
|
||||
xf86DeleteMode(&pI830->output[i].probed_modes,
|
||||
pI830->output[i].probed_modes);
|
||||
}
|
||||
|
||||
pI830->output[i].probed_modes =
|
||||
pI830->output[i].get_modes(pScrn, &pI830->output[i]);
|
||||
}
|
||||
|
||||
for (pipe = 0; pipe < pI830->availablePipes; pipe++) {
|
||||
I830ReprobePipeModeList(pScrn, pipe);
|
||||
}
|
||||
|
|
@ -1099,3 +1110,23 @@ I830ValidateXF86ModeList(ScrnInfoPtr pScrn, Bool first_time)
|
|||
|
||||
return 1; /* XXX */
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic get_modes function using DDC, used by many outputs.
|
||||
*/
|
||||
DisplayModePtr
|
||||
i830_ddc_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
xf86MonPtr ddc_mon;
|
||||
DisplayModePtr ddc_modes;
|
||||
|
||||
ddc_mon = xf86DoEDID_DDC2(pScrn->scrnIndex, output->pDDCBus);
|
||||
if (ddc_mon == NULL)
|
||||
return NULL;
|
||||
|
||||
ddc_modes = i830GetDDCModes(pScrn, ddc_mon);
|
||||
|
||||
xfree(ddc_mon);
|
||||
|
||||
return ddc_modes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -612,7 +612,6 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
|
|||
int p;
|
||||
int clone_types;
|
||||
int crtc_types;
|
||||
int connection;
|
||||
int pipe_type;
|
||||
int pipe;
|
||||
int subpixel;
|
||||
|
|
@ -631,6 +630,8 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
|
|||
randrp->virtualX, randrp->virtualY);
|
||||
for (i = 0; i < pI830->num_outputs; i++)
|
||||
{
|
||||
MonPtr mon;
|
||||
|
||||
output = &pI830->output[i];
|
||||
/*
|
||||
* Valid crtcs
|
||||
|
|
@ -705,50 +706,53 @@ I830RandRSetInfo12 (ScreenPtr pScreen)
|
|||
nmode = 0;
|
||||
npreferred = 0;
|
||||
rrmodes = NULL;
|
||||
if (pipe >= 0)
|
||||
{
|
||||
MonPtr mon = pI830->pipeMon[pipe];
|
||||
modes = mon->Modes;
|
||||
|
||||
for (mode = modes; mode; mode = mode->next)
|
||||
nmode++;
|
||||
modes = pI830->output[i].probed_modes;
|
||||
|
||||
if (nmode)
|
||||
{
|
||||
rrmodes = xalloc (nmode * sizeof (RRModePtr));
|
||||
if (!rrmodes)
|
||||
return FALSE;
|
||||
nmode = 0;
|
||||
for (p = 1; p >= 0; p--)
|
||||
{
|
||||
for (mode = modes; mode; mode = mode->next)
|
||||
{
|
||||
if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0))
|
||||
{
|
||||
modeInfo.nameLength = strlen (mode->name);
|
||||
if (pI830->output[i].pipe >= 0)
|
||||
mon = pI830->pipeMon[pipe];
|
||||
else
|
||||
mon = NULL;
|
||||
|
||||
for (mode = modes; mode; mode = mode->next)
|
||||
nmode++;
|
||||
|
||||
if (nmode) {
|
||||
rrmodes = xalloc (nmode * sizeof (RRModePtr));
|
||||
if (!rrmodes)
|
||||
return FALSE;
|
||||
nmode = 0;
|
||||
|
||||
for (p = 1; p >= 0; p--) {
|
||||
for (mode = modes; mode; mode = mode->next) {
|
||||
if ((p != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
|
||||
modeInfo.nameLength = strlen (mode->name);
|
||||
if (mon != NULL) {
|
||||
modeInfo.mmWidth = mon->widthmm;
|
||||
modeInfo.mmHeight = mon->heightmm;
|
||||
} else {
|
||||
modeInfo.mmWidth = 0;
|
||||
modeInfo.mmHeight = 0;
|
||||
}
|
||||
|
||||
modeInfo.width = mode->HDisplay;
|
||||
modeInfo.dotClock = mode->Clock * 1000;
|
||||
modeInfo.hSyncStart = mode->HSyncStart;
|
||||
modeInfo.hSyncEnd = mode->HSyncEnd;
|
||||
modeInfo.hTotal = mode->HTotal;
|
||||
modeInfo.hSkew = mode->HSkew;
|
||||
modeInfo.width = mode->HDisplay;
|
||||
modeInfo.dotClock = mode->Clock * 1000;
|
||||
modeInfo.hSyncStart = mode->HSyncStart;
|
||||
modeInfo.hSyncEnd = mode->HSyncEnd;
|
||||
modeInfo.hTotal = mode->HTotal;
|
||||
modeInfo.hSkew = mode->HSkew;
|
||||
|
||||
modeInfo.height = mode->VDisplay;
|
||||
modeInfo.vSyncStart = mode->VSyncStart;
|
||||
modeInfo.vSyncEnd = mode->VSyncEnd;
|
||||
modeInfo.vTotal = mode->VTotal;
|
||||
modeInfo.modeFlags = mode->Flags;
|
||||
modeInfo.height = mode->VDisplay;
|
||||
modeInfo.vSyncStart = mode->VSyncStart;
|
||||
modeInfo.vSyncEnd = mode->VSyncEnd;
|
||||
modeInfo.vTotal = mode->VTotal;
|
||||
modeInfo.modeFlags = mode->Flags;
|
||||
|
||||
rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
|
||||
rrmode->devPrivate = mode;
|
||||
if (rrmode)
|
||||
{
|
||||
rrmodes[nmode++] = rrmode;
|
||||
npreferred += p;
|
||||
}
|
||||
rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
|
||||
rrmode->devPrivate = mode;
|
||||
if (rrmode) {
|
||||
rrmodes[nmode++] = rrmode;
|
||||
npreferred += p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -940,6 +940,7 @@ i830_sdvo_init(ScrnInfoPtr pScrn, int output_device)
|
|||
output->pre_set_mode = i830_sdvo_pre_set_mode;
|
||||
output->post_set_mode = i830_sdvo_post_set_mode;
|
||||
output->detect = i830_sdvo_detect;
|
||||
output->get_modes = i830_ddc_get_modes;
|
||||
|
||||
/* While it's the same bus, we just initialize a new copy to avoid trouble
|
||||
* with tracking refcounting ourselves, since the XFree86 DDX bits don't.
|
||||
|
|
|
|||
|
|
@ -417,6 +417,18 @@ i830_tv_detect(ScrnInfoPtr pScrn, I830OutputPtr output)
|
|||
return OUTPUT_STATUS_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stub get_modes function.
|
||||
*
|
||||
* This should probably return a set of fixed modes, unless we can figure out
|
||||
* how to probe modes off of TV connections.
|
||||
*/
|
||||
DisplayModePtr
|
||||
i830_tv_get_modes(ScrnInfoPtr pScrn, I830OutputPtr output)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
i830_tv_init(ScrnInfoPtr pScrn)
|
||||
{
|
||||
|
|
@ -438,6 +450,7 @@ i830_tv_init(ScrnInfoPtr pScrn)
|
|||
pI830->output[pI830->num_outputs].pre_set_mode = i830_tv_pre_set_mode;
|
||||
pI830->output[pI830->num_outputs].post_set_mode = i830_tv_post_set_mode;
|
||||
pI830->output[pI830->num_outputs].detect = i830_tv_detect;
|
||||
pI830->output[pI830->num_outputs].get_modes = i830_tv_get_modes;
|
||||
|
||||
pI830->num_outputs++;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue