summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2006-10-31 17:10:08 -0800
committerEric Anholt <eric@anholt.net>2006-10-31 17:10:08 -0800
commit7195dfabd56239f08cdd8175a2ef3a66ef9600de (patch)
treec83545579654d375332e01d19a4a79e8604b00a9 /src
parentcc3728be2481637dda321d3bc2e4e89a220699cd (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/i830.h15
-rw-r--r--src/i830_crt.c1
-rw-r--r--src/i830_dvo.c1
-rw-r--r--src/i830_lvds.c5
-rw-r--r--src/i830_modes.c33
-rw-r--r--src/i830_randr.c84
-rw-r--r--src/i830_sdvo.c1
-rw-r--r--src/i830_tv.c13
8 files changed, 112 insertions, 41 deletions
diff --git a/src/i830.h b/src/i830.h
index 27a9817b..5915a178 100644
--- a/src/i830.h
+++ b/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);
diff --git a/src/i830_crt.c b/src/i830_crt.c
index d271eedb..bd0099ac 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -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,
diff --git a/src/i830_dvo.c b/src/i830_dvo.c
index ed21ecc5..c788e4f4 100644
--- a/src/i830_dvo.c
+++ b/src/i830_dvo.c
@@ -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");
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index e0e471ff..4b899033 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -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.
diff --git a/src/i830_modes.c b/src/i830_modes.c
index 130b7fe5..1ba1defb 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -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;
+}
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 23ffaf6c..a1c4b12c 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -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.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;
- }
+ 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;
+
+ rrmode = RRModeGet (pScreen, &modeInfo, mode->name);
+ rrmode->devPrivate = mode;
+ if (rrmode) {
+ rrmodes[nmode++] = rrmode;
+ npreferred += p;
}
}
}
diff --git a/src/i830_sdvo.c b/src/i830_sdvo.c
index 3932ea65..b6a3d676 100644
--- a/src/i830_sdvo.c
+++ b/src/i830_sdvo.c
@@ -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.
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 3e728822..47c0d03b 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -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++;
}