Comment 102 for bug 144322

Revision history for this message
In , Rvanderstelt (rvanderstelt) wrote :

While checking why the mode->CrtcV values are halve of what they should be (like they were in version 6.6.3) I came across the following comment in the function xf86InitialCheckModeForDriver (file hw/common/xf86Mode.c):

/*
 * NOTE: We (ab)use the mode->Crtc* values here to store timing
 * information for the calculation of Hsync and Vrefresh. Before
 * these values are calculated the driver is given the opportunity
 * to either set these HSync and VRefresh itself or modify the timing
 * values.
 * The difference to the final calculation is small but imortand:
 * here we pass the flag INTERLACE_HALVE_V regardless if the driver
 * sets it or not. This way our calculation of VRefresh has the same
 * effect as if we do if (flags & V_INTERLACE) refresh *= 2.0
 * This dual use of the mode->Crtc* values will certainly create
 * confusion and is bad software design. However since it's part of
 * the driver API it's hard to change.
 */

In version 6.6.3 the function RADEONPreInitModes (file src/radeon_driver.c) calls xf86SetCrtcForModes which in turn calls xf86SetModeCrtc for each mode with adjustFlag 0.

However in version 6.9.0 the new function radeon_mode_fixup (file src/radeon_output.c) only recalculates the mode->Crtc* values for a few specific conditions.
Namely when MonType is MT_LCD or MT_DFP and the display resolution is smaller then the panel resolution (and rmx_type is not RMX_OFF and either IS_AVIVO_VARIANT or radeon_crtc_id == 0 is true).

This means that at least for CRT monitors the CrtcV* values are left halve from what they should be.

To fix this I placed a call to xf86SetModeCrtc with adjustFlag 0 at the start of the radeon_mode_fixup function. But I'm not sure whether this is correct for all radeon cards because as I gather from the previous comments that this problem only seems to show up on older cards (I have a R350).

Note that the function radeon_mode_fixup contains two calls to xf86SetModeCrtc with the INTERLACE_HALVE_V flag. But after the call the Crtc* values are recalculated (without adjusting for interlacing or double scanning). However the values CrtcVBlankStart, CrtcVBlankEnd, CrtcHBlankStart and CrtcHBlankEnd are left untouched.

The problem with the pointer image placed to high is caused by the halving of the y coordinate in the function radeon_crtc_set_cursor_position when the V_INTERLACE flags is set. This wasn't done in version 6.6.3.
Removing it fixes the problem.

Note that the y coordinate is doubled when the V_DBLSCAN flag is set. This matched the doubling of the CrtcV values in xf86SetModeCrtc. But the y coordinate is not multiplied with mode->VScan.

Also note the corrected values in the 'adjusted_mode' don't seem to be propagated to the various copies of the mode in the xserver data structures.
The adjusted_mode is just dropped at the end of the xf86CrtcSetMode function.
So when the function RADEONDisplayVideo (radeon_video.c) uses crtc->mode.CrtcVDisplay it gets the halved valued.

Unfortunately this is not the cause of xv corruption I am experiencing on the second head (it is not related to interlacing).

Attached a patch.