From 3f83d7308f3b0aca4943262b0ba2715a32b61d58 Mon Sep 17 00:00:00 2001 From: Maarten Maathuis Date: Sun, 9 Dec 2007 12:47:55 +0100 Subject: [PATCH] randr12: Add noscale mode and some misc fixes. --- src/nv_crtc.c | 59 ++++++++++++++++++++++++++++++++++++------------- src/nv_output.c | 13 ++++++----- src/nvreg.h | 38 ++++++++++++++++++++----------- 3 files changed, 77 insertions(+), 33 deletions(-) diff --git a/src/nv_crtc.c b/src/nv_crtc.c index 748b258..772c919 100644 --- a/src/nv_crtc.c +++ b/src/nv_crtc.c @@ -1694,8 +1694,8 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP /* * bit0: positive vsync * bit4: positive hsync - * bit8: enable panel scaling - * bit9: something related to dual link dvi? + * bit8: enable center mode + * bit9: enable native mode * bit26: a bit sometimes seen on some g70 cards * bit31: set for dual link LVDS * This must also be set for non-flatpanels @@ -1715,18 +1715,29 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP regp->fp_control |= nvReadRAMDAC0(pNv, NV_RAMDAC_FP_CONTROL) & (1 << 26); } - /* Does this turn something off, since it's similar to what is used in dpms (being a "2" bit)? */ - if (is_fp && !is_lvds && pNv->dcb_table.entry[nv_output->dcb_entry].duallink_possible) - regp->fp_control |= (1 << 9); + if (is_fp) { + if (mode->Clock == adjusted_mode->Clock) { /* native mode */ + regp->fp_control |= NV_RAMDAC_FP_CONTROL_MODE_NATIVE; + } else if (nv_output->scaling_mode == 0) { /* panel needs to scale */ + regp->fp_control |= NV_RAMDAC_FP_CONTROL_MODE_CENTER; + } else { /* gpu needs to scale */ + regp->fp_control |= NV_RAMDAC_FP_CONTROL_MODE_SCALE; + } + } /* Deal with vsync/hsync polarity */ - /* These analog monitor offsets are guesswork */ - if (adjusted_mode->Flags & V_PVSYNC) { - regp->fp_control |= (1 << (0 + !is_fp)); - } + if (is_fp) { + if (adjusted_mode->Flags & V_PVSYNC) { + regp->fp_control |= NV_RAMDAC_FP_CONTROL_VSYNC_POS; + } - if (adjusted_mode->Flags & V_PHSYNC) { - regp->fp_control |= (1 << (4 + !is_fp)); + if (adjusted_mode->Flags & V_PHSYNC) { + regp->fp_control |= NV_RAMDAC_FP_CONTROL_HSYNC_POS; + } + } else { + /* The blob doesn't always do this, but often */ + regp->fp_control |= NV_RAMDAC_FP_CONTROL_VSYNC_DISABLE; + regp->fp_control |= NV_RAMDAC_FP_CONTROL_HSYNC_DISABLE; } if (is_fp) { @@ -1742,7 +1753,7 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP ErrorF("h_scale=%d\n", h_scale); ErrorF("v_scale=%d\n", v_scale); - /* Don't limit last fetched line */ + /* This can override HTOTAL and VTOTAL */ regp->debug_2 = 0; /* We want automatic scaling */ @@ -1757,12 +1768,12 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP /* 0 = panel scaling */ if (nv_output->scaling_mode == 0) { ErrorF("Flat panel is doing the scaling.\n"); - regp->fp_control |= (1 << 8); } else { ErrorF("GPU is doing the scaling.\n"); /* 1 = fullscale gpu */ /* 2 = aspect ratio scaling */ + /* 3 = no scaling */ if (nv_output->scaling_mode == 2) { /* GPU scaling happens automaticly at a ratio of 1.33 */ /* A 1280x1024 panel has a ratio of 1.25, we don't want to scale that at 4:3 resolutions */ @@ -1811,9 +1822,26 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP /* These are the common blob values, minus a few fp specific bit's */ /* Let's keep the TMDS pll and fpclock running in all situations */ - regp->debug_0 = 0x1101111; + regp->debug_0 = 0x1101100; + + if (is_fp && nv_output->scaling_mode != 3) { /* !no_scale mode */ + regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_XSCALE_ENABLED; + regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_YSCALE_ENABLED; + } else if (is_fp) { /* no_scale mode, so we must center it */ + uint32_t diff; + + diff = nv_output->fpWidth - mode->HDisplay; + regp->fp_hvalid_start = diff/2; + regp->fp_hvalid_end = (nv_output->fpWidth - diff/2 - 1); - if(is_fp) { + diff = nv_output->fpHeight - mode->VDisplay; + regp->fp_vvalid_start = diff/2; + regp->fp_vvalid_end = (nv_output->fpHeight - diff/2 - 1); + } + + /* Is this crtc bound or output bound? */ + /* Does the bios TMDS script try to change this sometimes? */ + if (is_fp) { /* I am not completely certain, but seems to be set only for dfp's */ regp->debug_0 |= NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED; } @@ -1848,6 +1876,7 @@ nv_crtc_mode_set_ramdac_regs(xf86CrtcPtr crtc, DisplayModePtr mode, DisplayModeP } if (pNv->alphaCursor) { + /* PIPE_LONG mode, something to do with the size of the cursor? */ regp->general |= (1<<29); } diff --git a/src/nv_output.c b/src/nv_output.c index 4dd13c6..3839952 100644 --- a/src/nv_output.c +++ b/src/nv_output.c @@ -851,21 +851,24 @@ static const xf86OutputFuncsRec nv_analog_output_funcs = { * Several scaling modes exist, let the user choose. */ #define SCALING_MODE_NAME "SCALING_MODE" -#define NUM_SCALING_METHODS 3 +#define NUM_SCALING_METHODS 4 static char *scaling_mode_names[] = { "panel", "fullscreen", "aspect", + "noscale", }; static Atom scaling_mode_atom; static int nv_scaling_mode_lookup(char *name, int size) { - int i; + int i, len; for (i = 0; i < NUM_SCALING_METHODS; i++) { - if (!strncmp(name, scaling_mode_names[i], size)) + /* We're getting non-terminated strings */ + len = strlen(scaling_mode_names[i]); + if (len == size && !strncmp(name, scaling_mode_names[i], size)) return i; } @@ -913,12 +916,12 @@ nv_tmds_set_property(xf86OutputPtr output, Atom property, if (property == scaling_mode_atom) { int32_t ret; - char *name; + char *name = NULL; if (value->type != XA_STRING || value->format != 8) return FALSE; - name = (char*) value->data; + name = (char *) value->data; /* Match a string to a scaling mode */ ret = nv_scaling_mode_lookup(name, value->size); diff --git a/src/nvreg.h b/src/nvreg.h index 9b9a78c..40d84e1 100644 --- a/src/nvreg.h +++ b/src/nvreg.h @@ -253,19 +253,31 @@ #define NV_RAMDAC_FP_HVALID_START 0x834 #define NV_RAMDAC_FP_HVALID_END 0x838 -#define NV_RAMDAC_FP_DITHER 0x83c -#define NV_RAMDAC_FP_CHECKSUM 0x840 -#define NV_RAMDAC_FP_TEST_CONTROL 0x844 -#define NV_RAMDAC_FP_CONTROL 0x848 -#define NV_RAMDAC_FP_CONTROL_ENABLE (1<<28) // toggling this bit turns things on/off - -#define NV_RAMDAC_FP_DEBUG_0 0x880 -/* Not a 100% sure, but several mmio traces confirm this */ -/* This is one of the things needed to determine how the dvi transmitter(s) is/are wired */ -#define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED (1<<7) -#define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1<<28) -#define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_TMDS_PLL (2<<28) -#define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH (3<<28) +#define NV_RAMDAC_FP_DITHER 0x83c +#define NV_RAMDAC_FP_CHECKSUM 0x840 +#define NV_RAMDAC_FP_TEST_CONTROL 0x844 +#define NV_RAMDAC_FP_CONTROL 0x848 +# define NV_RAMDAC_FP_CONTROL_VSYNC_NEG (0 << 0) +# define NV_RAMDAC_FP_CONTROL_VSYNC_POS (1 << 0) +# define NV_RAMDAC_FP_CONTROL_VSYNC_DISABLE (2 << 0) +# define NV_RAMDAC_FP_CONTROL_HSYNC_NEG (0 << 4) +# define NV_RAMDAC_FP_CONTROL_HSYNC_POS (1 << 4) +# define NV_RAMDAC_FP_CONTROL_HSYNC_DISABLE (2 << 4) +# define NV_RAMDAC_FP_CONTROL_MODE_SCALE (0 << 8) +# define NV_RAMDAC_FP_CONTROL_MODE_CENTER (1 << 8) +# define NV_RAMDAC_FP_CONTROL_MODE_NATIVE (2 << 8) + +# define NV_RAMDAC_FP_CONTROL_ENABLE (1<<28) // toggling this bit turns things on/off + +#define NV_RAMDAC_FP_DEBUG_0 0x880 +# define NV_RAMDAC_FP_DEBUG_0_XSCALE_ENABLED (1 << 0) +# define NV_RAMDAC_FP_DEBUG_0_YSCALE_ENABLED (1 << 4) +/* This doesn't seem to be essential for tmds, but still often set */ +# define NV_RAMDAC_FP_DEBUG_0_TMDS_ENABLED (1 << 7) +# define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1 << 28) +# define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_FPCLK (1 << 28) +# define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_TMDS_PLL (2 << 28) +# define NV_RAMDAC_FP_DEBUG_0_PWRDOWN_BOTH (3 << 28) #define NV_RAMDAC_FP_DEBUG_1 0x884 #define NV_RAMDAC_FP_DEBUG_2 0x888 #define NV_RAMDAC_FP_DEBUG_3 0x88C -- 2.32.0.93.g670b81a890