summaryrefslogtreecommitdiff
path: root/src/r128_driver.c
diff options
context:
space:
mode:
authorHenry Zhao <henryz@localhost.localdomain>2006-08-31 13:27:45 -0700
committerHenry Zhao <henryz@localhost.localdomain>2006-08-31 13:27:45 -0700
commitcaaed927a07ffbac68b08246185ef93c1e7bb98c (patch)
treeaea16f7c06f4aeea62f2cd909c6970b4b991a26e /src/r128_driver.c
parent6d2028b84ff2b82c849b74776258f8e52c952e36 (diff)
* [ Bug 6966 ] large negative refresh rates reported
* [ Bug 6309 ] radeon/r128 fails to read hsync/vsync rates when rang * descriptor is missing * [ Bug 5473 ] Blank screen with Radeon Mobility X700 (Acer Ferrari 4005) * Reboot should not be needed for external CRT to function when connected later on Ferrari 4000 * Modes need to be sorted, and sorted correctly * Provide all resolutions (instead only the largest one) in MergedFB clone mode without config file * Bump up clock rate for ES1000 to allow higher resolution
Diffstat (limited to 'src/r128_driver.c')
-rw-r--r--src/r128_driver.c275
1 files changed, 157 insertions, 118 deletions
diff --git a/src/r128_driver.c b/src/r128_driver.c
index 49c0d86..ce2f978 100644
--- a/src/r128_driver.c
+++ b/src/r128_driver.c
@@ -1529,127 +1529,166 @@ static Bool R128GetDFPInfo(ScrnInfoPtr pScrn)
static void R128SetSyncRangeFromEdid(ScrnInfoPtr pScrn, int flag)
{
- int i;
- xf86MonPtr ddc = pScrn->monitor->DDC;
- if(flag) /*HSync*/
- {
- for(i=0; i<4; i++)
- {
- if(ddc->det_mon[i].type == DS_RANGES)
- {
- pScrn->monitor->nHsync = 1;
- pScrn->monitor->hsync[0].lo =
- ddc->det_mon[i].section.ranges.min_h;
- pScrn->monitor->hsync[0].hi =
- ddc->det_mon[i].section.ranges.max_h;
- return;
- }
- }
- /*if no sync ranges detected in detailed timing table,
- let's try to derive them from supported VESA modes
- Are we doing too much here!!!?
- **/
- i = 0;
- if(ddc->timings1.t1 & 0x02) /*800x600@56*/
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 35.2;
- i++;
- }
- if(ddc->timings1.t1 & 0x04) /*640x480@75*/
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 37.5;
- i++;
- }
- if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t1 & 0x01))
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 37.9;
- i++;
- }
- if(ddc->timings1.t2 & 0x40)
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 46.9;
- i++;
- }
- if((ddc->timings1.t2 & 0x80) || (ddc->timings1.t2 & 0x08))
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 48.1;
- i++;
- }
- if(ddc->timings1.t2 & 0x04)
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 56.5;
- i++;
- }
- if(ddc->timings1.t2 & 0x02)
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 60.0;
- i++;
- }
- if(ddc->timings1.t2 & 0x01)
- {
- pScrn->monitor->hsync[i].lo =
- pScrn->monitor->hsync[i].hi = 64.0;
- i++;
- }
- pScrn->monitor->nHsync = i;
- }
- else /*Vrefresh*/
- {
- for(i=0; i<4; i++)
- {
- if(ddc->det_mon[i].type == DS_RANGES)
- {
- pScrn->monitor->nVrefresh = 1;
- pScrn->monitor->vrefresh[0].lo =
- ddc->det_mon[i].section.ranges.min_v;
- pScrn->monitor->vrefresh[0].hi =
- ddc->det_mon[i].section.ranges.max_v;
- return;
- }
- }
- i = 0;
- if(ddc->timings1.t1 & 0x02) /*800x600@56*/
- {
- pScrn->monitor->vrefresh[i].lo =
- pScrn->monitor->vrefresh[i].hi = 56;
- i++;
- }
- if((ddc->timings1.t1 & 0x01) || (ddc->timings1.t2 & 0x08))
- {
- pScrn->monitor->vrefresh[i].lo =
- pScrn->monitor->vrefresh[i].hi = 60;
- i++;
- }
- if(ddc->timings1.t2 & 0x04)
- {
- pScrn->monitor->vrefresh[i].lo =
- pScrn->monitor->vrefresh[i].hi = 70;
- i++;
- }
- if((ddc->timings1.t1 & 0x08) || (ddc->timings1.t2 & 0x80))
- {
- pScrn->monitor->vrefresh[i].lo =
- pScrn->monitor->vrefresh[i].hi = 72;
- i++;
- }
- if((ddc->timings1.t1 & 0x04) || (ddc->timings1.t2 & 0x40)
- || (ddc->timings1.t2 & 0x02) || (ddc->timings1.t2 & 0x01))
- {
- pScrn->monitor->vrefresh[i].lo =
- pScrn->monitor->vrefresh[i].hi = 75;
- i++;
- }
- pScrn->monitor->nVrefresh = i;
+ MonPtr monitor = pScrn->monitor;
+ xf86MonPtr DDC = (xf86MonPtr)(pScrn->monitor->DDC);
+ int i, j;
+ float hmin = 1e6, hmax = 0.0, vmin = 1e6, vmax = 0.0;
+ float h, v;
+ struct std_timings *t;
+ struct detailed_timings *dt;
+ struct monitor_ranges *mon_range = NULL;
+ int numTimings = 0;
+ range hsync[MAX_HSYNC];
+ range vrefresh[MAX_VREFRESH];
+
+ numTimings = 0;
+
+ if (flag) { /* Hsync */
+ for (i = 0; i < DET_TIMINGS; i++) {
+ switch (DDC->det_mon[i].type) {
+ case DS_RANGES:
+ mon_range = &DDC->det_mon[i].section.ranges;
+ hsync[numTimings].lo = mon_range->min_h;
+ hsync[numTimings].hi = mon_range->max_h;
+ numTimings++;
+ break;
+
+ case DS_STD_TIMINGS:
+ t = DDC->det_mon[i].section.std_t;
+ for (j = 0; j < 5; j++) {
+ if (t[j].hsize > 256) { /* sanity check */
+ h = t[j].refresh * 1.07 * t[j].vsize / 1000.0;
+ if (h < hmin)
+ hmin = h;
+ if (h > hmax)
+ hmax = h;
+ }
+ }
+ break;
+
+ case DT:
+ dt = &DDC->det_mon[i].section.d_timings;
+ if (dt->clock > 15000000) { /* sanity check */
+ h = (float)dt->clock / (dt->h_active + dt->h_blanking);
+ h /= 1000.0;
+ if (h < hmin)
+ hmin = h;
+ if (h > hmax)
+ hmax = h;
+ }
+ break;
+ }
+
+ if (numTimings > MAX_HSYNC)
+ break;
+ }
+
+ if (numTimings == 0) {
+ t = DDC->timings2;
+ for (i = 0; i < STD_TIMINGS; i++) {
+ if (t[i].hsize > 256) { /* sanity check */
+ h = t[i].refresh * 1.07 * t[i].vsize / 1000.0;
+ if (h < hmin)
+ hmin = h;
+ if (h > hmax)
+ hmax = h;
+ }
+ }
+
+ if (hmax > 0.0) {
+ hsync[numTimings].lo = hmin;
+ hsync[numTimings].hi = hmax;
+ numTimings++;
+ }
+ }
+
+ if (numTimings > 0) {
+ monitor->nHsync = numTimings;
+ for (i = 0; i < numTimings; i++) {
+ monitor->hsync[i].lo = hsync[i].lo;
+ monitor->hsync[i].hi = hsync[i].hi;
+ }
+ } else {
+ pScrn->monitor->hsync[0].lo = 28;
+ pScrn->monitor->hsync[0].hi = 60;
+ monitor->nHsync = 1;
+ }
+
+ } else { /* Vrefresh */
+ for (i = 0; i < DET_TIMINGS; i++) {
+ switch (DDC->det_mon[i].type) {
+ case DS_RANGES:
+ mon_range = &DDC->det_mon[i].section.ranges;
+ vrefresh[numTimings].lo = mon_range->min_v;
+ vrefresh[numTimings].hi = mon_range->max_v;
+ numTimings++;
+ break;
+
+ case DS_STD_TIMINGS:
+ t = DDC->det_mon[i].section.std_t;
+ for (j = 0; j < 5; j++) {
+ if (t[j].hsize > 256) { /* sanity check */
+ if (t[j].refresh < vmin)
+ vmin = t[i].refresh;
+ if (t[j].refresh > vmax)
+ vmax = t[i].refresh;
+ }
+ }
+ break;
+
+ case DT:
+ dt = &DDC->det_mon[i].section.d_timings;
+ if (dt->clock > 15000000) { /* sanity check */
+ h = (float)dt->clock / (dt->h_active + dt->h_blanking);
+ v = h / (dt->v_active + dt->v_blanking);
+ if (dt->interlaced)
+ v /= 2.0;
+
+ if (v < vmin)
+ vmin = v;
+ if (v > vmax)
+ vmax = v;
+ }
+ break;
+ }
+
+ if (numTimings > MAX_HSYNC)
+ break;
+ }
+
+ if (numTimings == 0) {
+ t = DDC->timings2;
+ for (i = 0; i < STD_TIMINGS; i++) {
+ if (t[i].hsize > 256) { /* sanity check */
+ if (t[i].refresh < vmin)
+ vmin = t[i].refresh;
+ if (t[i].refresh > vmax)
+ vmax = t[i].refresh;
+ }
+ }
+
+ if (vmax > 0.0) {
+ vrefresh[numTimings].lo = vmin;
+ vrefresh[numTimings].hi = vmax;
+ numTimings++;
+ }
+ }
+
+ if (numTimings > 0) {
+ monitor->nVrefresh = numTimings;
+ for (i = 0; i < numTimings; i++) {
+ monitor->vrefresh[i].lo = vrefresh[i].lo;
+ monitor->vrefresh[i].hi = vrefresh[i].hi;
+ }
+ } else {
+ pScrn->monitor->vrefresh[0].lo = 43;
+ pScrn->monitor->vrefresh[0].hi = 72;
+ monitor->nVrefresh = 1;
+ }
}
}
+
/***********
xfree's xf86ValidateModes routine deosn't work well with DFPs
here is our own validation routine. All modes between