diff options
Diffstat (limited to 'xorg-server/hw/xfree86')
30 files changed, 1577 insertions, 743 deletions
diff --git a/xorg-server/hw/xfree86/Makefile.am b/xorg-server/hw/xfree86/Makefile.am index 159b935cf..914e11fa1 100644 --- a/xorg-server/hw/xfree86/Makefile.am +++ b/xorg-server/hw/xfree86/Makefile.am @@ -92,7 +92,8 @@ if SOLARIS_ASM_INLINE BUILT_SOURCES += os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il os-support/solaris/solaris-@SOLARIS_INOUT_ARCH@.il: - cd os-support/solaris ; make solaris-@SOLARIS_INOUT_ARCH@.il + cd os-support/solaris ; \ + $(MAKE) $(AM_MAKEFLAGS) solaris-@SOLARIS_INOUT_ARCH@.il endif # do not use $(mkdir_p) if you want automake 1.7 to work diff --git a/xorg-server/hw/xfree86/common/xf86Configure.c b/xorg-server/hw/xfree86/common/xf86Configure.c index 3b7828a3f..2df6b4ec3 100644 --- a/xorg-server/hw/xfree86/common/xf86Configure.c +++ b/xorg-server/hw/xfree86/common/xf86Configure.c @@ -544,6 +544,36 @@ configureMonitorSection (int screennum) return ptr; } +/* Initialize Configure Monitor from Detailed Timing Block */ +static void handle_detailed_input(struct detailed_monitor_section *det_mon, + void *data) +{ + XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data; + + switch (det_mon->type) { + case DS_NAME: + ptr->mon_modelname = realloc(ptr->mon_modelname, + strlen((char*)(det_mon->section.name)) + + 1); + strcpy(ptr->mon_modelname, + (char*)(det_mon->section.name)); + break; + case DS_RANGES: + ptr->mon_hsync[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_h; + ptr->mon_hsync[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_h; + ptr->mon_n_vrefresh = 1; + ptr->mon_vrefresh[ptr->mon_n_hsync].lo = + det_mon->section.ranges.min_v; + ptr->mon_vrefresh[ptr->mon_n_hsync].hi = + det_mon->section.ranges.max_v; + ptr->mon_n_hsync++; + default: + break; + } +} + static XF86ConfMonitorPtr configureDDCMonitorSection (int screennum) { @@ -590,30 +620,8 @@ configureDDCMonitorSection (int screennum) } #endif /* def CONFIGURE_DISPLAYSIZE */ - for (i=0;i<4;i++) { - switch (ConfiguredMonitor->det_mon[i].type) { - case DS_NAME: - ptr->mon_modelname = realloc(ptr->mon_modelname, - strlen((char*)(ConfiguredMonitor->det_mon[i].section.name)) - + 1); - strcpy(ptr->mon_modelname, - (char*)(ConfiguredMonitor->det_mon[i].section.name)); - break; - case DS_RANGES: - ptr->mon_hsync[ptr->mon_n_hsync].lo = - ConfiguredMonitor->det_mon[i].section.ranges.min_h; - ptr->mon_hsync[ptr->mon_n_hsync].hi = - ConfiguredMonitor->det_mon[i].section.ranges.max_h; - ptr->mon_n_vrefresh = 1; - ptr->mon_vrefresh[ptr->mon_n_hsync].lo = - ConfiguredMonitor->det_mon[i].section.ranges.min_v; - ptr->mon_vrefresh[ptr->mon_n_hsync].hi = - ConfiguredMonitor->det_mon[i].section.ranges.max_v; - ptr->mon_n_hsync++; - default: - break; - } - } + xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, + ptr); if (ConfiguredMonitor->features.dpms) { ptr->mon_option_lst = xf86addNewOption(ptr->mon_option_lst, xstrdup("DPMS"), NULL); diff --git a/xorg-server/hw/xfree86/common/xf86Events.c b/xorg-server/hw/xfree86/common/xf86Events.c index 9487fe7b2..8cd765a1c 100644 --- a/xorg-server/hw/xfree86/common/xf86Events.c +++ b/xorg-server/hw/xfree86/common/xf86Events.c @@ -263,13 +263,14 @@ xf86Wakeup(pointer blockData, int err, pointer pReadmask) (FD_ISSET(pInfo->fd, &devicesWithInput) != 0)) { int sigstate = xf86BlockSIGIO(); - pInfo->read_input(pInfo); - xf86UnblockSIGIO(sigstate); /* * Remove the descriptior from the set because more than one * device may share the same file descriptor. */ FD_CLR(pInfo->fd, &devicesWithInput); + + pInfo->read_input(pInfo); + xf86UnblockSIGIO(sigstate); } pInfo = pInfo->next; } diff --git a/xorg-server/hw/xfree86/common/xf86Init.c b/xorg-server/hw/xfree86/common/xf86Init.c index c9baff3ef..2d682aaa9 100644 --- a/xorg-server/hw/xfree86/common/xf86Init.c +++ b/xorg-server/hw/xfree86/common/xf86Init.c @@ -97,6 +97,7 @@ static Bool add_matching_devices_to_configure_list(DriverPtr drvp); #ifdef XF86PM void (*xf86OSPMClose)(void) = NULL; #endif +static Bool xorgHWOpenConsole = FALSE; /* Common pixmap formats */ @@ -601,8 +602,6 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) if (xf86DoShowOptions) DoShowOptions(); - xf86OpenConsole(); - /* Do a general bus probe. This will be a PCI probe for x86 platforms */ xf86BusProbe(); @@ -676,20 +675,29 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) */ for (i = 0; i < xf86NumDrivers; i++) { - xorgHWFlags flags; - if (xf86DriverList[i]->Identify != NULL) xf86DriverList[i]->Identify(0); - if (!xorgHWAccess - && (!xf86DriverList[i]->driverFunc + if (!xorgHWAccess || !xorgHWOpenConsole) { + xorgHWFlags flags; + if(!xf86DriverList[i]->driverFunc || !xf86DriverList[i]->driverFunc(NULL, GET_REQUIRED_HW_INTERFACES, - &flags) - || NEED_IO_ENABLED(flags))) - xorgHWAccess = TRUE; + &flags)) + flags = HW_IO; + + if(NEED_IO_ENABLED(flags)) + xorgHWAccess = TRUE; + if(!(flags & HW_SKIP_CONSOLE)) + xorgHWOpenConsole = TRUE; + } } + if (xorgHWOpenConsole) + xf86OpenConsole(); + else + xf86Info.dontVTSwitch = TRUE; + /* Enable full I/O access */ if (xorgHWAccess) xorgHWAccess = xf86EnableIO(); @@ -966,7 +974,8 @@ InitOutput(ScreenInfo *pScreenInfo, int argc, char **argv) /* * serverGeneration != 1; some OSs have to do things here, too. */ - xf86OpenConsole(); + if (xorgHWOpenConsole) + xf86OpenConsole(); #ifdef XF86PM /* @@ -1203,7 +1212,8 @@ ddxGiveUp(void) DGAShutdown(); #endif - xf86CloseConsole(); + if (xorgHWOpenConsole) + xf86CloseConsole(); xf86CloseLog(); diff --git a/xorg-server/hw/xfree86/common/xf86Mode.c b/xorg-server/hw/xfree86/common/xf86Mode.c index 0e43946c5..4a948d752 100644 --- a/xorg-server/hw/xfree86/common/xf86Mode.c +++ b/xorg-server/hw/xfree86/common/xf86Mode.c @@ -249,6 +249,15 @@ xf86ShowClockRanges(ScrnInfoPtr scrp, ClockRangePtr clockRanges) } } +static Bool +modeInClockRange(ClockRangePtr cp, DisplayModePtr p) +{ + return ((p->Clock >= cp->minClock) && + (p->Clock <= cp->maxClock) && + (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) && + (cp->doubleScanAllowed || + ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN)))); +} /* * xf86FindClockRangeForMode() [... like the name says ...] @@ -259,12 +268,7 @@ xf86FindClockRangeForMode(ClockRangePtr clockRanges, DisplayModePtr p) ClockRangePtr cp; for (cp = clockRanges; ; cp = cp->next) - if (!cp || - ((p->Clock >= cp->minClock) && - (p->Clock <= cp->maxClock) && - (cp->interlaceAllowed || !(p->Flags & V_INTERLACE)) && - (cp->doubleScanAllowed || - ((p->VScan <= 1) && !(p->Flags & V_DBLSCAN))))) + if (!cp || modeInClockRange(cp, p)) return cp; } @@ -979,11 +983,7 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) if (scrp->progClock) { /* Check clock is in range */ for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { - if ((cp->minClock <= mode->Clock) && - (cp->maxClock >= mode->Clock) && - (cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) && - (cp->doubleScanAllowed || - ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1)))) + if (modeInClockRange(cp, mode)) break; } if (cp == NULL) { @@ -999,12 +999,7 @@ xf86CheckModeForDriver(ScrnInfoPtr scrp, DisplayModePtr mode, int flags) status = MODE_CLOCK_RANGE; /* Check clock is in range */ for (cp = scrp->clockRanges; cp != NULL; cp = cp->next) { - if ((cp->minClock <= mode->Clock) && - (cp->maxClock >= mode->Clock) && - (cp->interlaceAllowed || !(mode->Flags & V_INTERLACE)) && - (cp->doubleScanAllowed || - ((!(mode->Flags & V_DBLSCAN)) && (mode->VScan <= 1)))) { - + if (modeInClockRange(cp, mode)) { /* * Clock is in range, so if it is not a programmable clock, * find a matching clock. diff --git a/xorg-server/hw/xfree86/common/xf86Xinput.c b/xorg-server/hw/xfree86/common/xf86Xinput.c index fd07c2a06..f637cfe19 100644 --- a/xorg-server/hw/xfree86/common/xf86Xinput.c +++ b/xorg-server/hw/xfree86/common/xf86Xinput.c @@ -113,7 +113,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, return; /* common settings (available via device properties) */ - tempf = xf86SetIntOption(list, "ConstantDeceleration", 1); + tempf = xf86SetRealOption(list, "ConstantDeceleration", 1.0); if(tempf > 1.0){ xf86Msg(X_CONFIG, "%s: (accel) constant deceleration by %.1f\n", devname, tempf); @@ -122,7 +122,7 @@ ProcessVelocityConfiguration(DeviceIntPtr pDev, char* devname, pointer list, PropModeReplace, 1, &tempf, FALSE); } - tempf = xf86SetIntOption(list, "AdaptiveDeceleration", 1); + tempf = xf86SetRealOption(list, "AdaptiveDeceleration", 1.0); if(tempf > 1.0){ xf86Msg(X_CONFIG, "%s: (accel) adaptive deceleration by %.1f\n", devname, tempf); @@ -726,12 +726,15 @@ xf86PostMotionEventP(DeviceIntPtr device, int *valuators) { int i = 0, nevents = 0; - int dx = 0, dy = 0; Bool drag = xf86SendDragEvents(device); DeviceEvent *event; - int index; int flags = 0; +#if XFreeXDGA + int index; + int dx = 0, dy = 0; +#endif + XI_VERIFY_VALUATORS(num_valuators); if (is_absolute) @@ -856,9 +859,12 @@ xf86PostButtonEventP(DeviceIntPtr device, int *valuators) { int i = 0, nevents = 0; - int index; int flags = 0; +#if XFreeXDGA + int index; +#endif + XI_VERIFY_VALUATORS(num_valuators); if (is_absolute) diff --git a/xorg-server/hw/xfree86/common/xf86cmap.c b/xorg-server/hw/xfree86/common/xf86cmap.c index 36e6f96de..08f557ccd 100644 --- a/xorg-server/hw/xfree86/common/xf86cmap.c +++ b/xorg-server/hw/xfree86/common/xf86cmap.c @@ -115,7 +115,9 @@ static void CMapDestroyColormap (ColormapPtr); static Bool CMapEnterVT(int, int); static Bool CMapSwitchMode(int, DisplayModePtr, int); +#ifdef XFreeXDGA static int CMapSetDGAMode(int, int, DGADevicePtr); +#endif static int CMapChangeGamma(int, Gamma); static void ComputeGamma(CMapScreenPtr); diff --git a/xorg-server/hw/xfree86/common/xf86str.h b/xorg-server/hw/xfree86/common/xf86str.h index b9a2e06de..7b0b758d4 100644 --- a/xorg-server/hw/xfree86/common/xf86str.h +++ b/xorg-server/hw/xfree86/common/xf86str.h @@ -299,6 +299,7 @@ typedef struct { /* GET_REQUIRED_HW_INTERFACES */ #define HW_IO 1 #define HW_MMIO 2 +#define HW_SKIP_CONSOLE 4 #define NEED_IO_ENABLED(x) (x & HW_IO) typedef CARD32 xorgHWFlags; diff --git a/xorg-server/hw/xfree86/ddc/edid.h b/xorg-server/hw/xfree86/ddc/edid.h index 3feb9796f..cc4bd02ea 100644 --- a/xorg-server/hw/xfree86/ddc/edid.h +++ b/xorg-server/hw/xfree86/ddc/edid.h @@ -562,4 +562,101 @@ typedef struct { extern _X_EXPORT xf86MonPtr ConfiguredMonitor; +#define EXT_TAG 0 +#define EXT_REV 1 +#define CEA_EXT 0x02 +#define VTB_EXT 0x10 +#define DI_EXT 0x40 +#define LS_EXT 0x50 +#define MI_EXT 0x60 + +#define CEA_EXT_MIN_DATA_OFFSET 4 +#define CEA_EXT_MAX_DATA_OFFSET 127 +#define CEA_EXT_DET_TIMING_NUM 6 + +#define IEEE_ID_HDMI 0x000C03 +#define CEA_AUDIO_BLK 1 +#define CEA_VIDEO_BLK 2 +#define CEA_VENDOR_BLK 3 +#define CEA_SPEAKER_ALLOC_BLK 4 +#define CEA_VESA_DTC_BLK 5 +#define VENDOR_SUPPORT_AI(x) ((x) >> 7) +#define VENDOR_SUPPORT_DC_48bit(x) ( ( (x) >> 6) & 0x01) +#define VENDOR_SUPPORT_DC_36bit(x) ( ( (x) >> 5) & 0x01) +#define VENDOR_SUPPORT_DC_30bit(x) ( ( (x) >> 4) & 0x01) +#define VENDOR_SUPPORT_DC_Y444(x) ( ( (x) >> 3) & 0x01) +#define VENDOR_LATENCY_PRESENT(x) ( (x) >> 7) +#define VENDOR_LATENCY_PRESENT_I(x) ( ( (x) >> 6) & 0x01) +#define HDMI_MAX_TMDS_UNIT (5000) + +struct cea_video_block { + Uchar video_code; +}; + +struct cea_audio_block_descriptor { + Uchar audio_code[3]; +}; + +struct cea_audio_block { + struct cea_audio_block_descriptor descriptor[10]; +}; + +struct cea_vendor_block_hdmi { + Uchar portB:4; + Uchar portA:4; + Uchar portD:4; + Uchar portC:4; + Uchar support_flags; + Uchar max_tmds_clock; + Uchar latency_present; + Uchar video_latency; + Uchar audio_latency; + Uchar interlaced_video_latency; + Uchar interlaced_audio_latency; +}; + +struct cea_vendor_block { + unsigned char ieee_id[3]; + union { + struct cea_vendor_block_hdmi hdmi; + /* any other vendor blocks we know about */ + }; +}; + +struct cea_speaker_block +{ + Uchar FLR:1; + Uchar LFE:1; + Uchar FC:1; + Uchar RLR:1; + Uchar RC:1; + Uchar FLRC:1; + Uchar RLRC:1; + Uchar FLRW:1; + Uchar FLRH:1; + Uchar TC:1; + Uchar FCH:1; + Uchar Resv:5; + Uchar ResvByte; +}; + +struct cea_data_block { + Uchar len:5; + Uchar tag:3; + union{ + struct cea_video_block video; + struct cea_audio_block audio; + struct cea_vendor_block vendor; + struct cea_speaker_block speaker; + }u; +}; + +struct cea_ext_body { + Uchar tag; + Uchar rev; + Uchar dt_offset; + Uchar flags; + struct cea_data_block data_collection; +}; + #endif /* _EDID_H_ */ diff --git a/xorg-server/hw/xfree86/ddc/interpret_edid.c b/xorg-server/hw/xfree86/ddc/interpret_edid.c index 12a52545e..f3e593aec 100644 --- a/xorg-server/hw/xfree86/ddc/interpret_edid.c +++ b/xorg-server/hw/xfree86/ddc/interpret_edid.c @@ -42,6 +42,8 @@ static void get_display_section(Uchar*, struct disp_features *, static void get_established_timing_section(Uchar*, struct established_timings *); static void get_std_timing_section(Uchar*, struct std_timings *, struct edid_version *); +static void fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon); static void get_dt_md_section(Uchar *, struct edid_version *, struct detailed_monitor_section *det_mon); static void copy_string(Uchar *, Uchar *); @@ -53,11 +55,25 @@ static void get_detailed_timing_section(Uchar*, struct detailed_timings *); static Bool validate_version(int scrnIndex, struct edid_version *); static void +find_ranges_section(struct detailed_monitor_section *det, void *ranges) +{ + if (det->type == DS_RANGES && det->section.ranges.max_clock) + *(struct monitor_ranges **)ranges = &det->section.ranges; +} + +static void +find_max_detailed_clock(struct detailed_monitor_section *det, void *ret) +{ + if (det->type == DT) { + *(int *)ret = max(*((int *)ret), + det->section.d_timings.clock); + } +} + +static void handle_edid_quirks(xf86MonPtr m) { - int i, j; - struct detailed_timings *preferred_timing; - struct monitor_ranges *ranges; + struct monitor_ranges *ranges = NULL; /* * max_clock is only encoded in EDID in tens of MHz, so occasionally we @@ -65,28 +81,49 @@ handle_edid_quirks(xf86MonPtr m) * similar. Strictly we should refuse to round up too far, but let's * see how well this works. */ - for (i = 0; i < 4; i++) { - if (m->det_mon[i].type == DS_RANGES) { - ranges = &m->det_mon[i].section.ranges; - for (j = 0; j < 4; j++) { - if (m->det_mon[j].type == DT) { - preferred_timing = &m->det_mon[j].section.d_timings; - if (!ranges->max_clock) continue; /* zero is legal */ - if (ranges->max_clock * 1000000 < preferred_timing->clock) { - xf86Msg(X_WARNING, - "EDID preferred timing clock %.2fMHz exceeds " - "claimed max %dMHz, fixing\n", - preferred_timing->clock / 1.0e6, - ranges->max_clock); - ranges->max_clock = - (preferred_timing->clock+999999)/1000000; - return; - } - } - } - } + + /* Try to find Monitor Range and max clock, then re-set range value*/ + xf86ForEachDetailedBlock(m, find_ranges_section, &ranges); + if (ranges && ranges->max_clock) { + int clock = 0; + xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock); + if (clock && (ranges->max_clock * 1e6 < clock)) { + xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max " + "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock); + ranges->max_clock = (clock+999999)/1e6; + } + } +} + +struct det_hv_parameter { + int real_hsize; + int real_vsize; + float target_aspect; +}; + +static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon, + void *data) +{ + struct det_hv_parameter *p = (struct det_hv_parameter *)data; + float timing_aspect; + + if (det_mon->type == DT) { + struct detailed_timings *timing; + timing = &det_mon->section.d_timings; + + if (!timing->v_size) + return; + + timing_aspect = (float)timing->h_size / timing->v_size; + if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) { + p->real_hsize = max(p->real_hsize, timing->h_size); + p->real_vsize = max(p->real_vsize, timing->v_size); + } } +} +static void encode_aspect_ratio(xf86MonPtr m) +{ /* * some monitors encode the aspect ratio instead of the physical size. * try to find the largest detailed timing that matches that aspect @@ -96,38 +133,26 @@ handle_edid_quirks(xf86MonPtr m) (m->features.hsize == 16 && m->features.vsize == 10) || (m->features.hsize == 4 && m->features.vsize == 3) || (m->features.hsize == 5 && m->features.vsize == 4)) { - int real_hsize = 0, real_vsize = 0; - float target_aspect, timing_aspect; - - target_aspect = (float)m->features.hsize / (float)m->features.vsize; - for (i = 0; i < 4; i++) { - if (m->det_mon[i].type == DT) { - struct detailed_timings *timing; - timing = &m->det_mon[i].section.d_timings; - - if (!timing->v_size) - continue; - - timing_aspect = (float)timing->h_size / (float)timing->v_size; - if (fabs(1 - (timing_aspect / target_aspect)) < 0.05) { - real_hsize = max(real_hsize, timing->h_size); - real_vsize = max(real_vsize, timing->v_size); - } - } - } - if (!real_hsize || !real_vsize) { + struct det_hv_parameter p; + p.real_hsize = 0; + p.real_vsize = 0; + p.target_aspect = (float)m->features.hsize /m->features.vsize; + + xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p); + + if (!p.real_hsize || !p.real_vsize) { m->features.hsize = m->features.vsize = 0; - } else if ((m->features.hsize * 10 == real_hsize) && - (m->features.vsize * 10 == real_vsize)) { + } else if ((m->features.hsize * 10 == p.real_hsize) && + (m->features.vsize * 10 == p.real_vsize)) { /* exact match is just unlikely, should do a better check though */ m->features.hsize = m->features.vsize = 0; } else { /* convert mm to cm */ - m->features.hsize = (real_hsize + 5) / 10; - m->features.vsize = (real_vsize + 5) / 10; + m->features.hsize = (p.real_hsize + 5) / 10; + m->features.vsize = (p.real_vsize + 5) / 10; } - + xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n", m->features.hsize, m->features.vsize); } @@ -156,6 +181,7 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) m->no_sections = (int)*(char *)SECTION(NO_EDID,block); handle_edid_quirks(m); + encode_aspect_ratio(m); return (m); @@ -164,6 +190,141 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) return NULL; } +static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon, + struct detailed_monitor_section *det_mon) +{ + int dt_num; + int dt_offset = ((struct cea_ext_body *)blk)->dt_offset; + + dt_num = 0; + + if (dt_offset < CEA_EXT_MIN_DATA_OFFSET) + return dt_num; + + for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) && + dt_num < CEA_EXT_DET_TIMING_NUM; + _NEXT_DT_MD_SECTION(dt_offset)) { + + fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num); + dt_num = dt_num + 1 ; + } + + return dt_num; +} + +static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM]; + int det_mon_num; + + det_mon_num = get_cea_detail_timing(ext, mon, det_mon); + + for (i = 0; i < det_mon_num; i++) + fn(det_mon + i, data); +} + +void xf86ForEachDetailedBlock(xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < DET_TIMINGS; i++) + fn(mon->det_mon + i, data); + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]){ + case CEA_EXT: + handle_cea_detail_block(ext, mon, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + +static struct cea_data_block * +extract_cea_data_block(Uchar *ext, int data_type) +{ + struct cea_ext_body *cea; + struct cea_data_block *data_collection; + struct cea_data_block *data_end; + + cea = (struct cea_ext_body *)ext; + + if (cea->dt_offset <= CEA_EXT_MIN_DATA_OFFSET) + return NULL; + + data_collection = &cea->data_collection; + data_end = (struct cea_data_block *)(cea->dt_offset + ext); + + for ( ;data_collection < data_end;) { + + if (data_type == data_collection->tag) { + return data_collection; + } + data_collection = (void *)((unsigned char *)data_collection + + data_collection->len + 1); + } + + return NULL; +} + +static void handle_cea_video_block(Uchar *ext, handle_video_fn fn, void *data) +{ + struct cea_video_block *video; + struct cea_video_block *video_end; + struct cea_data_block *data_collection; + + data_collection = extract_cea_data_block(ext, CEA_VIDEO_BLK); + if (data_collection == NULL) + return; + + video = &data_collection->u.video; + video_end = (struct cea_video_block *) + ((Uchar *)video + data_collection->len); + + for (; video < video_end; video = video + 1) { + fn(video, data); + } +} + +void xf86ForEachVideoBlock(xf86MonPtr mon, + handle_video_fn fn, + void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]) { + case CEA_EXT: + handle_cea_video_block(ext, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + xf86MonPtr xf86InterpretEEDID(int scrnIndex, Uchar *block) { @@ -288,66 +449,72 @@ get_std_timing_section(Uchar *c, struct std_timings *r, static const unsigned char empty_block[18]; static void -get_dt_md_section(Uchar *c, struct edid_version *ver, - struct detailed_monitor_section *det_mon) +fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) { - int i; - - for (i=0;i<DET_TIMINGS;i++) { if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { - - switch (MONITOR_DESC_TYPE) { - case SERIAL_NUMBER: - det_mon[i].type = DS_SERIAL; - copy_string(c,det_mon[i].section.serial); - break; - case ASCII_STR: - det_mon[i].type = DS_ASCII_STR; - copy_string(c,det_mon[i].section.ascii_data); - break; - case MONITOR_RANGES: - det_mon[i].type = DS_RANGES; - get_monitor_ranges(c,&det_mon[i].section.ranges); - break; - case MONITOR_NAME: - det_mon[i].type = DS_NAME; - copy_string(c,det_mon[i].section.name); - break; - case ADD_COLOR_POINT: - det_mon[i].type = DS_WHITE_P; - get_whitepoint_section(c,det_mon[i].section.wp); - break; - case ADD_STD_TIMINGS: - det_mon[i].type = DS_STD_TIMINGS; - get_dst_timing_section(c,det_mon[i].section.std_t, ver); - break; - case COLOR_MANAGEMENT_DATA: - det_mon[i].type = DS_CMD; - break; - case CVT_3BYTE_DATA: - det_mon[i].type = DS_CVT; - get_cvt_timing_section(c, det_mon[i].section.cvt); - break; - case ADD_EST_TIMINGS: - det_mon[i].type = DS_EST_III; - memcpy(det_mon[i].section.est_iii, c + 6, 6); - break; - case ADD_DUMMY: - det_mon[i].type = DS_DUMMY; - break; - default: - det_mon[i].type = DS_UNKOWN; - break; - } - if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { - det_mon[i].type = DS_VENDOR + c[3]; - } + switch (MONITOR_DESC_TYPE) { + case SERIAL_NUMBER: + det_mon->type = DS_SERIAL; + copy_string(c,det_mon->section.serial); + break; + case ASCII_STR: + det_mon->type = DS_ASCII_STR; + copy_string(c,det_mon->section.ascii_data); + break; + case MONITOR_RANGES: + det_mon->type = DS_RANGES; + get_monitor_ranges(c,&det_mon->section.ranges); + break; + case MONITOR_NAME: + det_mon->type = DS_NAME; + copy_string(c,det_mon->section.name); + break; + case ADD_COLOR_POINT: + det_mon->type = DS_WHITE_P; + get_whitepoint_section(c,det_mon->section.wp); + break; + case ADD_STD_TIMINGS: + det_mon->type = DS_STD_TIMINGS; + get_dst_timing_section(c,det_mon->section.std_t, ver); + break; + case COLOR_MANAGEMENT_DATA: + det_mon->type = DS_CMD; + break; + case CVT_3BYTE_DATA: + det_mon->type = DS_CVT; + get_cvt_timing_section(c, det_mon->section.cvt); + break; + case ADD_EST_TIMINGS: + det_mon->type = DS_EST_III; + memcpy(det_mon->section.est_iii, c + 6, 6); + break; + case ADD_DUMMY: + det_mon->type = DS_DUMMY; + break; + default: + det_mon->type = DS_UNKOWN; + break; + } + if (c[3] <= 0x0F && memcmp(c, empty_block, sizeof(empty_block))) { + det_mon->type = DS_VENDOR + c[3]; + } } else { - det_mon[i].type = DT; - get_detailed_timing_section(c,&det_mon[i].section.d_timings); + det_mon->type = DT; + get_detailed_timing_section(c, &det_mon->section.d_timings); + } +} + +static void +get_dt_md_section(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + int i; + + for (i=0; i < DET_TIMINGS; i++) { + fetch_detailed_block(c, ver, det_mon + i); + NEXT_DT_MD_SECTION; } - NEXT_DT_MD_SECTION; - } } static void diff --git a/xorg-server/hw/xfree86/ddc/print_edid.c b/xorg-server/hw/xfree86/ddc/print_edid.c index ff0b39cc1..1faae1e33 100644 --- a/xorg-server/hw/xfree86/ddc/print_edid.c +++ b/xorg-server/hw/xfree86/ddc/print_edid.c @@ -334,129 +334,147 @@ print_detailed_timings(int scrnIndex, struct detailed_timings *t) } } +/* This function handle all detailed patchs, + * including EDID and EDID-extension + */ +struct det_print_parameter{ + xf86MonPtr m; + int index; + ddc_quirk_t quirks; +}; + static void -print_detailed_monitor_section(int scrnIndex, - struct detailed_monitor_section *m) +handle_detailed_print(struct detailed_monitor_section *det_mon, + void *data) { - int i,j; - - for (i=0;i<DET_TIMINGS;i++) { - switch (m[i].type) { - case DT: - print_detailed_timings(scrnIndex,&m[i].section.d_timings); - break; - case DS_SERIAL: - xf86DrvMsg(scrnIndex,X_INFO,"Serial No: %s\n",m[i].section.serial); - break; - case DS_ASCII_STR: - xf86DrvMsg(scrnIndex,X_INFO," %s\n",m[i].section.ascii_data); - break; - case DS_NAME: - xf86DrvMsg(scrnIndex,X_INFO,"Monitor name: %s\n",m[i].section.name); - break; - case DS_RANGES: - { - struct monitor_ranges *r = &m[i].section.ranges; + int j, scrnIndex; + struct det_print_parameter *p; + + p = (struct det_print_parameter *)data; + scrnIndex = p->m->scrnIndex; + xf86DetTimingApplyQuirks(det_mon,p->quirks, + p->m->features.hsize, + p->m->features.vsize); + + switch (det_mon->type) { + case DT: + print_detailed_timings(scrnIndex,&det_mon->section.d_timings); + break; + case DS_SERIAL: + xf86DrvMsg(scrnIndex,X_INFO,"Serial No: %s\n",det_mon->section.serial); + break; + case DS_ASCII_STR: + xf86DrvMsg(scrnIndex,X_INFO," %s\n",det_mon->section.ascii_data); + break; + case DS_NAME: + xf86DrvMsg(scrnIndex,X_INFO,"Monitor name: %s\n",det_mon->section.name); + break; + case DS_RANGES: + { + struct monitor_ranges *r = &det_mon->section.ranges; + xf86DrvMsg(scrnIndex,X_INFO, + "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,", + r->min_v, r->max_v, r->min_h, r->max_h); + if (r->max_clock_khz != 0) { + xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz); + if (r->maxwidth) + xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n", + r->maxwidth); + xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:"); + if (r->supported_aspect & SUPPORTED_ASPECT_4_3) + xf86ErrorF(" 4:3%s", + r->preferred_aspect == PREFERRED_ASPECT_4_3?"*":""); + if (r->supported_aspect & SUPPORTED_ASPECT_16_9) + xf86ErrorF(" 16:9%s", + r->preferred_aspect == PREFERRED_ASPECT_16_9?"*":""); + if (r->supported_aspect & SUPPORTED_ASPECT_16_10) + xf86ErrorF(" 16:10%s", + r->preferred_aspect == PREFERRED_ASPECT_16_10?"*":""); + if (r->supported_aspect & SUPPORTED_ASPECT_5_4) + xf86ErrorF(" 5:4%s", + r->preferred_aspect == PREFERRED_ASPECT_5_4?"*":""); + if (r->supported_aspect & SUPPORTED_ASPECT_15_9) + xf86ErrorF(" 15:9%s", + r->preferred_aspect == PREFERRED_ASPECT_15_9?"*":""); + xf86ErrorF("\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:"); + if (r->supported_blanking & CVT_STANDARD) + xf86ErrorF(" standard"); + if (r->supported_blanking & CVT_REDUCED) + xf86ErrorF(" reduced"); + xf86ErrorF("\n"); + xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:"); + if (r->supported_scaling & SCALING_HSHRINK) + xf86ErrorF(" hshrink"); + if (r->supported_scaling & SCALING_HSTRETCH) + xf86ErrorF(" hstretch"); + if (r->supported_scaling & SCALING_VSHRINK) + xf86ErrorF(" vshrink"); + if (r->supported_scaling & SCALING_VSTRETCH) + xf86ErrorF(" vstretch"); + xf86ErrorF("\n"); + if (r->preferred_refresh) + xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n", + r->preferred_refresh); + else + xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred " + "refresh rate given\n"); + } else if (r->max_clock != 0) { + xf86ErrorF(" PixClock max %i MHz\n", r->max_clock); + } else { + xf86ErrorF("\n"); + } + if (r->gtf_2nd_f > 0) + xf86DrvMsg(scrnIndex,X_INFO," 2nd GTF parameters: f: %i kHz " + "c: %i m: %i k %i j %i\n", r->gtf_2nd_f, + r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, + r->gtf_2nd_j); + break; + } + case DS_STD_TIMINGS: + for (j = 0; j<5; j++) xf86DrvMsg(scrnIndex,X_INFO, - "Ranges: V min: %i V max: %i Hz, H min: %i H max: %i kHz,", - r->min_v, r->max_v, r->min_h, r->max_h); - if (r->max_clock_khz != 0) { - xf86ErrorF(" PixClock max %i kHz\n", r->max_clock_khz); - if (r->maxwidth) - xf86DrvMsg(scrnIndex, X_INFO, "Maximum pixel width: %d\n", - r->maxwidth); - xf86DrvMsg(scrnIndex, X_INFO, "Supported aspect ratios:"); - if (r->supported_aspect & SUPPORTED_ASPECT_4_3) - xf86ErrorF(" 4:3%s", - r->preferred_aspect == PREFERRED_ASPECT_4_3?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_16_9) - xf86ErrorF(" 16:9%s", - r->preferred_aspect == PREFERRED_ASPECT_16_9?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_16_10) - xf86ErrorF(" 16:10%s", - r->preferred_aspect == PREFERRED_ASPECT_16_10?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_5_4) - xf86ErrorF(" 5:4%s", - r->preferred_aspect == PREFERRED_ASPECT_5_4?"*":""); - if (r->supported_aspect & SUPPORTED_ASPECT_15_9) - xf86ErrorF(" 15:9%s", - r->preferred_aspect == PREFERRED_ASPECT_15_9?"*":""); - xf86ErrorF("\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Supported blankings:"); - if (r->supported_blanking & CVT_STANDARD) - xf86ErrorF(" standard"); - if (r->supported_blanking & CVT_REDUCED) - xf86ErrorF(" reduced"); - xf86ErrorF("\n"); - xf86DrvMsg(scrnIndex, X_INFO, "Supported scalings:"); - if (r->supported_scaling & SCALING_HSHRINK) - xf86ErrorF(" hshrink"); - if (r->supported_scaling & SCALING_HSTRETCH) - xf86ErrorF(" hstretch"); - if (r->supported_scaling & SCALING_VSHRINK) - xf86ErrorF(" vshrink"); - if (r->supported_scaling & SCALING_VSTRETCH) - xf86ErrorF(" vstretch"); - xf86ErrorF("\n"); - if (r->preferred_refresh) - xf86DrvMsg(scrnIndex, X_INFO, "Preferred refresh rate: %d\n", - r->preferred_refresh); - else - xf86DrvMsg(scrnIndex, X_INFO, "Buggy monitor, no preferred " - "refresh rate given\n"); - } else if (r->max_clock != 0) { - xf86ErrorF(" PixClock max %i MHz\n", r->max_clock); - } else { - xf86ErrorF("\n"); - } - if (r->gtf_2nd_f > 0) - xf86DrvMsg(scrnIndex,X_INFO," 2nd GTF parameters: f: %i kHz " - "c: %i m: %i k %i j %i\n", r->gtf_2nd_f, - r->gtf_2nd_c, r->gtf_2nd_m, r->gtf_2nd_k, - r->gtf_2nd_j); - break; - } - case DS_STD_TIMINGS: - for (j = 0; j<5; j++) - xf86DrvMsg(scrnIndex,X_INFO,"#%i: hsize: %i vsize %i refresh: %i " - "vid: %i\n",i,m[i].section.std_t[i].hsize, - m[i].section.std_t[j].vsize,m[i].section.std_t[j].refresh, - m[i].section.std_t[j].id); - break; - case DS_WHITE_P: - for (j = 0; j<2; j++) - if (m[i].section.wp[j].index != 0) - xf86DrvMsg(scrnIndex,X_INFO, - "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", - m[i].section.wp[j].index,m[i].section.wp[j].white_x, - m[i].section.wp[j].white_y, - m[i].section.wp[j].white_gamma); - break; - case DS_CMD: - xf86DrvMsg(scrnIndex, X_INFO, - "Color management data: (not decoded)\n"); - break; - case DS_CVT: - xf86DrvMsg(scrnIndex, X_INFO, - "CVT 3-byte-code modes:\n"); - print_cvt_timings(scrnIndex, m[i].section.cvt); - break; - case DS_EST_III: - xf86DrvMsg(scrnIndex, X_INFO, - "Established timings III: (not decoded)\n"); - break; - case DS_DUMMY: - default: - break; - } - if (m[i].type >= DS_VENDOR && m[i].type <= DS_VENDOR_MAX) { - xf86DrvMsg(scrnIndex, X_INFO, - "Unknown vendor-specific block %hx\n", - m[i].type - DS_VENDOR); - } + "#%i: hsize: %i vsize %i refresh: %i " + "vid: %i\n",p->index ,det_mon->section.std_t[j].hsize, + det_mon->section.std_t[j].vsize, + det_mon->section.std_t[j].refresh, + det_mon->section.std_t[j].id); + break; + case DS_WHITE_P: + for (j = 0; j<2; j++) + if (det_mon->section.wp[j].index != 0) + xf86DrvMsg(scrnIndex,X_INFO, + "White point %i: whiteX: %f, whiteY: %f; gamma: %f\n", + det_mon->section.wp[j].index,det_mon->section.wp[j].white_x, + det_mon->section.wp[j].white_y, + det_mon->section.wp[j].white_gamma); + break; + case DS_CMD: + xf86DrvMsg(scrnIndex, X_INFO, + "Color management data: (not decoded)\n"); + break; + case DS_CVT: + xf86DrvMsg(scrnIndex, X_INFO, + "CVT 3-byte-code modes:\n"); + print_cvt_timings(scrnIndex, det_mon->section.cvt); + break; + case DS_EST_III: + xf86DrvMsg(scrnIndex, X_INFO, + "Established timings III: (not decoded)\n"); + break; + case DS_DUMMY: + default: + break; + } + if (det_mon->type >= DS_VENDOR && det_mon->type <= DS_VENDOR_MAX) { + xf86DrvMsg(scrnIndex, X_INFO, + "Unknown vendor-specific block %hx\n", + det_mon->type - DS_VENDOR); } + + p->index = p->index + 1; } - + static void print_number_sections(int scrnIndex, int num) { @@ -470,6 +488,7 @@ xf86PrintEDID(xf86MonPtr m) { CARD16 i, j, n; char buf[EDID_WIDTH * 2 + 1]; + struct det_print_parameter p; if (!m) return NULL; @@ -478,7 +497,12 @@ xf86PrintEDID(xf86MonPtr m) print_display(m->scrnIndex, &m->features, &m->ver); print_established_timings(m->scrnIndex, &m->timings1); print_std_timings(m->scrnIndex, m->timings2); - print_detailed_monitor_section(m->scrnIndex, m->det_mon); + p.m = m; + p.index = 0; + p.quirks = xf86DDCDetectQuirks(m->scrnIndex, m, FALSE); + xf86ForEachDetailedBlock(m, + handle_detailed_print , + &p); print_number_sections(m->scrnIndex, m->no_sections); /* extension block section stuff */ @@ -495,6 +519,6 @@ xf86PrintEDID(xf86MonPtr m) } xf86DrvMsg(m->scrnIndex, X_INFO, "\t%s\n", buf); } - + return m; } diff --git a/xorg-server/hw/xfree86/ddc/xf86DDC.h b/xorg-server/hw/xfree86/ddc/xf86DDC.h index 64869da10..af3ba06a5 100644 --- a/xorg-server/hw/xfree86/ddc/xf86DDC.h +++ b/xorg-server/hw/xfree86/ddc/xf86DDC.h @@ -73,4 +73,54 @@ FindDMTMode(int hsize, int vsize, int refresh, Bool rb); extern _X_EXPORT const DisplayModeRec DMTModes[]; +/* + * Quirks to work around broken EDID data from various monitors. + */ +typedef enum { + DDC_QUIRK_NONE = 0, + /* First detailed mode is bogus, prefer largest mode at 60hz */ + DDC_QUIRK_PREFER_LARGE_60 = 1 << 0, + /* 135MHz clock is too high, drop a bit */ + DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1, + /* Prefer the largest mode at 75 Hz */ + DDC_QUIRK_PREFER_LARGE_75 = 1 << 2, + /* Convert detailed timing's horizontal from units of cm to mm */ + DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3, + /* Convert detailed timing's vertical from units of cm to mm */ + DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4, + /* Detailed timing descriptors have bogus size values, so just take the + * maximum size and use that. + */ + DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5, + /* Monitor forgot to set the first detailed is preferred bit. */ + DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6, + /* use +hsync +vsync for detailed mode */ + DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7, + /* Force single-link DVI bandwidth limit */ + DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8, +} ddc_quirk_t; + +DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); + +extern Bool +xf86MonitorIsHDMI(xf86MonPtr mon); + +typedef void (* handle_detailed_fn)(struct detailed_monitor_section *,void *); + +void xf86ForEachDetailedBlock(xf86MonPtr mon, + handle_detailed_fn, + void *data); + +ddc_quirk_t +xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose); + +void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, + ddc_quirk_t quirks, int hsize, int vsize); + +typedef void (* handle_video_fn)(struct cea_video_block *, void *); + +void xf86ForEachVideoBlock(xf86MonPtr, + handle_video_fn, + void *); + #endif diff --git a/xorg-server/hw/xfree86/doc/README.modes b/xorg-server/hw/xfree86/doc/README.modes new file mode 100644 index 000000000..894e21313 --- /dev/null +++ b/xorg-server/hw/xfree86/doc/README.modes @@ -0,0 +1,474 @@ + Multi-monitor Mode Setting APIs + Keith Packard, <keithp@keithp.com + 6 March 2007 + +1. Introduction + +This document describes a set of mode setting APIs added in X server version +1.3 that support multiple monitors per card. These interfaces expose the +underlying hardware CRTC and output concepts to the xf86 DDX layer so that +the implementation of initial server setup and mode changes through +extensions can be shared across drivers. In addition, these new interfaces +support a new configuration mechanism as well which allows each monitor to +be customized separately providing a consistent cross-driver configuration +mechanism that supports the full range of output features. + +All of the code implementing this interface can be found in hw/xfree86/modes +in the X server sources. + +2. Overview + +This document describes both the driver API and the configuration data +placed in xorg.conf; these are entirely separate as the driver has no +interaction with the configuration information at all. Much of the structure +here is cloned from the RandR extension version 1.2 additions which deal +with the same kinds of information. + +2.1 API overview + +The mode setting API is expressed through two new driver-visible objects, +the 'CRTC' (xf86CrtcRec) and the 'Output' (xf86OutputRec). A CRTC refers to +hardware within the video system that can scan a subset of the framebuffer +and generate a video signal. An Output receives that signal and transmits it +to a monitor, projector or other device. + +The xf86CrtcRec and xf86OutputRec contain a small amount of state data +related to the object along with a pointer to a set of functions provided by +the driver that manipulate the object in fairly simple ways. + +To emulate older behaviour, one of the outputs is picked as the 'compat' +output; this output changes over time as outputs are detected and used, the +goal is to always have one 'special' output which is used for operations +which need a single defined monitor (like XFree86-VidModeExtension mode +setting, RandR 1.1 mode setting, DDC property setting, etc.). + +2.1.1 Output overview + +As outputs are connected to monitors, they hold a list of modes supported by +the monitor. If the monitor and output support DDC, then the list of modes +generally comes from the EDID data in the monitor. Otherwise, the server +uses the standard VESA modes, pruned by monitor timing. If the configuration +file doesn't contain monitor timing data, the server uses default timing +information which supports 640x480, 800x600 and 1024x768 all with a 60Hz +refresh rate. + +As hardware often limits possible configuration combinations, each output +knows the set of CRTCs that it can be connected to as well as the set of +other outputs which can be simutaneously connected to a CRTC. + +2.1.2 CRTC overview + +CRTCs serve only to stream frame buffer data to outputs using a mode line. +Ideally, they would not be presented to the user at all, and in fact the +configuration file doesn't expose them. The RandR 1.2 protocol does, but the +hope there is that client-side applications will hide them carefully away. + +Each crtc has an associated cursor, along with the current configuration. +All of the data needed to determine valid configurations is contained within +the Outputs. + +2.2 Configuration overview + +As outputs drive monitors, the "Monitor" section has been repurposed to +define their configuration. This provides for a bit more syntax than +the large list of driver-specific options that were used in the past for +similar configuration. + +However, the existing "Monitor" section referenced by the active "Screen" +section no longer has any use at all; some sensible meaning for this +parameter is needed now that a Screen can have multiple Monitors. + +3. Public Functions + +3.1 PreInit functions + +These functions should be used during the driver PreInit phase, they are +arranged in the order they should be invoked. + + void + xf86CrtcConfigInit (ScrnInfoPtr scrn + const xf86CrtcConfigFuncsRec *funcs) + +This function allocates and initializes structures needed to track CRTC and +Output state. + + void + xf86CrtcSetSizeRange (ScrnInfoPtr scrn, + int minWidth, int minHeight, + int maxWidth, int maxHeight) + +This sets the range of screen sizes supported by the driver. + + xf86CrtcPtr + xf86CrtcCreate (ScrnInfoPtr scrn, + const xf86CrtcFuncsRec *funcs) + +Create one CRTC object. See the discussion below for a description of the +contents of the xf86CrtcFuncsRec. Note that this is done in PreInit, so it +should not be re-invoked at each server generation. Create one of these for +each CRTC present in the hardware. + + xf86OutputPtr + xf86OutputCreate (ScrnInfoPtr scrn, + const xf86OutputFuncsRec *funcs, + const char *name) + +Create one Output object. See the discussion below for a description of the +contents of the xf86OutputFuncsRec. This is also called from PreInit and +need not be re-invoked at each ScreenInit time. An Output should be created +for every Output present in the hardware, not just for outputs which have +detected monitors. + + Bool + xf86OutputRename (xf86OutputPtr output, const char *name) + +If necessary, the name of an output can be changed after it is created using +this function. + + Bool + xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow) + +Using the resources provided, and the configuration specified by the user, +this function computes an initial configuration for the server. It tries to +enable as much hardware as possible using some fairly simple heuristics. + +The 'canGrow' parameter indicates that the frame buffer does not have a fixed +size (fixed size frame buffers are required by XAA). When the frame buffer +has a fixed size, the configuration selects a 'reasonablely large' frame +buffer so that common reconfiguration options are possible. For resizable +frame buffers, the frame buffer is set to the smallest size that encloses +the desired configuration. + +3.2 ScreenInit functions + +These functions should be used during the driver ScreenInit phase. + + Bool + xf86DiDGAInit (ScreenPtr screen, unsigned long dga_address) + +This function provides driver-independent accelerated DGA support for some +of the DGA operations; using this, the driver can avoid needing to implement +any of the rest of DGA. + + Bool + xf86SaveScreen(ScreenPtr pScreen, int mode) + +Stick this in pScreen->SaveScreen and the core X screen saver will be +implemented by disabling outputs and crtcs using their dpms functions. + + void + xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags) + +Pass this function to xf86DPMSInit and all DPMS mode switching will be +managed by using the dpms functions provided by the Outputs and CRTCs. + + Bool + xf86CrtcScreenInit (ScreenPtr screen) + +This function completes the screen initialization process for the crtc and +output objects. Call it near the end of the ScreenInit function, after the +frame buffer and acceleration layers have been added. + +3.3 EnterVT functions + +Functions used during EnterVT, or whenever the current configuration needs +to be applied to the hardware. + + Bool + xf86SetDesiredModes (ScrnInfoPtr scrn) + +xf86InitialConfiguration selects the desired configuration at PreInit time; +when the server finally hits ScreenInit, xf86SetDesiredModes is used by the +driver to take that configuration and apply it to the hardware. In addition, +successful mode selection at other times updates the configuration that will +be used by this function, so LeaveVT/EnterVT pairs can simply invoke this +and return to the previous configuration. + +3.4 SwitchMode functions + +Functions called from the pScrn->SwitchMode hook, which is used by the +XFree86-VidModeExtension and the keypad mode switch commands. + + Bool + xf86SetSingleMode (ScrnInfoPtr scrn, + DisplayModePtr desired, + Rotation rotation) + +This function applies the specified mode to all active outputs. Which is to +say, it picks reasonable modes for all active outputs, attempting to get the +screen to the specified size while not breaking anything that is currently +working. + +3.7 get_modes functions + +Functions called during output->get_modes to help build lists of modes + + xf86MonPtr + xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus) + +This returns the EDID data structure for the 'output' using the I2C bus +'pDDCBus'. This has no effect on 'output' itself. + + void + xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) + +Once the EDID data has been fetched, this call applies the EDID data to the +output object, setting the physical size and also various properties, like +the DDC root window property (when output is the 'compat' output), and the +RandR 1.2 EDID output properties. + + DisplayModePtr + xf86OutputGetEDIDModes (xf86OutputPtr output) + +Given an EDID data structure, this function computes a list of suitable +modes. This function also applies a sequence of 'quirks' during this process +so that the returned modes may not actually match the mode data present in +the EDID data. + +3.6 Other functions + +These remaining functions in the API can be used by the driver as needed. + + Bool + xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation, + int x, int y) + +Applies a mode to a CRTC. All of the outputs which are currently using the +specified CRTC are included in the mode setting process. 'x' and 'y' are the +offset within the frame buffer that the crtc is placed at. No checking is +done in this function to ensure that the mode is usable by the active +outputs. + + void + xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY) + +This discards the mode lists for all outputs, re-detects monitor presence +and then acquires new mode lists for all monitors which are not disconnected. +Monitor configuration data is used to modify the mode lists returned by the +outputs. 'maxX' and 'maxY' limit the maximum size modes that will be +returned. + + void + xf86SetScrnInfoModes (ScrnInfoPtr pScrn) + +This copies the 'compat' output mode list into the pScrn modes list which is +used by the XFree86-VidModeExtension and the keypad mode switching +operations. The current 'desired' mode for the CRTC associated with the +'compat' output is placed first in this list to indicate the current mode. +Usually, the driver won't need to call this function as +xf86InitialConfiguration will do so automatically, as well as any RandR +functions which reprobe for modes. However, if the driver reprobes for modes +at other times using xf86ProbeOutputModes, this function needs to be called. + + Bool + xf86DiDGAReInit (ScreenPtr pScreen) + +This is similar to xf86SetScrnInfoModes, but it applies the 'compat' output +mode list to the set of modes advertised by the DGA extension; it needs to +be called whenever xf86ProbeOutputModes is invoked. + + void + xf86DisableUnusedFunctions(ScrnInfoPtr pScrn) + +After any sequence of calls using xf86CrtcSetMode, this function cleans up +any leftover Output and CRTC objects by disabling them, saving power. It is +safe to call this whenever the server is running as it only disables objects +which are not currently in use. + +4. CRTC operations + +4.1 CRTC functions + +These functions provide an abstract interface for the CRTC object; most +manipulation of the CRTC object is done through these functions. + + void + crtc->funcs->dpms (xf86CrtcPtr crtc, int mode) + +Where 'mode' is one of DPMSModeOff, DPMSModeSuspend, DPMSModeStandby or +DPMSModeOn. This requests that the crtc go to the specified power state. +When changing power states, the output dpms functions are invoked before the +crtc dpms functions. + + void + crtc->funcs->save (xf86CrtcPtr crtc) + + void + crtc->funcs->restore (xf86CrtcPtr crtc) + +Preserve/restore any register contents related to the CRTC. These are +strictly a convenience for the driver writer; if the existing driver has +fully operation save/restore functions, you need not place any additional +code here. In particular, the server itself never uses this function. + + Bool + crtc->funcs->lock (xf86CrtcPtr crtc) + + void + crtc->funcs->unlock (xf86CrtcPtr crtc) + +These functions are invoked around mode setting operations; the intent is +that DRI locking be done here to prevent DRI applications from manipulating +the hardware while the server is busy changing the output configuration. If +the lock function returns FALSE, the unlock function will not be invoked. + + Bool + crtc->funcs->mode_fixup (xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode) + +This call gives the CRTC a chance to see what mode will be set and to +comment on the mode by changing 'adjusted_mode' as needed. This function +shall not modify the state of the crtc hardware at all. If the CRTC cannot +accept this mode, this function may return FALSE. + + void + crtc->funcs->prepare (xf86CrtcPtr crtc) + +This call is made just before the mode is set to make the hardware ready for +the operation. A usual function to perform here is to disable the crtc so +that mode setting can occur with clocks turned off and outputs deactivated. + + void + crtc->funcs->mode_set (xf86CrtcPtr crtc, + DisplayModePtr mode, + DisplayModePtr adjusted_mode) + +This function applies the specified mode (possibly adjusted by the CRTC +and/or Outputs). + + void + crtc->funcs->commit (xf86CrtcPtr crtc) + +Once the mode has been applied to the CRTC and Outputs, this function is +invoked to let the hardware turn things back on. + + void + crtc->funcs->gamma_set (xf86CrtcPtr crtc, CARD16 *red, + CARD16 *green, CARD16 *blue, int size) + +This function adjusts the gamma ramps for the specified crtc. + + void * + crtc->funcs->shadow_allocate (xf86CrtcPtr crtc, int width, int height) + +This function allocates frame buffer space for a shadow frame buffer. When +allocated, the crtc must scan from the shadow instead of the main frame +buffer. This is used for rotation. The address returned is passed to the +shadow_create function. This function should return NULL on failure. + + PixmapPtr + crtc->funcs->shadow_create (xf86CrtcPtr crtc, void *data, + int width, int height) + +This function creates a pixmap object that will be used as a shadow of the +main frame buffer for CRTCs which are rotated or reflected. 'data' is the +value returned by shadow_allocate. + + void + crtc->funcs->shadow_destroy (xf86CrtcPtr crtc, PixmapPtr pPixmap, + void *data) + +Destroys any associated shadow objects. If pPixmap is NULL, then a pixmap +was not created, but 'data' may still be non-NULL indicating that the shadow +had been allocated. + + void + crtc->funcs->destroy (xf86CrtcPtr crtc) + +When a CRTC is destroyed (which only happens in error cases), this function +can clean up any driver-specific data. + +4.2 CRTC fields + +The CRTC object is not opaque; there are several fields of interest to the +driver writer. + + struct _xf86Crtc { + /** + * Associated ScrnInfo + */ + ScrnInfoPtr scrn; + + /** + * Active state of this CRTC + * + * Set when this CRTC is driving one or more outputs + */ + Bool enabled; + + /** Track whether cursor is within CRTC range */ + Bool cursorInRange; + + /** Track state of cursor associated with this CRTC */ + Bool cursorShown; + + /** + * Active mode + * + * This reflects the mode as set in the CRTC currently + * It will be cleared when the VT is not active or + * during server startup + */ + DisplayModeRec mode; + Rotation rotation; + PixmapPtr rotatedPixmap; + void *rotatedData; + + /** + * Position on screen + * + * Locates this CRTC within the frame buffer + */ + int x, y; + + /** + * Desired mode + * + * This is set to the requested mode, independent of + * whether the VT is active. In particular, it receives + * the startup configured mode and saves the active mode + * on VT switch. + */ + DisplayModeRec desiredMode; + Rotation desiredRotation; + int desiredX, desiredY; + + /** crtc-specific functions */ + const xf86CrtcFuncsRec *funcs; + + /** + * Driver private + * + * Holds driver-private information + */ + void *driver_private; + #ifdef RANDR_12_INTERFACE + /** + * RandR crtc + * + * When RandR 1.2 is available, this + * points at the associated crtc object + */ + RRCrtcPtr randr_crtc; + #else + void *randr_crtc; + #endif + }; + + +5. Output functions. + +6. Configuration + +Because the configuration file syntax is fixed, +this was done by creating new "Driver" section options that hook specific +outputs to specific "Monitor" sections in the file. The option: +section of the form: + + Option "monitor-VGA" "My VGA Monitor" + +connects the VGA output of this driver to the "Monitor" section with +Identifier "My VGA Monitor". All of the usual monitor options can now be +placed in that "Monitor" section and will be applied to the VGA output +configuration. diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 6c14578d7..dc07b47af 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -81,7 +81,7 @@ ProcDRI2QueryVersion(ClientPtr client) rep.length = 0; rep.sequenceNumber = client->sequence; rep.majorVersion = SERVER_DRI2_MAJOR_VERSION; - rep.minorVersion = SERVER_DRI2_MAJOR_VERSION; + rep.minorVersion = SERVER_DRI2_MINOR_VERSION; if (client->swapped) { swaps(&rep.sequenceNumber, n); diff --git a/xorg-server/hw/xfree86/i2c/fi1236.c b/xorg-server/hw/xfree86/i2c/fi1236.c index 110563ed9..7c39edbee 100644 --- a/xorg-server/hw/xfree86/i2c/fi1236.c +++ b/xorg-server/hw/xfree86/i2c/fi1236.c @@ -225,7 +225,7 @@ m->f_ifbw=f_ifbw; m->f_step=f_step; m->f_lo1=f_rf+f_if1; -m->LO1I=(int)floor((m->f_lo1/f_ref)+0.5); +m->LO1I=lrint(m->f_lo1/f_ref); m->f_lo1=f_ref*m->LO1I; m->f_lo2=m->f_lo1-f_rf-f_if2; @@ -258,10 +258,10 @@ if(m->f_lo1<1890.0)m->SEL=1; m->SEL=0; /* calculate the rest of the registers */ -m->LO2I=(int)floor(m->f_lo2/f_ref); -m->STEP=(int)floor(3780.0*f_step/f_ref); -m->NUM=(int)floor(3780.0*(m->f_lo2/f_ref-m->LO2I)); -m->NUM=m->STEP*(int)floor((1.0*m->NUM)/(1.0*m->STEP)+0.5); +m->LO2I=floor(m->f_lo2/f_ref); +m->STEP=floor(3780.0*f_step/f_ref); +m->NUM=floor(3780.0*(m->f_lo2/f_ref-m->LO2I)); +m->NUM=m->STEP*lrint((1.0*m->NUM)/(1.0*m->STEP)); } static int MT2032_wait_for_lock(FI1236Ptr f) diff --git a/xorg-server/hw/xfree86/loader/Makefile.am b/xorg-server/hw/xfree86/loader/Makefile.am index 0bfa7a283..d3c17d173 100644 --- a/xorg-server/hw/xfree86/loader/Makefile.am +++ b/xorg-server/hw/xfree86/loader/Makefile.am @@ -21,6 +21,7 @@ libloader_la_SOURCES = \ dlloader.c \ os.c \ sdksyms.c +libloader_la_LIBADD = $(DLOPEN_LIBS) CLEANFILES = sdksyms.c sdksyms.dep diff --git a/xorg-server/hw/xfree86/loader/loadmod.c b/xorg-server/hw/xfree86/loader/loadmod.c index 0b220f1b6..5b175a546 100644 --- a/xorg-server/hw/xfree86/loader/loadmod.c +++ b/xorg-server/hw/xfree86/loader/loadmod.c @@ -399,8 +399,11 @@ FindModuleInSubdir(const char *dirpath, const char *module) while ((direntry = readdir(dir))) { if (direntry->d_name[0] == '.') continue; - if ((stat(direntry->d_name, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) { - snprintf(tmpBuf, PATH_MAX, "%s/%s", dirpath, direntry->d_name); + snprintf(tmpBuf, PATH_MAX, "%s%s/", dirpath, direntry->d_name); + /* the stat with the appended / fails for normal files, + and works for sub dirs fine, looks a bit strange in strace + but does seem to work */ + if ((stat(tmpBuf, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode)) { if ((ret = FindModuleInSubdir(tmpBuf, module))) break; continue; diff --git a/xorg-server/hw/xfree86/loader/sdksyms.sh b/xorg-server/hw/xfree86/loader/sdksyms.sh index 11865472f..eea024063 100644 --- a/xorg-server/hw/xfree86/loader/sdksyms.sh +++ b/xorg-server/hw/xfree86/loader/sdksyms.sh @@ -2,6 +2,7 @@ cat > sdksyms.c << EOF /* This file is automatically generated by sdksyms.sh. */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> diff --git a/xorg-server/hw/xfree86/modes/xf86Crtc.c b/xorg-server/hw/xfree86/modes/xf86Crtc.c index 506fbb9cb..d015c6a77 100644 --- a/xorg-server/hw/xfree86/modes/xf86Crtc.c +++ b/xorg-server/hw/xfree86/modes/xf86Crtc.c @@ -1377,34 +1377,6 @@ xf86InitialPanning (ScrnInfoPtr scrn) } } -/* - * XXX walk the monitor mode list and prune out duplicates that - * are inserted by xf86DDCMonitorSet. In an ideal world, that - * function would do this work by itself. - */ - -static void -xf86PruneDuplicateMonitorModes (MonPtr Monitor) -{ - DisplayModePtr master, clone, next; - - for (master = Monitor->Modes; - master && master != Monitor->Last; - master = master->next) - { - for (clone = master->next; clone && clone != Monitor->Modes; clone = next) - { - next = clone->next; - if (xf86ModesEqual (master, clone)) - { - if (Monitor->Last == clone) - Monitor->Last = clone->prev; - xf86DeleteMode (&Monitor->Modes, clone); - } - } - } -} - /** Return - 0 + if a should be earlier, same or later than b in list */ static int @@ -1523,6 +1495,42 @@ GuessRangeFromModes(MonPtr mon, DisplayModePtr mode) mon->vrefresh[0].lo = 58.0; } +struct det_monrec_parameter { + MonRec *mon_rec; + int *max_clock; + Bool set_hsync; + Bool set_vrefresh; + enum { sync_config, sync_edid, sync_default } *sync_source; +}; + +static void handle_detailed_monrec(struct detailed_monitor_section *det_mon, + void *data) +{ + enum { sync_config, sync_edid, sync_default }; + struct det_monrec_parameter *p; + p = (struct det_monrec_parameter *)data; + + if (det_mon->type == DS_RANGES) { + struct monitor_ranges *ranges = &det_mon->section.ranges; + if (p->set_hsync && ranges->max_h) { + p->mon_rec->hsync[p->mon_rec->nHsync].lo = ranges->min_h; + p->mon_rec->hsync[p->mon_rec->nHsync].hi = ranges->max_h; + p->mon_rec->nHsync++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (p->set_vrefresh && ranges->max_v) { + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].lo = ranges->min_v; + p->mon_rec->vrefresh[p->mon_rec->nVrefresh].hi = ranges->max_v; + p->mon_rec->nVrefresh++; + if (*p->sync_source == sync_default) + *p->sync_source = sync_edid; + } + if (ranges->max_clock * 1000 > *p->max_clock) + *p->max_clock = ranges->max_clock * 1000; + } +} + void xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) { @@ -1539,9 +1547,6 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) maxY = config->maxHeight; } - /* Elide duplicate modes before defaulting code uses them */ - xf86PruneDuplicateMonitorModes (scrn->monitor); - /* Probe the list of modes for each output. */ for (o = 0; o < config->num_output; o++) { @@ -1556,6 +1561,8 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) int max_clock = 0; double clock; Bool add_default_modes = TRUE; + Bool debug_modes = config->debug_modes || + xf86Initialising; enum { sync_config, sync_edid, sync_default } sync_source = sync_default; while (output->probed_modes != NULL) @@ -1601,42 +1608,24 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) edid_monitor = output->MonInfo; - if (edid_monitor) - { - int i; - Bool set_hsync = mon_rec.nHsync == 0; - Bool set_vrefresh = mon_rec.nVrefresh == 0; - struct disp_features *features = &edid_monitor->features; + if (edid_monitor) + { + struct det_monrec_parameter p; + struct disp_features *features = &edid_monitor->features; /* if display is not continuous-frequency, don't add default modes */ if (!GTF_SUPPORTED(features->msc)) add_default_modes = FALSE; - for (i = 0; i < sizeof (edid_monitor->det_mon) / sizeof (edid_monitor->det_mon[0]); i++) - { - if (edid_monitor->det_mon[i].type == DS_RANGES) - { - struct monitor_ranges *ranges = &edid_monitor->det_mon[i].section.ranges; - if (set_hsync && ranges->max_h) - { - mon_rec.hsync[mon_rec.nHsync].lo = ranges->min_h; - mon_rec.hsync[mon_rec.nHsync].hi = ranges->max_h; - mon_rec.nHsync++; - if (sync_source == sync_default) - sync_source = sync_edid; - } - if (set_vrefresh && ranges->max_v) - { - mon_rec.vrefresh[mon_rec.nVrefresh].lo = ranges->min_v; - mon_rec.vrefresh[mon_rec.nVrefresh].hi = ranges->max_v; - mon_rec.nVrefresh++; - if (sync_source == sync_default) - sync_source = sync_edid; - } - if (ranges->max_clock * 1000 > max_clock) - max_clock = ranges->max_clock * 1000; - } - } + p.mon_rec = &mon_rec; + p.max_clock = &max_clock; + p.set_hsync = mon_rec.nHsync == 0; + p.set_vrefresh = mon_rec.nVrefresh == 0; + p.sync_source = &sync_source; + + xf86ForEachDetailedBlock(edid_monitor, + handle_detailed_monrec, + &p); } if (xf86GetOptValFreq (output->options, OPTION_MIN_CLOCK, @@ -1725,8 +1714,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) if (mode->status == MODE_OK) mode->status = (*output->funcs->mode_valid)(output, mode); - xf86PruneInvalidModes(scrn, &output->probed_modes, - config->debug_modes); + xf86PruneInvalidModes(scrn, &output->probed_modes, debug_modes); output->probed_modes = xf86SortModes (output->probed_modes); @@ -1758,7 +1746,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) output->initial_rotation = xf86OutputInitialRotation (output); - if (config->debug_modes) { + if (debug_modes) { if (output->probed_modes != NULL) { xf86DrvMsg(scrn->scrnIndex, X_INFO, "Printing probed modes for output %s\n", @@ -1777,7 +1765,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY) mode->VRefresh = xf86ModeVRefresh(mode); xf86SetModeCrtc(mode, INTERLACE_HALVE_V); - if (config->debug_modes) + if (debug_modes) xf86PrintModeline(scrn->scrnIndex, mode); } } @@ -2900,6 +2888,35 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len) #endif +/* Pull out a phyiscal size from a detailed timing if available. */ +struct det_phySize_parameter { + xf86OutputPtr output; + ddc_quirk_t quirks; + Bool ret; +}; + +static void handle_detailed_physical_size(struct detailed_monitor_section + *det_mon, void *data) +{ + struct det_phySize_parameter *p; + p = (struct det_phySize_parameter *)data; + + if (p->ret == TRUE ) + return ; + + xf86DetTimingApplyQuirks(det_mon, p->quirks, + p->output->MonInfo->features.hsize, + p->output->MonInfo->features.vsize); + if (det_mon->type == DT && + det_mon->section.d_timings.h_size != 0 && + det_mon->section.d_timings.v_size != 0) { + + p->output->mm_width = det_mon->section.d_timings.h_size; + p->output->mm_height = det_mon->section.d_timings.v_size; + p->ret = TRUE; + } +} + /** * Set the EDID information for the specified output */ @@ -2908,7 +2925,7 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) { ScrnInfoPtr scrn = output->scrn; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - int i; + Bool debug_modes = config->debug_modes || xf86Initialising; #ifdef RANDR_12_INTERFACE int size; #endif @@ -2918,7 +2935,7 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) output->MonInfo = edid_mon; - if (config->debug_modes) { + if (debug_modes) { xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name); xf86PrintEDID(edid_mon); @@ -2943,20 +2960,15 @@ xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon) xf86OutputSetEDIDProperty (output, edid_mon ? edid_mon->rawData : NULL, size); #endif - if (edid_mon) - { - /* Pull out a phyiscal size from a detailed timing if available. */ - for (i = 0; i < 4; i++) { - if (edid_mon->det_mon[i].type == DT && - edid_mon->det_mon[i].section.d_timings.h_size != 0 && - edid_mon->det_mon[i].section.d_timings.v_size != 0) - { - output->mm_width = edid_mon->det_mon[i].section.d_timings.h_size; - output->mm_height = edid_mon->det_mon[i].section.d_timings.v_size; - break; - } - } - + if (edid_mon) { + + struct det_phySize_parameter p; + p.output = output; + p.quirks = xf86DDCDetectQuirks(scrn->scrnIndex,edid_mon, FALSE); + p.ret = FALSE; + xf86ForEachDetailedBlock(edid_mon, + handle_detailed_physical_size, &p); + /* if no mm size is available from a detailed timing, check the max size field */ if ((!output->mm_width || !output->mm_height) && (edid_mon->features.hsize && edid_mon->features.vsize)) diff --git a/xorg-server/hw/xfree86/modes/xf86EdidModes.c b/xorg-server/hw/xfree86/modes/xf86EdidModes.c index 2f80070cf..449078e2a 100644 --- a/xorg-server/hw/xfree86/modes/xf86EdidModes.c +++ b/xorg-server/hw/xfree86/modes/xf86EdidModes.c @@ -45,20 +45,23 @@ #include <string.h> #include <math.h> +static void handle_detailed_rblank(struct detailed_monitor_section *det_mon, + void *data) +{ + if (det_mon->type == DS_RANGES) + if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) + *(Bool*)data = TRUE; +} + static Bool xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) { /* EDID 1.4 explicitly defines RB support */ if (DDC->ver.revision >= 4) { - int i; - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - if (det_mon->type == DS_RANGES) - if (det_mon->section.ranges.supported_blanking & CVT_REDUCED) - return TRUE; - } - - return FALSE; + Bool ret = FALSE; + + xf86ForEachDetailedBlock(DDC, handle_detailed_rblank, &ret); + return ret; } /* For anything older, assume digital means RB support. Boo. */ @@ -68,34 +71,6 @@ xf86MonitorSupportsReducedBlanking(xf86MonPtr DDC) return FALSE; } -/* - * Quirks to work around broken EDID data from various monitors. - */ - -typedef enum { - DDC_QUIRK_NONE = 0, - /* First detailed mode is bogus, prefer largest mode at 60hz */ - DDC_QUIRK_PREFER_LARGE_60 = 1 << 0, - /* 135MHz clock is too high, drop a bit */ - DDC_QUIRK_135_CLOCK_TOO_HIGH = 1 << 1, - /* Prefer the largest mode at 75 Hz */ - DDC_QUIRK_PREFER_LARGE_75 = 1 << 2, - /* Convert detailed timing's horizontal from units of cm to mm */ - DDC_QUIRK_DETAILED_H_IN_CM = 1 << 3, - /* Convert detailed timing's vertical from units of cm to mm */ - DDC_QUIRK_DETAILED_V_IN_CM = 1 << 4, - /* Detailed timing descriptors have bogus size values, so just take the - * maximum size and use that. - */ - DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE = 1 << 5, - /* Monitor forgot to set the first detailed is preferred bit. */ - DDC_QUIRK_FIRST_DETAILED_PREFERRED = 1 << 6, - /* use +hsync +vsync for detailed mode */ - DDC_QUIRK_DETAILED_SYNC_PP = 1 << 7, - /* Force single-link DVI bandwidth limit */ - DDC_QUIRK_DVI_SINGLE_LINK = 1 << 8, -} ddc_quirk_t; - static Bool quirk_prefer_large_60 (int scrnIndex, xf86MonPtr DDC) { /* Belinea 10 15 55 */ @@ -266,7 +241,7 @@ static const ddc_quirk_map_t ddc_quirks[] = { }, { quirk_detailed_use_maximum_size, DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE, - "Detailed timings give sizes in cm." + "Use maximum size instead of detailed timing sizes." }, { quirk_first_detailed_preferred, DDC_QUIRK_FIRST_DETAILED_PREFERRED, @@ -498,8 +473,10 @@ DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks, vsize = timing[i].vsize; refresh = timing[i].refresh; - /* HDTV hack. Hooray. */ - if (hsize == 1360 && vsize == 765 && refresh == 60) { + /* HDTV hack, because you can't say 1366 */ + if (refresh == 60 && + ((hsize == 1360 && vsize == 765) || + (hsize == 1368 && vsize == 769))) { Mode = xf86CVTMode(1366, 768, 60, FALSE, FALSE); Mode->HDisplay = 1366; Mode->VSyncStart--; @@ -527,6 +504,45 @@ DDCModesFromStandardTiming(struct std_timings *timing, ddc_quirk_t quirks, return Modes; } +static void +DDCModeDoInterlaceQuirks(DisplayModePtr mode) +{ + /* + * EDID is delightfully ambiguous about how interlaced modes are to be + * encoded. X's internal representation is of frame height, but some + * HDTV detailed timings are encoded as field height. + * + * The format list here is from CEA, in frame size. Technically we + * should be checking refresh rate too. Whatever. + */ + static const struct { + int w, h; + } cea_interlaced[] = { + { 1920, 1080 }, + { 720, 480 }, + { 1440, 480 }, + { 2880, 480 }, + { 720, 576 }, + { 1440, 576 }, + { 2880, 576 }, + }; + static const int n_modes = sizeof(cea_interlaced)/sizeof(cea_interlaced[0]); + int i; + + for (i = 0; i < n_modes; i++) { + if ((mode->HDisplay == cea_interlaced[i].w) && + (mode->VDisplay == cea_interlaced[i].h / 2)) { + mode->VDisplay *= 2; + mode->VSyncStart *= 2; + mode->VSyncEnd *= 2; + mode->VTotal *= 2; + mode->VTotal |= 1; + } + } + + mode->Flags |= V_INTERLACE; +} + /* * */ @@ -591,12 +607,10 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, return NULL; } - xf86SetModeDefaultName(Mode); - /* We ignore h/v_size and h/v_border for now. */ if (timing->interlaced) - Mode->Flags |= V_INTERLACE; + DDCModeDoInterlaceQuirks(Mode); if (quirks & DDC_QUIRK_DETAILED_SYNC_PP) Mode->Flags |= V_PVSYNC | V_PHSYNC; @@ -612,6 +626,8 @@ DDCModeFromDetailedTiming(int scrnIndex, struct detailed_timings *timing, Mode->Flags |= V_NHSYNC; } + xf86SetModeDefaultName(Mode); + return Mode; } @@ -774,7 +790,7 @@ DDCGuessRangesFromModes(int scrnIndex, MonPtr Monitor, DisplayModePtr Modes) } } -static ddc_quirk_t +ddc_quirk_t xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) { ddc_quirk_t quirks; @@ -794,6 +810,25 @@ xf86DDCDetectQuirks(int scrnIndex, xf86MonPtr DDC, Bool verbose) return quirks; } +void xf86DetTimingApplyQuirks(struct detailed_monitor_section *det_mon, + ddc_quirk_t quirks, + int hsize, int vsize) +{ + if (det_mon->type != DT) + return; + + if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) + det_mon->section.d_timings.h_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) + det_mon->section.d_timings.v_size *= 10; + + if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { + det_mon->section.d_timings.h_size = 10 * hsize; + det_mon->section.d_timings.v_size = 10 * vsize; + } +} + /** * Applies monitor-specific quirks to the decoded EDID information. * @@ -807,21 +842,9 @@ xf86DDCApplyQuirks(int scrnIndex, xf86MonPtr DDC) int i; for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - - if (det_mon->type != DT) - continue; - - if (quirks & DDC_QUIRK_DETAILED_H_IN_CM) - det_mon->section.d_timings.h_size *= 10; - - if (quirks & DDC_QUIRK_DETAILED_V_IN_CM) - det_mon->section.d_timings.v_size *= 10; - - if (quirks & DDC_QUIRK_DETAILED_USE_MAXIMUM_SIZE) { - det_mon->section.d_timings.h_size = 10 * DDC->features.hsize; - det_mon->section.d_timings.v_size = 10 * DDC->features.vsize; - } + xf86DetTimingApplyQuirks(DDC->det_mon + i, quirks, + DDC->features.hsize, + DDC->features.vsize); } } @@ -866,14 +889,156 @@ xf86DDCSetPreferredRefresh(int scrnIndex, DisplayModePtr modes, best->type |= M_T_PREFERRED; } +#define CEA_VIDEO_MODES_NUM 64 +static const DisplayModeRec CEAVideoModes[CEA_VIDEO_MODES_NUM] = { + { MODEPREFIX, 25175, 640, 656, 752, 800, 0, 480, 490, 492, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 1:640x480@60Hz */ + { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 2:720x480@60Hz */ + { MODEPREFIX, 27000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 3:720x480@60Hz */ + { MODEPREFIX, 74250, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 4: 1280x720@60Hz */ + { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 5:1920x1080i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 6:1440x480i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 7:1440x480i@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 8:1440x240@60Hz */ + { MODEPREFIX, 27000, 1440, 1478, 1602, 1716, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 9:1440x240@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 10:2880x480i@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 11:2880x480i@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 12:2880x240@60Hz */ + { MODEPREFIX, 54000, 2880, 2956, 3204, 3432, 0, 240, 244, 247, 262, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 13:2880x240@60Hz */ + { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 14:1440x480@60Hz */ + { MODEPREFIX, 54000, 1440, 1472, 1596, 1716, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 15:1440x480@60Hz */ + { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 16:1920x1080@60Hz */ + { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 17:720x576@50Hz */ + { MODEPREFIX, 27000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 18:720x576@50Hz */ + { MODEPREFIX, 74250, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 19: 1280x720@50Hz */ + { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 20:1920x1080i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 21:1440x576i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 22:1440x576i@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 23:1440x288@50Hz */ + { MODEPREFIX, 27000, 1440, 1464, 1590, 1728, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 24:1440x288@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 25:2880x576i@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 26:2880x576i@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 27:2880x288@50Hz */ + { MODEPREFIX, 54000, 2880, 2928, 3180, 3456, 0, 288, 290, 293, 312, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 28:2880x288@50Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 29:1440x576@50Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1592, 1728, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 30:1440x576@50Hz */ + { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 31:1920x1080@50Hz */ + { MODEPREFIX, 74250, 1920, 2558, 2602, 2750, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 32:1920x1080@24Hz */ + { MODEPREFIX, 74250, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 33:1920x1080@25Hz */ + { MODEPREFIX, 74250, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 34:1920x1080@30Hz */ + { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 35:2880x480@60Hz */ + { MODEPREFIX, 108000, 2880, 2944, 3192, 3432, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 36:2880x480@60Hz */ + { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 37:2880x576@50Hz */ + { MODEPREFIX, 108000, 2880, 2928, 3184, 3456, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 38:2880x576@50Hz */ + { MODEPREFIX, 72000, 1920, 1952, 2120, 2304, 0, 1080, 1126, 1136, 1250, 0, V_PHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 39:1920x1080i@50Hz */ + { MODEPREFIX, 148500, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 40:1920x1080i@100Hz */ + { MODEPREFIX, 148500, 1280, 1720, 1760, 1980, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 41:1280x720@100Hz */ + { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 42:720x576@100Hz */ + { MODEPREFIX, 54000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 43:720x576@100Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 44:1440x576i@100Hz */ + { MODEPREFIX, 54000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 45:1440x576i@100Hz */ + { MODEPREFIX, 148500, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC | V_INTERLACE, MODESUFFIX }, /* VIC 46:1920x1080i@120Hz */ + { MODEPREFIX, 148500, 1280, 1390, 1430, 1650, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 47:1280x720@120Hz */ + { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 48:720x480@120Hz */ + { MODEPREFIX, 54000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 49:720x480@120Hz */ + { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 50:1440x480i@120Hz */ + { MODEPREFIX, 54000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 51:1440x480i@120Hz */ + { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 52:720x576@200Hz */ + { MODEPREFIX, 108000, 720, 732, 796, 864, 0, 576, 581, 586, 625, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 53:720x576@200Hz */ + { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 54:1440x576i@200Hz */ + { MODEPREFIX, 108000, 1440, 1464, 1590, 1728, 0, 576, 580, 586, 625, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 55:1440x576i@200Hz */ + { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 56:720x480@240Hz */ + { MODEPREFIX, 108000, 720, 736, 798, 858, 0, 480, 489, 495, 525, 0, V_NHSYNC | V_NVSYNC, MODESUFFIX }, /* VIC 57:720x480@240Hz */ + { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 58:1440x480i@240 */ + { MODEPREFIX, 108000, 1440, 1478, 1602, 1716, 0, 480, 488, 494, 525, 0, V_NHSYNC | V_NVSYNC | V_INTERLACE, MODESUFFIX },/* VIC 59:1440x480i@240 */ + { MODEPREFIX, 59400, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 60: 1280x720@24Hz */ + { MODEPREFIX, 74250, 3700, 3740, 1430, 3960, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 61: 1280x720@25Hz */ + { MODEPREFIX, 74250, 1280, 3040, 3080, 3300, 0, 720, 725, 730, 750, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 62: 1280x720@30Hz */ + { MODEPREFIX, 297000, 1920, 2008, 2052, 2200, 0, 1080, 1084, 1089, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 63: 1920x1080@120Hz */ + { MODEPREFIX, 297000, 1920, 2448, 2492, 2640, 0, 1080, 1084, 1094, 1125, 0, V_PHSYNC | V_PVSYNC, MODESUFFIX }, /* VIC 64:1920x1080@100Hz */ +}; + +/* chose mode line by cea short video descriptor*/ +static void handle_cea_svd(struct cea_video_block *video, void *data) +{ + DisplayModePtr Mode; + DisplayModePtr *Modes = (DisplayModePtr *) data; + int vid; + + vid = video ->video_code & 0x7f; + if (vid < CEA_VIDEO_MODES_NUM) { + Mode = xf86DuplicateMode(CEAVideoModes + vid); + *Modes = xf86ModesAdd(*Modes, Mode); + } +} + +static DisplayModePtr +DDCModesFromCEAExtension(int scrnIndex, xf86MonPtr MonPtr) +{ + DisplayModePtr Modes = NULL; + + xf86ForEachVideoBlock(MonPtr, + handle_cea_svd, + &Modes); + + return Modes; +} + +struct det_modes_parameter { + xf86MonPtr DDC; + ddc_quirk_t quirks; + DisplayModePtr Modes; + Bool rb; + Bool preferred; + int timing_level; +}; + +static void handle_detailed_modes(struct detailed_monitor_section *det_mon, + void *data) +{ + DisplayModePtr Mode; + struct det_modes_parameter *p = (struct det_modes_parameter *)data; + + xf86DetTimingApplyQuirks(det_mon,p->quirks, + p->DDC->features.hsize, + p->DDC->features.vsize); + + switch (det_mon->type) { + case DT: + Mode = DDCModeFromDetailedTiming(p->DDC->scrnIndex, + &det_mon->section.d_timings, + p->preferred, + p->quirks); + p->preferred = FALSE; + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; + case DS_STD_TIMINGS: + Mode = DDCModesFromStandardTiming(det_mon->section.std_t, + p->quirks, p->timing_level,p->rb); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) + case DS_CVT: + Mode = DDCModesFromCVT(p->DDC->scrnIndex, det_mon->section.cvt); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; +#endif + case DS_EST_III: + Mode = DDCModesFromEstIII(det_mon->section.est_iii); + p->Modes = xf86ModesAdd(p->Modes, Mode); + break; + default: + break; + } +} + DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) { - int i; DisplayModePtr Modes = NULL, Mode; ddc_quirk_t quirks; Bool preferred, rb; int timing_level; + struct det_modes_parameter p; xf86DrvMsg (scrnIndex, X_INFO, "EDID vendor \"%s\", prod id %d\n", DDC->vendor.name, DDC->vendor.prod_id); @@ -892,35 +1057,14 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) timing_level = MonitorStandardTimingLevel(DDC); - for (i = 0; i < DET_TIMINGS; i++) { - struct detailed_monitor_section *det_mon = &DDC->det_mon[i]; - - Mode = NULL; - switch (det_mon->type) { - case DT: - Mode = DDCModeFromDetailedTiming(scrnIndex, - &det_mon->section.d_timings, - preferred, - quirks); - preferred = FALSE; - break; - case DS_STD_TIMINGS: - Mode = DDCModesFromStandardTiming(det_mon->section.std_t, - quirks, timing_level, rb); - break; -#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(7,0,0,0,0) - case DS_CVT: - Mode = DDCModesFromCVT(scrnIndex, det_mon->section.cvt); - break; -#endif - case DS_EST_III: - Mode = DDCModesFromEstIII(det_mon->section.est_iii); - break; - default: - break; - } - Modes = xf86ModesAdd(Modes, Mode); - } + p.quirks = quirks; + p.DDC = DDC; + p.Modes = Modes; + p.rb = rb; + p.preferred = preferred; + p.timing_level = timing_level; + xf86ForEachDetailedBlock(DDC, handle_detailed_modes, &p); + Modes = p.Modes; /* Add established timings */ Mode = DDCModesFromEstablished(scrnIndex, &DDC->timings1, quirks); @@ -930,15 +1074,78 @@ xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC) Mode = DDCModesFromStandardTiming(DDC->timings2, quirks, timing_level, rb); Modes = xf86ModesAdd(Modes, Mode); + /* Add cea-extension mode timings */ + Mode = DDCModesFromCEAExtension(scrnIndex,DDC); + Modes = xf86ModesAdd(Modes, Mode); + if (quirks & DDC_QUIRK_PREFER_LARGE_60) xf86DDCSetPreferredRefresh(scrnIndex, Modes, 60); if (quirks & DDC_QUIRK_PREFER_LARGE_75) xf86DDCSetPreferredRefresh(scrnIndex, Modes, 75); + Modes = xf86PruneDuplicateModes(Modes); + return Modes; } +struct det_mon_parameter { + MonPtr Monitor; + ddc_quirk_t quirks; + Bool have_hsync; + Bool have_vrefresh; + Bool have_maxpixclock; +}; + +static void handle_detailed_monset(struct detailed_monitor_section *det_mon, + void *data) +{ + int clock; + struct det_mon_parameter *p = (struct det_mon_parameter *)data; + int scrnIndex = ((xf86MonPtr)(p->Monitor->DDC))->scrnIndex; + + switch (det_mon->type) { + case DS_RANGES: + if (!p->have_hsync) { + if (!p->Monitor->nHsync) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for horizontal sync\n"); + p->Monitor->hsync[p->Monitor->nHsync].lo = + det_mon->section.ranges.min_h; + p->Monitor->hsync[p->Monitor->nHsync].hi = + det_mon->section.ranges.max_h; + p->Monitor->nHsync++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using hsync ranges from config file\n"); + } + + if (!p->have_vrefresh) { + if (!p->Monitor->nVrefresh) + xf86DrvMsg(scrnIndex, X_INFO, + "Using EDID range info for vertical refresh\n"); + p->Monitor->vrefresh[p->Monitor->nVrefresh].lo = + det_mon->section.ranges.min_v; + p->Monitor->vrefresh[p->Monitor->nVrefresh].hi = + det_mon->section.ranges.max_v; + p->Monitor->nVrefresh++; + } else { + xf86DrvMsg(scrnIndex, X_INFO, + "Using vrefresh ranges from config file\n"); + } + + clock = det_mon->section.ranges.max_clock * 1000; + if (p->quirks & DDC_QUIRK_DVI_SINGLE_LINK) + clock = min(clock, 165000); + if (!p->have_maxpixclock && clock > p->Monitor->maxPixClock) + p->Monitor->maxPixClock = clock; + + break; + default: + break; + } +} + /* * Fill out MonPtr with xf86MonPtr information. */ @@ -946,17 +1153,13 @@ void xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) { DisplayModePtr Modes = NULL, Mode; - int i, clock; - Bool have_hsync = FALSE, have_vrefresh = FALSE, have_maxpixclock = FALSE; - ddc_quirk_t quirks; + struct det_mon_parameter p; if (!Monitor || !DDC) return; Monitor->DDC = DDC; - quirks = xf86DDCDetectQuirks(scrnIndex, DDC, FALSE); - if (Monitor->widthmm <= 0 || Monitor->heightmm <= 0) { Monitor->widthmm = 10 * DDC->features.hsize; Monitor->heightmm = 10 * DDC->features.vsize; @@ -966,54 +1169,13 @@ xf86EdidMonitorSet(int scrnIndex, MonPtr Monitor, xf86MonPtr DDC) Modes = xf86DDCGetModes(scrnIndex, DDC); - /* Skip EDID ranges if they were specified in the config file */ - have_hsync = (Monitor->nHsync != 0); - have_vrefresh = (Monitor->nVrefresh != 0); - have_maxpixclock = (Monitor->maxPixClock != 0); - /* Go through the detailed monitor sections */ - for (i = 0; i < DET_TIMINGS; i++) { - switch (DDC->det_mon[i].type) { - case DS_RANGES: - if (!have_hsync) { - if (!Monitor->nHsync) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for horizontal sync\n"); - Monitor->hsync[Monitor->nHsync].lo = - DDC->det_mon[i].section.ranges.min_h; - Monitor->hsync[Monitor->nHsync].hi = - DDC->det_mon[i].section.ranges.max_h; - Monitor->nHsync++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using hsync ranges from config file\n"); - } - - if (!have_vrefresh) { - if (!Monitor->nVrefresh) - xf86DrvMsg(scrnIndex, X_INFO, - "Using EDID range info for vertical refresh\n"); - Monitor->vrefresh[Monitor->nVrefresh].lo = - DDC->det_mon[i].section.ranges.min_v; - Monitor->vrefresh[Monitor->nVrefresh].hi = - DDC->det_mon[i].section.ranges.max_v; - Monitor->nVrefresh++; - } else { - xf86DrvMsg(scrnIndex, X_INFO, - "Using vrefresh ranges from config file\n"); - } - - clock = DDC->det_mon[i].section.ranges.max_clock * 1000; - if (quirks & DDC_QUIRK_DVI_SINGLE_LINK) - clock = min(clock, 165000); - if (!have_maxpixclock && clock > Monitor->maxPixClock) - Monitor->maxPixClock = clock; - - break; - default: - break; - } - } + p.Monitor = Monitor; + p.quirks = xf86DDCDetectQuirks(scrnIndex, Monitor->DDC, FALSE); + p.have_hsync = (Monitor->nHsync != 0); + p.have_vrefresh = (Monitor->nVrefresh != 0); + p.have_maxpixclock = (Monitor->maxPixClock != 0); + xf86ForEachDetailedBlock(DDC, handle_detailed_monset, &p); if (Modes) { /* Print Modes */ diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.c b/xorg-server/hw/xfree86/modes/xf86Modes.c index d105b48ab..75aedaa99 100644 --- a/xorg-server/hw/xfree86/modes/xf86Modes.c +++ b/xorg-server/hw/xfree86/modes/xf86Modes.c @@ -136,10 +136,12 @@ xf86ModeBandwidth(DisplayModePtr mode, int depth) void xf86SetModeDefaultName(DisplayModePtr mode) { - if (mode->name != NULL) - xfree(mode->name); + Bool interlaced = !!(mode->Flags & V_INTERLACE); - mode->name = XNFprintf("%dx%d", mode->HDisplay, mode->VDisplay); + xfree(mode->name); + + mode->name = XNFprintf("%dx%d%s", mode->HDisplay, mode->VDisplay, + interlaced ? "i" : ""); } /* @@ -689,3 +691,37 @@ xf86GetDefaultModes (void) } return head; } + +/* + * Walk a mode list and prune out duplicates. Will preserve the preferred + * mode of an otherwise-duplicate pair. + * + * Probably best to call this on lists that are all of a single class + * (driver, default, user, etc.), otherwise, which mode gets deleted is + * not especially well defined. + * + * Returns the new list. + */ + +DisplayModePtr +xf86PruneDuplicateModes(DisplayModePtr modes) +{ + DisplayModePtr m, n, o; + +top: + for (m = modes; m; m = m->next) { + for (n = m->next; n; n = o) { + o = n->next; + if (xf86ModesEqual(m, n)) { + if (n->type & M_T_PREFERRED) { + xf86DeleteMode(&modes, m); + goto top; + } + else + xf86DeleteMode(&modes, n); + } + } + } + + return modes; +} diff --git a/xorg-server/hw/xfree86/modes/xf86Modes.h b/xorg-server/hw/xfree86/modes/xf86Modes.h index 908f59b48..38927b128 100644 --- a/xorg-server/hw/xfree86/modes/xf86Modes.h +++ b/xorg-server/hw/xfree86/modes/xf86Modes.h @@ -95,6 +95,9 @@ extern _X_EXPORT void xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList, Bool verbose); +extern _X_EXPORT DisplayModePtr +xf86PruneDuplicateModes(DisplayModePtr modes); + extern _X_EXPORT void xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList, int flags); diff --git a/xorg-server/hw/xfree86/os-support/linux/Makefile.am b/xorg-server/hw/xfree86/os-support/linux/Makefile.am index 1239c8f6b..7a82627fd 100644 --- a/xorg-server/hw/xfree86/os-support/linux/Makefile.am +++ b/xorg-server/hw/xfree86/os-support/linux/Makefile.am @@ -40,13 +40,7 @@ AM_CFLAGS = -DUSESTDRES -DHAVE_SYSV_IPC $(DIX_CFLAGS) $(XORG_CFLAGS) $(PLATFORM_ INCLUDES = $(XORG_INCS) $(PLATFORM_INCLUDES) $(LIBDRM_CFLAGS) -# FIXME: These need to be added to the build -LNX_EXTRA_SRCS = \ - lnx_font.c - EXTRA_DIST = \ - $(LNX_EXTRA_SRCS) \ - lnx.h \ $(srcdir)/../shared/xf86Axp.h if LINUX_ALPHA diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx.h b/xorg-server/hw/xfree86/os-support/linux/lnx.h index 085c94265..33363dd3d 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx.h +++ b/xorg-server/hw/xfree86/os-support/linux/lnx.h @@ -41,13 +41,6 @@ extern long (*_iobase)(unsigned, int, int, int); # endif # endif /* __alpha__ */ -# if defined(DO_OS_FONTRESTORE) -Bool lnx_savefont(void); -Bool lnx_restorefont(void); -Bool lnx_switchaway(void); -void lnx_freefontdata(void); -# endif - #define LNX_H_ #endif diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_apm.c b/xorg-server/hw/xfree86/os-support/linux/lnx_apm.c index 4ccc7d662..54c698965 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_apm.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_apm.c @@ -16,7 +16,6 @@ extern PMClose lnxACPIOpen(void); #ifdef HAVE_APM -#include "lnx.h" #include <linux/apm_bios.h> #include <unistd.h> #include <sys/ioctl.h> diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c index f84c6149e..297e7a65a 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_init.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_init.c @@ -35,7 +35,6 @@ #include "xf86.h" #include "xf86Priv.h" #include "xf86_OSlib.h" -#include "lnx.h" #include <sys/stat.h> @@ -230,9 +229,6 @@ xf86OpenConsole(void) { struct termios nTty; -#if defined(DO_OS_FONTRESTORE) - lnx_savefont(); -#endif /* * now get the VT. This _must_ succeed, or else fail completely. */ @@ -302,17 +298,12 @@ xf86OpenConsole(void) strerror(errno)); } } - return; } void xf86CloseConsole(void) { struct vt_mode VT; -#if defined(DO_OS_FONTRESTORE) - struct vt_stat vts; - int vtno = -1; -#endif if (ShareVTs) { close(xf86Info.consoleFd); @@ -324,14 +315,6 @@ xf86CloseConsole(void) console_handler = NULL; }; -#if defined(DO_OS_FONTRESTORE) - if (ioctl(xf86Info.consoleFd, VT_GETSTATE, &vts) < 0) - xf86Msg(X_WARNING, "xf86CloseConsole: VT_GETSTATE failed: %s\n", - strerror(errno)); - else - vtno = vts.v_active; -#endif - /* Back to text mode ... */ if (ioctl(xf86Info.consoleFd, KDSETMODE, KD_TEXT) < 0) xf86Msg(X_WARNING, "xf86CloseConsole: KDSETMODE failed: %s\n", @@ -366,18 +349,10 @@ xf86CloseConsole(void) strerror(errno)); activeVT = -1; } - -#if defined(DO_OS_FONTRESTORE) - if (xf86Info.vtno == vtno) /* check if we are active */ - lnx_restorefont(); - lnx_freefontdata(); -#endif } close(xf86Info.consoleFd); /* make the vt-manager happy */ restoreVtPerms(); /* restore the permissions */ - - return; } int @@ -421,7 +396,6 @@ xf86UseMsg(void) ErrorF("vtXX use the specified VT number\n"); ErrorF("-keeptty "); ErrorF("don't detach controlling tty (for debugging only)\n"); - ErrorF("-novtswitch don't immediately switch to new VT\n"); - ErrorF("-sharevts share VTs with another X server\n"); - return; + ErrorF("-novtswitch don't immediately switch to new VT\n"); + ErrorF("-sharevts share VTs with another X server\n"); } diff --git a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c index 09d178797..e159f4691 100644 --- a/xorg-server/hw/xfree86/os-support/linux/lnx_video.c +++ b/xorg-server/hw/xfree86/os-support/linux/lnx_video.c @@ -38,7 +38,6 @@ #include "xf86Priv.h" #include "xf86_OSlib.h" #include "xf86OSpriv.h" -#include "lnx.h" #ifdef __alpha__ #include "shared/xf86Axp.h" #endif diff --git a/xorg-server/hw/xfree86/parser/Flags.c b/xorg-server/hw/xfree86/parser/Flags.c index 6865d3592..699f15ceb 100644 --- a/xorg-server/hw/xfree86/parser/Flags.c +++ b/xorg-server/hw/xfree86/parser/Flags.c @@ -434,7 +434,7 @@ xf86uLongToString(unsigned long i) char *s; int l; - l = (int)(ceil(log10((double)i) + 2.5)); + l = ceil(log10((double)i) + 2.5); s = malloc(l); if (!s) return NULL; diff --git a/xorg-server/hw/xfree86/x86emu/Makefile.am b/xorg-server/hw/xfree86/x86emu/Makefile.am index 987ea8bd7..bcacb331c 100644 --- a/xorg-server/hw/xfree86/x86emu/Makefile.am +++ b/xorg-server/hw/xfree86/x86emu/Makefile.am @@ -9,7 +9,7 @@ libx86emu_la_SOURCES = debug.c \ sys.c \ x86emu.h -INCLUDES = +INCLUDES = $(XORG_INCS) AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) diff --git a/xorg-server/hw/xfree86/x86emu/sys.c b/xorg-server/hw/xfree86/x86emu/sys.c index e15fb0931..2ebf6f157 100644 --- a/xorg-server/hw/xfree86/x86emu/sys.c +++ b/xorg-server/hw/xfree86/x86emu/sys.c @@ -48,168 +48,13 @@ #ifndef NO_SYS_HEADERS #include <string.h> #endif +#include "compiler.h" /* for unaligned access functions */ /*------------------------- Global Variables ------------------------------*/ X86EMU_sysEnv _X86EMU_env; /* Global emulator machine state */ X86EMU_intrFuncs _X86EMU_intrTab[256]; /*----------------------------- Implementation ----------------------------*/ -#if defined(__alpha__) || defined(__alpha) -/* to cope with broken egcs-1.1.2 :-(((( */ - -#define ALPHA_UALOADS -/* - * inline functions to do unaligned accesses - * from linux/include/asm-alpha/unaligned.h - */ - -/* - * EGCS 1.1 knows about arbitrary unaligned loads. Define some - * packed structures to talk about such things with. - */ - -#if defined(__GNUC__) -struct __una_u64 { unsigned long x __attribute__((packed)); }; -struct __una_u32 { unsigned int x __attribute__((packed)); }; -struct __una_u16 { unsigned short x __attribute__((packed)); }; -#endif - -static __inline__ unsigned long ldq_u(unsigned long * r11) -{ -#if defined(__GNUC__) - const struct __una_u64 *ptr = (const struct __una_u64 *) r11; - return ptr->x; -#else - unsigned long r1,r2; - __asm__("ldq_u %0,%3\n\t" - "ldq_u %1,%4\n\t" - "extql %0,%2,%0\n\t" - "extqh %1,%2,%1" - :"=&r" (r1), "=&r" (r2) - :"r" (r11), - "m" (*r11), - "m" (*(const unsigned long *)(7+(char *) r11))); - return r1 | r2; -#endif -} - -static __inline__ unsigned long ldl_u(unsigned int * r11) -{ -#if defined(__GNUC__) - const struct __una_u32 *ptr = (const struct __una_u32 *) r11; - return ptr->x; -#else - unsigned long r1,r2; - __asm__("ldq_u %0,%3\n\t" - "ldq_u %1,%4\n\t" - "extll %0,%2,%0\n\t" - "extlh %1,%2,%1" - :"=&r" (r1), "=&r" (r2) - :"r" (r11), - "m" (*r11), - "m" (*(const unsigned long *)(3+(char *) r11))); - return r1 | r2; -#endif -} - -static __inline__ unsigned long ldw_u(unsigned short * r11) -{ -#if defined(__GNUC__) - const struct __una_u16 *ptr = (const struct __una_u16 *) r11; - return ptr->x; -#else - unsigned long r1,r2; - __asm__("ldq_u %0,%3\n\t" - "ldq_u %1,%4\n\t" - "extwl %0,%2,%0\n\t" - "extwh %1,%2,%1" - :"=&r" (r1), "=&r" (r2) - :"r" (r11), - "m" (*r11), - "m" (*(const unsigned long *)(1+(char *) r11))); - return r1 | r2; -#endif -} - -/* - * Elemental unaligned stores - */ - -static __inline__ void stq_u(unsigned long r5, unsigned long * r11) -{ -#if defined(__GNUC__) - struct __una_u64 *ptr = (struct __una_u64 *) r11; - ptr->x = r5; -#else - unsigned long r1,r2,r3,r4; - - __asm__("ldq_u %3,%1\n\t" - "ldq_u %2,%0\n\t" - "insqh %6,%7,%5\n\t" - "insql %6,%7,%4\n\t" - "mskqh %3,%7,%3\n\t" - "mskql %2,%7,%2\n\t" - "bis %3,%5,%3\n\t" - "bis %2,%4,%2\n\t" - "stq_u %3,%1\n\t" - "stq_u %2,%0" - :"=m" (*r11), - "=m" (*(unsigned long *)(7+(char *) r11)), - "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) - :"r" (r5), "r" (r11)); -#endif -} - -static __inline__ void stl_u(unsigned long r5, unsigned int * r11) -{ -#if defined(__GNUC__) - struct __una_u32 *ptr = (struct __una_u32 *) r11; - ptr->x = r5; -#else - unsigned long r1,r2,r3,r4; - - __asm__("ldq_u %3,%1\n\t" - "ldq_u %2,%0\n\t" - "inslh %6,%7,%5\n\t" - "insll %6,%7,%4\n\t" - "msklh %3,%7,%3\n\t" - "mskll %2,%7,%2\n\t" - "bis %3,%5,%3\n\t" - "bis %2,%4,%2\n\t" - "stq_u %3,%1\n\t" - "stq_u %2,%0" - :"=m" (*r11), - "=m" (*(unsigned long *)(3+(char *) r11)), - "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) - :"r" (r5), "r" (r11)); -#endif -} - -static __inline__ void stw_u(unsigned long r5, unsigned short * r11) -{ -#if defined(__GNUC__) - struct __una_u16 *ptr = (struct __una_u16 *) r11; - ptr->x = r5; -#else - unsigned long r1,r2,r3,r4; - - __asm__("ldq_u %3,%1\n\t" - "ldq_u %2,%0\n\t" - "inswh %6,%7,%5\n\t" - "inswl %6,%7,%4\n\t" - "mskwh %3,%7,%3\n\t" - "mskwl %2,%7,%2\n\t" - "bis %3,%5,%3\n\t" - "bis %2,%4,%2\n\t" - "stq_u %3,%1\n\t" - "stq_u %2,%0" - :"=m" (*r11), - "=m" (*(unsigned long *)(1+(char *) r11)), - "=&r" (r1), "=&r" (r2), "=&r" (r3), "=&r" (r4) - :"r" (r5), "r" (r11)); -#endif -} -#endif /**************************************************************************** PARAMETERS: @@ -262,13 +107,7 @@ u16 X86API rdw( } else #endif -#if defined(ALPHA_UALOADS) val = ldw_u((u16*)(M.mem_base + addr)); -#elif defined(IA64_UALOADS) - val = uldw((u16*)(M.mem_base + addr)); -#else - val = *(u16*)(M.mem_base + addr); -#endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 2 -> %#x\n", addr, val);) return val; @@ -301,13 +140,7 @@ u32 X86API rdl( } else #endif -#if defined(ALPHA_UALOADS) val = ldl_u((u32*)(M.mem_base + addr)); -#elif defined(IA64_UALOADS) - val = uldl((u32*)(M.mem_base + addr)); -#else - val = *(u32*)(M.mem_base + addr); -#endif DB( if (DEBUG_MEM_TRACE()) printk("%#08x 4 -> %#x\n", addr, val);) return val; @@ -359,13 +192,7 @@ DB( if (DEBUG_MEM_TRACE()) } else #endif -#if defined(ALPHA_UALOADS) stw_u(val,(u16*)(M.mem_base + addr)); -#elif defined(IA64_UALOADS) - ustw(val,(u16*)(M.mem_base + addr)); -#else - *(u16*)(M.mem_base + addr) = val; -#endif } /**************************************************************************** @@ -395,13 +222,7 @@ DB( if (DEBUG_MEM_TRACE()) } else #endif -#if defined(ALPHA_UALOADS) stl_u(val,(u32*)(M.mem_base + addr)); -#elif defined(IA64_UALOADS) - ustl(val,(u32*)(M.mem_base + addr)); -#else - *(u32*)(M.mem_base + addr) = val; -#endif } /**************************************************************************** |