Use the new fields for SDVO pixel multiply on the G965.

This should fix display at resolutions/refresh rates in a different multiplier
class than the console display (generally, high resolution modes).
This commit is contained in:
Eric Anholt 2006-10-30 09:50:33 -08:00
parent 71545db461
commit 819a47b27c
5 changed files with 72 additions and 8 deletions

View File

@ -799,10 +799,56 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# define PLL_REF_INPUT_TVCLKINBC (2 << 13)
# define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13)
# define DISPLAY_RATE_SELECT_FPA1 (1 << 8)
/**
* SDVO multiplier for 945G/GM.
*
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
*/
# define SDVO_MULTIPLIER_MASK 0x000000ff
# define SDVO_MULTIPLIER_SHIFT_HIRES 4
# define SDVO_MULTIPLIER_SHIFT_VGA 0
/** @defgroup DPLL_MD
* @{
*/
/** Pipe A SDVO/UDI clock multiplier/divider register for G965. */
#define DPLL_A_MD 0x0601c
/** Pipe B SDVO/UDI clock multiplier/divider register for G965. */
#define DPLL_B_MD 0x06020
/**
* UDI pixel divider, controlling how many pixels are stuffed into a packet.
*
* Value is pixels minus 1. Must be set to 1 pixel for SDVO.
*/
# define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000
# define DPLL_MD_UDI_DIVIDER_SHIFT 24
/** UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */
# define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000
# define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16
/**
* SDVO/UDI pixel multiplier.
*
* SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus
* clock rate is 10 times the DPLL clock. At low resolution/refresh rate
* modes, the bus rate would be below the limits, so SDVO allows for stuffing
* dummy bytes in the datastream at an increased clock rate, with both sides of
* the link knowing how many bytes are fill.
*
* So, for a mode with a dotclock of 65Mhz, we would want to double the clock
* rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be
* set to 130Mhz, and the SDVO multiplier set to 2x in this register and
* through an SDVO command.
*
* This register field has values of multiplication factor minus 1, with
* a maximum multiplier of 5 for SDVO.
*/
# define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00
# define DPLL_MD_UDI_MULTIPLIER_SHIFT 8
/** SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. */
# define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f
# define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0
/** @} */
#define BLC_PWM_CTL 0x61254
#define BACKLIGHT_MODULATION_FREQ_SHIFT (17)
#define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17)
@ -842,7 +888,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define SDVO_PIPE_B_SELECT (1 << 30)
#define SDVO_STALL_SELECT (1 << 29)
#define SDVO_INTERRUPT_ENABLE (1 << 26)
/* Programmed value is multiplier - 1, up to 5x. alv, gdg only */
/**
* 915G/GM SDVO pixel multiplier.
*
* Programmed value is multiplier - 1, up to 5x.
*
* \sa DPLL_MD_UDI_MULTIPLIER_MASK
*/
#define SDVO_PORT_MULTIPLY_MASK (7 << 23)
#define SDVO_PORT_MULTIPLY_SHIFT 23
#define SDVO_PHASE_SELECT_MASK (15 << 19)

View File

@ -509,6 +509,7 @@ typedef struct _I830Rec {
CARD32 saveFPA0;
CARD32 saveFPA1;
CARD32 saveDPLL_A;
CARD32 saveDPLL_A_MD;
CARD32 saveHTOTAL_A;
CARD32 saveHBLANK_A;
CARD32 saveHSYNC_A;
@ -523,6 +524,7 @@ typedef struct _I830Rec {
CARD32 saveFPB0;
CARD32 saveFPB1;
CARD32 saveDPLL_B;
CARD32 saveDPLL_B_MD;
CARD32 saveHTOTAL_B;
CARD32 saveHBLANK_B;
CARD32 saveHSYNC_B;

View File

@ -472,11 +472,8 @@ i830PipeSetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, int pipe)
}
}
/* In SDVO, we need to keep the clock on the bus between 1Ghz and 2Ghz.
* The clock on the bus is 10 times the pixel clock normally. If that
* would be too low, we run the DPLL at a multiple of the pixel clock, and
* tell the SDVO device the multiplier so it can throw away the dummy
* bytes.
/* Adjust the clock for pixel multiplication.
* See DPLL_MD_UDI_MULTIPLIER_MASK.
*/
if (is_sdvo) {
pixel_clock *= i830_sdvo_get_pixel_multiplier(pMode);

View File

@ -2506,6 +2506,8 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->saveFPA0 = INREG(FPA0);
pI830->saveFPA1 = INREG(FPA1);
pI830->saveDPLL_A = INREG(DPLL_A);
if (IS_I965G(pI830))
pI830->saveDPLL_A_MD = INREG(DPLL_A_MD);
pI830->saveHTOTAL_A = INREG(HTOTAL_A);
pI830->saveHBLANK_A = INREG(HBLANK_A);
pI830->saveHSYNC_A = INREG(HSYNC_A);
@ -2528,6 +2530,8 @@ SaveHWState(ScrnInfoPtr pScrn)
pI830->saveFPB0 = INREG(FPB0);
pI830->saveFPB1 = INREG(FPB1);
pI830->saveDPLL_B = INREG(DPLL_B);
if (IS_I965G(pI830))
pI830->saveDPLL_B_MD = INREG(DPLL_B_MD);
pI830->saveHTOTAL_B = INREG(HTOTAL_B);
pI830->saveHBLANK_B = INREG(HBLANK_B);
pI830->saveHSYNC_B = INREG(HSYNC_B);
@ -2611,6 +2615,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(FPA0, pI830->saveFPA0);
OUTREG(FPA1, pI830->saveFPA1);
OUTREG(DPLL_A, pI830->saveDPLL_A);
if (IS_I965G(pI830))
OUTREG(DPLL_A_MD, pI830->saveDPLL_A_MD);
OUTREG(HTOTAL_A, pI830->saveHTOTAL_A);
OUTREG(HBLANK_A, pI830->saveHBLANK_A);
OUTREG(HSYNC_A, pI830->saveHSYNC_A);
@ -2630,6 +2636,8 @@ RestoreHWState(ScrnInfoPtr pScrn)
OUTREG(FPB0, pI830->saveFPB0);
OUTREG(FPB1, pI830->saveFPB1);
OUTREG(DPLL_B, pI830->saveDPLL_B);
if (IS_I965G(pI830))
OUTREG(DPLL_B_MD, pI830->saveDPLL_B_MD);
OUTREG(HTOTAL_B, pI830->saveHTOTAL_B);
OUTREG(HBLANK_B, pI830->saveHBLANK_B);
OUTREG(HSYNC_B, pI830->saveHSYNC_B);

View File

@ -600,6 +600,7 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
Bool out1, out2, input1, input2;
CARD32 dpll, sdvob, sdvoc;
int dpll_reg = (output->pipe == 0) ? DPLL_A : DPLL_B;
int dpll_md_reg = (output->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
int sdvo_pixel_multiply;
CARD8 status;
@ -630,10 +631,14 @@ i830_sdvo_post_set_mode(ScrnInfoPtr pScrn, I830OutputPtr output,
dpll = INREG(dpll_reg);
sdvo_pixel_multiply = i830_sdvo_get_pixel_multiplier(mode);
if (IS_I945G(pI830) || IS_I945GM(pI830))
if (IS_I965G(pI830)) {
OUTREG(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) |
((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
} else if (IS_I945G(pI830) || IS_I945GM(pI830)) {
dpll |= (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES;
else
} else {
sdvob |= (sdvo_pixel_multiply - 1) << SDVO_PORT_MULTIPLY_SHIFT;
}
OUTREG(dpll_reg, dpll | DPLL_DVO_HIGH_SPEED);